ARM: mach-shmobile: cpuidle single/global and last_state fixes

The following commits break cpuidle on SH-Mobile ARM:

46bcfad cpuidle: Single/Global registration of idle states
e978aa7 cpuidle: Move dev->last_residency update to driver enter routine; remove dev->last_state

This patch remedies these issues by up-porting the SH-Mobile
code to fit with the above introduced framework changes.

It is worth noting that the new code becomes significantly cleaner,
so these framework changes are very welcome. At the same time this
breakage could probably have been avoided by grepping for "last_state"
and "cpuidle_register_driver".

Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
Magnus Damm 2011-11-11 14:01:30 +09:00 committed by Paul Mundt
parent 9b49139b34
commit b73b5c493a
3 changed files with 30 additions and 40 deletions

View File

@ -26,65 +26,59 @@ void (*shmobile_cpuidle_modes[CPUIDLE_STATE_MAX])(void) = {
}; };
static int shmobile_cpuidle_enter(struct cpuidle_device *dev, static int shmobile_cpuidle_enter(struct cpuidle_device *dev,
struct cpuidle_state *state) struct cpuidle_driver *drv,
int index)
{ {
ktime_t before, after; ktime_t before, after;
int requested_state = state - &dev->states[0];
dev->last_state = &dev->states[requested_state];
before = ktime_get(); before = ktime_get();
local_irq_disable(); local_irq_disable();
local_fiq_disable(); local_fiq_disable();
shmobile_cpuidle_modes[requested_state](); shmobile_cpuidle_modes[index]();
local_irq_enable(); local_irq_enable();
local_fiq_enable(); local_fiq_enable();
after = ktime_get(); after = ktime_get();
return ktime_to_ns(ktime_sub(after, before)) >> 10; dev->last_residency = ktime_to_ns(ktime_sub(after, before)) >> 10;
return index;
} }
static struct cpuidle_device shmobile_cpuidle_dev; static struct cpuidle_device shmobile_cpuidle_dev;
static struct cpuidle_driver shmobile_cpuidle_driver = { static struct cpuidle_driver shmobile_cpuidle_driver = {
.name = "shmobile_cpuidle", .name = "shmobile_cpuidle",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.states[0] = {
.name = "C1",
.desc = "WFI",
.exit_latency = 1,
.target_residency = 1 * 2,
.flags = CPUIDLE_FLAG_TIME_VALID,
},
.safe_state_index = 0, /* C1 */
.state_count = 1,
}; };
void (*shmobile_cpuidle_setup)(struct cpuidle_device *dev); void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
static int shmobile_cpuidle_init(void) static int shmobile_cpuidle_init(void)
{ {
struct cpuidle_device *dev = &shmobile_cpuidle_dev; struct cpuidle_device *dev = &shmobile_cpuidle_dev;
struct cpuidle_state *state; struct cpuidle_driver *drv = &shmobile_cpuidle_driver;
int i; int i;
cpuidle_register_driver(&shmobile_cpuidle_driver); for (i = 0; i < CPUIDLE_STATE_MAX; i++)
drv->states[i].enter = shmobile_cpuidle_enter;
for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
dev->states[i].name[0] = '\0';
dev->states[i].desc[0] = '\0';
dev->states[i].enter = shmobile_cpuidle_enter;
}
i = CPUIDLE_DRIVER_STATE_START;
state = &dev->states[i++];
snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
strncpy(state->desc, "WFI", CPUIDLE_DESC_LEN);
state->exit_latency = 1;
state->target_residency = 1 * 2;
state->power_usage = 3;
state->flags = 0;
state->flags |= CPUIDLE_FLAG_TIME_VALID;
dev->safe_state = state;
dev->state_count = i;
if (shmobile_cpuidle_setup) if (shmobile_cpuidle_setup)
shmobile_cpuidle_setup(dev); shmobile_cpuidle_setup(drv);
cpuidle_register_driver(drv);
dev->state_count = drv->state_count;
cpuidle_register_device(dev); cpuidle_register_device(dev);
return 0; return 0;

View File

@ -9,9 +9,9 @@ extern int clk_init(void);
extern void shmobile_handle_irq_intc(struct pt_regs *); extern void shmobile_handle_irq_intc(struct pt_regs *);
extern void shmobile_handle_irq_gic(struct pt_regs *); extern void shmobile_handle_irq_gic(struct pt_regs *);
extern struct platform_suspend_ops shmobile_suspend_ops; extern struct platform_suspend_ops shmobile_suspend_ops;
struct cpuidle_device; struct cpuidle_driver;
extern void (*shmobile_cpuidle_modes[])(void); extern void (*shmobile_cpuidle_modes[])(void);
extern void (*shmobile_cpuidle_setup)(struct cpuidle_device *dev); extern void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
extern void sh7367_init_irq(void); extern void sh7367_init_irq(void);
extern void sh7367_add_early_devices(void); extern void sh7367_add_early_devices(void);

View File

@ -402,22 +402,18 @@ static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2)
#ifdef CONFIG_CPU_IDLE #ifdef CONFIG_CPU_IDLE
static void sh7372_cpuidle_setup(struct cpuidle_device *dev) static void sh7372_cpuidle_setup(struct cpuidle_driver *drv)
{ {
struct cpuidle_state *state; struct cpuidle_state *state = &drv->states[drv->state_count];
int i = dev->state_count;
state = &dev->states[i];
snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN); strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN);
state->exit_latency = 10; state->exit_latency = 10;
state->target_residency = 20 + 10; state->target_residency = 20 + 10;
state->power_usage = 1; /* perhaps not */ state->flags = CPUIDLE_FLAG_TIME_VALID;
state->flags = 0; shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_core_standby;
state->flags |= CPUIDLE_FLAG_TIME_VALID;
shmobile_cpuidle_modes[i] = sh7372_enter_core_standby;
dev->state_count = i + 1; drv->state_count++;
} }
static void sh7372_cpuidle_init(void) static void sh7372_cpuidle_init(void)