mirror of
https://github.com/torvalds/linux.git
synced 2024-11-14 08:02:07 +00:00
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: 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>
This commit is contained in:
parent
ae6874ba4b
commit
9bedd36e91
@ -3745,6 +3745,7 @@ static void megasas_sync_irqs(unsigned long instance_addr)
|
|||||||
if (irq_ctx->irq_poll_scheduled) {
|
if (irq_ctx->irq_poll_scheduled) {
|
||||||
irq_ctx->irq_poll_scheduled = false;
|
irq_ctx->irq_poll_scheduled = false;
|
||||||
enable_irq(irq_ctx->os_irq);
|
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_poll_complete(irqpoll);
|
||||||
irq_ctx->irq_poll_scheduled = false;
|
irq_ctx->irq_poll_scheduled = false;
|
||||||
enable_irq(irq_ctx->os_irq);
|
enable_irq(irq_ctx->os_irq);
|
||||||
|
complete_cmd_fusion(instance, irq_ctx->MSIxIndex, irq_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return num_entries;
|
return num_entries;
|
||||||
@ -3792,6 +3794,7 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
|
|||||||
{
|
{
|
||||||
struct megasas_instance *instance =
|
struct megasas_instance *instance =
|
||||||
(struct megasas_instance *)instance_addr;
|
(struct megasas_instance *)instance_addr;
|
||||||
|
struct megasas_irq_context *irq_ctx = NULL;
|
||||||
u32 count, MSIxIndex;
|
u32 count, MSIxIndex;
|
||||||
|
|
||||||
count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
|
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)
|
if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++)
|
for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++) {
|
||||||
complete_cmd_fusion(instance, MSIxIndex, NULL);
|
irq_ctx = &instance->irq_context[MSIxIndex];
|
||||||
|
complete_cmd_fusion(instance, MSIxIndex, irq_ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user