Update to 2.6.32.39 Mainline
/arch/x86/kernel/process.c
blob:fc6c84db0601bf87e9684e9bdf59279093d37dde -> blob:5fd5b07bf3a5774cd996e312d9fe55533a37b984
--- arch/x86/kernel/process.c
+++ arch/x86/kernel/process.c
@@ -438,6 +438,42 @@ static int __cpuinit mwait_usable(const
return (edx & MWAIT_EDX_C1);
}
+/*
+ * Check for AMD CPUs, where APIC timer interrupt does not wake up CPU from C1e.
+ * For more information see
+ * - Erratum #400 for NPT family 0xf and family 0x10 CPUs
+ * - Erratum #365 for family 0x11 (not affected because C1e not in use)
+ */
+static int __cpuinit check_c1e_idle(const struct cpuinfo_x86 *c)
+{
+ u64 val;
+ if (c->x86_vendor != X86_VENDOR_AMD)
+ goto no_c1e_idle;
+
+ /* Family 0x0f models < rev F do not have C1E */
+ if (c->x86 == 0x0F && c->x86_model >= 0x40)
+ return 1;
+
+ if (c->x86 == 0x10) {
+ /*
+ * check OSVW bit for CPUs that are not affected
+ * by erratum #400
+ */
+ if (cpu_has(c, X86_FEATURE_OSVW)) {
+ rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, val);
+ if (val >= 2) {
+ rdmsrl(MSR_AMD64_OSVW_STATUS, val);
+ if (!(val & BIT(1)))
+ goto no_c1e_idle;
+ }
+ }
+ return 1;
+ }
+
+no_c1e_idle:
+ return 0;
+}
+
static cpumask_var_t c1e_mask;
static int c1e_detected;
@@ -515,8 +551,7 @@ void __cpuinit select_idle_routine(const
*/
printk(KERN_INFO "using mwait in idle threads.\n");
pm_idle = mwait_idle;
- } else if (cpu_has_amd_erratum(amd_erratum_400)) {
- /* E400: APIC timer interrupt does not wake up CPU from C1e */
+ } else if (check_c1e_idle(c)) {
printk(KERN_INFO "using C1E aware idle routine\n");
pm_idle = c1e_idle;
} else