Commit 2a8b18e9 authored by Hans de Goede's avatar Hans de Goede Committed by Rafael J. Wysocki

ACPI / video: Fix acpi_video _register vs _unregister_backlight race

It is possible for a native backlight driver to load while
acpi_video_register is running, which may lead to
acpi_video_unregister_backlight being called while acpi_video_register
is running and the 2 racing against eachother.

The register_count variable protects against this, but not in a thread
safe manner, this commit adds locking to make this thread safe.
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Acked-by: default avatarDarren Hart <dvhart@linux.intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 7ee33baa
...@@ -82,6 +82,7 @@ static int disable_backlight_sysfs_if = -1; ...@@ -82,6 +82,7 @@ static int disable_backlight_sysfs_if = -1;
module_param(disable_backlight_sysfs_if, int, 0444); module_param(disable_backlight_sysfs_if, int, 0444);
static int register_count; static int register_count;
static DEFINE_MUTEX(register_count_mutex);
static struct mutex video_list_lock; static struct mutex video_list_lock;
static struct list_head video_bus_head; static struct list_head video_bus_head;
static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_add(struct acpi_device *device);
...@@ -1964,14 +1965,15 @@ static int __init intel_opregion_present(void) ...@@ -1964,14 +1965,15 @@ static int __init intel_opregion_present(void)
int acpi_video_register(void) int acpi_video_register(void)
{ {
int ret; int ret = 0;
mutex_lock(&register_count_mutex);
if (register_count) { if (register_count) {
/* /*
* if the function of acpi_video_register is already called, * if the function of acpi_video_register is already called,
* don't register the acpi_vide_bus again and return no error. * don't register the acpi_vide_bus again and return no error.
*/ */
return 0; goto leave;
} }
mutex_init(&video_list_lock); mutex_init(&video_list_lock);
...@@ -1981,7 +1983,7 @@ int acpi_video_register(void) ...@@ -1981,7 +1983,7 @@ int acpi_video_register(void)
ret = acpi_bus_register_driver(&acpi_video_bus); ret = acpi_bus_register_driver(&acpi_video_bus);
if (ret) if (ret)
return ret; goto leave;
/* /*
* When the acpi_video_bus is loaded successfully, increase * When the acpi_video_bus is loaded successfully, increase
...@@ -1989,24 +1991,20 @@ int acpi_video_register(void) ...@@ -1989,24 +1991,20 @@ int acpi_video_register(void)
*/ */
register_count = 1; register_count = 1;
return 0; leave:
mutex_unlock(&register_count_mutex);
return ret;
} }
EXPORT_SYMBOL(acpi_video_register); EXPORT_SYMBOL(acpi_video_register);
void acpi_video_unregister(void) void acpi_video_unregister(void)
{ {
if (!register_count) { mutex_lock(&register_count_mutex);
/* if (register_count) {
* If the acpi video bus is already unloaded, don't acpi_bus_unregister_driver(&acpi_video_bus);
* unload it again and return directly. register_count = 0;
*/
return;
} }
acpi_bus_unregister_driver(&acpi_video_bus); mutex_unlock(&register_count_mutex);
register_count = 0;
return;
} }
EXPORT_SYMBOL(acpi_video_unregister); EXPORT_SYMBOL(acpi_video_unregister);
...@@ -2014,13 +2012,14 @@ void acpi_video_unregister_backlight(void) ...@@ -2014,13 +2012,14 @@ void acpi_video_unregister_backlight(void)
{ {
struct acpi_video_bus *video; struct acpi_video_bus *video;
if (!register_count) mutex_lock(&register_count_mutex);
return; if (register_count) {
mutex_lock(&video_list_lock);
mutex_lock(&video_list_lock); list_for_each_entry(video, &video_bus_head, entry)
list_for_each_entry(video, &video_bus_head, entry) acpi_video_bus_unregister_backlight(video);
acpi_video_bus_unregister_backlight(video); mutex_unlock(&video_list_lock);
mutex_unlock(&video_list_lock); }
mutex_unlock(&register_count_mutex);
} }
EXPORT_SYMBOL(acpi_video_unregister_backlight); EXPORT_SYMBOL(acpi_video_unregister_backlight);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment