aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2018-05-22 07:16:50 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-05-24 04:52:49 -0400
commit5a802a7a285c8877ca872e44eeb0f06afcb5212f (patch)
tree7bf84f2a8a566ab35e45733dc2285cff9d497243
parent771c577c23bac90597c685971d7297ea00f99d11 (diff)
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> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/acpi_watchdog.c72
1 files 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,35 +12,51 @@
12#define pr_fmt(fmt) "ACPI: watchdog: " fmt 12#define pr_fmt(fmt) "ACPI: watchdog: " fmt
13 13
14#include <linux/acpi.h> 14#include <linux/acpi.h>
15#include <linux/dmi.h>
16#include <linux/ioport.h> 15#include <linux/ioport.h>
17#include <linux/platform_device.h> 16#include <linux/platform_device.h>
18 17
19#include "internal.h" 18#include "internal.h"
20 19
21static const struct dmi_system_id acpi_watchdog_skip[] = { 20#ifdef CONFIG_RTC_MC146818_LIB
22 { 21#include <linux/mc146818rtc.h>
23 /* 22
24 * On Lenovo Z50-70 there are two issues with the WDAT 23/*
25 * table. First some of the instructions use RTC SRAM 24 * There are several systems where the WDAT table is accessing RTC SRAM to
26 * to store persistent information. This does not work well 25 * store persistent information. This does not work well with the Linux RTC
27 * with Linux RTC driver. Second, more important thing is 26 * driver so on those systems we skip WDAT driver and prefer iTCO_wdt
28 * that the instructions do not actually reset the system. 27 * instead.
29 * 28 *
30 * On this particular system iTCO_wdt seems to work just 29 * See also https://bugzilla.kernel.org/show_bug.cgi?id=199033.
31 * fine so we prefer that over WDAT for now. 30 */
32 * 31static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat)
33 * See also https://bugzilla.kernel.org/show_bug.cgi?id=199033. 32{
34 */ 33 const struct acpi_wdat_entry *entries;
35 .ident = "Lenovo Z50-70", 34 int i;
36 .matches = { 35
37 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 36 entries = (struct acpi_wdat_entry *)(wdat + 1);
38 DMI_MATCH(DMI_PRODUCT_NAME, "20354"), 37 for (i = 0; i < wdat->entries; i++) {
39 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Z50-70"), 38 const struct acpi_generic_address *gas;
40 }, 39
41 }, 40 gas = &entries[i].register_region;
42 {} 41 if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
43}; 42 switch (gas->address) {
43 case RTC_PORT(0):
44 case RTC_PORT(1):
45 case RTC_PORT(2):
46 case RTC_PORT(3):
47 return true;
48 }
49 }
50 }
51
52 return false;
53}
54#else
55static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat)
56{
57 return false;
58}
59#endif
44 60
45static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void) 61static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
46{ 62{
@@ -50,9 +66,6 @@ static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
50 if (acpi_disabled) 66 if (acpi_disabled)
51 return NULL; 67 return NULL;
52 68
53 if (dmi_check_system(acpi_watchdog_skip))
54 return NULL;
55
56 status = acpi_get_table(ACPI_SIG_WDAT, 0, 69 status = acpi_get_table(ACPI_SIG_WDAT, 0,
57 (struct acpi_table_header **)&wdat); 70 (struct acpi_table_header **)&wdat);
58 if (ACPI_FAILURE(status)) { 71 if (ACPI_FAILURE(status)) {
@@ -60,6 +73,11 @@ static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
60 return NULL; 73 return NULL;
61 } 74 }
62 75
76 if (acpi_watchdog_uses_rtc(wdat)) {
77 pr_info("Skipping WDAT on this system because it uses RTC SRAM\n");
78 return NULL;
79 }
80
63 return wdat; 81 return wdat;
64} 82}
65 83