diff options
author | Andi Kleen <ak@suse.de> | 2006-10-21 12:37:02 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-10-21 12:37:02 -0400 |
commit | a1bae67243512ca30ceda48e3e24e25b543f8ab7 (patch) | |
tree | 9f90a2a4ac04ecd7e23c0049570cd570b6ae37ee | |
parent | 581910e2eb952e541b8ca9b5f551d6c124903b61 (diff) |
[PATCH] i386: Disable nmi watchdog on all ThinkPads
Even newer Thinkpads have bugs in SMM code that causes hangs with
NMI watchdog.
Signed-off-by: Andi Kleen <ak@suse.de>
-rw-r--r-- | arch/i386/kernel/nmi.c | 10 | ||||
-rw-r--r-- | drivers/firmware/dmi_scan.c | 20 | ||||
-rw-r--r-- | include/linux/dmi.h | 2 |
3 files changed, 27 insertions, 5 deletions
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index 3e8e3adb0489..eaafe233a5da 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c | |||
@@ -219,11 +219,11 @@ static int __init check_nmi_watchdog(void) | |||
219 | int cpu; | 219 | int cpu; |
220 | 220 | ||
221 | /* Enable NMI watchdog for newer systems. | 221 | /* Enable NMI watchdog for newer systems. |
222 | Actually it should be safe for most systems before 2004 too except | 222 | Probably safe on most older systems too, but let's be careful. |
223 | for some IBM systems that corrupt registers when NMI happens | 223 | IBM ThinkPads use INT10 inside SMM and that allows early NMI inside SMM |
224 | during SMM. Unfortunately we don't have more exact information | 224 | which hangs the system. Disable watchdog for all thinkpads */ |
225 | on these and use this coarse check. */ | 225 | if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004 && |
226 | if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004) | 226 | !dmi_name_in_vendors("ThinkPad")) |
227 | nmi_watchdog = NMI_LOCAL_APIC; | 227 | nmi_watchdog = NMI_LOCAL_APIC; |
228 | 228 | ||
229 | if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT)) | 229 | if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT)) |
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index b8b596d5778d..37deee6c0c1c 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c | |||
@@ -326,6 +326,26 @@ char *dmi_get_system_info(int field) | |||
326 | } | 326 | } |
327 | EXPORT_SYMBOL(dmi_get_system_info); | 327 | EXPORT_SYMBOL(dmi_get_system_info); |
328 | 328 | ||
329 | |||
330 | /** | ||
331 | * dmi_name_in_vendors - Check if string is anywhere in the DMI vendor information. | ||
332 | * @str: Case sensitive Name | ||
333 | */ | ||
334 | int dmi_name_in_vendors(char *str) | ||
335 | { | ||
336 | static int fields[] = { DMI_BIOS_VENDOR, DMI_BIOS_VERSION, DMI_SYS_VENDOR, | ||
337 | DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_BOARD_VENDOR, | ||
338 | DMI_BOARD_NAME, DMI_BOARD_VERSION, DMI_NONE }; | ||
339 | int i; | ||
340 | for (i = 0; fields[i] != DMI_NONE; i++) { | ||
341 | int f = fields[i]; | ||
342 | if (dmi_ident[f] && strstr(dmi_ident[f], str)) | ||
343 | return 1; | ||
344 | } | ||
345 | return 0; | ||
346 | } | ||
347 | EXPORT_SYMBOL(dmi_name_in_vendors); | ||
348 | |||
329 | /** | 349 | /** |
330 | * dmi_find_device - find onboard device by type/name | 350 | * dmi_find_device - find onboard device by type/name |
331 | * @type: device type or %DMI_DEV_TYPE_ANY to match all device types | 351 | * @type: device type or %DMI_DEV_TYPE_ANY to match all device types |
diff --git a/include/linux/dmi.h b/include/linux/dmi.h index 38dc403be70b..904bf3d2d90b 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h | |||
@@ -69,6 +69,7 @@ extern struct dmi_device * dmi_find_device(int type, const char *name, | |||
69 | struct dmi_device *from); | 69 | struct dmi_device *from); |
70 | extern void dmi_scan_machine(void); | 70 | extern void dmi_scan_machine(void); |
71 | extern int dmi_get_year(int field); | 71 | extern int dmi_get_year(int field); |
72 | extern int dmi_name_in_vendors(char *str); | ||
72 | 73 | ||
73 | #else | 74 | #else |
74 | 75 | ||
@@ -77,6 +78,7 @@ static inline char * dmi_get_system_info(int field) { return NULL; } | |||
77 | static inline struct dmi_device * dmi_find_device(int type, const char *name, | 78 | static inline struct dmi_device * dmi_find_device(int type, const char *name, |
78 | struct dmi_device *from) { return NULL; } | 79 | struct dmi_device *from) { return NULL; } |
79 | static inline int dmi_get_year(int year) { return 0; } | 80 | static inline int dmi_get_year(int year) { return 0; } |
81 | static inline int dmi_name_in_vendors(char *s) { return 0; } | ||
80 | 82 | ||
81 | #endif | 83 | #endif |
82 | 84 | ||