1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <linux/sched.h>
23#include <linux/kernel.h>
24#include <linux/smp.h>
25#include <linux/cpu.h>
26#include <linux/sysctl.h>
27#include <linux/tick.h>
28
29#include <asm/system.h>
30#include <asm/processor.h>
31#include <asm/cputable.h>
32#include <asm/time.h>
33#include <asm/machdep.h>
34#include <asm/smp.h>
35
36#ifdef CONFIG_HOTPLUG_CPU
37#define cpu_should_die() cpu_is_offline(smp_processor_id())
38#else
39#define cpu_should_die() 0
40#endif
41
42static int __init powersave_off(char *arg)
43{
44 ppc_md.power_save = NULL;
45 return 0;
46}
47__setup("powersave=off", powersave_off);
48
49
50
51
52void cpu_idle(void)
53{
54 if (ppc_md.idle_loop)
55 ppc_md.idle_loop();
56
57 set_thread_flag(TIF_POLLING_NRFLAG);
58 while (1) {
59 tick_nohz_stop_sched_tick(1);
60 while (!need_resched() && !cpu_should_die()) {
61 ppc64_runlatch_off();
62
63 if (ppc_md.power_save) {
64 clear_thread_flag(TIF_POLLING_NRFLAG);
65
66
67
68
69 smp_mb();
70 local_irq_disable();
71
72
73 stop_critical_timings();
74
75
76 if (!need_resched() && !cpu_should_die())
77 ppc_md.power_save();
78
79 start_critical_timings();
80
81 local_irq_enable();
82 set_thread_flag(TIF_POLLING_NRFLAG);
83
84 } else {
85
86
87
88
89 HMT_low();
90 HMT_very_low();
91 }
92 }
93
94 HMT_medium();
95 ppc64_runlatch_on();
96 tick_nohz_restart_sched_tick();
97 if (cpu_should_die())
98 cpu_die();
99 preempt_enable_no_resched();
100 schedule();
101 preempt_disable();
102 }
103}
104
105int powersave_nap;
106
107#ifdef CONFIG_SYSCTL
108
109
110
111static ctl_table powersave_nap_ctl_table[]={
112 {
113 .ctl_name = KERN_PPC_POWERSAVE_NAP,
114 .procname = "powersave-nap",
115 .data = &powersave_nap,
116 .maxlen = sizeof(int),
117 .mode = 0644,
118 .proc_handler = &proc_dointvec,
119 },
120 {}
121};
122static ctl_table powersave_nap_sysctl_root[] = {
123 {
124 .ctl_name = CTL_KERN,
125 .procname = "kernel",
126 .mode = 0555,
127 .child = powersave_nap_ctl_table,
128 },
129 {}
130};
131
132static int __init
133register_powersave_nap_sysctl(void)
134{
135 register_sysctl_table(powersave_nap_sysctl_root);
136
137 return 0;
138}
139__initcall(register_powersave_nap_sysctl);
140#endif
141