aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-13 20:58:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-13 20:58:54 -0400
commit7ec3fa1f4a5c4f9cc3d72983bfd8ac87cae356ab (patch)
treecd9dc3433846e59559666b6f5c022a27fc036607
parent9a459f6812fc26e0eb24bbe9c388000e23f67f6b (diff)
parent86ded1f35df32ad795cfc8cc1bdaeffbcaec0d5f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
* git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog: watchdog: hpwdt (12/12): Make NMI decoding a compile-time option watchdog: hpwdt (11/12): move NMI-decoding init and exit to seperate functions watchdog: hpwdt (10/12): Use "decoding" instead of "sourcing" watchdog: hpwdt (9/12): hpwdt_pretimeout reorganization watchdog: hpwdt (8/12): implement WDIOC_GETTIMELEFT watchdog: hpwdt (7/12): allow full range of timer values supported by hardware watchdog: hpwdt (6/12): Introduce SECS_TO_TICKS() macro watchdog: hpwdt (5/12): Make x86 assembly ifdef guard more strict watchdog: hpwdt (4/12): Despecificate driver from iLO2 watchdog: hpwdt (3/12): Group NMI sourcing specific items together watchdog: hpwdt (2/12): Group options that affect watchdog behavior together watchdog: hpwdt (1/12): clean-up include-files.
-rw-r--r--drivers/watchdog/Kconfig19
-rw-r--r--drivers/watchdog/hpwdt.c306
2 files changed, 186 insertions, 139 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 4d2992aadfb7..b036677df8c4 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -574,16 +574,21 @@ config IT87_WDT
574 be called it87_wdt. 574 be called it87_wdt.
575 575
576config HP_WATCHDOG 576config HP_WATCHDOG
577 tristate "HP Proliant iLO 2 Hardware Watchdog Timer" 577 tristate "HP Proliant iLO2+ Hardware Watchdog Timer"
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 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. 586config 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
588config SC1200_WDT 593config 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 fd312fc8940e..3d77116e4634 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -16,38 +16,55 @@
16#include <linux/device.h> 16#include <linux/device.h>
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/interrupt.h>
20#include <linux/io.h> 19#include <linux/io.h>
21#include <linux/irq.h> 20#include <linux/bitops.h>
22#include <linux/nmi.h>
23#include <linux/kernel.h> 21#include <linux/kernel.h>
24#include <linux/miscdevice.h> 22#include <linux/miscdevice.h>
25#include <linux/mm.h>
26#include <linux/module.h> 23#include <linux/module.h>
27#include <linux/kdebug.h>
28#include <linux/moduleparam.h> 24#include <linux/moduleparam.h>
29#include <linux/notifier.h>
30#include <linux/pci.h> 25#include <linux/pci.h>
31#include <linux/pci_ids.h> 26#include <linux/pci_ids.h>
32#include <linux/reboot.h>
33#include <linux/sched.h>
34#include <linux/timer.h>
35#include <linux/types.h> 27#include <linux/types.h>
36#include <linux/uaccess.h> 28#include <linux/uaccess.h>
37#include <linux/watchdog.h> 29#include <linux/watchdog.h>
30#ifdef CONFIG_HPWDT_NMI_DECODING
38#include <linux/dmi.h> 31#include <linux/dmi.h>
39#include <linux/efi.h> 32#include <linux/spinlock.h>
40#include <linux/string.h> 33#include <linux/nmi.h>
41#include <linux/bootmem.h> 34#include <linux/kdebug.h>
42#include <asm/desc.h> 35#include <linux/notifier.h>
43#include <asm/cacheflush.h> 36#include <asm/cacheflush.h>
37#endif /* CONFIG_HPWDT_NMI_DECODING */
38
39#define HPWDT_VERSION "1.2.0"
40#define SECS_TO_TICKS(secs) ((secs) * 1000 / 128)
41#define TICKS_TO_SECS(ticks) ((ticks) * 128 / 1000)
42#define HPWDT_MAX_TIMER TICKS_TO_SECS(65535)
43#define DEFAULT_MARGIN 30
44
45static unsigned int soft_margin = DEFAULT_MARGIN; /* in seconds */
46static unsigned int reload; /* the computed soft_margin */
47static int nowayout = WATCHDOG_NOWAYOUT;
48static char expect_release;
49static unsigned long hpwdt_is_open;
50
51static void __iomem *pci_mem_addr; /* the PCI-memory address */
52static unsigned long __iomem *hpwdt_timer_reg;
53static unsigned long __iomem *hpwdt_timer_con;
44 54
55static struct pci_device_id hpwdt_devices[] = {
56 { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) }, /* iLO2 */
57 { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) }, /* iLO3 */
58 {0}, /* terminate list */
59};
60MODULE_DEVICE_TABLE(pci, hpwdt_devices);
61
62#ifdef CONFIG_HPWDT_NMI_DECODING
45#define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */ 63#define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */
46#define CRU_BIOS_SIGNATURE_VALUE 0x55524324 64#define CRU_BIOS_SIGNATURE_VALUE 0x55524324
47#define PCI_BIOS32_PARAGRAPH_LEN 16 65#define PCI_BIOS32_PARAGRAPH_LEN 16
48#define PCI_ROM_BASE1 0x000F0000 66#define PCI_ROM_BASE1 0x000F0000
49#define ROM_SIZE 0x10000 67#define ROM_SIZE 0x10000
50#define HPWDT_VERSION "1.1.1"
51 68
52struct bios32_service_dir { 69struct bios32_service_dir {
53 u32 signature; 70 u32 signature;
@@ -112,37 +129,17 @@ struct cmn_registers {
112 u32 reflags; 129 u32 reflags;
113} __attribute__((packed)); 130} __attribute__((packed));
114 131
115#define DEFAULT_MARGIN 30 132static unsigned int hpwdt_nmi_decoding;
116static unsigned int soft_margin = DEFAULT_MARGIN; /* in seconds */
117static unsigned int reload; /* the computed soft_margin */
118static int nowayout = WATCHDOG_NOWAYOUT;
119static char expect_release;
120static unsigned long hpwdt_is_open;
121static unsigned int allow_kdump; 133static unsigned int allow_kdump;
122static unsigned int hpwdt_nmi_sourcing;
123static unsigned int priority; /* hpwdt at end of die_notify list */ 134static unsigned int priority; /* hpwdt at end of die_notify list */
124
125static void __iomem *pci_mem_addr; /* the PCI-memory address */
126static unsigned long __iomem *hpwdt_timer_reg;
127static unsigned long __iomem *hpwdt_timer_con;
128
129static DEFINE_SPINLOCK(rom_lock); 135static DEFINE_SPINLOCK(rom_lock);
130
131static void *cru_rom_addr; 136static void *cru_rom_addr;
132
133static struct cmn_registers cmn_regs; 137static struct cmn_registers cmn_regs;
134 138
135static struct pci_device_id hpwdt_devices[] = {
136 { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) },
137 { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) },
138 {0}, /* terminate list */
139};
140MODULE_DEVICE_TABLE(pci, hpwdt_devices);
141
142extern asmlinkage void asminline_call(struct cmn_registers *pi86Regs, 139extern asmlinkage void asminline_call(struct cmn_registers *pi86Regs,
143 unsigned long *pRomEntry); 140 unsigned long *pRomEntry);
144 141
145#ifndef CONFIG_X86_64 142#ifdef CONFIG_X86_32
146/* --32 Bit Bios------------------------------------------------------------ */ 143/* --32 Bit Bios------------------------------------------------------------ */
147 144
148#define HPWDT_ARCH 32 145#define HPWDT_ARCH 32
@@ -331,8 +328,9 @@ static int __devinit detect_cru_service(void)
331 iounmap(p); 328 iounmap(p);
332 return rc; 329 return rc;
333} 330}
334 331/* ------------------------------------------------------------------------- */
335#else 332#endif /* CONFIG_X86_32 */
333#ifdef CONFIG_X86_64
336/* --64 Bit Bios------------------------------------------------------------ */ 334/* --64 Bit Bios------------------------------------------------------------ */
337 335
338#define HPWDT_ARCH 64 336#define HPWDT_ARCH 64
@@ -410,17 +408,16 @@ static int __devinit detect_cru_service(void)
410 /* if cru_rom_addr has been set then we found a CRU service */ 408 /* if cru_rom_addr has been set then we found a CRU service */
411 return ((cru_rom_addr != NULL) ? 0 : -ENODEV); 409 return ((cru_rom_addr != NULL) ? 0 : -ENODEV);
412} 410}
413
414/* ------------------------------------------------------------------------- */ 411/* ------------------------------------------------------------------------- */
415 412#endif /* CONFIG_X86_64 */
416#endif 413#endif /* CONFIG_HPWDT_NMI_DECODING */
417 414
418/* 415/*
419 * Watchdog operations 416 * Watchdog operations
420 */ 417 */
421static void hpwdt_start(void) 418static void hpwdt_start(void)
422{ 419{
423 reload = (soft_margin * 1000) / 128; 420 reload = SECS_TO_TICKS(soft_margin);
424 iowrite16(reload, hpwdt_timer_reg); 421 iowrite16(reload, hpwdt_timer_reg);
425 iowrite16(0x85, hpwdt_timer_con); 422 iowrite16(0x85, hpwdt_timer_con);
426} 423}
@@ -441,8 +438,7 @@ static void hpwdt_ping(void)
441 438
442static int hpwdt_change_timer(int new_margin) 439static int hpwdt_change_timer(int new_margin)
443{ 440{
444 /* Arbitrary, can't find the card's limits */ 441 if (new_margin < 1 || new_margin > HPWDT_MAX_TIMER) {
445 if (new_margin < 5 || new_margin > 600) {
446 printk(KERN_WARNING 442 printk(KERN_WARNING
447 "hpwdt: New value passed in is invalid: %d seconds.\n", 443 "hpwdt: New value passed in is invalid: %d seconds.\n",
448 new_margin); 444 new_margin);
@@ -453,11 +449,17 @@ static int hpwdt_change_timer(int new_margin)
453 printk(KERN_DEBUG 449 printk(KERN_DEBUG
454 "hpwdt: New timer passed in is %d seconds.\n", 450 "hpwdt: New timer passed in is %d seconds.\n",
455 new_margin); 451 new_margin);
456 reload = (soft_margin * 1000) / 128; 452 reload = SECS_TO_TICKS(soft_margin);
457 453
458 return 0; 454 return 0;
459} 455}
460 456
457static int hpwdt_time_left(void)
458{
459 return TICKS_TO_SECS(ioread16(hpwdt_timer_reg));
460}
461
462#ifdef CONFIG_HPWDT_NMI_DECODING
461/* 463/*
462 * NMI Handler 464 * NMI Handler
463 */ 465 */
@@ -468,26 +470,29 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason,
468 static int die_nmi_called; 470 static int die_nmi_called;
469 471
470 if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) 472 if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI)
471 return NOTIFY_OK; 473 goto out;
472 474
473 if (hpwdt_nmi_sourcing) { 475 if (!hpwdt_nmi_decoding)
474 spin_lock_irqsave(&rom_lock, rom_pl); 476 goto out;
475 if (!die_nmi_called) 477
476 asminline_call(&cmn_regs, cru_rom_addr); 478 spin_lock_irqsave(&rom_lock, rom_pl);
477 die_nmi_called = 1; 479 if (!die_nmi_called)
478 spin_unlock_irqrestore(&rom_lock, rom_pl); 480 asminline_call(&cmn_regs, cru_rom_addr);
479 if (cmn_regs.u1.ral == 0) { 481 die_nmi_called = 1;
480 printk(KERN_WARNING "hpwdt: An NMI occurred, " 482 spin_unlock_irqrestore(&rom_lock, rom_pl);
481 "but unable to determine source.\n"); 483 if (cmn_regs.u1.ral == 0) {
482 } else { 484 printk(KERN_WARNING "hpwdt: An NMI occurred, "
483 if (allow_kdump) 485 "but unable to determine source.\n");
484 hpwdt_stop(); 486 } else {
485 panic("An NMI occurred, please see the Integrated " 487 if (allow_kdump)
486 "Management Log for details.\n"); 488 hpwdt_stop();
487 } 489 panic("An NMI occurred, please see the Integrated "
490 "Management Log for details.\n");
488 } 491 }
492out:
489 return NOTIFY_OK; 493 return NOTIFY_OK;
490} 494}
495#endif /* CONFIG_HPWDT_NMI_DECODING */
491 496
492/* 497/*
493 * /dev/watchdog handling 498 * /dev/watchdog handling
@@ -557,7 +562,7 @@ static const struct watchdog_info ident = {
557 .options = WDIOF_SETTIMEOUT | 562 .options = WDIOF_SETTIMEOUT |
558 WDIOF_KEEPALIVEPING | 563 WDIOF_KEEPALIVEPING |
559 WDIOF_MAGICCLOSE, 564 WDIOF_MAGICCLOSE,
560 .identity = "HP iLO2 HW Watchdog Timer", 565 .identity = "HP iLO2+ HW Watchdog Timer",
561}; 566};
562 567
563static long hpwdt_ioctl(struct file *file, unsigned int cmd, 568static long hpwdt_ioctl(struct file *file, unsigned int cmd,
@@ -599,6 +604,10 @@ static long hpwdt_ioctl(struct file *file, unsigned int cmd,
599 case WDIOC_GETTIMEOUT: 604 case WDIOC_GETTIMEOUT:
600 ret = put_user(soft_margin, p); 605 ret = put_user(soft_margin, p);
601 break; 606 break;
607
608 case WDIOC_GETTIMELEFT:
609 ret = put_user(hpwdt_time_left(), p);
610 break;
602 } 611 }
603 return ret; 612 return ret;
604} 613}
@@ -621,80 +630,45 @@ static struct miscdevice hpwdt_miscdev = {
621 .fops = &hpwdt_fops, 630 .fops = &hpwdt_fops,
622}; 631};
623 632
633#ifdef CONFIG_HPWDT_NMI_DECODING
624static struct notifier_block die_notifier = { 634static struct notifier_block die_notifier = {
625 .notifier_call = hpwdt_pretimeout, 635 .notifier_call = hpwdt_pretimeout,
626 .priority = 0, 636 .priority = 0,
627}; 637};
638#endif /* CONFIG_HPWDT_NMI_DECODING */
628 639
629/* 640/*
630 * Init & Exit 641 * Init & Exit
631 */ 642 */
632 643
644#ifdef CONFIG_HPWDT_NMI_DECODING
633#ifdef ARCH_HAS_NMI_WATCHDOG 645#ifdef ARCH_HAS_NMI_WATCHDOG
634static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev) 646static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
635{ 647{
636 /* 648 /*
637 * If nmi_watchdog is turned off then we can turn on 649 * If nmi_watchdog is turned off then we can turn on
638 * our nmi sourcing capability. 650 * our nmi decoding capability.
639 */ 651 */
640 if (!nmi_watchdog_active()) 652 if (!nmi_watchdog_active())
641 hpwdt_nmi_sourcing = 1; 653 hpwdt_nmi_decoding = 1;
642 else 654 else
643 dev_warn(&dev->dev, "NMI sourcing is disabled. To enable this " 655 dev_warn(&dev->dev, "NMI decoding is disabled. To enable this "
644 "functionality you must reboot with nmi_watchdog=0 " 656 "functionality you must reboot with nmi_watchdog=0 "
645 "and load the hpwdt driver with priority=1.\n"); 657 "and load the hpwdt driver with priority=1.\n");
646} 658}
647#else 659#else
648static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev) 660static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
649{ 661{
650 dev_warn(&dev->dev, "NMI sourcing is disabled. " 662 dev_warn(&dev->dev, "NMI decoding is disabled. "
651 "Your kernel does not support a NMI Watchdog.\n"); 663 "Your kernel does not support a NMI Watchdog.\n");
652} 664}
653#endif 665#endif /* ARCH_HAS_NMI_WATCHDOG */
654 666
655static int __devinit hpwdt_init_one(struct pci_dev *dev, 667static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
656 const struct pci_device_id *ent)
657{ 668{
658 int retval; 669 int retval;
659 670
660 /* 671 /*
661 * Check if we can do NMI sourcing or not
662 */
663 hpwdt_check_nmi_sourcing(dev);
664
665 /*
666 * First let's find out if we are on an iLO2 server. We will
667 * not run on a legacy ASM box.
668 * So we only support the G5 ProLiant servers and higher.
669 */
670 if (dev->subsystem_vendor != PCI_VENDOR_ID_HP) {
671 dev_warn(&dev->dev,
672 "This server does not have an iLO2 ASIC.\n");
673 return -ENODEV;
674 }
675
676 if (pci_enable_device(dev)) {
677 dev_warn(&dev->dev,
678 "Not possible to enable PCI Device: 0x%x:0x%x.\n",
679 ent->vendor, ent->device);
680 return -ENODEV;
681 }
682
683 pci_mem_addr = pci_iomap(dev, 1, 0x80);
684 if (!pci_mem_addr) {
685 dev_warn(&dev->dev,
686 "Unable to detect the iLO2 server memory.\n");
687 retval = -ENOMEM;
688 goto error_pci_iomap;
689 }
690 hpwdt_timer_reg = pci_mem_addr + 0x70;
691 hpwdt_timer_con = pci_mem_addr + 0x72;
692
693 /* Make sure that we have a valid soft_margin */
694 if (hpwdt_change_timer(soft_margin))
695 hpwdt_change_timer(DEFAULT_MARGIN);
696
697 /*
698 * We need to map the ROM to get the CRU service. 672 * We need to map the ROM to get the CRU service.
699 * For 32 bit Operating Systems we need to go through the 32 Bit 673 * For 32 bit Operating Systems we need to go through the 32 Bit
700 * BIOS Service Directory 674 * BIOS Service Directory
@@ -705,7 +679,7 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
705 dev_warn(&dev->dev, 679 dev_warn(&dev->dev,
706 "Unable to detect the %d Bit CRU Service.\n", 680 "Unable to detect the %d Bit CRU Service.\n",
707 HPWDT_ARCH); 681 HPWDT_ARCH);
708 goto error_get_cru; 682 return retval;
709 } 683 }
710 684
711 /* 685 /*
@@ -728,9 +702,87 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
728 dev_warn(&dev->dev, 702 dev_warn(&dev->dev,
729 "Unable to register a die notifier (err=%d).\n", 703 "Unable to register a die notifier (err=%d).\n",
730 retval); 704 retval);
731 goto error_die_notifier; 705 if (cru_rom_addr)
706 iounmap(cru_rom_addr);
732 } 707 }
733 708
709 dev_info(&dev->dev,
710 "HP Watchdog Timer Driver: NMI decoding initialized"
711 ", allow kernel dump: %s (default = 0/OFF)"
712 ", priority: %s (default = 0/LAST).\n",
713 (allow_kdump == 0) ? "OFF" : "ON",
714 (priority == 0) ? "LAST" : "FIRST");
715 return 0;
716}
717
718static void __devexit hpwdt_exit_nmi_decoding(void)
719{
720 unregister_die_notifier(&die_notifier);
721 if (cru_rom_addr)
722 iounmap(cru_rom_addr);
723}
724#else /* !CONFIG_HPWDT_NMI_DECODING */
725static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
726{
727}
728
729static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
730{
731 return 0;
732}
733
734static void __devexit hpwdt_exit_nmi_decoding(void)
735{
736}
737#endif /* CONFIG_HPWDT_NMI_DECODING */
738
739static int __devinit hpwdt_init_one(struct pci_dev *dev,
740 const struct pci_device_id *ent)
741{
742 int retval;
743
744 /*
745 * Check if we can do NMI decoding or not
746 */
747 hpwdt_check_nmi_decoding(dev);
748
749 /*
750 * First let's find out if we are on an iLO2+ server. We will
751 * not run on a legacy ASM box.
752 * So we only support the G5 ProLiant servers and higher.
753 */
754 if (dev->subsystem_vendor != PCI_VENDOR_ID_HP) {
755 dev_warn(&dev->dev,
756 "This server does not have an iLO2+ ASIC.\n");
757 return -ENODEV;
758 }
759
760 if (pci_enable_device(dev)) {
761 dev_warn(&dev->dev,
762 "Not possible to enable PCI Device: 0x%x:0x%x.\n",
763 ent->vendor, ent->device);
764 return -ENODEV;
765 }
766
767 pci_mem_addr = pci_iomap(dev, 1, 0x80);
768 if (!pci_mem_addr) {
769 dev_warn(&dev->dev,
770 "Unable to detect the iLO2+ server memory.\n");
771 retval = -ENOMEM;
772 goto error_pci_iomap;
773 }
774 hpwdt_timer_reg = pci_mem_addr + 0x70;
775 hpwdt_timer_con = pci_mem_addr + 0x72;
776
777 /* Make sure that we have a valid soft_margin */
778 if (hpwdt_change_timer(soft_margin))
779 hpwdt_change_timer(DEFAULT_MARGIN);
780
781 /* Initialize NMI Decoding functionality */
782 retval = hpwdt_init_nmi_decoding(dev);
783 if (retval != 0)
784 goto error_init_nmi_decoding;
785
734 retval = misc_register(&hpwdt_miscdev); 786 retval = misc_register(&hpwdt_miscdev);
735 if (retval < 0) { 787 if (retval < 0) {
736 dev_warn(&dev->dev, 788 dev_warn(&dev->dev,
@@ -739,23 +791,14 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
739 goto error_misc_register; 791 goto error_misc_register;
740 } 792 }
741 793
742 printk(KERN_INFO 794 dev_info(&dev->dev, "HP Watchdog Timer Driver: %s"
743 "hp Watchdog Timer Driver: %s" 795 ", timer margin: %d seconds (nowayout=%d).\n",
744 ", timer margin: %d seconds (nowayout=%d)" 796 HPWDT_VERSION, soft_margin, nowayout);
745 ", allow kernel dump: %s (default = 0/OFF)"
746 ", priority: %s (default = 0/LAST).\n",
747 HPWDT_VERSION, soft_margin, nowayout,
748 (allow_kdump == 0) ? "OFF" : "ON",
749 (priority == 0) ? "LAST" : "FIRST");
750
751 return 0; 797 return 0;
752 798
753error_misc_register: 799error_misc_register:
754 unregister_die_notifier(&die_notifier); 800 hpwdt_exit_nmi_decoding();
755error_die_notifier: 801error_init_nmi_decoding:
756 if (cru_rom_addr)
757 iounmap(cru_rom_addr);
758error_get_cru:
759 pci_iounmap(dev, pci_mem_addr); 802 pci_iounmap(dev, pci_mem_addr);
760error_pci_iomap: 803error_pci_iomap:
761 pci_disable_device(dev); 804 pci_disable_device(dev);
@@ -768,10 +811,7 @@ static void __devexit hpwdt_exit(struct pci_dev *dev)
768 hpwdt_stop(); 811 hpwdt_stop();
769 812
770 misc_deregister(&hpwdt_miscdev); 813 misc_deregister(&hpwdt_miscdev);
771 unregister_die_notifier(&die_notifier); 814 hpwdt_exit_nmi_decoding();
772
773 if (cru_rom_addr)
774 iounmap(cru_rom_addr);
775 pci_iounmap(dev, pci_mem_addr); 815 pci_iounmap(dev, pci_mem_addr);
776 pci_disable_device(dev); 816 pci_disable_device(dev);
777} 817}
@@ -802,16 +842,18 @@ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
802module_param(soft_margin, int, 0); 842module_param(soft_margin, int, 0);
803MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds"); 843MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds");
804 844
805module_param(allow_kdump, int, 0);
806MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs");
807
808module_param(nowayout, int, 0); 845module_param(nowayout, int, 0);
809MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 846MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
810 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 847 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
811 848
849#ifdef CONFIG_HPWDT_NMI_DECODING
850module_param(allow_kdump, int, 0);
851MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs");
852
812module_param(priority, int, 0); 853module_param(priority, int, 0);
813MODULE_PARM_DESC(priority, "The hpwdt driver handles NMIs first or last" 854MODULE_PARM_DESC(priority, "The hpwdt driver handles NMIs first or last"
814 " (default = 0/Last)\n"); 855 " (default = 0/Last)\n");
856#endif /* !CONFIG_HPWDT_NMI_DECODING */
815 857
816module_init(hpwdt_init); 858module_init(hpwdt_init);
817module_exit(hpwdt_cleanup); 859module_exit(hpwdt_cleanup);