diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-08-26 19:42:55 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-08-26 19:42:55 -0400 |
| commit | c7878810f2d3a637bafc4fd55126eb9a5548ec77 (patch) | |
| tree | c3945d713e9c75315e856d17bb3bcd3c8e96805f | |
| parent | 95b6fcb0a3b6d5ce7853ebe088c344fd016351e7 (diff) | |
| parent | 51f245b895e3fe4cbac0b2633e54a1830864a83f (diff) | |
Merge branch 'pm-cpuidle'
* pm-cpuidle: (25 commits)
cpuidle: Change struct menu_device field types
cpuidle: Add a comment warning about possible overflow
cpuidle: Fix variable domains in get_typical_interval()
cpuidle: Fix menu_device->intervals type
cpuidle: CodingStyle: Break up multiple assignments on single line
cpuidle: Check called function parameter in get_typical_interval()
cpuidle: Rearrange code and comments in get_typical_interval()
cpuidle: Ignore interval prediction result when timer is shorter
cpuidle-kirkwood.c: simplify use of devm_ioremap_resource()
cpuidle: kirkwood: Make kirkwood_cpuidle_remove function static
cpuidle: calxeda: Add missing __iomem annotation
SH: cpuidle: Add missing parameter for cpuidle_register()
ARM: ux500: cpuidle: Move ux500 cpuidle driver to drivers/cpuidle
ARM: ux500: cpuidle: Remove pointless include
ARM: ux500: cpuidle: Instantiate the driver from platform device
ARM: davinci: cpuidle: Fix target residency
cpuidle: Add Kconfig.arm and move calxeda, kirkwood and zynq
cpuidle: Check if device is already registered
cpuidle: Introduce __cpuidle_device_init()
cpuidle: Introduce __cpuidle_unregister_device()
...
| -rw-r--r-- | arch/arm/mach-davinci/cpuidle.c | 2 | ||||
| -rw-r--r-- | arch/arm/mach-ux500/Makefile | 1 | ||||
| -rw-r--r-- | arch/sh/kernel/cpu/shmobile/cpuidle.c | 4 | ||||
| -rw-r--r-- | drivers/cpuidle/Kconfig | 20 | ||||
| -rw-r--r-- | drivers/cpuidle/Kconfig.arm | 29 | ||||
| -rw-r--r-- | drivers/cpuidle/Makefile | 9 | ||||
| -rw-r--r-- | drivers/cpuidle/cpuidle-calxeda.c | 2 | ||||
| -rw-r--r-- | drivers/cpuidle/cpuidle-kirkwood.c | 5 | ||||
| -rw-r--r-- | drivers/cpuidle/cpuidle-ux500.c (renamed from arch/arm/mach-ux500/cpuidle.c) | 19 | ||||
| -rw-r--r-- | drivers/cpuidle/cpuidle.c | 94 | ||||
| -rw-r--r-- | drivers/cpuidle/governors/ladder.c | 12 | ||||
| -rw-r--r-- | drivers/cpuidle/governors/menu.c | 108 | ||||
| -rw-r--r-- | drivers/cpuidle/sysfs.c | 101 | ||||
| -rw-r--r-- | drivers/mfd/db8500-prcmu.c | 4 | ||||
| -rw-r--r-- | include/linux/cpuidle.h | 9 |
15 files changed, 256 insertions, 163 deletions
diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index 36aef3a7dedb..f1ac1c94ac0f 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c | |||
| @@ -65,7 +65,7 @@ static struct cpuidle_driver davinci_idle_driver = { | |||
| 65 | .states[1] = { | 65 | .states[1] = { |
| 66 | .enter = davinci_enter_idle, | 66 | .enter = davinci_enter_idle, |
| 67 | .exit_latency = 10, | 67 | .exit_latency = 10, |
| 68 | .target_residency = 100000, | 68 | .target_residency = 10000, |
| 69 | .flags = CPUIDLE_FLAG_TIME_VALID, | 69 | .flags = CPUIDLE_FLAG_TIME_VALID, |
| 70 | .name = "DDR SR", | 70 | .name = "DDR SR", |
| 71 | .desc = "WFI and DDR Self Refresh", | 71 | .desc = "WFI and DDR Self Refresh", |
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index bf9b6be5b180..fe1f3e26b88b 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | 4 | ||
| 5 | obj-y := cpu.o devices.o devices-common.o \ | 5 | obj-y := cpu.o devices.o devices-common.o \ |
| 6 | id.o usb.o timer.o pm.o | 6 | id.o usb.o timer.o pm.o |
| 7 | obj-$(CONFIG_CPU_IDLE) += cpuidle.o | ||
| 8 | obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o | 7 | obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o |
| 9 | obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o | 8 | obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o |
| 10 | obj-$(CONFIG_MACH_MOP500) += board-mop500.o board-mop500-sdi.o \ | 9 | obj-$(CONFIG_MACH_MOP500) += board-mop500.o board-mop500-sdi.o \ |
diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c index d30622592116..e3abfd4277e2 100644 --- a/arch/sh/kernel/cpu/shmobile/cpuidle.c +++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c | |||
| @@ -91,13 +91,11 @@ static struct cpuidle_driver cpuidle_driver = { | |||
| 91 | 91 | ||
| 92 | int __init sh_mobile_setup_cpuidle(void) | 92 | int __init sh_mobile_setup_cpuidle(void) |
| 93 | { | 93 | { |
| 94 | int ret; | ||
| 95 | |||
| 96 | if (sh_mobile_sleep_supported & SUSP_SH_SF) | 94 | if (sh_mobile_sleep_supported & SUSP_SH_SF) |
| 97 | cpuidle_driver.states[1].disabled = false; | 95 | cpuidle_driver.states[1].disabled = false; |
| 98 | 96 | ||
| 99 | if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) | 97 | if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) |
| 100 | cpuidle_driver.states[2].disabled = false; | 98 | cpuidle_driver.states[2].disabled = false; |
| 101 | 99 | ||
| 102 | return cpuidle_register(&cpuidle_driver); | 100 | return cpuidle_register(&cpuidle_driver, NULL); |
| 103 | } | 101 | } |
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index 0e2cd5cab4d0..b3fb81d7cf04 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | menu "CPU Idle" | ||
| 1 | 2 | ||
| 2 | menuconfig CPU_IDLE | 3 | config CPU_IDLE |
| 3 | bool "CPU idle PM support" | 4 | bool "CPU idle PM support" |
| 4 | default y if ACPI || PPC_PSERIES | 5 | default y if ACPI || PPC_PSERIES |
| 5 | select CPU_IDLE_GOV_LADDER if (!NO_HZ && !NO_HZ_IDLE) | 6 | select CPU_IDLE_GOV_LADDER if (!NO_HZ && !NO_HZ_IDLE) |
| @@ -29,20 +30,13 @@ config CPU_IDLE_GOV_MENU | |||
| 29 | bool "Menu governor (for tickless system)" | 30 | bool "Menu governor (for tickless system)" |
| 30 | default y | 31 | default y |
| 31 | 32 | ||
| 32 | config CPU_IDLE_CALXEDA | 33 | menu "ARM CPU Idle Drivers" |
| 33 | bool "CPU Idle Driver for Calxeda processors" | 34 | depends on ARM |
| 34 | depends on ARCH_HIGHBANK | 35 | source "drivers/cpuidle/Kconfig.arm" |
| 35 | select ARM_CPU_SUSPEND | 36 | endmenu |
| 36 | help | ||
| 37 | Select this to enable cpuidle on Calxeda processors. | ||
| 38 | |||
| 39 | config CPU_IDLE_ZYNQ | ||
| 40 | bool "CPU Idle Driver for Xilinx Zynq processors" | ||
| 41 | depends on ARCH_ZYNQ | ||
| 42 | help | ||
| 43 | Select this to enable cpuidle on Xilinx Zynq processors. | ||
| 44 | 37 | ||
| 45 | endif | 38 | endif |
| 46 | 39 | ||
| 47 | config ARCH_NEEDS_CPU_IDLE_COUPLED | 40 | config ARCH_NEEDS_CPU_IDLE_COUPLED |
| 48 | def_bool n | 41 | def_bool n |
| 42 | endmenu | ||
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm new file mode 100644 index 000000000000..b3302193c15a --- /dev/null +++ b/drivers/cpuidle/Kconfig.arm | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | # | ||
| 2 | # ARM CPU Idle drivers | ||
| 3 | # | ||
| 4 | |||
| 5 | config ARM_HIGHBANK_CPUIDLE | ||
| 6 | bool "CPU Idle Driver for Calxeda processors" | ||
| 7 | depends on ARCH_HIGHBANK | ||
| 8 | select ARM_CPU_SUSPEND | ||
| 9 | help | ||
| 10 | Select this to enable cpuidle on Calxeda processors. | ||
| 11 | |||
| 12 | config ARM_KIRKWOOD_CPUIDLE | ||
| 13 | bool "CPU Idle Driver for Marvell Kirkwood SoCs" | ||
| 14 | depends on ARCH_KIRKWOOD | ||
| 15 | help | ||
| 16 | This adds the CPU Idle driver for Marvell Kirkwood SoCs. | ||
| 17 | |||
| 18 | config ARM_ZYNQ_CPUIDLE | ||
| 19 | bool "CPU Idle Driver for Xilinx Zynq processors" | ||
| 20 | depends on ARCH_ZYNQ | ||
| 21 | help | ||
| 22 | Select this to enable cpuidle on Xilinx Zynq processors. | ||
| 23 | |||
| 24 | config ARM_U8500_CPUIDLE | ||
| 25 | bool "Cpu Idle Driver for the ST-E u8500 processors" | ||
| 26 | depends on ARCH_U8500 | ||
| 27 | help | ||
| 28 | Select this to enable cpuidle for ST-E u8500 processors | ||
| 29 | |||
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 8767a7b3eb91..0b9d200c7e45 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile | |||
| @@ -5,6 +5,9 @@ | |||
| 5 | obj-y += cpuidle.o driver.o governor.o sysfs.o governors/ | 5 | obj-y += cpuidle.o driver.o governor.o sysfs.o governors/ |
| 6 | obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o | 6 | obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o |
| 7 | 7 | ||
| 8 | obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o | 8 | ################################################################################## |
| 9 | obj-$(CONFIG_ARCH_KIRKWOOD) += cpuidle-kirkwood.o | 9 | # ARM SoC drivers |
| 10 | obj-$(CONFIG_CPU_IDLE_ZYNQ) += cpuidle-zynq.o | 10 | obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o |
| 11 | obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o | ||
| 12 | obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o | ||
| 13 | obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o | ||
diff --git a/drivers/cpuidle/cpuidle-calxeda.c b/drivers/cpuidle/cpuidle-calxeda.c index 0e6e408c0a63..346058479572 100644 --- a/drivers/cpuidle/cpuidle-calxeda.c +++ b/drivers/cpuidle/cpuidle-calxeda.c | |||
| @@ -35,7 +35,7 @@ | |||
| 35 | #include <asm/cp15.h> | 35 | #include <asm/cp15.h> |
| 36 | 36 | ||
| 37 | extern void highbank_set_cpu_jump(int cpu, void *jump_addr); | 37 | extern void highbank_set_cpu_jump(int cpu, void *jump_addr); |
| 38 | extern void *scu_base_addr; | 38 | extern void __iomem *scu_base_addr; |
| 39 | 39 | ||
| 40 | static noinline void calxeda_idle_restore(void) | 40 | static noinline void calxeda_idle_restore(void) |
| 41 | { | 41 | { |
diff --git a/drivers/cpuidle/cpuidle-kirkwood.c b/drivers/cpuidle/cpuidle-kirkwood.c index 521b0a7fdd89..41ba843251b8 100644 --- a/drivers/cpuidle/cpuidle-kirkwood.c +++ b/drivers/cpuidle/cpuidle-kirkwood.c | |||
| @@ -60,9 +60,6 @@ static int kirkwood_cpuidle_probe(struct platform_device *pdev) | |||
| 60 | struct resource *res; | 60 | struct resource *res; |
| 61 | 61 | ||
| 62 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 62 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 63 | if (res == NULL) | ||
| 64 | return -EINVAL; | ||
| 65 | |||
| 66 | ddr_operation_base = devm_ioremap_resource(&pdev->dev, res); | 63 | ddr_operation_base = devm_ioremap_resource(&pdev->dev, res); |
| 67 | if (IS_ERR(ddr_operation_base)) | 64 | if (IS_ERR(ddr_operation_base)) |
| 68 | return PTR_ERR(ddr_operation_base); | 65 | return PTR_ERR(ddr_operation_base); |
| @@ -70,7 +67,7 @@ static int kirkwood_cpuidle_probe(struct platform_device *pdev) | |||
| 70 | return cpuidle_register(&kirkwood_idle_driver, NULL); | 67 | return cpuidle_register(&kirkwood_idle_driver, NULL); |
| 71 | } | 68 | } |
| 72 | 69 | ||
| 73 | int kirkwood_cpuidle_remove(struct platform_device *pdev) | 70 | static int kirkwood_cpuidle_remove(struct platform_device *pdev) |
| 74 | { | 71 | { |
| 75 | cpuidle_unregister(&kirkwood_idle_driver); | 72 | cpuidle_unregister(&kirkwood_idle_driver); |
| 76 | return 0; | 73 | return 0; |
diff --git a/arch/arm/mach-ux500/cpuidle.c b/drivers/cpuidle/cpuidle-ux500.c index a45dd09daed9..e0564652af35 100644 --- a/arch/arm/mach-ux500/cpuidle.c +++ b/drivers/cpuidle/cpuidle-ux500.c | |||
| @@ -16,13 +16,11 @@ | |||
| 16 | #include <linux/smp.h> | 16 | #include <linux/smp.h> |
| 17 | #include <linux/mfd/dbx500-prcmu.h> | 17 | #include <linux/mfd/dbx500-prcmu.h> |
| 18 | #include <linux/platform_data/arm-ux500-pm.h> | 18 | #include <linux/platform_data/arm-ux500-pm.h> |
| 19 | #include <linux/platform_device.h> | ||
| 19 | 20 | ||
| 20 | #include <asm/cpuidle.h> | 21 | #include <asm/cpuidle.h> |
| 21 | #include <asm/proc-fns.h> | 22 | #include <asm/proc-fns.h> |
| 22 | 23 | ||
| 23 | #include "db8500-regs.h" | ||
| 24 | #include "id.h" | ||
| 25 | |||
| 26 | static atomic_t master = ATOMIC_INIT(0); | 24 | static atomic_t master = ATOMIC_INIT(0); |
| 27 | static DEFINE_SPINLOCK(master_lock); | 25 | static DEFINE_SPINLOCK(master_lock); |
| 28 | 26 | ||
| @@ -113,11 +111,8 @@ static struct cpuidle_driver ux500_idle_driver = { | |||
| 113 | .state_count = 2, | 111 | .state_count = 2, |
| 114 | }; | 112 | }; |
| 115 | 113 | ||
| 116 | int __init ux500_idle_init(void) | 114 | static int __init dbx500_cpuidle_probe(struct platform_device *pdev) |
| 117 | { | 115 | { |
| 118 | if (!(cpu_is_u8500_family() || cpu_is_ux540_family())) | ||
| 119 | return -ENODEV; | ||
| 120 | |||
| 121 | /* Configure wake up reasons */ | 116 | /* Configure wake up reasons */ |
| 122 | prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | | 117 | prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | |
| 123 | PRCMU_WAKEUP(ABB)); | 118 | PRCMU_WAKEUP(ABB)); |
| @@ -125,4 +120,12 @@ int __init ux500_idle_init(void) | |||
| 125 | return cpuidle_register(&ux500_idle_driver, NULL); | 120 | return cpuidle_register(&ux500_idle_driver, NULL); |
| 126 | } | 121 | } |
| 127 | 122 | ||
| 128 | device_initcall(ux500_idle_init); | 123 | static struct platform_driver dbx500_cpuidle_plat_driver = { |
| 124 | .driver = { | ||
| 125 | .name = "cpuidle-dbx500", | ||
| 126 | .owner = THIS_MODULE, | ||
| 127 | }, | ||
| 128 | .probe = dbx500_cpuidle_probe, | ||
| 129 | }; | ||
| 130 | |||
| 131 | module_platform_driver(dbx500_cpuidle_plat_driver); | ||
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index fdc432f18022..d75040ddd2b3 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
| @@ -42,8 +42,6 @@ void disable_cpuidle(void) | |||
| 42 | off = 1; | 42 | off = 1; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | static int __cpuidle_register_device(struct cpuidle_device *dev); | ||
| 46 | |||
| 47 | /** | 45 | /** |
| 48 | * cpuidle_play_dead - cpu off-lining | 46 | * cpuidle_play_dead - cpu off-lining |
| 49 | * | 47 | * |
| @@ -278,7 +276,7 @@ static void poll_idle_init(struct cpuidle_driver *drv) {} | |||
| 278 | */ | 276 | */ |
| 279 | int cpuidle_enable_device(struct cpuidle_device *dev) | 277 | int cpuidle_enable_device(struct cpuidle_device *dev) |
| 280 | { | 278 | { |
| 281 | int ret, i; | 279 | int ret; |
| 282 | struct cpuidle_driver *drv; | 280 | struct cpuidle_driver *drv; |
| 283 | 281 | ||
| 284 | if (!dev) | 282 | if (!dev) |
| @@ -292,15 +290,12 @@ int cpuidle_enable_device(struct cpuidle_device *dev) | |||
| 292 | if (!drv || !cpuidle_curr_governor) | 290 | if (!drv || !cpuidle_curr_governor) |
| 293 | return -EIO; | 291 | return -EIO; |
| 294 | 292 | ||
| 293 | if (!dev->registered) | ||
| 294 | return -EINVAL; | ||
| 295 | |||
| 295 | if (!dev->state_count) | 296 | if (!dev->state_count) |
| 296 | dev->state_count = drv->state_count; | 297 | dev->state_count = drv->state_count; |
| 297 | 298 | ||
| 298 | if (dev->registered == 0) { | ||
| 299 | ret = __cpuidle_register_device(dev); | ||
| 300 | if (ret) | ||
| 301 | return ret; | ||
| 302 | } | ||
| 303 | |||
| 304 | poll_idle_init(drv); | 299 | poll_idle_init(drv); |
| 305 | 300 | ||
| 306 | ret = cpuidle_add_device_sysfs(dev); | 301 | ret = cpuidle_add_device_sysfs(dev); |
| @@ -311,12 +306,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev) | |||
| 311 | (ret = cpuidle_curr_governor->enable(drv, dev))) | 306 | (ret = cpuidle_curr_governor->enable(drv, dev))) |
| 312 | goto fail_sysfs; | 307 | goto fail_sysfs; |
| 313 | 308 | ||
| 314 | for (i = 0; i < dev->state_count; i++) { | ||
| 315 | dev->states_usage[i].usage = 0; | ||
| 316 | dev->states_usage[i].time = 0; | ||
| 317 | } | ||
| 318 | dev->last_residency = 0; | ||
| 319 | |||
| 320 | smp_wmb(); | 309 | smp_wmb(); |
| 321 | 310 | ||
| 322 | dev->enabled = 1; | 311 | dev->enabled = 1; |
| @@ -360,6 +349,23 @@ void cpuidle_disable_device(struct cpuidle_device *dev) | |||
| 360 | 349 | ||
| 361 | EXPORT_SYMBOL_GPL(cpuidle_disable_device); | 350 | EXPORT_SYMBOL_GPL(cpuidle_disable_device); |
| 362 | 351 | ||
| 352 | static void __cpuidle_unregister_device(struct cpuidle_device *dev) | ||
| 353 | { | ||
| 354 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); | ||
| 355 | |||
| 356 | list_del(&dev->device_list); | ||
| 357 | per_cpu(cpuidle_devices, dev->cpu) = NULL; | ||
| 358 | module_put(drv->owner); | ||
| 359 | } | ||
| 360 | |||
| 361 | static int __cpuidle_device_init(struct cpuidle_device *dev) | ||
| 362 | { | ||
| 363 | memset(dev->states_usage, 0, sizeof(dev->states_usage)); | ||
| 364 | dev->last_residency = 0; | ||
| 365 | |||
| 366 | return 0; | ||
| 367 | } | ||
| 368 | |||
| 363 | /** | 369 | /** |
| 364 | * __cpuidle_register_device - internal register function called before register | 370 | * __cpuidle_register_device - internal register function called before register |
| 365 | * and enable routines | 371 | * and enable routines |
| @@ -377,24 +383,15 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) | |||
| 377 | 383 | ||
| 378 | per_cpu(cpuidle_devices, dev->cpu) = dev; | 384 | per_cpu(cpuidle_devices, dev->cpu) = dev; |
| 379 | list_add(&dev->device_list, &cpuidle_detected_devices); | 385 | list_add(&dev->device_list, &cpuidle_detected_devices); |
| 380 | ret = cpuidle_add_sysfs(dev); | ||
| 381 | if (ret) | ||
| 382 | goto err_sysfs; | ||
| 383 | 386 | ||
| 384 | ret = cpuidle_coupled_register_device(dev); | 387 | ret = cpuidle_coupled_register_device(dev); |
| 385 | if (ret) | 388 | if (ret) { |
| 386 | goto err_coupled; | 389 | __cpuidle_unregister_device(dev); |
| 390 | return ret; | ||
| 391 | } | ||
| 387 | 392 | ||
| 388 | dev->registered = 1; | 393 | dev->registered = 1; |
| 389 | return 0; | 394 | return 0; |
| 390 | |||
| 391 | err_coupled: | ||
| 392 | cpuidle_remove_sysfs(dev); | ||
| 393 | err_sysfs: | ||
| 394 | list_del(&dev->device_list); | ||
| 395 | per_cpu(cpuidle_devices, dev->cpu) = NULL; | ||
| 396 | module_put(drv->owner); | ||
| 397 | return ret; | ||
| 398 | } | 395 | } |
| 399 | 396 | ||
| 400 | /** | 397 | /** |
| @@ -403,25 +400,44 @@ err_sysfs: | |||
| 403 | */ | 400 | */ |
| 404 | int cpuidle_register_device(struct cpuidle_device *dev) | 401 | int cpuidle_register_device(struct cpuidle_device *dev) |
| 405 | { | 402 | { |
| 406 | int ret; | 403 | int ret = -EBUSY; |
| 407 | 404 | ||
| 408 | if (!dev) | 405 | if (!dev) |
| 409 | return -EINVAL; | 406 | return -EINVAL; |
| 410 | 407 | ||
| 411 | mutex_lock(&cpuidle_lock); | 408 | mutex_lock(&cpuidle_lock); |
| 412 | 409 | ||
| 413 | if ((ret = __cpuidle_register_device(dev))) { | 410 | if (dev->registered) |
| 414 | mutex_unlock(&cpuidle_lock); | 411 | goto out_unlock; |
| 415 | return ret; | 412 | |
| 416 | } | 413 | ret = __cpuidle_device_init(dev); |
| 414 | if (ret) | ||
| 415 | goto out_unlock; | ||
| 416 | |||
| 417 | ret = __cpuidle_register_device(dev); | ||
| 418 | if (ret) | ||
| 419 | goto out_unlock; | ||
| 420 | |||
| 421 | ret = cpuidle_add_sysfs(dev); | ||
| 422 | if (ret) | ||
| 423 | goto out_unregister; | ||
| 424 | |||
| 425 | ret = cpuidle_enable_device(dev); | ||
| 426 | if (ret) | ||
| 427 | goto out_sysfs; | ||
| 417 | 428 | ||
| 418 | cpuidle_enable_device(dev); | ||
| 419 | cpuidle_install_idle_handler(); | 429 | cpuidle_install_idle_handler(); |
| 420 | 430 | ||
| 431 | out_unlock: | ||
| 421 | mutex_unlock(&cpuidle_lock); | 432 | mutex_unlock(&cpuidle_lock); |
| 422 | 433 | ||
| 423 | return 0; | 434 | return ret; |
| 424 | 435 | ||
| 436 | out_sysfs: | ||
| 437 | cpuidle_remove_sysfs(dev); | ||
| 438 | out_unregister: | ||
| 439 | __cpuidle_unregister_device(dev); | ||
| 440 | goto out_unlock; | ||
| 425 | } | 441 | } |
| 426 | 442 | ||
| 427 | EXPORT_SYMBOL_GPL(cpuidle_register_device); | 443 | EXPORT_SYMBOL_GPL(cpuidle_register_device); |
| @@ -432,8 +448,6 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device); | |||
| 432 | */ | 448 | */ |
| 433 | void cpuidle_unregister_device(struct cpuidle_device *dev) | 449 | void cpuidle_unregister_device(struct cpuidle_device *dev) |
| 434 | { | 450 | { |
| 435 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); | ||
| 436 | |||
| 437 | if (dev->registered == 0) | 451 | if (dev->registered == 0) |
| 438 | return; | 452 | return; |
| 439 | 453 | ||
| @@ -442,14 +456,12 @@ void cpuidle_unregister_device(struct cpuidle_device *dev) | |||
| 442 | cpuidle_disable_device(dev); | 456 | cpuidle_disable_device(dev); |
| 443 | 457 | ||
| 444 | cpuidle_remove_sysfs(dev); | 458 | cpuidle_remove_sysfs(dev); |
| 445 | list_del(&dev->device_list); | 459 | |
| 446 | per_cpu(cpuidle_devices, dev->cpu) = NULL; | 460 | __cpuidle_unregister_device(dev); |
| 447 | 461 | ||
| 448 | cpuidle_coupled_unregister_device(dev); | 462 | cpuidle_coupled_unregister_device(dev); |
| 449 | 463 | ||
| 450 | cpuidle_resume_and_unlock(); | 464 | cpuidle_resume_and_unlock(); |
| 451 | |||
| 452 | module_put(drv->owner); | ||
| 453 | } | 465 | } |
| 454 | 466 | ||
| 455 | EXPORT_SYMBOL_GPL(cpuidle_unregister_device); | 467 | EXPORT_SYMBOL_GPL(cpuidle_unregister_device); |
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c index 9b784051ec12..9f08e8cce1af 100644 --- a/drivers/cpuidle/governors/ladder.c +++ b/drivers/cpuidle/governors/ladder.c | |||
| @@ -192,14 +192,4 @@ static int __init init_ladder(void) | |||
| 192 | return cpuidle_register_governor(&ladder_governor); | 192 | return cpuidle_register_governor(&ladder_governor); |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | /** | 195 | postcore_initcall(init_ladder); |
| 196 | * exit_ladder - exits the governor | ||
| 197 | */ | ||
| 198 | static void __exit exit_ladder(void) | ||
| 199 | { | ||
| 200 | cpuidle_unregister_governor(&ladder_governor); | ||
| 201 | } | ||
| 202 | |||
| 203 | MODULE_LICENSE("GPL"); | ||
| 204 | module_init(init_ladder); | ||
| 205 | module_exit(exit_ladder); | ||
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index bc580b67a652..cf7f2f0e4ef5 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
| @@ -21,6 +21,15 @@ | |||
| 21 | #include <linux/math64.h> | 21 | #include <linux/math64.h> |
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | 23 | ||
| 24 | /* | ||
| 25 | * Please note when changing the tuning values: | ||
| 26 | * If (MAX_INTERESTING-1) * RESOLUTION > UINT_MAX, the result of | ||
| 27 | * a scaling operation multiplication may overflow on 32 bit platforms. | ||
| 28 | * In that case, #define RESOLUTION as ULL to get 64 bit result: | ||
| 29 | * #define RESOLUTION 1024ULL | ||
| 30 | * | ||
| 31 | * The default values do not overflow. | ||
| 32 | */ | ||
| 24 | #define BUCKETS 12 | 33 | #define BUCKETS 12 |
| 25 | #define INTERVALS 8 | 34 | #define INTERVALS 8 |
| 26 | #define RESOLUTION 1024 | 35 | #define RESOLUTION 1024 |
| @@ -114,11 +123,11 @@ struct menu_device { | |||
| 114 | int needs_update; | 123 | int needs_update; |
| 115 | 124 | ||
| 116 | unsigned int expected_us; | 125 | unsigned int expected_us; |
| 117 | u64 predicted_us; | 126 | unsigned int predicted_us; |
| 118 | unsigned int exit_us; | 127 | unsigned int exit_us; |
| 119 | unsigned int bucket; | 128 | unsigned int bucket; |
| 120 | u64 correction_factor[BUCKETS]; | 129 | unsigned int correction_factor[BUCKETS]; |
| 121 | u32 intervals[INTERVALS]; | 130 | unsigned int intervals[INTERVALS]; |
| 122 | int interval_ptr; | 131 | int interval_ptr; |
| 123 | }; | 132 | }; |
| 124 | 133 | ||
| @@ -199,16 +208,20 @@ static u64 div_round64(u64 dividend, u32 divisor) | |||
| 199 | */ | 208 | */ |
| 200 | static void get_typical_interval(struct menu_device *data) | 209 | static void get_typical_interval(struct menu_device *data) |
| 201 | { | 210 | { |
| 202 | int i = 0, divisor = 0; | 211 | int i, divisor; |
| 203 | uint64_t max = 0, avg = 0, stddev = 0; | 212 | unsigned int max, thresh; |
| 204 | int64_t thresh = LLONG_MAX; /* Discard outliers above this value. */ | 213 | uint64_t avg, stddev; |
| 214 | |||
| 215 | thresh = UINT_MAX; /* Discard outliers above this value */ | ||
| 205 | 216 | ||
| 206 | again: | 217 | again: |
| 207 | 218 | ||
| 208 | /* first calculate average and standard deviation of the past */ | 219 | /* First calculate the average of past intervals */ |
| 209 | max = avg = divisor = stddev = 0; | 220 | max = 0; |
| 221 | avg = 0; | ||
| 222 | divisor = 0; | ||
| 210 | for (i = 0; i < INTERVALS; i++) { | 223 | for (i = 0; i < INTERVALS; i++) { |
| 211 | int64_t value = data->intervals[i]; | 224 | unsigned int value = data->intervals[i]; |
| 212 | if (value <= thresh) { | 225 | if (value <= thresh) { |
| 213 | avg += value; | 226 | avg += value; |
| 214 | divisor++; | 227 | divisor++; |
| @@ -218,15 +231,38 @@ again: | |||
| 218 | } | 231 | } |
| 219 | do_div(avg, divisor); | 232 | do_div(avg, divisor); |
| 220 | 233 | ||
| 234 | /* Then try to determine standard deviation */ | ||
| 235 | stddev = 0; | ||
| 221 | for (i = 0; i < INTERVALS; i++) { | 236 | for (i = 0; i < INTERVALS; i++) { |
| 222 | int64_t value = data->intervals[i]; | 237 | unsigned int value = data->intervals[i]; |
| 223 | if (value <= thresh) { | 238 | if (value <= thresh) { |
| 224 | int64_t diff = value - avg; | 239 | int64_t diff = value - avg; |
| 225 | stddev += diff * diff; | 240 | stddev += diff * diff; |
| 226 | } | 241 | } |
| 227 | } | 242 | } |
| 228 | do_div(stddev, divisor); | 243 | do_div(stddev, divisor); |
| 229 | stddev = int_sqrt(stddev); | 244 | /* |
| 245 | * The typical interval is obtained when standard deviation is small | ||
| 246 | * or standard deviation is small compared to the average interval. | ||
| 247 | * | ||
| 248 | * int_sqrt() formal parameter type is unsigned long. When the | ||
| 249 | * greatest difference to an outlier exceeds ~65 ms * sqrt(divisor) | ||
| 250 | * the resulting squared standard deviation exceeds the input domain | ||
| 251 | * of int_sqrt on platforms where unsigned long is 32 bits in size. | ||
| 252 | * In such case reject the candidate average. | ||
| 253 | * | ||
| 254 | * Use this result only if there is no timer to wake us up sooner. | ||
| 255 | */ | ||
| 256 | if (likely(stddev <= ULONG_MAX)) { | ||
| 257 | stddev = int_sqrt(stddev); | ||
| 258 | if (((avg > stddev * 6) && (divisor * 4 >= INTERVALS * 3)) | ||
| 259 | || stddev <= 20) { | ||
| 260 | if (data->expected_us > avg) | ||
| 261 | data->predicted_us = avg; | ||
| 262 | return; | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 230 | /* | 266 | /* |
| 231 | * If we have outliers to the upside in our distribution, discard | 267 | * If we have outliers to the upside in our distribution, discard |
| 232 | * those by setting the threshold to exclude these outliers, then | 268 | * those by setting the threshold to exclude these outliers, then |
| @@ -235,20 +271,12 @@ again: | |||
| 235 | * | 271 | * |
| 236 | * This can deal with workloads that have long pauses interspersed | 272 | * This can deal with workloads that have long pauses interspersed |
| 237 | * with sporadic activity with a bunch of short pauses. | 273 | * with sporadic activity with a bunch of short pauses. |
| 238 | * | ||
| 239 | * The typical interval is obtained when standard deviation is small | ||
| 240 | * or standard deviation is small compared to the average interval. | ||
| 241 | */ | 274 | */ |
| 242 | if (((avg > stddev * 6) && (divisor * 4 >= INTERVALS * 3)) | 275 | if ((divisor * 4) <= INTERVALS * 3) |
| 243 | || stddev <= 20) { | ||
| 244 | data->predicted_us = avg; | ||
| 245 | return; | 276 | return; |
| 246 | 277 | ||
| 247 | } else if ((divisor * 4) > INTERVALS * 3) { | 278 | thresh = max - 1; |
| 248 | /* Exclude the max interval */ | 279 | goto again; |
| 249 | thresh = max - 1; | ||
| 250 | goto again; | ||
| 251 | } | ||
| 252 | } | 280 | } |
| 253 | 281 | ||
| 254 | /** | 282 | /** |
| @@ -293,8 +321,13 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
| 293 | if (data->correction_factor[data->bucket] == 0) | 321 | if (data->correction_factor[data->bucket] == 0) |
| 294 | data->correction_factor[data->bucket] = RESOLUTION * DECAY; | 322 | data->correction_factor[data->bucket] = RESOLUTION * DECAY; |
| 295 | 323 | ||
| 296 | /* Make sure to round up for half microseconds */ | 324 | /* |
| 297 | data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket], | 325 | * Force the result of multiplication to be 64 bits even if both |
| 326 | * operands are 32 bits. | ||
| 327 | * Make sure to round up for half microseconds. | ||
| 328 | */ | ||
| 329 | data->predicted_us = div_round64((uint64_t)data->expected_us * | ||
| 330 | data->correction_factor[data->bucket], | ||
| 298 | RESOLUTION * DECAY); | 331 | RESOLUTION * DECAY); |
| 299 | 332 | ||
| 300 | get_typical_interval(data); | 333 | get_typical_interval(data); |
| @@ -360,7 +393,7 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
| 360 | unsigned int last_idle_us = cpuidle_get_last_residency(dev); | 393 | unsigned int last_idle_us = cpuidle_get_last_residency(dev); |
| 361 | struct cpuidle_state *target = &drv->states[last_idx]; | 394 | struct cpuidle_state *target = &drv->states[last_idx]; |
| 362 | unsigned int measured_us; | 395 | unsigned int measured_us; |
| 363 | u64 new_factor; | 396 | unsigned int new_factor; |
| 364 | 397 | ||
| 365 | /* | 398 | /* |
| 366 | * Ugh, this idle state doesn't support residency measurements, so we | 399 | * Ugh, this idle state doesn't support residency measurements, so we |
| @@ -381,10 +414,9 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
| 381 | measured_us -= data->exit_us; | 414 | measured_us -= data->exit_us; |
| 382 | 415 | ||
| 383 | 416 | ||
| 384 | /* update our correction ratio */ | 417 | /* Update our correction ratio */ |
| 385 | 418 | new_factor = data->correction_factor[data->bucket]; | |
| 386 | new_factor = data->correction_factor[data->bucket] | 419 | new_factor -= new_factor / DECAY; |
| 387 | * (DECAY - 1) / DECAY; | ||
| 388 | 420 | ||
| 389 | if (data->expected_us > 0 && measured_us < MAX_INTERESTING) | 421 | if (data->expected_us > 0 && measured_us < MAX_INTERESTING) |
| 390 | new_factor += RESOLUTION * measured_us / data->expected_us; | 422 | new_factor += RESOLUTION * measured_us / data->expected_us; |
| @@ -397,9 +429,11 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
| 397 | 429 | ||
| 398 | /* | 430 | /* |
| 399 | * We don't want 0 as factor; we always want at least | 431 | * We don't want 0 as factor; we always want at least |
| 400 | * a tiny bit of estimated time. | 432 | * a tiny bit of estimated time. Fortunately, due to rounding, |
| 433 | * new_factor will stay nonzero regardless of measured_us values | ||
| 434 | * and the compiler can eliminate this test as long as DECAY > 1. | ||
| 401 | */ | 435 | */ |
| 402 | if (new_factor == 0) | 436 | if (DECAY == 1 && unlikely(new_factor == 0)) |
| 403 | new_factor = 1; | 437 | new_factor = 1; |
| 404 | 438 | ||
| 405 | data->correction_factor[data->bucket] = new_factor; | 439 | data->correction_factor[data->bucket] = new_factor; |
| @@ -442,14 +476,4 @@ static int __init init_menu(void) | |||
| 442 | return cpuidle_register_governor(&menu_governor); | 476 | return cpuidle_register_governor(&menu_governor); |
| 443 | } | 477 | } |
| 444 | 478 | ||
| 445 | /** | 479 | postcore_initcall(init_menu); |
| 446 | * exit_menu - exits the governor | ||
| 447 | */ | ||
| 448 | static void __exit exit_menu(void) | ||
| 449 | { | ||
| 450 | cpuidle_unregister_governor(&menu_governor); | ||
| 451 | } | ||
| 452 | |||
| 453 | MODULE_LICENSE("GPL"); | ||
| 454 | module_init(init_menu); | ||
| 455 | module_exit(exit_menu); | ||
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 428754af6236..8739cc05228c 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c | |||
| @@ -11,8 +11,10 @@ | |||
| 11 | #include <linux/sysfs.h> | 11 | #include <linux/sysfs.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/cpu.h> | 13 | #include <linux/cpu.h> |
| 14 | #include <linux/completion.h> | ||
| 14 | #include <linux/capability.h> | 15 | #include <linux/capability.h> |
| 15 | #include <linux/device.h> | 16 | #include <linux/device.h> |
| 17 | #include <linux/kobject.h> | ||
| 16 | 18 | ||
| 17 | #include "cpuidle.h" | 19 | #include "cpuidle.h" |
| 18 | 20 | ||
| @@ -33,7 +35,8 @@ static ssize_t show_available_governors(struct device *dev, | |||
| 33 | 35 | ||
| 34 | mutex_lock(&cpuidle_lock); | 36 | mutex_lock(&cpuidle_lock); |
| 35 | list_for_each_entry(tmp, &cpuidle_governors, governor_list) { | 37 | list_for_each_entry(tmp, &cpuidle_governors, governor_list) { |
| 36 | if (i >= (ssize_t) ((PAGE_SIZE/sizeof(char)) - CPUIDLE_NAME_LEN - 2)) | 38 | if (i >= (ssize_t) ((PAGE_SIZE/sizeof(char)) - |
| 39 | CPUIDLE_NAME_LEN - 2)) | ||
| 37 | goto out; | 40 | goto out; |
| 38 | i += scnprintf(&buf[i], CPUIDLE_NAME_LEN, "%s ", tmp->name); | 41 | i += scnprintf(&buf[i], CPUIDLE_NAME_LEN, "%s ", tmp->name); |
| 39 | } | 42 | } |
| @@ -166,13 +169,28 @@ struct cpuidle_attr { | |||
| 166 | #define define_one_rw(_name, show, store) \ | 169 | #define define_one_rw(_name, show, store) \ |
| 167 | static struct cpuidle_attr attr_##_name = __ATTR(_name, 0644, show, store) | 170 | static struct cpuidle_attr attr_##_name = __ATTR(_name, 0644, show, store) |
| 168 | 171 | ||
| 169 | #define kobj_to_cpuidledev(k) container_of(k, struct cpuidle_device, kobj) | ||
| 170 | #define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr) | 172 | #define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr) |
| 171 | static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char * buf) | 173 | |
| 174 | struct cpuidle_device_kobj { | ||
| 175 | struct cpuidle_device *dev; | ||
| 176 | struct completion kobj_unregister; | ||
| 177 | struct kobject kobj; | ||
| 178 | }; | ||
| 179 | |||
| 180 | static inline struct cpuidle_device *to_cpuidle_device(struct kobject *kobj) | ||
| 181 | { | ||
| 182 | struct cpuidle_device_kobj *kdev = | ||
| 183 | container_of(kobj, struct cpuidle_device_kobj, kobj); | ||
| 184 | |||
| 185 | return kdev->dev; | ||
| 186 | } | ||
| 187 | |||
| 188 | static ssize_t cpuidle_show(struct kobject *kobj, struct attribute *attr, | ||
| 189 | char *buf) | ||
| 172 | { | 190 | { |
| 173 | int ret = -EIO; | 191 | int ret = -EIO; |
| 174 | struct cpuidle_device *dev = kobj_to_cpuidledev(kobj); | 192 | struct cpuidle_device *dev = to_cpuidle_device(kobj); |
| 175 | struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr); | 193 | struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr); |
| 176 | 194 | ||
| 177 | if (cattr->show) { | 195 | if (cattr->show) { |
| 178 | mutex_lock(&cpuidle_lock); | 196 | mutex_lock(&cpuidle_lock); |
| @@ -182,12 +200,12 @@ static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char | |||
| 182 | return ret; | 200 | return ret; |
| 183 | } | 201 | } |
| 184 | 202 | ||
| 185 | static ssize_t cpuidle_store(struct kobject * kobj, struct attribute * attr, | 203 | static ssize_t cpuidle_store(struct kobject *kobj, struct attribute *attr, |
| 186 | const char * buf, size_t count) | 204 | const char *buf, size_t count) |
| 187 | { | 205 | { |
| 188 | int ret = -EIO; | 206 | int ret = -EIO; |
| 189 | struct cpuidle_device *dev = kobj_to_cpuidledev(kobj); | 207 | struct cpuidle_device *dev = to_cpuidle_device(kobj); |
| 190 | struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr); | 208 | struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr); |
| 191 | 209 | ||
| 192 | if (cattr->store) { | 210 | if (cattr->store) { |
| 193 | mutex_lock(&cpuidle_lock); | 211 | mutex_lock(&cpuidle_lock); |
| @@ -204,9 +222,10 @@ static const struct sysfs_ops cpuidle_sysfs_ops = { | |||
| 204 | 222 | ||
| 205 | static void cpuidle_sysfs_release(struct kobject *kobj) | 223 | static void cpuidle_sysfs_release(struct kobject *kobj) |
| 206 | { | 224 | { |
| 207 | struct cpuidle_device *dev = kobj_to_cpuidledev(kobj); | 225 | struct cpuidle_device_kobj *kdev = |
| 226 | container_of(kobj, struct cpuidle_device_kobj, kobj); | ||
| 208 | 227 | ||
| 209 | complete(&dev->kobj_unregister); | 228 | complete(&kdev->kobj_unregister); |
| 210 | } | 229 | } |
| 211 | 230 | ||
| 212 | static struct kobj_type ktype_cpuidle = { | 231 | static struct kobj_type ktype_cpuidle = { |
| @@ -237,8 +256,8 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \ | |||
| 237 | 256 | ||
| 238 | #define define_store_state_ull_function(_name) \ | 257 | #define define_store_state_ull_function(_name) \ |
| 239 | static ssize_t store_state_##_name(struct cpuidle_state *state, \ | 258 | static ssize_t store_state_##_name(struct cpuidle_state *state, \ |
| 240 | struct cpuidle_state_usage *state_usage, \ | 259 | struct cpuidle_state_usage *state_usage, \ |
| 241 | const char *buf, size_t size) \ | 260 | const char *buf, size_t size) \ |
| 242 | { \ | 261 | { \ |
| 243 | unsigned long long value; \ | 262 | unsigned long long value; \ |
| 244 | int err; \ | 263 | int err; \ |
| @@ -256,14 +275,16 @@ static ssize_t store_state_##_name(struct cpuidle_state *state, \ | |||
| 256 | 275 | ||
| 257 | #define define_show_state_ull_function(_name) \ | 276 | #define define_show_state_ull_function(_name) \ |
| 258 | static ssize_t show_state_##_name(struct cpuidle_state *state, \ | 277 | static ssize_t show_state_##_name(struct cpuidle_state *state, \ |
| 259 | struct cpuidle_state_usage *state_usage, char *buf) \ | 278 | struct cpuidle_state_usage *state_usage, \ |
| 279 | char *buf) \ | ||
| 260 | { \ | 280 | { \ |
| 261 | return sprintf(buf, "%llu\n", state_usage->_name);\ | 281 | return sprintf(buf, "%llu\n", state_usage->_name);\ |
| 262 | } | 282 | } |
| 263 | 283 | ||
| 264 | #define define_show_state_str_function(_name) \ | 284 | #define define_show_state_str_function(_name) \ |
| 265 | static ssize_t show_state_##_name(struct cpuidle_state *state, \ | 285 | static ssize_t show_state_##_name(struct cpuidle_state *state, \ |
| 266 | struct cpuidle_state_usage *state_usage, char *buf) \ | 286 | struct cpuidle_state_usage *state_usage, \ |
| 287 | char *buf) \ | ||
| 267 | { \ | 288 | { \ |
| 268 | if (state->_name[0] == '\0')\ | 289 | if (state->_name[0] == '\0')\ |
| 269 | return sprintf(buf, "<null>\n");\ | 290 | return sprintf(buf, "<null>\n");\ |
| @@ -309,8 +330,9 @@ struct cpuidle_state_kobj { | |||
| 309 | #define kobj_to_state(k) (kobj_to_state_obj(k)->state) | 330 | #define kobj_to_state(k) (kobj_to_state_obj(k)->state) |
| 310 | #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage) | 331 | #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage) |
| 311 | #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr) | 332 | #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr) |
| 312 | static ssize_t cpuidle_state_show(struct kobject * kobj, | 333 | |
| 313 | struct attribute * attr ,char * buf) | 334 | static ssize_t cpuidle_state_show(struct kobject *kobj, struct attribute *attr, |
| 335 | char * buf) | ||
| 314 | { | 336 | { |
| 315 | int ret = -EIO; | 337 | int ret = -EIO; |
| 316 | struct cpuidle_state *state = kobj_to_state(kobj); | 338 | struct cpuidle_state *state = kobj_to_state(kobj); |
| @@ -323,8 +345,8 @@ static ssize_t cpuidle_state_show(struct kobject * kobj, | |||
| 323 | return ret; | 345 | return ret; |
| 324 | } | 346 | } |
| 325 | 347 | ||
| 326 | static ssize_t cpuidle_state_store(struct kobject *kobj, | 348 | static ssize_t cpuidle_state_store(struct kobject *kobj, struct attribute *attr, |
| 327 | struct attribute *attr, const char *buf, size_t size) | 349 | const char *buf, size_t size) |
| 328 | { | 350 | { |
| 329 | int ret = -EIO; | 351 | int ret = -EIO; |
| 330 | struct cpuidle_state *state = kobj_to_state(kobj); | 352 | struct cpuidle_state *state = kobj_to_state(kobj); |
| @@ -371,6 +393,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) | |||
| 371 | { | 393 | { |
| 372 | int i, ret = -ENOMEM; | 394 | int i, ret = -ENOMEM; |
| 373 | struct cpuidle_state_kobj *kobj; | 395 | struct cpuidle_state_kobj *kobj; |
| 396 | struct cpuidle_device_kobj *kdev = device->kobj_dev; | ||
| 374 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); | 397 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); |
| 375 | 398 | ||
| 376 | /* state statistics */ | 399 | /* state statistics */ |
| @@ -383,7 +406,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) | |||
| 383 | init_completion(&kobj->kobj_unregister); | 406 | init_completion(&kobj->kobj_unregister); |
| 384 | 407 | ||
| 385 | ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, | 408 | ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, |
| 386 | &device->kobj, "state%d", i); | 409 | &kdev->kobj, "state%d", i); |
| 387 | if (ret) { | 410 | if (ret) { |
| 388 | kfree(kobj); | 411 | kfree(kobj); |
| 389 | goto error_state; | 412 | goto error_state; |
| @@ -449,8 +472,8 @@ static void cpuidle_driver_sysfs_release(struct kobject *kobj) | |||
| 449 | complete(&driver_kobj->kobj_unregister); | 472 | complete(&driver_kobj->kobj_unregister); |
| 450 | } | 473 | } |
| 451 | 474 | ||
| 452 | static ssize_t cpuidle_driver_show(struct kobject *kobj, struct attribute * attr, | 475 | static ssize_t cpuidle_driver_show(struct kobject *kobj, struct attribute *attr, |
| 453 | char * buf) | 476 | char *buf) |
| 454 | { | 477 | { |
| 455 | int ret = -EIO; | 478 | int ret = -EIO; |
| 456 | struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj); | 479 | struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj); |
| @@ -500,6 +523,7 @@ static struct kobj_type ktype_driver_cpuidle = { | |||
| 500 | static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev) | 523 | static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev) |
| 501 | { | 524 | { |
| 502 | struct cpuidle_driver_kobj *kdrv; | 525 | struct cpuidle_driver_kobj *kdrv; |
| 526 | struct cpuidle_device_kobj *kdev = dev->kobj_dev; | ||
| 503 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); | 527 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); |
| 504 | int ret; | 528 | int ret; |
| 505 | 529 | ||
| @@ -511,7 +535,7 @@ static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev) | |||
| 511 | init_completion(&kdrv->kobj_unregister); | 535 | init_completion(&kdrv->kobj_unregister); |
| 512 | 536 | ||
| 513 | ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle, | 537 | ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle, |
| 514 | &dev->kobj, "driver"); | 538 | &kdev->kobj, "driver"); |
| 515 | if (ret) { | 539 | if (ret) { |
| 516 | kfree(kdrv); | 540 | kfree(kdrv); |
| 517 | return ret; | 541 | return ret; |
| @@ -580,16 +604,28 @@ void cpuidle_remove_device_sysfs(struct cpuidle_device *device) | |||
| 580 | */ | 604 | */ |
| 581 | int cpuidle_add_sysfs(struct cpuidle_device *dev) | 605 | int cpuidle_add_sysfs(struct cpuidle_device *dev) |
| 582 | { | 606 | { |
| 607 | struct cpuidle_device_kobj *kdev; | ||
| 583 | struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu); | 608 | struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu); |
| 584 | int error; | 609 | int error; |
| 585 | 610 | ||
| 586 | init_completion(&dev->kobj_unregister); | 611 | kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); |
| 612 | if (!kdev) | ||
| 613 | return -ENOMEM; | ||
| 614 | kdev->dev = dev; | ||
| 615 | dev->kobj_dev = kdev; | ||
| 587 | 616 | ||
| 588 | error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &cpu_dev->kobj, | 617 | init_completion(&kdev->kobj_unregister); |
| 589 | "cpuidle"); | 618 | |
| 590 | if (!error) | 619 | error = kobject_init_and_add(&kdev->kobj, &ktype_cpuidle, &cpu_dev->kobj, |
| 591 | kobject_uevent(&dev->kobj, KOBJ_ADD); | 620 | "cpuidle"); |
| 592 | return error; | 621 | if (error) { |
| 622 | kfree(kdev); | ||
| 623 | return error; | ||
| 624 | } | ||
| 625 | |||
| 626 | kobject_uevent(&kdev->kobj, KOBJ_ADD); | ||
| 627 | |||
| 628 | return 0; | ||
| 593 | } | 629 | } |
| 594 | 630 | ||
| 595 | /** | 631 | /** |
| @@ -598,6 +634,9 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev) | |||
| 598 | */ | 634 | */ |
| 599 | void cpuidle_remove_sysfs(struct cpuidle_device *dev) | 635 | void cpuidle_remove_sysfs(struct cpuidle_device *dev) |
| 600 | { | 636 | { |
| 601 | kobject_put(&dev->kobj); | 637 | struct cpuidle_device_kobj *kdev = dev->kobj_dev; |
| 602 | wait_for_completion(&dev->kobj_unregister); | 638 | |
| 639 | kobject_put(&kdev->kobj); | ||
| 640 | wait_for_completion(&kdev->kobj_unregister); | ||
| 641 | kfree(kdev); | ||
| 603 | } | 642 | } |
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 3c157faee645..0d68eb1a5ec5 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c | |||
| @@ -3094,6 +3094,10 @@ static struct mfd_cell db8500_prcmu_devs[] = { | |||
| 3094 | .pdata_size = sizeof(db8500_cpufreq_table), | 3094 | .pdata_size = sizeof(db8500_cpufreq_table), |
| 3095 | }, | 3095 | }, |
| 3096 | { | 3096 | { |
| 3097 | .name = "cpuidle-dbx500", | ||
| 3098 | .of_compatible = "stericsson,cpuidle-dbx500", | ||
| 3099 | }, | ||
| 3100 | { | ||
| 3097 | .name = "db8500-thermal", | 3101 | .name = "db8500-thermal", |
| 3098 | .num_resources = ARRAY_SIZE(db8500_thsens_resources), | 3102 | .num_resources = ARRAY_SIZE(db8500_thsens_resources), |
| 3099 | .resources = db8500_thsens_resources, | 3103 | .resources = db8500_thsens_resources, |
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 0bc4b74668e9..781addc66f03 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h | |||
| @@ -13,8 +13,6 @@ | |||
| 13 | 13 | ||
| 14 | #include <linux/percpu.h> | 14 | #include <linux/percpu.h> |
| 15 | #include <linux/list.h> | 15 | #include <linux/list.h> |
| 16 | #include <linux/kobject.h> | ||
| 17 | #include <linux/completion.h> | ||
| 18 | #include <linux/hrtimer.h> | 16 | #include <linux/hrtimer.h> |
| 19 | 17 | ||
| 20 | #define CPUIDLE_STATE_MAX 10 | 18 | #define CPUIDLE_STATE_MAX 10 |
| @@ -61,6 +59,10 @@ struct cpuidle_state { | |||
| 61 | 59 | ||
| 62 | #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) | 60 | #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) |
| 63 | 61 | ||
| 62 | struct cpuidle_device_kobj; | ||
| 63 | struct cpuidle_state_kobj; | ||
| 64 | struct cpuidle_driver_kobj; | ||
| 65 | |||
| 64 | struct cpuidle_device { | 66 | struct cpuidle_device { |
| 65 | unsigned int registered:1; | 67 | unsigned int registered:1; |
| 66 | unsigned int enabled:1; | 68 | unsigned int enabled:1; |
| @@ -71,9 +73,8 @@ struct cpuidle_device { | |||
| 71 | struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; | 73 | struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; |
| 72 | struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX]; | 74 | struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX]; |
| 73 | struct cpuidle_driver_kobj *kobj_driver; | 75 | struct cpuidle_driver_kobj *kobj_driver; |
| 76 | struct cpuidle_device_kobj *kobj_dev; | ||
| 74 | struct list_head device_list; | 77 | struct list_head device_list; |
| 75 | struct kobject kobj; | ||
| 76 | struct completion kobj_unregister; | ||
| 77 | 78 | ||
| 78 | #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED | 79 | #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED |
| 79 | int safe_state_index; | 80 | int safe_state_index; |
