From c991cc0db038ff1a61bee2261be74a3de71a1d4c Mon Sep 17 00:00:00 2001 From: Subhash Jadavani Date: Thu, 20 Nov 2014 21:03:49 -0800 Subject: [PATCH] scsi: ufs: fix possible unclocked register access during hibern8 exit ufshcd_queuecommand() function calls ufshcd_hibern8_hold() to bring the link out of hibern8 asynchronously. If the link was in hibern8 state then it schedules a work to execute the hibern8 without any timeout and returns error back to ufshcd_queuecommand(). ufshcd_queuecommand() calls ufshcd_release() which schedules the clock gating work to be executed after clock gating timeout (50ms at this moment). Ideally hibern8 exit work should have finished much before clock gating work starts execution but it may not be true on heavily loaded system. To protect this race, hibern8 exit work should make sure that clocks are running (by calling ufshcd_hold()) before executing hibern8 exit. Change-Id: I572b26881277886f5ec17b0eed96ee9e59ca1fbf Signed-off-by: Subhash Jadavani --- drivers/scsi/ufs/ufshcd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index ff15788e0e1a..51b9a1c4af1c 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1475,7 +1475,9 @@ static void ufshcd_hibern8_exit_work(struct work_struct *work) /* Exit from hibern8 */ if (ufshcd_is_link_hibern8(hba)) { + ufshcd_hold(hba, false); ret = ufshcd_uic_hibern8_exit(hba); + ufshcd_release(hba); if (!ret) { spin_lock_irqsave(hba->host->host_lock, flags); ufshcd_set_link_active(hba);