1a0652fc9SPaul Mackerras /* 2a0652fc9SPaul Mackerras * Idle daemon for PowerPC. Idle daemon will handle any action 3a0652fc9SPaul Mackerras * that needs to be taken when the system becomes idle. 4a0652fc9SPaul Mackerras * 5a0652fc9SPaul Mackerras * Originally written by Cort Dougan (cort@cs.nmt.edu). 6a0652fc9SPaul Mackerras * Subsequent 32-bit hacking by Tom Rini, Armin Kuster, 7a0652fc9SPaul Mackerras * Paul Mackerras and others. 8a0652fc9SPaul Mackerras * 9a0652fc9SPaul Mackerras * iSeries supported added by Mike Corrigan <mikejc@us.ibm.com> 10a0652fc9SPaul Mackerras * 11a0652fc9SPaul Mackerras * Additional shared processor, SMT, and firmware support 12a0652fc9SPaul Mackerras * Copyright (c) 2003 Dave Engebretsen <engebret@us.ibm.com> 13a0652fc9SPaul Mackerras * 14a0652fc9SPaul Mackerras * 32-bit and 64-bit versions merged by Paul Mackerras <paulus@samba.org> 15a0652fc9SPaul Mackerras * 16a0652fc9SPaul Mackerras * This program is free software; you can redistribute it and/or 17a0652fc9SPaul Mackerras * modify it under the terms of the GNU General Public License 18a0652fc9SPaul Mackerras * as published by the Free Software Foundation; either version 19a0652fc9SPaul Mackerras * 2 of the License, or (at your option) any later version. 20a0652fc9SPaul Mackerras */ 21a0652fc9SPaul Mackerras 22a0652fc9SPaul Mackerras #include <linux/sched.h> 23a0652fc9SPaul Mackerras #include <linux/kernel.h> 24a0652fc9SPaul Mackerras #include <linux/smp.h> 25a0652fc9SPaul Mackerras #include <linux/cpu.h> 26a0652fc9SPaul Mackerras #include <linux/sysctl.h> 271ad74998STony Breeds #include <linux/tick.h> 28a0652fc9SPaul Mackerras 29a0652fc9SPaul Mackerras #include <asm/system.h> 30a0652fc9SPaul Mackerras #include <asm/processor.h> 31a0652fc9SPaul Mackerras #include <asm/cputable.h> 32a0652fc9SPaul Mackerras #include <asm/time.h> 33a0652fc9SPaul Mackerras #include <asm/machdep.h> 34a0652fc9SPaul Mackerras #include <asm/smp.h> 35a0652fc9SPaul Mackerras 36a0652fc9SPaul Mackerras #ifdef CONFIG_HOTPLUG_CPU 3761e9916eSJohannes Berg #define cpu_should_die() cpu_is_offline(smp_processor_id()) 38a0652fc9SPaul Mackerras #else 39a0652fc9SPaul Mackerras #define cpu_should_die() 0 40a0652fc9SPaul Mackerras #endif 41a0652fc9SPaul Mackerras 42771dae81SDeepthi Dharwar unsigned long cpuidle_disable = IDLE_NO_OVERRIDE; 43771dae81SDeepthi Dharwar EXPORT_SYMBOL(cpuidle_disable); 44771dae81SDeepthi Dharwar 45302eca18Sarnd@arndb.de static int __init powersave_off(char *arg) 46302eca18Sarnd@arndb.de { 47302eca18Sarnd@arndb.de ppc_md.power_save = NULL; 48771dae81SDeepthi Dharwar cpuidle_disable = IDLE_POWERSAVE_OFF; 49302eca18Sarnd@arndb.de return 0; 50302eca18Sarnd@arndb.de } 51302eca18Sarnd@arndb.de __setup("powersave=off", powersave_off); 52302eca18Sarnd@arndb.de 53a0652fc9SPaul Mackerras /* 54a0652fc9SPaul Mackerras * The body of the idle task. 55a0652fc9SPaul Mackerras */ 56a0652fc9SPaul Mackerras void cpu_idle(void) 57a0652fc9SPaul Mackerras { 58a0652fc9SPaul Mackerras if (ppc_md.idle_loop) 59a0652fc9SPaul Mackerras ppc_md.idle_loop(); /* doesn't return */ 60a0652fc9SPaul Mackerras 61a0652fc9SPaul Mackerras set_thread_flag(TIF_POLLING_NRFLAG); 62a0652fc9SPaul Mackerras while (1) { 63a7b152d5SPaul E. McKenney tick_nohz_idle_enter(); 641268fbc7SFrederic Weisbecker rcu_idle_enter(); 651268fbc7SFrederic Weisbecker 66ddafddcfSAnton Blanchard while (!need_resched() && !cpu_should_die()) { 67a0652fc9SPaul Mackerras ppc64_runlatch_off(); 68a0652fc9SPaul Mackerras 69a0652fc9SPaul Mackerras if (ppc_md.power_save) { 70a0652fc9SPaul Mackerras clear_thread_flag(TIF_POLLING_NRFLAG); 71a0652fc9SPaul Mackerras /* 72a0652fc9SPaul Mackerras * smp_mb is so clearing of TIF_POLLING_NRFLAG 73a0652fc9SPaul Mackerras * is ordered w.r.t. need_resched() test. 74a0652fc9SPaul Mackerras */ 75a0652fc9SPaul Mackerras smp_mb(); 76a0652fc9SPaul Mackerras local_irq_disable(); 77a0652fc9SPaul Mackerras 786d07bb47SSteven Rostedt /* Don't trace irqs off for idle */ 796d07bb47SSteven Rostedt stop_critical_timings(); 806d07bb47SSteven Rostedt 81a0652fc9SPaul Mackerras /* check again after disabling irqs */ 82a0652fc9SPaul Mackerras if (!need_resched() && !cpu_should_die()) 83a0652fc9SPaul Mackerras ppc_md.power_save(); 84a0652fc9SPaul Mackerras 856d07bb47SSteven Rostedt start_critical_timings(); 866d07bb47SSteven Rostedt 87*7230c564SBenjamin Herrenschmidt /* Some power_save functions return with 88*7230c564SBenjamin Herrenschmidt * interrupts enabled, some don't. 89*7230c564SBenjamin Herrenschmidt */ 90*7230c564SBenjamin Herrenschmidt if (irqs_disabled()) 91a0652fc9SPaul Mackerras local_irq_enable(); 92a0652fc9SPaul Mackerras set_thread_flag(TIF_POLLING_NRFLAG); 93a0652fc9SPaul Mackerras 94a0652fc9SPaul Mackerras } else { 95a0652fc9SPaul Mackerras /* 96a0652fc9SPaul Mackerras * Go into low thread priority and possibly 97a0652fc9SPaul Mackerras * low power mode. 98a0652fc9SPaul Mackerras */ 99a0652fc9SPaul Mackerras HMT_low(); 100a0652fc9SPaul Mackerras HMT_very_low(); 101a0652fc9SPaul Mackerras } 102a0652fc9SPaul Mackerras } 103a0652fc9SPaul Mackerras 104a0652fc9SPaul Mackerras HMT_medium(); 105a0652fc9SPaul Mackerras ppc64_runlatch_on(); 1061268fbc7SFrederic Weisbecker rcu_idle_exit(); 107a7b152d5SPaul E. McKenney tick_nohz_idle_exit(); 108a7c2bb82SSigned-off-by: Darren Hart preempt_enable_no_resched(); 109a0652fc9SPaul Mackerras if (cpu_should_die()) 110a0652fc9SPaul Mackerras cpu_die(); 111a0652fc9SPaul Mackerras schedule(); 112a0652fc9SPaul Mackerras preempt_disable(); 113a0652fc9SPaul Mackerras } 114a0652fc9SPaul Mackerras } 115a0652fc9SPaul Mackerras 116771dae81SDeepthi Dharwar 117771dae81SDeepthi Dharwar /* 118771dae81SDeepthi Dharwar * cpu_idle_wait - Used to ensure that all the CPUs come out of the old 119771dae81SDeepthi Dharwar * idle loop and start using the new idle loop. 120771dae81SDeepthi Dharwar * Required while changing idle handler on SMP systems. 121771dae81SDeepthi Dharwar * Caller must have changed idle handler to the new value before the call. 122771dae81SDeepthi Dharwar * This window may be larger on shared systems. 123771dae81SDeepthi Dharwar */ 124771dae81SDeepthi Dharwar void cpu_idle_wait(void) 125771dae81SDeepthi Dharwar { 126771dae81SDeepthi Dharwar int cpu; 127771dae81SDeepthi Dharwar smp_mb(); 128771dae81SDeepthi Dharwar 129771dae81SDeepthi Dharwar /* kick all the CPUs so that they exit out of old idle routine */ 130771dae81SDeepthi Dharwar get_online_cpus(); 131771dae81SDeepthi Dharwar for_each_online_cpu(cpu) { 132771dae81SDeepthi Dharwar if (cpu != smp_processor_id()) 133771dae81SDeepthi Dharwar smp_send_reschedule(cpu); 134771dae81SDeepthi Dharwar } 135771dae81SDeepthi Dharwar put_online_cpus(); 136771dae81SDeepthi Dharwar } 137771dae81SDeepthi Dharwar EXPORT_SYMBOL_GPL(cpu_idle_wait); 138771dae81SDeepthi Dharwar 139a0652fc9SPaul Mackerras int powersave_nap; 140a0652fc9SPaul Mackerras 141a0652fc9SPaul Mackerras #ifdef CONFIG_SYSCTL 142a0652fc9SPaul Mackerras /* 143a0652fc9SPaul Mackerras * Register the sysctl to set/clear powersave_nap. 144a0652fc9SPaul Mackerras */ 145a0652fc9SPaul Mackerras static ctl_table powersave_nap_ctl_table[]={ 146a0652fc9SPaul Mackerras { 147a0652fc9SPaul Mackerras .procname = "powersave-nap", 148a0652fc9SPaul Mackerras .data = &powersave_nap, 149a0652fc9SPaul Mackerras .maxlen = sizeof(int), 150a0652fc9SPaul Mackerras .mode = 0644, 1516d456111SEric W. Biederman .proc_handler = proc_dointvec, 152a0652fc9SPaul Mackerras }, 153f5f10678SEric W. Biederman {} 154a0652fc9SPaul Mackerras }; 155a0652fc9SPaul Mackerras static ctl_table powersave_nap_sysctl_root[] = { 156f5f10678SEric W. Biederman { 157f5f10678SEric W. Biederman .procname = "kernel", 158fb293ae1SAlexey Dobriyan .mode = 0555, 159f5f10678SEric W. Biederman .child = powersave_nap_ctl_table, 160f5f10678SEric W. Biederman }, 161f5f10678SEric W. Biederman {} 162a0652fc9SPaul Mackerras }; 163a0652fc9SPaul Mackerras 164a0652fc9SPaul Mackerras static int __init 165a0652fc9SPaul Mackerras register_powersave_nap_sysctl(void) 166a0652fc9SPaul Mackerras { 1670b4d4147SEric W. Biederman register_sysctl_table(powersave_nap_sysctl_root); 168a0652fc9SPaul Mackerras 169a0652fc9SPaul Mackerras return 0; 170a0652fc9SPaul Mackerras } 171a0652fc9SPaul Mackerras __initcall(register_powersave_nap_sysctl); 172a0652fc9SPaul Mackerras #endif 173