From e7dcc514a49e74051b869697d5ab0370f6301d57 Mon Sep 17 00:00:00 2001 From: Sumit Saxena Date: Wed, 29 Sep 2021 18:10:20 +0530 Subject: scsi: megaraid_sas: Fix concurrent access to ISR between IRQ polling and real interrupt 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 Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_fusion.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/megaraid/megaraid_sas_fusion.c') diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 26d0cf9353dd..eb5ceb75a15e 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; -- cgit