From b1beab48f6148d50fee4a56d741cc3168fe1b995 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 31 Jan 2013 19:55:37 -0500 Subject: [PATCH 1/5] intel_idle: stop using driver_data for static flags The commit, 4202735e8ab6ecfb0381631a0d0b58fefe0bd4e2 (cpuidle: Split cpuidle_state structure and move per-cpu statistics fields) observed that the MWAIT flags for Cn on every processor to date were the same, and created get_driver_data() to supply them. Unfortunately, that assumption is false, going forward. So here we restore the MWAIT flags to the cpuidle_state table. However, instead restoring the old "driver_data" field, we put the flags into the existing "flags" field, where they probalby should have lived all along. This patch does not change any operation. This patch removes 1 of the 3 users of cpuidle_state_usage.driver_data. Perhaps some day we'll get rid of the other 2. Signed-off-by: Len Brown --- drivers/idle/intel_idle.c | 75 ++++++++++++++------------------------- 1 file changed, 26 insertions(+), 49 deletions(-) diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 2df9414a72f7..b2cf489ba3e1 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -108,6 +108,16 @@ static struct cpuidle_state *cpuidle_state_table; */ #define CPUIDLE_FLAG_TLB_FLUSHED 0x10000 +/* + * MWAIT takes an 8-bit "hint" in EAX "suggesting" + * the C-state (top nibble) and sub-state (bottom nibble) + * 0x00 means "MWAIT(C1)", 0x10 means "MWAIT(C2)" etc. + * + * We store the hint at the top of our "flags" for each state. + */ +#define flg2MWAIT(flags) (((flags) >> 24) & 0xFF) +#define MWAIT2flg(eax) ((eax & 0xFF) << 24) + /* * States are indexed by the cstate number, * which is also the index into the MWAIT hint array. @@ -118,21 +128,21 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = { { /* MWAIT C1 */ .name = "C1-NHM", .desc = "MWAIT 0x00", - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, .exit_latency = 3, .target_residency = 6, .enter = &intel_idle }, { /* MWAIT C2 */ .name = "C3-NHM", .desc = "MWAIT 0x10", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 20, .target_residency = 80, .enter = &intel_idle }, { /* MWAIT C3 */ .name = "C6-NHM", .desc = "MWAIT 0x20", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 200, .target_residency = 800, .enter = &intel_idle }, @@ -143,28 +153,28 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = { { /* MWAIT C1 */ .name = "C1-SNB", .desc = "MWAIT 0x00", - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, .exit_latency = 1, .target_residency = 1, .enter = &intel_idle }, { /* MWAIT C2 */ .name = "C3-SNB", .desc = "MWAIT 0x10", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 80, .target_residency = 211, .enter = &intel_idle }, { /* MWAIT C3 */ .name = "C6-SNB", .desc = "MWAIT 0x20", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 104, .target_residency = 345, .enter = &intel_idle }, { /* MWAIT C4 */ .name = "C7-SNB", .desc = "MWAIT 0x30", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 109, .target_residency = 345, .enter = &intel_idle }, @@ -175,28 +185,28 @@ static struct cpuidle_state ivb_cstates[MWAIT_MAX_NUM_CSTATES] = { { /* MWAIT C1 */ .name = "C1-IVB", .desc = "MWAIT 0x00", - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, .exit_latency = 1, .target_residency = 1, .enter = &intel_idle }, { /* MWAIT C2 */ .name = "C3-IVB", .desc = "MWAIT 0x10", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 59, .target_residency = 156, .enter = &intel_idle }, { /* MWAIT C3 */ .name = "C6-IVB", .desc = "MWAIT 0x20", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 80, .target_residency = 300, .enter = &intel_idle }, { /* MWAIT C4 */ .name = "C7-IVB", .desc = "MWAIT 0x30", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 87, .target_residency = 300, .enter = &intel_idle }, @@ -207,14 +217,14 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { { /* MWAIT C1 */ .name = "C1-ATM", .desc = "MWAIT 0x00", - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, .exit_latency = 1, .target_residency = 4, .enter = &intel_idle }, { /* MWAIT C2 */ .name = "C2-ATM", .desc = "MWAIT 0x10", - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID, .exit_latency = 20, .target_residency = 80, .enter = &intel_idle }, @@ -222,7 +232,7 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { { /* MWAIT C4 */ .name = "C4-ATM", .desc = "MWAIT 0x30", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 100, .target_residency = 400, .enter = &intel_idle }, @@ -230,41 +240,12 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { { /* MWAIT C6 */ .name = "C6-ATM", .desc = "MWAIT 0x52", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 140, .target_residency = 560, .enter = &intel_idle }, }; -static long get_driver_data(int cstate) -{ - int driver_data; - switch (cstate) { - - case 1: /* MWAIT C1 */ - driver_data = 0x00; - break; - case 2: /* MWAIT C2 */ - driver_data = 0x10; - break; - case 3: /* MWAIT C3 */ - driver_data = 0x20; - break; - case 4: /* MWAIT C4 */ - driver_data = 0x30; - break; - case 5: /* MWAIT C5 */ - driver_data = 0x40; - break; - case 6: /* MWAIT C6 */ - driver_data = 0x52; - break; - default: - driver_data = 0x00; - } - return driver_data; -} - /** * intel_idle * @dev: cpuidle_device @@ -278,8 +259,7 @@ static int intel_idle(struct cpuidle_device *dev, { unsigned long ecx = 1; /* break on interrupt flag */ struct cpuidle_state *state = &drv->states[index]; - struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; - unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage); + unsigned long eax = flg2MWAIT(state->flags); unsigned int cstate; int cpu = smp_processor_id(); @@ -558,9 +538,6 @@ static int intel_idle_cpu_init(int cpu) if (cpuidle_state_table[cstate].enter == NULL) continue; - dev->states_usage[dev->state_count].driver_data = - (void *)get_driver_data(cstate); - dev->state_count += 1; } From 5af4a21c6efd270a334202fb1fc4a347ea4624e3 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 4 Feb 2013 12:01:41 +0000 Subject: [PATCH 2/5] Replace the flag by a simple global boolean in the cpuidle.c. That will allow to cleanup the rest of the code right after, because the ops won't make sense. Signed-off-by: Daniel Lezcano Acked-by: Sekhar Nori Signed-off-by: Len Brown --- arch/arm/mach-davinci/cpuidle.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index 9107691adbdb..5fbd470d46ca 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -26,8 +26,8 @@ #define DAVINCI_CPUIDLE_MAX_STATES 2 struct davinci_ops { - void (*enter) (u32 flags); - void (*exit) (u32 flags); + void (*enter) (void); + void (*exit) (void); u32 flags; }; @@ -40,20 +40,17 @@ static int davinci_enter_idle(struct cpuidle_device *dev, struct davinci_ops *ops = cpuidle_get_statedata(state_usage); if (ops && ops->enter) - ops->enter(ops->flags); + ops->enter(); index = cpuidle_wrap_enter(dev, drv, index, arm_cpuidle_simple_enter); if (ops && ops->exit) - ops->exit(ops->flags); + ops->exit(); return index; } -/* fields in davinci_ops.flags */ -#define DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN BIT(0) - static struct cpuidle_driver davinci_idle_driver = { .name = "cpuidle-davinci", .owner = THIS_MODULE, @@ -72,6 +69,7 @@ static struct cpuidle_driver davinci_idle_driver = { static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device); static void __iomem *ddr2_reg_base; +static bool ddr2_pdown; static void davinci_save_ddr_power(int enter, bool pdown) { @@ -92,14 +90,14 @@ static void davinci_save_ddr_power(int enter, bool pdown) __raw_writel(val, ddr2_reg_base + DDR2_SDRCR_OFFSET); } -static void davinci_c2state_enter(u32 flags) +static void davinci_c2state_enter(void) { - davinci_save_ddr_power(1, !!(flags & DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN)); + davinci_save_ddr_power(1, ddr2_pdown); } -static void davinci_c2state_exit(u32 flags) +static void davinci_c2state_exit(void) { - davinci_save_ddr_power(0, !!(flags & DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN)); + davinci_save_ddr_power(0, ddr2_pdown); } static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { @@ -124,8 +122,7 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev) ddr2_reg_base = pdata->ddr2_ctlr_base; - if (pdata->ddr2_pdown) - davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN; + ddr2_pdown = pdata->ddr2_pdown; cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]); device->state_count = DAVINCI_CPUIDLE_MAX_STATES; From 8d60143a2367616a9d4f7c11656ade8521eb1874 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 4 Feb 2013 12:01:42 +0000 Subject: [PATCH 3/5] davinci: cpuidle - move code to prevent forward declaration The patch is mindless, it just moves the idle function below in the file in order to prevent forward declaration in the next patch. Signed-off-by: Daniel Lezcano Acked-by: Sekhar Nori Signed-off-by: Len Brown --- arch/arm/mach-davinci/cpuidle.c | 72 ++++++++++++++++----------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index 5fbd470d46ca..697febe5a8e5 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -31,42 +31,6 @@ struct davinci_ops { u32 flags; }; -/* Actual code that puts the SoC in different idle states */ -static int davinci_enter_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) -{ - struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; - struct davinci_ops *ops = cpuidle_get_statedata(state_usage); - - if (ops && ops->enter) - ops->enter(); - - index = cpuidle_wrap_enter(dev, drv, index, - arm_cpuidle_simple_enter); - - if (ops && ops->exit) - ops->exit(); - - return index; -} - -static struct cpuidle_driver davinci_idle_driver = { - .name = "cpuidle-davinci", - .owner = THIS_MODULE, - .en_core_tk_irqen = 1, - .states[0] = ARM_CPUIDLE_WFI_STATE, - .states[1] = { - .enter = davinci_enter_idle, - .exit_latency = 10, - .target_residency = 100000, - .flags = CPUIDLE_FLAG_TIME_VALID, - .name = "DDR SR", - .desc = "WFI and DDR Self Refresh", - }, - .state_count = DAVINCI_CPUIDLE_MAX_STATES, -}; - static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device); static void __iomem *ddr2_reg_base; static bool ddr2_pdown; @@ -107,6 +71,42 @@ 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_driver *drv, + int index) +{ + struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; + struct davinci_ops *ops = cpuidle_get_statedata(state_usage); + + if (ops && ops->enter) + ops->enter(); + + index = cpuidle_wrap_enter(dev, drv, index, + arm_cpuidle_simple_enter); + + if (ops && ops->exit) + ops->exit(); + + return index; +} + +static struct cpuidle_driver davinci_idle_driver = { + .name = "cpuidle-davinci", + .owner = THIS_MODULE, + .en_core_tk_irqen = 1, + .states[0] = ARM_CPUIDLE_WFI_STATE, + .states[1] = { + .enter = davinci_enter_idle, + .exit_latency = 10, + .target_residency = 100000, + .flags = CPUIDLE_FLAG_TIME_VALID, + .name = "DDR SR", + .desc = "WFI and DDR Self Refresh", + }, + .state_count = DAVINCI_CPUIDLE_MAX_STATES, +}; + static int __init davinci_cpuidle_probe(struct platform_device *pdev) { int ret; From 36ce8d4f5fecc20c2dfb08f24fe01c5eb81f6245 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 4 Feb 2013 12:01:43 +0000 Subject: [PATCH 4/5] davinci: cpuidle - remove the ops With one function handling the idle state and a single variable, the usage of the davinci_ops is overkill. This patch removes these ops and simplify the code. Furthermore, the 'driver_data' field is no longer used, we have 1 of the 3 remaining user of this field removed. Signed-off-by: Daniel Lezcano Acked-by: Sekhar Nori Signed-off-by: Len Brown --- arch/arm/mach-davinci/cpuidle.c | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index 697febe5a8e5..5e430bffb5d8 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -25,12 +25,6 @@ #define DAVINCI_CPUIDLE_MAX_STATES 2 -struct davinci_ops { - void (*enter) (void); - void (*exit) (void); - u32 flags; -}; - static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device); static void __iomem *ddr2_reg_base; static bool ddr2_pdown; @@ -54,39 +48,17 @@ static void davinci_save_ddr_power(int enter, bool pdown) __raw_writel(val, ddr2_reg_base + DDR2_SDRCR_OFFSET); } -static void davinci_c2state_enter(void) -{ - davinci_save_ddr_power(1, ddr2_pdown); -} - -static void davinci_c2state_exit(void) -{ - davinci_save_ddr_power(0, ddr2_pdown); -} - -static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { - [1] = { - .enter = davinci_c2state_enter, - .exit = davinci_c2state_exit, - }, -}; - /* Actual code that puts the SoC in different idle states */ static int davinci_enter_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; - struct davinci_ops *ops = cpuidle_get_statedata(state_usage); - - if (ops && ops->enter) - ops->enter(); + davinci_save_ddr_power(1, ddr2_pdown); index = cpuidle_wrap_enter(dev, drv, index, arm_cpuidle_simple_enter); - if (ops && ops->exit) - ops->exit(); + davinci_save_ddr_power(0, ddr2_pdown); return index; } @@ -123,7 +95,6 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev) ddr2_reg_base = pdata->ddr2_ctlr_base; ddr2_pdown = pdata->ddr2_pdown; - cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]); device->state_count = DAVINCI_CPUIDLE_MAX_STATES; From 748f11772154b58426c856b7d90538a9b60ae29a Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 4 Feb 2013 12:01:44 +0000 Subject: [PATCH 5/5] davinci: cpuidle - remove useless initialization The device->state_count is initialized in the cpuidle_register_device function. Signed-off-by: Daniel Lezcano Acked-by: Sekhar Nori Signed-off-by: Len Brown --- arch/arm/mach-davinci/cpuidle.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index 5e430bffb5d8..5ac9e9384b15 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -96,8 +96,6 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev) ddr2_pdown = pdata->ddr2_pdown; - device->state_count = DAVINCI_CPUIDLE_MAX_STATES; - ret = cpuidle_register_driver(&davinci_idle_driver); if (ret) { dev_err(&pdev->dev, "failed to register driver\n");