2005-04-16 15:20:36 -07:00
/*
* Idle daemon for PowerPC . Idle daemon will handle any action
* that needs to be taken when the system becomes idle .
*
2006-03-27 15:03:03 +11:00
* Originally written by Cort Dougan ( cort @ cs . nmt . edu ) .
* Subsequent 32 - bit hacking by Tom Rini , Armin Kuster ,
* Paul Mackerras and others .
2005-04-16 15:20:36 -07:00
*
* iSeries supported added by Mike Corrigan < mikejc @ us . ibm . com >
*
* Additional shared processor , SMT , and firmware support
* Copyright ( c ) 2003 Dave Engebretsen < engebret @ us . ibm . com >
*
2006-03-27 15:03:03 +11:00
* 32 - bit and 64 - bit versions merged by Paul Mackerras < paulus @ samba . org >
*
2005-04-16 15:20:36 -07:00
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*/
# include <linux/config.h>
# include <linux/sched.h>
# include <linux/kernel.h>
# include <linux/smp.h>
# include <linux/cpu.h>
# include <linux/sysctl.h>
# include <asm/system.h>
# include <asm/processor.h>
# include <asm/cputable.h>
# include <asm/time.h>
2005-07-07 17:56:28 -07:00
# include <asm/machdep.h>
2005-11-07 13:18:13 +11:00
# include <asm/smp.h>
2005-04-16 15:20:36 -07:00
2006-03-27 15:03:03 +11:00
# ifdef CONFIG_HOTPLUG_CPU
# define cpu_should_die() (cpu_is_offline(smp_processor_id()) && \
system_state = = SYSTEM_RUNNING )
# else
# define cpu_should_die() 0
# endif
2005-04-16 15:20:36 -07:00
2006-03-27 15:03:03 +11:00
/*
* The body of the idle task .
*/
void cpu_idle ( void )
2005-04-16 15:20:36 -07:00
{
2006-03-27 15:03:03 +11:00
if ( ppc_md . idle_loop )
ppc_md . idle_loop ( ) ; /* doesn't return */
2005-04-16 15:20:36 -07:00
2006-03-27 15:03:03 +11:00
set_thread_flag ( TIF_POLLING_NRFLAG ) ;
2005-04-16 15:20:36 -07:00
while ( 1 ) {
2006-03-27 15:03:03 +11:00
ppc64_runlatch_off ( ) ;
2005-07-07 17:56:33 -07:00
2006-03-27 15:03:03 +11:00
while ( ! need_resched ( ) & & ! cpu_should_die ( ) ) {
if ( ppc_md . power_save ) {
clear_thread_flag ( TIF_POLLING_NRFLAG ) ;
/*
* smp_mb is so clearing of TIF_POLLING_NRFLAG
* is ordered w . r . t . need_resched ( ) test .
*/
smp_mb ( ) ;
local_irq_disable ( ) ;
/* check again after disabling irqs */
if ( ! need_resched ( ) & & ! cpu_should_die ( ) )
ppc_md . power_save ( ) ;
local_irq_enable ( ) ;
set_thread_flag ( TIF_POLLING_NRFLAG ) ;
} else {
2005-04-16 15:20:36 -07:00
/*
* Go into low thread priority and possibly
* low power mode .
*/
HMT_low ( ) ;
HMT_very_low ( ) ;
}
}
2006-03-27 15:03:03 +11:00
HMT_medium ( ) ;
2005-07-07 17:56:33 -07:00
ppc64_runlatch_on ( ) ;
2006-03-27 15:03:03 +11:00
if ( cpu_should_die ( ) )
cpu_die ( ) ;
2005-11-08 21:39:01 -08:00
preempt_enable_no_resched ( ) ;
2005-04-16 15:20:36 -07:00
schedule ( ) ;
2005-11-08 21:39:01 -08:00
preempt_disable ( ) ;
2005-04-16 15:20:36 -07:00
}
}
int powersave_nap ;
# ifdef CONFIG_SYSCTL
/*
* Register the sysctl to set / clear powersave_nap .
*/
static ctl_table powersave_nap_ctl_table [ ] = {
{
. ctl_name = KERN_PPC_POWERSAVE_NAP ,
. procname = " powersave-nap " ,
. data = & powersave_nap ,
. maxlen = sizeof ( int ) ,
. mode = 0644 ,
. proc_handler = & proc_dointvec ,
} ,
{ 0 , } ,
} ;
static ctl_table powersave_nap_sysctl_root [ ] = {
{ 1 , " kernel " , NULL , 0 , 0755 , powersave_nap_ctl_table , } ,
{ 0 , } ,
} ;
static int __init
register_powersave_nap_sysctl ( void )
{
register_sysctl_table ( powersave_nap_sysctl_root , 0 ) ;
return 0 ;
}
__initcall ( register_powersave_nap_sysctl ) ;
# endif