On Monday, April 23, 2018 1:16:03 PM CEST Mika Westerberg wrote: > 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@xxxxxxxxx> > Link: https://bugzilla.kernel.org/show_bug.cgi?id=199033 > Signed-off-by: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx> > --- > 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; > } > Applied and merged into 4.17-rc3, thanks! -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html