[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>

diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 3137361..c0b9169 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 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 @@
 	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 @@
  *	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.