diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/acpi/processor.h | 5 | ||||
-rw-r--r-- | include/linux/acpi.h | 26 | ||||
-rw-r--r-- | include/linux/cpuidle.h | 180 | ||||
-rw-r--r-- | include/linux/tick.h | 9 |
4 files changed, 194 insertions, 26 deletions
diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 99934a9..26d79f6 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -3,6 +3,7 @@ #include <linux/kernel.h> #include <linux/cpu.h> +#include <linux/cpuidle.h> #include <asm/acpi.h> @@ -75,7 +76,9 @@ struct acpi_processor_cx { }; struct acpi_processor_power { + struct cpuidle_device dev; struct acpi_processor_cx *state; + struct acpi_processor_cx *bm_state; unsigned long bm_check_timestamp; u32 default_state; u32 bm_activity; @@ -199,6 +202,7 @@ struct acpi_processor_flags { u8 bm_check:1; u8 has_cst:1; u8 power_setup_done:1; + u8 bm_rld_set:1; }; struct acpi_processor { @@ -322,6 +326,7 @@ int acpi_processor_power_exit(struct acpi_processor *pr, struct acpi_device *device); int acpi_processor_suspend(struct acpi_device * device, pm_message_t state); int acpi_processor_resume(struct acpi_device * device); +extern struct cpuidle_driver acpi_idle_driver; /* in processor_thermal.c */ int acpi_processor_get_limit_info(struct acpi_processor *pr); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index bf5e000..8ccedf7 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -189,32 +189,6 @@ extern int ec_transaction(u8 command, extern int acpi_blacklisted(void); extern void acpi_bios_year(char *s); -#define ACPI_CSTATE_LIMIT_DEFINED /* for driver builds */ -#ifdef CONFIG_ACPI - -/* - * Set highest legal C-state - * 0: C0 okay, but not C1 - * 1: C1 okay, but not C2 - * 2: C2 okay, but not C3 etc. - */ - -extern unsigned int max_cstate; - -static inline unsigned int acpi_get_cstate_limit(void) -{ - return max_cstate; -} -static inline void acpi_set_cstate_limit(unsigned int new_limit) -{ - max_cstate = new_limit; - return; -} -#else -static inline unsigned int acpi_get_cstate_limit(void) { return 0; } -static inline void acpi_set_cstate_limit(unsigned int new_limit) { return; } -#endif - #ifdef CONFIG_ACPI_NUMA int acpi_get_pxm(acpi_handle handle); int acpi_get_node(acpi_handle *handle); diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h new file mode 100644 index 0000000..16a5154 --- /dev/null +++ b/include/linux/cpuidle.h @@ -0,0 +1,180 @@ +/* + * cpuidle.h - a generic framework for CPU idle power management + * + * (C) 2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> + * Shaohua Li <shaohua.li@intel.com> + * Adam Belay <abelay@novell.com> + * + * This code is licenced under the GPL. + */ + +#ifndef _LINUX_CPUIDLE_H +#define _LINUX_CPUIDLE_H + +#include <linux/percpu.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/kobject.h> +#include <linux/completion.h> + +#define CPUIDLE_STATE_MAX 8 +#define CPUIDLE_NAME_LEN 16 + +struct cpuidle_device; + + +/**************************** + * CPUIDLE DEVICE INTERFACE * + ****************************/ + +struct cpuidle_state { + char name[CPUIDLE_NAME_LEN]; + void *driver_data; + + unsigned int flags; + unsigned int exit_latency; /* in US */ + unsigned int power_usage; /* in mW */ + unsigned int target_residency; /* in US */ + + unsigned int usage; + unsigned int time; /* in US */ + + int (*enter) (struct cpuidle_device *dev, + struct cpuidle_state *state); +}; + +/* Idle State Flags */ +#define CPUIDLE_FLAG_TIME_VALID (0x01) /* is residency time measurable? */ +#define CPUIDLE_FLAG_CHECK_BM (0x02) /* BM activity will exit state */ +#define CPUIDLE_FLAG_SHALLOW (0x10) /* low latency, minimal savings */ +#define CPUIDLE_FLAG_BALANCED (0x20) /* medium latency, moderate savings */ +#define CPUIDLE_FLAG_DEEP (0x40) /* high latency, large savings */ + +#define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) + +/** + * cpuidle_get_statedata - retrieves private driver state data + * @state: the state + */ +static inline void * cpuidle_get_statedata(struct cpuidle_state *state) +{ + return state->driver_data; +} + +/** + * cpuidle_set_statedata - stores private driver state data + * @state: the state + * @data: the private data + */ +static inline void +cpuidle_set_statedata(struct cpuidle_state *state, void *data) +{ + state->driver_data = data; +} + +struct cpuidle_state_kobj { + struct cpuidle_state *state; + struct completion kobj_unregister; + struct kobject kobj; +}; + +struct cpuidle_device { + int enabled:1; + unsigned int cpu; + + int last_residency; + int state_count; + struct cpuidle_state states[CPUIDLE_STATE_MAX]; + struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX]; + struct cpuidle_state *last_state; + + struct list_head device_list; + struct kobject kobj; + struct completion kobj_unregister; + void *governor_data; +}; + +DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); + +/** + * cpuidle_get_last_residency - retrieves the last state's residency time + * @dev: the target CPU + * + * NOTE: this value is invalid if CPUIDLE_FLAG_TIME_VALID isn't set + */ +static inline int cpuidle_get_last_residency(struct cpuidle_device *dev) +{ + return dev->last_residency; +} + + +/**************************** + * CPUIDLE DRIVER INTERFACE * + ****************************/ + +struct cpuidle_driver { + char name[CPUIDLE_NAME_LEN]; + struct module *owner; +}; + +#ifdef CONFIG_CPU_IDLE + +extern int cpuidle_register_driver(struct cpuidle_driver *drv); +extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); +extern int cpuidle_register_device(struct cpuidle_device *dev); +extern void cpuidle_unregister_device(struct cpuidle_device *dev); + +extern void cpuidle_pause_and_lock(void); +extern void cpuidle_resume_and_unlock(void); +extern int cpuidle_enable_device(struct cpuidle_device *dev); +extern void cpuidle_disable_device(struct cpuidle_device *dev); + +#else + +static inline int cpuidle_register_driver(struct cpuidle_driver *drv) +{return 0;} +static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { } +static inline int cpuidle_register_device(struct cpuidle_device *dev) +{return 0;} +static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { } + +static inline void cpuidle_pause_and_lock(void) { } +static inline void cpuidle_resume_and_unlock(void) { } +static inline int cpuidle_enable_device(struct cpuidle_device *dev) +{return 0;} +static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } + +#endif + +/****************************** + * CPUIDLE GOVERNOR INTERFACE * + ******************************/ + +struct cpuidle_governor { + char name[CPUIDLE_NAME_LEN]; + struct list_head governor_list; + unsigned int rating; + + int (*enable) (struct cpuidle_device *dev); + void (*disable) (struct cpuidle_device *dev); + + int (*select) (struct cpuidle_device *dev); + void (*reflect) (struct cpuidle_device *dev); + + struct module *owner; +}; + +#ifdef CONFIG_CPU_IDLE + +extern int cpuidle_register_governor(struct cpuidle_governor *gov); +extern void cpuidle_unregister_governor(struct cpuidle_governor *gov); + +#else + +static inline int cpuidle_register_governor(struct cpuidle_governor *gov) +{return 0;} +static inline void cpuidle_unregister_governor(struct cpuidle_governor *gov) { } + +#endif + +#endif /* _LINUX_CPUIDLE_H */ diff --git a/include/linux/tick.h b/include/linux/tick.h index 9a7252e..f4a1395 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h @@ -40,6 +40,7 @@ enum tick_nohz_mode { * @idle_sleeps: Number of idle calls, where the sched tick was stopped * @idle_entrytime: Time when the idle call was entered * @idle_sleeptime: Sum of the time slept in idle with sched tick stopped + * @sleep_length: Duration of the current idle sleep */ struct tick_sched { struct hrtimer sched_timer; @@ -52,6 +53,7 @@ struct tick_sched { unsigned long idle_sleeps; ktime_t idle_entrytime; ktime_t idle_sleeptime; + ktime_t sleep_length; unsigned long last_jiffies; unsigned long next_jiffies; ktime_t idle_expires; @@ -100,10 +102,17 @@ static inline int tick_check_oneshot_change(int allow_nohz) { return 0; } extern void tick_nohz_stop_sched_tick(void); extern void tick_nohz_restart_sched_tick(void); extern void tick_nohz_update_jiffies(void); +extern ktime_t tick_nohz_get_sleep_length(void); # else static inline void tick_nohz_stop_sched_tick(void) { } static inline void tick_nohz_restart_sched_tick(void) { } static inline void tick_nohz_update_jiffies(void) { } +static inline ktime_t tick_nohz_get_sleep_length(void) +{ + ktime_t len = { .tv64 = NSEC_PER_SEC/HZ }; + + return len; +} # endif /* !NO_HZ */ #endif |