Commit 9bedd36e authored by Chandrakanth Patil's avatar Chandrakanth Patil Committed by Martin K. Petersen
Browse files

scsi: megaraid_sas: Handle missing interrupts while re-enabling IRQs

While reenabling the IRQ after IRQ poll there may be a small window for the
firmware to post the replies with interrupts raised. In that case the
driver will not see the interrupts which leads to I/O timeout.

This issue only happens when there are many I/O completions on a single
reply queue. This forces the driver to switch between the interrupt and IRQ
context.

Make the driver process the reply queue one more time after enabling the
IRQ.

Link: https://lore.kernel.org/linux-scsi/20201102072746.27410-1-sreekanth.reddy@broadcom.com/
Link: https://lore.kernel.org/r/20210528131307.25683-5-chandrakanth.patil@broadcom.com


Cc: Tomas Henzl <thenzl@redhat.com>
Reported-by: default avatarkernel test robot <lkp@intel.com>
Signed-off-by: default avatarChandrakanth Patil <chandrakanth.patil@broadcom.com>
Signed-off-by: default avatarSumit Saxena <sumit.saxena@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent ae6874ba
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -3745,6 +3745,7 @@ static void megasas_sync_irqs(unsigned long instance_addr)
		if (irq_ctx->irq_poll_scheduled) {
			irq_ctx->irq_poll_scheduled = false;
			enable_irq(irq_ctx->os_irq);
			complete_cmd_fusion(instance, irq_ctx->MSIxIndex, irq_ctx);
		}
	}
}
@@ -3776,6 +3777,7 @@ int megasas_irqpoll(struct irq_poll *irqpoll, int budget)
		irq_poll_complete(irqpoll);
		irq_ctx->irq_poll_scheduled = false;
		enable_irq(irq_ctx->os_irq);
		complete_cmd_fusion(instance, irq_ctx->MSIxIndex, irq_ctx);
	}

	return num_entries;
@@ -3792,6 +3794,7 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
{
	struct megasas_instance *instance =
		(struct megasas_instance *)instance_addr;
	struct megasas_irq_context *irq_ctx = NULL;
	u32 count, MSIxIndex;

	count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
@@ -3800,8 +3803,10 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
	if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR)
		return;

	for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++)
		complete_cmd_fusion(instance, MSIxIndex, NULL);
	for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++) {
		irq_ctx = &instance->irq_context[MSIxIndex];
		complete_cmd_fusion(instance, MSIxIndex, irq_ctx);
	}
}

/**