summaryrefslogtreecommitdiff
path: root/drivers/acpi/internal.h
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2021-11-23 19:36:51 +0100
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2021-12-01 20:17:32 +0100
commit4a9af6cac050dce2e895ec3205c4615383ad9112 (patch)
tree517402e788e888f5fc353bd68cbd4a6febc56a07 /drivers/acpi/internal.h
parentd58071a8a76d779eedab38033ae4c821c30295a5 (diff)
ACPI: EC: Rework flushing of EC work while suspended to idle
The flushing of pending work in the EC driver uses drain_workqueue() to flush the event handling work that can requeue itself via advance_transaction(), but this is problematic, because that work may also be requeued from the query workqueue. Namely, if an EC transaction is carried out during the execution of a query handler, it involves calling advance_transaction() which may queue up the event handling work again. This causes the kernel to complain about attempts to add a work item to the EC event workqueue while it is being drained and worst-case it may cause a valid event to be skipped. To avoid this problem, introduce two new counters, events_in_progress and queries_in_progress, incremented when a work item is queued on the event workqueue or the query workqueue, respectively, and decremented at the end of the corresponding work function, and make acpi_ec_dispatch_gpe() the workqueues in a loop until the both of these counters are zero (or system wakeup is pending) instead of calling acpi_ec_flush_work(). At the same time, change __acpi_ec_flush_work() to call flush_workqueue() instead of drain_workqueue() to flush the event workqueue. While at it, use the observation that the work item queued in acpi_ec_query() cannot be pending at that time, because it is used only once, to simplify the code in there. Additionally, clean up a comment in acpi_ec_query() and adjust white space in acpi_ec_event_processor(). Fixes: f0ac20c3f613 ("ACPI: EC: Fix flushing of pending work") Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/internal.h')
-rw-r--r--drivers/acpi/internal.h2
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index d91b560e8867..54b2be94d23d 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -183,6 +183,8 @@ struct acpi_ec {
struct work_struct work;
unsigned long timestamp;
unsigned long nr_pending_queries;
+ unsigned int events_in_progress;
+ unsigned int queries_in_progress;
bool busy_polling;
unsigned int polling_guard;
};