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); |
