lkml.org 
[lkml]   [2021]   [Nov]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 610/917] scsi: megaraid_sas: Fix concurrent access to ISR between IRQ polling and real interrupt
    Date
    From: Sumit Saxena <sumit.saxena@broadcom.com>

    [ Upstream commit e7dcc514a49e74051b869697d5ab0370f6301d57 ]

    IRQ polling thread calls ISR after enable_irq() to handle any missed I/O
    completion. The atomic flag "in_used" was added to have the synchronization
    between the IRQ polling thread and the interrupt context. There is a bug
    around it leading to a race condition.

    Below is the sequence:

    - IRQ polling thread accesses ISR, fetches the reply descriptor.

    - Real interrupt arrives and pre-empts polling thread (enable_irq() is
    already called).

    - Interrupt context picks the same reply descriptor as fetched by polling
    thread, processes it, and exits.

    - Polling thread resumes and processes the descriptor which is already
    processed by interrupt thread leads to kernel crash.

    Setting the "in_used" flag before fetching the reply descriptor ensures
    synchronized access to ISR.

    Link: https://www.spinics.net/lists/linux-scsi/msg159440.html
    Link: https://lore.kernel.org/r/20210929124022.24605-2-sumit.saxena@broadcom.com
    Fixes: 9bedd36e9146 ("scsi: megaraid_sas: Handle missing interrupts while re-enabling IRQs")
    Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com>
    Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/scsi/megaraid/megaraid_sas_fusion.c | 11 +++++++----
    1 file changed, 7 insertions(+), 4 deletions(-)

    diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
    index 26d0cf9353dd6..eb5ceb75a15ec 100644
    --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
    +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
    @@ -3530,6 +3530,9 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex,
    if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR)
    return IRQ_HANDLED;

    + if (irq_context && !atomic_add_unless(&irq_context->in_used, 1, 1))
    + return 0;
    +
    desc = fusion->reply_frames_desc[MSIxIndex] +
    fusion->last_reply_idx[MSIxIndex];

    @@ -3540,11 +3543,11 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex,
    reply_descript_type = reply_desc->ReplyFlags &
    MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;

    - if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
    + if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) {
    + if (irq_context)
    + atomic_dec(&irq_context->in_used);
    return IRQ_NONE;
    -
    - if (irq_context && !atomic_add_unless(&irq_context->in_used, 1, 1))
    - return 0;
    + }

    num_completed = 0;

    --
    2.33.0


    \
     
     \ /
      Last update: 2021-11-16 00:57    [W:4.054 / U:0.620 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site