From: Petr Tesarik <ptesarik@suse.cz>
Subject: hpwdt: handle NMI_SERR and NMI_IO_CHECK
Patch-mainline: v3.5-rc5
Git-commit: 553222f3e81f18da31b2552e18dc519715198590
Git-commit: a089361cf5f1d6a5295aa5385238bd044998e1e9
References: bnc#777746

hpwdt: handle NMI_SERR and NMI_IO_CHECK

In discussions with Thomas Mingarelli about hpwdt, he explained
to me some issues they were some when using their virtual NMI
button to test the hpwdt driver.

It turns out the virtual NMI button used on HP's machines do no
send unknown NMIs but instead send IO_CHK NMIs.  The way the
kernel code is written, the hpwdt driver can not register itself
against that type of NMI and therefore can not successfully
capture system information before panicking.

To solve this I created two new NMI die chains to allow driver to
register against the IO_CHK and SERR NMIs.  Or in the hpwdt all
three (if you include unknown NMIs too).

The change is straightforward and just mimics what the unknown
NMI does.

NOTE: Mainline commit added two NMI queues to accomplish the job,
because it was implemented after the rewrite of the NMI code.
SLES11 still uses die chains, but the idea is the same.

Reported-and-tested-by: Thomas Mingarelli <thomas.mingarelli@hp.com>
Signed-off-by: Don Zickus <dzickus@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Link: http://lkml.kernel.org/r/1333051877-15755-3-git-send-email-dzickus@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>

Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
---
 arch/x86/include/asm/kdebug.h |    2 ++
 arch/x86/kernel/traps.c       |    8 ++++++++
 drivers/watchdog/hpwdt.c      |    4 +++-
 3 files changed, 13 insertions(+), 1 deletion(-)

--- a/arch/x86/include/asm/kdebug.h
+++ b/arch/x86/include/asm/kdebug.h
@@ -19,6 +19,8 @@ enum die_val {
 	DIE_CALL,
 	DIE_PAGE_FAULT,
 	DIE_NMIUNKNOWN,
+	DIE_NMISERR,
+	DIE_NMIIOCK,
 };
 
 extern void printk_address(unsigned long address);
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -317,6 +317,10 @@ __setup("unknown_nmi_panic", setup_unkno
 static notrace __kprobes void
 pci_serr_error(unsigned char reason, struct pt_regs *regs)
 {
+	if (notify_die(DIE_NMISERR, "nmi_serr", regs, reason, 2, SIGINT) ==
+			NOTIFY_STOP)
+		return;
+
 	pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n",
 		 reason, smp_processor_id());
 
@@ -346,6 +350,10 @@ io_check_error(unsigned char reason, str
 {
 	unsigned long i;
 
+	if (notify_die(DIE_NMIIOCK, "nmi_iock", regs, reason, 2, SIGINT) ==
+			NOTIFY_STOP)
+		return;
+
 	pr_emerg(
 	"NMI: IOCK error (debug interrupt?) for reason %02x on CPU %d.\n",
 		 reason, smp_processor_id());
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -487,7 +487,9 @@ static int hpwdt_pretimeout(struct notif
 	unsigned long rom_pl;
 	static int die_nmi_called;
 
-	if (ulReason != DIE_NMIUNKNOWN)
+	if (ulReason != DIE_NMIUNKNOWN &&
+	    ulReason != DIE_NMISERR &&
+	    ulReason != DIE_NMIIOCK)
 		goto out;
 
 	if (!hpwdt_nmi_decoding)
