[PATCH 2/4] OMAP3: cpuidle: re-organize the C-states data
Kevin Hilman
khilman at ti.com
Thu May 5 13:55:52 EDT 2011
Hi Jean,
jean.pihet at newoldbits.com writes:
> From: Jean Pihet <j-pihet at ti.com>
>
> The current implementation defines an internal structure and a
> C-states array. Using those structures is redundant to the
> structs used by the cpuidle framework.
>
> This patch provides a clean-up of the internal struct, removes the
> internal C-states array, stores the data using the existing cpuidle
> per C-state struct and registers the mach specific data to cpuidle
> C-state driver_data (accessed using cpuidle_[gs]et_statedata).
> Also removes unused macros, fields and code and compacts the repeating
> code using an inline helper function.
>
> The result is more compact and more readable code as well as
> reduced data RAM usage.
>
> Signed-off-by: Jean Pihet <j-pihet at ti.com>
Some minor comments below...
> ---
> arch/arm/mach-omap2/cpuidle34xx.c | 291 ++++++++++++------------------------
> 1 files changed, 97 insertions(+), 194 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
> index d7bc31a..816b483 100644
> --- a/arch/arm/mach-omap2/cpuidle34xx.c
> +++ b/arch/arm/mach-omap2/cpuidle34xx.c
> @@ -36,34 +36,19 @@
>
> #ifdef CONFIG_CPU_IDLE
>
> -#define OMAP3_MAX_STATES 7
> -#define OMAP3_STATE_C1 0 /* C1 - MPU WFI + Core active */
> -#define OMAP3_STATE_C2 1 /* C2 - MPU WFI + Core inactive */
> -#define OMAP3_STATE_C3 2 /* C3 - MPU CSWR + Core inactive */
> -#define OMAP3_STATE_C4 3 /* C4 - MPU OFF + Core iactive */
> -#define OMAP3_STATE_C5 4 /* C5 - MPU RET + Core RET */
> -#define OMAP3_STATE_C6 5 /* C6 - MPU OFF + Core RET */
> -#define OMAP3_STATE_C7 6 /* C7 - MPU OFF + Core OFF */
> +#define OMAP3_STATE_MIN 0
> +#define OMAP3_STATE_MAX 6 /* Deepest sleep C-state */
> +#define OMAP3_NB_STATES (OMAP3_STATE_MAX + 1)
How about droping MIN and MAX all together. Min is always zero, just
use zero in the code.
Then later,
static struct cpuidle_params cpuidle_params_table[] = {
/* C1 */
{2 + 2, 5, 1},
...
};
#define OMAP3_NUM_STATES ARRAY_SIZE(cpuidle_params_table);
This way is less error prone, since when adding/removing states, you
don't also have to manually update NUM_STATES.
> -#define OMAP3_STATE_MAX OMAP3_STATE_C7
> -
> -#define CPUIDLE_FLAG_CHECK_BM 0x10000 /* use omap3_enter_idle_bm() */
> -
> -struct omap3_processor_cx {
> - u8 valid;
> - u8 type;
> - u32 exit_latency;
> +/* Mach specific information to be recorded in the C-state driver_data */
> +struct omap3_idle_statedata {
> u32 mpu_state;
> u32 core_state;
> - u32 target_residency;
> - u32 flags;
> - const char *desc;
> + u8 valid;
> };
> +struct omap3_idle_statedata omap3_idle_data[OMAP3_NB_STATES];
> -struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES];
> -struct omap3_processor_cx current_cx_state;
> -struct powerdomain *mpu_pd, *core_pd, *per_pd;
> -struct powerdomain *cam_pd;
> +struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
>
> /*
> * The latencies/thresholds for various C states have
> @@ -72,7 +57,7 @@ struct powerdomain *cam_pd;
> * the best power savings) used on boards which do not
> * pass these details from the board file.
> */
> -static struct cpuidle_params cpuidle_params_table[] = {
> +static struct cpuidle_params cpuidle_params_table[OMAP3_NB_STATES] = {
> /* C1 */
> {2 + 2, 5, 1},
> /* C2 */
> @@ -121,12 +106,10 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
> static int omap3_enter_idle(struct cpuidle_device *dev,
> struct cpuidle_state *state)
> {
> - struct omap3_processor_cx *cx = cpuidle_get_statedata(state);
> + struct omap3_idle_statedata *cx = cpuidle_get_statedata(state);
> struct timespec ts_preidle, ts_postidle, ts_idle;
> u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
>
> - current_cx_state = *cx;
> -
> /* Used to keep track of the total time in idle */
> getnstimeofday(&ts_preidle);
>
> @@ -139,7 +122,8 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
> if (omap_irq_pending() || need_resched())
> goto return_sleep_time;
>
> - if (cx->type == OMAP3_STATE_C1) {
> + /* Deny idle for C1 */
> + if (state == &dev->states[0]) {
> pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
> pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
> }
> @@ -147,7 +131,8 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
> /* Execute ARM wfi */
> omap_sram_idle();
>
> - if (cx->type == OMAP3_STATE_C1) {
> + /* Re-allow idle for C1 */
> + if (state == &dev->states[0]) {
> pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
> pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
> }
> @@ -169,15 +154,15 @@ return_sleep_time:
> *
> * If the current state is valid, it is returned back to the caller.
> * Else, this function searches for a lower c-state which is still
> - * valid (as defined in omap3_power_states[]).
> + * valid.
> */
> static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
> - struct cpuidle_state *curr)
> + struct cpuidle_state *curr)
> {
> struct cpuidle_state *next = NULL;
> - struct omap3_processor_cx *cx;
> + struct omap3_idle_statedata *cx;
>
> - cx = (struct omap3_processor_cx *)cpuidle_get_statedata(curr);
> + cx = cpuidle_get_statedata(curr);
>
> /* Check if current state is valid */
> if (cx->valid) {
> @@ -188,7 +173,7 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
> /*
> * Reach the current state starting at highest C-state
> */
> - for (; idx >= OMAP3_STATE_C1; idx--) {
> + for (; idx >= OMAP3_STATE_MIN; idx--) {
> if (&dev->states[idx] == curr) {
> next = &dev->states[idx];
> break;
> @@ -205,9 +190,7 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
> * Start search from the next (lower) state.
> */
> idx--;
> - for (; idx >= OMAP3_STATE_C1; idx--) {
> - struct omap3_processor_cx *cx;
> -
> + for (; idx >= OMAP3_STATE_MIN; idx--) {
> cx = cpuidle_get_statedata(&dev->states[idx]);
> if (cx->valid) {
> next = &dev->states[idx];
> @@ -228,9 +211,8 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
> * @dev: cpuidle device
> * @state: The target state to be programmed
> *
> - * Used for C states with CPUIDLE_FLAG_CHECK_BM flag set. This
> - * function checks for any pending activity and then programs the
> - * device to the specified or a safer state.
> + * This function checks for any pending activity and then programs
> + * the device to the specified or a safer state.
> */
> static int omap3_enter_idle_bm(struct cpuidle_device *dev,
> struct cpuidle_state *state)
> @@ -238,10 +220,10 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
> struct cpuidle_state *new_state = next_valid_state(dev, state);
> u32 core_next_state, per_next_state = 0, per_saved_state = 0;
> u32 cam_state;
> - struct omap3_processor_cx *cx;
> + struct omap3_idle_statedata *cx;
> int ret;
>
> - if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap3_idle_bm_check()) {
> + if (omap3_idle_bm_check()) {
> BUG_ON(!dev->safe_state);
> new_state = dev->safe_state;
> goto select_state;
> @@ -307,8 +289,8 @@ void omap3_cpuidle_update_states(u32 mpu_deepest_state, u32 core_deepest_state)
> {
> int i;
>
> - for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) {
> - struct omap3_processor_cx *cx = &omap3_power_states[i];
> + for (i = OMAP3_STATE_MIN; i < OMAP3_NB_STATES; i++) {
> + struct omap3_idle_statedata *cx = &omap3_idle_data[i];
>
> if ((cx->mpu_state >= mpu_deepest_state) &&
> (cx->core_state >= core_deepest_state)) {
> @@ -326,9 +308,8 @@ void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params)
> if (!cpuidle_board_params)
> return;
>
> - for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) {
> - cpuidle_params_table[i].valid =
> - cpuidle_board_params[i].valid;
> + for (i = OMAP3_STATE_MIN; i < OMAP3_NB_STATES; i++) {
> + cpuidle_params_table[i].valid = cpuidle_board_params[i].valid;
> cpuidle_params_table[i].exit_latency =
> cpuidle_board_params[i].exit_latency;
> cpuidle_params_table[i].target_residency =
> @@ -337,134 +318,30 @@ void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params)
> return;
> }
>
> -/* omap3_init_power_states - Initialises the OMAP3 specific C states.
> - *
> - * Below is the desciption of each C state.
> - * C1 . MPU WFI + Core active
> - * C2 . MPU WFI + Core inactive
> - * C3 . MPU CSWR + Core inactive
> - * C4 . MPU OFF + Core inactive
> - * C5 . MPU CSWR + Core CSWR
> - * C6 . MPU OFF + Core CSWR
> - * C7 . MPU OFF + Core OFF
> - */
> -void omap_init_power_states(void)
> -{
> - /* C1 . MPU WFI + Core active */
> - omap3_power_states[OMAP3_STATE_C1].valid =
> - cpuidle_params_table[OMAP3_STATE_C1].valid;
> - omap3_power_states[OMAP3_STATE_C1].type = OMAP3_STATE_C1;
> - omap3_power_states[OMAP3_STATE_C1].exit_latency =
> - cpuidle_params_table[OMAP3_STATE_C1].exit_latency;
> - omap3_power_states[OMAP3_STATE_C1].target_residency =
> - cpuidle_params_table[OMAP3_STATE_C1].target_residency;
> - omap3_power_states[OMAP3_STATE_C1].mpu_state = PWRDM_POWER_ON;
> - omap3_power_states[OMAP3_STATE_C1].core_state = PWRDM_POWER_ON;
> - omap3_power_states[OMAP3_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID;
> - omap3_power_states[OMAP3_STATE_C1].desc = "MPU ON + CORE ON";
> -
> - /* C2 . MPU WFI + Core inactive */
> - omap3_power_states[OMAP3_STATE_C2].valid =
> - cpuidle_params_table[OMAP3_STATE_C2].valid;
> - omap3_power_states[OMAP3_STATE_C2].type = OMAP3_STATE_C2;
> - omap3_power_states[OMAP3_STATE_C2].exit_latency =
> - cpuidle_params_table[OMAP3_STATE_C2].exit_latency;
> - omap3_power_states[OMAP3_STATE_C2].target_residency =
> - cpuidle_params_table[OMAP3_STATE_C2].target_residency;
> - omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
> - omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
> - omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
> - CPUIDLE_FLAG_CHECK_BM;
> - omap3_power_states[OMAP3_STATE_C2].desc = "MPU ON + CORE ON";
> -
> - /* C3 . MPU CSWR + Core inactive */
> - omap3_power_states[OMAP3_STATE_C3].valid =
> - cpuidle_params_table[OMAP3_STATE_C3].valid;
> - omap3_power_states[OMAP3_STATE_C3].type = OMAP3_STATE_C3;
> - omap3_power_states[OMAP3_STATE_C3].exit_latency =
> - cpuidle_params_table[OMAP3_STATE_C3].exit_latency;
> - omap3_power_states[OMAP3_STATE_C3].target_residency =
> - cpuidle_params_table[OMAP3_STATE_C3].target_residency;
> - omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET;
> - omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON;
> - omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
> - CPUIDLE_FLAG_CHECK_BM;
> - omap3_power_states[OMAP3_STATE_C3].desc = "MPU RET + CORE ON";
> -
> - /* C4 . MPU OFF + Core inactive */
> - omap3_power_states[OMAP3_STATE_C4].valid =
> - cpuidle_params_table[OMAP3_STATE_C4].valid;
> - omap3_power_states[OMAP3_STATE_C4].type = OMAP3_STATE_C4;
> - omap3_power_states[OMAP3_STATE_C4].exit_latency =
> - cpuidle_params_table[OMAP3_STATE_C4].exit_latency;
> - omap3_power_states[OMAP3_STATE_C4].target_residency =
> - cpuidle_params_table[OMAP3_STATE_C4].target_residency;
> - omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF;
> - omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON;
> - omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
> - CPUIDLE_FLAG_CHECK_BM;
> - omap3_power_states[OMAP3_STATE_C4].desc = "MPU OFF + CORE ON";
> -
> - /* C5 . MPU CSWR + Core CSWR*/
> - omap3_power_states[OMAP3_STATE_C5].valid =
> - cpuidle_params_table[OMAP3_STATE_C5].valid;
> - omap3_power_states[OMAP3_STATE_C5].type = OMAP3_STATE_C5;
> - omap3_power_states[OMAP3_STATE_C5].exit_latency =
> - cpuidle_params_table[OMAP3_STATE_C5].exit_latency;
> - omap3_power_states[OMAP3_STATE_C5].target_residency =
> - cpuidle_params_table[OMAP3_STATE_C5].target_residency;
> - omap3_power_states[OMAP3_STATE_C5].mpu_state = PWRDM_POWER_RET;
> - omap3_power_states[OMAP3_STATE_C5].core_state = PWRDM_POWER_RET;
> - omap3_power_states[OMAP3_STATE_C5].flags = CPUIDLE_FLAG_TIME_VALID |
> - CPUIDLE_FLAG_CHECK_BM;
> - omap3_power_states[OMAP3_STATE_C5].desc = "MPU RET + CORE RET";
> -
> - /* C6 . MPU OFF + Core CSWR */
> - omap3_power_states[OMAP3_STATE_C6].valid =
> - cpuidle_params_table[OMAP3_STATE_C6].valid;
> - omap3_power_states[OMAP3_STATE_C6].type = OMAP3_STATE_C6;
> - omap3_power_states[OMAP3_STATE_C6].exit_latency =
> - cpuidle_params_table[OMAP3_STATE_C6].exit_latency;
> - omap3_power_states[OMAP3_STATE_C6].target_residency =
> - cpuidle_params_table[OMAP3_STATE_C6].target_residency;
> - omap3_power_states[OMAP3_STATE_C6].mpu_state = PWRDM_POWER_OFF;
> - omap3_power_states[OMAP3_STATE_C6].core_state = PWRDM_POWER_RET;
> - omap3_power_states[OMAP3_STATE_C6].flags = CPUIDLE_FLAG_TIME_VALID |
> - CPUIDLE_FLAG_CHECK_BM;
> - omap3_power_states[OMAP3_STATE_C6].desc = "MPU OFF + CORE RET";
> -
> - /* C7 . MPU OFF + Core OFF */
> - omap3_power_states[OMAP3_STATE_C7].valid =
> - cpuidle_params_table[OMAP3_STATE_C7].valid;
> - omap3_power_states[OMAP3_STATE_C7].type = OMAP3_STATE_C7;
> - omap3_power_states[OMAP3_STATE_C7].exit_latency =
> - cpuidle_params_table[OMAP3_STATE_C7].exit_latency;
> - omap3_power_states[OMAP3_STATE_C7].target_residency =
> - cpuidle_params_table[OMAP3_STATE_C7].target_residency;
> - omap3_power_states[OMAP3_STATE_C7].mpu_state = PWRDM_POWER_OFF;
> - omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF;
> - omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID |
> - CPUIDLE_FLAG_CHECK_BM;
> - omap3_power_states[OMAP3_STATE_C7].desc = "MPU OFF + CORE OFF";
> -
> - /*
> - * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
> - * enable OFF mode in a stable form for previous revisions.
> - * we disable C7 state as a result.
> - */
> - if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) {
> - omap3_power_states[OMAP3_STATE_C7].valid = 0;
> - cpuidle_params_table[OMAP3_STATE_C7].valid = 0;
> - pr_warn("%s: core off state C7 disabled due to i583\n",
> - __func__);
> - }
> -}
> -
> struct cpuidle_driver omap3_idle_driver = {
> .name = "omap3_idle",
> .owner = THIS_MODULE,
> };
>
> +/* Fill in the state data from the mach tables and register the driver_data */
> +static inline struct omap3_idle_statedata *fill_in_cstates_data(int idx,
Please prefix internal function helper with '_'. Also, _data suffix
isn't really needed. How about simply _fill_state()
> + const char *descr,
> + struct cpuidle_state *state)
> +{
> + struct omap3_idle_statedata *data = &omap3_idle_data[idx];
Minor: please name this 'cx' to be consistent with other usage in this
file.
Also, I think this function should take 'struct cpuidle_device *dev'
instead of 'struct cpuidle_state', and here it should do
struct cpuidle_state *state = dev->states[idx]
IOW
static inline
struct omap3_idle_statedata *_fill_state(struct cpuidle_device *dev,
int idx, const char *desc);
> + state->exit_latency = cpuidle_params_table[idx].exit_latency;
> + state->target_residency = cpuidle_params_table[idx].target_residency;
> + state->flags = CPUIDLE_FLAG_TIME_VALID;
> + state->enter = omap3_enter_idle_bm;
> + data->valid = cpuidle_params_table[idx].valid;
> + sprintf(state->name, "C%d", idx + 1);
> + strncpy(state->desc, descr, CPUIDLE_DESC_LEN);
> + cpuidle_set_statedata(state, data);
> +
> + return data;
> +}
> +
> /**
> * omap3_idle_init - Init routine for OMAP3 idle
> *
> @@ -473,43 +350,69 @@ struct cpuidle_driver omap3_idle_driver = {
> */
> int __init omap3_idle_init(void)
> {
> - int i, count = 0;
> - struct omap3_processor_cx *cx;
> struct cpuidle_state *state;
> struct cpuidle_device *dev;
> + struct omap3_idle_statedata *data;
same here, please name this 'cx'
> mpu_pd = pwrdm_lookup("mpu_pwrdm");
> core_pd = pwrdm_lookup("core_pwrdm");
> per_pd = pwrdm_lookup("per_pwrdm");
> cam_pd = pwrdm_lookup("cam_pwrdm");
>
> - omap_init_power_states();
> cpuidle_register_driver(&omap3_idle_driver);
> -
> dev = &per_cpu(omap3_idle_dev, smp_processor_id());
>
> - for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) {
> - cx = &omap3_power_states[i];
> - state = &dev->states[count];
> -
> - if (!cx->valid)
> - continue;
> - cpuidle_set_statedata(state, cx);
> - state->exit_latency = cx->exit_latency;
> - state->target_residency = cx->target_residency;
> - state->flags = cx->flags;
> - state->enter = (state->flags & CPUIDLE_FLAG_CHECK_BM) ?
> - omap3_enter_idle_bm : omap3_enter_idle;
> - if (cx->type == OMAP3_STATE_C1)
> - dev->safe_state = state;
> - sprintf(state->name, "C%d", count+1);
> - strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
> - count++;
> + /* C1 . MPU WFI + Core active */
> + state = &dev->states[0];
> + data = fill_in_cstates_data(0, "MPU ON + CORE ON", state);
> + state->enter = omap3_enter_idle;
> + dev->safe_state = state;
> + data->valid = 1; /* C1 is always valid */
> + data->mpu_state = PWRDM_POWER_ON;
> + data->core_state = PWRDM_POWER_ON;
> +
> + /* C2 . MPU WFI + Core inactive */
> + data = fill_in_cstates_data(1, "MPU ON + CORE ON", &dev->states[1]);
> + data->valid = 1; /* C2 is always valid */
Why?
> + data->mpu_state = PWRDM_POWER_ON;
> + data->core_state = PWRDM_POWER_ON;
> +
> + /* C3 . MPU CSWR + Core inactive */
> + data = fill_in_cstates_data(2, "MPU RET + CORE ON", &dev->states[2]);
> + data->mpu_state = PWRDM_POWER_RET;
> + data->core_state = PWRDM_POWER_ON;
> +
> + /* C4 . MPU OFF + Core inactive */
> + data = fill_in_cstates_data(3, "MPU OFF + CORE ON", &dev->states[3]);
> + data->mpu_state = PWRDM_POWER_OFF;
> + data->core_state = PWRDM_POWER_ON;
> +
> + /* C5 . MPU RET + Core RET */
> + data = fill_in_cstates_data(4, "MPU RET + CORE RET", &dev->states[4]);
> + data->mpu_state = PWRDM_POWER_RET;
> + data->core_state = PWRDM_POWER_RET;
> +
> + /* C6 . MPU OFF + Core RET */
> + data = fill_in_cstates_data(5, "MPU OFF + CORE RET", &dev->states[5]);
> + data->mpu_state = PWRDM_POWER_OFF;
> + data->core_state = PWRDM_POWER_RET;
> +
> + /* C7 . MPU OFF + Core OFF */
> + data = fill_in_cstates_data(6, "MPU OFF + CORE OFF", &dev->states[6]);
> + /*
> + * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
> + * enable OFF mode in a stable form for previous revisions.
> + * We disable C7 state as a result.
> + */
> + if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) {
> + data->valid = 0;
> + pr_warn("%s: core off state C7 disabled due to i583\n",
> + __func__);
> }
> + data->mpu_state = PWRDM_POWER_OFF;
> + data->core_state = PWRDM_POWER_OFF;
>
> - if (!count)
> - return -EINVAL;
> - dev->state_count = count;
> + dev->state_count = OMAP3_NB_STATES;
>
> if (enable_off_mode)
> omap3_cpuidle_update_states(PWRDM_POWER_OFF, PWRDM_POWER_OFF);
Kevin
More information about the linux-arm-kernel
mailing list