diff options
Diffstat (limited to 'drivers')
76 files changed, 360 insertions, 429 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 6cad0b33d7ad..8188963a405b 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -58,6 +58,15 @@ config WATCHDOG_HANDLE_BOOT_ENABLED the watchdog on its own. Thus if your userspace does not start fast enough your device will reboot. +config WATCHDOG_OPEN_TIMEOUT + int "Timeout value for opening watchdog device" + default 0 + help + The maximum time, in seconds, for which the watchdog framework takes + care of pinging a hardware watchdog. A value of 0 means infinite. The + value set here can be overridden by the commandline parameter + "watchdog.open_timeout". + config WATCHDOG_SYSFS bool "Read different watchdog information through sysfs" help @@ -717,6 +726,7 @@ config IMX2_WDT config IMX_SC_WDT tristate "IMX SC Watchdog" depends on HAVE_ARM_SMCCC + depends on IMX_SCU select WATCHDOG_CORE help This is the driver for the system controller watchdog diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c index 957d1255d4ca..848db958411e 100644 --- a/drivers/watchdog/acquirewdt.c +++ b/drivers/watchdog/acquirewdt.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Acquire Single Board Computer Watchdog Timer driver * @@ -6,11 +7,6 @@ * (c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>, * All Rights Reserved. * - * 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 Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide * warranty for any of this software. This material is provided * "AS-IS" and at no charge. diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c index 2766af292a71..0d02bb275b3d 100644 --- a/drivers/watchdog/advantechwdt.c +++ b/drivers/watchdog/advantechwdt.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Advantech Single Board Computer WDT driver * @@ -9,11 +10,6 @@ * (c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>, * All Rights Reserved. * - * 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 Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide * warranty for any of this software. This material is provided * "AS-IS" and at no charge. diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index f0148637e5dd..cc71861e033a 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -309,13 +309,7 @@ static int aspeed_wdt_probe(struct platform_device *pdev) if (status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY) wdt->wdd.bootstatus = WDIOF_CARDRESET; - ret = devm_watchdog_register_device(dev, &wdt->wdd); - if (ret) { - dev_err(dev, "failed to register\n"); - return ret; - } - - return 0; + return devm_watchdog_register_device(dev, &wdt->wdd); } static struct platform_driver aspeed_watchdog_driver = { diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c index 560c1c54c177..dec6ca019bea 100644 --- a/drivers/watchdog/bcm2835_wdt.c +++ b/drivers/watchdog/bcm2835_wdt.c @@ -202,10 +202,8 @@ static int bcm2835_wdt_probe(struct platform_device *pdev) watchdog_stop_on_reboot(&bcm2835_wdt_wdd); err = devm_watchdog_register_device(dev, &bcm2835_wdt_wdd); - if (err) { - dev_err(dev, "Failed to register watchdog device"); + if (err) return err; - } if (pm_power_off == NULL) { pm_power_off = bcm2835_power_off; @@ -240,6 +238,7 @@ module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +MODULE_ALIAS("platform:bcm2835-wdt"); MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>"); MODULE_DESCRIPTION("Driver for Broadcom BCM2835 watchdog timer"); MODULE_LICENSE("GPL"); diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c index d3d88f6703d7..979caa18d3c8 100644 --- a/drivers/watchdog/bcm7038_wdt.c +++ b/drivers/watchdog/bcm7038_wdt.c @@ -159,10 +159,8 @@ static int bcm7038_wdt_probe(struct platform_device *pdev) watchdog_stop_on_reboot(&wdt->wdd); watchdog_stop_on_unregister(&wdt->wdd); err = devm_watchdog_register_device(dev, &wdt->wdd); - if (err) { - dev_err(dev, "Failed to register watchdog device\n"); + if (err) return err; - } dev_info(dev, "Registered BCM7038 Watchdog\n"); diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c index 921291025680..eb850a8d19df 100644 --- a/drivers/watchdog/bcm_kona_wdt.c +++ b/drivers/watchdog/bcm_kona_wdt.c @@ -301,10 +301,8 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev) watchdog_stop_on_reboot(&bcm_kona_wdt_wdd); watchdog_stop_on_unregister(&bcm_kona_wdt_wdd); ret = devm_watchdog_register_device(dev, &bcm_kona_wdt_wdd); - if (ret) { - dev_err(dev, "Failed to register watchdog device"); + if (ret) return ret; - } bcm_kona_wdt_debug_init(pdev); dev_dbg(dev, "Broadcom Kona Watchdog Timer"); diff --git a/drivers/watchdog/cadence_wdt.c b/drivers/watchdog/cadence_wdt.c index a22f2d431a35..f8d4e91d0383 100644 --- a/drivers/watchdog/cadence_wdt.c +++ b/drivers/watchdog/cadence_wdt.c @@ -363,10 +363,8 @@ static int cdns_wdt_probe(struct platform_device *pdev) watchdog_stop_on_reboot(cdns_wdt_device); watchdog_stop_on_unregister(cdns_wdt_device); ret = devm_watchdog_register_device(dev, cdns_wdt_device); - if (ret) { - dev_err(dev, "Failed to register wdt device\n"); + if (ret) return ret; - } platform_set_drvdata(pdev, wdt); dev_info(dev, "Xilinx Watchdog Timer at %p with timeout %ds%s\n", diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c index a2feef1ff307..d708c091bf1b 100644 --- a/drivers/watchdog/da9052_wdt.c +++ b/drivers/watchdog/da9052_wdt.c @@ -176,14 +176,7 @@ static int da9052_wdt_probe(struct platform_device *pdev) return ret; } - ret = devm_watchdog_register_device(dev, &driver_data->wdt); - if (ret != 0) { - dev_err(da9052->dev, "watchdog_register_device() failed: %d\n", - ret); - return ret; - } - - return ret; + return devm_watchdog_register_device(dev, &driver_data->wdt); } static struct platform_driver da9052_wdt_driver = { diff --git a/drivers/watchdog/da9062_wdt.c b/drivers/watchdog/da9062_wdt.c index aac749cfaccb..e149e66a6ea9 100644 --- a/drivers/watchdog/da9062_wdt.c +++ b/drivers/watchdog/da9062_wdt.c @@ -214,11 +214,8 @@ static int da9062_wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(&wdt->wdtdev, wdt); ret = devm_watchdog_register_device(dev, &wdt->wdtdev); - if (ret < 0) { - dev_err(wdt->hw->dev, - "watchdog registration failed (%d)\n", ret); + if (ret < 0) return ret; - } return da9062_wdt_ping(&wdt->wdtdev); } diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c index 7b2ee35b5ffd..2b3f3cd382ef 100644 --- a/drivers/watchdog/davinci_wdt.c +++ b/drivers/watchdog/davinci_wdt.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/char/watchdog/davinci_wdt.c * @@ -5,10 +6,7 @@ * * Copyright (C) 2006-2013 Texas Instruments. * - * 2007 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. + * 2007 (c) MontaVista Software, Inc. */ #include <linux/module.h> @@ -247,13 +245,7 @@ static int davinci_wdt_probe(struct platform_device *pdev) if (IS_ERR(davinci_wdt->base)) return PTR_ERR(davinci_wdt->base); - ret = devm_watchdog_register_device(dev, wdd); - if (ret) { - dev_err(dev, "cannot register watchdog device\n"); - return ret; - } - - return 0; + return devm_watchdog_register_device(dev, wdd); } static const struct of_device_id davinci_wdt_of_match[] = { diff --git a/drivers/watchdog/digicolor_wdt.c b/drivers/watchdog/digicolor_wdt.c index 8af6e9a67d0d..073d37867f47 100644 --- a/drivers/watchdog/digicolor_wdt.c +++ b/drivers/watchdog/digicolor_wdt.c @@ -118,7 +118,6 @@ static int dc_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct dc_wdt *wdt; - int ret; wdt = devm_kzalloc(dev, sizeof(struct dc_wdt), GFP_KERNEL); if (!wdt) @@ -141,13 +140,7 @@ static int dc_wdt_probe(struct platform_device *pdev) watchdog_set_restart_priority(&dc_wdt_wdd, 128); watchdog_init_timeout(&dc_wdt_wdd, timeout, dev); watchdog_stop_on_reboot(&dc_wdt_wdd); - ret = devm_watchdog_register_device(dev, &dc_wdt_wdd); - if (ret) { - dev_err(dev, "Failed to register watchdog device"); - return ret; - } - - return 0; + return devm_watchdog_register_device(dev, &dc_wdt_wdd); } static const struct of_device_id dc_wdt_of_match[] = { diff --git a/drivers/watchdog/ebc-c384_wdt.c b/drivers/watchdog/ebc-c384_wdt.c index c176f59fea28..8ef4b0df3855 100644 --- a/drivers/watchdog/ebc-c384_wdt.c +++ b/drivers/watchdog/ebc-c384_wdt.c @@ -2,15 +2,6 @@ /* * Watchdog timer driver for the WinSystems EBC-C384 * Copyright (C) 2016 William Breathitt Gray - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. */ #include <linux/device.h> #include <linux/dmi.h> diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c index 89129e6fa9b6..3a83a48abcae 100644 --- a/drivers/watchdog/eurotechwdt.c +++ b/drivers/watchdog/eurotechwdt.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Eurotech CPU-1220/1410/1420 on board WDT driver * @@ -11,11 +12,6 @@ * (c) Copyright 1996-1997 Alan Cox <alan@lxorguk.ukuu.org.uk>, * All Rights Reserved. * - * 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 Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide * warranty for any of this software. This material is provided * "AS-IS" and at no charge. diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c index d9626ef9b9ae..21dcc7765688 100644 --- a/drivers/watchdog/ftwdt010_wdt.c +++ b/drivers/watchdog/ftwdt010_wdt.c @@ -165,10 +165,8 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev) } ret = devm_watchdog_register_device(dev, &gwdt->wdd); - if (ret) { - dev_err(dev, "failed to register watchdog\n"); + if (ret) return ret; - } /* Set up platform driver data */ platform_set_drvdata(pdev, gwdt); diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c index 777de10f2a78..0923201ce874 100644 --- a/drivers/watchdog/gpio_wdt.c +++ b/drivers/watchdog/gpio_wdt.c @@ -13,6 +13,12 @@ #include <linux/platform_device.h> #include <linux/watchdog.h> +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, + "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + #define SOFT_TIMEOUT_MIN 1 #define SOFT_TIMEOUT_DEF 60 @@ -151,6 +157,7 @@ static int gpio_wdt_probe(struct platform_device *pdev) priv->wdd.timeout = SOFT_TIMEOUT_DEF; watchdog_init_timeout(&priv->wdd, 0, dev); + watchdog_set_nowayout(&priv->wdd, nowayout); watchdog_stop_on_reboot(&priv->wdd); diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 8a90f159ffb1..7d34bcf1c45b 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -22,10 +22,11 @@ #include <linux/watchdog.h> #include <asm/nmi.h> -#define HPWDT_VERSION "2.0.2" +#define HPWDT_VERSION "2.0.3" #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 HPWDT_MAX_TICKS 65535 +#define HPWDT_MAX_TIMER TICKS_TO_SECS(HPWDT_MAX_TICKS) #define DEFAULT_MARGIN 30 #define PRETIMEOUT_SEC 9 @@ -33,6 +34,7 @@ static bool ilo5; static unsigned int soft_margin = DEFAULT_MARGIN; /* in seconds */ static bool nowayout = WATCHDOG_NOWAYOUT; static bool pretimeout = IS_ENABLED(CONFIG_HPWDT_NMI_DECODING); +static int kdumptimeout = -1; static void __iomem *pci_mem_addr; /* the PCI-memory address */ static unsigned long __iomem *hpwdt_nmistat; @@ -52,15 +54,21 @@ static const struct pci_device_id hpwdt_blacklist[] = { {0}, /* terminate list */ }; +static struct watchdog_device hpwdt_dev; /* * Watchdog operations */ +static int hpwdt_hw_is_running(void) +{ + return ioread8(hpwdt_timer_con) & 0x01; +} + static int hpwdt_start(struct watchdog_device *wdd) { int control = 0x81 | (pretimeout ? 0x4 : 0); - int reload = SECS_TO_TICKS(wdd->timeout); + int reload = SECS_TO_TICKS(min(wdd->timeout, wdd->max_hw_heartbeat_ms/1000)); - dev_dbg(wdd->parent, "start watchdog 0x%08x:0x%02x\n", reload, control); + dev_dbg(wdd->parent, "start watchdog 0x%08x:0x%08x:0x%02x\n", wdd->timeout, reload, control); iowrite16(reload, hpwdt_timer_reg); iowrite8(control, hpwdt_timer_con); @@ -85,12 +93,18 @@ static int hpwdt_stop_core(struct watchdog_device *wdd) return 0; } +static void hpwdt_ping_ticks(int val) +{ + val = min(val, HPWDT_MAX_TICKS); + iowrite16(val, hpwdt_timer_reg); +} + static int hpwdt_ping(struct watchdog_device *wdd) { - int reload = SECS_TO_TICKS(wdd->timeout); + int reload = SECS_TO_TICKS(min(wdd->timeout, wdd->max_hw_heartbeat_ms/1000)); - dev_dbg(wdd->parent, "ping watchdog 0x%08x\n", reload); - iowrite16(reload, hpwdt_timer_reg); + dev_dbg(wdd->parent, "ping watchdog 0x%08x:0x%08x\n", wdd->timeout, reload); + hpwdt_ping_ticks(reload); return 0; } @@ -166,7 +180,14 @@ static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs) if (ilo5 && !pretimeout && !mynmi) return NMI_DONE; - hpwdt_stop(); + if (kdumptimeout < 0) + hpwdt_stop(); + else if (kdumptimeout == 0) + ; + else { + unsigned int val = max((unsigned int)kdumptimeout, hpwdt_dev.timeout); + hpwdt_ping_ticks(SECS_TO_TICKS(val)); + } hex_byte_pack(panic_msg, mynmi); nmi_panic(regs, panic_msg); @@ -204,9 +225,9 @@ static struct watchdog_device hpwdt_dev = { .info = &ident, .ops = &hpwdt_ops, .min_timeout = 1, - .max_timeout = HPWDT_MAX_TIMER, .timeout = DEFAULT_MARGIN, .pretimeout = PRETIMEOUT_SEC, + .max_hw_heartbeat_ms = HPWDT_MAX_TIMER * 1000, }; @@ -298,14 +319,18 @@ static int hpwdt_init_one(struct pci_dev *dev, hpwdt_timer_reg = pci_mem_addr + 0x70; hpwdt_timer_con = pci_mem_addr + 0x72; - /* Make sure that timer is disabled until /dev/watchdog is opened */ - hpwdt_stop(); + /* Have the core update running timer until user space is ready */ + if (hpwdt_hw_is_running()) { + dev_info(&dev->dev, "timer is running\n"); + set_bit(WDOG_HW_RUNNING, &hpwdt_dev.status); + } /* Initialize NMI Decoding functionality */ retval = hpwdt_init_nmi_decoding(dev); if (retval != 0) goto error_init_nmi_decoding; + watchdog_stop_on_unregister(&hpwdt_dev); watchdog_set_nowayout(&hpwdt_dev, nowayout); watchdog_init_timeout(&hpwdt_dev, soft_margin, NULL); @@ -314,13 +339,12 @@ static int hpwdt_init_one(struct pci_dev *dev, pretimeout = 0; } hpwdt_dev.pretimeout = pretimeout ? PRETIMEOUT_SEC : 0; + kdumptimeout = min(kdumptimeout, HPWDT_MAX_TIMER); hpwdt_dev.parent = &dev->dev; retval = watchdog_register_device(&hpwdt_dev); - if (retval & |