diff --git a/[refs] b/[refs] index fd6502d50dab..14fd52f908b1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 86e437f077c68112edcb6854ec036ed7e3f9a7f3 +refs/heads/master: c02256be79a1a3557332ac51e653d574a2a7d2b5 diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index d916bea729f1..71670719d61a 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -79,6 +79,7 @@ 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 acpi_res_list { resource_size_t start; @@ -192,8 +193,10 @@ acpi_status acpi_os_initialize1(void) { kacpid_wq = create_singlethread_workqueue("kacpid"); kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); + kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug"); BUG_ON(!kacpid_wq); BUG_ON(!kacpi_notify_wq); + BUG_ON(!kacpi_hotplug_wq); return AE_OK; } @@ -206,6 +209,7 @@ acpi_status acpi_os_terminate(void) destroy_workqueue(kacpid_wq); destroy_workqueue(kacpi_notify_wq); + destroy_workqueue(kacpi_hotplug_wq); return AE_OK; } @@ -716,6 +720,7 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, acpi_status status = AE_OK; struct acpi_os_dpc *dpc; struct workqueue_struct *queue; + work_func_t func; int ret; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", @@ -740,15 +745,17 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, dpc->function = function; dpc->context = context; - if (!hp) { - INIT_WORK(&dpc->work, acpi_os_execute_deferred); - queue = (type == OSL_NOTIFY_HANDLER) ? - kacpi_notify_wq : kacpid_wq; - ret = queue_work(queue, &dpc->work); - } else { - INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred); - ret = schedule_work(&dpc->work); - } + /* + * We can't run hotplug code in keventd_wq/kacpid_wq/kacpid_notify_wq + * because the hotplug code may call driver .remove() functions, + * which invoke flush_scheduled_work/acpi_os_wait_events_complete + * to flush these workqueues. + */ + queue = hp ? kacpi_hotplug_wq : + (type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq); + func = hp ? acpi_os_execute_hp_deferred : acpi_os_execute_deferred; + INIT_WORK(&dpc->work, func); + ret = queue_work(queue, &dpc->work); if (!ret) { printk(KERN_ERR PREFIX diff --git a/trunk/drivers/acpi/video.c b/trunk/drivers/acpi/video.c index a63566ba230b..1bdfb37377e3 100644 --- a/trunk/drivers/acpi/video.c +++ b/trunk/drivers/acpi/video.c @@ -76,7 +76,6 @@ MODULE_LICENSE("GPL"); static int brightness_switch_enabled = 1; module_param(brightness_switch_enabled, bool, 0644); -static int register_count = 0; static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_remove(struct acpi_device *device, int type); static int acpi_video_resume(struct acpi_device *device); @@ -2319,13 +2318,6 @@ static int __init intel_opregion_present(void) int acpi_video_register(void) { int result = 0; - if (register_count) { - /* - * if the function of acpi_video_register is already called, - * don't register the acpi_vide_bus again and return no error. - */ - return 0; - } acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); if (!acpi_video_dir) @@ -2337,35 +2329,10 @@ int acpi_video_register(void) return -ENODEV; } - /* - * When the acpi_video_bus is loaded successfully, increase - * the counter reference. - */ - register_count = 1; - return 0; } EXPORT_SYMBOL(acpi_video_register); -void acpi_video_unregister(void) -{ - if (!register_count) { - /* - * If the acpi video bus is already unloaded, don't - * unload it again and return directly. - */ - return; - } - acpi_bus_unregister_driver(&acpi_video_bus); - - remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); - - register_count = 0; - - return; -} -EXPORT_SYMBOL(acpi_video_unregister); - /* * This is kind of nasty. Hardware using Intel chipsets may require * the video opregion code to be run first in order to initialise @@ -2383,12 +2350,16 @@ static int __init acpi_video_init(void) return acpi_video_register(); } -static void __exit acpi_video_exit(void) +void acpi_video_exit(void) { - acpi_video_unregister(); + + acpi_bus_unregister_driver(&acpi_video_bus); + + remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); return; } +EXPORT_SYMBOL(acpi_video_exit); module_init(acpi_video_init); module_exit(acpi_video_exit); diff --git a/trunk/drivers/gpu/drm/i915/i915_opregion.c b/trunk/drivers/gpu/drm/i915/i915_opregion.c index e4b4e8898e39..dc425e74a268 100644 --- a/trunk/drivers/gpu/drm/i915/i915_opregion.c +++ b/trunk/drivers/gpu/drm/i915/i915_opregion.c @@ -419,7 +419,7 @@ void intel_opregion_free(struct drm_device *dev, int suspend) return; if (!suspend) - acpi_video_unregister(); + acpi_video_exit(); opregion->acpi->drdy = 0; diff --git a/trunk/include/acpi/video.h b/trunk/include/acpi/video.h index cf7be3dd157b..af6fe95fd3d0 100644 --- a/trunk/include/acpi/video.h +++ b/trunk/include/acpi/video.h @@ -3,10 +3,10 @@ #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) extern int acpi_video_register(void); -extern void acpi_video_unregister(void); +extern int acpi_video_exit(void); #else static inline int acpi_video_register(void) { return 0; } -static inline void acpi_video_unregister(void) { return; } +static inline void acpi_video_exit(void) { return; } #endif #endif