Skip to content

Commit 3c7ac40

Browse files
superna9999martinkpetersen
authored andcommitted
scsi: ufs: core: Delegate the interrupt service routine to a threaded IRQ handler
On systems with a large number request slots and unavailable MCQ ESI, the current design of the interrupt handler can delay handling of other subsystems interrupts causing display artifacts, GPU stalls or system firmware requests timeouts. Since the interrupt routine can take quite some time, it's preferable to move it to a threaded handler and leave the hard interrupt handler wake up the threaded interrupt routine, the interrupt line would be masked until the processing is finished in the thread thanks to the IRQS_ONESHOT flag. When MCQ & ESI interrupts are enabled the I/O completions are now directly handled in the "hard" interrupt routine to keep IOPs high since queues handling is done in separate per-queue interrupt routines. This fixes all encountered issued when running FIO tests on the Qualcomm SM8650 platform. Example of errors reported on a loaded system: [drm:dpu_encoder_frame_done_timeout:2706] [dpu error]enc32 frame done timeout msm_dpu ae01000.display-controller: [drm:hangcheck_handler [msm]] *ERROR* 67.5.20.1: hangcheck detected gpu lockup rb 2! msm_dpu ae01000.display-controller: [drm:hangcheck_handler [msm]] *ERROR* 67.5.20.1: completed fence: 74285 msm_dpu ae01000.display-controller: [drm:hangcheck_handler [msm]] *ERROR* 67.5.20.1: submitted fence: 74286 Error sending AMC RPMH requests (-110) Signed-off-by: Neil Armstrong <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Bart Van Assche <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 2d6c7bc commit 3c7ac40

File tree

1 file changed

+27
-3
lines changed

1 file changed

+27
-3
lines changed

drivers/ufs/core/ufshcd.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6971,15 +6971,15 @@ static irqreturn_t ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)
69716971
}
69726972

69736973
/**
6974-
* ufshcd_intr - Main interrupt service routine
6974+
* ufshcd_threaded_intr - Threaded interrupt service routine
69756975
* @irq: irq number
69766976
* @__hba: pointer to adapter instance
69776977
*
69786978
* Return:
69796979
* IRQ_HANDLED - If interrupt is valid
69806980
* IRQ_NONE - If invalid interrupt
69816981
*/
6982-
static irqreturn_t ufshcd_intr(int irq, void *__hba)
6982+
static irqreturn_t ufshcd_threaded_intr(int irq, void *__hba)
69836983
{
69846984
u32 last_intr_status, intr_status, enabled_intr_status = 0;
69856985
irqreturn_t retval = IRQ_NONE;
@@ -7018,6 +7018,29 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)
70187018
return retval;
70197019
}
70207020

7021+
/**
7022+
* ufshcd_intr - Main interrupt service routine
7023+
* @irq: irq number
7024+
* @__hba: pointer to adapter instance
7025+
*
7026+
* Return:
7027+
* IRQ_HANDLED - If interrupt is valid
7028+
* IRQ_WAKE_THREAD - If handling is moved to threaded handled
7029+
* IRQ_NONE - If invalid interrupt
7030+
*/
7031+
static irqreturn_t ufshcd_intr(int irq, void *__hba)
7032+
{
7033+
struct ufs_hba *hba = __hba;
7034+
7035+
/* Move interrupt handling to thread when MCQ & ESI are not enabled */
7036+
if (!hba->mcq_enabled || !hba->mcq_esi_enabled)
7037+
return IRQ_WAKE_THREAD;
7038+
7039+
/* Directly handle interrupts since MCQ ESI handlers does the hard job */
7040+
return ufshcd_sl_intr(hba, ufshcd_readl(hba, REG_INTERRUPT_STATUS) &
7041+
ufshcd_readl(hba, REG_INTERRUPT_ENABLE));
7042+
}
7043+
70217044
static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag)
70227045
{
70237046
int err = 0;
@@ -10577,7 +10600,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
1057710600
ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
1057810601

1057910602
/* IRQ registration */
10580-
err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
10603+
err = devm_request_threaded_irq(dev, irq, ufshcd_intr, ufshcd_threaded_intr,
10604+
IRQF_ONESHOT | IRQF_SHARED, UFSHCD, hba);
1058110605
if (err) {
1058210606
dev_err(hba->dev, "request irq failed\n");
1058310607
goto out_disable;

0 commit comments

Comments
 (0)