diff options
author | Adrien Schildknecht <adrien+dev@schischi.me> | 2016-01-04 23:22:28 +0100 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-01-05 13:38:50 +0100 |
commit | aecbd9b1bff6afbe349921b406b99d285b412820 (patch) | |
tree | 002e2aea096bdb9c1f335f37bfe2ff7c19547c37 | |
parent | 49eb5208220a9eef7529decbdefd95e4b94a928b (diff) |
ACPI / video: driver must be registered before checking for keypresses
acpi_video_handles_brightness_key_presses() may use an uninitialized mutex.
The error has been reported by lockdep: DEBUG_LOCKS_WARN_ON(l->magic != l).
The function assumes that the video driver has been registered before being
called. As explained in the comment of acpi_video_init(), the registration
of the video class may be defered and thus may not take place in the init
function of the module.
Use completion mechanisms to make sure that
acpi_video_handles_brightness_key_presses() wait for the completion of
acpi_video_register() before using the mutex.
Also get rid of register_count since task completion can replace it.
Signed-off-by: Adrien Schildknecht <adrien+dev@schischi.me>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/acpi/acpi_video.c | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index 80b13d498091..06a006ff89b0 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -90,8 +90,8 @@ module_param(device_id_scheme, bool, 0444); static bool only_lcd = false; module_param(only_lcd, bool, 0444); -static int register_count; -static DEFINE_MUTEX(register_count_mutex); +static DECLARE_COMPLETION(register_done); +static DEFINE_MUTEX(register_done_mutex); static struct mutex video_list_lock; static struct list_head video_bus_head; static int acpi_video_bus_add(struct acpi_device *device); @@ -2049,8 +2049,8 @@ int acpi_video_register(void) { int ret = 0; - mutex_lock(®ister_count_mutex); - if (register_count) { + mutex_lock(®ister_done_mutex); + if (completion_done(®ister_done)) { /* * if the function of acpi_video_register is already called, * don't register the acpi_vide_bus again and return no error. @@ -2071,22 +2071,22 @@ int acpi_video_register(void) * When the acpi_video_bus is loaded successfully, increase * the counter reference. */ - register_count = 1; + complete(®ister_done); leave: - mutex_unlock(®ister_count_mutex); + mutex_unlock(®ister_done_mutex); return ret; } EXPORT_SYMBOL(acpi_video_register); void acpi_video_unregister(void) { - mutex_lock(®ister_count_mutex); - if (register_count) { + mutex_lock(®ister_done_mutex); + if (completion_done(®ister_done)) { acpi_bus_unregister_driver(&acpi_video_bus); - register_count = 0; + reinit_completion(®ister_done); } - mutex_unlock(®ister_count_mutex); + mutex_unlock(®ister_done_mutex); } EXPORT_SYMBOL(acpi_video_unregister); @@ -2094,20 +2094,21 @@ void acpi_video_unregister_backlight(void) { struct acpi_video_bus *video; - mutex_lock(®ister_count_mutex); - if (register_count) { + mutex_lock(®ister_done_mutex); + if (completion_done(®ister_done)) { mutex_lock(&video_list_lock); list_for_each_entry(video, &video_bus_head, entry) acpi_video_bus_unregister_backlight(video); mutex_unlock(&video_list_lock); } - mutex_unlock(®ister_count_mutex); + mutex_unlock(®ister_done_mutex); } bool acpi_video_handles_brightness_key_presses(void) { bool have_video_busses; + wait_for_completion(®ister_done); mutex_lock(&video_list_lock); have_video_busses = !list_empty(&video_bus_head); mutex_unlock(&video_list_lock); |