diff options
author | Hans de Goede <hdegoede@redhat.com> | 2015-06-16 10:27:54 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-06-18 19:11:14 -0400 |
commit | 2a8b18e9fb650ab5c637005a7506045c46ed2b0e (patch) | |
tree | 637a4660e3ba3e89e8c3bea3b709712c4bcb333e | |
parent | 7ee33baabcae765e1eda73b988a62fe102c0ce76 (diff) |
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: Hans de Goede <hdegoede@redhat.com>
Acked-by: Darren Hart <dvhart@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/acpi/acpi_video.c | 43 |
1 files changed, 21 insertions, 22 deletions
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index efa0ab553aa3..5b877a127167 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c | |||
@@ -82,6 +82,7 @@ static int disable_backlight_sysfs_if = -1; | |||
82 | module_param(disable_backlight_sysfs_if, int, 0444); | 82 | module_param(disable_backlight_sysfs_if, int, 0444); |
83 | 83 | ||
84 | static int register_count; | 84 | static int register_count; |
85 | static DEFINE_MUTEX(register_count_mutex); | ||
85 | static struct mutex video_list_lock; | 86 | static struct mutex video_list_lock; |
86 | static struct list_head video_bus_head; | 87 | static struct list_head video_bus_head; |
87 | static int acpi_video_bus_add(struct acpi_device *device); | 88 | static int acpi_video_bus_add(struct acpi_device *device); |
@@ -1964,14 +1965,15 @@ static int __init intel_opregion_present(void) | |||
1964 | 1965 | ||
1965 | int acpi_video_register(void) | 1966 | int acpi_video_register(void) |
1966 | { | 1967 | { |
1967 | int ret; | 1968 | int ret = 0; |
1968 | 1969 | ||
1970 | mutex_lock(®ister_count_mutex); | ||
1969 | if (register_count) { | 1971 | if (register_count) { |
1970 | /* | 1972 | /* |
1971 | * if the function of acpi_video_register is already called, | 1973 | * if the function of acpi_video_register is already called, |
1972 | * don't register the acpi_vide_bus again and return no error. | 1974 | * don't register the acpi_vide_bus again and return no error. |
1973 | */ | 1975 | */ |
1974 | return 0; | 1976 | goto leave; |
1975 | } | 1977 | } |
1976 | 1978 | ||
1977 | mutex_init(&video_list_lock); | 1979 | mutex_init(&video_list_lock); |
@@ -1981,7 +1983,7 @@ int acpi_video_register(void) | |||
1981 | 1983 | ||
1982 | ret = acpi_bus_register_driver(&acpi_video_bus); | 1984 | ret = acpi_bus_register_driver(&acpi_video_bus); |
1983 | if (ret) | 1985 | if (ret) |
1984 | return ret; | 1986 | goto leave; |
1985 | 1987 | ||
1986 | /* | 1988 | /* |
1987 | * When the acpi_video_bus is loaded successfully, increase | 1989 | * When the acpi_video_bus is loaded successfully, increase |
@@ -1989,24 +1991,20 @@ int acpi_video_register(void) | |||
1989 | */ | 1991 | */ |
1990 | register_count = 1; | 1992 | register_count = 1; |
1991 | 1993 | ||
1992 | return 0; | 1994 | leave: |
1995 | mutex_unlock(®ister_count_mutex); | ||
1996 | return ret; | ||
1993 | } | 1997 | } |
1994 | EXPORT_SYMBOL(acpi_video_register); | 1998 | EXPORT_SYMBOL(acpi_video_register); |
1995 | 1999 | ||
1996 | void acpi_video_unregister(void) | 2000 | void acpi_video_unregister(void) |
1997 | { | 2001 | { |
1998 | if (!register_count) { | 2002 | mutex_lock(®ister_count_mutex); |
1999 | /* | 2003 | if (register_count) { |
2000 | * If the acpi video bus is already unloaded, don't | 2004 | acpi_bus_unregister_driver(&acpi_video_bus); |
2001 | * unload it again and return directly. | 2005 | register_count = 0; |
2002 | */ | ||
2003 | return; | ||
2004 | } | 2006 | } |
2005 | acpi_bus_unregister_driver(&acpi_video_bus); | 2007 | mutex_unlock(®ister_count_mutex); |
2006 | |||
2007 | register_count = 0; | ||
2008 | |||
2009 | return; | ||
2010 | } | 2008 | } |
2011 | EXPORT_SYMBOL(acpi_video_unregister); | 2009 | EXPORT_SYMBOL(acpi_video_unregister); |
2012 | 2010 | ||
@@ -2014,13 +2012,14 @@ void acpi_video_unregister_backlight(void) | |||
2014 | { | 2012 | { |
2015 | struct acpi_video_bus *video; | 2013 | struct acpi_video_bus *video; |
2016 | 2014 | ||
2017 | if (!register_count) | 2015 | mutex_lock(®ister_count_mutex); |
2018 | return; | 2016 | if (register_count) { |
2019 | 2017 | mutex_lock(&video_list_lock); | |
2020 | mutex_lock(&video_list_lock); | 2018 | list_for_each_entry(video, &video_bus_head, entry) |
2021 | list_for_each_entry(video, &video_bus_head, entry) | 2019 | acpi_video_bus_unregister_backlight(video); |
2022 | acpi_video_bus_unregister_backlight(video); | 2020 | mutex_unlock(&video_list_lock); |
2023 | mutex_unlock(&video_list_lock); | 2021 | } |
2022 | mutex_unlock(®ister_count_mutex); | ||
2024 | } | 2023 | } |
2025 | EXPORT_SYMBOL(acpi_video_unregister_backlight); | 2024 | EXPORT_SYMBOL(acpi_video_unregister_backlight); |
2026 | 2025 | ||