aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2015-06-16 10:27:54 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-06-18 19:11:14 -0400
commit2a8b18e9fb650ab5c637005a7506045c46ed2b0e (patch)
tree637a4660e3ba3e89e8c3bea3b709712c4bcb333e
parent7ee33baabcae765e1eda73b988a62fe102c0ce76 (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.c43
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;
82module_param(disable_backlight_sysfs_if, int, 0444); 82module_param(disable_backlight_sysfs_if, int, 0444);
83 83
84static int register_count; 84static int register_count;
85static DEFINE_MUTEX(register_count_mutex);
85static struct mutex video_list_lock; 86static struct mutex video_list_lock;
86static struct list_head video_bus_head; 87static struct list_head video_bus_head;
87static int acpi_video_bus_add(struct acpi_device *device); 88static int acpi_video_bus_add(struct acpi_device *device);
@@ -1964,14 +1965,15 @@ static int __init intel_opregion_present(void)
1964 1965
1965int acpi_video_register(void) 1966int acpi_video_register(void)
1966{ 1967{
1967 int ret; 1968 int ret = 0;
1968 1969
1970 mutex_lock(&register_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; 1994leave:
1995 mutex_unlock(&register_count_mutex);
1996 return ret;
1993} 1997}
1994EXPORT_SYMBOL(acpi_video_register); 1998EXPORT_SYMBOL(acpi_video_register);
1995 1999
1996void acpi_video_unregister(void) 2000void acpi_video_unregister(void)
1997{ 2001{
1998 if (!register_count) { 2002 mutex_lock(&register_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(&register_count_mutex);
2006
2007 register_count = 0;
2008
2009 return;
2010} 2008}
2011EXPORT_SYMBOL(acpi_video_unregister); 2009EXPORT_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(&register_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(&register_count_mutex);
2024} 2023}
2025EXPORT_SYMBOL(acpi_video_unregister_backlight); 2024EXPORT_SYMBOL(acpi_video_unregister_backlight);
2026 2025