summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/ec.c
diff options
context:
space:
mode:
authorKieran Clancy <clancy.kieran@gmail.com>2014-02-28 09:12:28 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-03-06 07:27:23 -0500
commitad332c8a45330d170bb38b95209de449b31cd1b4 (patch)
tree5e2135b0fd8039c5d2fe7b204fb8d3d1b6aa7d8f /drivers/acpi/ec.c
parentcfbf8d4857c26a8a307fb7cd258074c9dcd8c691 (diff)
ACPI / EC: Clear stale EC events on Samsung systems
A number of Samsung notebooks (530Uxx/535Uxx/540Uxx/550Pxx/900Xxx/etc) continue to log events during sleep (lid open/close, AC plug/unplug, battery level change), which accumulate in the EC until a buffer fills. After the buffer is full (tests suggest it holds 8 events), GPEs stop being triggered for new events. This state persists on wake or even on power cycle, and prevents new events from being registered until the EC is manually polled. This is the root cause of a number of bugs, including AC not being detected properly, lid close not triggering suspend, and low ambient light not triggering the keyboard backlight. The bug also seemed to be responsible for performance issues on at least one user's machine. Juan Manuel Cabo found the cause of bug and the workaround of polling the EC manually on wake. The loop which clears the stale events is based on an earlier patch by Lan Tianyu (see referenced attachment). This patch: - Adds a function acpi_ec_clear() which polls the EC for stale _Q events at most ACPI_EC_CLEAR_MAX (currently 100) times. A warning is logged if this limit is reached. - Adds a flag EC_FLAGS_CLEAR_ON_RESUME which is set to 1 if the DMI system vendor is Samsung. This check could be replaced by several more specific DMI vendor/product pairs, but it's likely that the bug affects more Samsung products than just the five series mentioned above. Further, it should not be harmful to run acpi_ec_clear() on systems without the bug; it will return immediately after finding no data waiting. - Runs acpi_ec_clear() on initialisation (boot), from acpi_ec_add() - Runs acpi_ec_clear() on wake, from acpi_ec_unblock_transactions() References: https://bugzilla.kernel.org/show_bug.cgi?id=44161 References: https://bugzilla.kernel.org/show_bug.cgi?id=45461 References: https://bugzilla.kernel.org/show_bug.cgi?id=57271 References: https://bugzilla.kernel.org/attachment.cgi?id=126801 Suggested-by: Juan Manuel Cabo <juanmanuel.cabo@gmail.com> Signed-off-by: Kieran Clancy <clancy.kieran@gmail.com> Reviewed-by: Lan Tianyu <tianyu.lan@intel.com> Reviewed-by: Dennis Jansen <dennis.jansen@web.de> Tested-by: Kieran Clancy <clancy.kieran@gmail.com> Tested-by: Juan Manuel Cabo <juanmanuel.cabo@gmail.com> Tested-by: Dennis Jansen <dennis.jansen@web.de> Tested-by: Maurizio D'Addona <mauritiusdadd@gmail.com> Tested-by: San Zamoyski <san@plusnet.pl> Cc: All applicable <stable@vger.kernel.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r--drivers/acpi/ec.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 959d41acc108..d7d32c28829b 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -67,6 +67,8 @@ enum ec_command {
67#define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ 67#define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */
68#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ 68#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
69#define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */ 69#define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */
70#define ACPI_EC_CLEAR_MAX 100 /* Maximum number of events to query
71 * when trying to clear the EC */
70 72
71enum { 73enum {
72 EC_FLAGS_QUERY_PENDING, /* Query is pending */ 74 EC_FLAGS_QUERY_PENDING, /* Query is pending */
@@ -116,6 +118,7 @@ EXPORT_SYMBOL(first_ec);
116static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */ 118static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
117static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ 119static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
118static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */ 120static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
121static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
119 122
120/* -------------------------------------------------------------------------- 123/* --------------------------------------------------------------------------
121 Transaction Management 124 Transaction Management
@@ -440,6 +443,29 @@ acpi_handle ec_get_handle(void)
440 443
441EXPORT_SYMBOL(ec_get_handle); 444EXPORT_SYMBOL(ec_get_handle);
442 445
446static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 *data);
447
448/*
449 * Clears stale _Q events that might have accumulated in the EC.
450 * Run with locked ec mutex.
451 */
452static void acpi_ec_clear(struct acpi_ec *ec)
453{
454 int i, status;
455 u8 value = 0;
456
457 for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) {
458 status = acpi_ec_query_unlocked(ec, &value);
459 if (status || !value)
460 break;
461 }
462
463 if (unlikely(i == ACPI_EC_CLEAR_MAX))
464 pr_warn("Warning: Maximum of %d stale EC events cleared\n", i);
465 else
466 pr_info("%d stale EC events cleared\n", i);
467}
468
443void acpi_ec_block_transactions(void) 469void acpi_ec_block_transactions(void)
444{ 470{
445 struct acpi_ec *ec = first_ec; 471 struct acpi_ec *ec = first_ec;
@@ -463,6 +489,10 @@ void acpi_ec_unblock_transactions(void)
463 mutex_lock(&ec->mutex); 489 mutex_lock(&ec->mutex);
464 /* Allow transactions to be carried out again */ 490 /* Allow transactions to be carried out again */
465 clear_bit(EC_FLAGS_BLOCKED, &ec->flags); 491 clear_bit(EC_FLAGS_BLOCKED, &ec->flags);
492
493 if (EC_FLAGS_CLEAR_ON_RESUME)
494 acpi_ec_clear(ec);
495
466 mutex_unlock(&ec->mutex); 496 mutex_unlock(&ec->mutex);
467} 497}
468 498
@@ -821,6 +851,13 @@ static int acpi_ec_add(struct acpi_device *device)
821 851
822 /* EC is fully operational, allow queries */ 852 /* EC is fully operational, allow queries */
823 clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); 853 clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
854
855 /* Clear stale _Q events if hardware might require that */
856 if (EC_FLAGS_CLEAR_ON_RESUME) {
857 mutex_lock(&ec->mutex);
858 acpi_ec_clear(ec);
859 mutex_unlock(&ec->mutex);
860 }
824 return ret; 861 return ret;
825} 862}
826 863
@@ -922,6 +959,30 @@ static int ec_enlarge_storm_threshold(const struct dmi_system_id *id)
922 return 0; 959 return 0;
923} 960}
924 961
962/*
963 * On some hardware it is necessary to clear events accumulated by the EC during
964 * sleep. These ECs stop reporting GPEs until they are manually polled, if too
965 * many events are accumulated. (e.g. Samsung Series 5/9 notebooks)
966 *
967 * https://bugzilla.kernel.org/show_bug.cgi?id=44161
968 *
969 * Ideally, the EC should also be instructed NOT to accumulate events during
970 * sleep (which Windows seems to do somehow), but the interface to control this
971 * behaviour is not known at this time.
972 *
973 * Models known to be affected are Samsung 530Uxx/535Uxx/540Uxx/550Pxx/900Xxx,
974 * however it is very likely that other Samsung models are affected.
975 *
976 * On systems which don't accumulate _Q events during sleep, this extra check
977 * should be harmless.
978 */
979static int ec_clear_on_resume(const struct dmi_system_id *id)
980{
981 pr_debug("Detected system needing EC poll on resume.\n");
982 EC_FLAGS_CLEAR_ON_RESUME = 1;
983 return 0;
984}
985
925static struct dmi_system_id ec_dmi_table[] __initdata = { 986static struct dmi_system_id ec_dmi_table[] __initdata = {
926 { 987 {
927 ec_skip_dsdt_scan, "Compal JFL92", { 988 ec_skip_dsdt_scan, "Compal JFL92", {
@@ -965,6 +1026,9 @@ static struct dmi_system_id ec_dmi_table[] __initdata = {
965 ec_validate_ecdt, "ASUS hardware", { 1026 ec_validate_ecdt, "ASUS hardware", {
966 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer Inc."), 1027 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer Inc."),
967 DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),}, NULL}, 1028 DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),}, NULL},
1029 {
1030 ec_clear_on_resume, "Samsung hardware", {
1031 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
968 {}, 1032 {},
969}; 1033};
970 1034