From 1f6602c8ed1eccac4fa83e338d02aafe3a0e2c0a Mon Sep 17 00:00:00 2001 From: Mark Pearson Date: Fri, 15 Mar 2024 15:52:12 -0400 Subject: [PATCH 1/9] watchdog: lenovo_se10_wdt: Watchdog driver for Lenovo SE10 platform Watchdog driver implementation for Lenovo SE10 platform. Signed-off-by: Mark Pearson Signed-off-by: David Ober Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20240315195227.91282-1-mpearson-lenovo@squebb.ca Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 10 + drivers/watchdog/Makefile | 1 + drivers/watchdog/lenovo_se10_wdt.c | 308 +++++++++++++++++++++++++++++ 3 files changed, 319 insertions(+) create mode 100644 drivers/watchdog/lenovo_se10_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 6bee137cfbe0..419a2e3e0dbe 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -254,6 +254,16 @@ config GPIO_WATCHDOG_ARCH_INITCALL arch_initcall. If in doubt, say N. +config LENOVO_SE10_WDT + tristate "Lenovo SE10 Watchdog" + select WATCHDOG_CORE + help + If you say yes here you get support for the watchdog + functionality for the Lenovo SE10 platform. + + This driver can also be built as a module. If so, the module + will be called lenovo-se10-wdt. + config MENF21BMC_WATCHDOG tristate "MEN 14F021P00 BMC Watchdog" depends on MFD_MENF21BMC || COMPILE_TEST diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 3710c218f05e..2d1117564f5b 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -120,6 +120,7 @@ obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o obj-$(CONFIG_IE6XX_WDT) += ie6xx_wdt.o obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o +obj-$(CONFIG_LENOVO_SE10_WDT) += lenovo_se10_wdt.o ifeq ($(CONFIG_ITCO_VENDOR_SUPPORT),y) obj-$(CONFIG_ITCO_WDT) += iTCO_vendor_support.o endif diff --git a/drivers/watchdog/lenovo_se10_wdt.c b/drivers/watchdog/lenovo_se10_wdt.c new file mode 100644 index 000000000000..139ff0e8220f --- /dev/null +++ b/drivers/watchdog/lenovo_se10_wdt.c @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * WDT driver for Lenovo SE10. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STATUS_PORT 0x6C +#define CMD_PORT 0x6C +#define DATA_PORT 0x68 +#define OUTBUF_FULL 0x01 +#define INBUF_EMPTY 0x02 +#define CFG_LDN 0x07 +#define CFG_BRAM_LDN 0x10 /* for BRAM Base */ +#define CFG_PORT 0x2E +#define CFG_SIZE 2 +#define CMD_SIZE 4 +#define BRAM_SIZE 2 + +#define UNLOCK_KEY 0x87 +#define LOCK_KEY 0xAA + +#define CUS_WDT_SWI 0x1A +#define CUS_WDT_CFG 0x1B +#define CUS_WDT_FEED 0xB0 +#define CUS_WDT_CNT 0xB1 + +#define DRVNAME "lenovo-se10-wdt" + +/*The timeout range is 1-255 seconds*/ +#define MIN_TIMEOUT 1 +#define MAX_TIMEOUT 255 +#define MAX_WAIT 10 + +#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ +static unsigned short bram_base; +static struct platform_device *se10_pdev; + +static int timeout; /* in seconds */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. 1 <= timeout <= 255, default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) "."); + +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) ")"); + +struct se10_wdt { + struct watchdog_device wdd; +}; + +static int set_bram(unsigned char offset, unsigned char val) +{ + if (!request_muxed_region(bram_base, BRAM_SIZE, DRVNAME)) + return -EBUSY; + outb(offset, bram_base); + outb(val, bram_base + 1); + release_region(bram_base, BRAM_SIZE); + return 0; +} + +static void wait_for_buffer(int condition) +{ + int loop = 0; + + while (1) { + if (inb(STATUS_PORT) & condition || loop > MAX_WAIT) + break; + loop++; + usleep_range(10, 125); + } +} + +static void send_cmd(unsigned char cmd) +{ + wait_for_buffer(INBUF_EMPTY); + outb(cmd, CMD_PORT); + wait_for_buffer(INBUF_EMPTY); +} + +static void lpc_write(unsigned char index, unsigned char data) +{ + outb(index, CFG_PORT); + outb(data, CFG_PORT + 1); +} + +static unsigned char lpc_read(unsigned char index) +{ + outb(index, CFG_PORT); + return inb(CFG_PORT + 1); +} + +static int wdt_start(struct watchdog_device *wdog) +{ + return set_bram(CUS_WDT_SWI, 0x80); +} + +static int wdt_set_timeout(struct watchdog_device *wdog, unsigned int timeout) +{ + wdog->timeout = timeout; + return set_bram(CUS_WDT_CFG, wdog->timeout); +} + +static int wdt_stop(struct watchdog_device *wdog) +{ + return set_bram(CUS_WDT_SWI, 0); +} + +static unsigned int wdt_get_time(struct watchdog_device *wdog) +{ + unsigned char time; + + if (!request_muxed_region(CMD_PORT, CMD_SIZE, DRVNAME)) + return -EBUSY; + send_cmd(CUS_WDT_CNT); + wait_for_buffer(OUTBUF_FULL); + time = inb(DATA_PORT); + release_region(CMD_PORT, CMD_SIZE); + return time; +} + +static int wdt_ping(struct watchdog_device *wdog) +{ + if (!request_muxed_region(CMD_PORT, CMD_SIZE, DRVNAME)) + return -EBUSY; + send_cmd(CUS_WDT_FEED); + release_region(CMD_PORT, CMD_SIZE); + return 0; +} + +static const struct watchdog_info wdt_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, + .identity = "Lenovo SE10 Watchdog", +}; + +static const struct watchdog_ops se10_wdt_ops = { + .owner = THIS_MODULE, + .start = wdt_start, + .stop = wdt_stop, + .ping = wdt_ping, + .set_timeout = wdt_set_timeout, + .get_timeleft = wdt_get_time, +}; + +static unsigned int get_chipID(void) +{ + unsigned char msb, lsb; + + outb(UNLOCK_KEY, CFG_PORT); + outb(0x01, CFG_PORT); + outb(0x55, CFG_PORT); + outb(0x55, CFG_PORT); + msb = lpc_read(0x20); + lsb = lpc_read(0x21); + outb(LOCK_KEY, CFG_PORT); + return (msb * 256 + lsb); +} + +static int se10_wdt_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct se10_wdt *priv; + unsigned int chip_id; + int ret; + + if (!request_muxed_region(CFG_PORT, CFG_SIZE, DRVNAME)) + return -EBUSY; + + chip_id = get_chipID(); + if (chip_id != 0x5632) { + release_region(CFG_PORT, CFG_SIZE); + return -ENODEV; + } + + lpc_write(CFG_LDN, CFG_BRAM_LDN); + bram_base = (lpc_read(0x60) << 8) | lpc_read(0x61); + release_region(CFG_PORT, CFG_SIZE); + + dev_info(dev, "Found Lenovo SE10 0x%x\n", chip_id); + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + watchdog_set_drvdata(&priv->wdd, priv); + + priv->wdd.parent = dev; + priv->wdd.info = &wdt_info, + priv->wdd.ops = &se10_wdt_ops, + priv->wdd.timeout = WATCHDOG_TIMEOUT; /* Set default timeout */ + priv->wdd.min_timeout = MIN_TIMEOUT; + priv->wdd.max_timeout = MAX_TIMEOUT; + + set_bram(CUS_WDT_CFG, WATCHDOG_TIMEOUT); /* Set time to default */ + + watchdog_init_timeout(&priv->wdd, timeout, dev); + watchdog_set_nowayout(&priv->wdd, nowayout); + watchdog_stop_on_reboot(&priv->wdd); + watchdog_stop_on_unregister(&priv->wdd); + + ret = devm_watchdog_register_device(dev, &priv->wdd); + + dev_dbg(&pdev->dev, "initialized. timeout=%d sec (nowayout=%d)\n", + priv->wdd.timeout, nowayout); + + return ret; +} + +static struct platform_driver se10_wdt_driver = { + .driver = { + .name = DRVNAME, + }, + .probe = se10_wdt_probe, +}; + +static int se10_create_platform_device(const struct dmi_system_id *id) +{ + int err; + + se10_pdev = platform_device_alloc("lenovo-se10-wdt", -1); + if (!se10_pdev) + return -ENOMEM; + + err = platform_device_add(se10_pdev); + if (err) + platform_device_put(se10_pdev); + + return err; +} + +static const struct dmi_system_id se10_dmi_table[] __initconst = { + { + .ident = "LENOVO-SE10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "12NH"), + }, + .callback = se10_create_platform_device, + }, + { + .ident = "LENOVO-SE10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "12NJ"), + }, + .callback = se10_create_platform_device, + }, + { + .ident = "LENOVO-SE10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "12NK"), + }, + .callback = se10_create_platform_device, + }, + { + .ident = "LENOVO-SE10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "12NL"), + }, + .callback = se10_create_platform_device, + }, + { + .ident = "LENOVO-SE10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "12NM"), + }, + .callback = se10_create_platform_device, + }, + {} +}; +MODULE_DEVICE_TABLE(dmi, se10_dmi_table); + +static int __init se10_wdt_init(void) +{ + if (!dmi_check_system(se10_dmi_table)) + return -ENODEV; + + return platform_driver_register(&se10_wdt_driver); +} + +static void __exit se10_wdt_exit(void) +{ + if (se10_pdev) + platform_device_unregister(se10_pdev); + platform_driver_unregister(&se10_wdt_driver); +} + +module_init(se10_wdt_init); +module_exit(se10_wdt_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Ober"); +MODULE_AUTHOR("Mark Pearson "); +MODULE_DESCRIPTION("WDT driver for Lenovo SE10"); From 573601521277119f2e2ba5f28ae6e87fc594f4d4 Mon Sep 17 00:00:00 2001 From: Duoming Zhou Date: Sun, 24 Mar 2024 22:04:44 +0800 Subject: [PATCH 2/9] watchdog: cpu5wdt.c: Fix use-after-free bug caused by cpu5wdt_trigger When the cpu5wdt module is removing, the origin code uses del_timer() to de-activate the timer. If the timer handler is running, del_timer() could not stop it and will return directly. If the port region is released by release_region() and then the timer handler cpu5wdt_trigger() calls outb() to write into the region that is released, the use-after-free bug will happen. Change del_timer() to timer_shutdown_sync() in order that the timer handler could be finished before the port region is released. Fixes: e09d9c3e9f85 ("watchdog: cpu5wdt.c: add missing del_timer call") Signed-off-by: Duoming Zhou Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20240324140444.119584-1-duoming@zju.edu.cn Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/cpu5wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c index 688b112e712b..9f279c0e13a6 100644 --- a/drivers/watchdog/cpu5wdt.c +++ b/drivers/watchdog/cpu5wdt.c @@ -252,7 +252,7 @@ static void cpu5wdt_exit(void) if (cpu5wdt_device.queue) { cpu5wdt_device.queue = 0; wait_for_completion(&cpu5wdt_device.stop); - del_timer(&cpu5wdt_device.timer); + timer_shutdown_sync(&cpu5wdt_device.timer); } misc_deregister(&cpu5wdt_misc); From 56e23c6d7ffbf0dfc6506552f1059b309a4d5dcd Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:46:38 +0100 Subject: [PATCH 3/9] watchdog: mtx-1: drop driver owner assignment Core in platform_driver_register() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20240327174638.519445-1-krzysztof.kozlowski@linaro.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/mtx-1_wdt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 152e41ecbb14..06756135033d 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -236,7 +236,6 @@ static struct platform_driver mtx1_wdt_driver = { .probe = mtx1_wdt_probe, .remove_new = mtx1_wdt_remove, .driver.name = "mtx1-wdt", - .driver.owner = THIS_MODULE, }; module_platform_driver(mtx1_wdt_driver); From e3b3afd34d84efcbe4543deb966b1990f43584b8 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 8 Apr 2024 13:02:31 +0300 Subject: [PATCH 4/9] watchdog: bd9576: Drop "always-running" property The always-running (from linux,wdt-gpio.yaml) is abused by the BD9576 watchdog driver. It's defined meaning is "the watchdog is always running and can not be stopped". The BD9576 watchdog driver has implemented it as "start watchdog when loading the module and prevent it from being stopped". Furthermore, the implementation does not set the WDOG_HW_RUNNING when enabling the watchdog due to the "always-running" at module loading. This will end up resulting a watchdog timeout if the device is not opened. The culprit was pointed out by Guenter, discussion can be found from https://lore.kernel.org/lkml/4fa3a64b-60fb-4e5e-8785-0f14da37eea2@roeck-us.net/ Drop the invalid "always-running" handling. Signed-off-by: Matti Vaittinen Reported-by: Guenter Roeck Fixes: b237bcac557a ("wdt: Support wdt on ROHM BD9576MUF and BD9573MUF") Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/ZhPAt76yaJMersXf@fedora Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/bd9576_wdt.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/watchdog/bd9576_wdt.c b/drivers/watchdog/bd9576_wdt.c index 4a20e07fbb69..f00ea1b4e40b 100644 --- a/drivers/watchdog/bd9576_wdt.c +++ b/drivers/watchdog/bd9576_wdt.c @@ -29,7 +29,6 @@ struct bd9576_wdt_priv { struct gpio_desc *gpiod_en; struct device *dev; struct regmap *regmap; - bool always_running; struct watchdog_device wdd; }; @@ -62,10 +61,7 @@ static int bd9576_wdt_stop(struct watchdog_device *wdd) { struct bd9576_wdt_priv *priv = watchdog_get_drvdata(wdd); - if (!priv->always_running) - bd9576_wdt_disable(priv); - else - set_bit(WDOG_HW_RUNNING, &wdd->status); + bd9576_wdt_disable(priv); return 0; } @@ -264,9 +260,6 @@ static int bd9576_wdt_probe(struct platform_device *pdev) if (ret) return ret; - priv->always_running = device_property_read_bool(dev->parent, - "always-running"); - watchdog_set_drvdata(&priv->wdd, priv); priv->wdd.info = &bd957x_wdt_ident; @@ -281,9 +274,6 @@ static int bd9576_wdt_probe(struct platform_device *pdev) watchdog_stop_on_reboot(&priv->wdd); - if (priv->always_running) - bd9576_wdt_start(&priv->wdd); - return devm_watchdog_register_device(dev, &priv->wdd); } From 4c97f0433de08ab4b52d7a2747daf44430c6d489 Mon Sep 17 00:00:00 2001 From: Dawei Li Date: Wed, 10 Apr 2024 21:13:59 +0800 Subject: [PATCH 5/9] watchdog/wdt-main: Use cpumask_of() to avoid cpumask var on stack In general it's preferable to avoid placing cpumasks on the stack, as for large values of NR_CPUS these can consume significant amounts of stack space and make stack overflows more likely. Use cpumask_of() to avoid the need for a temporary cpumask on the stack Signed-off-by: Dawei Li Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/TYTP286MB3564B037A81DAAE1AC3A16F3CA062@TYTP286MB3564.JPNP286.PROD.OUTLOOK.COM Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/octeon-wdt-main.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c index 0fe71f7e66d5..52d49e4e35a0 100644 --- a/drivers/watchdog/octeon-wdt-main.c +++ b/drivers/watchdog/octeon-wdt-main.c @@ -381,11 +381,7 @@ static int octeon_wdt_cpu_online(unsigned int cpu) /* Must set the irq affinity here */ if (octeon_has_feature(OCTEON_FEATURE_CIU3)) { - cpumask_t mask; - - cpumask_clear(&mask); - cpumask_set_cpu(cpu, &mask); - irq_set_affinity(irq, &mask); + irq_set_affinity(irq, cpumask_of(cpu)); } cpumask_set_cpu(cpu, &irq_enabled_cpus); From 52df67b6b313984e1b58030fd1f6b8a873799e36 Mon Sep 17 00:00:00 2001 From: Niklas Schnelle Date: Wed, 10 Apr 2024 10:42:01 +0200 Subject: [PATCH 6/9] watchdog: add HAS_IOPORT dependencies In a future patch HAS_IOPORT=n will disable inb()/outb() and friends at compile time. We thus need to add HAS_IOPORT as dependency for those drivers using them. Co-developed-by: Arnd Bergmann Signed-off-by: Arnd Bergmann Signed-off-by: Niklas Schnelle Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20240410084201.1481930-2-schnelle@linux.ibm.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 58 +++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 419a2e3e0dbe..f99880a3b976 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -492,6 +492,7 @@ config 21285_WATCHDOG config 977_WATCHDOG tristate "NetWinder WB83C977 watchdog" depends on (FOOTBRIDGE && ARCH_NETWINDER) || (ARM && COMPILE_TEST) + depends on HAS_IOPORT help Say Y here to include support for the WB977 watchdog included in NetWinder machines. Alternatively say M to compile the driver as @@ -1085,7 +1086,7 @@ config ACQUIRE_WDT config ADVANTECH_WDT tristate "Advantech SBC Watchdog Timer" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help If you are configuring a Linux kernel for the Advantech single-board computer, say `Y' here to support its built-in watchdog timer @@ -1094,7 +1095,7 @@ config ADVANTECH_WDT config ADVANTECH_EC_WDT tristate "Advantech Embedded Controller Watchdog Timer" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT select ISA_BUS_API select WATCHDOG_CORE help @@ -1127,7 +1128,7 @@ config ALIM7101_WDT config EBC_C384_WDT tristate "WinSystems EBC-C384 Watchdog Timer" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT select ISA_BUS_API select WATCHDOG_CORE help @@ -1137,7 +1138,7 @@ config EBC_C384_WDT config EXAR_WDT tristate "Exar Watchdog Timer" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT select WATCHDOG_CORE help Enables watchdog timer support for the watchdog timer present @@ -1148,7 +1149,7 @@ config EXAR_WDT config F71808E_WDT tristate "Fintek F718xx, F818xx Super I/O Watchdog" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT select WATCHDOG_CORE help This is the driver for the hardware watchdog on the Fintek F71808E, @@ -1160,7 +1161,7 @@ config F71808E_WDT config SP5100_TCO tristate "AMD/ATI SP5100 TCO Timer/Watchdog" - depends on (X86 || COMPILE_TEST) && PCI + depends on (X86 || COMPILE_TEST) && PCI && HAS_IOPORT select WATCHDOG_CORE help Hardware watchdog driver for the AMD/ATI SP5100 chipset. The TCO @@ -1199,7 +1200,7 @@ config SC520_WDT config SBC_FITPC2_WATCHDOG tristate "Compulab SBC-FITPC2 watchdog" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help This is the driver for the built-in watchdog timer on the fit-PC2, fit-PC2i, CM-iAM single-board computers made by Compulab. @@ -1224,7 +1225,7 @@ config SBC_FITPC2_WATCHDOG config EUROTECH_WDT tristate "Eurotech CPU-1220/1410 Watchdog Timer" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help Enable support for the watchdog timer on the Eurotech CPU-1220 and CPU-1410 cards. These are PC/104 SBCs. Spec sheets and product @@ -1232,7 +1233,7 @@ config EUROTECH_WDT config IB700_WDT tristate "IB700 SBC Watchdog Timer" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help This is the driver for the hardware watchdog on the IB700 Single Board Computer produced by TMC Technology (www.tmc-uk.com). This @@ -1249,7 +1250,7 @@ config IB700_WDT config IBMASR tristate "IBM Automatic Server Restart" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help This is the driver for the IBM Automatic Server Restart watchdog timer built-in into some eServer xSeries machines. @@ -1259,7 +1260,7 @@ config IBMASR config WAFER_WDT tristate "ICP Single Board Computer Watchdog Timer" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help This is a driver for the hardware watchdog on the ICP Single Board Computer. This driver is working on (at least) the following @@ -1281,7 +1282,7 @@ config I6300ESB_WDT config IE6XX_WDT tristate "Intel Atom E6xx Watchdog" - depends on (X86 || COMPILE_TEST) && PCI + depends on (X86 || COMPILE_TEST) && PCI && HAS_IOPORT select WATCHDOG_CORE select MFD_CORE select LPC_SCH @@ -1311,6 +1312,7 @@ config ITCO_WDT select WATCHDOG_CORE depends on I2C || I2C=n depends on MFD_INTEL_PMC_BXT || !MFD_INTEL_PMC_BXT + depends on HAS_IOPORT # for I2C_I801 select LPC_ICH if !EXPERT select I2C_I801 if !EXPERT && I2C help @@ -1341,7 +1343,7 @@ config ITCO_VENDOR_SUPPORT config IT8712F_WDT tristate "IT8712F (Smart Guardian) Watchdog Timer" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help This is the driver for the built-in watchdog timer on the IT8712F Super I/0 chipset used on many motherboards. @@ -1354,7 +1356,7 @@ config IT8712F_WDT config IT87_WDT tristate "IT87 Watchdog Timer" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT select WATCHDOG_CORE help This is the driver for the hardware watchdog on the ITE IT8607, @@ -1402,7 +1404,7 @@ config KEMPLD_WDT config SC1200_WDT tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help This is a driver for National Semiconductor PC87307/PC97307 hardware watchdog cards as found on the SC1200. This watchdog is mainly used @@ -1425,7 +1427,7 @@ config SCx200_WDT config PC87413_WDT tristate "NS PC87413 watchdog" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help This is the driver for the hardware watchdog on the PC87413 chipset This watchdog simply watches your kernel to make sure it doesn't @@ -1439,7 +1441,7 @@ config PC87413_WDT config NV_TCO tristate "nVidia TCO Timer/Watchdog" - depends on (X86 || COMPILE_TEST) && PCI + depends on (X86 || COMPILE_TEST) && PCI && HAS_IOPORT help Hardware driver for the TCO timer built into the nVidia Hub family (such as the MCP51). The TCO (Total Cost of Ownership) timer is a @@ -1468,7 +1470,7 @@ config RDC321X_WDT config 60XX_WDT tristate "SBC-60XX Watchdog Timer" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help This driver can be used with the watchdog timer found on some single board computers, namely the 6010 PII based computer. @@ -1508,7 +1510,7 @@ config SBC7240_WDT config CPU5_WDT tristate "SMA CPU5 Watchdog" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help TBD. To compile this driver as a module, choose M here: the @@ -1516,7 +1518,7 @@ config CPU5_WDT config SMSC_SCH311X_WDT tristate "SMSC SCH311X Watchdog Timer" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help This is the driver for the hardware watchdog timer on the SMSC SCH3112, SCH3114 and SCH3116 Super IO chipset @@ -1528,7 +1530,7 @@ config SMSC_SCH311X_WDT config SMSC37B787_WDT tristate "Winbond SMsC37B787 Watchdog Timer" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help This is the driver for the hardware watchdog component on the Winbond SMsC37B787 chipset as used on the NetRunner Mainboard @@ -1574,7 +1576,7 @@ config VIA_WDT config W83627HF_WDT tristate "Watchdog timer for W83627HF/W83627DHG and compatibles" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT select WATCHDOG_CORE help This is the driver for the hardware watchdog on the following @@ -1604,7 +1606,7 @@ config W83627HF_WDT config W83877F_WDT tristate "W83877F (EMACS) Watchdog Timer" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help This is the driver for the hardware watchdog on the W83877F chipset as used in EMACS PC-104 motherboards (and likely others). This @@ -1619,7 +1621,7 @@ config W83877F_WDT config W83977F_WDT tristate "W83977F (PCM-5335) Watchdog Timer" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help This is the driver for the hardware watchdog on the W83977F I/O chip as used in AAEON's PCM-5335 SBC (and likely others). This @@ -1632,7 +1634,7 @@ config W83977F_WDT config MACHZ_WDT tristate "ZF MachZ Watchdog" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help If you are using a ZF Micro MachZ processor, say Y here, otherwise N. This is the driver for the watchdog timer built-in on that @@ -1645,7 +1647,7 @@ config MACHZ_WDT config SBC_EPX_C3_WATCHDOG tristate "Winsystems SBC EPX-C3 watchdog" - depends on X86 || COMPILE_TEST + depends on (X86 || COMPILE_TEST) && HAS_IOPORT help This is the driver for the built-in watchdog timer on the EPX-C3 Single-board computer made by Winsystems, Inc. @@ -2207,7 +2209,7 @@ comment "PCI-based Watchdog Cards" config PCIPCWATCHDOG tristate "Berkshire Products PCI-PC Watchdog" - depends on PCI + depends on PCI && HAS_IOPORT help This is the driver for the Berkshire Products PCI-PC Watchdog card. This card simply watches your kernel to make sure it doesn't freeze, @@ -2222,7 +2224,7 @@ config PCIPCWATCHDOG config WDTPCI tristate "PCI-WDT500/501 Watchdog timer" - depends on PCI + depends on PCI && HAS_IOPORT help If you have a PCI-WDT500/501 watchdog board, say Y here, otherwise N. From cae58516534e110f4a8558d48aa4435e15519121 Mon Sep 17 00:00:00 2001 From: Judith Mendez Date: Wed, 17 Apr 2024 15:57:00 -0500 Subject: [PATCH 7/9] watchdog: rti_wdt: Set min_hw_heartbeat_ms to accommodate a safety margin On AM62x, the watchdog is pet before the valid window is open. Fix min_hw_heartbeat and accommodate a 2% + static offset safety margin. The static offset accounts for max hardware error. Remove the hack in the driver which shifts the open window boundary, since it is no longer necessary due to the fix mentioned above. cc: stable@vger.kernel.org Fixes: 5527483f8f7c ("watchdog: rti-wdt: attach to running watchdog during probe") Signed-off-by: Judith Mendez Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20240417205700.3947408-1-jm@ti.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rti_wdt.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c index 9215793a1c81..4895a69015a8 100644 --- a/drivers/watchdog/rti_wdt.c +++ b/drivers/watchdog/rti_wdt.c @@ -59,6 +59,8 @@ #define PON_REASON_EOF_NUM 0xCCCCBBBB #define RESERVED_MEM_MIN_SIZE 12 +#define MAX_HW_ERROR 250 + static int heartbeat = DEFAULT_HEARTBEAT; /* @@ -97,7 +99,7 @@ static int rti_wdt_start(struct watchdog_device *wdd) * to be 50% or less than that; we obviouly want to configure the open * window as large as possible so we select the 50% option. */ - wdd->min_hw_heartbeat_ms = 500 * wdd->timeout; + wdd->min_hw_heartbeat_ms = 520 * wdd->timeout + MAX_HW_ERROR; /* Generate NMI when wdt expires */ writel_relaxed(RTIWWDRX_NMI, wdt->base + RTIWWDRXCTRL); @@ -131,31 +133,33 @@ static int rti_wdt_setup_hw_hb(struct watchdog_device *wdd, u32 wsize) * be petted during the open window; not too early or not too late. * The HW configuration options only allow for the open window size * to be 50% or less than that. + * To avoid any glitches, we accommodate 2% + max hardware error + * safety margin. */ switch (wsize) { case RTIWWDSIZE_50P: - /* 50% open window => 50% min heartbeat */ - wdd->min_hw_heartbeat_ms = 500 * heartbeat; + /* 50% open window => 52% min heartbeat */ + wdd->min_hw_heartbeat_ms = 520 * heartbeat + MAX_HW_ERROR; break; case RTIWWDSIZE_25P: - /* 25% open window => 75% min heartbeat */ - wdd->min_hw_heartbeat_ms = 750 * heartbeat; + /* 25% open window => 77% min heartbeat */ + wdd->min_hw_heartbeat_ms = 770 * heartbeat + MAX_HW_ERROR; break; case RTIWWDSIZE_12P5: - /* 12.5% open window => 87.5% min heartbeat */ - wdd->min_hw_heartbeat_ms = 875 * heartbeat; + /* 12.5% open window => 89.5% min heartbeat */ + wdd->min_hw_heartbeat_ms = 895 * heartbeat + MAX_HW_ERROR; break; case RTIWWDSIZE_6P25: - /* 6.5% open window => 93.5% min heartbeat */ - wdd->min_hw_heartbeat_ms = 935 * heartbeat; + /* 6.5% open window => 95.5% min heartbeat */ + wdd->min_hw_heartbeat_ms = 955 * heartbeat + MAX_HW_ERROR; break; case RTIWWDSIZE_3P125: - /* 3.125% open window => 96.9% min heartbeat */ - wdd->min_hw_heartbeat_ms = 969 * heartbeat; + /* 3.125% open window => 98.9% min heartbeat */ + wdd->min_hw_heartbeat_ms = 989 * heartbeat + MAX_HW_ERROR; break; default: @@ -233,14 +237,6 @@ static int rti_wdt_probe(struct platform_device *pdev) return -EINVAL; } - /* - * If watchdog is running at 32k clock, it is not accurate. - * Adjust frequency down in this case so that we don't pet - * the watchdog too often. - */ - if (wdt->freq < 32768) - wdt->freq = wdt->freq * 9 / 10; - pm_runtime_enable(dev); ret = pm_runtime_resume_and_get(dev); if (ret < 0) { From 413bf4e857fd79617524d5dcd35f463e9aa2dd41 Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Fri, 26 Apr 2024 15:58:08 +0800 Subject: [PATCH 8/9] watchdog: sa1100: Fix PTR_ERR_OR_ZERO() vs NULL check in sa1100dog_probe() devm_ioremap() doesn't return error pointers, it returns NULL on error. Update the check accordingly. Fixes: e86bd43bcfc5 ("watchdog: sa1100: use platform device registration") Signed-off-by: Chen Ni Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20240426075808.1582678-1-nichen@iscas.ac.cn Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sa1100_wdt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c index 5d2df008b92a..34a917221e31 100644 --- a/drivers/watchdog/sa1100_wdt.c +++ b/drivers/watchdog/sa1100_wdt.c @@ -191,9 +191,8 @@ static int sa1100dog_probe(struct platform_device *pdev) if (!res) return -ENXIO; reg_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - ret = PTR_ERR_OR_ZERO(reg_base); - if (ret) - return ret; + if (!reg_base) + return -ENOMEM; clk = clk_get(NULL, "OSTIMER0"); if (IS_ERR(clk)) { From c45b8cfc6d5c12fbbc4d89b24b59402df99c1ecb Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 7 May 2024 12:07:56 +0200 Subject: [PATCH 9/9] watchdog: LENOVO_SE10_WDT should depend on X86 && DMI The Lenovo SE10 watchdog is only present on Lenovo ThinkEdge SE10 platforms, which are based on Intel Atom SoCs, and its driver relies on DMI tables. Hence add dependencies on X86 && DMI, to prevent asking the user about this driver when configuring a kernel without Intel Atom or DMI support. While at it, fix the odd indentation (spaces instead of TABs). Fixes: 1f6602c8ed1eccac ("watchdog: lenovo_se10_wdt: Watchdog driver for Lenovo SE10 platform") Signed-off-by: Geert Uytterhoeven Reviewed-by: Mark Pearson Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/58005595a05ef803b454b78d3ae9b8ee0675bd5d.1715076440.git.geert+renesas@glider.be Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index f99880a3b976..85eea38dbdf4 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -255,14 +255,15 @@ config GPIO_WATCHDOG_ARCH_INITCALL If in doubt, say N. config LENOVO_SE10_WDT - tristate "Lenovo SE10 Watchdog" - select WATCHDOG_CORE - help - If you say yes here you get support for the watchdog - functionality for the Lenovo SE10 platform. + tristate "Lenovo SE10 Watchdog" + depends on (X86 && DMI) || COMPILE_TEST + select WATCHDOG_CORE + help + If you say yes here you get support for the watchdog + functionality for the Lenovo SE10 platform. - This driver can also be built as a module. If so, the module - will be called lenovo-se10-wdt. + This driver can also be built as a module. If so, the module + will be called lenovo-se10-wdt. config MENF21BMC_WATCHDOG tristate "MEN 14F021P00 BMC Watchdog"