Skip to content

Commit

Permalink
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/g…
Browse files Browse the repository at this point in the history
…it/lenb/linux

* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux:
  cpuidle: Single/Global registration of idle states
  cpuidle: Split cpuidle_state structure and move per-cpu statistics fields
  cpuidle: Remove CPUIDLE_FLAG_IGNORE and dev->prepare()
  cpuidle: Move dev->last_residency update to driver enter routine; remove dev->last_state
  ACPI: Fix CONFIG_ACPI_DOCK=n compiler warning
  ACPI: Export FADT pm_profile integer value to userspace
  thermal: Prevent polling from happening during system suspend
  ACPI: Drop ACPI_NO_HARDWARE_INIT
  ACPI atomicio: Convert width in bits to bytes in __acpi_ioremap_fast()
  PNPACPI: Simplify disabled resource registration
  ACPI: Fix possible recursive locking in hwregs.c
  ACPI: use kstrdup()
  mrst pmu: update comment
  tools/power turbostat: less verbose debugging
  • Loading branch information
torvalds committed Nov 7, 2011
2 parents 83dbb15 + efb9058 commit 3c00303
Show file tree
Hide file tree
Showing 28 changed files with 729 additions and 412 deletions.
22 changes: 22 additions & 0 deletions Documentation/ABI/stable/sysfs-acpi-pmprofile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
What: /sys/firmware/acpi/pm_profile
Date: 03-Nov-2011
KernelVersion: v3.2
Contact: [email protected]
Description: The ACPI pm_profile sysfs interface exports the platform
power management (and performance) requirement expectations
as provided by BIOS. The integer value is directly passed as
retrieved from the FADT ACPI table.
Values: For possible values see ACPI specification:
5.2.9 Fixed ACPI Description Table (FADT)
Field: Preferred_PM_Profile

