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 <subhashj@codeaurora.org>
This commit is contained in:
Subhash Jadavani 2014-11-20 21:03:49 -08:00 committed by David Keitel
parent b19709a5c3
commit c991cc0db0

View file

@ -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);