summaryrefslogtreecommitdiffstats
path: root/acpi-ec-add-delay-before-write.patch
diff options
context:
space:
mode:
Diffstat (limited to 'acpi-ec-add-delay-before-write.patch')
-rw-r--r--acpi-ec-add-delay-before-write.patch52
1 files changed, 52 insertions, 0 deletions
diff --git a/acpi-ec-add-delay-before-write.patch b/acpi-ec-add-delay-before-write.patch
new file mode 100644
index 000000000..af49cccbd
--- /dev/null
+++ b/acpi-ec-add-delay-before-write.patch
@@ -0,0 +1,52 @@
+https://bugzilla.kernel.org/show_bug.cgi?id=14733#c41
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index 27e0b92..09fbb69 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -226,6 +226,7 @@ static int ec_poll(struct acpi_ec *ec)
+ if (ec_transaction_done(ec))
+ return 0;
+ } else {
++ msleep(1);
+ if (wait_event_timeout(ec->wait,
+ ec_transaction_done(ec),
+ msecs_to_jiffies(1)))
+@@ -233,8 +234,8 @@ static int ec_poll(struct acpi_ec *ec)
+ }
+ advance_transaction(ec, acpi_ec_read_status(ec));
+ } while (time_before(jiffies, delay));
+- if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)
+- break;
++// if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)
++// break;
+ pr_debug(PREFIX "controller reset, restart transaction\n");
+ spin_lock_irqsave(&ec->curr_lock, flags);
+ start_transaction(ec);
+@@ -271,15 +272,25 @@ static int ec_check_ibf0(struct acpi_ec *ec)
+ return (status & ACPI_EC_FLAG_IBF) == 0;
+ }
+
++/* try to clean input buffer with burst_disable transaction */
++static int acpi_ec_clean_buffer(struct acpi_ec *ec)
++{
++ struct transaction t = {.command = ACPI_EC_BURST_DISABLE,
++ .wdata = NULL, .rdata = NULL,
++ .wlen = 0, .rlen = 0};
++ return acpi_ec_transaction_unlocked(ec, &t);
++}
++
+ static int ec_wait_ibf0(struct acpi_ec *ec)
+ {
++
+ unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
+ /* interrupt wait manually if GPE mode is not active */
+ while (time_before(jiffies, delay))
+ if (wait_event_timeout(ec->wait, ec_check_ibf0(ec),
+ msecs_to_jiffies(1)))
+ return 0;
+- return -ETIME;
++ return acpi_ec_clean_buffer(ec);
+ }
+
+ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)