Commit a48353f6 authored by Yaniv Gardi's avatar Yaniv Gardi Committed by Martin K. Petersen

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: default avatarSubhash Jadavani <subhashj@codeaurora.org>
Reviewed-by: default avatarGilad Broner <gbroner@codeaurora.org>
Reviewed-by: default avatarDolev Raviv <draviv@codeaurora.org>
Signed-off-by: default avatarYaniv Gardi <ygardi@codeaurora.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 14497328
...@@ -363,6 +363,16 @@ static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos) ...@@ -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_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 * ufshcd_get_lists_status - Check UCRDY, UTRLRDY and UTMRLRDY
* @reg: Register value of host controller status * @reg: Register value of host controller status
...@@ -1501,9 +1511,17 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba, ...@@ -1501,9 +1511,17 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
if (!time_left) { if (!time_left) {
err = -ETIMEDOUT; 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)) if (!ufshcd_clear_cmd(hba, lrbp->task_tag))
/* sucessfully cleared the command, retry if needed */ /* successfully cleared the command, retry if needed */
err = -EAGAIN; 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; return err;
...@@ -3941,7 +3959,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) ...@@ -3941,7 +3959,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
scsi_dma_unmap(cmd); scsi_dma_unmap(cmd);
spin_lock_irqsave(host->host_lock, flags); spin_lock_irqsave(host->host_lock, flags);
__clear_bit(tag, &hba->outstanding_reqs); ufshcd_outstanding_req_clear(hba, tag);
hba->lrb[tag].cmd = NULL; hba->lrb[tag].cmd = NULL;
spin_unlock_irqrestore(host->host_lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment