hc
2024-05-14 bedbef8ad3e75a304af6361af235302bcc61d06b
kernel/drivers/watchdog/wdat_wdt.c
....@@ -1,12 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * ACPI Hardware Watchdog (WDAT) driver.
34 *
45 * Copyright (C) 2016, Intel Corporation
56 * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License version 2 as
9
- * published by the Free Software Foundation.
107 */
118
129 #include <linux/acpi.h>
....@@ -56,6 +53,13 @@
5653 module_param(nowayout, bool, 0);
5754 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
5855 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
56
+
57
+#define WDAT_DEFAULT_TIMEOUT 30
58
+
59
+static int timeout = WDAT_DEFAULT_TIMEOUT;
60
+module_param(timeout, int, 0);
61
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default="
62
+ __MODULE_STRING(WDAT_DEFAULT_TIMEOUT) ")");
5963
6064 static int wdat_wdt_read(struct wdat_wdt *wdat,
6165 const struct wdat_instruction *instr, u32 *value)
....@@ -205,7 +209,7 @@
205209 * WDAT specification says that the watchdog is required to reboot
206210 * the system when it fires. However, it also states that it is
207211 * recommeded to make it configurable through hardware register. We
208
- * enable reboot now if it is configrable, just in case.
212
+ * enable reboot now if it is configurable, just in case.
209213 */
210214 ret = wdat_wdt_run_action(wdat, ACPI_WDAT_SET_REBOOT, 0, NULL);
211215 if (ret && ret != -EOPNOTSUPP) {
....@@ -287,7 +291,7 @@
287291 struct wdat_wdt *wdat = to_wdat_wdt(wdd);
288292 u32 periods = 0;
289293
290
- wdat_wdt_run_action(wdat, ACPI_WDAT_GET_COUNTDOWN, 0, &periods);
294
+ wdat_wdt_run_action(wdat, ACPI_WDAT_GET_CURRENT_COUNTDOWN, 0, &periods);
291295 return periods * wdat->period / 1000;
292296 }
293297
....@@ -308,6 +312,7 @@
308312
309313 static int wdat_wdt_probe(struct platform_device *pdev)
310314 {
315
+ struct device *dev = &pdev->dev;
311316 const struct acpi_wdat_entry *entries;
312317 const struct acpi_table_wdat *tbl;
313318 struct wdat_wdt *wdat;
....@@ -321,11 +326,11 @@
321326 if (ACPI_FAILURE(status))
322327 return -ENODEV;
323328
324
- wdat = devm_kzalloc(&pdev->dev, sizeof(*wdat), GFP_KERNEL);
329
+ wdat = devm_kzalloc(dev, sizeof(*wdat), GFP_KERNEL);
325330 if (!wdat)
326331 return -ENOMEM;
327332
328
- regs = devm_kcalloc(&pdev->dev, pdev->num_resources, sizeof(*regs),
333
+ regs = devm_kcalloc(dev, pdev->num_resources, sizeof(*regs),
329334 GFP_KERNEL);
330335 if (!regs)
331336 return -ENOMEM;
....@@ -350,15 +355,15 @@
350355
351356 res = &pdev->resource[i];
352357 if (resource_type(res) == IORESOURCE_MEM) {
353
- reg = devm_ioremap_resource(&pdev->dev, res);
358
+ reg = devm_ioremap_resource(dev, res);
354359 if (IS_ERR(reg))
355360 return PTR_ERR(reg);
356361 } else if (resource_type(res) == IORESOURCE_IO) {
357
- reg = devm_ioport_map(&pdev->dev, res->start, 1);
362
+ reg = devm_ioport_map(dev, res->start, 1);
358363 if (!reg)
359364 return -ENOMEM;
360365 } else {
361
- dev_err(&pdev->dev, "Unsupported resource\n");
366
+ dev_err(dev, "Unsupported resource\n");
362367 return -EINVAL;
363368 }
364369
....@@ -376,12 +381,11 @@
376381
377382 action = entries[i].action;
378383 if (action >= MAX_WDAT_ACTIONS) {
379
- dev_dbg(&pdev->dev, "Skipping unknown action: %u\n",
380
- action);
384
+ dev_dbg(dev, "Skipping unknown action: %u\n", action);
381385 continue;
382386 }
383387
384
- instr = devm_kzalloc(&pdev->dev, sizeof(*instr), GFP_KERNEL);
388
+ instr = devm_kzalloc(dev, sizeof(*instr), GFP_KERNEL);
385389 if (!instr)
386390 return -ENOMEM;
387391
....@@ -398,7 +402,7 @@
398402 } else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
399403 r.flags = IORESOURCE_IO;
400404 } else {
401
- dev_dbg(&pdev->dev, "Unsupported address space: %d\n",
405
+ dev_dbg(dev, "Unsupported address space: %d\n",
402406 gas->space_id);
403407 continue;
404408 }
....@@ -413,14 +417,15 @@
413417 }
414418
415419 if (!instr->reg) {
416
- dev_err(&pdev->dev, "I/O resource not found\n");
420
+ dev_err(dev, "I/O resource not found\n");
417421 return -EINVAL;
418422 }
419423
420424 instructions = wdat->instructions[action];
421425 if (!instructions) {
422
- instructions = devm_kzalloc(&pdev->dev,
423
- sizeof(*instructions), GFP_KERNEL);
426
+ instructions = devm_kzalloc(dev,
427
+ sizeof(*instructions),
428
+ GFP_KERNEL);
424429 if (!instructions)
425430 return -ENOMEM;
426431
....@@ -440,8 +445,25 @@
440445
441446 platform_set_drvdata(pdev, wdat);
442447
448
+ /*
449
+ * Set initial timeout so that userspace has time to configure the
450
+ * watchdog properly after it has opened the device. In some cases
451
+ * the BIOS default is too short and causes immediate reboot.
452
+ */
453
+ if (timeout * 1000 < wdat->wdd.min_hw_heartbeat_ms ||
454
+ timeout * 1000 > wdat->wdd.max_hw_heartbeat_ms) {
455
+ dev_warn(dev, "Invalid timeout %d given, using %d\n",
456
+ timeout, WDAT_DEFAULT_TIMEOUT);
457
+ timeout = WDAT_DEFAULT_TIMEOUT;
458
+ }
459
+
460
+ ret = wdat_wdt_set_timeout(&wdat->wdd, timeout);
461
+ if (ret)
462
+ return ret;
463
+
443464 watchdog_set_nowayout(&wdat->wdd, nowayout);
444
- return devm_watchdog_register_device(&pdev->dev, &wdat->wdd);
465
+ watchdog_stop_on_reboot(&wdat->wdd);
466
+ return devm_watchdog_register_device(dev, &wdat->wdd);
445467 }
446468
447469 #ifdef CONFIG_PM_SLEEP