12
12
#define pr_fmt (fmt ) "ACPI: watchdog: " fmt
13
13
14
14
#include <linux/acpi.h>
15
- #include <linux/dmi.h>
16
15
#include <linux/ioport.h>
17
16
#include <linux/platform_device.h>
18
17
19
18
#include "internal.h"
20
19
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
44
60
45
61
static const struct acpi_table_wdat * acpi_watchdog_get_wdat (void )
46
62
{
@@ -50,16 +66,18 @@ static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
50
66
if (acpi_disabled )
51
67
return NULL ;
52
68
53
- if (dmi_check_system (acpi_watchdog_skip ))
54
- return NULL ;
55
-
56
69
status = acpi_get_table (ACPI_SIG_WDAT , 0 ,
57
70
(struct acpi_table_header * * )& wdat );
58
71
if (ACPI_FAILURE (status )) {
59
72
/* It is fine if there is no WDAT */
60
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
81
return wdat ;
64
82
}
65
83
0 commit comments