Skip to content

Commit

Permalink
[PATCH] i386: Disable nmi watchdog on all ThinkPads
Browse files Browse the repository at this point in the history
Even newer Thinkpads have bugs in SMM code that causes hangs with
NMI watchdog.

Signed-off-by: Andi Kleen <ak@suse.de>
  • Loading branch information
Andi Kleen authored and Andi Kleen committed Oct 21, 2006
1 parent 581910e commit a1bae67
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 5 deletions.
10 changes: 5 additions & 5 deletions arch/i386/kernel/nmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,11 @@ static int __init check_nmi_watchdog(void)
int cpu;

/* Enable NMI watchdog for newer systems.
Actually it should be safe for most systems before 2004 too except
for some IBM systems that corrupt registers when NMI happens
during SMM. Unfortunately we don't have more exact information
on these and use this coarse check. */
if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004)
Probably safe on most older systems too, but let's be careful.
IBM ThinkPads use INT10 inside SMM and that allows early NMI inside SMM
which hangs the system. Disable watchdog for all thinkpads */
if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004 &&
!dmi_name_in_vendors("ThinkPad"))
nmi_watchdog = NMI_LOCAL_APIC;

if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT))
Expand Down
20 changes: 20 additions & 0 deletions drivers/firmware/dmi_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,26 @@ char *dmi_get_system_info(int field)
}
EXPORT_SYMBOL(dmi_get_system_info);


/**
* dmi_name_in_vendors - Check if string is anywhere in the DMI vendor information.
* @str: Case sensitive Name
*/
int dmi_name_in_vendors(char *str)
{
static int fields[] = { DMI_BIOS_VENDOR, DMI_BIOS_VERSION, DMI_SYS_VENDOR,
DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_BOARD_VENDOR,
DMI_BOARD_NAME, DMI_BOARD_VERSION, DMI_NONE };
int i;
for (i = 0; fields[i] != DMI_NONE; i++) {
int f = fields[i];
if (dmi_ident[f] && strstr(dmi_ident[f], str))
return 1;
}
return 0;
}
EXPORT_SYMBOL(dmi_name_in_vendors);

/**
* dmi_find_device - find onboard device by type/name
* @type: device type or %DMI_DEV_TYPE_ANY to match all device types
Expand Down
2 changes: 2 additions & 0 deletions include/linux/dmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ extern struct dmi_device * dmi_find_device(int type, const char *name,
struct dmi_device *from);
extern void dmi_scan_machine(void);
extern int dmi_get_year(int field);
extern int dmi_name_in_vendors(char *str);

#else

Expand All @@ -77,6 +78,7 @@ static inline char * dmi_get_system_info(int field) { return NULL; }
static inline struct dmi_device * dmi_find_device(int type, const char *name,
struct dmi_device *from) { return NULL; }
static inline int dmi_get_year(int year) { return 0; }
static inline int dmi_name_in_vendors(char *s) { return 0; }

#endif

Expand Down

0 comments on commit a1bae67

Please sign in to comment.