From a48353f6d5054f2d01d62e56a0d87bd606527cc3 Mon Sep 17 00:00:00 2001 From: Yaniv Gardi Date: Mon, 1 Feb 2016 15:02:40 +0200 Subject: scsi: ufs: clear outstanding_request bit in case query timeout When sending a query to the device returns with a timeout error, we clear the corresponding bit in the DOORBELL register but we don't clear the outstanding_request field as we should. This patch fixes this bug. Reviewed-by: Subhash Jadavani Reviewed-by: Gilad Broner Reviewed-by: Dolev Raviv Signed-off-by: Yaniv Gardi Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/ufs/ufshcd.c') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 8a34f61be679..4863e93d97be 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -363,6 +363,16 @@ static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos) ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR); } +/** + * ufshcd_outstanding_req_clear - Clear a bit in outstanding request field + * @hba: per adapter instance + * @tag: position of the bit to be cleared + */ +static inline void ufshcd_outstanding_req_clear(struct ufs_hba *hba, int tag) +{ + __clear_bit(tag, &hba->outstanding_reqs); +} + /** * ufshcd_get_lists_status - Check UCRDY, UTRLRDY and UTMRLRDY * @reg: Register value of host controller status @@ -1501,9 +1511,17 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba, if (!time_left) { err = -ETIMEDOUT; + dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n", + __func__, lrbp->task_tag); if (!ufshcd_clear_cmd(hba, lrbp->task_tag)) - /* sucessfully cleared the command, retry if needed */ + /* successfully cleared the command, retry if needed */ err = -EAGAIN; + /* + * in case of an error, after clearing the doorbell, + * we also need to clear the outstanding_request + * field in hba + */ + ufshcd_outstanding_req_clear(hba, lrbp->task_tag); } return err; @@ -3941,7 +3959,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) scsi_dma_unmap(cmd); spin_lock_irqsave(host->host_lock, flags); - __clear_bit(tag, &hba->outstanding_reqs); + ufshcd_outstanding_req_clear(hba, tag); hba->lrb[tag].cmd = NULL; spin_unlock_irqrestore(host->host_lock, flags); -- cgit v1.2.3