summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChandrakanth Patil <chandrakanth.patil@broadcom.com>2021-05-28 18:43:06 +0530
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-07-20 16:10:42 +0200
commit9896b67e1b5632d8125088d3a18de55cef579368 (patch)
tree04199a2f7b9f19f56274e732b41aaf9cc2febb03
parente8c75b5d88f255ac5dcc4a90ae0c300f0b171fe7 (diff)
scsi: megaraid_sas: Handle missing interrupts while re-enabling IRQs
[ Upstream commit 9bedd36e9146b34dda4d6994e3aa1d72bc6442c1 ] 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: kernel test robot <lkp@intel.com> Signed-off-by: Chandrakanth Patil <chandrakanth.patil@broadcom.com> 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>
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index ae7a3e154bb2..a78a702511fa 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -3716,6 +3716,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);
}
}
}
@@ -3747,6 +3748,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;
@@ -3763,6 +3765,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;
@@ -3771,8 +3774,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);
+ }
}
/**