diff options
-rw-r--r-- | drivers/acpi/acpi_pad.c | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index d269a8f3329c..446aced33aff 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c | |||
@@ -46,6 +46,8 @@ static unsigned long power_saving_mwait_eax; | |||
46 | 46 | ||
47 | static unsigned char tsc_detected_unstable; | 47 | static unsigned char tsc_detected_unstable; |
48 | static unsigned char tsc_marked_unstable; | 48 | static unsigned char tsc_marked_unstable; |
49 | static unsigned char lapic_detected_unstable; | ||
50 | static unsigned char lapic_marked_unstable; | ||
49 | 51 | ||
50 | static void power_saving_mwait_init(void) | 52 | static void power_saving_mwait_init(void) |
51 | { | 53 | { |
@@ -75,9 +77,6 @@ static void power_saving_mwait_init(void) | |||
75 | power_saving_mwait_eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) | | 77 | power_saving_mwait_eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) | |
76 | (highest_subcstate - 1); | 78 | (highest_subcstate - 1); |
77 | 79 | ||
78 | for_each_online_cpu(i) | ||
79 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &i); | ||
80 | |||
81 | #if defined(CONFIG_GENERIC_TIME) && defined(CONFIG_X86) | 80 | #if defined(CONFIG_GENERIC_TIME) && defined(CONFIG_X86) |
82 | switch (boot_cpu_data.x86_vendor) { | 81 | switch (boot_cpu_data.x86_vendor) { |
83 | case X86_VENDOR_AMD: | 82 | case X86_VENDOR_AMD: |
@@ -86,13 +85,15 @@ static void power_saving_mwait_init(void) | |||
86 | * AMD Fam10h TSC will tick in all | 85 | * AMD Fam10h TSC will tick in all |
87 | * C/P/S0/S1 states when this bit is set. | 86 | * C/P/S0/S1 states when this bit is set. |
88 | */ | 87 | */ |
89 | if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) | 88 | if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) |
90 | return; | 89 | tsc_detected_unstable = 1; |
91 | 90 | if (!boot_cpu_has(X86_FEATURE_ARAT)) | |
92 | /*FALL THROUGH*/ | 91 | lapic_detected_unstable = 1; |
92 | break; | ||
93 | default: | 93 | default: |
94 | /* TSC could halt in idle */ | 94 | /* TSC & LAPIC could halt in idle */ |
95 | tsc_detected_unstable = 1; | 95 | tsc_detected_unstable = 1; |
96 | lapic_detected_unstable = 1; | ||
96 | } | 97 | } |
97 | #endif | 98 | #endif |
98 | } | 99 | } |
@@ -180,10 +181,20 @@ static int power_saving_thread(void *data) | |||
180 | mark_tsc_unstable("TSC halts in idle"); | 181 | mark_tsc_unstable("TSC halts in idle"); |
181 | tsc_marked_unstable = 1; | 182 | tsc_marked_unstable = 1; |
182 | } | 183 | } |
184 | if (lapic_detected_unstable && !lapic_marked_unstable) { | ||
185 | int i; | ||
186 | /* LAPIC could halt in idle, so notify users */ | ||
187 | for_each_online_cpu(i) | ||
188 | clockevents_notify( | ||
189 | CLOCK_EVT_NOTIFY_BROADCAST_ON, | ||
190 | &i); | ||
191 | lapic_marked_unstable = 1; | ||
192 | } | ||
183 | local_irq_disable(); | 193 | local_irq_disable(); |
184 | cpu = smp_processor_id(); | 194 | cpu = smp_processor_id(); |
185 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, | 195 | if (lapic_marked_unstable) |
186 | &cpu); | 196 | clockevents_notify( |
197 | CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); | ||
187 | stop_critical_timings(); | 198 | stop_critical_timings(); |
188 | 199 | ||
189 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | 200 | __monitor((void *)¤t_thread_info()->flags, 0, 0); |
@@ -192,8 +203,9 @@ static int power_saving_thread(void *data) | |||
192 | __mwait(power_saving_mwait_eax, 1); | 203 | __mwait(power_saving_mwait_eax, 1); |
193 | 204 | ||
194 | start_critical_timings(); | 205 | start_critical_timings(); |
195 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, | 206 | if (lapic_marked_unstable) |
196 | &cpu); | 207 | clockevents_notify( |
208 | CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); | ||
197 | local_irq_enable(); | 209 | local_irq_enable(); |
198 | 210 | ||
199 | if (jiffies > expire_time) { | 211 | if (jiffies > expire_time) { |