aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2013-02-09 21:10:04 -0500
committerLen Brown <len.brown@intel.com>2013-02-17 23:34:46 -0500
commitdd8af076262cc1ff85a8d5e0c5b1a4716d19fe25 (patch)
tree793a32e3d0bfc64f77d349fbf61054aabfc8b087
parent88b62b915b0b7e25870eb0604ed9a92ba4bfc9f7 (diff)
APM idle: register apm_cpu_idle via cpuidle
Update APM to register its local idle routine with cpuidle. This allows us to stop exporting pm_idle to modules on x86. The Kconfig sub-option, APM_CPU_IDLE, now depends on on CPU_IDLE. Compile-tested only. Signed-off-by: Len Brown <len.brown@intel.com> Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org> Cc: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/kernel/apm_32.c57
-rw-r--r--arch/x86/kernel/process.c3
3 files changed, 35 insertions, 26 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 225543bf45a5..1b635861401c 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1912,6 +1912,7 @@ config APM_DO_ENABLE
1912 this feature. 1912 this feature.
1913 1913
1914config APM_CPU_IDLE 1914config APM_CPU_IDLE
1915 depends on CPU_IDLE
1915 bool "Make CPU Idle calls when idle" 1916 bool "Make CPU Idle calls when idle"
1916 ---help--- 1917 ---help---
1917 Enable calls to APM CPU Idle/CPU Busy inside the kernel's idle loop. 1918 Enable calls to APM CPU Idle/CPU Busy inside the kernel's idle loop.
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index d65464e43503..9f4bc6a1164d 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -232,6 +232,7 @@
232#include <linux/acpi.h> 232#include <linux/acpi.h>
233#include <linux/syscore_ops.h> 233#include <linux/syscore_ops.h>
234#include <linux/i8253.h> 234#include <linux/i8253.h>
235#include <linux/cpuidle.h>
235 236
236#include <asm/uaccess.h> 237#include <asm/uaccess.h>
237#include <asm/desc.h> 238#include <asm/desc.h>
@@ -360,13 +361,35 @@ struct apm_user {
360 * idle percentage above which bios idle calls are done 361 * idle percentage above which bios idle calls are done
361 */ 362 */
362#ifdef CONFIG_APM_CPU_IDLE 363#ifdef CONFIG_APM_CPU_IDLE
363#warning deprecated CONFIG_APM_CPU_IDLE will be deleted in 2012
364#define DEFAULT_IDLE_THRESHOLD 95 364#define DEFAULT_IDLE_THRESHOLD 95
365#else 365#else
366#define DEFAULT_IDLE_THRESHOLD 100 366#define DEFAULT_IDLE_THRESHOLD 100
367#endif 367#endif
368#define DEFAULT_IDLE_PERIOD (100 / 3) 368#define DEFAULT_IDLE_PERIOD (100 / 3)
369 369
370static int apm_cpu_idle(struct cpuidle_device *dev,
371 struct cpuidle_driver *drv, int index);
372
373static struct cpuidle_driver apm_idle_driver = {
374 .name = "apm_idle",
375 .owner = THIS_MODULE,
376 .en_core_tk_irqen = 1,
377 .states = {
378 { /* entry 0 is for polling */ },
379 { /* entry 1 is for APM idle */
380 .name = "APM",
381 .desc = "APM idle",
382 .flags = CPUIDLE_FLAG_TIME_VALID,
383 .exit_latency = 250, /* WAG */
384 .target_residency = 500, /* WAG */
385 .enter = &apm_cpu_idle
386 },
387 },
388 .state_count = 2,
389};
390
391static struct cpuidle_device apm_cpuidle_device;
392
370/* 393/*
371 * Local variables 394 * Local variables
372 */ 395 */
@@ -377,7 +400,6 @@ static struct {
377static int clock_slowed; 400static int clock_slowed;
378static int idle_threshold __read_mostly = DEFAULT_IDLE_THRESHOLD; 401static int idle_threshold __read_mostly = DEFAULT_IDLE_THRESHOLD;
379static int idle_period __read_mostly = DEFAULT_IDLE_PERIOD; 402static int idle_period __read_mostly = DEFAULT_IDLE_PERIOD;
380static int set_pm_idle;
381static int suspends_pending; 403static int suspends_pending;
382static int standbys_pending; 404static int standbys_pending;
383static int ignore_sys_suspend; 405static int ignore_sys_suspend;
@@ -884,8 +906,6 @@ static void apm_do_busy(void)
884#define IDLE_CALC_LIMIT (HZ * 100) 906#define IDLE_CALC_LIMIT (HZ * 100)
885#define IDLE_LEAKY_MAX 16 907#define IDLE_LEAKY_MAX 16
886 908
887static void (*original_pm_idle)(void) __read_mostly;
888
889/** 909/**
890 * apm_cpu_idle - cpu idling for APM capable Linux 910 * apm_cpu_idle - cpu idling for APM capable Linux
891 * 911 *
@@ -894,7 +914,8 @@ static void (*original_pm_idle)(void) __read_mostly;
894 * Furthermore it calls the system default idle routine. 914 * Furthermore it calls the system default idle routine.
895 */ 915 */
896 916
897static void apm_cpu_idle(void) 917static int apm_cpu_idle(struct cpuidle_device *dev,
918 struct cpuidle_driver *drv, int index)
898{ 919{
899 static int use_apm_idle; /* = 0 */ 920 static int use_apm_idle; /* = 0 */
900 static unsigned int last_jiffies; /* = 0 */ 921 static unsigned int last_jiffies; /* = 0 */
@@ -904,7 +925,6 @@ static void apm_cpu_idle(void)
904 unsigned int jiffies_since_last_check = jiffies - last_jiffies; 925 unsigned int jiffies_since_last_check = jiffies - last_jiffies;
905 unsigned int bucket; 926 unsigned int bucket;
906 927
907 WARN_ONCE(1, "deprecated apm_cpu_idle will be deleted in 2012");
908recalc: 928recalc:
909 if (jiffies_since_last_check > IDLE_CALC_LIMIT) { 929 if (jiffies_since_last_check > IDLE_CALC_LIMIT) {
910 use_apm_idle = 0; 930 use_apm_idle = 0;
@@ -950,10 +970,7 @@ recalc:
950 break; 970 break;
951 } 971 }
952 } 972 }
953 if (original_pm_idle) 973 default_idle();
954 original_pm_idle();
955 else
956 default_idle();
957 local_irq_disable(); 974 local_irq_disable();
958 jiffies_since_last_check = jiffies - last_jiffies; 975 jiffies_since_last_check = jiffies - last_jiffies;
959 if (jiffies_since_last_check > idle_period) 976 if (jiffies_since_last_check > idle_period)
@@ -963,7 +980,7 @@ recalc:
963 if (apm_idle_done) 980 if (apm_idle_done)
964 apm_do_busy(); 981 apm_do_busy();
965 982
966 local_irq_enable(); 983 return index;
967} 984}
968 985
969/** 986/**
@@ -2381,9 +2398,9 @@ static int __init apm_init(void)
2381 if (HZ != 100) 2398 if (HZ != 100)
2382 idle_period = (idle_period * HZ) / 100; 2399 idle_period = (idle_period * HZ) / 100;
2383 if (idle_threshold < 100) { 2400 if (idle_threshold < 100) {
2384 original_pm_idle = pm_idle; 2401 if (!cpuidle_register_driver(&apm_idle_driver))
2385 pm_idle = apm_cpu_idle; 2402 if (cpuidle_register_device(&apm_cpuidle_device))
2386 set_pm_idle = 1; 2403 cpuidle_unregister_driver(&apm_idle_driver);
2387 } 2404 }
2388 2405
2389 return 0; 2406 return 0;
@@ -2393,15 +2410,9 @@ static void __exit apm_exit(void)
2393{ 2410{
2394 int error; 2411 int error;
2395 2412
2396 if (set_pm_idle) { 2413 cpuidle_unregister_device(&apm_cpuidle_device);
2397 pm_idle = original_pm_idle; 2414 cpuidle_unregister_driver(&apm_idle_driver);
2398 /* 2415
2399 * We are about to unload the current idle thread pm callback
2400 * (pm_idle), Wait for all processors to update cached/local
2401 * copies of pm_idle before proceeding.
2402 */
2403 kick_all_cpus_sync();
2404 }
2405 if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0) 2416 if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
2406 && (apm_info.connection_version > 0x0100)) { 2417 && (apm_info.connection_version > 0x0100)) {
2407 error = apm_engage_power_management(APM_DEVICE_ALL, 0); 2418 error = apm_engage_power_management(APM_DEVICE_ALL, 0);
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 2ed787f15bf0..f571a6e08710 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -272,9 +272,6 @@ EXPORT_SYMBOL(boot_option_idle_override);
272 * Powermanagement idle function, if any.. 272 * Powermanagement idle function, if any..
273 */ 273 */
274void (*pm_idle)(void); 274void (*pm_idle)(void);
275#ifdef CONFIG_APM_MODULE
276EXPORT_SYMBOL(pm_idle);
277#endif
278 275
279#ifndef CONFIG_SMP 276#ifndef CONFIG_SMP
280static inline void play_dead(void) 277static inline void play_dead(void)