Skip to content

Commit 93b6c5d

Browse files
Stanley Chumartinkpetersen
authored andcommitted
scsi: ufs: Fix possible infinite loop in ufshcd_hold
In ufshcd_suspend(), after clk-gating is suspended and link is set as Hibern8 state, ufshcd_hold() is still possibly invoked before ufshcd_suspend() returns. For example, MediaTek's suspend vops may issue UIC commands which would call ufshcd_hold() during the command issuing flow. Now if UFSHCD_CAP_HIBERN8_WITH_CLK_GATING capability is enabled, then ufshcd_hold() may enter infinite loops because there is no clk-ungating work scheduled or pending. In this case, ufshcd_hold() shall just bypass, and keep the link as Hibern8 state. Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Avri Altman <[email protected]> Co-developed-by: Andy Teng <[email protected]> Signed-off-by: Andy Teng <[email protected]> Signed-off-by: Stanley Chu <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent fa39ab5 commit 93b6c5d

File tree

1 file changed

+4
-1
lines changed

1 file changed

+4
-1
lines changed

drivers/scsi/ufs/ufshcd.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1561,6 +1561,7 @@ static void ufshcd_ungate_work(struct work_struct *work)
15611561
int ufshcd_hold(struct ufs_hba *hba, bool async)
15621562
{
15631563
int rc = 0;
1564+
bool flush_result;
15641565
unsigned long flags;
15651566

15661567
if (!ufshcd_is_clkgating_allowed(hba))
@@ -1592,7 +1593,9 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
15921593
break;
15931594
}
15941595
spin_unlock_irqrestore(hba->host->host_lock, flags);
1595-
flush_work(&hba->clk_gating.ungate_work);
1596+
flush_result = flush_work(&hba->clk_gating.ungate_work);
1597+
if (hba->clk_gating.is_suspended && !flush_result)
1598+
goto out;
15961599
spin_lock_irqsave(hba->host->host_lock, flags);
15971600
goto start;
15981601
}

0 commit comments

Comments
 (0)