X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fs390%2Fkernel%2Fprocess.c;h=73cb6baeb5259c1a39277273099cc709a61a373e;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=63818a50e48152096c8bb9422eff57fcdf3dd3e3;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 63818a50e..73cb6baeb 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,8 @@ #include #include #include +#include +#include #include #include @@ -41,9 +44,7 @@ #include #include #include -#if defined(CONFIG_VIRT_TIMER) || defined (CONFIG_NO_IDLE_HZ) #include -#endif asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); @@ -68,13 +69,39 @@ unsigned long thread_saved_pc(struct task_struct *tsk) } /* - * The idle loop on a S390... + * Need to know about CPUs going idle? */ +static struct notifier_block *idle_chain; + +int register_idle_notifier(struct notifier_block *nb) +{ + return notifier_chain_register(&idle_chain, nb); +} +EXPORT_SYMBOL(register_idle_notifier); + +int unregister_idle_notifier(struct notifier_block *nb) +{ + return notifier_chain_unregister(&idle_chain, nb); +} +EXPORT_SYMBOL(unregister_idle_notifier); + +void do_monitor_call(struct pt_regs *regs, long interruption_code) +{ + /* disable monitor call class 0 */ + __ctl_clear_bit(8, 15); + + notifier_call_chain(&idle_chain, CPU_NOT_IDLE, + (void *)(long) smp_processor_id()); +} +/* + * The idle loop on a S390... + */ void default_idle(void) { psw_t wait_psw; unsigned long reg; + int cpu, rc; local_irq_disable(); if (need_resched()) { @@ -83,14 +110,22 @@ void default_idle(void) return; } -#if defined(CONFIG_VIRT_TIMER) || defined (CONFIG_NO_IDLE_HZ) - /* - * hook to stop timers that should not tick while CPU is idle - */ - if (stop_timers()) { + /* CPU is going idle. */ + cpu = smp_processor_id(); + rc = notifier_call_chain(&idle_chain, CPU_IDLE, (void *)(long) cpu); + if (rc != NOTIFY_OK && rc != NOTIFY_DONE) + BUG(); + if (rc != NOTIFY_OK) { local_irq_enable(); return; } + + /* enable monitor call class 0 */ + __ctl_set_bit(8, 15); + +#ifdef CONFIG_HOTPLUG_CPU + if (cpu_is_offline(smp_processor_id())) + cpu_die(); #endif /*