diff options
author | Stephen Boyd <sboyd@codeaurora.org> | 2012-03-28 17:31:00 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2012-03-28 17:31:00 -0400 |
commit | a36cf844c543c6193445a7b1492d16e5a8cf376e (patch) | |
tree | 7839e51c505a12662ada9affef4cc9da5277b192 | |
parent | dddb5549da6b15ea8b9ce9ee0859c8d1fa268b5b (diff) |
firmware_class: Move request_firmware_nowait() to workqueues
Oddly enough a work_struct was already part of the firmware_work
structure but nobody was using it. Instead of creating a new
kthread for each request_firmware_nowait() call just schedule the
work on the system workqueue. This should avoid some overhead
in forking new threads when they're not strictly necessary.
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-rw-r--r-- | drivers/base/firmware_class.c | 27 |
1 files changed, 7 insertions, 20 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index ae00a2fd280f..5401814c874d 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -16,10 +16,11 @@ | |||
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/bitops.h> | 17 | #include <linux/bitops.h> |
18 | #include <linux/mutex.h> | 18 | #include <linux/mutex.h> |
19 | #include <linux/kthread.h> | 19 | #include <linux/workqueue.h> |
20 | #include <linux/highmem.h> | 20 | #include <linux/highmem.h> |
21 | #include <linux/firmware.h> | 21 | #include <linux/firmware.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/sched.h> | ||
23 | 24 | ||
24 | #define to_dev(obj) container_of(obj, struct device, kobj) | 25 | #define to_dev(obj) container_of(obj, struct device, kobj) |
25 | 26 | ||
@@ -630,19 +631,15 @@ struct firmware_work { | |||
630 | bool uevent; | 631 | bool uevent; |
631 | }; | 632 | }; |
632 | 633 | ||
633 | static int request_firmware_work_func(void *arg) | 634 | static void request_firmware_work_func(struct work_struct *work) |
634 | { | 635 | { |
635 | struct firmware_work *fw_work = arg; | 636 | struct firmware_work *fw_work; |
636 | const struct firmware *fw; | 637 | const struct firmware *fw; |
637 | struct firmware_priv *fw_priv; | 638 | struct firmware_priv *fw_priv; |
638 | long timeout; | 639 | long timeout; |
639 | int ret; | 640 | int ret; |
640 | 641 | ||
641 | if (!arg) { | 642 | fw_work = container_of(work, struct firmware_work, work); |
642 | WARN_ON(1); | ||
643 | return 0; | ||
644 | } | ||
645 | |||
646 | fw_priv = _request_firmware_prepare(&fw, fw_work->name, fw_work->device, | 643 | fw_priv = _request_firmware_prepare(&fw, fw_work->name, fw_work->device, |
647 | fw_work->uevent, true); | 644 | fw_work->uevent, true); |
648 | if (IS_ERR_OR_NULL(fw_priv)) { | 645 | if (IS_ERR_OR_NULL(fw_priv)) { |
@@ -667,8 +664,6 @@ static int request_firmware_work_func(void *arg) | |||
667 | 664 | ||
668 | module_put(fw_work->module); | 665 | module_put(fw_work->module); |
669 | kfree(fw_work); | 666 | kfree(fw_work); |
670 | |||
671 | return ret; | ||
672 | } | 667 | } |
673 | 668 | ||
674 | /** | 669 | /** |
@@ -694,7 +689,6 @@ request_firmware_nowait( | |||
694 | const char *name, struct device *device, gfp_t gfp, void *context, | 689 | const char *name, struct device *device, gfp_t gfp, void *context, |
695 | void (*cont)(const struct firmware *fw, void *context)) | 690 | void (*cont)(const struct firmware *fw, void *context)) |
696 | { | 691 | { |
697 | struct task_struct *task; | ||
698 | struct firmware_work *fw_work; | 692 | struct firmware_work *fw_work; |
699 | 693 | ||
700 | fw_work = kzalloc(sizeof (struct firmware_work), gfp); | 694 | fw_work = kzalloc(sizeof (struct firmware_work), gfp); |
@@ -713,15 +707,8 @@ request_firmware_nowait( | |||
713 | return -EFAULT; | 707 | return -EFAULT; |
714 | } | 708 | } |
715 | 709 | ||
716 | task = kthread_run(request_firmware_work_func, fw_work, | 710 | INIT_WORK(&fw_work->work, request_firmware_work_func); |
717 | "firmware/%s", name); | 711 | schedule_work(&fw_work->work); |
718 | if (IS_ERR(task)) { | ||
719 | fw_work->cont(NULL, fw_work->context); | ||
720 | module_put(fw_work->module); | ||
721 | kfree(fw_work); | ||
722 | return PTR_ERR(task); | ||
723 | } | ||
724 | |||
725 | return 0; | 712 | return 0; |
726 | } | 713 | } |
727 | 714 | ||