at v3.6 7.0 kB view raw
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/kobject.h> 17#include <linux/completion.h> 18#include <linux/hrtimer.h> 19 20#define CPUIDLE_STATE_MAX 8 21#define CPUIDLE_NAME_LEN 16 22#define CPUIDLE_DESC_LEN 32 23 24struct module; 25 26struct cpuidle_device; 27struct cpuidle_driver; 28 29 30/**************************** 31 * CPUIDLE DEVICE INTERFACE * 32 ****************************/ 33 34struct cpuidle_state_usage { 35 void *driver_data; 36 37 unsigned long long disable; 38 unsigned long long usage; 39 unsigned long long time; /* in US */ 40}; 41 42struct cpuidle_state { 43 char name[CPUIDLE_NAME_LEN]; 44 char desc[CPUIDLE_DESC_LEN]; 45 46 unsigned int flags; 47 unsigned int exit_latency; /* in US */ 48 int power_usage; /* in mW */ 49 unsigned int target_residency; /* in US */ 50 bool disabled; /* disabled on all CPUs */ 51 52 int (*enter) (struct cpuidle_device *dev, 53 struct cpuidle_driver *drv, 54 int index); 55 56 int (*enter_dead) (struct cpuidle_device *dev, int index); 57}; 58 59/* Idle State Flags */ 60#define CPUIDLE_FLAG_TIME_VALID (0x01) /* is residency time measurable? */ 61#define CPUIDLE_FLAG_COUPLED (0x02) /* state applies to multiple cpus */ 62 63#define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) 64 65/** 66 * cpuidle_get_statedata - retrieves private driver state data 67 * @st_usage: the state usage statistics 68 */ 69static inline void *cpuidle_get_statedata(struct cpuidle_state_usage *st_usage) 70{ 71 return st_usage->driver_data; 72} 73 74/** 75 * cpuidle_set_statedata - stores private driver state data 76 * @st_usage: the state usage statistics 77 * @data: the private data 78 */ 79static inline void 80cpuidle_set_statedata(struct cpuidle_state_usage *st_usage, void *data) 81{ 82 st_usage->driver_data = data; 83} 84 85struct cpuidle_state_kobj { 86 struct cpuidle_state *state; 87 struct cpuidle_state_usage *state_usage; 88 struct completion kobj_unregister; 89 struct kobject kobj; 90}; 91 92struct cpuidle_device { 93 unsigned int registered:1; 94 unsigned int enabled:1; 95 unsigned int cpu; 96 97 int last_residency; 98 int state_count; 99 struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; 100 struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX]; 101 102 struct list_head device_list; 103 struct kobject kobj; 104 struct completion kobj_unregister; 105 106#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED 107 int safe_state_index; 108 cpumask_t coupled_cpus; 109 struct cpuidle_coupled *coupled; 110#endif 111}; 112 113DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); 114 115/** 116 * cpuidle_get_last_residency - retrieves the last state's residency time 117 * @dev: the target CPU 118 * 119 * NOTE: this value is invalid if CPUIDLE_FLAG_TIME_VALID isn't set 120 */ 121static inline int cpuidle_get_last_residency(struct cpuidle_device *dev) 122{ 123 return dev->last_residency; 124} 125 126 127/**************************** 128 * CPUIDLE DRIVER INTERFACE * 129 ****************************/ 130 131struct cpuidle_driver { 132 const char *name; 133 struct module *owner; 134 135 unsigned int power_specified:1; 136 /* set to 1 to use the core cpuidle time keeping (for all states). */ 137 unsigned int en_core_tk_irqen:1; 138 struct cpuidle_state states[CPUIDLE_STATE_MAX]; 139 int state_count; 140 int safe_state_index; 141}; 142 143#ifdef CONFIG_CPU_IDLE 144extern void disable_cpuidle(void); 145extern int cpuidle_idle_call(void); 146extern int cpuidle_register_driver(struct cpuidle_driver *drv); 147extern struct cpuidle_driver *cpuidle_get_driver(void); 148extern struct cpuidle_driver *cpuidle_driver_ref(void); 149extern void cpuidle_driver_unref(void); 150extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); 151extern int cpuidle_register_device(struct cpuidle_device *dev); 152extern void cpuidle_unregister_device(struct cpuidle_device *dev); 153 154extern void cpuidle_pause_and_lock(void); 155extern void cpuidle_resume_and_unlock(void); 156extern void cpuidle_pause(void); 157extern void cpuidle_resume(void); 158extern int cpuidle_enable_device(struct cpuidle_device *dev); 159extern void cpuidle_disable_device(struct cpuidle_device *dev); 160extern int cpuidle_wrap_enter(struct cpuidle_device *dev, 161 struct cpuidle_driver *drv, int index, 162 int (*enter)(struct cpuidle_device *dev, 163 struct cpuidle_driver *drv, int index)); 164extern int cpuidle_play_dead(void); 165 166#else 167static inline void disable_cpuidle(void) { } 168static inline int cpuidle_idle_call(void) { return -ENODEV; } 169static inline int cpuidle_register_driver(struct cpuidle_driver *drv) 170{return -ENODEV; } 171static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; } 172static inline struct cpuidle_driver *cpuidle_driver_ref(void) {return NULL; } 173static inline void cpuidle_driver_unref(void) {} 174static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { } 175static inline int cpuidle_register_device(struct cpuidle_device *dev) 176{return -ENODEV; } 177static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { } 178 179static inline void cpuidle_pause_and_lock(void) { } 180static inline void cpuidle_resume_and_unlock(void) { } 181static inline void cpuidle_pause(void) { } 182static inline void cpuidle_resume(void) { } 183static inline int cpuidle_enable_device(struct cpuidle_device *dev) 184{return -ENODEV; } 185static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } 186static inline int cpuidle_wrap_enter(struct cpuidle_device *dev, 187 struct cpuidle_driver *drv, int index, 188 int (*enter)(struct cpuidle_device *dev, 189 struct cpuidle_driver *drv, int index)) 190{ return -ENODEV; } 191static inline int cpuidle_play_dead(void) {return -ENODEV; } 192 193#endif 194 195#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED 196void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, atomic_t *a); 197#else 198static inline void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, atomic_t *a) 199{ 200} 201#endif 202 203/****************************** 204 * CPUIDLE GOVERNOR INTERFACE * 205 ******************************/ 206 207struct cpuidle_governor { 208 char name[CPUIDLE_NAME_LEN]; 209 struct list_head governor_list; 210 unsigned int rating; 211 212 int (*enable) (struct cpuidle_driver *drv, 213 struct cpuidle_device *dev); 214 void (*disable) (struct cpuidle_driver *drv, 215 struct cpuidle_device *dev); 216 217 int (*select) (struct cpuidle_driver *drv, 218 struct cpuidle_device *dev); 219 void (*reflect) (struct cpuidle_device *dev, int index); 220 221 struct module *owner; 222}; 223 224#ifdef CONFIG_CPU_IDLE 225 226extern int cpuidle_register_governor(struct cpuidle_governor *gov); 227extern void cpuidle_unregister_governor(struct cpuidle_governor *gov); 228 229#else 230 231static inline int cpuidle_register_governor(struct cpuidle_governor *gov) 232{return 0;} 233static inline void cpuidle_unregister_governor(struct cpuidle_governor *gov) { } 234 235#endif 236 237#ifdef CONFIG_ARCH_HAS_CPU_RELAX 238#define CPUIDLE_DRIVER_STATE_START 1 239#else 240#define CPUIDLE_DRIVER_STATE_START 0 241#endif 242 243#endif /* _LINUX_CPUIDLE_H */