Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 298009
b: refs/heads/master
c: e168979
h: refs/heads/master
i:
  298007: c93ce8e
v: v3
  • Loading branch information
Robert Lee authored and Len Brown committed Mar 21, 2012
1 parent a1987a3 commit 43ae643
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 12 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cf450136bfde77c7f95065c91bffded4aa7fa731
refs/heads/master: e1689795a784a7c41ac4cf9032794986b095a133
29 changes: 29 additions & 0 deletions trunk/arch/arm/include/asm/cpuidle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef __ASM_ARM_CPUIDLE_H
#define __ASM_ARM_CPUIDLE_H

#ifdef CONFIG_CPU_IDLE
extern int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index);
#else
static inline int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index) { return -ENODEV; }
#endif

/* Common ARM WFI state */
#define ARM_CPUIDLE_WFI_STATE_PWR(p) {\
.enter = arm_cpuidle_simple_enter,\
.exit_latency = 1,\
.target_residency = 1,\
.power_usage = p,\
.flags = CPUIDLE_FLAG_TIME_VALID,\
.name = "WFI",\
.desc = "ARM WFI",\
}

/*
* in case power_specified == 1, give a default WFI power value needed
* by some governors
*/
#define ARM_CPUIDLE_WFI_STATE ARM_CPUIDLE_WFI_STATE_PWR(UINT_MAX)

#endif
2 changes: 1 addition & 1 deletion trunk/arch/arm/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o

obj-$(CONFIG_LEDS) += leds.o
obj-$(CONFIG_OC_ETM) += etm.o

obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_ISA_DMA_API) += dma.o
obj-$(CONFIG_ARCH_ACORN) += ecard.o
obj-$(CONFIG_FIQ) += fiq.o fiqasm.o
Expand Down
21 changes: 21 additions & 0 deletions trunk/arch/arm/kernel/cpuidle.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright 2012 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/

#include <linux/cpuidle.h>
#include <asm/proc-fns.h>

int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
cpu_do_idle();

return index;
}
3 changes: 2 additions & 1 deletion trunk/drivers/acpi/acpica/hwxface.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ acpi_status acpi_reset(void)

/* Check if the reset register is supported */

if (!reset_reg->address) {
if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
!reset_reg->address) {
return_ACPI_STATUS(AE_NOT_EXIST);
}

Expand Down
3 changes: 2 additions & 1 deletion trunk/drivers/acpi/reboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ void acpi_reboot(void)
/* Is the reset register supported? The spec says we should be
* checking the bit width and bit offset, but Windows ignores
* these fields */
/* Ignore also acpi_gbl_FADT.flags.ACPI_FADT_RESET_REGISTER */
if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER))
return;

reset_value = acpi_gbl_FADT.reset_value;

Expand Down
66 changes: 59 additions & 7 deletions trunk/drivers/cpuidle/cpuidle.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,24 @@ static void cpuidle_kick_cpus(void) {}

static int __cpuidle_register_device(struct cpuidle_device *dev);

static inline int cpuidle_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
struct cpuidle_state *target_state = &drv->states[index];
return target_state->enter(dev, drv, index);
}

static inline int cpuidle_enter_tk(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
return cpuidle_wrap_enter(dev, drv, index, cpuidle_enter);
}

typedef int (*cpuidle_enter_t)(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index);

static cpuidle_enter_t cpuidle_enter_ops;

