aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/firmware_class.c
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2012-03-28 17:31:00 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-03-28 17:31:00 -0400
commita36cf844c543c6193445a7b1492d16e5a8cf376e (patch)
tree7839e51c505a12662ada9affef4cc9da5277b192 /drivers/base/firmware_class.c
parentdddb5549da6b15ea8b9ce9ee0859c8d1fa268b5b (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>
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r--drivers/base/firmware_class.c27
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
633static int request_firmware_work_func(void *arg) 634static 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