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. Change-Id: Ia7e0aa29b0d822742654ba206a5837b9091fdb4a Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
This commit is contained in:
parent
5cdbfe11ca
commit
5e500d99d2
1 changed files with 20 additions and 4 deletions
|
@ -702,6 +702,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
|
||||
|
@ -2588,8 +2598,14 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
|
|||
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;
|
||||
|
@ -4668,7 +4684,7 @@ void ufshcd_abort_outstanding_transfer_requests(struct ufs_hba *hba, int result)
|
|||
lrbp->cmd = NULL;
|
||||
/* Clear pending transfer requests */
|
||||
ufshcd_clear_cmd(hba, index);
|
||||
__clear_bit(index, &hba->outstanding_reqs);
|
||||
ufshcd_outstanding_req_clear(hba, index);
|
||||
clear_bit_unlock(index, &hba->lrb_in_use);
|
||||
/* Do not touch lrbp after scsi done */
|
||||
cmd->scsi_done(cmd);
|
||||
|
@ -4677,7 +4693,7 @@ void ufshcd_abort_outstanding_transfer_requests(struct ufs_hba *hba, int result)
|
|||
if (hba->dev_cmd.complete) {
|
||||
ufshcd_cond_add_cmd_trace(hba, index,
|
||||
"dev_failed");
|
||||
__clear_bit(index, &hba->outstanding_reqs);
|
||||
ufshcd_outstanding_req_clear(hba, index);
|
||||
complete(hba->dev_cmd.complete);
|
||||
}
|
||||
}
|
||||
|
@ -5794,7 +5810,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);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue