idle_64.c 2.48 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*
 * Idle daemon for PowerPC.  Idle daemon will handle any action
 * that needs to be taken when the system becomes idle.
 *
 * Originally Written by Cort Dougan (cort@cs.nmt.edu)
 *
 * 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>
 *
 * 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>
29
#include <asm/machdep.h>
30
#include <asm/smp.h>
Linus Torvalds's avatar
Linus Torvalds committed
31 32 33

extern void power4_idle(void);

Paul Mackerras's avatar
Paul Mackerras committed
34
void default_idle(void)
Linus Torvalds's avatar
Linus Torvalds committed
35 36
{
	unsigned int cpu = smp_processor_id();
37
	set_thread_flag(TIF_POLLING_NRFLAG);
Linus Torvalds's avatar
Linus Torvalds committed
38 39

	while (1) {
40
		if (!need_resched()) {
Linus Torvalds's avatar
Linus Torvalds committed
41
			while (!need_resched() && !cpu_is_offline(cpu)) {
Anton Blanchard's avatar
Anton Blanchard committed
42 43
				ppc64_runlatch_off();

Linus Torvalds's avatar
Linus Torvalds committed
44 45 46 47 48 49 50 51 52 53 54
				/*
				 * Go into low thread priority and possibly
				 * low power mode.
				 */
				HMT_low();
				HMT_very_low();
			}

			HMT_medium();
		}

Anton Blanchard's avatar
Anton Blanchard committed
55
		ppc64_runlatch_on();
56
		preempt_enable_no_resched();
Linus Torvalds's avatar
Linus Torvalds committed
57
		schedule();
58
		preempt_disable();
Linus Torvalds's avatar
Linus Torvalds committed
59 60 61 62 63
		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
			cpu_die();
	}
}

Paul Mackerras's avatar
Paul Mackerras committed
64
void native_idle(void)
Linus Torvalds's avatar
Linus Torvalds committed
65
{
Anton Blanchard's avatar
Anton Blanchard committed
66 67 68
	while (1) {
		ppc64_runlatch_off();

Linus Torvalds's avatar
Linus Torvalds committed
69 70
		if (!need_resched())
			power4_idle();
Anton Blanchard's avatar
Anton Blanchard committed
71 72 73

		if (need_resched()) {
			ppc64_runlatch_on();
74
			preempt_enable_no_resched();
Linus Torvalds's avatar
Linus Torvalds committed
75
			schedule();
76
			preempt_disable();
Anton Blanchard's avatar
Anton Blanchard committed
77
		}
Linus Torvalds's avatar
Linus Torvalds committed
78

Anton Blanchard's avatar
Anton Blanchard committed
79
		if (cpu_is_offline(smp_processor_id()) &&
Linus Torvalds's avatar
Linus Torvalds committed
80 81 82 83 84 85 86
		    system_state == SYSTEM_RUNNING)
			cpu_die();
	}
}

void cpu_idle(void)
{
87 88
	BUG_ON(NULL == ppc_md.idle_loop);
	ppc_md.idle_loop();
Linus Torvalds's avatar
Linus Torvalds committed
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
}

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