133 lines
3.9 KiB
Diff
133 lines
3.9 KiB
Diff
|
From 1e45a10dbea00f3a9ead21a9b3d25ad00021261d Mon Sep 17 00:00:00 2001
|
||
|
Message-Id: <1e45a10dbea00f3a9ead21a9b3d25ad00021261d.1528777685.git.jan.steffens@gmail.com>
|
||
|
In-Reply-To: <9a5adbc45b1c7d43fe4b27936f2a6939660617a1.1528777685.git.jan.steffens@gmail.com>
|
||
|
References: <9a5adbc45b1c7d43fe4b27936f2a6939660617a1.1528777685.git.jan.steffens@gmail.com>
|
||
|
From: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||
|
Date: Tue, 22 May 2018 14:16:50 +0300
|
||
|
Subject: [PATCH 3/3] ACPI / watchdog: Prefer iTCO_wdt always when WDAT table
|
||
|
uses RTC SRAM
|
||
|
|
||
|
After we added quirk for Lenovo Z50-70 it turns out there are at least
|
||
|
two more systems where WDAT table includes instructions accessing RTC
|
||
|
SRAM. Instead of quirking each system separately, look for such
|
||
|
instructions in the table and automatically prefer iTCO_wdt if found.
|
||
|
|
||
|
Link: https://bugzilla.kernel.org/show_bug.cgi?id=199033
|
||
|
Reported-by: Arnold Guy <aurnoldg@gmail.com>
|
||
|
Reported-by: Alois Nespor <nespor@fssp.cz>
|
||
|
Reported-by: Yury Pakin <zxwarior@gmail.com>
|
||
|
Reported-by: Ihor Chyhin <ihorchyhin@ukr.net>
|
||
|
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||
|
Acked-by: Guenter Roeck <linux@roeck-us.net>
|
||
|
---
|
||
|
drivers/acpi/acpi_watchdog.c | 72 ++++++++++++++++++++++--------------
|
||
|
1 file changed, 45 insertions(+), 27 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/acpi/acpi_watchdog.c b/drivers/acpi/acpi_watchdog.c
|
||
|
index 4bde16fb97d8..95600309ce42 100644
|
||
|
--- a/drivers/acpi/acpi_watchdog.c
|
||
|
+++ b/drivers/acpi/acpi_watchdog.c
|
||
|
@@ -12,54 +12,72 @@
|
||
|
#define pr_fmt(fmt) "ACPI: watchdog: " fmt
|
||
|
|
||
|
#include <linux/acpi.h>
|
||
|
-#include <linux/dmi.h>
|
||
|
#include <linux/ioport.h>
|
||
|
#include <linux/platform_device.h>
|
||
|
|
||
|
#include "internal.h"
|
||
|
|
||
|
-static const struct dmi_system_id acpi_watchdog_skip[] = {
|
||
|
- {
|
||
|
- /*
|
||
|
- * On Lenovo Z50-70 there are two issues with the WDAT
|
||
|
- * table. First some of the instructions use RTC SRAM
|
||
|
- * to store persistent information. This does not work well
|
||
|
- * with Linux RTC driver. Second, more important thing is
|
||
|
- * that the instructions do not actually reset the system.
|
||
|
- *
|
||
|
- * On this particular system iTCO_wdt seems to work just
|
||
|
- * fine so we prefer that over WDAT for now.
|
||
|
- *
|
||
|
- * See also https://bugzilla.kernel.org/show_bug.cgi?id=199033.
|
||
|
- */
|
||
|
- .ident = "Lenovo Z50-70",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "20354"),
|
||
|
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Z50-70"),
|
||
|
- },
|
||
|
- },
|
||
|
- {}
|
||
|
-};
|
||
|
+#ifdef CONFIG_RTC_MC146818_LIB
|
||
|
+#include <linux/mc146818rtc.h>
|
||
|
+
|
||
|
+/*
|
||
|
+ * There are several systems where the WDAT table is accessing RTC SRAM to
|
||
|
+ * store persistent information. This does not work well with the Linux RTC
|
||
|
+ * driver so on those systems we skip WDAT driver and prefer iTCO_wdt
|
||
|
+ * instead.
|
||
|
+ *
|
||
|
+ * See also https://bugzilla.kernel.org/show_bug.cgi?id=199033.
|
||
|
+ */
|
||
|
+static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat)
|
||
|
+{
|
||
|
+ const struct acpi_wdat_entry *entries;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ entries = (struct acpi_wdat_entry *)(wdat + 1);
|
||
|
+ for (i = 0; i < wdat->entries; i++) {
|
||
|
+ const struct acpi_generic_address *gas;
|
||
|
+
|
||
|
+ gas = &entries[i].register_region;
|
||
|
+ if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
|
||
|
+ switch (gas->address) {
|
||
|
+ case RTC_PORT(0):
|
||
|
+ case RTC_PORT(1):
|
||
|
+ case RTC_PORT(2):
|
||
|
+ case RTC_PORT(3):
|
||
|
+ return true;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return false;
|
||
|
+}
|
||
|
+#else
|
||
|
+static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat)
|
||
|
+{
|
||
|
+ return false;
|
||
|
+}
|
||
|
+#endif
|
||
|
|
||
|
static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
|
||
|
{
|
||
|
const struct acpi_table_wdat *wdat = NULL;
|
||
|
acpi_status status;
|
||
|
|
||
|
if (acpi_disabled)
|
||
|
return NULL;
|
||
|
|
||
|
- if (dmi_check_system(acpi_watchdog_skip))
|
||
|
- return NULL;
|
||
|
-
|
||
|
status = acpi_get_table(ACPI_SIG_WDAT, 0,
|
||
|
(struct acpi_table_header **)&wdat);
|
||
|
if (ACPI_FAILURE(status)) {
|
||
|
/* It is fine if there is no WDAT */
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
+ if (acpi_watchdog_uses_rtc(wdat)) {
|
||
|
+ pr_info("Skipping WDAT on this system because it uses RTC SRAM\n");
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
return wdat;
|
||
|
}
|
||
|
|
||
|
--
|
||
|
2.17.1
|
||
|
|