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