From 3880d21450b3413c1b30440e8aca6e7dad7d9876 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 13 Sep 2013 16:38:41 +0100 Subject: drivers: cpuidle: rename ARM big.LITTLE driver config and makefile entries Following the reorganization of CPU idle drivers configurations into an ARM specific Kconfig, the existing idle drivers Kconfig entries were renamed and moved to the Kconfig.arm file. Makefile entries were updated accordingly. This patch renames the entries in Kconfig.arm and makefile to make the newly added big.LITTLE CPUidle driver compliant with the new naming convention. Signed-off-by: Lorenzo Pieralisi Acked-by: Kevin Hilman Signed-off-by: Daniel Lezcano --- drivers/cpuidle/Kconfig.arm | 22 +++++++++++----------- drivers/cpuidle/Makefile | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index 8e3660322308..6a7e6f2d8adc 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -2,6 +2,17 @@ # ARM CPU Idle drivers # +config ARM_BIG_LITTLE_CPUIDLE + bool "Support for ARM big.LITTLE processors" + depends on ARCH_VEXPRESS_TC2_PM + select ARM_CPU_SUSPEND + select CPU_IDLE_MULTIPLE_DRIVERS + help + Select this option to enable CPU idle driver for big.LITTLE based + ARM systems. Driver manages CPUs coordination through MCPM and + define different C-states for little and big cores through the + multiple CPU idle drivers infrastructure. + config ARM_HIGHBANK_CPUIDLE bool "CPU Idle Driver for Calxeda processors" depends on ARCH_HIGHBANK @@ -26,14 +37,3 @@ config ARM_U8500_CPUIDLE depends on ARCH_U8500 help Select this to enable cpuidle for ST-E u8500 processors - -config CPU_IDLE_BIG_LITTLE - bool "Support for ARM big.LITTLE processors" - depends on ARCH_VEXPRESS_TC2_PM - select ARM_CPU_SUSPEND - select CPU_IDLE_MULTIPLE_DRIVERS - help - Select this option to enable CPU idle driver for big.LITTLE based - ARM systems. Driver manages CPUs coordination through MCPM and - define different C-states for little and big cores through the - multiple CPU idle drivers infrastructure. diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index cea5ef58876d..d08bd4055a49 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -7,8 +7,8 @@ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o ################################################################################## # ARM SoC drivers +obj-$(CONFIG_ARM_BIG_LITTLE_CPUIDLE) += cpuidle-big_little.o obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o -obj-$(CONFIG_CPU_IDLE_BIG_LITTLE) += cpuidle-big_little.o -- cgit v1.2.3 From 4aa88fbe6d6f78a8a464445eb6b55a360e3d3733 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 27 Sep 2013 09:46:09 +0200 Subject: ARM: zynq: cpuidle: Remove useless compatibility string All zynq platforms have this compatibility string and there is no any other clone. Signed-off-by: Daniel Lezcano Acked-by: Michal Simek --- drivers/cpuidle/cpuidle-zynq.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/cpuidle-zynq.c b/drivers/cpuidle/cpuidle-zynq.c index 38e03a183591..ab6c4b4ffc7b 100644 --- a/drivers/cpuidle/cpuidle-zynq.c +++ b/drivers/cpuidle/cpuidle-zynq.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -72,9 +71,6 @@ static struct cpuidle_driver zynq_idle_driver = { /* Initialize CPU idle by registering the idle states */ static int __init zynq_cpuidle_init(void) { - if (!of_machine_is_compatible("xlnx,zynq-7000")) - return -ENODEV; - pr_info("Xilinx Zynq CpuIdle Driver started\n"); return cpuidle_register(&zynq_idle_driver, NULL); -- cgit v1.2.3 From 3e8ceca6c76ec2d5ee47ece0420cf10d041cf58f Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sat, 21 Sep 2013 18:41:02 +0200 Subject: ARM: zynq: cpuidle: convert to platform driver As the ux500 and the kirkwood driver, make the zynq driver a platform driver Signed-off-by: Daniel Lezcano Acked-by: Michal Simek Tested-by: Soren Brinkmann --- arch/arm/mach-zynq/common.c | 6 ++++++ drivers/cpuidle/cpuidle-zynq.c | 13 +++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers/cpuidle') diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 5f252569c689..9a7bd137c8fd 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -44,6 +44,10 @@ static struct of_device_id zynq_of_bus_ids[] __initdata = { {} }; +static struct platform_device zynq_cpuidle_device = { + .name = "cpuidle-zynq", +}; + /** * zynq_init_machine - System specific initialization, intended to be * called from board specific initialization. @@ -56,6 +60,8 @@ static void __init zynq_init_machine(void) l2x0_of_init(0x02060000, 0xF0F0FFFF); of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL); + + platform_device_register(&zynq_cpuidle_device); } static void __init zynq_timer_init(void) diff --git a/drivers/cpuidle/cpuidle-zynq.c b/drivers/cpuidle/cpuidle-zynq.c index ab6c4b4ffc7b..aded75928028 100644 --- a/drivers/cpuidle/cpuidle-zynq.c +++ b/drivers/cpuidle/cpuidle-zynq.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -69,11 +70,19 @@ static struct cpuidle_driver zynq_idle_driver = { }; /* Initialize CPU idle by registering the idle states */ -static int __init zynq_cpuidle_init(void) +static int zynq_cpuidle_probe(struct platform_device *pdev) { pr_info("Xilinx Zynq CpuIdle Driver started\n"); return cpuidle_register(&zynq_idle_driver, NULL); } -device_initcall(zynq_cpuidle_init); +static struct platform_driver zynq_cpuidle_driver = { + .driver = { + .name = "cpuidle-zynq", + .owner = THIS_MODULE, + }, + .probe = zynq_cpuidle_probe, +}; + +module_platform_driver(zynq_cpuidle_driver); -- cgit v1.2.3 From 2c2b24d9c3e96d5cf974be4559a936e7f3b50225 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 27 Sep 2013 18:57:07 +0200 Subject: ARM: ux500: cpuidle: fix section mismatch The dbx500_cpuidle_probe is tagged as an __init section but the variable dbx500_cpuidle_plat_driver is not. The dbx500_cpuidle_probe could not be declared as __init because of macro module_platform_driver builds the exit function, tags as __exit and this one refers to the dbx500_cpuidle_plat_driver which is an __initdata. That leads to a section mismatch. Fix it by removing the __init tag for the probe function. Signed-off-by: Daniel Lezcano Acked-by: Linus Walleij --- drivers/cpuidle/cpuidle-ux500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/cpuidle-ux500.c b/drivers/cpuidle/cpuidle-ux500.c index e0564652af35..5e35804b1a95 100644 --- a/drivers/cpuidle/cpuidle-ux500.c +++ b/drivers/cpuidle/cpuidle-ux500.c @@ -111,7 +111,7 @@ static struct cpuidle_driver ux500_idle_driver = { .state_count = 2, }; -static int __init dbx500_cpuidle_probe(struct platform_device *pdev) +static int dbx500_cpuidle_probe(struct platform_device *pdev) { /* Configure wake up reasons */ prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | -- cgit v1.2.3 From 1ce3c48e6c76920fa46bfdde84a69e155f880c32 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 26 Sep 2013 17:34:24 +0200 Subject: ARM: at91: cpuidle: Move driver to drivers/cpuidle As the cpuidle driver code has no more the dependency with the pm code, the 'standby' callback being passed as a parameter to the device's platform data, we can move the cpuidle driver in the drivers/cpuidle directory. Signed-off-by: Daniel Lezcano Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Nicolas Ferre Conflicts: drivers/cpuidle/Kconfig.arm drivers/cpuidle/Makefile --- arch/arm/mach-at91/Makefile | 1 - arch/arm/mach-at91/cpuidle.c | 69 ------------------------------------------ drivers/cpuidle/Kconfig.arm | 7 +++++ drivers/cpuidle/Makefile | 1 + drivers/cpuidle/cpuidle-at91.c | 69 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 77 insertions(+), 70 deletions(-) delete mode 100644 arch/arm/mach-at91/cpuidle.c create mode 100644 drivers/cpuidle/cpuidle-at91.c (limited to 'drivers/cpuidle') diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 3b0a9538093c..c1b737097c95 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -98,7 +98,6 @@ obj-y += leds.o # Power Management obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_AT91_SLOW_CLOCK) += pm_slowclock.o -obj-$(CONFIG_CPU_IDLE) += cpuidle.o ifeq ($(CONFIG_PM_DEBUG),y) CFLAGS_pm.o += -DDEBUG diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c deleted file mode 100644 index a0774370c6bc..000000000000 --- a/arch/arm/mach-at91/cpuidle.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * based on arch/arm/mach-kirkwood/cpuidle.c - * - * CPU idle support for AT91 SoC - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * - * The cpu idle uses wait-for-interrupt and RAM self refresh in order - * to implement two idle states - - * #1 wait-for-interrupt - * #2 wait-for-interrupt and RAM self refresh - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define AT91_MAX_STATES 2 - -static void (*at91_standby)(void); - -/* Actual code that puts the SoC in different idle states */ -static int at91_enter_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) -{ - at91_standby(); - return index; -} - -static struct cpuidle_driver at91_idle_driver = { - .name = "at91_idle", - .owner = THIS_MODULE, - .states[0] = ARM_CPUIDLE_WFI_STATE, - .states[1] = { - .enter = at91_enter_idle, - .exit_latency = 10, - .target_residency = 10000, - .flags = CPUIDLE_FLAG_TIME_VALID, - .name = "RAM_SR", - .desc = "WFI and DDR Self Refresh", - }, - .state_count = AT91_MAX_STATES, -}; - -/* Initialize CPU idle by registering the idle states */ -static int at91_cpuidle_probe(struct platform_device *dev) -{ - at91_standby = (void *)(dev->dev.platform_data); - - return cpuidle_register(&at91_idle_driver, NULL); -} - -static struct platform_driver at91_cpuidle_driver = { - .driver = { - .name = "cpuidle-at91", - .owner = THIS_MODULE, - }, - .probe = at91_cpuidle_probe, -}; - -module_platform_driver(at91_cpuidle_driver); diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index 6a7e6f2d8adc..f23bd75426cd 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -37,3 +37,10 @@ config ARM_U8500_CPUIDLE depends on ARCH_U8500 help Select this to enable cpuidle for ST-E u8500 processors + +config ARM_AT91_CPUIDLE + bool "Cpu Idle Driver for the AT91 processors" + default y + depends on ARCH_AT91 + help + Select this to enable cpuidle for AT91 processors diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index d08bd4055a49..527be28e5c1e 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o +obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o diff --git a/drivers/cpuidle/cpuidle-at91.c b/drivers/cpuidle/cpuidle-at91.c new file mode 100644 index 000000000000..a0774370c6bc --- /dev/null +++ b/drivers/cpuidle/cpuidle-at91.c @@ -0,0 +1,69 @@ +/* + * based on arch/arm/mach-kirkwood/cpuidle.c + * + * CPU idle support for AT91 SoC + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + * The cpu idle uses wait-for-interrupt and RAM self refresh in order + * to implement two idle states - + * #1 wait-for-interrupt + * #2 wait-for-interrupt and RAM self refresh + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define AT91_MAX_STATES 2 + +static void (*at91_standby)(void); + +/* Actual code that puts the SoC in different idle states */ +static int at91_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + at91_standby(); + return index; +} + +static struct cpuidle_driver at91_idle_driver = { + .name = "at91_idle", + .owner = THIS_MODULE, + .states[0] = ARM_CPUIDLE_WFI_STATE, + .states[1] = { + .enter = at91_enter_idle, + .exit_latency = 10, + .target_residency = 10000, + .flags = CPUIDLE_FLAG_TIME_VALID, + .name = "RAM_SR", + .desc = "WFI and DDR Self Refresh", + }, + .state_count = AT91_MAX_STATES, +}; + +/* Initialize CPU idle by registering the idle states */ +static int at91_cpuidle_probe(struct platform_device *dev) +{ + at91_standby = (void *)(dev->dev.platform_data); + + return cpuidle_register(&at91_idle_driver, NULL); +} + +static struct platform_driver at91_cpuidle_driver = { + .driver = { + .name = "cpuidle-at91", + .owner = THIS_MODULE, + }, + .probe = at91_cpuidle_probe, +}; + +module_platform_driver(at91_cpuidle_driver); -- cgit v1.2.3 From caf4a36e818ba8df4e002b7dfa4eff5b8384dda0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:41 +0530 Subject: cpuidle: Fix comments in cpuidle core Some comments in cpuidle core files contain trivial mistakes. This patch fixes them. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/coupled.c | 2 +- drivers/cpuidle/cpuidle.c | 2 +- drivers/cpuidle/driver.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/coupled.c b/drivers/cpuidle/coupled.c index f8a86364c6b6..e952936418d0 100644 --- a/drivers/cpuidle/coupled.c +++ b/drivers/cpuidle/coupled.c @@ -147,7 +147,7 @@ static cpumask_t cpuidle_coupled_poked; * has returned from this function, the barrier is immediately available for * reuse. * - * The atomic variable a must be initialized to 0 before any cpu calls + * The atomic variable must be initialized to 0 before any cpu calls * this function, will be reset to 0 before any cpu returns from this function. * * Must only be called from within a coupled idle state handler diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index d75040ddd2b3..8827c02af87c 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -516,7 +516,7 @@ int cpuidle_register(struct cpuidle_driver *drv, #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED /* - * On multiplatform for ARM, the coupled idle states could + * On multiplatform for ARM, the coupled idle states could be * enabled in the kernel even if the cpuidle driver does not * use it. Note, coupled_cpus is a struct copy. */ diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 6e11701f0fca..ced1df6844eb 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -56,7 +56,7 @@ static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv) } /** - * __cpuidle_set_driver - set per CPU driver variables the the given driver. + * __cpuidle_set_driver - set per CPU driver variables for the given driver. * @drv: a valid pointer to a struct cpuidle_driver * * For each CPU in the driver's cpumask, unset the registered driver per CPU @@ -132,7 +132,7 @@ static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv) * cpuidle_setup_broadcast_timer - enable/disable the broadcast timer * @arg: a void pointer used to match the SMP cross call API * - * @arg is used as a value of type 'long' with on of the two values: + * @arg is used as a value of type 'long' with one of the two values: * - CLOCK_EVT_NOTIFY_BROADCAST_ON * - CLOCK_EVT_NOTIFY_BROADCAST_OFF * @@ -169,7 +169,7 @@ static int __cpuidle_driver_init(struct cpuidle_driver *drv) /* * Look for the timer stop flag in the different states, so that we know * if the broadcast timer has to be set up. The loop is in the reverse - * order, because usually on of the the deeper states has this flag set. + * order, because usually one of the deeper states have this flag set. */ for (i = drv->state_count - 1; i >= 0 ; i--) { -- cgit v1.2.3 From 267d4bf8ee6dbde889f4c55d0188f561616dbc7a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:43 +0530 Subject: cpuidle: make __cpuidle_device_init() return void The only value returned by __cpuidle_device_init() is 0, so it very well may be a void function. Make that happen. [rjw: Changelog] Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 8827c02af87c..211e504263fa 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -358,12 +358,10 @@ static void __cpuidle_unregister_device(struct cpuidle_device *dev) module_put(drv->owner); } -static int __cpuidle_device_init(struct cpuidle_device *dev) +static void __cpuidle_device_init(struct cpuidle_device *dev) { memset(dev->states_usage, 0, sizeof(dev->states_usage)); dev->last_residency = 0; - - return 0; } /** @@ -410,9 +408,7 @@ int cpuidle_register_device(struct cpuidle_device *dev) if (dev->registered) goto out_unlock; - ret = __cpuidle_device_init(dev); - if (ret) - goto out_unlock; + __cpuidle_device_init(dev); ret = __cpuidle_register_device(dev); if (ret) -- cgit v1.2.3 From e437f3e37369606bf1a340e0504554d6530abc51 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:44 +0530 Subject: cpuidle: make __cpuidle_driver_init() return void The only value returned by __cpuidle_driver_init() is 0, so it very well may be a void function. [rjw: Changelog] Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/driver.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index ced1df6844eb..d97d072a461c 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -149,10 +149,8 @@ static void cpuidle_setup_broadcast_timer(void *arg) /** * __cpuidle_driver_init - initialize the driver's internal data * @drv: a valid pointer to a struct cpuidle_driver - * - * Returns 0 on success, a negative error code otherwise. */ -static int __cpuidle_driver_init(struct cpuidle_driver *drv) +static void __cpuidle_driver_init(struct cpuidle_driver *drv) { int i; @@ -179,8 +177,6 @@ static int __cpuidle_driver_init(struct cpuidle_driver *drv) drv->bctimer = 1; break; } - - return 0; } /** @@ -206,9 +202,7 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv) if (cpuidle_disabled()) return -ENODEV; - ret = __cpuidle_driver_init(drv); - if (ret) - return ret; + __cpuidle_driver_init(drv); ret = __cpuidle_set_driver(drv); if (ret) -- cgit v1.2.3 From b171a85648e7055c6680c259a9a87806a56a24c3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:45 +0530 Subject: cpuidle: rearrange code in __cpuidle_driver_init() This is trivial patch that just reorders a few statements in __cpuidle_driver_init() routine so that we don't need both 'continue' and 'break' in the for loop. Functionally it shouldn't change anything. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/driver.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index d97d072a461c..a930005d5a3a 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -170,12 +170,10 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv) * order, because usually one of the deeper states have this flag set. */ for (i = drv->state_count - 1; i >= 0 ; i--) { - - if (!(drv->states[i].flags & CPUIDLE_FLAG_TIMER_STOP)) - continue; - - drv->bctimer = 1; - break; + if (drv->states[i].flags & CPUIDLE_FLAG_TIMER_STOP) { + drv->bctimer = 1; + break; + } } } -- cgit v1.2.3 From 47182668ca140ae067d5961ec8c59edf646b36c7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:46 +0530 Subject: cpuidle: rearrange __cpuidle_register_device() to keep minimal exit points This patch rearranges __cpuidle_register_device() a bit in order to reduce the number of exit points in that function. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 211e504263fa..8c91badff00b 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -383,13 +383,12 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) list_add(&dev->device_list, &cpuidle_detected_devices); ret = cpuidle_coupled_register_device(dev); - if (ret) { + if (ret) __cpuidle_unregister_device(dev); - return ret; - } + else + dev->registered = 1; - dev->registered = 1; - return 0; + return ret; } /** -- cgit v1.2.3 From 9b29a86f04f87cdb9eaacadf2e2d33a55af1c7cc Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:47 +0530 Subject: cpuidle: merge two if() statements for checking error cases Two checks cpuidle_idle_call() cause the same error code to be returned if they fail, so merge them for clarity. [rjw: Changelog] Acked-by: Daniel Lezcano Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 8c91badff00b..518b542cad54 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -119,10 +119,7 @@ int cpuidle_idle_call(void) struct cpuidle_driver *drv; int next_state, entered_state; - if (off) - return -ENODEV; - - if (!initialized) + if (off || !initialized) return -ENODEV; /* check if the device is ready */ -- cgit v1.2.3 From fb11c9c63f995afbe0e909f061d9866a722cb4bf Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:48 +0530 Subject: cpuidle: reduce code duplication inside cpuidle_idle_call() We are doing this twice in cpuidle_idle_call() routine: drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP Would be better if we actually store this in a local variable and use that. That reduces code duplication and likely makes this piece of code run faster (in case the compiler wasn't able to optimize it earlier) [rjw: Cast the result of bitwise AND to bool explicitly using !!] Acked-by: Daniel Lezcano Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 518b542cad54..86e805986d6f 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -118,6 +118,7 @@ int cpuidle_idle_call(void) struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); struct cpuidle_driver *drv; int next_state, entered_state; + bool broadcast; if (off || !initialized) return -ENODEV; @@ -141,7 +142,9 @@ int cpuidle_idle_call(void) trace_cpu_idle_rcuidle(next_state, dev->cpu); - if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP) + broadcast = !!(drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP); + + if (broadcast) clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu); @@ -151,7 +154,7 @@ int cpuidle_idle_call(void) else entered_state = cpuidle_enter_state(dev, drv, next_state); - if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP) + if (broadcast) clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); -- cgit v1.2.3 From 6d281e97a1c53abb73477a34806c1a000409c4b9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:49 +0530 Subject: cpuidle: replace multiline statements with single line in cpuidle_idle_call() Few statements in cpuidle_idle_call() are broken into multiple lines, although that isn't really necessary. Convert those to single line. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 86e805986d6f..039a807b217a 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -145,8 +145,7 @@ int cpuidle_idle_call(void) broadcast = !!(drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP); if (broadcast) - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, - &dev->cpu); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu); if (cpuidle_state_is_coupled(dev, drv, next_state)) entered_state = cpuidle_enter_state_coupled(dev, drv, @@ -155,8 +154,7 @@ int cpuidle_idle_call(void) entered_state = cpuidle_enter_state(dev, drv, next_state); if (broadcast) - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, - &dev->cpu); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); -- cgit v1.2.3 From 0d09d3125642ac1f02937e577819dbc515291d93 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:50 +0530 Subject: cpuidle: call cpuidle_get_driver() from after taking cpuidle_driver_lock There are a few cpuidle_get_driver() calls that aren't made under cpuidle_driver_lock which is incorrect. Fix them by calling cpuidle_get_driver() after taking cpuidle_driver_lock. Acked-by: Daniel Lezcano Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/driver.c | 3 ++- drivers/cpuidle/sysfs.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index a930005d5a3a..2458a741ad45 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -338,10 +338,11 @@ struct cpuidle_driver *cpuidle_driver_ref(void) */ void cpuidle_driver_unref(void) { - struct cpuidle_driver *drv = cpuidle_get_driver(); + struct cpuidle_driver *drv; spin_lock(&cpuidle_driver_lock); + drv = cpuidle_get_driver(); if (drv && !WARN_ON(drv->refcnt <= 0)) drv->refcnt--; diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 8739cc05228c..a0223933536e 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -52,9 +52,10 @@ static ssize_t show_current_driver(struct device *dev, char *buf) { ssize_t ret; - struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); + struct cpuidle_driver *cpuidle_driver; spin_lock(&cpuidle_driver_lock); + cpuidle_driver = cpuidle_get_driver(); if (cpuidle_driver) ret = sprintf(buf, "%s\n", cpuidle_driver->name); else -- cgit v1.2.3 From 1f6b9f74ee3d96909e5e70d4207b4b6740d4db62 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:51 +0530 Subject: cpuidle: use drv instead of cpuidle_driver in show_current_driver() Instances of "struct cpuidle_driver *" are consistently named as "drv" in the cpuidle core except in show_current_driver(). Make that function use variable naming consistent with the rest of the code. [rjw: Changelog] Acked-by: Daniel Lezcano Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/sysfs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index a0223933536e..e918b6d0caf7 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -52,12 +52,12 @@ static ssize_t show_current_driver(struct device *dev, char *buf) { ssize_t ret; - struct cpuidle_driver *cpuidle_driver; + struct cpuidle_driver *drv; spin_lock(&cpuidle_driver_lock); - cpuidle_driver = cpuidle_get_driver(); - if (cpuidle_driver) - ret = sprintf(buf, "%s\n", cpuidle_driver->name); + drv = cpuidle_get_driver(); + if (drv) + ret = sprintf(buf, "%s\n", drv->name); else ret = sprintf(buf, "none\n"); spin_unlock(&cpuidle_driver_lock); -- cgit v1.2.3 From d7c7f103262bc2248548ed0e113e916e843c4eeb Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:54 +0530 Subject: cpuidle: don't call poll_idle_init() for every cpu poll_idle_init() just initializes drv->states[0] and so that is required to be done only once for each driver. Currently, it is called from cpuidle_enable_device() which is called for every CPU that the driver supports. That is not required, so move it to a better place and call it from __cpuidle_register_driver() so that the initialization is carried out only once. Acked-by: Daniel Lezcano Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle.c | 41 ----------------------------------------- drivers/cpuidle/driver.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 41 deletions(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 039a807b217a..2a991e468f78 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -226,45 +226,6 @@ void cpuidle_resume(void) mutex_unlock(&cpuidle_lock); } -#ifdef CONFIG_ARCH_HAS_CPU_RELAX -static int poll_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, int index) -{ - ktime_t t1, t2; - s64 diff; - - t1 = ktime_get(); - local_irq_enable(); - while (!need_resched()) - cpu_relax(); - - t2 = ktime_get(); - diff = ktime_to_us(ktime_sub(t2, t1)); - if (diff > INT_MAX) - diff = INT_MAX; - - dev->last_residency = (int) diff; - - return index; -} - -static void poll_idle_init(struct cpuidle_driver *drv) -{ - struct cpuidle_state *state = &drv->states[0]; - - snprintf(state->name, CPUIDLE_NAME_LEN, "POLL"); - snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE"); - state->exit_latency = 0; - state->target_residency = 0; - state->power_usage = -1; - state->flags = 0; - state->enter = poll_idle; - state->disabled = false; -} -#else -static void poll_idle_init(struct cpuidle_driver *drv) {} -#endif /* CONFIG_ARCH_HAS_CPU_RELAX */ - /** * cpuidle_enable_device - enables idle PM for a CPU * @dev: the CPU @@ -294,8 +255,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev) if (!dev->state_count) dev->state_count = drv->state_count; - poll_idle_init(drv); - ret = cpuidle_add_device_sysfs(dev); if (ret) return ret; diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 2458a741ad45..06dbe7c86199 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -177,6 +178,45 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv) } } +#ifdef CONFIG_ARCH_HAS_CPU_RELAX +static int poll_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + ktime_t t1, t2; + s64 diff; + + t1 = ktime_get(); + local_irq_enable(); + while (!need_resched()) + cpu_relax(); + + t2 = ktime_get(); + diff = ktime_to_us(ktime_sub(t2, t1)); + if (diff > INT_MAX) + diff = INT_MAX; + + dev->last_residency = (int) diff; + + return index; +} + +static void poll_idle_init(struct cpuidle_driver *drv) +{ + struct cpuidle_state *state = &drv->states[0]; + + snprintf(state->name, CPUIDLE_NAME_LEN, "POLL"); + snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE"); + state->exit_latency = 0; + state->target_residency = 0; + state->power_usage = -1; + state->flags = 0; + state->enter = poll_idle; + state->disabled = false; +} +#else +static void poll_idle_init(struct cpuidle_driver *drv) {} +#endif /* !CONFIG_ARCH_HAS_CPU_RELAX */ + /** * __cpuidle_register_driver: register the driver * @drv: a valid pointer to a struct cpuidle_driver @@ -210,6 +250,8 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv) on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer, (void *)CLOCK_EVT_NOTIFY_BROADCAST_ON, 1); + poll_idle_init(drv); + return 0; } -- cgit v1.2.3 From f60e230f6be5672241e48434a6c2a417d9674d42 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:55 +0530 Subject: cpuidle: remove cpuidle_unregister_governor() cpuidle_unregister_governor() and cpuidle_replace_governor() aren't used anymore and can be removed. They were used by cpufreq governors earlier, but since the governors can't be compiled as modules any more, these two functions aren't necessary. Suggested-by: Daniel Lezcano Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- Documentation/cpuidle/governor.txt | 1 - drivers/cpuidle/governor.c | 43 -------------------------------------- include/linux/cpuidle.h | 6 ------ 3 files changed, 50 deletions(-) (limited to 'drivers/cpuidle') diff --git a/Documentation/cpuidle/governor.txt b/Documentation/cpuidle/governor.txt index 12c6bd50c9f6..d9020f5e847b 100644 --- a/Documentation/cpuidle/governor.txt +++ b/Documentation/cpuidle/governor.txt @@ -25,5 +25,4 @@ kernel configuration and platform will be selected by cpuidle. Interfaces: extern int cpuidle_register_governor(struct cpuidle_governor *gov); -extern void cpuidle_unregister_governor(struct cpuidle_governor *gov); struct cpuidle_governor diff --git a/drivers/cpuidle/governor.c b/drivers/cpuidle/governor.c index ea2f8e7aa24a..ca89412f5122 100644 --- a/drivers/cpuidle/governor.c +++ b/drivers/cpuidle/governor.c @@ -96,46 +96,3 @@ int cpuidle_register_governor(struct cpuidle_governor *gov) return ret; } - -/** - * cpuidle_replace_governor - find a replacement governor - * @exclude_rating: the rating that will be skipped while looking for - * new governor. - */ -static struct cpuidle_governor *cpuidle_replace_governor(int exclude_rating) -{ - struct cpuidle_governor *gov; - struct cpuidle_governor *ret_gov = NULL; - unsigned int max_rating = 0; - - list_for_each_entry(gov, &cpuidle_governors, governor_list) { - if (gov->rating == exclude_rating) - continue; - if (gov->rating > max_rating) { - max_rating = gov->rating; - ret_gov = gov; - } - } - - return ret_gov; -} - -/** - * cpuidle_unregister_governor - unregisters a governor - * @gov: the governor - */ -void cpuidle_unregister_governor(struct cpuidle_governor *gov) -{ - if (!gov) - return; - - mutex_lock(&cpuidle_lock); - if (gov == cpuidle_curr_governor) { - struct cpuidle_governor *new_gov; - new_gov = cpuidle_replace_governor(gov->rating); - cpuidle_switch_governor(new_gov); - } - list_del(&gov->governor_list); - mutex_unlock(&cpuidle_lock); -} - diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index c082425757f4..50fcbb0ac4e7 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -195,16 +195,10 @@ struct cpuidle_governor { }; #ifdef CONFIG_CPU_IDLE - extern int cpuidle_register_governor(struct cpuidle_governor *gov); -extern void cpuidle_unregister_governor(struct cpuidle_governor *gov); - #else - static inline int cpuidle_register_governor(struct cpuidle_governor *gov) {return 0;} -static inline void cpuidle_unregister_governor(struct cpuidle_governor *gov) { } - #endif #ifdef CONFIG_ARCH_HAS_CPU_RELAX -- cgit v1.2.3