diff options
author | Thomas Mingarelli <thomas.mingarelli@hp.com> | 2009-06-04 15:50:45 -0400 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2009-06-18 03:32:06 -0400 |
commit | 47bece87b14b866872b52ff04d469832e4936756 (patch) | |
tree | 812f6e1856cb322f1246a761a46ef20295b4689b /drivers/watchdog/hpwdt.c | |
parent | 55e8ddecec6a9dbe35a99d03cc4189fd7c56e600 (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/hpwdt.c')
-rw-r--r-- | drivers/watchdog/hpwdt.c | 59 |
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 @@ | |||
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
22 | #include <linux/nmi.h> | ||
22 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
23 | #include <linux/miscdevice.h> | 24 | #include <linux/miscdevice.h> |
24 | #include <linux/mm.h> | 25 | #include <linux/mm.h> |
@@ -47,7 +48,7 @@ | |||
47 | #define PCI_BIOS32_PARAGRAPH_LEN 16 | 48 | #define PCI_BIOS32_PARAGRAPH_LEN 16 |
48 | #define PCI_ROM_BASE1 0x000F0000 | 49 | #define PCI_ROM_BASE1 0x000F0000 |
49 | #define ROM_SIZE 0x10000 | 50 | #define ROM_SIZE 0x10000 |
50 | #define HPWDT_VERSION "1.01" | 51 | #define HPWDT_VERSION "1.1.1" |
51 | 52 | ||
52 | struct bios32_service_dir { | 53 | struct bios32_service_dir { |
53 | u32 signature; | 54 | u32 signature; |
@@ -119,6 +120,7 @@ static int nowayout = WATCHDOG_NOWAYOUT; | |||
119 | static char expect_release; | 120 | static char expect_release; |
120 | static unsigned long hpwdt_is_open; | 121 | static unsigned long hpwdt_is_open; |
121 | static unsigned int allow_kdump; | 122 | static unsigned int allow_kdump; |
123 | static int hpwdt_nmi_sourcing; | ||
122 | 124 | ||
123 | static void __iomem *pci_mem_addr; /* the PCI-memory address */ | 125 | static void __iomem *pci_mem_addr; /* the PCI-memory address */ |
124 | static unsigned long __iomem *hpwdt_timer_reg; | 126 | static unsigned long __iomem *hpwdt_timer_reg; |
@@ -468,21 +470,22 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, | |||
468 | if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) | 470 | if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) |
469 | return NOTIFY_OK; | 471 | return NOTIFY_OK; |
470 | 472 | ||
471 | spin_lock_irqsave(&rom_lock, rom_pl); | 473 | if (hpwdt_nmi_sourcing) { |
472 | if (!die_nmi_called) | 474 | spin_lock_irqsave(&rom_lock, rom_pl); |
473 | asminline_call(&cmn_regs, cru_rom_addr); | 475 | if (!die_nmi_called) |
474 | die_nmi_called = 1; | 476 | asminline_call(&cmn_regs, cru_rom_addr); |
475 | spin_unlock_irqrestore(&rom_lock, rom_pl); | 477 | die_nmi_called = 1; |
476 | if (cmn_regs.u1.ral == 0) { | 478 | spin_unlock_irqrestore(&rom_lock, rom_pl); |
477 | printk(KERN_WARNING "hpwdt: An NMI occurred, " | 479 | if (cmn_regs.u1.ral == 0) { |
478 | "but unable to determine source.\n"); | 480 | printk(KERN_WARNING "hpwdt: An NMI occurred, " |
479 | } else { | 481 | "but unable to determine source.\n"); |
480 | if (allow_kdump) | 482 | } else { |
481 | hpwdt_stop(); | 483 | if (allow_kdump) |
482 | panic("An NMI occurred, please see the Integrated " | 484 | hpwdt_stop(); |
483 | "Management Log for details.\n"); | 485 | panic("An NMI occurred, please see the Integrated " |
486 | "Management Log for details.\n"); | ||
487 | } | ||
484 | } | 488 | } |
485 | |||
486 | return NOTIFY_OK; | 489 | return NOTIFY_OK; |
487 | } | 490 | } |
488 | 491 | ||
@@ -627,12 +630,38 @@ static struct notifier_block die_notifier = { | |||
627 | * Init & Exit | 630 | * Init & Exit |
628 | */ | 631 | */ |
629 | 632 | ||
633 | #ifdef ARCH_HAS_NMI_WATCHDOG | ||
634 | static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev) | ||
635 | { | ||
636 | /* | ||
637 | * If nmi_watchdog is turned off then we can turn on | ||
638 | * our nmi sourcing capability. | ||
639 | */ | ||
640 | if (!nmi_watchdog_active()) | ||
641 | hpwdt_nmi_sourcing = 1; | ||
642 | else | ||
643 | dev_warn(&dev->dev, "NMI sourcing is disabled. To enable this " | ||
644 | "functionality you must reboot with nmi_watchdog=0.\n"); | ||
645 | } | ||
646 | #else | ||
647 | static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev) | ||
648 | { | ||
649 | dev_warn(&dev->dev, "NMI sourcing is disabled. " | ||
650 | "Your kernel does not support a NMI Watchdog.\n"); | ||
651 | } | ||
652 | #endif | ||
653 | |||
630 | static int __devinit hpwdt_init_one(struct pci_dev *dev, | 654 | static int __devinit hpwdt_init_one(struct pci_dev *dev, |
631 | const struct pci_device_id *ent) | 655 | const struct pci_device_id *ent) |
632 | { | 656 | { |
633 | int retval; | 657 | int retval; |
634 | 658 | ||
635 | /* | 659 | /* |
660 | * Check if we can do NMI sourcing or not | ||
661 | */ | ||
662 | hpwdt_check_nmi_sourcing(dev); | ||
663 | |||
664 | /* | ||
636 | * First let's find out if we are on an iLO2 server. We will | 665 | * First let's find out if we are on an iLO2 server. We will |
637 | * not run on a legacy ASM box. | 666 | * not run on a legacy ASM box. |
638 | * So we only support the G5 ProLiant servers and higher. | 667 | * So we only support the G5 ProLiant servers and higher. |