diff options
-rw-r--r-- | drivers/watchdog/Kconfig | 17 | ||||
-rw-r--r-- | drivers/watchdog/hpwdt.c | 27 |
2 files changed, 37 insertions, 7 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index cee25e401440..b036677df8c4 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -578,12 +578,17 @@ config HP_WATCHDOG | |||
578 | depends on X86 | 578 | depends on X86 |
579 | help | 579 | help |
580 | A software monitoring watchdog and NMI sourcing driver. This driver | 580 | A software monitoring watchdog and NMI sourcing driver. This driver |
581 | will detect lockups and provide a stack trace. Also, when an NMI | 581 | will detect lockups and provide a stack trace. This is a driver that |
582 | occurs this driver will make the necessary BIOS calls to log | 582 | will only load on a HP ProLiant system with a minimum of iLO2 support. |
583 | the cause of the NMI. This is a driver that will only load on a | 583 | To compile this driver as a module, choose M here: the module will be |
584 | HP ProLiant system with a minimum of iLO2 support. | 584 | called hpwdt. |
585 | To compile this driver as a module, choose M here: the | 585 | |
586 | module will be called hpwdt. | 586 | config HPWDT_NMI_DECODING |
587 | bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer" | ||
588 | depends on HP_WATCHDOG | ||
589 | help | ||
590 | When an NMI occurs this feature will make the necessary BIOS calls to | ||
591 | log the cause of the NMI. | ||
587 | 592 | ||
588 | config SC1200_WDT | 593 | config SC1200_WDT |
589 | tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" | 594 | tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" |
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 850f17877e9c..3d77116e4634 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c | |||
@@ -27,14 +27,16 @@ | |||
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | #include <linux/watchdog.h> | 29 | #include <linux/watchdog.h> |
30 | #ifdef CONFIG_HPWDT_NMI_DECODING | ||
30 | #include <linux/dmi.h> | 31 | #include <linux/dmi.h> |
31 | #include <linux/spinlock.h> | 32 | #include <linux/spinlock.h> |
32 | #include <linux/nmi.h> | 33 | #include <linux/nmi.h> |
33 | #include <linux/kdebug.h> | 34 | #include <linux/kdebug.h> |
34 | #include <linux/notifier.h> | 35 | #include <linux/notifier.h> |
35 | #include <asm/cacheflush.h> | 36 | #include <asm/cacheflush.h> |
37 | #endif /* CONFIG_HPWDT_NMI_DECODING */ | ||
36 | 38 | ||
37 | #define HPWDT_VERSION "1.1.1" | 39 | #define HPWDT_VERSION "1.2.0" |
38 | #define SECS_TO_TICKS(secs) ((secs) * 1000 / 128) | 40 | #define SECS_TO_TICKS(secs) ((secs) * 1000 / 128) |
39 | #define TICKS_TO_SECS(ticks) ((ticks) * 128 / 1000) | 41 | #define TICKS_TO_SECS(ticks) ((ticks) * 128 / 1000) |
40 | #define HPWDT_MAX_TIMER TICKS_TO_SECS(65535) | 42 | #define HPWDT_MAX_TIMER TICKS_TO_SECS(65535) |
@@ -57,6 +59,7 @@ static struct pci_device_id hpwdt_devices[] = { | |||
57 | }; | 59 | }; |
58 | MODULE_DEVICE_TABLE(pci, hpwdt_devices); | 60 | MODULE_DEVICE_TABLE(pci, hpwdt_devices); |
59 | 61 | ||
62 | #ifdef CONFIG_HPWDT_NMI_DECODING | ||
60 | #define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */ | 63 | #define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */ |
61 | #define CRU_BIOS_SIGNATURE_VALUE 0x55524324 | 64 | #define CRU_BIOS_SIGNATURE_VALUE 0x55524324 |
62 | #define PCI_BIOS32_PARAGRAPH_LEN 16 | 65 | #define PCI_BIOS32_PARAGRAPH_LEN 16 |
@@ -407,6 +410,7 @@ static int __devinit detect_cru_service(void) | |||
407 | } | 410 | } |
408 | /* ------------------------------------------------------------------------- */ | 411 | /* ------------------------------------------------------------------------- */ |
409 | #endif /* CONFIG_X86_64 */ | 412 | #endif /* CONFIG_X86_64 */ |
413 | #endif /* CONFIG_HPWDT_NMI_DECODING */ | ||
410 | 414 | ||
411 | /* | 415 | /* |
412 | * Watchdog operations | 416 | * Watchdog operations |
@@ -455,6 +459,7 @@ static int hpwdt_time_left(void) | |||
455 | return TICKS_TO_SECS(ioread16(hpwdt_timer_reg)); | 459 | return TICKS_TO_SECS(ioread16(hpwdt_timer_reg)); |
456 | } | 460 | } |
457 | 461 | ||
462 | #ifdef CONFIG_HPWDT_NMI_DECODING | ||
458 | /* | 463 | /* |
459 | * NMI Handler | 464 | * NMI Handler |
460 | */ | 465 | */ |
@@ -487,6 +492,7 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, | |||
487 | out: | 492 | out: |
488 | return NOTIFY_OK; | 493 | return NOTIFY_OK; |
489 | } | 494 | } |
495 | #endif /* CONFIG_HPWDT_NMI_DECODING */ | ||
490 | 496 | ||
491 | /* | 497 | /* |
492 | * /dev/watchdog handling | 498 | * /dev/watchdog handling |
@@ -624,15 +630,18 @@ static struct miscdevice hpwdt_miscdev = { | |||
624 | .fops = &hpwdt_fops, | 630 | .fops = &hpwdt_fops, |
625 | }; | 631 | }; |
626 | 632 | ||
633 | #ifdef CONFIG_HPWDT_NMI_DECODING | ||
627 | static struct notifier_block die_notifier = { | 634 | static struct notifier_block die_notifier = { |
628 | .notifier_call = hpwdt_pretimeout, | 635 | .notifier_call = hpwdt_pretimeout, |
629 | .priority = 0, | 636 | .priority = 0, |
630 | }; | 637 | }; |
638 | #endif /* CONFIG_HPWDT_NMI_DECODING */ | ||
631 | 639 | ||
632 | /* | 640 | /* |
633 | * Init & Exit | 641 | * Init & Exit |
634 | */ | 642 | */ |
635 | 643 | ||
644 | #ifdef CONFIG_HPWDT_NMI_DECODING | ||
636 | #ifdef ARCH_HAS_NMI_WATCHDOG | 645 | #ifdef ARCH_HAS_NMI_WATCHDOG |
637 | static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev) | 646 | static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev) |
638 | { | 647 | { |
@@ -712,6 +721,20 @@ static void __devexit hpwdt_exit_nmi_decoding(void) | |||
712 | if (cru_rom_addr) | 721 | if (cru_rom_addr) |
713 | iounmap(cru_rom_addr); | 722 | iounmap(cru_rom_addr); |
714 | } | 723 | } |
724 | #else /* !CONFIG_HPWDT_NMI_DECODING */ | ||
725 | static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev) | ||
726 | { | ||
727 | } | ||
728 | |||
729 | static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) | ||
730 | { | ||
731 | return 0; | ||
732 | } | ||
733 | |||
734 | static void __devexit hpwdt_exit_nmi_decoding(void) | ||
735 | { | ||
736 | } | ||
737 | #endif /* CONFIG_HPWDT_NMI_DECODING */ | ||
715 | 738 | ||
716 | static int __devinit hpwdt_init_one(struct pci_dev *dev, | 739 | static int __devinit hpwdt_init_one(struct pci_dev *dev, |
717 | const struct pci_device_id *ent) | 740 | const struct pci_device_id *ent) |
@@ -823,12 +846,14 @@ module_param(nowayout, int, 0); | |||
823 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | 846 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" |
824 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 847 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); |
825 | 848 | ||
849 | #ifdef CONFIG_HPWDT_NMI_DECODING | ||
826 | module_param(allow_kdump, int, 0); | 850 | module_param(allow_kdump, int, 0); |
827 | MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs"); | 851 | MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs"); |
828 | 852 | ||
829 | module_param(priority, int, 0); | 853 | module_param(priority, int, 0); |
830 | MODULE_PARM_DESC(priority, "The hpwdt driver handles NMIs first or last" | 854 | MODULE_PARM_DESC(priority, "The hpwdt driver handles NMIs first or last" |
831 | " (default = 0/Last)\n"); | 855 | " (default = 0/Last)\n"); |
856 | #endif /* !CONFIG_HPWDT_NMI_DECODING */ | ||
832 | 857 | ||
833 | module_init(hpwdt_init); | 858 | module_init(hpwdt_init); |
834 | module_exit(hpwdt_cleanup); | 859 | module_exit(hpwdt_cleanup); |