diff options
| -rw-r--r-- | drivers/watchdog/hpwdt.c | 124 |
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 | |||
| 658 | static 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 | |||
| 709 | static 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 | ||
| 658 | static int __devinit hpwdt_init_one(struct pci_dev *dev, | 716 | static 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 | ||
| 756 | error_misc_register: | 776 | error_misc_register: |
| 757 | unregister_die_notifier(&die_notifier); | 777 | hpwdt_exit_nmi_decoding(); |
| 758 | error_die_notifier: | 778 | error_init_nmi_decoding: |
| 759 | if (cru_rom_addr) | ||
| 760 | iounmap(cru_rom_addr); | ||
| 761 | error_get_cru: | ||
| 762 | pci_iounmap(dev, pci_mem_addr); | 779 | pci_iounmap(dev, pci_mem_addr); |
| 763 | error_pci_iomap: | 780 | error_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 | } |
