diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-24 02:01:49 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-24 02:01:49 +0300 |
commit | 6755f4563144e38f375f43dbb01926fd4ce08620 (patch) | |
tree | 41259ef1f87ff66793a0fd7d132bc716dc654626 /drivers | |
parent | 614cb5894306cfa2c7d9b6168182876ff5948735 (diff) | |
parent | 0b9491b621196a5d7f163dde81d98e0687bdba97 (diff) | |
download | linux-6755f4563144e38f375f43dbb01926fd4ce08620.tar.xz |
Merge tag 'linux-watchdog-5.11-rc1' of git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck:
- Removal of the pnx83xx driver
- Add a binding for A100's watchdog controller
- Add Rockchip compatibles to snps,dw-wdt.yaml
- hpwdt: Disable NMI in Crash Kernel
- Fix potential dereferencing of null pointer in watchdog_core
- Several other small fixes and improvements
* tag 'linux-watchdog-5.11-rc1' of git://www.linux-watchdog.org/linux-watchdog: (23 commits)
watchdog: convert comma to semicolon
watchdog: iTCO_wdt: use dev_*() instead of pr_*() for logging
dt-binding: watchdog: add Rockchip compatibles to snps,dw-wdt.yaml
watchdog: coh901327: add COMMON_CLK dependency
dt-bindings: watchdog: sun4i: Add A100 compatible
watchdog: qcom: Avoid context switch in restart handler
watchdog: iTCO_wdt: use module_platform_device() macro
watchdog: Fix potential dereferencing of null pointer
watchdog: wdat_wdt: Fix missing kerneldoc reported by W=1
watchdog/hpwdt: Reflect changes
watchdog/hpwdt: Disable NMI in Crash Kernel
wdt: sp805: add watchdog_stop on reboot
watchdog: sbc_fitpc2_wdt: add __user annotations
watchdog: geodewdt: remove unneeded break
watchdog: rti-wdt: fix reference leak in rti_wdt_probe
watchdog: qcom_wdt: set WDOG_HW_RUNNING bit when appropriate
watchdog: remove pnx83xx driver
watchdog: stm32_iwdg: don't print an error on probe deferral
watchdog: sprd: change to use usleep_range() instead of busy loop
watchdog: sprd: check busy bit before new loading rather than after that
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/watchdog/Kconfig | 14 | ||||
-rw-r--r-- | drivers/watchdog/Makefile | 1 | ||||
-rw-r--r-- | drivers/watchdog/geodewdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/hpwdt.c | 8 | ||||
-rw-r--r-- | drivers/watchdog/iTCO_wdt.c | 34 | ||||
-rw-r--r-- | drivers/watchdog/mpc8xxx_wdt.c | 4 | ||||
-rw-r--r-- | drivers/watchdog/pnx833x_wdt.c | 277 | ||||
-rw-r--r-- | drivers/watchdog/qcom-wdt.c | 20 | ||||
-rw-r--r-- | drivers/watchdog/rti_wdt.c | 4 | ||||
-rw-r--r-- | drivers/watchdog/sbc_fitpc2_wdt.c | 12 | ||||
-rw-r--r-- | drivers/watchdog/sp805_wdt.c | 1 | ||||
-rw-r--r-- | drivers/watchdog/sprd_wdt.c | 43 | ||||
-rw-r--r-- | drivers/watchdog/stm32_iwdg.c | 13 | ||||
-rw-r--r-- | drivers/watchdog/watchdog_core.c | 22 | ||||
-rw-r--r-- | drivers/watchdog/wdat_wdt.c | 6 |
15 files changed, 92 insertions, 369 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index f22e37337030..7ff941e71b79 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -386,6 +386,7 @@ config ARM_SBSA_WATCHDOG config ARMADA_37XX_WATCHDOG tristate "Armada 37xx watchdog" depends on ARCH_MVEBU || COMPILE_TEST + depends on HAS_IOMEM select MFD_SYSCON select WATCHDOG_CORE help @@ -631,7 +632,7 @@ config SUNXI_WATCHDOG config COH901327_WATCHDOG bool "ST-Ericsson COH 901 327 watchdog" - depends on ARCH_U300 || (ARM && COMPILE_TEST) + depends on ARCH_U300 || (ARM && COMMON_CLK && COMPILE_TEST) default y if MACH_U300 select WATCHDOG_CORE help @@ -789,6 +790,7 @@ config MOXART_WDT config SIRFSOC_WATCHDOG tristate "SiRFSOC watchdog" + depends on HAS_IOMEM depends on ARCH_SIRF || COMPILE_TEST select WATCHDOG_CORE default y @@ -1696,16 +1698,6 @@ config WDT_MTX1 Hardware driver for the MTX-1 boards. This is a watchdog timer that will reboot the machine after a 100 seconds timer expired. -config PNX833X_WDT - tristate "PNX833x Hardware Watchdog" - depends on SOC_PNX8335 - depends on BROKEN - help - Hardware driver for the PNX833x's watchdog. This is a - watchdog timer that will reboot the machine after a programmable - timer has expired and no process has written to /dev/watchdog during - that time. - config SIBYTE_WDOG tristate "Sibyte SoC hardware watchdog" depends on CPU_SB1 || (MIPS && COMPILE_TEST) diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 071a2e50be98..5c74ee19d441 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -161,7 +161,6 @@ obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o obj-$(CONFIG_INDYDOG) += indydog.o obj-$(CONFIG_JZ4740_WDT) += jz4740_wdt.o obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o -obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o obj-$(CONFIG_AR7_WDT) += ar7_wdt.o obj-$(CONFIG_TXX9_WDT) += txx9wdt.o diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c index 83418924e30a..0b699c783d57 100644 --- a/drivers/watchdog/geodewdt.c +++ b/drivers/watchdog/geodewdt.c @@ -150,8 +150,6 @@ static long geodewdt_ioctl(struct file *file, unsigned int cmd, case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; - break; - case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 7d34bcf1c45b..cbd1498ff015 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -21,8 +21,9 @@ #include <linux/types.h> #include <linux/watchdog.h> #include <asm/nmi.h> +#include <linux/crash_dump.h> -#define HPWDT_VERSION "2.0.3" +#define HPWDT_VERSION "2.0.4" #define SECS_TO_TICKS(secs) ((secs) * 1000 / 128) #define TICKS_TO_SECS(ticks) ((ticks) * 128 / 1000) #define HPWDT_MAX_TICKS 65535 @@ -334,6 +335,11 @@ static int hpwdt_init_one(struct pci_dev *dev, watchdog_set_nowayout(&hpwdt_dev, nowayout); watchdog_init_timeout(&hpwdt_dev, soft_margin, NULL); + if (is_kdump_kernel()) { + pretimeout = 0; + kdumptimeout = 0; + } + if (pretimeout && hpwdt_dev.timeout <= PRETIMEOUT_SEC) { dev_warn(&dev->dev, "timeout <= pretimeout. Setting pretimeout to zero\n"); pretimeout = 0; diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index a370a185a41c..bf31d7b67a69 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -40,8 +40,6 @@ * Includes, defines, variables, module parameters, ... */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - /* Module and version information */ #define DRV_NAME "iTCO_wdt" #define DRV_VERSION "1.11" @@ -279,7 +277,7 @@ static int iTCO_wdt_start(struct watchdog_device *wd_dev) /* disable chipset's NO_REBOOT bit */ if (p->update_no_reboot_bit(p->no_reboot_priv, false)) { spin_unlock(&p->io_lock); - pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n"); + dev_err(wd_dev->parent, "failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n"); return -EIO; } @@ -510,7 +508,7 @@ static int iTCO_wdt_probe(struct platform_device *pdev) /* Check chipset's NO_REBOOT bit */ if (p->update_no_reboot_bit(p->no_reboot_priv, false) && iTCO_vendor_check_noreboot_on()) { - pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n"); + dev_info(dev, "unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n"); return -ENODEV; /* Cannot reset NO_REBOOT bit */ } @@ -530,12 +528,12 @@ static int iTCO_wdt_probe(struct platform_device *pdev) if (!devm_request_region(dev, p->tco_res->start, resource_size(p->tco_res), pdev->name)) { - pr_err("I/O address 0x%04llx already in use, device disabled\n", + dev_err(dev, "I/O address 0x%04llx already in use, device disabled\n", (u64)TCOBASE(p)); return -EBUSY; } - pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04llx)\n", + dev_info(dev, "Found a %s TCO device (Version=%d, TCOBASE=0x%04llx)\n", pdata->name, pdata->version, (u64)TCOBASE(p)); /* Clear out the (probably old) status */ @@ -558,7 +556,7 @@ static int iTCO_wdt_probe(struct platform_device *pdev) break; } - p->wddev.info = &ident, + p->wddev.info = &ident, p->wddev.ops = &iTCO_wdt_ops, p->wddev.bootstatus = 0; p->wddev.timeout = WATCHDOG_TIMEOUT; @@ -575,7 +573,7 @@ static int iTCO_wdt_probe(struct platform_device *pdev) if not reset to the default */ if (iTCO_wdt_set_timeout(&p->wddev, heartbeat)) { iTCO_wdt_set_timeout(&p->wddev, WATCHDOG_TIMEOUT); - pr_info("timeout value out of range, using %d\n", + dev_info(dev, "timeout value out of range, using %d\n", WATCHDOG_TIMEOUT); } @@ -583,11 +581,11 @@ static int iTCO_wdt_probe(struct platform_device *pdev) watchdog_stop_on_unregister(&p->wddev); ret = devm_watchdog_register_device(dev, &p->wddev); if (ret != 0) { - pr_err("cannot register watchdog device (err=%d)\n", ret); + dev_err(dev, "cannot register watchdog device (err=%d)\n", ret); return ret; } - pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n", + dev_info(dev, "initialized. heartbeat=%d sec (nowayout=%d)\n", heartbeat, nowayout); return 0; @@ -651,21 +649,7 @@ static struct platform_driver iTCO_wdt_driver = { }, }; -static int __init iTCO_wdt_init_module(void) -{ - pr_info("Intel TCO WatchDog Timer Driver v%s\n", DRV_VERSION); - - return platform_driver_register(&iTCO_wdt_driver); -} - -static void __exit iTCO_wdt_cleanup_module(void) -{ - platform_driver_unregister(&iTCO_wdt_driver); - pr_info("Watchdog Module Unloaded\n"); -} - -module_init(iTCO_wdt_init_module); -module_exit(iTCO_wdt_cleanup_module); +module_platform_driver(iTCO_wdt_driver); MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>"); MODULE_DESCRIPTION("Intel TCO WatchDog Timer Driver"); diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 3fc457bc16db..2f7ded32e878 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c @@ -175,8 +175,8 @@ static int mpc8xxx_wdt_probe(struct platform_device *ofdev) spin_lock_init(&ddata->lock); - ddata->wdd.info = &mpc8xxx_wdt_info, - ddata->wdd.ops = &mpc8xxx_wdt_ops, + ddata->wdd.info = &mpc8xxx_wdt_info; + ddata->wdd.ops = &mpc8xxx_wdt_ops; ddata->wdd.timeout = WATCHDOG_TIMEOUT; watchdog_init_timeout(&ddata->wdd, timeout, dev); diff --git a/drivers/watchdog/pnx833x_wdt.c b/drivers/watchdog/pnx833x_wdt.c deleted file mode 100644 index 4097d076aab8..000000000000 --- a/drivers/watchdog/pnx833x_wdt.c +++ /dev/null @@ -1,277 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * PNX833x Hardware Watchdog Driver - * Copyright 2008 NXP Semiconductors - * Daniel Laird <daniel.j.laird@nxp.com> - * Andre McCurdy <andre.mccurdy@nxp.com> - * - * Heavily based upon - IndyDog 0.3 - * A Hardware Watchdog Device for SGI IP22 - * - * (c) Copyright 2002 Guido Guenther <agx@sigxcpu.org>, All Rights Reserved. - * - * based on softdog.c by Alan Cox <alan@redhat.com> - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/mm.h> -#include <linux/miscdevice.h> -#include <linux/watchdog.h> -#include <linux/notifier.h> -#include <linux/reboot.h> -#include <linux/init.h> -#include <asm/mach-pnx833x/pnx833x.h> - -#define WATCHDOG_TIMEOUT 30 /* 30 sec Maximum timeout */ -#define WATCHDOG_COUNT_FREQUENCY 68000000U /* Watchdog counts at 68MHZ. */ -#define PNX_WATCHDOG_TIMEOUT (WATCHDOG_TIMEOUT * WATCHDOG_COUNT_FREQUENCY) -#define PNX_TIMEOUT_VALUE 2040000000U - -/** CONFIG block */ -#define PNX833X_CONFIG (0x07000U) -#define PNX833X_CONFIG_CPU_WATCHDOG (0x54) -#define PNX833X_CONFIG_CPU_WATCHDOG_COMPARE (0x58) -#define PNX833X_CONFIG_CPU_COUNTERS_CONTROL (0x1c) - -/** RESET block */ -#define PNX833X_RESET (0x08000U) -#define PNX833X_RESET_CONFIG (0x08) - -static int pnx833x_wdt_alive; - -/* Set default timeout in MHZ.*/ -static int pnx833x_wdt_timeout = PNX_WATCHDOG_TIMEOUT; -module_param(pnx833x_wdt_timeout, int, 0); -MODULE_PARM_DESC(timeout, "Watchdog timeout in Mhz. (68Mhz clock), default=" - __MODULE_STRING(PNX_TIMEOUT_VALUE) "(30 seconds)."); - -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 START_DEFAULT 1 -static int start_enabled = START_DEFAULT; -module_param(start_enabled, int, 0); -MODULE_PARM_DESC(start_enabled, "Watchdog is started on module insertion " - "(default=" __MODULE_STRING(START_DEFAULT) ")"); - -static void pnx833x_wdt_start(void) -{ - /* Enable watchdog causing reset. */ - PNX833X_REG(PNX833X_RESET + PNX833X_RESET_CONFIG) |= 0x1; - /* Set timeout.*/ - PNX833X_REG(PNX833X_CONFIG + - PNX833X_CONFIG_CPU_WATCHDOG_COMPARE) = pnx833x_wdt_timeout; - /* Enable watchdog. */ - PNX833X_REG(PNX833X_CONFIG + - PNX833X_CONFIG_CPU_COUNTERS_CONTROL) |= 0x1; - - pr_info("Started watchdog timer\n"); -} - -static void pnx833x_wdt_stop(void) -{ - /* Disable watchdog causing reset. */ - PNX833X_REG(PNX833X_RESET + PNX833X_CONFIG) &= 0xFFFFFFFE; - /* Disable watchdog.*/ - PNX833X_REG(PNX833X_CONFIG + - PNX833X_CONFIG_CPU_COUNTERS_CONTROL) &= 0xFFFFFFFE; - - pr_info("Stopped watchdog timer\n"); -} - -static void pnx833x_wdt_ping(void) -{ - PNX833X_REG(PNX833X_CONFIG + - PNX833X_CONFIG_CPU_WATCHDOG_COMPARE) = pnx833x_wdt_timeout; -} - -/* - * Allow only one person to hold it open - */ -static int pnx833x_wdt_open(struct inode *inode, struct file *file) -{ - if (test_and_set_bit(0, &pnx833x_wdt_alive)) - return -EBUSY; - - if (nowayout) - __module_get(THIS_MODULE); - - /* Activate timer */ - if (!start_enabled) - pnx833x_wdt_start(); - - pnx833x_wdt_ping(); - - pr_info("Started watchdog timer\n"); - - return stream_open(inode, file); -} - -static int pnx833x_wdt_release(struct inode *inode, struct file *file) -{ - /* Shut off the timer. - * Lock it in if it's a module and we defined ...NOWAYOUT */ - if (!nowayout) - pnx833x_wdt_stop(); /* Turn the WDT off */ - - clear_bit(0, &pnx833x_wdt_alive); - return 0; -} - -static ssize_t pnx833x_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) -{ - /* Refresh the timer. */ - if (len) - pnx833x_wdt_ping(); - - return len; -} - -static long pnx833x_wdt_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - int options, new_timeout = 0; - uint32_t timeout, timeout_left = 0; - - static const struct watchdog_info ident = { - .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, - .firmware_version = 0, - .identity = "Hardware Watchdog for PNX833x", - }; - - switch (cmd) { - default: - return -ENOTTY; - - case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, - &ident, sizeof(ident))) - return -EFAULT; - return 0; - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); - - case WDIOC_SETOPTIONS: - if (get_user(options, (int *)arg)) - return -EFAULT; - - if (options & WDIOS_DISABLECARD) - pnx833x_wdt_stop(); - - if (options & WDIOS_ENABLECARD) - pnx833x_wdt_start(); - - return 0; - - case WDIOC_KEEPALIVE: - pnx833x_wdt_ping(); - return 0; - - case WDIOC_SETTIMEOUT: - { - if (get_user(new_timeout, (int *)arg)) - return -EFAULT; - - pnx833x_wdt_timeout = new_timeout; - PNX833X_REG(PNX833X_CONFIG + - PNX833X_CONFIG_CPU_WATCHDOG_COMPARE) = new_timeout; - return put_user(new_timeout, (int *)arg); - } - - case WDIOC_GETTIMEOUT: - timeout = PNX833X_REG(PNX833X_CONFIG + - PNX833X_CONFIG_CPU_WATCHDOG_COMPARE); - return put_user(timeout, (int *)arg); - - case WDIOC_GETTIMELEFT: - timeout_left = PNX833X_REG(PNX833X_CONFIG + - PNX833X_CONFIG_CPU_WATCHDOG); - return put_user(timeout_left, (int *)arg); - - } -} - -static int pnx833x_wdt_notify_sys(struct notifier_block *this, - unsigned long code, void *unused) -{ - if (code == SYS_DOWN || code == SYS_HALT) - pnx833x_wdt_stop(); /* Turn the WDT off */ - - return NOTIFY_DONE; -} - -static const struct file_operations pnx833x_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = pnx833x_wdt_write, - .unlocked_ioctl = pnx833x_wdt_ioctl, - .compat_ioctl = compat_ptr_ioctl, - .open = pnx833x_wdt_open, - .release = pnx833x_wdt_release, -}; - -static struct miscdevice pnx833x_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &pnx833x_wdt_fops, -}; - -static struct notifier_block pnx833x_wdt_notifier = { - .notifier_call = pnx833x_wdt_notify_sys, -}; - -static int __init watchdog_init(void) -{ - int ret, cause; - - /* Lets check the reason for the reset.*/ - cause = PNX833X_REG(PNX833X_RESET); - /*If bit 31 is set then watchdog was cause of reset.*/ - if (cause & 0x80000000) { - pr_info("The system was previously reset due to the watchdog firing - please investigate...\n"); - } - - ret = register_reboot_notifier(&pnx833x_wdt_notifier); - if (ret) { - pr_err("cannot register reboot notifier (err=%d)\n", ret); - return ret; - } - - ret = misc_register(&pnx833x_wdt_miscdev); - if (ret) { - pr_err("cannot register miscdev on minor=%d (err=%d)\n", - WATCHDOG_MINOR, ret); - unregister_reboot_notifier(&pnx833x_wdt_notifier); - return ret; - } - - pr_info("Hardware Watchdog Timer for PNX833x: Version 0.1\n"); - - if (start_enabled) - pnx833x_wdt_start(); - - return 0; -} - -static void __exit watchdog_exit(void) -{ - misc_deregister(&pnx833x_wdt_miscdev); - unregister_reboot_notifier(&pnx833x_wdt_notifier); -} - -module_init(watchdog_init); -module_exit(watchdog_exit); - -MODULE_AUTHOR("Daniel Laird/Andre McCurdy"); -MODULE_DESCRIPTION("Hardware Watchdog Device for PNX833x"); -MODULE_LICENSE("GPL"); diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c index ab7465d186fd..7cf0f2ec649b 100644 --- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c @@ -148,10 +148,17 @@ static int qcom_wdt_restart(struct watchdog_device *wdd, unsigned long action, */ wmb(); - msleep(150); + mdelay(150); return 0; } +static int qcom_wdt_is_running(struct watchdog_device *wdd) +{ + struct qcom_wdt *wdt = to_qcom_wdt(wdd); + + return (readl(wdt_addr(wdt, WDT_EN)) & QCOM_WDT_ENABLE); +} + static const struct watchdog_ops qcom_wdt_ops = { .start = qcom_wdt_start, .stop = qcom_wdt_stop, @@ -294,6 +301,17 @@ static int qcom_wdt_probe(struct platform_device *pdev) wdt->wdd.timeout = min(wdt->wdd.max_timeout, 30U); watchdog_init_timeout(&wdt->wdd, 0, dev); + /* + * If WDT is already running, call WDT start which + * will stop the WDT, set timeouts as bootloader + * might use different ones and set running bit + * to inform the WDT subsystem to ping the WDT + */ + if (qcom_wdt_is_running(&wdt->wdd)) { + qcom_wdt_start(&wdt->wdd); + set_bit(WDOG_HW_RUNNING, &wdt->wdd.status); + } + ret = devm_watchdog_register_device(dev, &wdt->wdd); if (ret) return ret; diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c index 836319cbaca9..359302f71f7e 100644 --- a/drivers/watchdog/rti_wdt.c +++ b/drivers/watchdog/rti_wdt.c @@ -227,8 +227,10 @@ static int rti_wdt_probe(struct platform_device *pdev) pm_runtime_enable(dev); ret = pm_runtime_get_sync(dev); - if (ret) + if (ret) { + pm_runtime_put_noidle(dev); return dev_err_probe(dev, ret, "runtime pm failed\n"); + } platform_set_drvdata(pdev, wdt); diff --git a/drivers/watchdog/sbc_fitpc2_wdt.c b/drivers/watchdog/sbc_fitpc2_wdt.c index 04483d6453d6..13db71e16583 100644 --- a/drivers/watchdog/sbc_fitpc2_wdt.c +++ b/drivers/watchdog/sbc_fitpc2_wdt.c @@ -78,7 +78,7 @@ static int fitpc2_wdt_open(struct inode *inode, struct file *file) return stream_open(inode, file); } -static ssize_t fitpc2_wdt_write(struct file *file, const char *data, +static ssize_t fitpc2_wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { size_t i; @@ -125,16 +125,16 @@ static long fitpc2_wdt_ioctl(struct file *file, unsigned int cmd, switch (cmd) { case WDIOC_GETSUPPORT: - ret = copy_to_user((struct watchdog_info *)arg, &ident, + ret = copy_to_user((struct watchdog_info __user *)arg, &ident, sizeof(ident)) ? -EFAULT : 0; break; case WDIOC_GETSTATUS: - ret = put_user(0, (int *)arg); + ret = put_user(0, (int __user *)arg); break; case WDIOC_GETBOOTSTATUS: - ret = put_user(0, (int *)arg); + ret = put_user(0, (int __user *)arg); break; case WDIOC_KEEPALIVE: @@ -143,7 +143,7 @@ static long fitpc2_wdt_ioctl(struct file *file, unsigned int cmd, break; case WDIOC_SETTIMEOUT: - ret = get_user(time, (int *)arg); + ret = get_user(time, (int __user *)arg); if (ret) break; @@ -157,7 +157,7 @@ static long fitpc2_wdt_ioctl(struct file *file, unsigned int cmd, fallthrough; case WDIOC_GETTIMEOUT: - ret = put_user(margin, (int *)arg); + ret = put_user(margin, (int __user *)arg); break; } diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 190d26e2e75f..958dc32a708f 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -291,6 +291,7 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) set_bit(WDOG_HW_RUNNING, &wdt->wdd.status); } + watchdog_stop_on_reboot(&wdt->wdd); ret = watchdog_register_device(&wdt->wdd); if (ret) goto err; diff --git a/drivers/watchdog/sprd_wdt.c b/drivers/watchdog/sprd_wdt.c index 65cb55f3916f..4e689b6ff141 100644 --- a/drivers/watchdog/sprd_wdt.c +++ b/drivers/watchdog/sprd_wdt.c @@ -6,6 +6,7 @@ #include <linux/bitops.h> #include <linux/clk.h> +#include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> #include <linux/interrupt.h> @@ -53,7 +54,7 @@ #define SPRD_WDT_CNT_HIGH_SHIFT 16 #define SPRD_WDT_LOW_VALUE_MASK GENMASK(15, 0) -#define SPRD_WDT_LOAD_TIMEOUT 1000 +#define SPRD_WDT_LOAD_TIMEOUT 11 struct sprd_wdt { void __iomem *base; @@ -108,6 +109,23 @@ static int sprd_wdt_load_value(struct sprd_wdt *wdt, u32 timeout, u32 tmr_step = timeout * SPRD_WDT_CNT_STEP; u32 prtmr_step = pretimeout * SPRD_WDT_CNT_STEP; + /* + * Checking busy bit to make sure the previous loading operation is + * done. According to the specification, the busy bit would be set + * after a new loading operation and last 2 or 3 RTC clock + * cycles (about 60us~92us). + */ + do { + val = readl_relaxed(wdt->base + SPRD_WDT_INT_RAW); + if (!(val & SPRD_WDT_LD_BUSY_BIT)) + break; + + usleep_range(10, 100); + } while (delay_cnt++ < SPRD_WDT_LOAD_TIMEOUT); + + if (delay_cnt >= SPRD_WDT_LOAD_TIMEOUT) + return -EBUSY; + sprd_wdt_unlock(wdt->base); writel_relaxed((tmr_step >> SPRD_WDT_CNT_HIGH_SHIFT) & SPRD_WDT_LOW_VALUE_MASK, wdt->base + SPRD_WDT_LOAD_HIGH); @@ -120,20 +138,6 @@ static int sprd_wdt_load_value(struct sprd_wdt *wdt, u32 timeout, wdt->base + SPRD_WDT_IRQ_LOAD_LOW); sprd_wdt_lock(wdt->base); - /* - * Waiting the load value operation done, - * it needs two or three RTC clock cycles. - */ - do { - val = readl_relaxed(wdt->base + SPRD_WDT_INT_RAW); - if (!(val & SPRD_WDT_LD_BUSY_BIT)) - break; - - cpu_relax(); - } while (delay_cnt++ < SPRD_WDT_LOAD_TIMEOUT); - - if (delay_cnt >= SPRD_WDT_LOAD_TIMEOUT) - return -EBUSY; return 0; } @@ -345,15 +349,10 @@ static int __maybe_unused sprd_wdt_pm_resume(struct device *dev) if (ret) return ret; - if (watchdog_active(&wdt->wdd)) { + if (watchdog_active(&wdt->wdd)) ret = sprd_wdt_start(&wdt->wdd); - if (ret) { - sprd_wdt_disable(wdt); - return ret; - } - } - return 0; + return ret; } static const struct dev_pm_ops sprd_wdt_pm_ops = { diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c index 25188d6bbe15..a3436c296c97 100644 --- a/drivers/watchdog/stm32_iwdg.c +++ b/drivers/watchdog/stm32_iwdg.c @@ -162,18 +162,15 @@ static int stm32_iwdg_clk_init(struct platform_device *pdev, u32 ret; wdt->clk_lsi = devm_clk_get(dev, "lsi"); - if (IS_ERR(wdt->clk_lsi)) { - dev_err(dev, "Unable to get lsi clock\n"); - return PTR_ERR(wdt->clk_lsi); - } + if (IS_ERR(wdt->clk_lsi)) + return dev_err_probe(dev, PTR_ERR(wdt->clk_lsi), "Unable to get lsi clock\n"); /* optional peripheral clock */ if (wdt->data->has_pclk) { wdt->clk_pclk = devm_clk_get(dev, "pclk"); - if (IS_ERR(wdt->clk_pclk)) { - dev_err(dev, "Unable to get pclk clock\n"); - return PTR_ERR(wdt->clk_pclk); - } + if (IS_ERR(wdt->clk_pclk)) + return dev_err_probe(dev, PTR_ERR(wdt->clk_pclk), + "Unable to get pclk clock\n"); ret = clk_prepare_enable(wdt->clk_pclk); if (ret) { diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c index 423844757812..0e9a99559609 100644 --- a/drivers/watchdog/watchdog_core.c +++ b/drivers/watchdog/watchdog_core.c @@ -267,15 +267,19 @@ static int __watchdog_register_device(struct watchdog_device *wdd) } if (test_bit(WDOG_STOP_ON_REBOOT, &wdd->status)) { - wdd->reboot_nb.notifier_call = watchdog_reboot_notifier; - - ret = register_reboot_notifier(&wdd->reboot_nb); - if (ret) { - pr_err("watchdog%d: Cannot register reboot notifier (%d)\n", - wdd->id, ret); - watchdog_dev_unregister(wdd); - ida_simple_remove(&watchdog_ida, id); - return ret; + if (!wdd->ops->stop) + pr_warn("watchdog%d: stop_on_reboot not supported\n", wdd->id); + else { + wdd->reboot_nb.notifier_call = watchdog_reboot_notifier; + + ret = register_reboot_notifier(&wdd->reboot_nb); + if (ret) { + pr_err("watchdog%d: Cannot register reboot notifier (%d)\n", + wdd->id, ret); + watchdog_dev_unregister(wdd); + ida_simple_remove(&watchdog_ida, id); + return ret; + } } } diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c index 3065dd670a18..cec7917790e5 100644 --- a/drivers/watchdog/wdat_wdt.c +++ b/drivers/watchdog/wdat_wdt.c @@ -34,9 +34,9 @@ struct wdat_instruction { * @period: How long is one watchdog period in ms * @stopped_in_sleep: Is this watchdog stopped by the firmware in S1-S5 * @stopped: Was the watchdog stopped by the driver in suspend - * @actions: An array of instruction lists indexed by an action number from - * the WDAT table. There can be %NULL entries for not implemented - * actions. + * @instructions: An array of instruction lists indexed by an action number from + * the WDAT table. There can be %NULL entries for not implemented + * actions. */ struct wdat_wdt { struct platform_device *pdev; |