@@ -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;
IRQ polling thread calls ISR after enable_irq() to handle any missed IO completion. 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(see 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 Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com> Fixes: 9bedd36e9146 (scsi: megaraid_sas: Handle missing interrupts while re-enabling IRQs) --- drivers/scsi/megaraid/megaraid_sas_fusion.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)