| From 3382f9890be02262de63624ce8fd4ddbb6486696 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 28 May 2021 18:43:06 +0530 |
| Subject: scsi: megaraid_sas: Handle missing interrupts while re-enabling IRQs |
| |
| From: Chandrakanth Patil <chandrakanth.patil@broadcom.com> |
| |
| [ 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> |
| --- |
| 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 54f8a8073ca0..5abb84ebc0ed 100644 |
| --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c |
| +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c |
| @@ -3676,6 +3676,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); |
| } |
| } |
| } |
| @@ -3707,6 +3708,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; |
| @@ -3723,6 +3725,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; |
| @@ -3731,8 +3734,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); |
| + } |
| } |
| |
| /** |
| -- |
| 2.30.2 |
| |