aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2008-04-26 00:02:28 -0400
committerLen Brown <len.brown@intel.com>2008-04-29 09:47:03 -0400
commite0e3c0615abdb1c3e28356595f7be87627288d5b (patch)
treefbb502f9853a15197097137834fc6517d2fdd236 /drivers/misc
parent10cc92759bb5d6031d308bdde96775f74082bb44 (diff)
ACPI: thinkpad-acpi: use a private workqueue
Switch all task workers to a private thinkpad-acpi workqueue. This way, we don't risk causing trouble for other tasks scheduled to the default work queue, as our workers end up needing to access the ACPI EC, run ACPI AML code, trigger SMI traps... and none of those are exactly known to be fast, simple operations. Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/thinkpad_acpi.c26
1 files changed, 19 insertions, 7 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index f471b46dcf5c..d5c08c01fd11 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -140,6 +140,7 @@ enum {
140#define TPACPI_HWMON_DRVR_NAME TPACPI_NAME "_hwmon" 140#define TPACPI_HWMON_DRVR_NAME TPACPI_NAME "_hwmon"
141 141
142#define TPACPI_NVRAM_KTHREAD_NAME "ktpacpi_nvramd" 142#define TPACPI_NVRAM_KTHREAD_NAME "ktpacpi_nvramd"
143#define TPACPI_WORKQUEUE_NAME "ktpacpid"
143 144
144#define TPACPI_MAX_ACPI_ARGS 3 145#define TPACPI_MAX_ACPI_ARGS 3
145 146
@@ -272,6 +273,8 @@ static enum {
272static int experimental; 273static int experimental;
273static u32 dbg_level; 274static u32 dbg_level;
274 275
276static struct workqueue_struct *tpacpi_wq;
277
275/* Special LED class that can defer work */ 278/* Special LED class that can defer work */
276struct tpacpi_led_classdev { 279struct tpacpi_led_classdev {
277 struct led_classdev led_classdev; 280 struct led_classdev led_classdev;
@@ -3298,7 +3301,7 @@ static void light_sysfs_set(struct led_classdev *led_cdev,
3298 struct tpacpi_led_classdev, 3301 struct tpacpi_led_classdev,
3299 led_classdev); 3302 led_classdev);
3300 data->new_brightness = brightness; 3303 data->new_brightness = brightness;
3301 schedule_work(&data->work); 3304 queue_work(tpacpi_wq, &data->work);
3302} 3305}
3303 3306
3304static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev) 3307static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev)
@@ -3355,7 +3358,7 @@ static void light_exit(void)
3355{ 3358{
3356 led_classdev_unregister(&tpacpi_led_thinklight.led_classdev); 3359 led_classdev_unregister(&tpacpi_led_thinklight.led_classdev);
3357 if (work_pending(&tpacpi_led_thinklight.work)) 3360 if (work_pending(&tpacpi_led_thinklight.work))
3358 flush_scheduled_work(); 3361 flush_workqueue(tpacpi_wq);
3359} 3362}
3360 3363
3361static int light_read(char *p) 3364static int light_read(char *p)
@@ -3925,7 +3928,7 @@ static void led_sysfs_set(struct led_classdev *led_cdev,
3925 struct tpacpi_led_classdev, led_classdev); 3928 struct tpacpi_led_classdev, led_classdev);
3926 3929
3927 data->new_brightness = brightness; 3930 data->new_brightness = brightness;
3928 schedule_work(&data->work); 3931 queue_work(tpacpi_wq, &data->work);
3929} 3932}
3930 3933
3931static int led_sysfs_blink_set(struct led_classdev *led_cdev, 3934static int led_sysfs_blink_set(struct led_classdev *led_cdev,
@@ -3943,7 +3946,7 @@ static int led_sysfs_blink_set(struct led_classdev *led_cdev,
3943 return -EINVAL; 3946 return -EINVAL;
3944 3947
3945 data->new_brightness = TPACPI_LED_BLINK; 3948 data->new_brightness = TPACPI_LED_BLINK;
3946 schedule_work(&data->work); 3949 queue_work(tpacpi_wq, &data->work);
3947 3950
3948 return 0; 3951 return 0;
3949} 3952}
@@ -5408,11 +5411,11 @@ static void fan_watchdog_reset(void)
5408 if (fan_watchdog_maxinterval > 0 && 5411 if (fan_watchdog_maxinterval > 0 &&
5409 tpacpi_lifecycle != TPACPI_LIFE_EXITING) { 5412 tpacpi_lifecycle != TPACPI_LIFE_EXITING) {
5410 fan_watchdog_active = 1; 5413 fan_watchdog_active = 1;
5411 if (!schedule_delayed_work(&fan_watchdog_task, 5414 if (!queue_delayed_work(tpacpi_wq, &fan_watchdog_task,
5412 msecs_to_jiffies(fan_watchdog_maxinterval 5415 msecs_to_jiffies(fan_watchdog_maxinterval
5413 * 1000))) { 5416 * 1000))) {
5414 printk(TPACPI_ERR 5417 printk(TPACPI_ERR
5415 "failed to schedule the fan watchdog, " 5418 "failed to queue the fan watchdog, "
5416 "watchdog will not trigger\n"); 5419 "watchdog will not trigger\n");
5417 } 5420 }
5418 } else 5421 } else
@@ -5782,7 +5785,7 @@ static void fan_exit(void)
5782 &driver_attr_fan_watchdog); 5785 &driver_attr_fan_watchdog);
5783 5786
5784 cancel_delayed_work(&fan_watchdog_task); 5787 cancel_delayed_work(&fan_watchdog_task);
5785 flush_scheduled_work(); 5788 flush_workqueue(tpacpi_wq);
5786} 5789}
5787 5790
5788static int fan_read(char *p) 5791static int fan_read(char *p)
@@ -6436,6 +6439,9 @@ static void thinkpad_acpi_module_exit(void)
6436 if (proc_dir) 6439 if (proc_dir)
6437 remove_proc_entry(TPACPI_PROC_DIR, acpi_root_dir); 6440 remove_proc_entry(TPACPI_PROC_DIR, acpi_root_dir);
6438 6441
6442 if (tpacpi_wq)
6443 destroy_workqueue(tpacpi_wq);
6444
6439 kfree(thinkpad_id.bios_version_str); 6445 kfree(thinkpad_id.bios_version_str);
6440 kfree(thinkpad_id.ec_version_str); 6446 kfree(thinkpad_id.ec_version_str);
6441 kfree(thinkpad_id.model_str); 6447 kfree(thinkpad_id.model_str);
@@ -6466,6 +6472,12 @@ static int __init thinkpad_acpi_module_init(void)
6466 TPACPI_ACPIHANDLE_INIT(ecrd); 6472 TPACPI_ACPIHANDLE_INIT(ecrd);
6467 TPACPI_ACPIHANDLE_INIT(ecwr); 6473 TPACPI_ACPIHANDLE_INIT(ecwr);
6468 6474
6475 tpacpi_wq = create_singlethread_workqueue(TPACPI_WORKQUEUE_NAME);
6476 if (!tpacpi_wq) {
6477 thinkpad_acpi_module_exit();
6478 return -ENOMEM;
6479 }
6480
6469 proc_dir = proc_mkdir(TPACPI_PROC_DIR, acpi_root_dir); 6481 proc_dir = proc_mkdir(TPACPI_PROC_DIR, acpi_root_dir);
6470 if (!proc_dir) { 6482 if (!proc_dir) {
6471 printk(TPACPI_ERR 6483 printk(TPACPI_ERR