at v3.8 7.1 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_device { 86 unsigned int registered:1; 87 unsigned int enabled:1; 88 unsigned int cpu; 89 90 int last_residency; 91 int state_count; 92 struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; 93 struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX]; 94 struct cpuidle_driver_kobj *kobj_driver; 95 struct list_head device_list; 96 struct kobject kobj; 97 struct completion kobj_unregister; 98 99#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED 100 int safe_state_index; 101 cpumask_t coupled_cpus; 102 struct cpuidle_coupled *coupled; 103#endif 104}; 105 106DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); 107 108/** 109 * cpuidle_get_last_residency - retrieves the last state's residency time 110 * @dev: the target CPU 111 * 112 * NOTE: this value is invalid if CPUIDLE_FLAG_TIME_VALID isn't set 113 */ 114static inline int cpuidle_get_last_residency(struct cpuidle_device *dev) 115{ 116 return dev->last_residency; 117} 118 119 120/**************************** 121 * CPUIDLE DRIVER INTERFACE * 122 ****************************/ 123 124struct cpuidle_driver { 125 const char *name; 126 struct module *owner; 127 int refcnt; 128 129 /* set to 1 to use the core cpuidle time keeping (for all states). */ 130 unsigned int en_core_tk_irqen:1; 131 /* states array must be ordered in decreasing power consumption */ 132 struct cpuidle_state states[CPUIDLE_STATE_MAX]; 133 int state_count; 134 int safe_state_index; 135}; 136 137#ifdef CONFIG_CPU_IDLE 138extern void disable_cpuidle(void); 139extern int cpuidle_idle_call(void); 140extern int cpuidle_register_driver(struct cpuidle_driver *drv); 141extern struct cpuidle_driver *cpuidle_get_driver(void); 142extern struct cpuidle_driver *cpuidle_driver_ref(void); 143extern void cpuidle_driver_unref(void); 144extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); 145extern int cpuidle_register_device(struct cpuidle_device *dev); 146extern void cpuidle_unregister_device(struct cpuidle_device *dev); 147 148extern void cpuidle_pause_and_lock(void); 149extern void cpuidle_resume_and_unlock(void); 150extern void cpuidle_pause(void); 151extern void cpuidle_resume(void); 152extern int cpuidle_enable_device(struct cpuidle_device *dev); 153extern void cpuidle_disable_device(struct cpuidle_device *dev); 154extern int cpuidle_wrap_enter(struct cpuidle_device *dev, 155 struct cpuidle_driver *drv, int index, 156 int (*enter)(struct cpuidle_device *dev, 157 struct cpuidle_driver *drv, int index)); 158extern int cpuidle_play_dead(void); 159 160extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev); 161extern int cpuidle_register_cpu_driver(struct cpuidle_driver *drv, int cpu); 162extern void cpuidle_unregister_cpu_driver(struct cpuidle_driver *drv, int cpu); 163 164#else 165static inline void disable_cpuidle(void) { } 166static inline int cpuidle_idle_call(void) { return -ENODEV; } 167static inline int cpuidle_register_driver(struct cpuidle_driver *drv) 168{return -ENODEV; } 169static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; } 170static inline struct cpuidle_driver *cpuidle_driver_ref(void) {return NULL; } 171static inline void cpuidle_driver_unref(void) {} 172static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { } 173static inline int cpuidle_register_device(struct cpuidle_device *dev) 174{return -ENODEV; } 175static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { } 176 177static inline void cpuidle_pause_and_lock(void) { } 178static inline void cpuidle_resume_and_unlock(void) { } 179static inline void cpuidle_pause(void) { } 180static inline void cpuidle_resume(void) { } 181static inline int cpuidle_enable_device(struct cpuidle_device *dev) 182{return -ENODEV; } 183static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } 184static inline int cpuidle_wrap_enter(struct cpuidle_device *dev, 185 struct cpuidle_driver *drv, int index, 186 int (*enter)(struct cpuidle_device *dev, 187 struct cpuidle_driver *drv, int index)) 188{ return -ENODEV; } 189static inline int cpuidle_play_dead(void) {return -ENODEV; } 190#endif 191 192#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED 193void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, atomic_t *a); 194#else 195static inline void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, atomic_t *a) 196{ 197} 198#endif 199 200/****************************** 201 * CPUIDLE GOVERNOR INTERFACE * 202 ******************************/ 203 204struct cpuidle_governor { 205 char name[CPUIDLE_NAME_LEN]; 206 struct list_head governor_list; 207 unsigned int rating; 208 209 int (*enable) (struct cpuidle_driver *drv, 210 struct cpuidle_device *dev); 211 void (*disable) (struct cpuidle_driver *drv, 212 struct cpuidle_device *dev); 213 214 int (*select) (struct cpuidle_driver *drv, 215 struct cpuidle_device *dev); 216 void (*reflect) (struct cpuidle_device *dev, int index); 217 218 struct module *owner; 219}; 220 221#ifdef CONFIG_CPU_IDLE 222 223extern int cpuidle_register_governor(struct cpuidle_governor *gov); 224extern void cpuidle_unregister_governor(struct cpuidle_governor *gov); 225 226#else 227 228static inline int cpuidle_register_governor(struct cpuidle_governor *gov) 229{return 0;} 230static inline void cpuidle_unregister_governor(struct cpuidle_governor *gov) { } 231 232#endif 233 234#ifdef CONFIG_ARCH_HAS_CPU_RELAX 235#define CPUIDLE_DRIVER_STATE_START 1 236#else 237#define CPUIDLE_DRIVER_STATE_START 0 238#endif 239 240#endif /* _LINUX_CPUIDLE_H */