Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'linux-watchdog-6.17-rc1' of git://www.linux-watchdog.org/linux-watchdog

Pull watchdog updates from Wim Van Sebroeck:

- sbsa: Adjust keepalive timeout to avoid MediaTek WS0 race condition

- Various improvements and fixes

* tag 'linux-watchdog-6.17-rc1' of git://www.linux-watchdog.org/linux-watchdog:
watchdog: sbsa: Adjust keepalive timeout to avoid MediaTek WS0 race condition
watchdog: dw_wdt: Fix default timeout
watchdog: Don't use "proxy" headers
watchdog: it87_wdt: Don't use "proxy" headers
watchdog: renesas_wdt: Convert to DEFINE_SIMPLE_DEV_PM_OPS()
watchdog: iTCO_wdt: Report error if timeout configuration fails
watchdog: rti_wdt: Use of_reserved_mem_region_to_resource() for "memory-region"
dt-bindings: watchdog: nxp,pnx4008-wdt: allow clocks property
watchdog: ziirave_wdt: check record length in ziirave_firm_verify()

+87 -25
+3
Documentation/devicetree/bindings/watchdog/nxp,pnx4008-wdt.yaml
··· 19 19 reg: 20 20 maxItems: 1 21 21 22 + clocks: 23 + maxItems: 1 24 + 22 25 required: 23 26 - compatible 24 27 - reg
+2
drivers/watchdog/dw_wdt.c
··· 644 644 } else { 645 645 wdd->timeout = DW_WDT_DEFAULT_SECONDS; 646 646 watchdog_init_timeout(wdd, 0, dev); 647 + /* Limit timeout value to hardware constraints. */ 648 + dw_wdt_set_timeout(wdd, wdd->timeout); 647 649 } 648 650 649 651 platform_set_drvdata(pdev, dw_wdt);
+5 -1
drivers/watchdog/iTCO_wdt.c
··· 577 577 /* Check that the heartbeat value is within it's range; 578 578 if not reset to the default */ 579 579 if (iTCO_wdt_set_timeout(&p->wddev, heartbeat)) { 580 - iTCO_wdt_set_timeout(&p->wddev, WATCHDOG_TIMEOUT); 580 + ret = iTCO_wdt_set_timeout(&p->wddev, WATCHDOG_TIMEOUT); 581 + if (ret != 0) { 582 + dev_err(dev, "Failed to set watchdog timeout (%d)\n", WATCHDOG_TIMEOUT); 583 + return ret; 584 + } 581 585 dev_info(dev, "timeout value out of range, using %d\n", 582 586 WATCHDOG_TIMEOUT); 583 587 heartbeat = WATCHDOG_TIMEOUT;
+3 -1
drivers/watchdog/it87_wdt.c
··· 22 22 23 23 #include <linux/bits.h> 24 24 #include <linux/dmi.h> 25 + #include <linux/errno.h> 25 26 #include <linux/init.h> 26 27 #include <linux/io.h> 27 - #include <linux/kernel.h> 28 + #include <linux/ioport.h> 28 29 #include <linux/module.h> 29 30 #include <linux/moduleparam.h> 31 + #include <linux/printk.h> 30 32 #include <linux/types.h> 31 33 #include <linux/watchdog.h> 32 34
+4 -4
drivers/watchdog/renesas_wdt.c
··· 300 300 pm_runtime_disable(&pdev->dev); 301 301 } 302 302 303 - static int __maybe_unused rwdt_suspend(struct device *dev) 303 + static int rwdt_suspend(struct device *dev) 304 304 { 305 305 struct rwdt_priv *priv = dev_get_drvdata(dev); 306 306 ··· 310 310 return 0; 311 311 } 312 312 313 - static int __maybe_unused rwdt_resume(struct device *dev) 313 + static int rwdt_resume(struct device *dev) 314 314 { 315 315 struct rwdt_priv *priv = dev_get_drvdata(dev); 316 316 ··· 320 320 return 0; 321 321 } 322 322 323 - static SIMPLE_DEV_PM_OPS(rwdt_pm_ops, rwdt_suspend, rwdt_resume); 323 + static DEFINE_SIMPLE_DEV_PM_OPS(rwdt_pm_ops, rwdt_suspend, rwdt_resume); 324 324 325 325 static const struct of_device_id rwdt_ids[] = { 326 326 { .compatible = "renesas,rcar-gen2-wdt", }, ··· 334 334 .driver = { 335 335 .name = "renesas_wdt", 336 336 .of_match_table = rwdt_ids, 337 - .pm = &rwdt_pm_ops, 337 + .pm = pm_sleep_ptr(&rwdt_pm_ops), 338 338 }, 339 339 .probe = rwdt_probe, 340 340 .remove = rwdt_remove,
+3 -11
drivers/watchdog/rti_wdt.c
··· 15 15 #include <linux/module.h> 16 16 #include <linux/moduleparam.h> 17 17 #include <linux/of.h> 18 - #include <linux/of_address.h> 18 + #include <linux/of_reserved_mem.h> 19 19 #include <linux/platform_device.h> 20 20 #include <linux/pm_runtime.h> 21 21 #include <linux/types.h> ··· 214 214 struct rti_wdt_device *wdt; 215 215 struct clk *clk; 216 216 u32 last_ping = 0; 217 - struct device_node *node; 218 217 u32 reserved_mem_size; 219 218 struct resource res; 220 219 u32 *vaddr; ··· 298 299 } 299 300 } 300 301 301 - node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); 302 - if (node) { 303 - ret = of_address_to_resource(node, 0, &res); 304 - of_node_put(node); 305 - if (ret) { 306 - dev_err(dev, "No memory address assigned to the region.\n"); 307 - goto err_iomap; 308 - } 309 - 302 + ret = of_reserved_mem_region_to_resource(pdev->dev.of_node, 0, &res); 303 + if (!ret) { 310 304 /* 311 305 * If reserved memory is defined for watchdog reset cause. 312 306 * Readout the Power-on(PON) reason and pass to bootstatus.
+47 -3
drivers/watchdog/sbsa_gwdt.c
··· 75 75 #define SBSA_GWDT_VERSION_MASK 0xF 76 76 #define SBSA_GWDT_VERSION_SHIFT 16 77 77 78 + #define SBSA_GWDT_IMPL_MASK 0x7FF 79 + #define SBSA_GWDT_IMPL_SHIFT 0 80 + #define SBSA_GWDT_IMPL_MEDIATEK 0x426 81 + 78 82 /** 79 83 * struct sbsa_gwdt - Internal representation of the SBSA GWDT 80 84 * @wdd: kernel watchdog_device structure 81 85 * @clk: store the System Counter clock frequency, in Hz. 82 86 * @version: store the architecture version 87 + * @need_ws0_race_workaround: 88 + * indicate whether to adjust wdd->timeout to avoid a race with WS0 83 89 * @refresh_base: Virtual address of the watchdog refresh frame 84 90 * @control_base: Virtual address of the watchdog control frame 85 91 */ ··· 93 87 struct watchdog_device wdd; 94 88 u32 clk; 95 89 int version; 90 + bool need_ws0_race_workaround; 96 91 void __iomem *refresh_base; 97 92 void __iomem *control_base; 98 93 }; ··· 168 161 */ 169 162 sbsa_gwdt_reg_write(((u64)gwdt->clk / 2) * timeout, gwdt); 170 163 164 + /* 165 + * Some watchdog hardware has a race condition where it will ignore 166 + * sbsa_gwdt_keepalive() if it is called at the exact moment that a 167 + * timeout occurs and WS0 is being asserted. Unfortunately, the default 168 + * behavior of the watchdog core is very likely to trigger this race 169 + * when action=0 because it programs WOR to be half of the desired 170 + * timeout, and watchdog_next_keepalive() chooses the exact same time to 171 + * send keepalive pings. 172 + * 173 + * This triggers a race where sbsa_gwdt_keepalive() can be called right 174 + * as WS0 is being asserted, and affected hardware will ignore that 175 + * write and continue to assert WS0. After another (timeout / 2) 176 + * seconds, the same race happens again. If the driver wins then the 177 + * explicit refresh will reset WS0 to false but if the hardware wins, 178 + * then WS1 is asserted and the system resets. 179 + * 180 + * Avoid the problem by scheduling keepalive heartbeats one second later 181 + * than the WOR timeout. 182 + * 183 + * This workaround might not be needed in a future revision of the 184 + * hardware. 185 + */ 186 + if (gwdt->need_ws0_race_workaround) 187 + wdd->min_hw_heartbeat_ms = timeout * 500 + 1000; 188 + 171 189 return 0; 172 190 } 173 191 ··· 234 202 static void sbsa_gwdt_get_version(struct watchdog_device *wdd) 235 203 { 236 204 struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd); 237 - int ver; 205 + int iidr, ver, impl; 238 206 239 - ver = readl(gwdt->control_base + SBSA_GWDT_W_IIDR); 240 - ver = (ver >> SBSA_GWDT_VERSION_SHIFT) & SBSA_GWDT_VERSION_MASK; 207 + iidr = readl(gwdt->control_base + SBSA_GWDT_W_IIDR); 208 + ver = (iidr >> SBSA_GWDT_VERSION_SHIFT) & SBSA_GWDT_VERSION_MASK; 209 + impl = (iidr >> SBSA_GWDT_IMPL_SHIFT) & SBSA_GWDT_IMPL_MASK; 241 210 242 211 gwdt->version = ver; 212 + gwdt->need_ws0_race_workaround = 213 + !action && (impl == SBSA_GWDT_IMPL_MEDIATEK); 243 214 } 244 215 245 216 static int sbsa_gwdt_start(struct watchdog_device *wdd) ··· 333 298 wdd->max_hw_heartbeat_ms = U32_MAX / gwdt->clk * 1000; 334 299 else 335 300 wdd->max_hw_heartbeat_ms = GENMASK_ULL(47, 0) / gwdt->clk * 1000; 301 + 302 + if (gwdt->need_ws0_race_workaround) { 303 + /* 304 + * A timeout of 3 seconds means that WOR will be set to 1.5 305 + * seconds and the heartbeat will be scheduled every 2.5 306 + * seconds. 307 + */ 308 + wdd->min_timeout = 3; 309 + } 336 310 337 311 status = readl(cf_base + SBSA_GWDT_WCS); 338 312 if (status & SBSA_GWDT_WCS_WS1) {
+7 -1
drivers/watchdog/watchdog_core.h
··· 24 24 * This material is provided "AS-IS" and at no charge. 25 25 */ 26 26 27 - #include <linux/hrtimer.h> 27 + #include <linux/cdev.h> 28 + #include <linux/device.h> 29 + #include <linux/hrtimer_types.h> 30 + #include <linux/init.h> 28 31 #include <linux/kthread.h> 32 + #include <linux/mutex_types.h> 33 + #include <linux/types.h> 34 + #include <linux/watchdog.h> 29 35 30 36 #define MAX_DOGS 32 /* Maximum number of watchdog devices */ 31 37
+2
drivers/watchdog/watchdog_pretimeout.c
··· 7 7 #include <linux/slab.h> 8 8 #include <linux/spinlock.h> 9 9 #include <linux/string.h> 10 + #include <linux/sysfs.h> 11 + #include <linux/types.h> 10 12 #include <linux/watchdog.h> 11 13 12 14 #include "watchdog_core.h"
+3
drivers/watchdog/ziirave_wdt.c
··· 302 302 const u16 len = be16_to_cpu(rec->len); 303 303 const u32 addr = be32_to_cpu(rec->addr); 304 304 305 + if (len > sizeof(data)) 306 + return -EINVAL; 307 + 305 308 if (ziirave_firm_addr_readonly(addr)) 306 309 continue; 307 310
+8 -4
include/linux/watchdog.h
··· 9 9 #ifndef _LINUX_WATCHDOG_H 10 10 #define _LINUX_WATCHDOG_H 11 11 12 - 13 12 #include <linux/bitops.h> 14 - #include <linux/cdev.h> 15 - #include <linux/device.h> 16 - #include <linux/kernel.h> 13 + #include <linux/limits.h> 17 14 #include <linux/notifier.h> 15 + #include <linux/printk.h> 16 + #include <linux/types.h> 17 + 18 18 #include <uapi/linux/watchdog.h> 19 + 20 + struct attribute_group; 21 + struct device; 22 + struct module; 19 23 20 24 struct watchdog_ops; 21 25 struct watchdog_device;