diff options
Diffstat (limited to 'arch/x86/kernel/apm_32.c')
-rw-r--r-- | arch/x86/kernel/apm_32.c | 57 |
1 files changed, 34 insertions, 23 deletions
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 8d7012b7f402..66b5faffe14a 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 | ||
370 | static int apm_cpu_idle(struct cpuidle_device *dev, | ||
371 | struct cpuidle_driver *drv, int index); | ||
372 | |||
373 | static 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 | |||
391 | static struct cpuidle_device apm_cpuidle_device; | ||
392 | |||
370 | /* | 393 | /* |
371 | * Local variables | 394 | * Local variables |
372 | */ | 395 | */ |
@@ -377,7 +400,6 @@ static struct { | |||
377 | static int clock_slowed; | 400 | static int clock_slowed; |
378 | static int idle_threshold __read_mostly = DEFAULT_IDLE_THRESHOLD; | 401 | static int idle_threshold __read_mostly = DEFAULT_IDLE_THRESHOLD; |
379 | static int idle_period __read_mostly = DEFAULT_IDLE_PERIOD; | 402 | static int idle_period __read_mostly = DEFAULT_IDLE_PERIOD; |
380 | static int set_pm_idle; | ||
381 | static int suspends_pending; | 403 | static int suspends_pending; |
382 | static int standbys_pending; | 404 | static int standbys_pending; |
383 | static int ignore_sys_suspend; | 405 | static 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 | ||
887 | static 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 | ||
897 | static void apm_cpu_idle(void) | 917 | static 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 */ |
@@ -905,7 +926,6 @@ static void apm_cpu_idle(void) | |||
905 | unsigned int jiffies_since_last_check = jiffies - last_jiffies; | 926 | unsigned int jiffies_since_last_check = jiffies - last_jiffies; |
906 | unsigned int bucket; | 927 | unsigned int bucket; |
907 | 928 | ||
908 | WARN_ONCE(1, "deprecated apm_cpu_idle will be deleted in 2012"); | ||
909 | recalc: | 929 | recalc: |
910 | task_cputime(current, NULL, &stime); | 930 | task_cputime(current, NULL, &stime); |
911 | if (jiffies_since_last_check > IDLE_CALC_LIMIT) { | 931 | if (jiffies_since_last_check > IDLE_CALC_LIMIT) { |
@@ -951,10 +971,7 @@ recalc: | |||
951 | break; | 971 | break; |
952 | } | 972 | } |
953 | } | 973 | } |
954 | if (original_pm_idle) | 974 | default_idle(); |
955 | original_pm_idle(); | ||
956 | else | ||
957 | default_idle(); | ||
958 | local_irq_disable(); | 975 | local_irq_disable(); |
959 | jiffies_since_last_check = jiffies - last_jiffies; | 976 | jiffies_since_last_check = jiffies - last_jiffies; |
960 | if (jiffies_since_last_check > idle_period) | 977 | if (jiffies_since_last_check > idle_period) |
@@ -964,7 +981,7 @@ recalc: | |||
964 | if (apm_idle_done) | 981 | if (apm_idle_done) |
965 | apm_do_busy(); | 982 | apm_do_busy(); |
966 | 983 | ||
967 | local_irq_enable(); | 984 | return index; |
968 | } | 985 | } |
969 | 986 | ||
970 | /** | 987 | /** |
@@ -2382,9 +2399,9 @@ static int __init apm_init(void) | |||
2382 | if (HZ != 100) | 2399 | if (HZ != 100) |
2383 | idle_period = (idle_period * HZ) / 100; | 2400 | idle_period = (idle_period * HZ) / 100; |
2384 | if (idle_threshold < 100) { | 2401 | if (idle_threshold < 100) { |
2385 | original_pm_idle = pm_idle; | 2402 | if (!cpuidle_register_driver(&apm_idle_driver)) |
2386 | pm_idle = apm_cpu_idle; | 2403 | if (cpuidle_register_device(&apm_cpuidle_device)) |
2387 | set_pm_idle = 1; | 2404 | cpuidle_unregister_driver(&apm_idle_driver); |
2388 | } | 2405 | } |
2389 | 2406 | ||
2390 | return 0; | 2407 | return 0; |
@@ -2394,15 +2411,9 @@ static void __exit apm_exit(void) | |||
2394 | { | 2411 | { |
2395 | int error; | 2412 | int error; |
2396 | 2413 | ||
2397 | if (set_pm_idle) { | 2414 | cpuidle_unregister_device(&apm_cpuidle_device); |
2398 | pm_idle = original_pm_idle; | 2415 | cpuidle_unregister_driver(&apm_idle_driver); |
2399 | /* | 2416 | |
2400 | * We are about to unload the current idle thread pm callback | ||
2401 | * (pm_idle), Wait for all processors to update cached/local | ||
2402 | * copies of pm_idle before proceeding. | ||
2403 | */ | ||
2404 | kick_all_cpus_sync(); | ||
2405 | } | ||
2406 | if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0) | 2417 | if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0) |
2407 | && (apm_info.connection_version > 0x0100)) { | 2418 | && (apm_info.connection_version > 0x0100)) { |
2408 | error = apm_engage_power_management(APM_DEVICE_ALL, 0); | 2419 | error = apm_engage_power_management(APM_DEVICE_ALL, 0); |