1 /*
2 * cpuidle.h - a generic framework for CPU idle power management
3 *
4 * (C) 2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
5 * Shaohua Li <shaohua.li@intel.com>
6 * Adam Belay <abelay@novell.com>
7 *
8 * This code is licenced under the GPL.
9 */
10
11 #ifndef _LINUX_CPUIDLE_H
12 #define _LINUX_CPUIDLE_H
13
14 #include <linux/percpu.h>
15 #include <linux/list.h>
16 #include <linux/hrtimer.h>
17
18 #define CPUIDLE_STATE_MAX 10
19 #define CPUIDLE_NAME_LEN 16
20 #define CPUIDLE_DESC_LEN 32
21
22 struct module;
23
24 struct cpuidle_device;
25 struct cpuidle_driver;
26
27
28 /****************************
29 * CPUIDLE DEVICE INTERFACE *
30 ****************************/
31
32 struct cpuidle_state_usage {
33 unsigned long long disable;
34 unsigned long long usage;
35 unsigned long long time; /* in US */
36 unsigned long long above; /* Number of times it's been too deep */
37 unsigned long long below; /* Number of times it's been too shallow */
38 #ifdef CONFIG_SUSPEND
39 unsigned long long s2idle_usage;
40 unsigned long long s2idle_time; /* in US */
41 #endif
42 };
43
44 struct cpuidle_state {
45 char name[CPUIDLE_NAME_LEN];
46 char desc[CPUIDLE_DESC_LEN];
47
48 unsigned int flags;
49 unsigned int exit_latency; /* in US */
50 int power_usage; /* in mW */
51 unsigned int target_residency; /* in US */
52 bool disabled; /* disabled on all CPUs */
53
54 int (*enter) (struct cpuidle_device *dev,
55 struct cpuidle_driver *drv,
56 int index);
57
58 int (*enter_dead) (struct cpuidle_device *dev, int index);
59
60 /*
61 * CPUs execute ->enter_s2idle with the local tick or entire timekeeping
62 * suspended, so it must not re-enable interrupts at any point (even
63 * temporarily) or attempt to change states of clock event devices.
64 *
65 * This callback may point to the same function as ->enter if all of
66 * the above requirements are met by it.
67 */
68 int (*enter_s2idle)(struct cpuidle_device *dev,
69 struct cpuidle_driver *drv,
70 int index);
71 };
72
73 /* Idle State Flags */
74 #define CPUIDLE_FLAG_NONE (0x00)
75 #define CPUIDLE_FLAG_POLLING BIT(0) /* polling state */
76 #define CPUIDLE_FLAG_COUPLED BIT(1) /* state applies to multiple cpus */
77 #define CPUIDLE_FLAG_TIMER_STOP BIT(2) /* timer is stopped on this state */
78
79 struct cpuidle_device_kobj;
80 struct cpuidle_state_kobj;
81 struct cpuidle_driver_kobj;
82
83 struct cpuidle_device {
84 unsigned int registered:1;
85 unsigned int enabled:1;
86 unsigned int use_deepest_state:1;
87 unsigned int poll_time_limit:1;
88 unsigned int cpu;
89 ktime_t next_hrtimer;
90
91 int last_state_idx;
92 int last_residency;
93 u64 poll_limit_ns;
94 struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX];
95 struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
96 struct cpuidle_driver_kobj *kobj_driver;
97 struct cpuidle_device_kobj *kobj_dev;
98 struct list_head device_list;
99
100 #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
101 cpumask_t coupled_cpus;
102 struct cpuidle_coupled *coupled;
103 #endif
104 };
105
106 DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
107 DECLARE_PER_CPU(struct cpuidle_device, cpuidle_dev);
108
109 /****************************
110 * CPUIDLE DRIVER INTERFACE *
111 ****************************/
112
113 struct cpuidle_driver {
114 const char *name;
115 struct module *owner;
116 int refcnt;
117
118 /* used by the cpuidle framework to setup the broadcast timer */
119 unsigned int bctimer:1;
120 /* states array must be ordered in decreasing power consumption */
121 struct cpuidle_state states[CPUIDLE_STATE_MAX];
122 int state_count;
123 int safe_state_index;
124
125 /* the driver handles the cpus in cpumask */
126 struct cpumask *cpumask;
127
128 /* preferred governor to switch at register time */
129 const char *governor;
130 };
131
132 #ifdef CONFIG_CPU_IDLE
133 extern void disable_cpuidle(void);
134 extern bool cpuidle_not_available(struct cpuidle_driver *drv,
135 struct cpuidle_device *dev);
136
137 extern int cpuidle_select(struct cpuidle_driver *drv,
138 struct cpuidle_device *dev,
139 bool *stop_tick);
140 extern int cpuidle_enter(struct cpuidle_driver *drv,
141 struct cpuidle_device *dev, int index);
142 extern void cpuidle_reflect(struct cpuidle_device *dev, int index);
143 extern u64 cpuidle_poll_time(struct cpuidle_driver *drv,
144 struct cpuidle_device *dev);
145
146 extern int cpuidle_register_driver(struct cpuidle_driver *drv);
147 extern struct cpuidle_driver *cpuidle_get_driver(void);
148 extern struct cpuidle_driver *cpuidle_driver_ref(void);
149 extern void cpuidle_driver_unref(void);
150 extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
151 extern int cpuidle_register_device(struct cpuidle_device *dev);
152 extern void cpuidle_unregister_device(struct cpuidle_device *dev);
153 extern int cpuidle_register(struct cpuidle_driver *drv,
154 const struct cpumask *const coupled_cpus);
155 extern void cpuidle_unregister(struct cpuidle_driver *drv);
156 extern void cpuidle_pause_and_lock(void);
157 extern void cpuidle_resume_and_unlock(void);
158 extern void cpuidle_pause(void);
159 extern void cpuidle_resume(void);
160 extern int cpuidle_enable_device(struct cpuidle_device *dev);
161 extern void cpuidle_disable_device(struct cpuidle_device *dev);
162 extern int cpuidle_play_dead(void);
163
164 extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev);
cpuidle_get_device(void)165 static inline struct cpuidle_device *cpuidle_get_device(void)
166 {return __this_cpu_read(cpuidle_devices); }
167 #else
disable_cpuidle(void)168 static inline void disable_cpuidle(void) { }
cpuidle_not_available(struct cpuidle_driver * drv,struct cpuidle_device * dev)169 static inline bool cpuidle_not_available(struct cpuidle_driver *drv,
170 struct cpuidle_device *dev)
171 {return true; }
cpuidle_select(struct cpuidle_driver * drv,struct cpuidle_device * dev,bool * stop_tick)172 static inline int cpuidle_select(struct cpuidle_driver *drv,
173 struct cpuidle_device *dev, bool *stop_tick)
174 {return -ENODEV; }
cpuidle_enter(struct cpuidle_driver * drv,struct cpuidle_device * dev,int index)175 static inline int cpuidle_enter(struct cpuidle_driver *drv,
176 struct cpuidle_device *dev, int index)
177 {return -ENODEV; }
cpuidle_reflect(struct cpuidle_device * dev,int index)178 static inline void cpuidle_reflect(struct cpuidle_device *dev, int index) { }
cpuidle_poll_time(struct cpuidle_driver * drv,struct cpuidle_device * dev)179 static inline u64 cpuidle_poll_time(struct cpuidle_driver *drv,
180 struct cpuidle_device *dev)
181 {return 0; }
cpuidle_register_driver(struct cpuidle_driver * drv)182 static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
183 {return -ENODEV; }
cpuidle_get_driver(void)184 static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
cpuidle_driver_ref(void)185 static inline struct cpuidle_driver *cpuidle_driver_ref(void) {return NULL; }
cpuidle_driver_unref(void)186 static inline void cpuidle_driver_unref(void) {}
cpuidle_unregister_driver(struct cpuidle_driver * drv)187 static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { }
cpuidle_register_device(struct cpuidle_device * dev)188 static inline int cpuidle_register_device(struct cpuidle_device *dev)
189 {return -ENODEV; }
cpuidle_unregister_device(struct cpuidle_device * dev)190 static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { }
cpuidle_register(struct cpuidle_driver * drv,const struct cpumask * const coupled_cpus)191 static inline int cpuidle_register(struct cpuidle_driver *drv,
192 const struct cpumask *const coupled_cpus)
193 {return -ENODEV; }
cpuidle_unregister(struct cpuidle_driver * drv)194 static inline void cpuidle_unregister(struct cpuidle_driver *drv) { }
cpuidle_pause_and_lock(void)195 static inline void cpuidle_pause_and_lock(void) { }
cpuidle_resume_and_unlock(void)196 static inline void cpuidle_resume_and_unlock(void) { }
cpuidle_pause(void)197 static inline void cpuidle_pause(void) { }
cpuidle_resume(void)198 static inline void cpuidle_resume(void) { }
cpuidle_enable_device(struct cpuidle_device * dev)199 static inline int cpuidle_enable_device(struct cpuidle_device *dev)
200 {return -ENODEV; }
cpuidle_disable_device(struct cpuidle_device * dev)201 static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
cpuidle_play_dead(void)202 static inline int cpuidle_play_dead(void) {return -ENODEV; }
cpuidle_get_cpu_driver(struct cpuidle_device * dev)203 static inline struct cpuidle_driver *cpuidle_get_cpu_driver(
204 struct cpuidle_device *dev) {return NULL; }
cpuidle_get_device(void)205 static inline struct cpuidle_device *cpuidle_get_device(void) {return NULL; }
206 #endif
207
208 #ifdef CONFIG_CPU_IDLE
209 extern int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
210 struct cpuidle_device *dev);
211 extern int cpuidle_enter_s2idle(struct cpuidle_driver *drv,
212 struct cpuidle_device *dev);
213 extern void cpuidle_use_deepest_state(bool enable);
214 #else
cpuidle_find_deepest_state(struct cpuidle_driver * drv,struct cpuidle_device * dev)215 static inline int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
216 struct cpuidle_device *dev)
217 {return -ENODEV; }
cpuidle_enter_s2idle(struct cpuidle_driver * drv,struct cpuidle_device * dev)218 static inline int cpuidle_enter_s2idle(struct cpuidle_driver *drv,
219 struct cpuidle_device *dev)
220 {return -ENODEV; }
cpuidle_use_deepest_state(bool enable)221 static inline void cpuidle_use_deepest_state(bool enable)
222 {
223 }
224 #endif
225
226 /* kernel/sched/idle.c */
227 extern void sched_idle_set_state(struct cpuidle_state *idle_state);
228 extern void default_idle_call(void);
229
230 #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
231 void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, atomic_t *a);
232 #else
cpuidle_coupled_parallel_barrier(struct cpuidle_device * dev,atomic_t * a)233 static inline void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, atomic_t *a)
234 {
235 }
236 #endif
237
238 #if defined(CONFIG_CPU_IDLE) && defined(CONFIG_ARCH_HAS_CPU_RELAX)
239 void cpuidle_poll_state_init(struct cpuidle_driver *drv);
240 #else
cpuidle_poll_state_init(struct cpuidle_driver * drv)241 static inline void cpuidle_poll_state_init(struct cpuidle_driver *drv) {}
242 #endif
243
244 /******************************
245 * CPUIDLE GOVERNOR INTERFACE *
246 ******************************/
247
248 struct cpuidle_governor {
249 char name[CPUIDLE_NAME_LEN];
250 struct list_head governor_list;
251 unsigned int rating;
252
253 int (*enable) (struct cpuidle_driver *drv,
254 struct cpuidle_device *dev);
255 void (*disable) (struct cpuidle_driver *drv,
256 struct cpuidle_device *dev);
257
258 int (*select) (struct cpuidle_driver *drv,
259 struct cpuidle_device *dev,
260 bool *stop_tick);
261 void (*reflect) (struct cpuidle_device *dev, int index);
262 };
263
264 #ifdef CONFIG_CPU_IDLE
265 extern int cpuidle_register_governor(struct cpuidle_governor *gov);
266 extern int cpuidle_governor_latency_req(unsigned int cpu);
267 #else
cpuidle_register_governor(struct cpuidle_governor * gov)268 static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
269 {return 0;}
270 #endif
271
272 #define __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, \
273 idx, \
274 state, \
275 is_retention) \
276 ({ \
277 int __ret = 0; \
278 \
279 if (!idx) { \
280 cpu_do_idle(); \
281 return idx; \
282 } \
283 \
284 if (!is_retention) \
285 __ret = cpu_pm_enter(); \
286 if (!__ret) { \
287 __ret = low_level_idle_enter(state); \
288 if (!is_retention) \
289 cpu_pm_exit(); \
290 } \
291 \
292 __ret ? -1 : idx; \
293 })
294
295 #define CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx) \
296 __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, idx, 0)
297
298 #define CPU_PM_CPU_IDLE_ENTER_RETENTION(low_level_idle_enter, idx) \
299 __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, idx, 1)
300
301 #define CPU_PM_CPU_IDLE_ENTER_PARAM(low_level_idle_enter, idx, state) \
302 __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, state, 0)
303
304 #define CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(low_level_idle_enter, idx, state) \
305 __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, state, 1)
306
307 #endif /* _LINUX_CPUIDLE_H */
308