[WATCHDOG] hpwdt: Add NMI priority option

Add a priority option so that the user can choose if we do the NMI
first or last.

Signed-off-by: Thomas Mingarelli <thomas.mingarelli@hp.com>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
This commit is contained in:
Tom Mingarelli 2009-06-18 23:28:57 +00:00 committed by Wim Van Sebroeck
parent 789cd4702b
commit 44df75353b
2 changed files with 36 additions and 9 deletions

View File

@ -19,30 +19,41 @@ Last reviewed: 06/02/2009
not be updated in a timely fashion and a hardware system reset (also known as
an Automatic Server Recovery (ASR)) event will occur.
The hpwdt driver also has three (3) module parameters. They are the following:
The hpwdt driver also has four (4) module parameters. They are the following:
soft_margin - allows the user to set the watchdog timer value
allow_kdump - allows the user to save off a kernel dump image after an NMI
nowayout - basic watchdog parameter that does not allow the timer to
be restarted or an impending ASR to be escaped.
priority - determines whether or not the hpwdt driver is first on the
die_notify list to handle NMIs or last. The default value
for this module parameter is 0 or LAST. If the user wants to
enable NMI sourcing then reload the hpwdt driver with
priority=1 (and boot with nmi_watchdog=0).
NOTE: More information about watchdog drivers in general, including the ioctl
interface to /dev/watchdog can be found in
Documentation/watchdog/watchdog-api.txt and Documentation/IPMI.txt.
The NMI sourcing capability is disabled when the driver discovers that the
nmi_watchdog is turned on (nmi_watchdog = 1). This is due to the inability to
The priority parameter was introduced due to other kernel software that relied
on handling NMIs (like oprofile). Keeping hpwdt's priority at 0 (or LAST)
enables the users of NMIs for non critical events to be work as expected.
The NMI sourcing capability is disabled by default due to the inability to
distinguish between "NMI Watchdog Ticks" and "HW generated NMI events" in the
Linux kernel. What this means is that the hpwdt nmi handler code is called
each time the NMI signal fires off. This could amount to several thousands of
NMIs in a matter of seconds. If a user sees the Linux kernel's "dazed and
confused" message in the logs or if the system gets into a hung state, then
the user should reboot with nmi_watchdog=0.
the hpwdt driver can be reloaded with the "priority" module parameter set
(priority=1).
1. If the kernel has not been booted with nmi_watchdog turned off then
edit /boot/grub/menu.lst and place the nmi_watchdog=0 at the end of the
currently booting kernel line.
2. reboot the sever
3. Once the system comes up perform a rmmod hpwdt
4. insmod /lib/modules/`uname -r`/kernel/drivers/char/watchdog/hpwdt.ko priority=1
Now, the hpwdt can successfully receive and source the NMI and provide a log
message that details the reason for the NMI (as determined by the HP BIOS).

View File

@ -120,7 +120,8 @@ static int nowayout = WATCHDOG_NOWAYOUT;
static char expect_release;
static unsigned long hpwdt_is_open;
static unsigned int allow_kdump;
static int hpwdt_nmi_sourcing;
static unsigned int hpwdt_nmi_sourcing;
static unsigned int priority; /* hpwdt at end of die_notify list */
static void __iomem *pci_mem_addr; /* the PCI-memory address */
static unsigned long __iomem *hpwdt_timer_reg;
@ -623,7 +624,7 @@ static struct miscdevice hpwdt_miscdev = {
static struct notifier_block die_notifier = {
.notifier_call = hpwdt_pretimeout,
.priority = 0x7FFFFFFF,
.priority = 0,
};
/*
@ -641,7 +642,8 @@ static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev)
hpwdt_nmi_sourcing = 1;
else
dev_warn(&dev->dev, "NMI sourcing is disabled. To enable this "
"functionality you must reboot with nmi_watchdog=0.\n");
"functionality you must reboot with nmi_watchdog=0 "
"and load the hpwdt driver with priority=1.\n");
}
#else
static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev)
@ -714,6 +716,14 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
cmn_regs.u1.rah = 0x0D;
cmn_regs.u1.ral = 0x02;
/*
* If the priority is set to 1, then we will be put first on the
* die notify list to handle a critical NMI. The default is to
* be last so other users of the NMI signal can function.
*/
if (priority)
die_notifier.priority = 0x7FFFFFFF;
retval = register_die_notifier(&die_notifier);
if (retval != 0) {
dev_warn(&dev->dev,
@ -733,9 +743,11 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
printk(KERN_INFO
"hp Watchdog Timer Driver: %s"
", timer margin: %d seconds (nowayout=%d)"
", allow kernel dump: %s (default = 0/OFF).\n",
", allow kernel dump: %s (default = 0/OFF)"
", priority: %s (default = 0/LAST).\n",
HPWDT_VERSION, soft_margin, nowayout,
(allow_kdump == 0) ? "OFF" : "ON");
(allow_kdump == 0) ? "OFF" : "ON",
(priority == 0) ? "LAST" : "FIRST");
return 0;
@ -798,5 +810,9 @@ module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
module_param(priority, int, 0);
MODULE_PARM_DESC(priority, "The hpwdt driver handles NMIs first or last"
" (default = 0/Last)\n");
module_init(hpwdt_init);
module_exit(hpwdt_cleanup);