• Rafael J. Wysocki's avatar
    ACPI: EC: Fix flushing of pending work · f0ac20c3
    Rafael J. Wysocki authored
    Commit 016b87ca ("ACPI: EC: Rework flushing of pending work")
    introduced a subtle bug into the flushing of pending EC work while
    suspended to idle, which may cause the EC driver to fail to
    re-enable the EC GPE after handling a non-wakeup event (like a
    battery status change event, for example).
    
    The problem is that the work item flushed by flush_scheduled_work()
    in __acpi_ec_flush_work() may disable the EC GPE and schedule another
    work item expected to re-enable it, but that new work item is not
    flushed, so __acpi_ec_flush_work() returns with the EC GPE disabled
    and the CPU running it goes into an idle state subsequently.  If all
    of the other CPUs are in idle states at that point, the EC GPE won't
    be re-enabled until at least one CPU is woken up by another interrupt
    source, so system wakeup events that would normally come from the EC
    then don't work.
    
    This is reproducible on a Dell XPS13 9360 in my office which
    sometimes stops reacting to power button and lid events (triggered
    by the EC on that machine) after switching from AC power to battery
    power or vice versa while suspended to idle (each of those switches
    causes the EC GPE to trigger for several times in a row, but they
    are not system wakeup events).
    
    To avoid this problem, it is necessary to drain the workqueue
    entirely in __acpi_ec_flush_work(), but that cannot be done with
    respect to system_wq, because work items may be added to it from
    other places while __acpi_ec_flush_work() is running.  For this
    reason, make the EC driver use a dedicated workqueue for EC events
    processing (let that workqueue be ordered so that EC events are
    processed sequentially) and use drain_workqueue() on it in
    __acpi_ec_flush_work().
    
    Fixes: 016b87ca ("ACPI: EC: Rework flushing of pending work")
    Cc: 5.4+ <stable@vger.kernel.org> # 5.4+
    Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    f0ac20c3
ec.c 58.2 KB