From: Chandrakanth Patil chandrakanth.patil@broadcom.com
stable inclusion from stable-5.10.52 commit 5ac2428f2b9636b507970ce0ab4e7a71a53daaf1 bugzilla: 175542 https://gitee.com/openeuler/kernel/issues/I4DTKU
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
[ 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@br... Link: https://lore.kernel.org/r/20210528131307.25683-5-chandrakanth.patil@broadcom... 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 Signed-off-by: Chen Jun chenjun102@huawei.com Acked-by: Weilong Chen chenweilong@huawei.com Signed-off-by: Chen Jun chenjun102@huawei.com --- drivers/scsi/megaraid/megaraid_sas_fusion.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 562a18e341a0..b8ec6db532b0 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -3670,6 +3670,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); } } } @@ -3701,6 +3702,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; @@ -3717,6 +3719,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; @@ -3725,8 +3728,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); + } }
/**