diff mbox

[v2] ACPI / EC: Clear stale EC events on Samsung systems

Message ID 1393596748-3656-1-git-send-email-clancy.kieran@gmail.com (mailing list archive)
State Accepted, archived
Headers show

Commit Message

Kieran Clancy Feb. 28, 2014, 2:12 p.m. UTC
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
Signed-off-by: Kieran Clancy <clancy.kieran@gmail.com>
Suggested-by: Juan Manuel Cabo <juanmanuel.cabo@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>
---

Changes in PATCH v2:
 - Changed some of the 'Signed-off-by' lines to better reflect contributions,
   as suggested by Rafael J. Wysocki <rjw@rjwysocki.net>.
 - Directly reference prior work by Lan Tianyu.
 - Increase ACPI_EC_CLEAR_MAX to 100, after discussion with
   Li Guang <lig.fnst@cn.fujitsu.com> and Juan Manuel Cabo.
 - Made source comments more explicit, thanks to suggestions by Li Guang.
 - Marked warning for hitting ACPI_EC_CLEAR_MAX as unlikely(), as suggested by
   Dennis Jansen.

 drivers/acpi/ec.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

Comments

Rafael J. Wysocki March 2, 2014, 12:40 a.m. UTC | #1
On Saturday, March 01, 2014 12:42:28 AM Kieran Clancy wrote:
> 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
> Signed-off-by: Kieran Clancy <clancy.kieran@gmail.com>
> Suggested-by: Juan Manuel Cabo <juanmanuel.cabo@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>

Queued up for 3.15, thanks!

