Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/kernel/idle.c
10817 views
1
/*
2
* Idle daemon for PowerPC. Idle daemon will handle any action
3
* that needs to be taken when the system becomes idle.
4
*
5
* Originally written by Cort Dougan ([email protected]).
6
* Subsequent 32-bit hacking by Tom Rini, Armin Kuster,
7
* Paul Mackerras and others.
8
*
9
* iSeries supported added by Mike Corrigan <[email protected]>
10
*
11
* Additional shared processor, SMT, and firmware support
12
* Copyright (c) 2003 Dave Engebretsen <[email protected]>
13
*
14
* 32-bit and 64-bit versions merged by Paul Mackerras <[email protected]>
15
*
16
* This program is free software; you can redistribute it and/or
17
* modify it under the terms of the GNU General Public License
18
* as published by the Free Software Foundation; either version
19
* 2 of the License, or (at your option) any later version.
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
42
static 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
* The body of the idle task.
51
*/
52
void cpu_idle(void)
53
{
54
if (ppc_md.idle_loop)
55
ppc_md.idle_loop(); /* doesn't return */
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
* smp_mb is so clearing of TIF_POLLING_NRFLAG
67
* is ordered w.r.t. need_resched() test.
68
*/
69
smp_mb();
70
local_irq_disable();
71
72
/* Don't trace irqs off for idle */
73
stop_critical_timings();
74
75
/* check again after disabling irqs */
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
* Go into low thread priority and possibly
87
* low power mode.
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
preempt_enable_no_resched();
98
if (cpu_should_die())
99
cpu_die();
100
schedule();
101
preempt_disable();
102
}
103
}
104
105
int powersave_nap;
106
107
#ifdef CONFIG_SYSCTL
108
/*
109
* Register the sysctl to set/clear powersave_nap.
110
*/
111
static ctl_table powersave_nap_ctl_table[]={
112
{
113
.procname = "powersave-nap",
114
.data = &powersave_nap,
115
.maxlen = sizeof(int),
116
.mode = 0644,
117
.proc_handler = proc_dointvec,
118
},
119
{}
120
};
121
static ctl_table powersave_nap_sysctl_root[] = {
122
{
123
.procname = "kernel",
124
.mode = 0555,
125
.child = powersave_nap_ctl_table,
126
},
127
{}
128
};
129
130
static int __init
131
register_powersave_nap_sysctl(void)
132
{
133
register_sysctl_table(powersave_nap_sysctl_root);
134
135
return 0;
136
}
137
__initcall(register_powersave_nap_sysctl);
138
#endif
139
140