summaryrefslogtreecommitdiff
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorThomas Mingarelli <thomas.mingarelli@hp.com>2009-06-04 19:50:45 +0000
committerWim Van Sebroeck <wim@iguana.be>2009-06-18 07:32:06 +0000
commit47bece87b14b866872b52ff04d469832e4936756 (patch)
tree812f6e1856cb322f1246a761a46ef20295b4689b /drivers/watchdog
parent55e8ddecec6a9dbe35a99d03cc4189fd7c56e600 (diff)
[WATCHDOG] hpwdt: Add NMI sourcing
Add NMI sourcing functionality (Can only be active if nmi_watchdog is inactive). Signed-off-by: Thomas Mingarelli <thomas.mingarelli@hp.com> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/hpwdt.c59
1 files changed, 44 insertions, 15 deletions
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 3137361ccbfe..c0b9169ba5d5 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -19,6 +19,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/nmi.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/mm.h>
@@ -47,7 +48,7 @@
#define PCI_BIOS32_PARAGRAPH_LEN 16
#define PCI_ROM_BASE1 0x000F0000
#define ROM_SIZE 0x10000
-#define HPWDT_VERSION "1.01"
+#define HPWDT_VERSION "1.1.1"
struct bios32_service_dir {
u32 signature;
@@ -119,6 +120,7 @@ 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 void __iomem *pci_mem_addr; /* the PCI-memory address */
static unsigned long __iomem *hpwdt_timer_reg;
@@ -468,21 +470,22 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason,
if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI)
return NOTIFY_OK;
- spin_lock_irqsave(&rom_lock, rom_pl);
- if (!die_nmi_called)
- asminline_call(&cmn_regs, cru_rom_addr);
- die_nmi_called = 1;
- spin_unlock_irqrestore(&rom_lock, rom_pl);
- if (cmn_regs.u1.ral == 0) {
- printk(KERN_WARNING "hpwdt: An NMI occurred, "
- "but unable to determine source.\n");
- } else {
- if (allow_kdump)
- hpwdt_stop();
- panic("An NMI occurred, please see the Integrated "
- "Management Log for details.\n");
+ if (hpwdt_nmi_sourcing) {
+ spin_lock_irqsave(&rom_lock, rom_pl);
+ if (!die_nmi_called)
+ asminline_call(&cmn_regs, cru_rom_addr);
+ die_nmi_called = 1;
+ spin_unlock_irqrestore(&rom_lock, rom_pl);
+ if (cmn_regs.u1.ral == 0) {
+ printk(KERN_WARNING "hpwdt: An NMI occurred, "
+ "but unable to determine source.\n");
+ } else {
+ if (allow_kdump)
+ hpwdt_stop();
+ panic("An NMI occurred, please see the Integrated "
+ "Management Log for details.\n");
+ }
}
-
return NOTIFY_OK;
}
@@ -627,12 +630,38 @@ static struct notifier_block die_notifier = {
* Init & Exit
*/
+#ifdef ARCH_HAS_NMI_WATCHDOG
+static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev)
+{
+ /*
+ * If nmi_watchdog is turned off then we can turn on
+ * our nmi sourcing capability.
+ */
+ if (!nmi_watchdog_active())
+ 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");
+}
+#else
+static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev)
+{
+ dev_warn(&dev->dev, "NMI sourcing is disabled. "
+ "Your kernel does not support a NMI Watchdog.\n");
+}
+#endif
+
static int __devinit hpwdt_init_one(struct pci_dev *dev,
const struct pci_device_id *ent)
{
int retval;
/*
+ * Check if we can do NMI sourcing or not
+ */
+ hpwdt_check_nmi_sourcing(dev);
+
+ /*
* First let's find out if we are on an iLO2 server. We will
* not run on a legacy ASM box.
* So we only support the G5 ProLiant servers and higher.