Commit f60d63f6 authored by Len Brown's avatar Len Brown

Merge branches 'release', 'dmi', 'idle' and 'misc' into release

...@@ -109,6 +109,8 @@ cpu-hotplug.txt ...@@ -109,6 +109,8 @@ cpu-hotplug.txt
- document describing CPU hotplug support in the Linux kernel. - document describing CPU hotplug support in the Linux kernel.
cpu-load.txt cpu-load.txt
- document describing how CPU load statistics are collected. - document describing how CPU load statistics are collected.
cpuidle/
- info on CPU_IDLE, CPU idle state management subsystem.
cpusets.txt cpusets.txt
- documents the cpusets feature; assign CPUs and Mem to a set of tasks. - documents the cpusets feature; assign CPUs and Mem to a set of tasks.
cputopology.txt cputopology.txt
......
Supporting multiple CPU idle levels in kernel
cpuidle
General Information:
Various CPUs today support multiple idle levels that are differentiated
by varying exit latencies and power consumption during idle.
cpuidle is a generic in-kernel infrastructure that separates
idle policy (governor) from idle mechanism (driver) and provides a
standardized infrastructure to support independent development of
governors and drivers.
cpuidle resides under drivers/cpuidle.
Boot options:
"cpuidle_sysfs_switch"
enables current_governor interface in /sys/devices/system/cpu/cpuidle/,
which can be used to switch governors at run time. This boot option
is meant for developer testing only. In normal usage, kernel picks the
best governor based on governor ratings.
SEE ALSO: sysfs.txt in this directory.
Supporting multiple CPU idle levels in kernel
cpuidle drivers
cpuidle driver hooks into the cpuidle infrastructure and handles the
architecture/platform dependent part of CPU idle states. Driver
provides the platform idle state detection capability and also
has mechanisms in place to support actual entry-exit into CPU idle states.
cpuidle driver initializes the cpuidle_device structure for each CPU device
and registers with cpuidle using cpuidle_register_device.
It can also support the dynamic changes (like battery <-> AC), by using
cpuidle_pause_and_lock, cpuidle_disable_device and cpuidle_enable_device,
cpuidle_resume_and_unlock.
Interfaces:
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);
Supporting multiple CPU idle levels in kernel
cpuidle governors
cpuidle governor is policy routine that decides what idle state to enter at
any given time. cpuidle core uses different callbacks to the governor.
* enable() to enable governor for a particular device
* disable() to disable governor for a particular device
* select() to select an idle state to enter
* reflect() called after returning from the idle state, which can be used
by the governor for some record keeping.
More than one governor can be registered at the same time and
users can switch between drivers using /sysfs interface (when enabled).
More than one governor part is supported for developers to easily experiment
with different governors. By default, most optimal governor based on your
kernel configuration and platform will be selected by cpuidle.
Interfaces:
extern int cpuidle_register_governor(struct cpuidle_governor *gov);
extern void cpuidle_unregister_governor(struct cpuidle_governor *gov);
struct cpuidle_governor
Supporting multiple CPU idle levels in kernel
cpuidle sysfs
System global cpuidle related information and tunables are under
/sys/devices/system/cpu/cpuidle
The current interfaces in this directory has self-explanatory names:
* current_driver
* current_governor_ro
With cpuidle_sysfs_switch boot option (meant for developer testing)
following objects are visible instead.
* current_driver
* available_governors
* current_governor
In this case users can switch the governor at run time by writing
to current_governor.
Per logical CPU specific cpuidle information are under
/sys/devices/system/cpu/cpuX/cpuidle
for each online cpu X
--------------------------------------------------------------------------------
# ls -lR /sys/devices/system/cpu/cpu0/cpuidle/
/sys/devices/system/cpu/cpu0/cpuidle/:
total 0
drwxr-xr-x 2 root root 0 Feb 8 10:42 state0
drwxr-xr-x 2 root root 0 Feb 8 10:42 state1
drwxr-xr-x 2 root root 0 Feb 8 10:42 state2
drwxr-xr-x 2 root root 0 Feb 8 10:42 state3
/sys/devices/system/cpu/cpu0/cpuidle/state0:
total 0
-r--r--r-- 1 root root 4096 Feb 8 10:42 desc
-r--r--r-- 1 root root 4096 Feb 8 10:42 latency
-r--r--r-- 1 root root 4096 Feb 8 10:42 name
-r--r--r-- 1 root root 4096 Feb 8 10:42 power
-r--r--r-- 1 root root 4096 Feb 8 10:42 time
-r--r--r-- 1 root root 4096 Feb 8 10:42 usage
/sys/devices/system/cpu/cpu0/cpuidle/state1:
total 0
-r--r--r-- 1 root root 4096 Feb 8 10:42 desc
-r--r--r-- 1 root root 4096 Feb 8 10:42 latency
-r--r--r-- 1 root root 4096 Feb 8 10:42 name
-r--r--r-- 1 root root 4096 Feb 8 10:42 power
-r--r--r-- 1 root root 4096 Feb 8 10:42 time
-r--r--r-- 1 root root 4096 Feb 8 10:42 usage
/sys/devices/system/cpu/cpu0/cpuidle/state2:
total 0
-r--r--r-- 1 root root 4096 Feb 8 10:42 desc
-r--r--r-- 1 root root 4096 Feb 8 10:42 latency
-r--r--r-- 1 root root 4096 Feb 8 10:42 name
-r--r--r-- 1 root root 4096 Feb 8 10:42 power
-r--r--r-- 1 root root 4096 Feb 8 10:42 time
-r--r--r-- 1 root root 4096 Feb 8 10:42 usage
/sys/devices/system/cpu/cpu0/cpuidle/state3:
total 0
-r--r--r-- 1 root root 4096 Feb 8 10:42 desc
-r--r--r-- 1 root root 4096 Feb 8 10:42 latency
-r--r--r-- 1 root root 4096 Feb 8 10:42 name
-r--r--r-- 1 root root 4096 Feb 8 10:42 power
-r--r--r-- 1 root root 4096 Feb 8 10:42 time
-r--r--r-- 1 root root 4096 Feb 8 10:42 usage
--------------------------------------------------------------------------------
* desc : Small description about the idle state (string)
* latency : Latency to exit out of this idle state (in microseconds)
* name : Name of the idle state (string)
* power : Power consumed while in this idle state (in milliwatts)
* time : Total time spent in this idle state (in microseconds)
* usage : Number of times this state was entered (count)
...@@ -126,6 +126,8 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu, ...@@ -126,6 +126,8 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
printk(KERN_DEBUG "Monitor-Mwait will be used to enter C-%d " printk(KERN_DEBUG "Monitor-Mwait will be used to enter C-%d "
"state\n", cx->type); "state\n", cx->type);
} }
snprintf(cx->desc, ACPI_CX_DESC_LEN, "ACPI FFH INTEL MWAIT 0x%x",
cx->address);
out: out:
set_cpus_allowed(current, saved_mask); set_cpus_allowed(current, saved_mask);
......
...@@ -110,7 +110,7 @@ static const struct file_operations acpi_system_event_ops = { ...@@ -110,7 +110,7 @@ static const struct file_operations acpi_system_event_ops = {
#endif /* CONFIG_ACPI_PROC_EVENT */ #endif /* CONFIG_ACPI_PROC_EVENT */
/* ACPI notifier chain */ /* ACPI notifier chain */
BLOCKING_NOTIFIER_HEAD(acpi_chain_head); static BLOCKING_NOTIFIER_HEAD(acpi_chain_head);
int acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data) int acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data)
{ {
......
...@@ -616,6 +616,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) ...@@ -616,6 +616,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
arg.integer.value = sleep_state;
status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL); status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK")); ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK"));
......
...@@ -325,7 +325,7 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val, ...@@ -325,7 +325,7 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
} }
#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD #ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
struct acpi_table_header *acpi_find_dsdt_initrd(void) static struct acpi_table_header *acpi_find_dsdt_initrd(void)
{ {
struct file *firmware_file; struct file *firmware_file;
mm_segment_t oldfs; mm_segment_t oldfs;
...@@ -419,7 +419,7 @@ acpi_os_table_override(struct acpi_table_header * existing_table, ...@@ -419,7 +419,7 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
} }
#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD #ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
int __init acpi_no_initrd_override_setup(char *s) static int __init acpi_no_initrd_override_setup(char *s)
{ {
acpi_no_initrd_override = 1; acpi_no_initrd_override = 1;
return 1; return 1;
......
...@@ -945,11 +945,16 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) ...@@ -945,11 +945,16 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
* Otherwise, ignore this info and continue. * Otherwise, ignore this info and continue.
*/ */
cx.entry_method = ACPI_CSTATE_HALT; cx.entry_method = ACPI_CSTATE_HALT;
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
} else { } else {
continue; continue;
} }
} else {
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x",
cx.address);
} }
obj = &(element->package.elements[2]); obj = &(element->package.elements[2]);
if (obj->type != ACPI_TYPE_INTEGER) if (obj->type != ACPI_TYPE_INTEGER)
continue; continue;
...@@ -1420,6 +1425,14 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, ...@@ -1420,6 +1425,14 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
return 0; return 0;
local_irq_disable(); local_irq_disable();
/* Do not access any ACPI IO ports in suspend path */
if (acpi_idle_suspend) {
acpi_safe_halt();
local_irq_enable();
return 0;
}
if (pr->flags.bm_check) if (pr->flags.bm_check)
acpi_idle_update_bm_rld(pr, cx); acpi_idle_update_bm_rld(pr, cx);
...@@ -1643,6 +1656,11 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) ...@@ -1643,6 +1656,11 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
return -EINVAL; return -EINVAL;
} }
for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
dev->states[i].name[0] = '\0';
dev->states[i].desc[0] = '\0';
}
for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
cx = &pr->power.states[i]; cx = &pr->power.states[i];
state = &dev->states[count]; state = &dev->states[count];
...@@ -1659,6 +1677,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) ...@@ -1659,6 +1677,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
cpuidle_set_statedata(state, cx); cpuidle_set_statedata(state, cx);
snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
state->exit_latency = cx->latency; state->exit_latency = cx->latency;
state->target_residency = cx->latency * latency_factor; state->target_residency = cx->latency * latency_factor;
state->power_usage = cx->power; state->power_usage = cx->power;
......
...@@ -219,7 +219,8 @@ static void poll_idle_init(struct cpuidle_device *dev) ...@@ -219,7 +219,8 @@ static void poll_idle_init(struct cpuidle_device *dev)
cpuidle_set_statedata(state, NULL); cpuidle_set_statedata(state, NULL);
snprintf(state->name, CPUIDLE_NAME_LEN, "C0 (poll idle)"); snprintf(state->name, CPUIDLE_NAME_LEN, "C0");
snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
state->exit_latency = 0; state->exit_latency = 0;
state->target_residency = 0; state->target_residency = 0;
state->power_usage = -1; state->power_usage = -1;
......
...@@ -218,16 +218,23 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ ...@@ -218,16 +218,23 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
return sprintf(buf, "%u\n", state->_name);\ return sprintf(buf, "%u\n", state->_name);\
} }
static ssize_t show_state_name(struct cpuidle_state *state, char *buf) #define define_show_state_str_function(_name) \
{ static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
return sprintf(buf, "%s\n", state->name); { \
if (state->_name[0] == '\0')\
return sprintf(buf, "<null>\n");\
return sprintf(buf, "%s\n", state->_name);\
} }
define_show_state_function(exit_latency) define_show_state_function(exit_latency)
define_show_state_function(power_usage) define_show_state_function(power_usage)
define_show_state_function(usage) define_show_state_function(usage)
define_show_state_function(time) define_show_state_function(time)
define_show_state_str_function(name)
define_show_state_str_function(desc)
define_one_state_ro(name, show_state_name); define_one_state_ro(name, show_state_name);
define_one_state_ro(desc, show_state_desc);
define_one_state_ro(latency, show_state_exit_latency); define_one_state_ro(latency, show_state_exit_latency);
define_one_state_ro(power, show_state_power_usage); define_one_state_ro(power, show_state_power_usage);
define_one_state_ro(usage, show_state_usage); define_one_state_ro(usage, show_state_usage);
...@@ -235,6 +242,7 @@ define_one_state_ro(time, show_state_time); ...@@ -235,6 +242,7 @@ define_one_state_ro(time, show_state_time);
static struct attribute *cpuidle_state_default_attrs[] = { static struct attribute *cpuidle_state_default_attrs[] = {
&attr_name.attr, &attr_name.attr,
&attr_desc.attr,
&attr_latency.attr, &attr_latency.attr,
&attr_power.attr, &attr_power.attr,
&attr_usage.attr, &attr_usage.attr,
......
...@@ -1689,7 +1689,7 @@ static ssize_t hotkey_wakeup_reason_show(struct device *dev, ...@@ -1689,7 +1689,7 @@ static ssize_t hotkey_wakeup_reason_show(struct device *dev,
static struct device_attribute dev_attr_hotkey_wakeup_reason = static struct device_attribute dev_attr_hotkey_wakeup_reason =
__ATTR(wakeup_reason, S_IRUGO, hotkey_wakeup_reason_show, NULL); __ATTR(wakeup_reason, S_IRUGO, hotkey_wakeup_reason_show, NULL);
void hotkey_wakeup_reason_notify_change(void) static void hotkey_wakeup_reason_notify_change(void)
{ {
if (tp_features.hotkey_mask) if (tp_features.hotkey_mask)
sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, sysfs_notify(&tpacpi_pdev->dev.kobj, NULL,
...@@ -1708,7 +1708,7 @@ static struct device_attribute dev_attr_hotkey_wakeup_hotunplug_complete = ...@@ -1708,7 +1708,7 @@ static struct device_attribute dev_attr_hotkey_wakeup_hotunplug_complete =
__ATTR(wakeup_hotunplug_complete, S_IRUGO, __ATTR(wakeup_hotunplug_complete, S_IRUGO,
hotkey_wakeup_hotunplug_complete_show, NULL); hotkey_wakeup_hotunplug_complete_show, NULL);
void hotkey_wakeup_hotunplug_complete_notify_change(void) static void hotkey_wakeup_hotunplug_complete_notify_change(void)
{ {
if (tp_features.hotkey_mask) if (tp_features.hotkey_mask)
sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, sysfs_notify(&tpacpi_pdev->dev.kobj, NULL,
......
...@@ -36,7 +36,7 @@ static int num = 0; ...@@ -36,7 +36,7 @@ static int num = 0;
* have irqs (PIC, Timer) because we call acpi_register_gsi. * have irqs (PIC, Timer) because we call acpi_register_gsi.
* Finally, only devices that have a CRS method need to be in this list. * Finally, only devices that have a CRS method need to be in this list.
*/ */
static struct __initdata acpi_device_id excluded_id_list[] = { static struct acpi_device_id excluded_id_list[] __initdata = {
{"PNP0C09", 0}, /* EC */ {"PNP0C09", 0}, /* EC */
{"PNP0C0F", 0}, /* Link device */ {"PNP0C0F", 0}, /* Link device */
{"PNP0000", 0}, /* PIC */ {"PNP0000", 0}, /* PIC */
......
...@@ -32,9 +32,11 @@ ...@@ -32,9 +32,11 @@
#define DOMAIN_COORD_TYPE_SW_ANY 0xfd #define DOMAIN_COORD_TYPE_SW_ANY 0xfd
#define DOMAIN_COORD_TYPE_HW_ALL 0xfe #define DOMAIN_COORD_TYPE_HW_ALL 0xfe
#define ACPI_CSTATE_SYSTEMIO (0) #define ACPI_CSTATE_SYSTEMIO 0
#define ACPI_CSTATE_FFH (1) #define ACPI_CSTATE_FFH 1
#define ACPI_CSTATE_HALT (2) #define ACPI_CSTATE_HALT 2
#define ACPI_CX_DESC_LEN 32
/* Power Management */ /* Power Management */
...@@ -74,6 +76,7 @@ struct acpi_processor_cx { ...@@ -74,6 +76,7 @@ struct acpi_processor_cx {
u64 time; u64 time;
struct acpi_processor_cx_policy promotion; struct acpi_processor_cx_policy promotion;
struct acpi_processor_cx_policy demotion; struct acpi_processor_cx_policy demotion;
char desc[ACPI_CX_DESC_LEN];
}; };
struct acpi_processor_power { struct acpi_processor_power {
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#define CPUIDLE_STATE_MAX 8 #define CPUIDLE_STATE_MAX 8
#define CPUIDLE_NAME_LEN 16 #define CPUIDLE_NAME_LEN 16
#define CPUIDLE_DESC_LEN 32
struct cpuidle_device; struct cpuidle_device;
...@@ -29,6 +30,7 @@ struct cpuidle_device; ...@@ -29,6 +30,7 @@ struct cpuidle_device;
struct cpuidle_state { struct cpuidle_state {
char name[CPUIDLE_NAME_LEN]; char name[CPUIDLE_NAME_LEN];
char desc[CPUIDLE_DESC_LEN];
void *driver_data; void *driver_data;
unsigned int flags; unsigned int flags;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment