diff options
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/kernel/apic.c | 32 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/amd.c | 34 |
2 files changed, 37 insertions, 29 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index e88415282a6f..93aa911646ad 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c | |||
@@ -272,32 +272,6 @@ static void __devinit setup_APIC_timer(void) | |||
272 | } | 272 | } |
273 | 273 | ||
274 | /* | 274 | /* |
275 | * Detect systems with known broken BIOS implementations | ||
276 | */ | ||
277 | static int __init lapic_check_broken_bios(struct dmi_system_id *d) | ||
278 | { | ||
279 | printk(KERN_NOTICE "%s detected: disabling lapic timer.\n", | ||
280 | d->ident); | ||
281 | local_apic_timer_disabled = 1; | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static struct dmi_system_id __initdata broken_bios_dmi_table[] = { | ||
286 | { | ||
287 | /* | ||
288 | * BIOS exports only C1 state, but uses deeper power | ||
289 | * modes behind the kernels back. | ||
290 | */ | ||
291 | .callback = lapic_check_broken_bios, | ||
292 | .ident = "HP nx6325", | ||
293 | .matches = { | ||
294 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"), | ||
295 | }, | ||
296 | }, | ||
297 | {} | ||
298 | }; | ||
299 | |||
300 | /* | ||
301 | * In this functions we calibrate APIC bus clocks to the external timer. | 275 | * In this functions we calibrate APIC bus clocks to the external timer. |
302 | * | 276 | * |
303 | * We want to do the calibration only once since we want to have local timer | 277 | * We want to do the calibration only once since we want to have local timer |
@@ -372,12 +346,12 @@ void __init setup_boot_APIC_clock(void) | |||
372 | long delta, deltapm; | 346 | long delta, deltapm; |
373 | int pm_referenced = 0; | 347 | int pm_referenced = 0; |
374 | 348 | ||
375 | /* Detect know broken systems */ | 349 | if (boot_cpu_has(X86_FEATURE_LAPIC_TIMER_BROKEN)) |
376 | dmi_check_system(broken_bios_dmi_table); | 350 | local_apic_timer_disabled = 1; |
377 | 351 | ||
378 | /* | 352 | /* |
379 | * The local apic timer can be disabled via the kernel | 353 | * The local apic timer can be disabled via the kernel |
380 | * commandline or from the dmi quirk above. Register the lapic | 354 | * commandline or from the test above. Register the lapic |
381 | * timer as a dummy clock event source on SMP systems, so the | 355 | * timer as a dummy clock event source on SMP systems, so the |
382 | * broadcast mechanism is used. On UP systems simply ignore it. | 356 | * broadcast mechanism is used. On UP systems simply ignore it. |
383 | */ | 357 | */ |
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index 41cfea57232b..2d47db482972 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c | |||
@@ -22,6 +22,37 @@ | |||
22 | extern void vide(void); | 22 | extern void vide(void); |
23 | __asm__(".align 4\nvide: ret"); | 23 | __asm__(".align 4\nvide: ret"); |
24 | 24 | ||
25 | #define ENABLE_C1E_MASK 0x18000000 | ||
26 | #define CPUID_PROCESSOR_SIGNATURE 1 | ||
27 | #define CPUID_XFAM 0x0ff00000 | ||
28 | #define CPUID_XFAM_K8 0x00000000 | ||
29 | #define CPUID_XFAM_10H 0x00100000 | ||
30 | #define CPUID_XFAM_11H 0x00200000 | ||
31 | #define CPUID_XMOD 0x000f0000 | ||
32 | #define CPUID_XMOD_REV_F 0x00040000 | ||
33 | |||
34 | /* AMD systems with C1E don't have a working lAPIC timer. Check for that. */ | ||
35 | static __cpuinit int amd_apic_timer_broken(void) | ||
36 | { | ||
37 | u32 lo, hi; | ||
38 | u32 eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); | ||
39 | switch (eax & CPUID_XFAM) { | ||
40 | case CPUID_XFAM_K8: | ||
41 | if ((eax & CPUID_XMOD) < CPUID_XMOD_REV_F) | ||
42 | break; | ||
43 | case CPUID_XFAM_10H: | ||
44 | case CPUID_XFAM_11H: | ||
45 | rdmsr(MSR_K8_ENABLE_C1E, lo, hi); | ||
46 | if (lo & ENABLE_C1E_MASK) | ||
47 | return 1; | ||
48 | break; | ||
49 | default: | ||
50 | /* err on the side of caution */ | ||
51 | return 1; | ||
52 | } | ||
53 | return 0; | ||
54 | } | ||
55 | |||
25 | static void __cpuinit init_amd(struct cpuinfo_x86 *c) | 56 | static void __cpuinit init_amd(struct cpuinfo_x86 *c) |
26 | { | 57 | { |
27 | u32 l, h; | 58 | u32 l, h; |
@@ -241,6 +272,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) | |||
241 | 272 | ||
242 | if (cpuid_eax(0x80000000) >= 0x80000006) | 273 | if (cpuid_eax(0x80000000) >= 0x80000006) |
243 | num_cache_leaves = 3; | 274 | num_cache_leaves = 3; |
275 | |||
276 | if (amd_apic_timer_broken()) | ||
277 | set_bit(X86_FEATURE_LAPIC_TIMER_BROKEN, c->x86_capability); | ||
244 | } | 278 | } |
245 | 279 | ||
246 | static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned int size) | 280 | static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned int size) |