[3.11.y.z extended stable] Patch "ACPI / EC: Process rather than discard events in acpi_ec_clear" has been added to staging queue

Luis Henriques luis.henriques at canonical.com
Wed May 14 14:57:59 UTC 2014


This is a note to let you know that I have just added a patch titled

    ACPI / EC: Process rather than discard events in acpi_ec_clear

to the linux-3.11.y-queue branch of the 3.11.y.z extended stable tree 
which can be found at:

 http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.11.y-queue

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.11.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Luis

------

>From 4721f756c2f29265f0a698a79f5f415dff77eb61 Mon Sep 17 00:00:00 2001
From: Kieran Clancy <clancy.kieran at gmail.com>
Date: Wed, 30 Apr 2014 00:21:20 +0930
Subject: ACPI / EC: Process rather than discard events in acpi_ec_clear

commit 3eba563e280101209bad27d40bfc83ddf1489234 upstream.

Address a regression caused by commit ad332c8a4533:
(ACPI / EC: Clear stale EC events on Samsung systems)

After the earlier patch, there was found to be a race condition on some
earlier Samsung systems (N150/N210/N220). The function acpi_ec_clear was
sometimes discarding a new EC event before its GPE was triggered by the
system. In the case of these systems, this meant that the "lid open"
event was not registered on resume if that was the cause of the wake,
leading to problems when attempting to close the lid to suspend again.

After testing on a number of Samsung systems, both those affected by the
previous EC bug and those affected by the race condition, it seemed that
the best course of action was to process rather than discard the events.
On Samsung systems which accumulate stale EC events, there does not seem
to be any adverse side-effects of running the associated _Q methods.

This patch adds an argument to the static function acpi_ec_sync_query so
that it may be used within the acpi_ec_clear loop in place of
acpi_ec_query_unlocked which was used previously.

With thanks to Stefan Biereigel for reporting the issue, and for all the
people who helped test the new patch on affected systems.

Fixes: ad332c8a4533 (ACPI / EC: Clear stale EC events on Samsung systems)
References: https://lkml.kernel.org/r/532FE3B2.9060808@biereigel-wb.de
References: https://bugzilla.kernel.org/show_bug.cgi?id=44161#c173
Reported-by: Stefan Biereigel <stefan at biereigel.de>
Signed-off-by: Kieran Clancy <clancy.kieran at gmail.com>
Tested-by: Stefan Biereigel <stefan at biereigel.de>
Tested-by: Dennis Jansen <dennis.jansen at web.de>
Tested-by: Nicolas Porcel <nicolasporcel06 at gmail.com>
Tested-by: Maurizio D'Addona <mauritiusdadd at gmail.com>
Tested-by: Juan Manuel Cabo <juanmanuel.cabo at gmail.com>
Tested-by: Giannis Koutsou <giannis.koutsou at gmail.com>
Tested-by: Kieran Clancy <clancy.kieran at gmail.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
Signed-off-by: Luis Henriques <luis.henriques at canonical.com>
---
 drivers/acpi/ec.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index e053d15..3ed7136 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -213,13 +213,13 @@ unlock:
 	spin_unlock_irqrestore(&ec->lock, flags);
 }

-static int acpi_ec_sync_query(struct acpi_ec *ec);
+static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data);

 static int ec_check_sci_sync(struct acpi_ec *ec, u8 state)
 {
 	if (state & ACPI_EC_FLAG_SCI) {
 		if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
-			return acpi_ec_sync_query(ec);
+			return acpi_ec_sync_query(ec, NULL);
 	}
 	return 0;
 }
@@ -471,10 +471,8 @@ acpi_handle ec_get_handle(void)

 EXPORT_SYMBOL(ec_get_handle);

-static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 *data);
-
 /*
- * Clears stale _Q events that might have accumulated in the EC.
+ * Process _Q events that might have accumulated in the EC.
  * Run with locked ec mutex.
  */
 static void acpi_ec_clear(struct acpi_ec *ec)
@@ -483,7 +481,7 @@ static void acpi_ec_clear(struct acpi_ec *ec)
 	u8 value = 0;

 	for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) {
-		status = acpi_ec_query_unlocked(ec, &value);
+		status = acpi_ec_sync_query(ec, &value);
 		if (status || !value)
 			break;
 	}
@@ -610,13 +608,18 @@ static void acpi_ec_run(void *cxt)
 	kfree(handler);
 }

-static int acpi_ec_sync_query(struct acpi_ec *ec)
+static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data)
 {
 	u8 value = 0;
 	int status;
 	struct acpi_ec_query_handler *handler, *copy;
-	if ((status = acpi_ec_query_unlocked(ec, &value)))
+
+	status = acpi_ec_query_unlocked(ec, &value);
+	if (data)
+		*data = value;
+	if (status)
 		return status;
+
 	list_for_each_entry(handler, &ec->list, node) {
 		if (value == handler->query_bit) {
 			/* have custom handler for this bit */
@@ -639,7 +642,7 @@ static void acpi_ec_gpe_query(void *ec_cxt)
 	if (!ec)
 		return;
 	mutex_lock(&ec->mutex);
-	acpi_ec_sync_query(ec);
+	acpi_ec_sync_query(ec, NULL);
 	mutex_unlock(&ec->mutex);
 }

--
1.9.1





More information about the kernel-team mailing list