diff options
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/Kconfig | 47 | ||||
-rw-r--r-- | drivers/watchdog/ar7_wdt.c | 1 | ||||
-rw-r--r-- | drivers/watchdog/booke_wdt.c | 47 | ||||
-rw-r--r-- | drivers/watchdog/cpwd.c | 20 | ||||
-rw-r--r-- | drivers/watchdog/ep93xx_wdt.c | 1 | ||||
-rw-r--r-- | drivers/watchdog/gef_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/hpwdt.c | 306 | ||||
-rw-r--r-- | drivers/watchdog/mpc8xxx_wdt.c | 4 | ||||
-rw-r--r-- | drivers/watchdog/octeon-wdt-main.c | 1 | ||||
-rw-r--r-- | drivers/watchdog/omap_wdt.c | 1 | ||||
-rw-r--r-- | drivers/watchdog/riowd.c | 4 | ||||
-rw-r--r-- | drivers/watchdog/sb_wdog.c | 12 | ||||
-rw-r--r-- | drivers/watchdog/ts72xx_wdt.c | 3 |
13 files changed, 280 insertions, 169 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 4d2992aadfb..c356146bd71 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -213,11 +213,11 @@ config OMAP_WATCHDOG here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. config PNX4008_WATCHDOG - tristate "PNX4008 Watchdog" - depends on ARCH_PNX4008 + tristate "PNX4008 and LPC32XX Watchdog" + depends on ARCH_PNX4008 || ARCH_LPC32XX help Say Y here if to include support for the watchdog timer - in the PNX4008 processor. + in the PNX4008 or LPC32XX processor. This driver can be built as a module by choosing M. The module will be called pnx4008_wdt. @@ -574,16 +574,21 @@ config IT87_WDT be called it87_wdt. config HP_WATCHDOG - tristate "HP Proliant iLO 2 Hardware Watchdog Timer" + tristate "HP Proliant iLO2+ Hardware Watchdog Timer" depends on X86 help A software monitoring watchdog and NMI sourcing driver. This driver - will detect lockups and provide stack trace. Also, when an NMI - occurs this driver will make the necessary BIOS calls to log - the cause of the NMI. This is a driver that will only load on a - HP ProLiant system with a minimum of iLO2 support. - To compile this driver as a module, choose M here: the - module will be called hpwdt. + will detect lockups and provide a stack trace. This is a driver that + will only load on a HP ProLiant system with a minimum of iLO2 support. + To compile this driver as a module, choose M here: the module will be + called hpwdt. + +config HPWDT_NMI_DECODING + bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer" + depends on HP_WATCHDOG + help + When an NMI occurs this feature will make the necessary BIOS calls to + log the cause of the NMI. config SC1200_WDT tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" @@ -952,12 +957,32 @@ config PIKA_WDT the Warp platform. config BOOKE_WDT - bool "PowerPC Book-E Watchdog Timer" + tristate "PowerPC Book-E Watchdog Timer" depends on BOOKE || 4xx ---help--- + Watchdog driver for PowerPC Book-E chips, such as the Freescale + MPC85xx SOCs and the IBM PowerPC 440. + Please see Documentation/watchdog/watchdog-api.txt for more information. +config BOOKE_WDT_DEFAULT_TIMEOUT + int "PowerPC Book-E Watchdog Timer Default Timeout" + depends on BOOKE_WDT + default 38 if FSL_BOOKE + range 0 63 if FSL_BOOKE + default 3 if !FSL_BOOKE + range 0 3 if !FSL_BOOKE + help + Select the default watchdog timer period to be used by the PowerPC + Book-E watchdog driver. A watchdog "event" occurs when the bit + position represented by this number transitions from zero to one. + + For Freescale Book-E processors, this is a number between 0 and 63. + For other Book-E processors, this is a number between 0 and 3. + + The value can be overidden by the wdt_period command-line parameter. + # PPC64 Architecture config WATCHDOG_RTAS diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index c764c52412e..b2922178359 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c @@ -267,6 +267,7 @@ static const struct file_operations ar7_wdt_fops = { .unlocked_ioctl = ar7_wdt_ioctl, .open = ar7_wdt_open, .release = ar7_wdt_release, + .llseek = no_llseek, }; static struct miscdevice ar7_wdt_miscdev = { diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index 3d49671cdf5..d11ffb091b0 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c @@ -4,7 +4,7 @@ * Author: Matthew McClintock * Maintainer: Kumar Gala <galak@kernel.crashing.org> * - * Copyright 2005, 2008 Freescale Semiconductor Inc. + * Copyright 2005, 2008, 2010 Freescale Semiconductor Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -33,14 +33,8 @@ * occur, and the final time the board will reset. */ -#ifdef CONFIG_FSL_BOOKE -#define WDT_PERIOD_DEFAULT 38 /* Ex. wdt_period=28 bus=333Mhz,reset=~40sec */ -#else -#define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */ -#endif /* for timing information */ - u32 booke_wdt_enabled; -u32 booke_wdt_period = WDT_PERIOD_DEFAULT; +u32 booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT; #ifdef CONFIG_FSL_BOOKE #define WDTP(x) ((((x)&0x3)<<30)|(((x)&0x3c)<<15)) @@ -114,6 +108,27 @@ static void __booke_wdt_enable(void *data) mtspr(SPRN_TCR, val); } +/** + * booke_wdt_disable - disable the watchdog on the given CPU + * + * This function is called on each CPU. It disables the watchdog on that CPU. + * + * TCR[WRC] cannot be changed once it has been set to non-zero, but we can + * effectively disable the watchdog by setting its period to the maximum value. + */ +static void __booke_wdt_disable(void *data) +{ + u32 val; + + val = mfspr(SPRN_TCR); + val &= ~(TCR_WIE | WDTP_MASK); + mtspr(SPRN_TCR, val); + + /* clear status to make sure nothing is pending */ + __booke_wdt_ping(NULL); + +} + static ssize_t booke_wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { @@ -193,12 +208,21 @@ static int booke_wdt_open(struct inode *inode, struct file *file) return nonseekable_open(inode, file); } +static int booke_wdt_release(struct inode *inode, struct file *file) +{ + on_each_cpu(__booke_wdt_disable, NULL, 0); + booke_wdt_enabled = 0; + + return 0; +} + static const struct file_operations booke_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = booke_wdt_write, .unlocked_ioctl = booke_wdt_ioctl, .open = booke_wdt_open, + .release = booke_wdt_release, }; static struct miscdevice booke_wdt_miscdev = { @@ -237,4 +261,9 @@ static int __init booke_wdt_init(void) return ret; } -device_initcall(booke_wdt_init); + +module_init(booke_wdt_init); +module_exit(booke_wdt_exit); + +MODULE_DESCRIPTION("PowerPC Book-E watchdog driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 30a2512fd52..eca855a55c0 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -25,7 +25,7 @@ #include <linux/ioport.h> #include <linux/timer.h> #include <linux/slab.h> -#include <linux/smp_lock.h> +#include <linux/mutex.h> #include <linux/io.h> #include <linux/of.h> #include <linux/of_device.h> @@ -89,6 +89,7 @@ struct cpwd { } devs[WD_NUMDEVS]; }; +static DEFINE_MUTEX(cpwd_mutex); static struct cpwd *cpwd_device; /* Sun uses Altera PLD EPF8820ATC144-4 @@ -368,7 +369,7 @@ static int cpwd_open(struct inode *inode, struct file *f) { struct cpwd *p = cpwd_device; - lock_kernel(); + mutex_lock(&cpwd_mutex); switch (iminor(inode)) { case WD0_MINOR: case WD1_MINOR: @@ -376,7 +377,7 @@ static int cpwd_open(struct inode *inode, struct file *f) break; default: - unlock_kernel(); + mutex_unlock(&cpwd_mutex); return -ENODEV; } @@ -386,13 +387,13 @@ static int cpwd_open(struct inode *inode, struct file *f) IRQF_SHARED, DRIVER_NAME, p)) { printk(KERN_ERR PFX "Cannot register IRQ %d\n", p->irq); - unlock_kernel(); + mutex_unlock(&cpwd_mutex); return -EBUSY; } p->initialized = true; } - unlock_kernel(); + mutex_unlock(&cpwd_mutex); return nonseekable_open(inode, f); } @@ -482,9 +483,9 @@ static long cpwd_compat_ioctl(struct file *file, unsigned int cmd, case WIOCSTART: case WIOCSTOP: case WIOCGSTAT: - lock_kernel(); + mutex_lock(&cpwd_mutex); rval = cpwd_ioctl(file, cmd, arg); - unlock_kernel(); + mutex_unlock(&cpwd_mutex); break; /* everything else is handled by the generic compat layer */ @@ -524,9 +525,10 @@ static const struct file_operations cpwd_fops = { .write = cpwd_write, .read = cpwd_read, .release = cpwd_release, + .llseek = no_llseek, }; -static int __devinit cpwd_probe(struct of_device *op, +static int __devinit cpwd_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *options; @@ -639,7 +641,7 @@ out_free: goto out; } -static int __devexit cpwd_remove(struct of_device *op) +static int __devexit cpwd_remove(struct platform_device *op) { struct cpwd *p = dev_get_drvdata(&op->dev); int i; diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c index 59359c9a5e0..726b7df61fd 100644 --- a/drivers/watchdog/ep93xx_wdt.c +++ b/drivers/watchdog/ep93xx_wdt.c @@ -188,6 +188,7 @@ static const struct file_operations ep93xx_wdt_fops = { .unlocked_ioctl = ep93xx_wdt_ioctl, .open = ep93xx_wdt_open, .release = ep93xx_wdt_release, + .llseek = no_llseek, }; static struct miscdevice ep93xx_wdt_miscdev = { diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index 1df284f9c2a..9c21d19043a 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c @@ -260,7 +260,7 @@ static struct miscdevice gef_wdt_miscdev = { }; -static int __devinit gef_wdt_probe(struct of_device *dev, +static int __devinit gef_wdt_probe(struct platform_device *dev, const struct of_device_id *match) { int timeout = 10; diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index fd312fc8940..3d77116e463 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -16,38 +16,55 @@ #include <linux/device.h> #include <linux/fs.h> #include <linux/init.h> -#include <linux/interrupt.h> #include <linux/io.h> -#include <linux/irq.h> -#include <linux/nmi.h> +#include <linux/bitops.h> #include <linux/kernel.h> #include <linux/miscdevice.h> -#include <linux/mm.h> #include <linux/module.h> -#include <linux/kdebug.h> #include <linux/moduleparam.h> -#include <linux/notifier.h> #include <linux/pci.h> #include <linux/pci_ids.h> -#include <linux/reboot.h> -#include <linux/sched.h> -#include <linux/timer.h> #include <linux/types.h> #include <linux/uaccess.h> #include <linux/watchdog.h> +#ifdef CONFIG_HPWDT_NMI_DECODING #include <linux/dmi.h> -#include <linux/efi.h> -#include <linux/string.h> -#include <linux/bootmem.h> -#include <asm/desc.h> +#include <linux/spinlock.h> +#include <linux/nmi.h> +#include <linux/kdebug.h> +#include <linux/notifier.h> #include <asm/cacheflush.h> +#endif /* CONFIG_HPWDT_NMI_DECODING */ + +#define HPWDT_VERSION "1.2.0" +#define SECS_TO_TICKS(secs) ((secs) * 1000 / 128) +#define TICKS_TO_SECS(ticks) ((ticks) * 128 / 1000) +#define HPWDT_MAX_TIMER TICKS_TO_SECS(65535) +#define DEFAULT_MARGIN 30 + +static unsigned int soft_margin = DEFAULT_MARGIN; /* in seconds */ +static unsigned int reload; /* the computed soft_margin */ +static int nowayout = WATCHDOG_NOWAYOUT; +static char expect_release; +static unsigned long hpwdt_is_open; + +static void __iomem *pci_mem_addr; /* the PCI-memory address */ +static unsigned long __iomem *hpwdt_timer_reg; +static unsigned long __iomem *hpwdt_timer_con; +static struct pci_device_id hpwdt_devices[] = { + { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) }, /* iLO2 */ + { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) }, /* iLO3 */ + {0}, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, hpwdt_devices); + +#ifdef CONFIG_HPWDT_NMI_DECODING #define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */ #define CRU_BIOS_SIGNATURE_VALUE 0x55524324 #define PCI_BIOS32_PARAGRAPH_LEN 16 #define PCI_ROM_BASE1 0x000F0000 #define ROM_SIZE 0x10000 -#define HPWDT_VERSION "1.1.1" struct bios32_service_dir { u32 signature; @@ -112,37 +129,17 @@ struct cmn_registers { u32 reflags; } __attribute__((packed)); -#define DEFAULT_MARGIN 30 -static unsigned int soft_margin = DEFAULT_MARGIN; /* in seconds */ -static unsigned int reload; /* the computed soft_margin */ -static int nowayout = WATCHDOG_NOWAYOUT; -static char expect_release; -static unsigned long hpwdt_is_open; +static unsigned int hpwdt_nmi_decoding; static unsigned int allow_kdump; -static unsigned int hpwdt_nmi_sourcing; static unsigned int priority; /* hpwdt at end of die_notify list */ - -static void __iomem *pci_mem_addr; /* the PCI-memory address */ -static unsigned long __iomem *hpwdt_timer_reg; -static unsigned long __iomem *hpwdt_timer_con; - static DEFINE_SPINLOCK(rom_lock); - static void *cru_rom_addr; - static struct cmn_registers cmn_regs; -static struct pci_device_id hpwdt_devices[] = { - { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) }, - { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) }, - {0}, /* terminate list */ -}; -MODULE_DEVICE_TABLE(pci, hpwdt_devices); - extern asmlinkage void asminline_call(struct cmn_registers *pi86Regs, unsigned long *pRomEntry); -#ifndef CONFIG_X86_64 +#ifdef CONFIG_X86_32 /* --32 Bit Bios------------------------------------------------------------ */ #define HPWDT_ARCH 32 @@ -331,8 +328,9 @@ static int __devinit detect_cru_service(void) iounmap(p); return rc; } - -#else +/* ------------------------------------------------------------------------- */ +#endif /* CONFIG_X86_32 */ +#ifdef CONFIG_X86_64 /* --64 Bit Bios------------------------------------------------------------ */ #define HPWDT_ARCH 64 @@ -410,17 +408,16 @@ static int __devinit detect_cru_service(void) /* if cru_rom_addr has been set then we found a CRU service */ return ((cru_rom_addr != NULL) ? 0 : -ENODEV); } - /* ------------------------------------------------------------------------- */ - -#endif +#endif /* CONFIG_X86_64 */ +#endif /* CONFIG_HPWDT_NMI_DECODING */ /* * Watchdog operations */ static void hpwdt_start(void) { - reload = (soft_margin * 1000) / 128; + reload = SECS_TO_TICKS(soft_margin); iowrite16(reload, hpwdt_timer_reg); iowrite16(0x85, hpwdt_timer_con); } @@ -441,8 +438,7 @@ static void hpwdt_ping(void) static int hpwdt_change_timer(int new_margin) { - /* Arbitrary, can't find the card's limits */ - if (new_margin < 5 || new_margin > 600) { + if (new_margin < 1 || new_margin > HPWDT_MAX_TIMER) { printk(KERN_WARNING "hpwdt: New value passed in is invalid: %d seconds.\n", new_margin); @@ -453,11 +449,17 @@ static int hpwdt_change_timer(int new_margin) printk(KERN_DEBUG "hpwdt: New timer passed in is %d seconds.\n", new_margin); - reload = (soft_margin * 1000) / 128; + reload = SECS_TO_TICKS(soft_margin); return 0; } +static int hpwdt_time_left(void) +{ + return TICKS_TO_SECS(ioread16(hpwdt_timer_reg)); +} + +#ifdef CONFIG_HPWDT_NMI_DECODING /* * NMI Handler */ @@ -468,26 +470,29 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, static int die_nmi_called; if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) - return NOTIFY_OK; - - if (hpwdt_nmi_sourcing) { - spin_lock_irqsave(&rom_lock, rom_pl); - if (!die_nmi_called) - asminline_call(&cmn_regs, cru_rom_addr); - die_nmi_called = 1; - spin_unlock_irqrestore(&rom_lock, rom_pl); - if (cmn_regs.u1.ral == 0) { - printk(KERN_WARNING "hpwdt: An NMI occurred, " - "but unable to determine source.\n"); - } else { - if (allow_kdump) - hpwdt_stop(); - panic("An NMI occurred, please see the Integrated " - "Management Log for details.\n"); - } + goto out; + + if (!hpwdt_nmi_decoding) + goto out; + + spin_lock_irqsave(&rom_lock, rom_pl); + if (!die_nmi_called) + asminline_call(&cmn_regs, cru_rom_addr); + die_nmi_called = 1; + spin_unlock_irqrestore(&rom_lock, rom_pl); + if (cmn_regs.u1.ral == 0) { + printk(KERN_WARNING "hpwdt: An NMI occurred, " + "but unable to determine source.\n"); + } else { + if (allow_kdump) + hpwdt_stop(); + panic("An NMI occurred, please see the Integrated " + "Management Log for details.\n"); } +out: return NOTIFY_OK; } +#endif /* CONFIG_HPWDT_NMI_DECODING */ /* * /dev/watchdog handling @@ -557,7 +562,7 @@ static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, - .identity = "HP iLO2 HW Watchdog Timer", + .identity = "HP iLO2+ HW Watchdog Timer", }; static long hpwdt_ioctl(struct file *file, unsigned int cmd, @@ -599,6 +604,10 @@ static long hpwdt_ioctl(struct file *file, unsigned int cmd, case WDIOC_GETTIMEOUT: ret = put_user(soft_margin, p); break; + + case WDIOC_GETTIMELEFT: + ret = put_user(hpwdt_time_left(), p); + break; } return ret; } @@ -621,80 +630,45 @@ static struct miscdevice hpwdt_miscdev = { .fops = &hpwdt_fops, }; +#ifdef CONFIG_HPWDT_NMI_DECODING static struct notifier_block die_notifier = { .notifier_call = hpwdt_pretimeout, .priority = 0, }; +#endif /* CONFIG_HPWDT_NMI_DECODING */ /* * Init & Exit */ +#ifdef CONFIG_HPWDT_NMI_DECODING #ifdef ARCH_HAS_NMI_WATCHDOG -static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev) +static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev) { /* * If nmi_watchdog is turned off then we can turn on - * our nmi sourcing capability. + * our nmi decoding capability. */ if (!nmi_watchdog_active()) - hpwdt_nmi_sourcing = 1; + hpwdt_nmi_decoding = 1; else - dev_warn(&dev->dev, "NMI sourcing is disabled. To enable this " + dev_warn(&dev->dev, "NMI decoding is disabled. To enable this " "functionality you must reboot with nmi_watchdog=0 " "and load the hpwdt driver with priority=1.\n"); } #else -static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev) +static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev) { - dev_warn(&dev->dev, "NMI sourcing is disabled. " + dev_warn(&dev->dev, "NMI decoding is disabled. " "Your kernel does not support a NMI Watchdog.\n"); } -#endif +#endif /* ARCH_HAS_NMI_WATCHDOG */ -static int __devinit hpwdt_init_one(struct pci_dev *dev, - const struct pci_device_id *ent) +static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) { int retval; /* - * Check if we can do NMI sourcing or not - */ - hpwdt_check_nmi_sourcing(dev); - - /* - * First let's find out if we are on an iLO2 server. We will - * not run on a legacy ASM box. - * So we only support the G5 ProLiant servers and higher. - */ - if (dev->subsystem_vendor != PCI_VENDOR_ID_HP) { - dev_warn(&dev->dev, - "This server does not have an iLO2 ASIC.\n"); - return -ENODEV; - } - - if (pci_enable_device(dev)) { - dev_warn(&dev->dev, - "Not possible to enable PCI Device: 0x%x:0x%x.\n", - ent->vendor, ent->device); - return -ENODEV; - } - - pci_mem_addr = pci_iomap(dev, 1, 0x80); - if (!pci_mem_addr) { - dev_warn(&dev->dev, - "Unable to detect the iLO2 server memory.\n"); - retval = -ENOMEM; - goto error_pci_iomap; - } - hpwdt_timer_reg = pci_mem_addr + 0x70; - hpwdt_timer_con = pci_mem_addr + 0x72; - - /* Make sure that we have a valid soft_margin */ - if (hpwdt_change_timer(soft_margin)) - hpwdt_change_timer(DEFAULT_MARGIN); - - /* * We need to map the ROM to get the CRU service. * For 32 bit Operating Systems we need to go through the 32 Bit * BIOS Service Directory @@ -705,7 +679,7 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev, dev_warn(&dev->dev, "Unable to detect the %d Bit CRU Service.\n", HPWDT_ARCH); - goto error_get_cru; + return retval; } /* @@ -728,9 +702,87 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev, dev_warn(&dev->dev, "Unable to register a die notifier (err=%d).\n", retval); - goto error_die_notifier; + if (cru_rom_addr) + iounmap(cru_rom_addr); } + dev_info(&dev->dev, + "HP Watchdog Timer Driver: NMI decoding initialized" + ", allow kernel dump: %s (default = 0/OFF)" + ", priority: %s (default = 0/LAST).\n", + (allow_kdump == 0) ? "OFF" : "ON", + (priority == 0) ? "LAST" : "FIRST"); + return 0; +} + +static void __devexit hpwdt_exit_nmi_decoding(void) +{ + unregister_die_notifier(&die_notifier); + if (cru_rom_addr) + iounmap(cru_rom_addr); +} +#else /* !CONFIG_HPWDT_NMI_DECODING */ +static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev) +{ +} + +static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) +{ + return 0; +} + +static void __devexit hpwdt_exit_nmi_decoding(void) +{ +} +#endif /* CONFIG_HPWDT_NMI_DECODING */ + +static int __devinit hpwdt_init_one(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + int retval; + + /* + * Check if we can do NMI decoding or not + */ + hpwdt_check_nmi_decoding(dev); + + /* + * First let's find out if we are on an iLO2+ server. We will + * not run on a legacy ASM box. + * So we only support the G5 ProLiant servers and higher. + */ + if (dev->subsystem_vendor != PCI_VENDOR_ID_HP) { + dev_warn(&dev->dev, + "This server does not have an iLO2+ ASIC.\n"); + return -ENODEV; + } + + if (pci_enable_device(dev)) { + dev_warn(&dev->dev, + "Not possible to enable PCI Device: 0x%x:0x%x.\n", + ent->vendor, ent->device); + return -ENODEV; + } + + pci_mem_addr = pci_iomap(dev, 1, 0x80); + if (!pci_mem_addr) { + dev_warn(&dev->dev, + "Unable to detect the iLO2+ server memory.\n"); + retval = -ENOMEM; + goto error_pci_iomap; + } + hpwdt_timer_reg = pci_mem_addr + 0x70; + hpwdt_timer_con = pci_mem_addr + 0x72; + + /* Make sure that we have a valid soft_margin */ + if (hpwdt_change_timer(soft_margin)) + hpwdt_change_timer(DEFAULT_MARGIN); + + /* Initialize NMI Decoding functionality */ + retval = hpwdt_init_nmi_decoding(dev); + if (retval != 0) + goto error_init_nmi_decoding; + retval = misc_register(&hpwdt_miscdev); if (retval < 0) { dev_warn(&dev->dev, @@ -739,23 +791,14 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev, goto error_misc_register; } - printk(KERN_INFO - "hp Watchdog Timer Driver: %s" - ", timer margin: %d seconds (nowayout=%d)" - ", allow kernel dump: %s (default = 0/OFF)" - ", priority: %s (default = 0/LAST).\n", - HPWDT_VERSION, soft_margin, nowayout, - (allow_kdump == 0) ? "OFF" : "ON", - (priority == 0) ? "LAST" : "FIRST"); - + dev_info(&dev->dev, "HP Watchdog Timer Driver: %s" + ", timer margin: %d seconds (nowayout=%d).\n", + HPWDT_VERSION, soft_margin, nowayout); return 0; error_misc_register: - unregister_die_notifier(&die_notifier); -error_die_notifier: - if (cru_rom_addr) - iounmap(cru_rom_addr); -error_get_cru: + hpwdt_exit_nmi_decoding(); +error_init_nmi_decoding: pci_iounmap(dev, pci_mem_addr); error_pci_iomap: pci_disable_device(dev); @@ -768,10 +811,7 @@ static void __devexit hpwdt_exit(struct pci_dev *dev) hpwdt_stop(); misc_deregister(&hpwdt_miscdev); - unregister_die_notifier(&die_notifier); - - if (cru_rom_addr) - iounmap(cru_rom_addr); + hpwdt_exit_nmi_decoding(); pci_iounmap(dev, pci_mem_addr); pci_disable_device(dev); } @@ -802,16 +842,18 @@ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); module_param(soft_margin, int, 0); MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds"); -module_param(allow_kdump, int, 0); -MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs"); - module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +#ifdef CONFIG_HPWDT_NMI_DECODING +module_param(allow_kdump, int, 0); +MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs"); + module_param(priority, int, 0); MODULE_PARM_DESC(priority, "The hpwdt driver handles NMIs first or last" " (default = 0/Last)\n"); +#endif /* !CONFIG_HPWDT_NMI_DECODING */ module_init(hpwdt_init); module_exit(hpwdt_cleanup); diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 4cda64dd309..8fa213cdb49 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c @@ -185,7 +185,7 @@ static struct miscdevice mpc8xxx_wdt_miscdev = { .fops = &mpc8xxx_wdt_fops, }; -static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev, +static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev, const struct of_device_id *match) { int ret; @@ -238,7 +238,7 @@ err_unmap: return ret; } -static int __devexit mpc8xxx_wdt_remove(struct of_device *ofdev) +static int __devexit mpc8xxx_wdt_remove(struct platform_device *ofdev) { mpc8xxx_wdt_pr_warn("watchdog removed"); del_timer_sync(&wdt_timer); diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c index 2a410170eca..909923800a0 100644 --- a/drivers/watchdog/octeon-wdt-main.c +++ b/drivers/watchdog/octeon-wdt-main.c @@ -64,6 +64,7 @@ #include <linux/cpu.h> #include <linux/smp.h> #include <linux/fs.h> +#include <linux/irq.h> #include <asm/mipsregs.h> #include <asm/uasm.h> diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 76b58abf445..81e3d610089 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -258,6 +258,7 @@ static const struct file_operations omap_wdt_fops = { .unlocked_ioctl = omap_wdt_ioctl, .open = omap_wdt_open, .release = omap_wdt_release, + .llseek = no_llseek, }; static int __devinit omap_wdt_probe(struct platform_device *pdev) diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index 4082b4ace1f..3faee1ae64b 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c @@ -172,7 +172,7 @@ static struct miscdevice riowd_miscdev = { .fops = &riowd_fops }; -static int __devinit riowd_probe(struct of_device *op, +static int __devinit riowd_probe(struct platform_device *op, const struct of_device_id *match) { struct riowd *p; @@ -219,7 +219,7 @@ out: return err; } -static int __devexit riowd_remove(struct of_device *op) +static int __devexit riowd_remove(struct platform_device *op) { struct riowd *p = dev_get_drvdata(&op->dev); diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c index 88c83aa5730..f31493e65b3 100644 --- a/drivers/watchdog/sb_wdog.c +++ b/drivers/watchdog/sb_wdog.c @@ -305,7 +305,7 @@ static int __init sbwdog_init(void) if (ret) { printk(KERN_ERR "%s: failed to request irq 1 - %d\n", ident.identity, ret); - return ret; + goto out; } ret = misc_register(&sbwdog_miscdev); @@ -313,14 +313,20 @@ static int __init sbwdog_init(void) printk(KERN_INFO "%s: timeout is %ld.%ld secs\n", ident.identity, timeout / 1000000, (timeout / 100000) % 10); - } else - free_irq(1, (void *)user_dog); + return 0; + } + free_irq(1, (void *)user_dog); +out: + unregister_reboot_notifier(&sbwdog_notifier); + return ret; } static void __exit sbwdog_exit(void) { misc_deregister(&sbwdog_miscdev); + free_irq(1, (void *)user_dog); + unregister_reboot_notifier(&sbwdog_notifier); } module_init(sbwdog_init); diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c index 458c499c122..18cdeb4c425 100644 --- a/drivers/watchdog/ts72xx_wdt.c +++ b/drivers/watchdog/ts72xx_wdt.c @@ -449,6 +449,9 @@ static __devinit int ts72xx_wdt_probe(struct platform_device *pdev) wdt->pdev = pdev; mutex_init(&wdt->lock); + /* make sure that the watchdog is disabled */ + ts72xx_wdt_stop(wdt); + error = misc_register(&ts72xx_wdt_miscdev); if (error) { dev_err(&pdev->dev, "failed to register miscdev\n"); |