summaryrefslogtreecommitdiff
path: root/ACPI-watchdog-Prefer-iTCO_wdt-on-Lenovo-Z50-70.patch
diff options
context:
space:
mode:
authorjc_gargma <jc_gargma@iserlohn-fortress.net>2018-05-30 01:52:29 -0700
committerjc_gargma <jc_gargma@iserlohn-fortress.net>2018-05-30 01:52:29 -0700
commite9782577288df8f7be9e6001f9ce16f964b9a765 (patch)
tree28143dca32c4b00c5309d6481a6d87e87967469d /ACPI-watchdog-Prefer-iTCO_wdt-on-Lenovo-Z50-70.patch
parentUpdated to 4.16.11.a (diff)
downloadlinux-libre-hardened-ck-e9782577288df8f7be9e6001f9ce16f964b9a765.tar.xz
Updated to 4.16.12.a
Diffstat (limited to 'ACPI-watchdog-Prefer-iTCO_wdt-on-Lenovo-Z50-70.patch')
-rw-r--r--ACPI-watchdog-Prefer-iTCO_wdt-on-Lenovo-Z50-70.patch117
1 files changed, 117 insertions, 0 deletions
diff --git a/ACPI-watchdog-Prefer-iTCO_wdt-on-Lenovo-Z50-70.patch b/ACPI-watchdog-Prefer-iTCO_wdt-on-Lenovo-Z50-70.patch
new file mode 100644
index 0000000..1855da1
--- /dev/null
+++ b/ACPI-watchdog-Prefer-iTCO_wdt-on-Lenovo-Z50-70.patch
@@ -0,0 +1,117 @@
+From a0a37862a4e1844793d39aca9ccb8fecbdcb8659 Mon Sep 17 00:00:00 2001
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+Date: Mon, 23 Apr 2018 14:16:03 +0300
+Subject: [PATCH] ACPI / watchdog: Prefer iTCO_wdt on Lenovo Z50-70
+
+WDAT table on Lenovo Z50-70 is using RTC SRAM (ports 0x70 and 0x71) to
+store state of the timer. This conflicts with Linux RTC driver
+(rtc-cmos.c) who fails to reserve those ports for itself preventing RTC
+from functioning. In addition the WDAT table seems not to be fully
+functional because it does not reset the system when the watchdog times
+out.
+
+On this system iTCO_wdt works just fine so we simply prefer to use it
+instead of WDAT. This makes RTC working again and also results working
+watchdog via iTCO_wdt.
+
+Reported-by: Peter Milley <pbmilley@gmail.com>
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=199033
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ drivers/acpi/acpi_watchdog.c | 59 ++++++++++++++++++++++++++++++------
+ 1 file changed, 49 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/acpi/acpi_watchdog.c b/drivers/acpi/acpi_watchdog.c
+index ebb626ffb5fa..4bde16fb97d8 100644
+--- a/drivers/acpi/acpi_watchdog.c
++++ b/drivers/acpi/acpi_watchdog.c
+@@ -12,23 +12,64 @@
+ #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"),
++ },
++ },
++ {}
++};
++
++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;
++ }
++
++ return wdat;
++}
++
+ /**
+ * Returns true if this system should prefer ACPI based watchdog instead of
+ * the native one (which are typically the same hardware).
+ */
+ bool acpi_has_watchdog(void)
+ {
+- struct acpi_table_header hdr;
+-
+- if (acpi_disabled)
+- return false;
+-
+- return ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_WDAT, 0, &hdr));
++ return !!acpi_watchdog_get_wdat();
+ }
+ EXPORT_SYMBOL_GPL(acpi_has_watchdog);
+
+@@ -41,12 +82,10 @@ void __init acpi_watchdog_init(void)
+ struct platform_device *pdev;
+ struct resource *resources;
+ size_t nresources = 0;
+- acpi_status status;
+ int i;
+
+- status = acpi_get_table(ACPI_SIG_WDAT, 0,
+- (struct acpi_table_header **)&wdat);
+- if (ACPI_FAILURE(status)) {
++ wdat = acpi_watchdog_get_wdat();
++ if (!wdat) {
+ /* It is fine if there is no WDAT */
+ return;
+ }
+--
+2.17.0
+