From bedbef8ad3e75a304af6361af235302bcc61d06b Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 14 May 2024 06:39:01 +0000 Subject: [PATCH] 修改内核路径 --- kernel/drivers/watchdog/wdat_wdt.c | 60 +++++++++++++++++++++++++++++++++++++++++------------------- 1 files changed, 41 insertions(+), 19 deletions(-) diff --git a/kernel/drivers/watchdog/wdat_wdt.c b/kernel/drivers/watchdog/wdat_wdt.c index 9d91ed5..c60723f 100644 --- a/kernel/drivers/watchdog/wdat_wdt.c +++ b/kernel/drivers/watchdog/wdat_wdt.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * ACPI Hardware Watchdog (WDAT) driver. * * Copyright (C) 2016, Intel Corporation * Author: Mika Westerberg <mika.westerberg@linux.intel.com> - * - * 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. */ #include <linux/acpi.h> @@ -56,6 +53,13 @@ module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +#define WDAT_DEFAULT_TIMEOUT 30 + +static int timeout = WDAT_DEFAULT_TIMEOUT; +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=" + __MODULE_STRING(WDAT_DEFAULT_TIMEOUT) ")"); static int wdat_wdt_read(struct wdat_wdt *wdat, const struct wdat_instruction *instr, u32 *value) @@ -205,7 +209,7 @@ * WDAT specification says that the watchdog is required to reboot * the system when it fires. However, it also states that it is * recommeded to make it configurable through hardware register. We - * enable reboot now if it is configrable, just in case. + * enable reboot now if it is configurable, just in case. */ ret = wdat_wdt_run_action(wdat, ACPI_WDAT_SET_REBOOT, 0, NULL); if (ret && ret != -EOPNOTSUPP) { @@ -287,7 +291,7 @@ struct wdat_wdt *wdat = to_wdat_wdt(wdd); u32 periods = 0; - wdat_wdt_run_action(wdat, ACPI_WDAT_GET_COUNTDOWN, 0, &periods); + wdat_wdt_run_action(wdat, ACPI_WDAT_GET_CURRENT_COUNTDOWN, 0, &periods); return periods * wdat->period / 1000; } @@ -308,6 +312,7 @@ static int wdat_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; const struct acpi_wdat_entry *entries; const struct acpi_table_wdat *tbl; struct wdat_wdt *wdat; @@ -321,11 +326,11 @@ if (ACPI_FAILURE(status)) return -ENODEV; - wdat = devm_kzalloc(&pdev->dev, sizeof(*wdat), GFP_KERNEL); + wdat = devm_kzalloc(dev, sizeof(*wdat), GFP_KERNEL); if (!wdat) return -ENOMEM; - regs = devm_kcalloc(&pdev->dev, pdev->num_resources, sizeof(*regs), + regs = devm_kcalloc(dev, pdev->num_resources, sizeof(*regs), GFP_KERNEL); if (!regs) return -ENOMEM; @@ -350,15 +355,15 @@ res = &pdev->resource[i]; if (resource_type(res) == IORESOURCE_MEM) { - reg = devm_ioremap_resource(&pdev->dev, res); + reg = devm_ioremap_resource(dev, res); if (IS_ERR(reg)) return PTR_ERR(reg); } else if (resource_type(res) == IORESOURCE_IO) { - reg = devm_ioport_map(&pdev->dev, res->start, 1); + reg = devm_ioport_map(dev, res->start, 1); if (!reg) return -ENOMEM; } else { - dev_err(&pdev->dev, "Unsupported resource\n"); + dev_err(dev, "Unsupported resource\n"); return -EINVAL; } @@ -376,12 +381,11 @@ action = entries[i].action; if (action >= MAX_WDAT_ACTIONS) { - dev_dbg(&pdev->dev, "Skipping unknown action: %u\n", - action); + dev_dbg(dev, "Skipping unknown action: %u\n", action); continue; } - instr = devm_kzalloc(&pdev->dev, sizeof(*instr), GFP_KERNEL); + instr = devm_kzalloc(dev, sizeof(*instr), GFP_KERNEL); if (!instr) return -ENOMEM; @@ -398,7 +402,7 @@ } else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { r.flags = IORESOURCE_IO; } else { - dev_dbg(&pdev->dev, "Unsupported address space: %d\n", + dev_dbg(dev, "Unsupported address space: %d\n", gas->space_id); continue; } @@ -413,14 +417,15 @@ } if (!instr->reg) { - dev_err(&pdev->dev, "I/O resource not found\n"); + dev_err(dev, "I/O resource not found\n"); return -EINVAL; } instructions = wdat->instructions[action]; if (!instructions) { - instructions = devm_kzalloc(&pdev->dev, - sizeof(*instructions), GFP_KERNEL); + instructions = devm_kzalloc(dev, + sizeof(*instructions), + GFP_KERNEL); if (!instructions) return -ENOMEM; @@ -440,8 +445,25 @@ platform_set_drvdata(pdev, wdat); + /* + * Set initial timeout so that userspace has time to configure the + * watchdog properly after it has opened the device. In some cases + * the BIOS default is too short and causes immediate reboot. + */ + if (timeout * 1000 < wdat->wdd.min_hw_heartbeat_ms || + timeout * 1000 > wdat->wdd.max_hw_heartbeat_ms) { + dev_warn(dev, "Invalid timeout %d given, using %d\n", + timeout, WDAT_DEFAULT_TIMEOUT); + timeout = WDAT_DEFAULT_TIMEOUT; + } + + ret = wdat_wdt_set_timeout(&wdat->wdd, timeout); + if (ret) + return ret; + watchdog_set_nowayout(&wdat->wdd, nowayout); - return devm_watchdog_register_device(&pdev->dev, &wdat->wdd); + watchdog_stop_on_reboot(&wdat->wdd); + return devm_watchdog_register_device(dev, &wdat->wdd); } #ifdef CONFIG_PM_SLEEP -- Gitblit v1.6.2