Skip to content

Commit b6a3e14

Browse files
zhang-ruirafaeljw
authored andcommitted
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 4c23737 ("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 4c23737 ("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>
1 parent 116f2b3 commit b6a3e14

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

drivers/acpi/ec.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ static struct workqueue_struct *ec_query_wq;
196196
static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
197197
static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */
198198
static int EC_FLAGS_IGNORE_DSDT_GPE; /* Needs ECDT GPE as correction setting */
199+
static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
199200

200201
/* --------------------------------------------------------------------------
201202
* Logging/Debugging
@@ -501,6 +502,26 @@ static inline void __acpi_ec_disable_event(struct acpi_ec *ec)
501502
ec_log_drv("event blocked");
502503
}
503504

505+
/*
506+
* Process _Q events that might have accumulated in the EC.
507+
* Run with locked ec mutex.
508+
*/
509+
static 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+
504525
static void acpi_ec_enable_event(struct acpi_ec *ec)
505526
{
506527
unsigned long flags;
@@ -509,6 +530,10 @@ static void acpi_ec_enable_event(struct acpi_ec *ec)
509530
if (acpi_ec_started(ec))
510531
__acpi_ec_enable_event(ec);
511532
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);
512537
}
513538

514539
#ifdef CONFIG_PM_SLEEP
@@ -1781,6 +1806,31 @@ static int ec_flag_query_handshake(const struct dmi_system_id *id)
17811806
}
17821807
#endif
17831808

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+
*/
1826+
static 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+
17841834
/*
17851835
* Some ECDTs contain wrong register addresses.
17861836
* MSI MS-171F
@@ -1830,6 +1880,9 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = {
18301880
ec_honor_ecdt_gpe, "ASUS X580VD", {
18311881
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
18321882
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},
18331886
{},
18341887
};
18351888

0 commit comments

Comments
 (0)