From: Tejun Heo Date: Fri, 24 Aug 2012 01:11:34 +0000 (-0700) Subject: x86, apm: Make on_cpu0() use workqueue instead of work_on_cpu() X-Git-Tag: next-20120904~37^2 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=f07bb365960ae262d2dfcad44692be733ceb4e93;p=karo-tx-linux.git 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 --- 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; } /**