Currently these values are defined by spec:
0 Unspecified
1 Desktop
2 Mobile
3 Workstation
4 Enterprise Server
5 SOHO Server
6 Appliance PC
7 Performance Server
>7 Reserved
41 changes: 23 additions & 18 deletions arch/arm/mach-at91/cpuidle.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,19 @@ static struct cpuidle_driver at91_idle_driver = {

/* Actual code that puts the SoC in different idle states */
static int at91_enter_idle(struct cpuidle_device *dev,
struct cpuidle_state *state)
struct cpuidle_driver *drv,
int index)
{
struct timeval before, after;
int idle_time;
u32 saved_lpr;

local_irq_disable();
do_gettimeofday(&before);
if (state == &dev->states[0])
if (index == 0)
/* Wait for interrupt state */
cpu_do_idle();
else if (state == &dev->states[1]) {
else if (index == 1) {
asm("b 1f; .align 5; 1:");
asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */
saved_lpr = sdram_selfrefresh_enable();
Expand All @@ -56,34 +57,38 @@ static int at91_enter_idle(struct cpuidle_device *dev,
local_irq_enable();
idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
(after.tv_usec - before.tv_usec);
return idle_time;

dev->last_residency = idle_time;
return index;
}

/* Initialize CPU idle by registering the idle states */
static int at91_init_cpuidle(void)
{
struct cpuidle_device *device;

cpuidle_register_driver(&at91_idle_driver);
struct cpuidle_driver *driver = &at91_idle_driver;

device = &per_cpu(at91_cpuidle_device, smp_processor_id());
device->state_count = AT91_MAX_STATES;
driver->state_count = AT91_MAX_STATES;

/* Wait for interrupt state */
device->states[0].enter = at91_enter_idle;
device->states[0].exit_latency = 1;
device->states[0].target_residency = 10000;
device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
strcpy(device->states[0].name, "WFI");
strcpy(device->states[0].desc, "Wait for interrupt");
driver->states[0].enter = at91_enter_idle;
driver->states[0].exit_latency = 1;
driver->states[0].target_residency = 10000;
driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
strcpy(driver->states[0].name, "WFI");
strcpy(driver->states[0].desc, "Wait for interrupt");

/* Wait for interrupt and RAM self refresh state */
device->states[1].enter = at91_enter_idle;
device->states[1].exit_latency = 10;
device->states[1].target_residency = 10000;
device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
strcpy(device->states[1].name, "RAM_SR");
strcpy(device->states[1].desc, "WFI and RAM Self Refresh");
driver->states[1].enter = at91_enter_idle;
driver->states[1].exit_latency = 10;
driver->states[1].target_residency = 10000;
driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
strcpy(driver->states[1].name, "RAM_SR");
strcpy(driver->states[1].desc, "WFI and RAM Self Refresh");

cpuidle_register_driver(&at91_idle_driver);

if (cpuidle_register_device(device)) {
printk(KERN_ERR "at91_init_cpuidle: Failed registering\n");
Expand Down
51 changes: 29 additions & 22 deletions arch/arm/mach-davinci/cpuidle.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,11 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = {

/* Actual code that puts the SoC in different idle states */
static int davinci_enter_idle(struct cpuidle_device *dev,
struct cpuidle_state *state)
struct cpuidle_driver *drv,
int index)
{
struct davinci_ops *ops = cpuidle_get_statedata(state);
struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
struct davinci_ops *ops = cpuidle_get_statedata(state_usage);
struct timeval before, after;
int idle_time;

Expand All @@ -99,13 +101,17 @@ static int davinci_enter_idle(struct cpuidle_device *dev,
local_irq_enable();
idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
(after.tv_usec - before.tv_usec);
return idle_time;

dev->last_residency = idle_time;

return index;
}

static int __init davinci_cpuidle_probe(struct platform_device *pdev)
{
int ret;
struct cpuidle_device *device;
struct cpuidle_driver *driver = &davinci_idle_driver;
struct davinci_cpuidle_config *pdata = pdev->dev.platform_data;

device = &per_cpu(davinci_cpuidle_device, smp_processor_id());
Expand All @@ -117,32 +123,33 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)

ddr2_reg_base = pdata->ddr2_ctlr_base;

ret = cpuidle_register_driver(&davinci_idle_driver);
if (ret) {
dev_err(&pdev->dev, "failed to register driver\n");
return ret;
}

/* Wait for interrupt state */
device->states[0].enter = davinci_enter_idle;
device->states[0].exit_latency = 1;
device->states[0].target_residency = 10000;
device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
strcpy(device->states[0].name, "WFI");
strcpy(device->states[0].desc, "Wait for interrupt");
driver->states[0].enter = davinci_enter_idle;
driver->states[0].exit_latency = 1;
driver->states[0].target_residency = 10000;
driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
strcpy(driver->states[0].name, "WFI");
strcpy(driver->states[0].desc, "Wait for interrupt");

/* Wait for interrupt and DDR self refresh state */
device->states[1].enter = davinci_enter_idle;
device->states[1].exit_latency = 10;
device->states[1].target_residency = 10000;
device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
strcpy(device->states[1].name, "DDR SR");
strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
driver->states[1].enter = davinci_enter_idle;
driver->states[1].exit_latency = 10;
driver->states[1].target_residency = 10000;
driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
strcpy(driver->states[1].name, "DDR SR");
strcpy(driver->states[1].desc, "WFI and DDR Self Refresh");
if (pdata->ddr2_pdown)
davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN;
cpuidle_set_statedata(&device->states[1], &davinci_states[1]);
cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]);

device->state_count = DAVINCI_CPUIDLE_MAX_STATES;
driver->state_count = DAVINCI_CPUIDLE_MAX_STATES;

ret = cpuidle_register_driver(&davinci_idle_driver);
if (ret) {
dev_err(&pdev->dev, "failed to register driver\n");
return ret;
}

ret = cpuidle_register_device(device);
if (ret) {
Expand Down
30 changes: 17 additions & 13 deletions arch/arm/mach-exynos/cpuidle.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
#include <asm/proc-fns.h>

static int exynos4_enter_idle(struct cpuidle_device *dev,
struct cpuidle_state *state);
struct cpuidle_driver *drv,
int index);

static struct cpuidle_state exynos4_cpuidle_set[] = {
[0] = {
Expand All @@ -37,7 +38,8 @@ static struct cpuidle_driver exynos4_idle_driver = {
};

static int exynos4_enter_idle(struct cpuidle_device *dev,
struct cpuidle_state *state)
struct cpuidle_driver *drv,
int index)
{
struct timeval before, after;
int idle_time;
Expand All @@ -52,29 +54,31 @@ static int exynos4_enter_idle(struct cpuidle_device *dev,
idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
(after.tv_usec - before.tv_usec);

return idle_time;
dev->last_residency = idle_time;
return index;
}

static int __init exynos4_init_cpuidle(void)
{
int i, max_cpuidle_state, cpu_id;
struct cpuidle_device *device;

struct cpuidle_driver *drv = &exynos4_idle_driver;

/* Setup cpuidle driver */
drv->state_count = (sizeof(exynos4_cpuidle_set) /
sizeof(struct cpuidle_state));
max_cpuidle_state = drv->state_count;
for (i = 0; i < max_cpuidle_state; i++) {
memcpy(&drv->states[i], &exynos4_cpuidle_set[i],
sizeof(struct cpuidle_state));
}
cpuidle_register_driver(&exynos4_idle_driver);

for_each_cpu(cpu_id, cpu_online_mask) {
device = &per_cpu(exynos4_cpuidle_device, cpu_id);
device->cpu = cpu_id;

device->state_count = (sizeof(exynos4_cpuidle_set) /
sizeof(struct cpuidle_state));

max_cpuidle_state = device->state_count;

for (i = 0; i < max_cpuidle_state; i++) {
memcpy(&device->states[i], &exynos4_cpuidle_set[i],
sizeof(struct cpuidle_state));
}
device->state_count = drv->state_count;

if (cpuidle_register_device(device)) {
printk(KERN_ERR "CPUidle register device failed\n,");
Expand Down
42 changes: 24 additions & 18 deletions arch/arm/mach-kirkwood/cpuidle.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,18 @@ static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);

/* Actual code that puts the SoC in different idle states */
static int kirkwood_enter_idle(struct cpuidle_device *dev,
struct cpuidle_state *state)
struct cpuidle_driver *drv,
int index)
{
struct timeval before, after;
int idle_time;

local_irq_disable();
do_gettimeofday(&before);
if (state == &dev->states[0])
if (index == 0)
/* Wait for interrupt state */
cpu_do_idle();
else if (state == &dev->states[1]) {
else if (index == 1) {
/*
* Following write will put DDR in self refresh.
* Note that we have 256 cycles before DDR puts it
Expand All @@ -58,35 +59,40 @@ static int kirkwood_enter_idle(struct cpuidle_device *dev,
local_irq_enable();
idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
(after.tv_usec - before.tv_usec);
return idle_time;

/* Update last residency */
dev->last_residency = idle_time;

return index;
}

/* Initialize CPU idle by registering the idle states */
static int kirkwood_init_cpuidle(void)
{
struct cpuidle_device *device;

cpuidle_register_driver(&kirkwood_idle_driver);
struct cpuidle_driver *driver = &kirkwood_idle_driver;

device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
device->state_count = KIRKWOOD_MAX_STATES;
driver->state_count = KIRKWOOD_MAX_STATES;

/* Wait for interrupt state */
device->states[0].enter = kirkwood_enter_idle;
device->states[0].exit_latency = 1;
device->states[0].target_residency = 10000;
device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
strcpy(device->states[0].name, "WFI");
strcpy(device->states[0].desc, "Wait for interrupt");
driver->states[0].enter = kirkwood_enter_idle;
driver->states[0].exit_latency = 1;
driver->states[0].target_residency = 10000;
driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
strcpy(driver->states[0].name, "WFI");
strcpy(driver->states[0].desc, "Wait for interrupt");

/* Wait for interrupt and DDR self refresh state */
device->states[1].enter = kirkwood_enter_idle;
device->states[1].exit_latency = 10;
device->states[1].target_residency = 10000;
device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
strcpy(device->states[1].name, "DDR SR");
strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
driver->states[1].enter = kirkwood_enter_idle;
driver->states[1].exit_latency = 10;
driver->states[1].target_residency = 10000;
driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
strcpy(driver->states[1].name, "DDR SR");
strcpy(driver->states[1].desc, "WFI and DDR Self Refresh");

cpuidle_register_driver(&kirkwood_idle_driver);
if (cpuidle_register_device(device)) {
printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n");
return -EIO;
Expand Down
Loading

0 comments on commit 3c00303

Please sign in to comment.