Commit bb5850b1 authored by Lv Zheng's avatar Lv Zheng Committed by Ben Hutchings

ACPI / EC: Fix regression due to conflicting firmware behavior between Samsung and Acer.

commit 79149001 upstream.

It is reported that Samsung laptops that need to poll events are broken by
the following commit:
 Commit 3afcf2ec
 Subject: ACPI / EC: Add support to disallow QR_EC to be issued when SCI_EVT isn't set

The behaviors of the 2 vendor firmwares are conflict:
 1. Acer: OSPM shouldn't issue QR_EC unless SCI_EVT is set, firmware
         automatically sets SCI_EVT as long as there is event queued up.
 2. Samsung: OSPM should issue QR_EC whatever SCI_EVT is set, firmware
            returns 0 when there is no event queued up.

This patch is a quick fix to distinguish the behaviors to make Acer
behavior only effective for Acer EC firmware so that the breakages on
Samsung EC firmware can be avoided.

Fixes: 3afcf2ec (ACPI / EC: Add support to disallow QR_EC to be issued ...)
Link: https://bugzilla.kernel.org/show_bug.cgi?id=44161Reported-and-tested-by: default avatarOrtwin Glück <odi@odi.ch>
Signed-off-by: default avatarLv Zheng <lv.zheng@intel.com>
[ rjw : Subject ]
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
Cc: Kamal Mostafa <kamal@canonical.com>
parent 309adf3c
...@@ -129,6 +129,7 @@ static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */ ...@@ -129,6 +129,7 @@ static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */ static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
Transaction Management Transaction Management
...@@ -206,13 +207,8 @@ static bool advance_transaction(struct acpi_ec *ec) ...@@ -206,13 +207,8 @@ static bool advance_transaction(struct acpi_ec *ec)
} }
return wakeup; return wakeup;
} else { } else {
/* if (EC_FLAGS_QUERY_HANDSHAKE &&
* There is firmware refusing to respond QR_EC when SCI_EVT !(status & ACPI_EC_FLAG_SCI) &&
* is not set, for which case, we complete the QR_EC
* without issuing it to the firmware.
* https://bugzilla.kernel.org/show_bug.cgi?id=86211
*/
if (!(status & ACPI_EC_FLAG_SCI) &&
(t->command == ACPI_EC_COMMAND_QUERY)) { (t->command == ACPI_EC_COMMAND_QUERY)) {
t->flags |= ACPI_EC_COMMAND_POLL; t->flags |= ACPI_EC_COMMAND_POLL;
t->rdata[t->ri++] = 0x00; t->rdata[t->ri++] = 0x00;
...@@ -986,6 +982,18 @@ static int ec_enlarge_storm_threshold(const struct dmi_system_id *id) ...@@ -986,6 +982,18 @@ static int ec_enlarge_storm_threshold(const struct dmi_system_id *id)
return 0; return 0;
} }
/*
* Acer EC firmware refuses to respond QR_EC when SCI_EVT is not set, for
* which case, we complete the QR_EC without issuing it to the firmware.
* https://bugzilla.kernel.org/show_bug.cgi?id=86211
*/
static int ec_flag_query_handshake(const struct dmi_system_id *id)
{
pr_debug("Detected the EC firmware requiring QR_EC issued when SCI_EVT set\n");
EC_FLAGS_QUERY_HANDSHAKE = 1;
return 0;
}
/* /*
* On some hardware it is necessary to clear events accumulated by the EC during * On some hardware it is necessary to clear events accumulated by the EC during
* sleep. These ECs stop reporting GPEs until they are manually polled, if too * sleep. These ECs stop reporting GPEs until they are manually polled, if too
...@@ -1052,6 +1060,9 @@ static struct dmi_system_id __initdata ec_dmi_table[] = { ...@@ -1052,6 +1060,9 @@ static struct dmi_system_id __initdata ec_dmi_table[] = {
{ {
ec_clear_on_resume, "Samsung hardware", { ec_clear_on_resume, "Samsung hardware", {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL}, DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
{
ec_flag_query_handshake, "Acer hardware", {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"), }, NULL},
{}, {},
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment