Skip to content

Commit 7f6ba4f

Browse files
Venkat Gopalakrishnanmartinkpetersen
authored andcommitted
scsi: ufs: make sure all interrupts are processed
As multiple requests are submitted to the ufs host controller in parallel there could be instances where the command completion interrupt arrives later for a request that is already processed earlier as the corresponding doorbell was cleared when handling the previous interrupt. Read the interrupt status in a loop after processing the received interrupt to catch such interrupts and handle it. Signed-off-by: Venkat Gopalakrishnan <[email protected]> Signed-off-by: Asutosh Das <[email protected]> Reviewed-by: Subhash Jadavani <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 69a6fff commit 7f6ba4f

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

drivers/scsi/ufs/ufshcd.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5489,19 +5489,30 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)
54895489
u32 intr_status, enabled_intr_status;
54905490
irqreturn_t retval = IRQ_NONE;
54915491
struct ufs_hba *hba = __hba;
5492+
int retries = hba->nutrs;
54925493

54935494
spin_lock(hba->host->host_lock);
54945495
intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
5495-
enabled_intr_status =
5496-
intr_status & ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
54975496

5498-
if (intr_status)
5499-
ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
5497+
/*
5498+
* There could be max of hba->nutrs reqs in flight and in worst case
5499+
* if the reqs get finished 1 by 1 after the interrupt status is
5500+
* read, make sure we handle them by checking the interrupt status
5501+
* again in a loop until we process all of the reqs before returning.
5502+
*/
5503+
do {
5504+
enabled_intr_status =
5505+
intr_status & ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
5506+
if (intr_status)
5507+
ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
5508+
if (enabled_intr_status) {
5509+
ufshcd_sl_intr(hba, enabled_intr_status);
5510+
retval = IRQ_HANDLED;
5511+
}
5512+
5513+
intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
5514+
} while (intr_status && --retries);
55005515

5501-
if (enabled_intr_status) {
5502-
ufshcd_sl_intr(hba, enabled_intr_status);
5503-
retval = IRQ_HANDLED;
5504-
}
55055516
spin_unlock(hba->host->host_lock);
55065517
return retval;
55075518
}

0 commit comments

Comments
 (0)