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