From f07bb365960ae262d2dfcad44692be733ceb4e93 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 23 Aug 2012 18:11:34 -0700 Subject: [PATCH] x86, apm: Make on_cpu0() use workqueue instead of work_on_cpu() Make APM schedule a work item on CPU0 instead of using the expensive work_on_cpu(); hopefully, this is the last user of work_on_cpu() and we can take out work_on_cpu() in not too distant future. Tested both paths. Seems to work fine. Signed-off-by: Tejun Heo Signed-off-by: Jiri Kosina --- arch/x86/kernel/apm_32.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index a46bd383953c..a7f0914a0a26 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -604,28 +604,43 @@ static long __apm_bios_call(void *_call) return call->eax & 0xff; } +struct on_cpu0_arg { + struct work_struct work; + long (*fn)(void *); + struct apm_bios_call *call; + int ret; +}; + +static void on_cpu0_workfn(struct work_struct *work) +{ + struct on_cpu0_arg *arg = container_of(work, struct on_cpu0_arg, work); + + arg->ret = arg->fn(arg->call); +} + /* Run __apm_bios_call or __apm_bios_call_simple on CPU 0 */ static int on_cpu0(long (*fn)(void *), struct apm_bios_call *call) { - int ret; + struct on_cpu0_arg arg = { .fn = fn, .call = call }; - /* Don't bother with work_on_cpu in the common case, so we don't - * have to worry about OOM or overhead. */ + /* directly invoke on_cpu0_workfn() in the common case */ if (get_cpu() == 0) { - ret = fn(call); + on_cpu0_workfn(&arg.work); put_cpu(); } else { put_cpu(); - ret = work_on_cpu(0, fn, call); + INIT_WORK_ONSTACK(&arg.work, on_cpu0_workfn); + schedule_work_on(0, &arg.work); + flush_work(&arg.work); } /* work_on_cpu can fail with -ENOMEM */ - if (ret < 0) - call->err = ret; + if (arg.ret < 0) + call->err = arg.ret; else call->err = (call->eax >> 8) & 0xff; - return ret; + return arg.ret; } /** -- 2.39.5