/**
* cpuidle_idle_call - the main idle loop
*
Expand All @@ -63,7 +81,6 @@ int cpuidle_idle_call(void)
{
struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
struct cpuidle_driver *drv = cpuidle_get_driver();
struct cpuidle_state *target_state;
int next_state, entered_state;

if (off)
Expand Down Expand Up @@ -92,12 +109,10 @@ int cpuidle_idle_call(void)
return 0;
}

target_state = &drv->states[next_state];

trace_power_start(POWER_CSTATE, next_state, dev->cpu);
trace_cpu_idle(next_state, dev->cpu);

entered_state = target_state->enter(dev, drv, next_state);
entered_state = cpuidle_enter_ops(dev, drv, next_state);

trace_power_end(dev->cpu);
trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
Expand All @@ -110,6 +125,8 @@ int cpuidle_idle_call(void)
dev->states_usage[entered_state].time +=
(unsigned long long)dev->last_residency;
dev->states_usage[entered_state].usage++;
} else {
dev->last_residency = 0;
}

/* give the governor an opportunity to reflect on the outcome */
Expand Down Expand Up @@ -164,6 +181,37 @@ void cpuidle_resume_and_unlock(void)

EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);

/**
* cpuidle_wrap_enter - performs timekeeping and irqen around enter function
* @dev: pointer to a valid cpuidle_device object
* @drv: pointer to a valid cpuidle_driver object
* @index: index of the target cpuidle state.
*/
int cpuidle_wrap_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index,
int (*enter)(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index))
{
ktime_t time_start, time_end;
s64 diff;

time_start = ktime_get();

index = enter(dev, drv, index);

time_end = ktime_get();

local_irq_enable();

diff = ktime_to_us(ktime_sub(time_end, time_start));
if (diff > INT_MAX)
diff = INT_MAX;

dev->last_residency = (int) diff;

return index;
}

#ifdef CONFIG_ARCH_HAS_CPU_RELAX
static int poll_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
Expand Down Expand Up @@ -212,10 +260,11 @@ static void poll_idle_init(struct cpuidle_driver *drv) {}
int cpuidle_enable_device(struct cpuidle_device *dev)
{
int ret, i;
struct cpuidle_driver *drv = cpuidle_get_driver();

if (dev->enabled)
return 0;
if (!cpuidle_get_driver() || !cpuidle_curr_governor)
if (!drv || !cpuidle_curr_governor)
return -EIO;
if (!dev->state_count)
return -EINVAL;
Expand All @@ -226,13 +275,16 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
return ret;
}

poll_idle_init(cpuidle_get_driver());
cpuidle_enter_ops = drv->en_core_tk_irqen ?
cpuidle_enter_tk : cpuidle_enter;

poll_idle_init(drv);

if ((ret = cpuidle_add_state_sysfs(dev)))
return ret;

if (cpuidle_curr_governor->enable &&
(ret = cpuidle_curr_governor->enable(cpuidle_get_driver(), dev)))
(ret = cpuidle_curr_governor->enable(drv, dev)))
goto fail_sysfs;

for (i = 0; i < dev->state_count; i++) {
Expand Down
13 changes: 12 additions & 1 deletion trunk/include/linux/cpuidle.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/kobject.h>
#include <linux/completion.h>
#include <linux/hrtimer.h>

#define CPUIDLE_STATE_MAX 8
#define CPUIDLE_NAME_LEN 16
Expand Down Expand Up @@ -122,6 +123,8 @@ struct cpuidle_driver {
struct module *owner;

unsigned int power_specified:1;
/* set to 1 to use the core cpuidle time keeping (for all states). */
unsigned int en_core_tk_irqen:1;
struct cpuidle_state states[CPUIDLE_STATE_MAX];
int state_count;
int safe_state_index;
Expand All @@ -140,7 +143,10 @@ 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);

extern int cpuidle_wrap_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index,
int (*enter)(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index));
#else
static inline void disable_cpuidle(void) { }
static inline int cpuidle_idle_call(void) { return -ENODEV; }
Expand All @@ -157,6 +163,11 @@ static inline void cpuidle_resume_and_unlock(void) { }
static inline int cpuidle_enable_device(struct cpuidle_device *dev)
{return -ENODEV; }
static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
static inline int cpuidle_wrap_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index,
int (*enter)(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index))
{ return -ENODEV; }

#endif

Expand Down

0 comments on commit 43ae643

Please sign in to comment.