1*a0652fc9SPaul Mackerras /* 2*a0652fc9SPaul Mackerras * Idle daemon for PowerPC. Idle daemon will handle any action 3*a0652fc9SPaul Mackerras * that needs to be taken when the system becomes idle. 4*a0652fc9SPaul Mackerras * 5*a0652fc9SPaul Mackerras * Originally written by Cort Dougan (cort@cs.nmt.edu). 6*a0652fc9SPaul Mackerras * Subsequent 32-bit hacking by Tom Rini, Armin Kuster, 7*a0652fc9SPaul Mackerras * Paul Mackerras and others. 8*a0652fc9SPaul Mackerras * 9*a0652fc9SPaul Mackerras * iSeries supported added by Mike Corrigan <mikejc@us.ibm.com> 10*a0652fc9SPaul Mackerras * 11*a0652fc9SPaul Mackerras * Additional shared processor, SMT, and firmware support 12*a0652fc9SPaul Mackerras * Copyright (c) 2003 Dave Engebretsen <engebret@us.ibm.com> 13*a0652fc9SPaul Mackerras * 14*a0652fc9SPaul Mackerras * 32-bit and 64-bit versions merged by Paul Mackerras <paulus@samba.org> 15*a0652fc9SPaul Mackerras * 16*a0652fc9SPaul Mackerras * This program is free software; you can redistribute it and/or 17*a0652fc9SPaul Mackerras * modify it under the terms of the GNU General Public License 18*a0652fc9SPaul Mackerras * as published by the Free Software Foundation; either version 19*a0652fc9SPaul Mackerras * 2 of the License, or (at your option) any later version. 20*a0652fc9SPaul Mackerras */ 21*a0652fc9SPaul Mackerras 22*a0652fc9SPaul Mackerras #include <linux/config.h> 23*a0652fc9SPaul Mackerras #include <linux/sched.h> 24*a0652fc9SPaul Mackerras #include <linux/kernel.h> 25*a0652fc9SPaul Mackerras #include <linux/smp.h> 26*a0652fc9SPaul Mackerras #include <linux/cpu.h> 27*a0652fc9SPaul Mackerras #include <linux/sysctl.h> 28*a0652fc9SPaul Mackerras 29*a0652fc9SPaul Mackerras #include <asm/system.h> 30*a0652fc9SPaul Mackerras #include <asm/processor.h> 31*a0652fc9SPaul Mackerras #include <asm/cputable.h> 32*a0652fc9SPaul Mackerras #include <asm/time.h> 33*a0652fc9SPaul Mackerras #include <asm/machdep.h> 34*a0652fc9SPaul Mackerras #include <asm/smp.h> 35*a0652fc9SPaul Mackerras 36*a0652fc9SPaul Mackerras #ifdef CONFIG_HOTPLUG_CPU 37*a0652fc9SPaul Mackerras #define cpu_should_die() (cpu_is_offline(smp_processor_id()) && \ 38*a0652fc9SPaul Mackerras system_state == SYSTEM_RUNNING) 39*a0652fc9SPaul Mackerras #else 40*a0652fc9SPaul Mackerras #define cpu_should_die() 0 41*a0652fc9SPaul Mackerras #endif 42*a0652fc9SPaul Mackerras 43*a0652fc9SPaul Mackerras /* 44*a0652fc9SPaul Mackerras * The body of the idle task. 45*a0652fc9SPaul Mackerras */ 46*a0652fc9SPaul Mackerras void cpu_idle(void) 47*a0652fc9SPaul Mackerras { 48*a0652fc9SPaul Mackerras if (ppc_md.idle_loop) 49*a0652fc9SPaul Mackerras ppc_md.idle_loop(); /* doesn't return */ 50*a0652fc9SPaul Mackerras 51*a0652fc9SPaul Mackerras set_thread_flag(TIF_POLLING_NRFLAG); 52*a0652fc9SPaul Mackerras while (1) { 53*a0652fc9SPaul Mackerras ppc64_runlatch_off(); 54*a0652fc9SPaul Mackerras 55*a0652fc9SPaul Mackerras while (!need_resched() && !cpu_should_die()) { 56*a0652fc9SPaul Mackerras if (ppc_md.power_save) { 57*a0652fc9SPaul Mackerras clear_thread_flag(TIF_POLLING_NRFLAG); 58*a0652fc9SPaul Mackerras /* 59*a0652fc9SPaul Mackerras * smp_mb is so clearing of TIF_POLLING_NRFLAG 60*a0652fc9SPaul Mackerras * is ordered w.r.t. need_resched() test. 61*a0652fc9SPaul Mackerras */ 62*a0652fc9SPaul Mackerras smp_mb(); 63*a0652fc9SPaul Mackerras local_irq_disable(); 64*a0652fc9SPaul Mackerras 65*a0652fc9SPaul Mackerras /* check again after disabling irqs */ 66*a0652fc9SPaul Mackerras if (!need_resched() && !cpu_should_die()) 67*a0652fc9SPaul Mackerras ppc_md.power_save(); 68*a0652fc9SPaul Mackerras 69*a0652fc9SPaul Mackerras local_irq_enable(); 70*a0652fc9SPaul Mackerras set_thread_flag(TIF_POLLING_NRFLAG); 71*a0652fc9SPaul Mackerras 72*a0652fc9SPaul Mackerras } else { 73*a0652fc9SPaul Mackerras /* 74*a0652fc9SPaul Mackerras * Go into low thread priority and possibly 75*a0652fc9SPaul Mackerras * low power mode. 76*a0652fc9SPaul Mackerras */ 77*a0652fc9SPaul Mackerras HMT_low(); 78*a0652fc9SPaul Mackerras HMT_very_low(); 79*a0652fc9SPaul Mackerras } 80*a0652fc9SPaul Mackerras } 81*a0652fc9SPaul Mackerras 82*a0652fc9SPaul Mackerras HMT_medium(); 83*a0652fc9SPaul Mackerras ppc64_runlatch_on(); 84*a0652fc9SPaul Mackerras if (cpu_should_die()) 85*a0652fc9SPaul Mackerras cpu_die(); 86*a0652fc9SPaul Mackerras preempt_enable_no_resched(); 87*a0652fc9SPaul Mackerras schedule(); 88*a0652fc9SPaul Mackerras preempt_disable(); 89*a0652fc9SPaul Mackerras } 90*a0652fc9SPaul Mackerras } 91*a0652fc9SPaul Mackerras 92*a0652fc9SPaul Mackerras int powersave_nap; 93*a0652fc9SPaul Mackerras 94*a0652fc9SPaul Mackerras #ifdef CONFIG_SYSCTL 95*a0652fc9SPaul Mackerras /* 96*a0652fc9SPaul Mackerras * Register the sysctl to set/clear powersave_nap. 97*a0652fc9SPaul Mackerras */ 98*a0652fc9SPaul Mackerras static ctl_table powersave_nap_ctl_table[]={ 99*a0652fc9SPaul Mackerras { 100*a0652fc9SPaul Mackerras .ctl_name = KERN_PPC_POWERSAVE_NAP, 101*a0652fc9SPaul Mackerras .procname = "powersave-nap", 102*a0652fc9SPaul Mackerras .data = &powersave_nap, 103*a0652fc9SPaul Mackerras .maxlen = sizeof(int), 104*a0652fc9SPaul Mackerras .mode = 0644, 105*a0652fc9SPaul Mackerras .proc_handler = &proc_dointvec, 106*a0652fc9SPaul Mackerras }, 107*a0652fc9SPaul Mackerras { 0, }, 108*a0652fc9SPaul Mackerras }; 109*a0652fc9SPaul Mackerras static ctl_table powersave_nap_sysctl_root[] = { 110*a0652fc9SPaul Mackerras { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, }, 111*a0652fc9SPaul Mackerras { 0,}, 112*a0652fc9SPaul Mackerras }; 113*a0652fc9SPaul Mackerras 114*a0652fc9SPaul Mackerras static int __init 115*a0652fc9SPaul Mackerras register_powersave_nap_sysctl(void) 116*a0652fc9SPaul Mackerras { 117*a0652fc9SPaul Mackerras register_sysctl_table(powersave_nap_sysctl_root, 0); 118*a0652fc9SPaul Mackerras 119*a0652fc9SPaul Mackerras return 0; 120*a0652fc9SPaul Mackerras } 121*a0652fc9SPaul Mackerras __initcall(register_powersave_nap_sysctl); 122*a0652fc9SPaul Mackerras #endif 123