diff mbox series

Revert "ACPI / EC: Remove old CLEAR_ON_RESUME quirk"

Message ID 1549001621-23355-1-git-send-email-rui.zhang@intel.com (mailing list archive)
State Accepted, archived
Delegated to: Rafael Wysocki
Headers show
Series Revert "ACPI / EC: Remove old CLEAR_ON_RESUME quirk" | expand

Commit Message

Zhang, Rui Feb. 1, 2019, 6:13 a.m. UTC
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>
---
 drivers/acpi/ec.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

Comments

Rafael J. Wysocki Feb. 6, 2019, 10:36 a.m. UTC | #1
On Friday, February 1, 2019 7:13:41 AM CET Zhang Rui wrote:
> 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>
> ---
>  drivers/acpi/ec.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
> 
> diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
> index 9d66a47..49e16f0 100644
> --- a/drivers/acpi/ec.c
> +++ b/drivers/acpi/ec.c
> @@ -194,6 +194,7 @@ static struct workqueue_struct *ec_query_wq;
>  static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
>  static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */
>  static int EC_FLAGS_IGNORE_DSDT_GPE; /* Needs ECDT GPE as correction setting */
> +static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
>  
>  /* --------------------------------------------------------------------------
>   *                           Logging/Debugging
> @@ -499,6 +500,26 @@ static inline void __acpi_ec_disable_event(struct acpi_ec *ec)
>  		ec_log_drv("event blocked");
>  }
>  
> +/*
> + * Process _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(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);
> +}
> +
>  static void acpi_ec_enable_event(struct acpi_ec *ec)
>  {
>  	unsigned long flags;
> @@ -507,6 +528,10 @@ static void acpi_ec_enable_event(struct acpi_ec *ec)
>  	if (acpi_ec_started(ec))
>  		__acpi_ec_enable_event(ec);
>  	spin_unlock_irqrestore(&ec->lock, flags);
> +
> +	/* Drain additional events if hardware requires that */
> +	if (EC_FLAGS_CLEAR_ON_RESUME)
> +		acpi_ec_clear(ec);
>  }
>  
>  #ifdef CONFIG_PM_SLEEP
> @@ -1821,6 +1846,31 @@ static int ec_flag_query_handshake(const struct dmi_system_id *id)
>  #endif
>  
>  /*
> + * 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;
> +	ec_event_clearing = ACPI_EC_EVT_TIMING_STATUS;
> +	return 0;
> +}
> +
> +/*
>   * Some ECDTs contain wrong register addresses.
>   * MSI MS-171F
>   * https://bugzilla.kernel.org/show_bug.cgi?id=12461
> @@ -1869,6 +1919,9 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = {
>  	ec_honor_ecdt_gpe, "ASUS X580VD", {
>  	DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
>  	DMI_MATCH(DMI_PRODUCT_NAME, "X580VD"),}, NULL},
> +	{
> +	ec_clear_on_resume, "Samsung hardware", {
> +	DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
>  	{},
>  };
>  
> 

Applied, thanks!
diff mbox series

Patch

diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 9d66a47..49e16f0 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -194,6 +194,7 @@  static struct workqueue_struct *ec_query_wq;
 static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
 static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */
 static int EC_FLAGS_IGNORE_DSDT_GPE; /* Needs ECDT GPE as correction setting */
+static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
 
 /* --------------------------------------------------------------------------
  *                           Logging/Debugging
@@ -499,6 +500,26 @@  static inline void __acpi_ec_disable_event(struct acpi_ec *ec)
 		ec_log_drv("event blocked");
 }
 
+/*
+ * Process _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(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);
+}
+
 static void acpi_ec_enable_event(struct acpi_ec *ec)
 {
 	unsigned long flags;
@@ -507,6 +528,10 @@  static void acpi_ec_enable_event(struct acpi_ec *ec)
 	if (acpi_ec_started(ec))
 		__acpi_ec_enable_event(ec);
 	spin_unlock_irqrestore(&ec->lock, flags);
+
+	/* Drain additional events if hardware requires that */
+	if (EC_FLAGS_CLEAR_ON_RESUME)
+		acpi_ec_clear(ec);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -1821,6 +1846,31 @@  static int ec_flag_query_handshake(const struct dmi_system_id *id)
 #endif
 
 /*
+ * 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;
+	ec_event_clearing = ACPI_EC_EVT_TIMING_STATUS;
+	return 0;
+}
+
+/*
  * Some ECDTs contain wrong register addresses.
  * MSI MS-171F
  * https://bugzilla.kernel.org/show_bug.cgi?id=12461
@@ -1869,6 +1919,9 @@  static const struct dmi_system_id ec_dmi_table[] __initconst = {
 	ec_honor_ecdt_gpe, "ASUS X580VD", {
 	DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 	DMI_MATCH(DMI_PRODUCT_NAME, "X580VD"),}, NULL},
+	{
+	ec_clear_on_resume, "Samsung hardware", {
+	DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
 	{},
 };