diff options
Diffstat (limited to 'drivers/acpi/processor_idle.c')
-rw-r--r-- | drivers/acpi/processor_idle.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 71066066d626..0a395fca843b 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/dmi.h> | 38 | #include <linux/dmi.h> |
39 | #include <linux/moduleparam.h> | 39 | #include <linux/moduleparam.h> |
40 | #include <linux/sched.h> /* need_resched() */ | 40 | #include <linux/sched.h> /* need_resched() */ |
41 | #include <linux/latency.h> | ||
41 | 42 | ||
42 | #include <asm/io.h> | 43 | #include <asm/io.h> |
43 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
@@ -453,7 +454,8 @@ static void acpi_processor_idle(void) | |||
453 | */ | 454 | */ |
454 | if (cx->promotion.state && | 455 | if (cx->promotion.state && |
455 | ((cx->promotion.state - pr->power.states) <= max_cstate)) { | 456 | ((cx->promotion.state - pr->power.states) <= max_cstate)) { |
456 | if (sleep_ticks > cx->promotion.threshold.ticks) { | 457 | if (sleep_ticks > cx->promotion.threshold.ticks && |
458 | cx->promotion.state->latency <= system_latency_constraint()) { | ||
457 | cx->promotion.count++; | 459 | cx->promotion.count++; |
458 | cx->demotion.count = 0; | 460 | cx->demotion.count = 0; |
459 | if (cx->promotion.count >= | 461 | if (cx->promotion.count >= |
@@ -494,8 +496,10 @@ static void acpi_processor_idle(void) | |||
494 | end: | 496 | end: |
495 | /* | 497 | /* |
496 | * Demote if current state exceeds max_cstate | 498 | * Demote if current state exceeds max_cstate |
499 | * or if the latency of the current state is unacceptable | ||
497 | */ | 500 | */ |
498 | if ((pr->power.state - pr->power.states) > max_cstate) { | 501 | if ((pr->power.state - pr->power.states) > max_cstate || |
502 | pr->power.state->latency > system_latency_constraint()) { | ||
499 | if (cx->demotion.state) | 503 | if (cx->demotion.state) |
500 | next_state = cx->demotion.state; | 504 | next_state = cx->demotion.state; |
501 | } | 505 | } |
@@ -1009,9 +1013,11 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) | |||
1009 | 1013 | ||
1010 | seq_printf(seq, "active state: C%zd\n" | 1014 | seq_printf(seq, "active state: C%zd\n" |
1011 | "max_cstate: C%d\n" | 1015 | "max_cstate: C%d\n" |
1012 | "bus master activity: %08x\n", | 1016 | "bus master activity: %08x\n" |
1017 | "maximum allowed latency: %d usec\n", | ||
1013 | pr->power.state ? pr->power.state - pr->power.states : 0, | 1018 | pr->power.state ? pr->power.state - pr->power.states : 0, |
1014 | max_cstate, (unsigned)pr->power.bm_activity); | 1019 | max_cstate, (unsigned)pr->power.bm_activity, |
1020 | system_latency_constraint()); | ||
1015 | 1021 | ||
1016 | seq_puts(seq, "states:\n"); | 1022 | seq_puts(seq, "states:\n"); |
1017 | 1023 | ||
@@ -1077,6 +1083,28 @@ static const struct file_operations acpi_processor_power_fops = { | |||
1077 | .release = single_release, | 1083 | .release = single_release, |
1078 | }; | 1084 | }; |
1079 | 1085 | ||
1086 | static void smp_callback(void *v) | ||
1087 | { | ||
1088 | /* we already woke the CPU up, nothing more to do */ | ||
1089 | } | ||
1090 | |||
1091 | /* | ||
1092 | * This function gets called when a part of the kernel has a new latency | ||
1093 | * requirement. This means we need to get all processors out of their C-state, | ||
1094 | * and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that | ||
1095 | * wakes them all right up. | ||
1096 | */ | ||
1097 | static int acpi_processor_latency_notify(struct notifier_block *b, | ||
1098 | unsigned long l, void *v) | ||
1099 | { | ||
1100 | smp_call_function(smp_callback, NULL, 0, 1); | ||
1101 | return NOTIFY_OK; | ||
1102 | } | ||
1103 | |||
1104 | static struct notifier_block acpi_processor_latency_notifier = { | ||
1105 | .notifier_call = acpi_processor_latency_notify, | ||
1106 | }; | ||
1107 | |||
1080 | int acpi_processor_power_init(struct acpi_processor *pr, | 1108 | int acpi_processor_power_init(struct acpi_processor *pr, |
1081 | struct acpi_device *device) | 1109 | struct acpi_device *device) |
1082 | { | 1110 | { |
@@ -1093,6 +1121,7 @@ int acpi_processor_power_init(struct acpi_processor *pr, | |||
1093 | "ACPI: processor limited to max C-state %d\n", | 1121 | "ACPI: processor limited to max C-state %d\n", |
1094 | max_cstate); | 1122 | max_cstate); |
1095 | first_run++; | 1123 | first_run++; |
1124 | register_latency_notifier(&acpi_processor_latency_notifier); | ||
1096 | } | 1125 | } |
1097 | 1126 | ||
1098 | if (!pr) | 1127 | if (!pr) |
@@ -1164,6 +1193,7 @@ int acpi_processor_power_exit(struct acpi_processor *pr, | |||
1164 | * copies of pm_idle before proceeding. | 1193 | * copies of pm_idle before proceeding. |
1165 | */ | 1194 | */ |
1166 | cpu_idle_wait(); | 1195 | cpu_idle_wait(); |
1196 | unregister_latency_notifier(&acpi_processor_latency_notifier); | ||
1167 | } | 1197 | } |
1168 | 1198 | ||
1169 | return 0; | 1199 | return 0; |