aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2009-06-15 23:23:13 -0400
committerLen Brown <len.brown@intel.com>2009-06-23 23:38:41 -0400
commit86e437f077c68112edcb6854ec036ed7e3f9a7f3 (patch)
treeac6ec8b6ac4f96ce7ef7b5e9fa057099d7ce9af1 /drivers/acpi
parent07a2039b8eb0af4ff464efd3dfd95de5c02648c6 (diff)
ACPI: Add the reference count to avoid unloading ACPI video bus twice
Sometimes both acpi video and i915 driver are compiled as modules. And there exists the strict dependency between the two drivers. The acpi video bus will be unloaded in course of unloading the i915 driver. If we unload the acpi video driver, then the kernel oops will be triggered. Add the reference count to avoid unloading the ACPI video bus twice. The reference count should be checked before unregistering the acpi video bus. If the reference count is already zero, it won't unregister it again. And after the acpi video bus is already unregistered, the reference count will be set to zero. http://bugzilla.kernel.org/show_bug.cgi?id=13396 Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Acked-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/video.c41
1 files changed, 35 insertions, 6 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 1bdfb37377e3..a63566ba230b 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -76,6 +76,7 @@ MODULE_LICENSE("GPL");
76static int brightness_switch_enabled = 1; 76static int brightness_switch_enabled = 1;
77module_param(brightness_switch_enabled, bool, 0644); 77module_param(brightness_switch_enabled, bool, 0644);
78 78
79static int register_count = 0;
79static int acpi_video_bus_add(struct acpi_device *device); 80static int acpi_video_bus_add(struct acpi_device *device);
80static int acpi_video_bus_remove(struct acpi_device *device, int type); 81static int acpi_video_bus_remove(struct acpi_device *device, int type);
81static int acpi_video_resume(struct acpi_device *device); 82static int acpi_video_resume(struct acpi_device *device);
@@ -2318,6 +2319,13 @@ static int __init intel_opregion_present(void)
2318int acpi_video_register(void) 2319int acpi_video_register(void)
2319{ 2320{
2320 int result = 0; 2321 int result = 0;
2322 if (register_count) {
2323 /*
2324 * if the function of acpi_video_register is already called,
2325 * don't register the acpi_vide_bus again and return no error.
2326 */
2327 return 0;
2328 }
2321 2329
2322 acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); 2330 acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
2323 if (!acpi_video_dir) 2331 if (!acpi_video_dir)
@@ -2329,10 +2337,35 @@ int acpi_video_register(void)
2329 return -ENODEV; 2337 return -ENODEV;
2330 } 2338 }
2331 2339
2340 /*
2341 * When the acpi_video_bus is loaded successfully, increase
2342 * the counter reference.
2343 */
2344 register_count = 1;
2345
2332 return 0; 2346 return 0;
2333} 2347}
2334EXPORT_SYMBOL(acpi_video_register); 2348EXPORT_SYMBOL(acpi_video_register);
2335 2349
2350void acpi_video_unregister(void)
2351{
2352 if (!register_count) {
2353 /*
2354 * If the acpi video bus is already unloaded, don't
2355 * unload it again and return directly.
2356 */
2357 return;
2358 }
2359 acpi_bus_unregister_driver(&acpi_video_bus);
2360
2361 remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
2362
2363 register_count = 0;
2364
2365 return;
2366}
2367EXPORT_SYMBOL(acpi_video_unregister);
2368
2336/* 2369/*
2337 * This is kind of nasty. Hardware using Intel chipsets may require 2370 * This is kind of nasty. Hardware using Intel chipsets may require
2338 * the video opregion code to be run first in order to initialise 2371 * the video opregion code to be run first in order to initialise
@@ -2350,16 +2383,12 @@ static int __init acpi_video_init(void)
2350 return acpi_video_register(); 2383 return acpi_video_register();
2351} 2384}
2352 2385
2353void acpi_video_exit(void) 2386static void __exit acpi_video_exit(void)
2354{ 2387{
2355 2388 acpi_video_unregister();
2356 acpi_bus_unregister_driver(&acpi_video_bus);
2357
2358 remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
2359 2389
2360 return; 2390 return;
2361} 2391}
2362EXPORT_SYMBOL(acpi_video_exit);
2363 2392
2364module_init(acpi_video_init); 2393module_init(acpi_video_init);
2365module_exit(acpi_video_exit); 2394module_exit(acpi_video_exit);