Commit 7aa12d2f authored by Bao D. Nguyen's avatar Bao D. Nguyen Committed by Martin K. Petersen

scsi: ufs: core: Update the ufshcd_clear_cmds() functionality

In the ufshcd_clear_cmds(), the 2nd parameter would be the bit mask of the
command to be cleared in the transfer request door bell register. This bit
mask mechanism does not scale well in MCQ mode when the queue depth becomes
much greater than 64. Change the 2nd parameter to the function to be the
task_tag number of the corresponding bit to be cleared in the door bell
register.  By doing so, MCQ mode with a large queue depth can reuse this
function.

Since the behavior of this function is changed from handling multiple
commands into a single command, rename ufshcd_clear_cmds() into
ufshcd_clear_cmd().
Signed-off-by: default avatarBao D. Nguyen <quic_nguyenb@quicinc.com>
Link: https://lore.kernel.org/r/8411fb5363acc90519bced30ea2c2ac582ff2340.1685396241.git.quic_nguyenb@quicinc.comReviewed-by: default avatarBart Van Assche <bvanassche@acm.org>
Reviewed-by: default avatarStanley Chu <stanley.chu@mediatek.com>
Tested-by: default avatarStanley Chu <stanley.chu@mediatek.com>
Reviewed-by: default avatarCan Guo <quic_cang@quicinc.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent a8f9a36e
...@@ -2999,13 +2999,15 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba, ...@@ -2999,13 +2999,15 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba,
} }
/* /*
* Clear all the requests from the controller for which a bit has been set in * Clear the pending command in the controller and wait until
* @mask and wait until the controller confirms that these requests have been * the controller confirms that the command has been cleared.
* cleared. * @hba: per adapter instance
* @task_tag: The tag number of the command to be cleared.
*/ */
static int ufshcd_clear_cmds(struct ufs_hba *hba, u32 mask) static int ufshcd_clear_cmd(struct ufs_hba *hba, u32 task_tag)
{ {
unsigned long flags; unsigned long flags;
u32 mask = 1U << task_tag;
/* clear outstanding transaction before retry */ /* clear outstanding transaction before retry */
spin_lock_irqsave(hba->host->host_lock, flags); spin_lock_irqsave(hba->host->host_lock, flags);
...@@ -3106,7 +3108,7 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba, ...@@ -3106,7 +3108,7 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
err = -ETIMEDOUT; err = -ETIMEDOUT;
dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n", dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n",
__func__, lrbp->task_tag); __func__, lrbp->task_tag);
if (ufshcd_clear_cmds(hba, 1U << lrbp->task_tag) == 0) { if (ufshcd_clear_cmd(hba, lrbp->task_tag) == 0) {
/* successfully cleared the command, retry if needed */ /* successfully cleared the command, retry if needed */
err = -EAGAIN; err = -EAGAIN;
/* /*
...@@ -7279,7 +7281,7 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd) ...@@ -7279,7 +7281,7 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
unsigned long flags, pending_reqs = 0, not_cleared = 0; unsigned long flags, pending_reqs = 0, not_cleared = 0;
struct Scsi_Host *host; struct Scsi_Host *host;
struct ufs_hba *hba; struct ufs_hba *hba;
u32 pos; u32 pos, not_cleared_mask = 0;
int err; int err;
u8 resp = 0xF, lun; u8 resp = 0xF, lun;
...@@ -7302,17 +7304,20 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd) ...@@ -7302,17 +7304,20 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
hba->outstanding_reqs &= ~pending_reqs; hba->outstanding_reqs &= ~pending_reqs;
spin_unlock_irqrestore(&hba->outstanding_lock, flags); spin_unlock_irqrestore(&hba->outstanding_lock, flags);
if (ufshcd_clear_cmds(hba, pending_reqs) < 0) { for_each_set_bit(pos, &pending_reqs, hba->nutrs) {
if (ufshcd_clear_cmd(hba, pos) < 0) {
spin_lock_irqsave(&hba->outstanding_lock, flags); spin_lock_irqsave(&hba->outstanding_lock, flags);
not_cleared = pending_reqs & not_cleared = 1U << pos &
ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
hba->outstanding_reqs |= not_cleared; hba->outstanding_reqs |= not_cleared;
not_cleared_mask |= not_cleared;
spin_unlock_irqrestore(&hba->outstanding_lock, flags); spin_unlock_irqrestore(&hba->outstanding_lock, flags);
dev_err(hba->dev, "%s: failed to clear requests %#lx\n", dev_err(hba->dev, "%s: failed to clear request %d\n",
__func__, not_cleared); __func__, pos);
}
} }
__ufshcd_transfer_req_compl(hba, pending_reqs & ~not_cleared); __ufshcd_transfer_req_compl(hba, pending_reqs & ~not_cleared_mask);
out: out:
hba->req_abort_count = 0; hba->req_abort_count = 0;
...@@ -7409,7 +7414,7 @@ static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag) ...@@ -7409,7 +7414,7 @@ static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag)
goto out; goto out;
} }
err = ufshcd_clear_cmds(hba, 1U << tag); err = ufshcd_clear_cmd(hba, tag);
if (err) if (err)
dev_err(hba->dev, "%s: Failed clearing cmd at tag %d, err %d\n", dev_err(hba->dev, "%s: Failed clearing cmd at tag %d, err %d\n",
__func__, tag, err); __func__, tag, err);
......
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