> ---
> 
> Changes in PATCH v2:
>  - Changed some of the 'Signed-off-by' lines to better reflect contributions,
>    as suggested by Rafael J. Wysocki <rjw@rjwysocki.net>.
>  - Directly reference prior work by Lan Tianyu.
>  - Increase ACPI_EC_CLEAR_MAX to 100, after discussion with
>    Li Guang <lig.fnst@cn.fujitsu.com> and Juan Manuel Cabo.
>  - Made source comments more explicit, thanks to suggestions by Li Guang.
>  - Marked warning for hitting ACPI_EC_CLEAR_MAX as unlikely(), as suggested by
>    Dennis Jansen.
> 
>  drivers/acpi/ec.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 64 insertions(+)
> 
> diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
> index 959d41a..d7d32c2 100644
> --- a/drivers/acpi/ec.c
> +++ b/drivers/acpi/ec.c
> @@ -67,6 +67,8 @@ enum ec_command {
>  #define ACPI_EC_DELAY		500	/* Wait 500ms max. during EC ops */
>  #define ACPI_EC_UDELAY_GLK	1000	/* Wait 1ms max. to get global lock */
>  #define ACPI_EC_MSI_UDELAY	550	/* Wait 550us for MSI EC */
> +#define ACPI_EC_CLEAR_MAX	100	/* Maximum number of events to query
> +					 * when trying to clear the EC */
>  
>  enum {
>  	EC_FLAGS_QUERY_PENDING,		/* Query is pending */
> @@ -116,6 +118,7 @@ EXPORT_SYMBOL(first_ec);
>  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_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
> +static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
>  
>  /* --------------------------------------------------------------------------
>                               Transaction Management
> @@ -440,6 +443,29 @@ 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.
> + * Run with locked ec mutex.
> + */
> +static void acpi_ec_clear(struct acpi_ec *ec)
> +{
> +	int i, status;
> +	u8 value = 0;
> +
> +	for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) {
> +		status = acpi_ec_query_unlocked(ec, &value);
> +		if (status || !value)
> +			break;
> +	}
> +
> +	if (unlikely(i == ACPI_EC_CLEAR_MAX))
> +		pr_warn("Warning: Maximum of %d stale EC events cleared\n", i);
> +	else
> +		pr_info("%d stale EC events cleared\n", i);
> +}
> +
>  void acpi_ec_block_transactions(void)
>  {
>  	struct acpi_ec *ec = first_ec;
> @@ -463,6 +489,10 @@ void acpi_ec_unblock_transactions(void)
>  	mutex_lock(&ec->mutex);
>  	/* Allow transactions to be carried out again */
>  	clear_bit(EC_FLAGS_BLOCKED, &ec->flags);
> +
> +	if (EC_FLAGS_CLEAR_ON_RESUME)
> +		acpi_ec_clear(ec);
> +
>  	mutex_unlock(&ec->mutex);
>  }
>  
> @@ -821,6 +851,13 @@ static int acpi_ec_add(struct acpi_device *device)
>  
>  	/* EC is fully operational, allow queries */
>  	clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
> +
> +	/* Clear stale _Q events if hardware might require that */
> +	if (EC_FLAGS_CLEAR_ON_RESUME) {
> +		mutex_lock(&ec->mutex);
> +		acpi_ec_clear(ec);
> +		mutex_unlock(&ec->mutex);
> +	}
>  	return ret;
>  }
>  
> @@ -922,6 +959,30 @@ static int ec_enlarge_storm_threshold(const struct dmi_system_id *id)
>  	return 0;
>  }
>  
> +/*
> + * 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
> + * many events are accumulated. (e.g. Samsung Series 5/9 notebooks)
> + *
> + * https://bugzilla.kernel.org/show_bug.cgi?id=44161
> + *
> + * Ideally, the EC should also be instructed NOT to accumulate events during
> + * sleep (which Windows seems to do somehow), but the interface to control this
> + * behaviour is not known at this time.
> + *
> + * Models known to be affected are Samsung 530Uxx/535Uxx/540Uxx/550Pxx/900Xxx,
> + * however it is very likely that other Samsung models are affected.
> + *
> + * On systems which don't accumulate _Q events during sleep, this extra check
> + * should be harmless.
> + */
> +static int ec_clear_on_resume(const struct dmi_system_id *id)
> +{
> +	pr_debug("Detected system needing EC poll on resume.\n");
> +	EC_FLAGS_CLEAR_ON_RESUME = 1;
> +	return 0;
> +}
> +
>  static struct dmi_system_id ec_dmi_table[] __initdata = {
>  	{
>  	ec_skip_dsdt_scan, "Compal JFL92", {
> @@ -965,6 +1026,9 @@ static struct dmi_system_id ec_dmi_table[] __initdata = {
>  	ec_validate_ecdt, "ASUS hardware", {
>  	DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer Inc."),
>  	DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),}, NULL},
> +	{
> +	ec_clear_on_resume, "Samsung hardware", {
> +	DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
>  	{},
>  };
>  
>
Joseph Salisbury March 5, 2014, 6:30 p.m. UTC | #2
On 02/28/2014 09:12 AM, Kieran Clancy wrote:
> 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
> Signed-off-by: Kieran Clancy <clancy.kieran@gmail.com>
> Suggested-by: Juan Manuel Cabo <juanmanuel.cabo@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>
> ---
>
> Changes in PATCH v2:
>  - Changed some of the 'Signed-off-by' lines to better reflect contributions,
>    as suggested by Rafael J. Wysocki <rjw@rjwysocki.net>.
>  - Directly reference prior work by Lan Tianyu.
>  - Increase ACPI_EC_CLEAR_MAX to 100, after discussion with
>    Li Guang <lig.fnst@cn.fujitsu.com> and Juan Manuel Cabo.
>  - Made source comments more explicit, thanks to suggestions by Li Guang.
>  - Marked warning for hitting ACPI_EC_CLEAR_MAX as unlikely(), as suggested by
>    Dennis Jansen.
>
>  drivers/acpi/ec.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 64 insertions(+)
>
> diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
> index 959d41a..d7d32c2 100644
> --- a/drivers/acpi/ec.c
> +++ b/drivers/acpi/ec.c
> @@ -67,6 +67,8 @@ enum ec_command {
>  #define ACPI_EC_DELAY		500	/* Wait 500ms max. during EC ops */
>  #define ACPI_EC_UDELAY_GLK	1000	/* Wait 1ms max. to get global lock */
>  #define ACPI_EC_MSI_UDELAY	550	/* Wait 550us for MSI EC */
> +#define ACPI_EC_CLEAR_MAX	100	/* Maximum number of events to query
> +					 * when trying to clear the EC */
>  
>  enum {
>  	EC_FLAGS_QUERY_PENDING,		/* Query is pending */
> @@ -116,6 +118,7 @@ EXPORT_SYMBOL(first_ec);
>  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_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
> +static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
>  
>  /* --------------------------------------------------------------------------
>                               Transaction Management
> @@ -440,6 +443,29 @@ 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.
> + * Run with locked ec mutex.
> + */
> +static void acpi_ec_clear(struct acpi_ec *ec)
> +{
> +	int i, status;
> +	u8 value = 0;
> +
> +	for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) {
> +		status = acpi_ec_query_unlocked(ec, &value);
> +		if (status || !value)
> +			break;
> +	}
> +
> +	if (unlikely(i == ACPI_EC_CLEAR_MAX))
> +		pr_warn("Warning: Maximum of %d stale EC events cleared\n", i);
> +	else
> +		pr_info("%d stale EC events cleared\n", i);
> +}
> +
>  void acpi_ec_block_transactions(void)
>  {
>  	struct acpi_ec *ec = first_ec;
> @@ -463,6 +489,10 @@ void acpi_ec_unblock_transactions(void)
>  	mutex_lock(&ec->mutex);
>  	/* Allow transactions to be carried out again */
>  	clear_bit(EC_FLAGS_BLOCKED, &ec->flags);
> +
> +	if (EC_FLAGS_CLEAR_ON_RESUME)
> +		acpi_ec_clear(ec);
> +
>  	mutex_unlock(&ec->mutex);
>  }
>  
> @@ -821,6 +851,13 @@ static int acpi_ec_add(struct acpi_device *device)
>  
>  	/* EC is fully operational, allow queries */
>  	clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
> +
> +	/* Clear stale _Q events if hardware might require that */
> +	if (EC_FLAGS_CLEAR_ON_RESUME) {
> +		mutex_lock(&ec->mutex);
> +		acpi_ec_clear(ec);
> +		mutex_unlock(&ec->mutex);
> +	}
>  	return ret;
>  }
>  
> @@ -922,6 +959,30 @@ static int ec_enlarge_storm_threshold(const struct dmi_system_id *id)
>  	return 0;
>  }
>  
> +/*
> + * 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
> + * many events are accumulated. (e.g. Samsung Series 5/9 notebooks)
> + *
> + * https://bugzilla.kernel.org/show_bug.cgi?id=44161
> + *
> + * Ideally, the EC should also be instructed NOT to accumulate events during
> + * sleep (which Windows seems to do somehow), but the interface to control this
> + * behaviour is not known at this time.
> + *
> + * Models known to be affected are Samsung 530Uxx/535Uxx/540Uxx/550Pxx/900Xxx,
> + * however it is very likely that other Samsung models are affected.
> + *
> + * On systems which don't accumulate _Q events during sleep, this extra check
> + * should be harmless.
> + */
> +static int ec_clear_on_resume(const struct dmi_system_id *id)
> +{
> +	pr_debug("Detected system needing EC poll on resume.\n");
> +	EC_FLAGS_CLEAR_ON_RESUME = 1;
> +	return 0;
> +}
> +
>  static struct dmi_system_id ec_dmi_table[] __initdata = {
>  	{
>  	ec_skip_dsdt_scan, "Compal JFL92", {
> @@ -965,6 +1026,9 @@ static struct dmi_system_id ec_dmi_table[] __initdata = {
>  	ec_validate_ecdt, "ASUS hardware", {
>  	DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer Inc."),
>  	DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),}, NULL},
> +	{
> +	ec_clear_on_resume, "Samsung hardware", {
> +	DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
>  	{},
>  };
>  
I notice there was no cc to stable.  Were you also planning on
submitting this for inclusion in the upstream stable kernels?
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kieran Clancy March 6, 2014, 12:34 a.m. UTC | #3
On Thu, Mar 6, 2014 at 5:00 AM, Joseph Salisbury
<joseph.salisbury@canonical.com> wrote:
> I notice there was no cc to stable.  Were you also planning on
> submitting this for inclusion in the upstream stable kernels?

I don't really know the process for stable kernels
(Documentation/SubmittingPatches mentions nothing), but of course I'd
like it included if possible.

Rafael, is it a separate process to get this in the stable tree or
will it naturally happen after being merged into the mainline?

Thanks,
Kieran
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael J. Wysocki March 6, 2014, 12:52 a.m. UTC | #4
On Thursday, March 06, 2014 11:04:14 AM Kieran Clancy wrote:
> On Thu, Mar 6, 2014 at 5:00 AM, Joseph Salisbury
> <joseph.salisbury@canonical.com> wrote:
> > I notice there was no cc to stable.  Were you also planning on
> > submitting this for inclusion in the upstream stable kernels?
> 
> I don't really know the process for stable kernels
> (Documentation/SubmittingPatches mentions nothing), but of course I'd
> like it included if possible.
> 
> Rafael, is it a separate process to get this in the stable tree or
> will it naturally happen after being merged into the mainline?

I need to add a proper "CC stable" tag to your patch for this to happen.

Which -stable kernels should it go to?
Kieran Clancy March 6, 2014, 1:24 a.m. UTC | #5
On Thu, Mar 6, 2014 at 11:22 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> On Thursday, March 06, 2014 11:04:14 AM Kieran Clancy wrote:
>>
>> Rafael, is it a separate process to get this in the stable tree or
>> will it naturally happen after being merged into the mainline?
>
> I need to add a proper "CC stable" tag to your patch for this to happen.
>
> Which -stable kernels should it go to?

3.2 and 3.10 seem like natural choices (3.4?), but I don't know the
norm for this kind of fix. Would there be any reason not to include it
in some particular stable kernels?

Cheers,
Kieran.
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Juan Manuel Cabo March 6, 2014, 1:36 a.m. UTC | #6
Beware, the context line:        
             static struct dmi_system_id ec_dmi_table[] __initdata = {
has changed in recent kernels, so that line of the patch would need
to be different for it to apply older kernels.
It used to be this:
             static struct dmi_system_id __initdata ec_dmi_table[] = {
until 3.11 I guess.

It is just a context line and is not important for the patch itself.

See:
http://lxr.free-electrons.com/source/drivers/acpi/ec.c?v=3.11
http://lxr.free-electrons.com/source/drivers/acpi/ec.c?v=3.12

Cheers!
--Juan Manuel Cabo


On 03/05/2014 10:24 PM, Kieran Clancy wrote:
> On Thu, Mar 6, 2014 at 11:22 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
>> On Thursday, March 06, 2014 11:04:14 AM Kieran Clancy wrote:
>>> Rafael, is it a separate process to get this in the stable tree or
>>> will it naturally happen after being merged into the mainline?
>> I need to add a proper "CC stable" tag to your patch for this to happen.
>>
>> Which -stable kernels should it go to?
> 3.2 and 3.10 seem like natural choices (3.4?), but I don't know the
> norm for this kind of fix. Would there be any reason not to include it
> in some particular stable kernels?
>
> Cheers,
> Kieran.
>

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael J. Wysocki March 6, 2014, 12:32 p.m. UTC | #7
On Thursday, March 06, 2014 11:54:28 AM Kieran Clancy wrote:
> On Thu, Mar 6, 2014 at 11:22 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> > On Thursday, March 06, 2014 11:04:14 AM Kieran Clancy wrote:
> >>
> >> Rafael, is it a separate process to get this in the stable tree or
> >> will it naturally happen after being merged into the mainline?
> >
> > I need to add a proper "CC stable" tag to your patch for this to happen.
> >
> > Which -stable kernels should it go to?
> 
> 3.2 and 3.10 seem like natural choices (3.4?), but I don't know the
> norm for this kind of fix. Would there be any reason not to include it
> in some particular stable kernels?

In some cases patches are not needed in older -stable, because the
changes are not relevant there etc.

OK, I'll mark if for all applicable -stable series.

Thanks!
Joseph Salisbury March 6, 2014, 11:12 p.m. UTC | #8
On 03/06/2014 07:32 AM, Rafael J. Wysocki wrote:
> On Thursday, March 06, 2014 11:54:28 AM Kieran Clancy wrote:
>> On Thu, Mar 6, 2014 at 11:22 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
>>> On Thursday, March 06, 2014 11:04:14 AM Kieran Clancy wrote:
>>>> Rafael, is it a separate process to get this in the stable tree or
>>>> will it naturally happen after being merged into the mainline?
>>> I need to add a proper "CC stable" tag to your patch for this to happen.
>>>
>>> Which -stable kernels should it go to?
>> 3.2 and 3.10 seem like natural choices (3.4?), but I don't know the
>> norm for this kind of fix. Would there be any reason not to include it
>> in some particular stable kernels?
> In some cases patches are not needed in older -stable, because the
> changes are not relevant there etc.
>
> OK, I'll mark if for all applicable -stable series.
>
> Thanks!
>
Thanks, Rafael!
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 959d41a..d7d32c2 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -67,6 +67,8 @@  enum ec_command {
 #define ACPI_EC_DELAY		500	/* Wait 500ms max. during EC ops */
 #define ACPI_EC_UDELAY_GLK	1000	/* Wait 1ms max. to get global lock */
 #define ACPI_EC_MSI_UDELAY	550	/* Wait 550us for MSI EC */
+#define ACPI_EC_CLEAR_MAX	100	/* Maximum number of events to query
+					 * when trying to clear the EC */
 
 enum {
 	EC_FLAGS_QUERY_PENDING,		/* Query is pending */
@@ -116,6 +118,7 @@  EXPORT_SYMBOL(first_ec);
 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_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
+static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
 
 /* --------------------------------------------------------------------------
                              Transaction Management
@@ -440,6 +443,29 @@  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.
+ * Run with locked ec mutex.
+ */
+static void acpi_ec_clear(struct acpi_ec *ec)
+{
+	int i, status;
+	u8 value = 0;
+
+	for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) {
+		status = acpi_ec_query_unlocked(ec, &value);
+		if (status || !value)
+			break;
+	}
+
+	if (unlikely(i == ACPI_EC_CLEAR_MAX))
+		pr_warn("Warning: Maximum of %d stale EC events cleared\n", i);
+	else
+		pr_info("%d stale EC events cleared\n", i);
+}
+
 void acpi_ec_block_transactions(void)
 {
 	struct acpi_ec *ec = first_ec;
@@ -463,6 +489,10 @@  void acpi_ec_unblock_transactions(void)
 	mutex_lock(&ec->mutex);
 	/* Allow transactions to be carried out again */
 	clear_bit(EC_FLAGS_BLOCKED, &ec->flags);
+
+	if (EC_FLAGS_CLEAR_ON_RESUME)
+		acpi_ec_clear(ec);
+
 	mutex_unlock(&ec->mutex);
 }
 
@@ -821,6 +851,13 @@  static int acpi_ec_add(struct acpi_device *device)
 
 	/* EC is fully operational, allow queries */
 	clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
+
+	/* Clear stale _Q events if hardware might require that */
+	if (EC_FLAGS_CLEAR_ON_RESUME) {
+		mutex_lock(&ec->mutex);
+		acpi_ec_clear(ec);
+		mutex_unlock(&ec->mutex);
+	}
 	return ret;
 }
 
@@ -922,6 +959,30 @@  static int ec_enlarge_storm_threshold(const struct dmi_system_id *id)
 	return 0;
 }
 
+/*
+ * 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
+ * many events are accumulated. (e.g. Samsung Series 5/9 notebooks)
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=44161
+ *
+ * Ideally, the EC should also be instructed NOT to accumulate events during
+ * sleep (which Windows seems to do somehow), but the interface to control this
+ * behaviour is not known at this time.
+ *
+ * Models known to be affected are Samsung 530Uxx/535Uxx/540Uxx/550Pxx/900Xxx,
+ * however it is very likely that other Samsung models are affected.
+ *
+ * On systems which don't accumulate _Q events during sleep, this extra check
+ * should be harmless.
+ */
+static int ec_clear_on_resume(const struct dmi_system_id *id)
+{
+	pr_debug("Detected system needing EC poll on resume.\n");
+	EC_FLAGS_CLEAR_ON_RESUME = 1;
+	return 0;
+}
+
 static struct dmi_system_id ec_dmi_table[] __initdata = {
 	{
 	ec_skip_dsdt_scan, "Compal JFL92", {
@@ -965,6 +1026,9 @@  static struct dmi_system_id ec_dmi_table[] __initdata = {
 	ec_validate_ecdt, "ASUS hardware", {
 	DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer Inc."),
 	DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),}, NULL},
+	{
+	ec_clear_on_resume, "Samsung hardware", {
+	DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
 	{},
 };