diff options
| author | Subhash Jadavani <subhashj@codeaurora.org> | 2015-06-08 13:13:16 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 10:59:55 -0700 |
| commit | 4d53145d9793da4f24c0923de350303b2f09d3fb (patch) | |
| tree | 98d447d10ba7ecfa1ee0cca1be11e545025b4325 | |
| parent | 88abe3727bb5ed5c60e52f3c35fff9620d44ffbb (diff) | |
scsi: ufs: fix timeout waiting for doorbell clear
ufshcd_wait_for_doorbell_clr() function should wait for the
doorbell to be cleared until the specified timeout period but
current implementation really seems to be waiting until the doorbell
is cleared (instead of timing out after timeout period), this
change fixes this issue.
Change-Id: I0dee77db7d319250b5fab5f77e51175ea7d1d664
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
| -rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index c2318eaa7265..cc567cd7572e 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -3769,8 +3769,8 @@ int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, u64 wait_timeout_us) int ret = 0; u32 tm_doorbell; u32 tr_doorbell; - bool timeout = false; - ktime_t start = ktime_get(); + bool timeout = false, do_last_check = false; + ktime_t start; ufshcd_hold_all(hba); spin_lock_irqsave(hba->host->host_lock, flags); @@ -3783,19 +3783,29 @@ int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, u64 wait_timeout_us) * Wait for all the outstanding tasks/transfer requests. * Verify by checking the doorbell registers are clear. */ + start = ktime_get(); do { tm_doorbell = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL); tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); if (!tm_doorbell && !tr_doorbell) { timeout = false; break; + } else if (do_last_check) { + break; } spin_unlock_irqrestore(hba->host->host_lock, flags); schedule(); if (ktime_to_us(ktime_sub(ktime_get(), start)) > - wait_timeout_us) + wait_timeout_us) { timeout = true; + /* + * We might have scheduled out for long time so make + * sure to check if doorbells are cleared by this time + * or not. + */ + do_last_check = true; + } spin_lock_irqsave(hba->host->host_lock, flags); } while (tm_doorbell || tr_doorbell); |
