diff options
author | Tom Mingarelli <thomas.mingarelli@hp.com> | 2009-06-18 19:28:57 -0400 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2009-06-23 03:13:45 -0400 |
commit | 44df75353bc8f32e26e049284053a61d4f1047d6 (patch) | |
tree | 8ac01af7888c6d5c3746d30834fd63a148305078 | |
parent | 789cd4702bf830416d2e1794495407be42fe95ad (diff) |
[WATCHDOG] hpwdt: Add NMI priority option
Add a priority option so that the user can choose if we do the NMI
first or last.
Signed-off-by: Thomas Mingarelli <thomas.mingarelli@hp.com>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
-rw-r--r-- | Documentation/watchdog/hpwdt.txt | 19 | ||||
-rw-r--r-- | drivers/watchdog/hpwdt.c | 26 |
2 files changed, 36 insertions, 9 deletions
diff --git a/Documentation/watchdog/hpwdt.txt b/Documentation/watchdog/hpwdt.txt index 127839e53043..9c24d5ffbb06 100644 --- a/Documentation/watchdog/hpwdt.txt +++ b/Documentation/watchdog/hpwdt.txt | |||
@@ -19,30 +19,41 @@ Last reviewed: 06/02/2009 | |||
19 | not be updated in a timely fashion and a hardware system reset (also known as | 19 | not be updated in a timely fashion and a hardware system reset (also known as |
20 | an Automatic Server Recovery (ASR)) event will occur. | 20 | an Automatic Server Recovery (ASR)) event will occur. |
21 | 21 | ||
22 | The hpwdt driver also has three (3) module parameters. They are the following: | 22 | The hpwdt driver also has four (4) module parameters. They are the following: |
23 | 23 | ||
24 | soft_margin - allows the user to set the watchdog timer value | 24 | soft_margin - allows the user to set the watchdog timer value |
25 | allow_kdump - allows the user to save off a kernel dump image after an NMI | 25 | allow_kdump - allows the user to save off a kernel dump image after an NMI |
26 | nowayout - basic watchdog parameter that does not allow the timer to | 26 | nowayout - basic watchdog parameter that does not allow the timer to |
27 | be restarted or an impending ASR to be escaped. | 27 | be restarted or an impending ASR to be escaped. |
28 | priority - determines whether or not the hpwdt driver is first on the | ||
29 | die_notify list to handle NMIs or last. The default value | ||
30 | for this module parameter is 0 or LAST. If the user wants to | ||
31 | enable NMI sourcing then reload the hpwdt driver with | ||
32 | priority=1 (and boot with nmi_watchdog=0). | ||
28 | 33 | ||
29 | NOTE: More information about watchdog drivers in general, including the ioctl | 34 | NOTE: More information about watchdog drivers in general, including the ioctl |
30 | interface to /dev/watchdog can be found in | 35 | interface to /dev/watchdog can be found in |
31 | Documentation/watchdog/watchdog-api.txt and Documentation/IPMI.txt. | 36 | Documentation/watchdog/watchdog-api.txt and Documentation/IPMI.txt. |
32 | 37 | ||
33 | The NMI sourcing capability is disabled when the driver discovers that the | 38 | The priority parameter was introduced due to other kernel software that relied |
34 | nmi_watchdog is turned on (nmi_watchdog = 1). This is due to the inability to | 39 | on handling NMIs (like oprofile). Keeping hpwdt's priority at 0 (or LAST) |
40 | enables the users of NMIs for non critical events to be work as expected. | ||
41 | |||
42 | The NMI sourcing capability is disabled by default due to the inability to | ||
35 | distinguish between "NMI Watchdog Ticks" and "HW generated NMI events" in the | 43 | distinguish between "NMI Watchdog Ticks" and "HW generated NMI events" in the |
36 | Linux kernel. What this means is that the hpwdt nmi handler code is called | 44 | Linux kernel. What this means is that the hpwdt nmi handler code is called |
37 | each time the NMI signal fires off. This could amount to several thousands of | 45 | each time the NMI signal fires off. This could amount to several thousands of |
38 | NMIs in a matter of seconds. If a user sees the Linux kernel's "dazed and | 46 | NMIs in a matter of seconds. If a user sees the Linux kernel's "dazed and |
39 | confused" message in the logs or if the system gets into a hung state, then | 47 | confused" message in the logs or if the system gets into a hung state, then |
40 | the user should reboot with nmi_watchdog=0. | 48 | the hpwdt driver can be reloaded with the "priority" module parameter set |
49 | (priority=1). | ||
41 | 50 | ||
42 | 1. If the kernel has not been booted with nmi_watchdog turned off then | 51 | 1. If the kernel has not been booted with nmi_watchdog turned off then |
43 | edit /boot/grub/menu.lst and place the nmi_watchdog=0 at the end of the | 52 | edit /boot/grub/menu.lst and place the nmi_watchdog=0 at the end of the |
44 | currently booting kernel line. | 53 | currently booting kernel line. |
45 | 2. reboot the sever | 54 | 2. reboot the sever |
55 | 3. Once the system comes up perform a rmmod hpwdt | ||
56 | 4. insmod /lib/modules/`uname -r`/kernel/drivers/char/watchdog/hpwdt.ko priority=1 | ||
46 | 57 | ||
47 | Now, the hpwdt can successfully receive and source the NMI and provide a log | 58 | Now, the hpwdt can successfully receive and source the NMI and provide a log |
48 | message that details the reason for the NMI (as determined by the HP BIOS). | 59 | message that details the reason for the NMI (as determined by the HP BIOS). |
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index c0b9169ba5d5..a6c5674c78e6 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c | |||
@@ -120,7 +120,8 @@ static int nowayout = WATCHDOG_NOWAYOUT; | |||
120 | static char expect_release; | 120 | static char expect_release; |
121 | static unsigned long hpwdt_is_open; | 121 | static unsigned long hpwdt_is_open; |
122 | static unsigned int allow_kdump; | 122 | static unsigned int allow_kdump; |
123 | static int hpwdt_nmi_sourcing; | 123 | static unsigned int hpwdt_nmi_sourcing; |
124 | static unsigned int priority; /* hpwdt at end of die_notify list */ | ||
124 | 125 | ||
125 | static void __iomem *pci_mem_addr; /* the PCI-memory address */ | 126 | static void __iomem *pci_mem_addr; /* the PCI-memory address */ |
126 | static unsigned long __iomem *hpwdt_timer_reg; | 127 | static unsigned long __iomem *hpwdt_timer_reg; |
@@ -623,7 +624,7 @@ static struct miscdevice hpwdt_miscdev = { | |||
623 | 624 | ||
624 | static struct notifier_block die_notifier = { | 625 | static struct notifier_block die_notifier = { |
625 | .notifier_call = hpwdt_pretimeout, | 626 | .notifier_call = hpwdt_pretimeout, |
626 | .priority = 0x7FFFFFFF, | 627 | .priority = 0, |
627 | }; | 628 | }; |
628 | 629 | ||
629 | /* | 630 | /* |
@@ -641,7 +642,8 @@ static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev) | |||
641 | hpwdt_nmi_sourcing = 1; | 642 | hpwdt_nmi_sourcing = 1; |
642 | else | 643 | else |
643 | dev_warn(&dev->dev, "NMI sourcing is disabled. To enable this " | 644 | dev_warn(&dev->dev, "NMI sourcing is disabled. To enable this " |
644 | "functionality you must reboot with nmi_watchdog=0.\n"); | 645 | "functionality you must reboot with nmi_watchdog=0 " |
646 | "and load the hpwdt driver with priority=1.\n"); | ||
645 | } | 647 | } |
646 | #else | 648 | #else |
647 | static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev) | 649 | static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev) |
@@ -714,6 +716,14 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev, | |||
714 | cmn_regs.u1.rah = 0x0D; | 716 | cmn_regs.u1.rah = 0x0D; |
715 | cmn_regs.u1.ral = 0x02; | 717 | cmn_regs.u1.ral = 0x02; |
716 | 718 | ||
719 | /* | ||
720 | * If the priority is set to 1, then we will be put first on the | ||
721 | * die notify list to handle a critical NMI. The default is to | ||
722 | * be last so other users of the NMI signal can function. | ||
723 | */ | ||
724 | if (priority) | ||
725 | die_notifier.priority = 0x7FFFFFFF; | ||
726 | |||
717 | retval = register_die_notifier(&die_notifier); | 727 | retval = register_die_notifier(&die_notifier); |
718 | if (retval != 0) { | 728 | if (retval != 0) { |
719 | dev_warn(&dev->dev, | 729 | dev_warn(&dev->dev, |
@@ -733,9 +743,11 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev, | |||
733 | printk(KERN_INFO | 743 | printk(KERN_INFO |
734 | "hp Watchdog Timer Driver: %s" | 744 | "hp Watchdog Timer Driver: %s" |
735 | ", timer margin: %d seconds (nowayout=%d)" | 745 | ", timer margin: %d seconds (nowayout=%d)" |
736 | ", allow kernel dump: %s (default = 0/OFF).\n", | 746 | ", allow kernel dump: %s (default = 0/OFF)" |
747 | ", priority: %s (default = 0/LAST).\n", | ||
737 | HPWDT_VERSION, soft_margin, nowayout, | 748 | HPWDT_VERSION, soft_margin, nowayout, |
738 | (allow_kdump == 0) ? "OFF" : "ON"); | 749 | (allow_kdump == 0) ? "OFF" : "ON", |
750 | (priority == 0) ? "LAST" : "FIRST"); | ||
739 | 751 | ||
740 | return 0; | 752 | return 0; |
741 | 753 | ||
@@ -798,5 +810,9 @@ module_param(nowayout, int, 0); | |||
798 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | 810 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" |
799 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 811 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); |
800 | 812 | ||
813 | module_param(priority, int, 0); | ||
814 | MODULE_PARM_DESC(priority, "The hpwdt driver handles NMIs first or last" | ||
815 | " (default = 0/Last)\n"); | ||
816 | |||
801 | module_init(hpwdt_init); | 817 | module_init(hpwdt_init); |
802 | module_exit(hpwdt_cleanup); | 818 | module_exit(hpwdt_cleanup); |