aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhang Rui <rui.zhang@intel.com>2019-02-01 01:13:41 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-02-01 06:56:49 -0500
commitb6a3e1475b0220378ad32bdf4d8692f058b1fc03 (patch)
tree42326013e8801c3bae214f7c4a4257c498d9687d
parent116f2b348b7454ff377b779076b3ead7d47ccb7b (diff)
Revert "ACPI / EC: Remove old CLEAR_ON_RESUME quirk"
On some Samsung 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 many events are accumulated. Thus the CLEAR_ON_RESUME quirk is introduced to send EC query commands unconditionally after resume to clear all the EC query events on those platforms. Later, commit 4c237371f290 ("ACPI / EC: Remove old CLEAR_ON_RESUME quirk") removes the CLEAR_ON_RESUME quirk because we thought the new EC IRQ polling logic should handle this case. Now it has been proved that the EC IRQ Polling logic does not fix the issue actually because we got regression report on these Samsung platforms after removing the quirk. Thus revert commit 4c237371f290 ("ACPI / EC: Remove old CLEAR_ON_RESUME quirk") to introduce back the Samsung quirk in this patch. Link: https://bugzilla.kernel.org/show_bug.cgi?id=44161 Tested-by: Ortwin Glück <odi@odi.ch> Tested-by: Francisco Cribari <cribari@gmail.com> Tested-by: Balazs Varga <balazs4web@gmail.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/ec.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 9c40f6715c69..48d4815603e5 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -196,6 +196,7 @@ static struct workqueue_struct *ec_query_wq;
196static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */ 196static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
197static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */ 197static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */
198static int EC_FLAGS_IGNORE_DSDT_GPE; /* Needs ECDT GPE as correction setting */ 198static int EC_FLAGS_IGNORE_DSDT_GPE; /* Needs ECDT GPE as correction setting */
199static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
199 200
200/* -------------------------------------------------------------------------- 201/* --------------------------------------------------------------------------
201 * Logging/Debugging 202 * Logging/Debugging
@@ -501,6 +502,26 @@ static inline void __acpi_ec_disable_event(struct acpi_ec *ec)
501 ec_log_drv("event blocked"); 502 ec_log_drv("event blocked");
502} 503}
503 504
505/*
506 * Process _Q events that might have accumulated in the EC.
507 * Run with locked ec mutex.
508 */
509static void acpi_ec_clear(struct acpi_ec *ec)
510{
511 int i, status;
512 u8 value = 0;
513
514 for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) {
515 status = acpi_ec_query(ec, &value);
516 if (status || !value)
517 break;
518 }
519 if (unlikely(i == ACPI_EC_CLEAR_MAX))
520 pr_warn("Warning: Maximum of %d stale EC events cleared\n", i);
521 else
522 pr_info("%d stale EC events cleared\n", i);
523}
524
504static void acpi_ec_enable_event(struct acpi_ec *ec) 525static void acpi_ec_enable_event(struct acpi_ec *ec)
505{ 526{
506 unsigned long flags; 527 unsigned long flags;
@@ -509,6 +530,10 @@ static void acpi_ec_enable_event(struct acpi_ec *ec)
509 if (acpi_ec_started(ec)) 530 if (acpi_ec_started(ec))
510 __acpi_ec_enable_event(ec); 531 __acpi_ec_enable_event(ec);
511 spin_unlock_irqrestore(&ec->lock, flags); 532 spin_unlock_irqrestore(&ec->lock, flags);
533
534 /* Drain additional events if hardware requires that */
535 if (EC_FLAGS_CLEAR_ON_RESUME)
536 acpi_ec_clear(ec);
512} 537}
513 538
514#ifdef CONFIG_PM_SLEEP 539#ifdef CONFIG_PM_SLEEP
@@ -1782,6 +1807,31 @@ static int ec_flag_query_handshake(const struct dmi_system_id *id)
1782#endif 1807#endif
1783 1808
1784/* 1809/*
1810 * On some hardware it is necessary to clear events accumulated by the EC during
1811 * sleep. These ECs stop reporting GPEs until they are manually polled, if too
1812 * many events are accumulated. (e.g. Samsung Series 5/9 notebooks)
1813 *
1814 * https://bugzilla.kernel.org/show_bug.cgi?id=44161
1815 *
1816 * Ideally, the EC should also be instructed NOT to accumulate events during
1817 * sleep (which Windows seems to do somehow), but the interface to control this
1818 * behaviour is not known at this time.
1819 *
1820 * Models known to be affected are Samsung 530Uxx/535Uxx/540Uxx/550Pxx/900Xxx,
1821 * however it is very likely that other Samsung models are affected.
1822 *
1823 * On systems which don't accumulate _Q events during sleep, this extra check
1824 * should be harmless.
1825 */
1826static int ec_clear_on_resume(const struct dmi_system_id *id)
1827{
1828 pr_debug("Detected system needing EC poll on resume.\n");
1829 EC_FLAGS_CLEAR_ON_RESUME = 1;
1830 ec_event_clearing = ACPI_EC_EVT_TIMING_STATUS;
1831 return 0;
1832}
1833
1834/*
1785 * Some ECDTs contain wrong register addresses. 1835 * Some ECDTs contain wrong register addresses.
1786 * MSI MS-171F 1836 * MSI MS-171F
1787 * https://bugzilla.kernel.org/show_bug.cgi?id=12461 1837 * https://bugzilla.kernel.org/show_bug.cgi?id=12461
@@ -1830,6 +1880,9 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = {
1830 ec_honor_ecdt_gpe, "ASUS X580VD", { 1880 ec_honor_ecdt_gpe, "ASUS X580VD", {
1831 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 1881 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1832 DMI_MATCH(DMI_PRODUCT_NAME, "X580VD"),}, NULL}, 1882 DMI_MATCH(DMI_PRODUCT_NAME, "X580VD"),}, NULL},
1883 {
1884 ec_clear_on_resume, "Samsung hardware", {
1885 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
1833 {}, 1886 {},
1834}; 1887};
1835 1888