blob: e19f1d2fbeb61da872de84d74161ff0fee5f086b [file] [log] [blame]
From 70b67a437841a3bd29f844cb295b5af69e9ebdc1 Mon Sep 17 00:00:00 2001
From: Can Guo <>
Date: Mon, 10 Feb 2020 19:40:48 -0800
Subject: [PATCH] scsi: ufs: Fix ufshcd_hold() caused scheduling while atomic
commit c63d6099a7959ecc919b2549dc6b71f53521f819 upstream.
The async version of ufshcd_hold(async == true), which is only called in
queuecommand path as for now, is expected to work in atomic context, thus
it should not sleep or schedule out. When it runs into the condition that
clocks are ON but link is still in hibern8 state, it should bail out
without flushing the clock ungate work.
Fixes: f2a785ac2312 ("scsi: ufshcd: Fix race between clk scaling and ungate work")
Reviewed-by: Hongwu Su <>
Reviewed-by: Asutosh Das <>
Reviewed-by: Bean Huo <>
Reviewed-by: Stanley Chu <>
Signed-off-by: Can Guo <>
Signed-off-by: Martin K. Petersen <>
Signed-off-by: Paul Gortmaker <>
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 60f2a989c872..c6f8745fd32c 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1537,6 +1537,11 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
if (ufshcd_can_hibern8_during_gating(hba) &&
ufshcd_is_link_hibern8(hba)) {
+ if (async) {
+ rc = -EAGAIN;
+ hba->clk_gating.active_reqs--;
+ break;
+ }
spin_unlock_irqrestore(hba->host->host_lock, flags);
spin_lock_irqsave(hba->host->host_lock, flags);