aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/hpwdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/hpwdt.c')
-rw-r--r--drivers/watchdog/hpwdt.c124
1 files changed, 69 insertions, 55 deletions
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 99aa76c489a3..850f17877e9c 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -653,7 +653,65 @@ static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
653 dev_warn(&dev->dev, "NMI decoding is disabled. " 653 dev_warn(&dev->dev, "NMI decoding is disabled. "
654 "Your kernel does not support a NMI Watchdog.\n"); 654 "Your kernel does not support a NMI Watchdog.\n");
655} 655}
656#endif 656#endif /* ARCH_HAS_NMI_WATCHDOG */
657
658static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
659{
660 int retval;
661
662 /*
663 * We need to map the ROM to get the CRU service.
664 * For 32 bit Operating Systems we need to go through the 32 Bit
665 * BIOS Service Directory
666 * For 64 bit Operating Systems we get that service through SMBIOS.
667 */
668 retval = detect_cru_service();
669 if (retval < 0) {
670 dev_warn(&dev->dev,
671 "Unable to detect the %d Bit CRU Service.\n",
672 HPWDT_ARCH);
673 return retval;
674 }
675
676 /*
677 * We know this is the only CRU call we need to make so lets keep as
678 * few instructions as possible once the NMI comes in.
679 */
680 cmn_regs.u1.rah = 0x0D;
681 cmn_regs.u1.ral = 0x02;
682
683 /*
684 * If the priority is set to 1, then we will be put first on the
685 * die notify list to handle a critical NMI. The default is to
686 * be last so other users of the NMI signal can function.
687 */
688 if (priority)
689 die_notifier.priority = 0x7FFFFFFF;
690
691 retval = register_die_notifier(&die_notifier);
692 if (retval != 0) {
693 dev_warn(&dev->dev,
694 "Unable to register a die notifier (err=%d).\n",
695 retval);
696 if (cru_rom_addr)
697 iounmap(cru_rom_addr);
698 }
699
700 dev_info(&dev->dev,
701 "HP Watchdog Timer Driver: NMI decoding initialized"
702 ", allow kernel dump: %s (default = 0/OFF)"
703 ", priority: %s (default = 0/LAST).\n",
704 (allow_kdump == 0) ? "OFF" : "ON",
705 (priority == 0) ? "LAST" : "FIRST");
706 return 0;
707}
708
709static void __devexit hpwdt_exit_nmi_decoding(void)
710{
711 unregister_die_notifier(&die_notifier);
712 if (cru_rom_addr)
713 iounmap(cru_rom_addr);
714}
657 715
658static int __devinit hpwdt_init_one(struct pci_dev *dev, 716static int __devinit hpwdt_init_one(struct pci_dev *dev,
659 const struct pci_device_id *ent) 717 const struct pci_device_id *ent)
@@ -697,42 +755,10 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
697 if (hpwdt_change_timer(soft_margin)) 755 if (hpwdt_change_timer(soft_margin))
698 hpwdt_change_timer(DEFAULT_MARGIN); 756 hpwdt_change_timer(DEFAULT_MARGIN);
699 757
700 /* 758 /* Initialize NMI Decoding functionality */
701 * We need to map the ROM to get the CRU service. 759 retval = hpwdt_init_nmi_decoding(dev);
702 * For 32 bit Operating Systems we need to go through the 32 Bit 760 if (retval != 0)
703 * BIOS Service Directory 761 goto error_init_nmi_decoding;
704 * For 64 bit Operating Systems we get that service through SMBIOS.
705 */
706 retval = detect_cru_service();
707 if (retval < 0) {
708 dev_warn(&dev->dev,
709 "Unable to detect the %d Bit CRU Service.\n",
710 HPWDT_ARCH);
711 goto error_get_cru;
712 }
713
714 /*
715 * We know this is the only CRU call we need to make so lets keep as
716 * few instructions as possible once the NMI comes in.
717 */
718 cmn_regs.u1.rah = 0x0D;
719 cmn_regs.u1.ral = 0x02;
720
721 /*
722 * If the priority is set to 1, then we will be put first on the
723 * die notify list to handle a critical NMI. The default is to
724 * be last so other users of the NMI signal can function.
725 */
726 if (priority)
727 die_notifier.priority = 0x7FFFFFFF;
728
729 retval = register_die_notifier(&die_notifier);
730 if (retval != 0) {
731 dev_warn(&dev->dev,
732 "Unable to register a die notifier (err=%d).\n",
733 retval);
734 goto error_die_notifier;
735 }
736 762
737 retval = misc_register(&hpwdt_miscdev); 763 retval = misc_register(&hpwdt_miscdev);
738 if (retval < 0) { 764 if (retval < 0) {
@@ -742,23 +768,14 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
742 goto error_misc_register; 768 goto error_misc_register;
743 } 769 }
744 770
745 printk(KERN_INFO 771 dev_info(&dev->dev, "HP Watchdog Timer Driver: %s"
746 "hp Watchdog Timer Driver: %s" 772 ", timer margin: %d seconds (nowayout=%d).\n",
747 ", timer margin: %d seconds (nowayout=%d)" 773 HPWDT_VERSION, soft_margin, nowayout);
748 ", allow kernel dump: %s (default = 0/OFF)"
749 ", priority: %s (default = 0/LAST).\n",
750 HPWDT_VERSION, soft_margin, nowayout,
751 (allow_kdump == 0) ? "OFF" : "ON",
752 (priority == 0) ? "LAST" : "FIRST");
753
754 return 0; 774 return 0;
755 775
756error_misc_register: 776error_misc_register:
757 unregister_die_notifier(&die_notifier); 777 hpwdt_exit_nmi_decoding();
758error_die_notifier: 778error_init_nmi_decoding:
759 if (cru_rom_addr)
760 iounmap(cru_rom_addr);
761error_get_cru:
762 pci_iounmap(dev, pci_mem_addr); 779 pci_iounmap(dev, pci_mem_addr);
763error_pci_iomap: 780error_pci_iomap:
764 pci_disable_device(dev); 781 pci_disable_device(dev);
@@ -771,10 +788,7 @@ static void __devexit hpwdt_exit(struct pci_dev *dev)
771 hpwdt_stop(); 788 hpwdt_stop();
772 789
773 misc_deregister(&hpwdt_miscdev); 790 misc_deregister(&hpwdt_miscdev);
774 unregister_die_notifier(&die_notifier); 791 hpwdt_exit_nmi_decoding();
775
776 if (cru_rom_addr)
777 iounmap(cru_rom_addr);
778 pci_iounmap(dev, pci_mem_addr); 792 pci_iounmap(dev, pci_mem_addr);
779 pci_disable_device(dev); 793 pci_disable_device(dev);
780} 794}