Skip to content

Commit 5a802a7

Browse files
westerirafaeljw
authored andcommitted
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 <[email protected]> Reported-by: Alois Nespor <[email protected]> Reported-by: Yury Pakin <[email protected]> Reported-by: Ihor Chyhin <[email protected]> Signed-off-by: Mika Westerberg <[email protected]> Acked-by: Guenter Roeck <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 771c577 commit 5a802a7

File tree

1 file changed

+45
-27
lines changed

1 file changed

+45
-27
lines changed

drivers/acpi/acpi_watchdog.c

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,51 @@
1212
#define pr_fmt(fmt) "ACPI: watchdog: " fmt
1313

1414
#include <linux/acpi.h>
15-
#include <linux/dmi.h>
1615
#include <linux/ioport.h>
1716
#include <linux/platform_device.h>
1817

1918
#include "internal.h"
2019

21-
static const struct dmi_system_id acpi_watchdog_skip[] = {
22-
{
23-
/*
24-
* On Lenovo Z50-70 there are two issues with the WDAT
25-
* table. First some of the instructions use RTC SRAM
26-
* to store persistent information. This does not work well
27-
* with Linux RTC driver. Second, more important thing is
28-
* that the instructions do not actually reset the system.
29-
*
30-
* On this particular system iTCO_wdt seems to work just
31-
* fine so we prefer that over WDAT for now.
32-
*
33-
* See also https://bugzilla.kernel.org/show_bug.cgi?id=199033.
34-
*/
35-
.ident = "Lenovo Z50-70",
36-
.matches = {
37-
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
38-
DMI_MATCH(DMI_PRODUCT_NAME, "20354"),
39-
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Z50-70"),
40-
},
41-
},
42-
{}
43-
};
20+
#ifdef CONFIG_RTC_MC146818_LIB
21+
#include <linux/mc146818rtc.h>
22+
23+
/*
24+
* There are several systems where the WDAT table is accessing RTC SRAM to
25+
* store persistent information. This does not work well with the Linux RTC
26+
* driver so on those systems we skip WDAT driver and prefer iTCO_wdt
27+
* instead.
28+
*
29+
* See also https://bugzilla.kernel.org/show_bug.cgi?id=199033.
30+
*/
31+
static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat)
32+
{
33+
const struct acpi_wdat_entry *entries;
34+
int i;
35+
36+
entries = (struct acpi_wdat_entry *)(wdat + 1);
37+
for (i = 0; i < wdat->entries; i++) {
38+
const struct acpi_generic_address *gas;
39+
40+
gas = &entries[i].register_region;
41+
if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
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
55+
static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat)
56+
{
57+
return false;
58+
}
59+
#endif
4460

4561
static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
4662
{
@@ -50,16 +66,18 @@ static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
5066
if (acpi_disabled)
5167
return NULL;
5268

53-
if (dmi_check_system(acpi_watchdog_skip))
54-
return NULL;
55-
5669
status = acpi_get_table(ACPI_SIG_WDAT, 0,
5770
(struct acpi_table_header **)&wdat);
5871
if (ACPI_FAILURE(status)) {
5972
/* It is fine if there is no WDAT */
6073
return NULL;
6174
}
6275

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+
6381
return wdat;
6482
}
6583

0 commit comments

Comments
 (0)