aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-10-21 12:37:02 -0400
committerAndi Kleen <andi@basil.nowhere.org>2006-10-21 12:37:02 -0400
commita1bae67243512ca30ceda48e3e24e25b543f8ab7 (patch)
tree9f90a2a4ac04ecd7e23c0049570cd570b6ae37ee
parent581910e2eb952e541b8ca9b5f551d6c124903b61 (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.c10
-rw-r--r--drivers/firmware/dmi_scan.c20
-rw-r--r--include/linux/dmi.h2
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}
327EXPORT_SYMBOL(dmi_get_system_info); 327EXPORT_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 */
334int 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}
347EXPORT_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);
70extern void dmi_scan_machine(void); 70extern void dmi_scan_machine(void);
71extern int dmi_get_year(int field); 71extern int dmi_get_year(int field);
72extern 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; }
77static inline struct dmi_device * dmi_find_device(int type, const char *name, 78static 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; }
79static inline int dmi_get_year(int year) { return 0; } 80static inline int dmi_get_year(int year) { return 0; }
81static inline int dmi_name_in_vendors(char *s) { return 0; }
80 82
81#endif 83#endif
82 84