diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 26 |
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 { | |||
272 | static int experimental; | 273 | static int experimental; |
273 | static u32 dbg_level; | 274 | static u32 dbg_level; |
274 | 275 | ||
276 | static struct workqueue_struct *tpacpi_wq; | ||
277 | |||
275 | /* Special LED class that can defer work */ | 278 | /* Special LED class that can defer work */ |
276 | struct tpacpi_led_classdev { | 279 | struct 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 | ||
3304 | static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev) | 3307 | static 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 | ||
3361 | static int light_read(char *p) | 3364 | static 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 | ||
3931 | static int led_sysfs_blink_set(struct led_classdev *led_cdev, | 3934 | static 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 | ||
5788 | static int fan_read(char *p) | 5791 | static 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 |