lkml.org 
[lkml]   [2018]   [Apr]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL for 4.9 153/293] ACPI: EC: Fix an EC event IRQ storming issue
    Date
    From: Lv Zheng <lv.zheng@intel.com>

    [ Upstream commit 1ab69f27cbb57e0f970bcd852d9f22ed34259b57 ]

    The EC event IRQ (SCI_EVT) can only be handled by submitting QR_EC. As the
    EC driver handles SCI_EVT in a workqueue, after SCI_EVT is flagged and
    before QR_EC is submitted, there is a period risking IRQ storming. EC IRQ
    must be masked for this period but linux EC driver never does so.

    No end user notices the IRQ storming and no developer fixes this known
    issue because:

    1. The EC IRQ is always edge triggered GPE, and
    2. The kernel can execute no-op EC IRQ handler very fast.

    For edge-triggered EC GPE platforms, it is only reported of post-resume EC
    event lost issues, there won't be an IRQ storming. For level triggered EC
    GPE platforms, fortunately the kernel is always fast enough to execute such
    a no-op EC IRQ handler so that the IRQ handler won't be accumulated to
    starve the task contexts, causing a real IRQ storming.

    But the IRQ storming actually can still happen when:

    1. The EC IRQ performs like level triggered GPE, and
    2. The kernel EC debugging log is turned on but the console is slow enough.

    There are more and more platforms using EC GPE as wake GPE where the EC GPE
    is likely designed as level triggered. Then when EC debugging log is
    enabled, the EC IRQ handler is no longer a no-op but dumps IRQ status to
    the consoles. If the consoles are slow enough, the EC IRQs can arrive much
    faster than executing the handler. Finally the accumulated EC event IRQ
    handlers starve the task contexts, causing the IRQ storming to occur, and
    the kernel hangs can be observed during boot/resume.

    This patch fixes this issue by masking EC IRQ for this period:

    1. Begins when there is an SCI_EVT IRQ pending, and
    2. Ends when there is a QR_EC completed (SCI_EVT acknowledged).

    Tested-by: Wang Wendy <wendy.wang@intel.com>
    Tested-by: Feng Chenzhou <chenzhoux.feng@intel.com>
    Signed-off-by: Lv Zheng <lv.zheng@intel.com>
    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
    Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
    ---
    drivers/acpi/ec.c | 11 ++++++-----
    1 file changed, 6 insertions(+), 5 deletions(-)

    diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
    index c3bcb7f5986e..38136d608471 100644
    --- a/drivers/acpi/ec.c
    +++ b/drivers/acpi/ec.c
    @@ -460,8 +460,10 @@ static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec)

    static void acpi_ec_submit_query(struct acpi_ec *ec)
    {
    - if (acpi_ec_event_enabled(ec) &&
    - !test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
    + acpi_ec_set_storm(ec, EC_FLAGS_COMMAND_STORM);
    + if (!acpi_ec_event_enabled(ec))
    + return;
    + if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
    ec_dbg_evt("Command(%s) submitted/blocked",
    acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));
    ec->nr_pending_queries++;
    @@ -471,11 +473,10 @@ static void acpi_ec_submit_query(struct acpi_ec *ec)

    static void acpi_ec_complete_query(struct acpi_ec *ec)
    {
    - if (test_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
    - clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
    + if (test_and_clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
    ec_dbg_evt("Command(%s) unblocked",
    acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));
    - }
    + acpi_ec_clear_storm(ec, EC_FLAGS_COMMAND_STORM);
    }

    static inline void __acpi_ec_enable_event(struct acpi_ec *ec)
    --
    2.15.1
    \
     
     \ /
      Last update: 2018-04-09 02:31    [W:4.075 / U:0.168 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site