From: robherring2@gmail.com (Rob Herring)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 1/7] cpuidle: Add common init interface and idle functionality
Date: Tue, 24 Jan 2012 08:36:52 -0600 [thread overview]
Message-ID: <4F1EC204.9020807@gmail.com> (raw)
In-Reply-To: <1327379854-12403-2-git-send-email-rob.lee@linaro.org>
On 01/23/2012 10:37 PM, Robert Lee wrote:
> The patch adds some cpuidle initialization functionality commonly
> duplicated by many platforms.
>
> Signed-off-by: Robert Lee <rob.lee@linaro.org>
A few cosmetic comments below, but otherwise looks good.
Reviewed-by: Rob Herring <rob.herring@calxeda.com>
> ---
> drivers/cpuidle/Makefile | 2 +-
> drivers/cpuidle/common.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/cpuidle.h | 24 +++++++
> 3 files changed, 177 insertions(+), 1 deletions(-)
> create mode 100644 drivers/cpuidle/common.c
>
> diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
> index 5634f88..2928d93 100644
> --- a/drivers/cpuidle/Makefile
> +++ b/drivers/cpuidle/Makefile
> @@ -2,4 +2,4 @@
> # Makefile for cpuidle.
> #
>
> -obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
> +obj-y += cpuidle.o driver.o governor.o sysfs.o common.o governors/
> diff --git a/drivers/cpuidle/common.c b/drivers/cpuidle/common.c
> new file mode 100644
> index 0000000..dafa758
> --- /dev/null
> +++ b/drivers/cpuidle/common.c
> @@ -0,0 +1,152 @@
> +/*
> + * Copyright 2011 Freescale Semiconductor, Inc.
> + * Copyright 2011 Linaro Ltd.
2012 now...
> + *
> + * 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
> + */
> +
> +/*
> + * This code performs provides some commonly used cpuidle setup functionality
> + * used by many ARM SoC platforms. Providing this functionality here
> + * reduces the duplication of this code for each ARM platform that uses it.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/io.h>
> +#include <linux/cpuidle.h>
> +#include <linux/hrtimer.h>
> +#include <linux/err.h>
> +#include <linux/slab.h>
> +#include <asm/proc-fns.h>
> +
> +static struct cpuidle_device __percpu * common_cpuidle_devices;
> +
> +static int (*do_idle[CPUIDLE_STATE_MAX])(struct cpuidle_device *dev,
> + struct cpuidle_driver *drv, int index);
> +
> +int cpuidle_def_idle(struct cpuidle_device *dev,
> + struct cpuidle_driver *drv, int index)
> +{
> + cpu_do_idle();
> + return index;
> +}
> +
> +static int simple_enter(struct cpuidle_device *dev,
> + struct cpuidle_driver *drv, int index)
> +{
> + ktime_t time_start, time_end;
> +
> + local_irq_disable();
> +
> + time_start = ktime_get();
> +
> + index = do_idle[index](dev, drv, index);
> +
> + time_end = ktime_get();
> +
> + local_irq_enable();
> +
> + dev->last_residency =
> + (int)ktime_to_us(ktime_sub(time_end, time_start));
> +
> + return index;
> +}
> +
> +void common_cpuidle_devices_uninit(void)
> +{
> + int cpu_id;
> + struct cpuidle_device *dev;
> +
> + for_each_possible_cpu(cpu_id) {
> + dev = per_cpu_ptr(common_cpuidle_devices, cpu_id);
> + cpuidle_unregister_device(dev);
> + }
> +
> + free_percpu(common_cpuidle_devices);
> +}
> +
> +/**
> + * common_cpuidle_init() - Provides some commonly used init functionality.
> + * @pdrv Pointer to your cpuidle_driver object.
> + * @simple Use the common simple_enter wrapper?
remove the ?
> + * @driver_data_init Pointer to your platform function to initialize your
> + * platform specific driver data. Use NULL if platform
> + * specific data is not needed.
> + *
> + * Common cpuidle init interface to provide common cpuidle functionality
> + * used by many platforms.
> + */
> +int __init common_cpuidle_init(struct cpuidle_driver *pdrv, bool simple,
> + void (*driver_data_init)(struct cpuidle_device *dev))
> +{
> + struct cpuidle_device *dev;
> + struct cpuidle_driver *drv;
> + int i, cpu_id, ret;
> +
> + if (!pdrv || pdrv->state_count > CPUIDLE_STATE_MAX) {
> + pr_err("%s: Invalid Input\n", __func__);
Using pr_fmt rather than function name is preferred.
> + return -EINVAL;
> + }
> +
> + drv = kmalloc(sizeof(struct cpuidle_driver), GFP_KERNEL);
> + if (!drv) {
> + pr_err("%s: no memory for cpuidle driver\n", __func__);
> + return -ENOMEM;
> + }
> +
> + *drv = *pdrv;
Perhaps a comment so it is clear you intend this to be struct copy.
> +
> + for (i = 0; simple && (i < drv->state_count); i++) {
> + do_idle[i] = drv->states[i].enter;
> + drv->states[i].enter = simple_enter;
> + }
> +
> + ret = cpuidle_register_driver(drv);
> + if (ret) {
> + pr_err("%s: Failed to register cpuidle driver\n", __func__);
> + goto free_drv;
> + }
> +
> + common_cpuidle_devices = alloc_percpu(struct cpuidle_device);
> + if (common_cpuidle_devices == NULL) {
> + ret = -ENOMEM;
> + goto unregister_drv;
> + }
> +
> + /* initialize state data for each cpuidle_device */
> + for_each_possible_cpu(cpu_id) {
> + dev = per_cpu_ptr(common_cpuidle_devices, cpu_id);
> + dev->cpu = cpu_id;
> + dev->state_count = drv->state_count;
> +
> + if (driver_data_init)
> + driver_data_init(dev);
> +
> + ret = cpuidle_register_device(dev);
> + if (ret) {
> + pr_err("%s: Failed to register cpu %u\n",
> + __func__, cpu_id);
> + goto uninit;
> + }
> + }
> +
> + return 0;
> +uninit:
> +
> + common_cpuidle_devices_uninit();
> +
> +unregister_drv:
> +
> + cpuidle_unregister_driver(drv);
> +
> +free_drv:
> +
> + kfree(drv);
> +
> + return ret;
Remove all the blank lines in the error handling.
> +}
> diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
> index 712abcc..2aa89db 100644
> --- a/include/linux/cpuidle.h
> +++ b/include/linux/cpuidle.h
> @@ -56,6 +56,16 @@ struct cpuidle_state {
>
> #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
>
> +/* Common ARM WFI state */
> +#define CPUIDLE_ARM_WFI_STATE {\
> + .enter = cpuidle_def_idle,\
> + .exit_latency = 2,\
> + .target_residency = 1,\
> + .flags = CPUIDLE_FLAG_TIME_VALID,\
> + .name = "WFI",\
> + .desc = "ARM core clock gating (WFI)",\
> +}
> +
> /**
> * cpuidle_get_statedata - retrieves private driver state data
> * @st_usage: the state usage statistics
> @@ -141,6 +151,13 @@ 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);
>
> +/* provide a default idle function */
> +extern int cpuidle_def_idle(struct cpuidle_device *dev,
> + struct cpuidle_driver *drv, int index);
> +extern int common_cpuidle_init(struct cpuidle_driver *drv, bool simple,
> + void (*driver_data_init)(struct cpuidle_device *dev));
> +extern void common_cpuidle_devices_uninit(void);
> +
> #else
> static inline void disable_cpuidle(void) { }
> static inline int cpuidle_idle_call(void) { return -ENODEV; }
> @@ -157,6 +174,13 @@ 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_def_idle(struct cpuidle_device *dev,
> + struct cpuidle_driver *drv, int index)
> +{return -ENODEV; }
> +static inline int common_cpuidle_init(struct cpuidle_driver *pdrv,
> + bool simple, void (*driver_data_init)(struct cpuidle_device *dev))
> +{return -ENODEV; }
> +static inline void common_cpuidle_devices_uninit(void) { }
>
> #endif
>
next prev parent reply other threads:[~2012-01-24 14:36 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-24 4:37 [PATCH v3 0/7] Add common cpuidle code for consolidation Robert Lee
2012-01-24 4:37 ` [PATCH v3 1/7] cpuidle: Add common init interface and idle functionality Robert Lee
2012-01-24 14:36 ` Rob Herring [this message]
2012-01-24 22:43 ` Rob Lee
2012-01-24 20:16 ` Kevin Hilman
2012-01-24 23:10 ` Rob Lee
2012-01-24 23:46 ` Turquette, Mike
2012-01-25 2:03 ` Rob Lee
2012-01-24 23:49 ` Daniel Lezcano
2012-01-25 2:38 ` Rob Lee
2012-01-25 14:52 ` Daniel Lezcano
2012-01-24 4:37 ` [PATCH v3 2/7] ARM: exynos: Modify to use new common cpuidle code Robert Lee
2012-01-29 4:47 ` Barry Song
2012-01-24 4:37 ` [PATCH v3 3/7] ARM: shmobile: " Robert Lee
2012-01-24 4:37 ` [PATCH v3 4/7] ARM: kirkwood: " Robert Lee
2012-01-24 4:37 ` [PATCH v3 5/7] ARM: davinci: " Robert Lee
2012-01-24 4:37 ` [PATCH v3 6/7] ARM: imx: Init imx5 gpc_dvfs clock for global use Robert Lee
2012-01-24 4:37 ` [PATCH v3 7/7] ARM: imx: Add imx5 cpuidle implementation Robert Lee
2012-01-24 20:08 ` [PATCH v3 0/7] Add common cpuidle code for consolidation Kevin Hilman
2012-01-24 20:17 ` Mark Brown
2012-01-25 0:41 ` Kevin Hilman
2012-01-25 0:46 ` Rob Lee
2012-01-25 18:58 ` Kevin Hilman
2012-01-29 15:34 ` Russell King - ARM Linux
2012-01-31 3:02 ` Rob Lee
2012-01-31 21:55 ` Kevin Hilman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4F1EC204.9020807@gmail.com \
--to=robherring2@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.