scsi: ufs: core: Rework ufshcd_eh_device_reset_handler()
Merge the MCQ mode and legacy mode loops into a single loop. This patch prepares for optimizing the hot path by removing the direct hba->lrb[] accesses from ufshcd_eh_device_reset_handler(). Reviewed-by: Avri Altman <avri.altman@sandisk.com> Signed-off-by: Bart Van Assche <bvanassche@acm.org> Link: https://patch.msgid.link/20251031204029.2883185-17-bvanassche@acm.org Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
committed by
Martin K. Petersen
parent
63a5b959c8
commit
f18fac1e2b
@@ -7566,6 +7566,36 @@ int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *r
|
||||
return err ? : result;
|
||||
}
|
||||
|
||||
static bool ufshcd_clear_lu_cmds(struct request *req, void *priv)
|
||||
{
|
||||
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
|
||||
struct scsi_device *sdev = cmd->device;
|
||||
struct Scsi_Host *shost = sdev->host;
|
||||
struct ufs_hba *hba = shost_priv(shost);
|
||||
const u64 lun = *(u64 *)priv;
|
||||
const u32 tag = req->tag;
|
||||
|
||||
if (sdev->lun != lun)
|
||||
return true;
|
||||
|
||||
if (ufshcd_clear_cmd(hba, tag) < 0) {
|
||||
dev_err(hba->dev, "%s: failed to clear request %d\n", __func__,
|
||||
tag);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hba->mcq_enabled) {
|
||||
struct ufs_hw_queue *hwq = ufshcd_mcq_req_to_hwq(hba, req);
|
||||
|
||||
if (hwq)
|
||||
ufshcd_mcq_poll_cqe_lock(hba, hwq);
|
||||
return true;
|
||||
}
|
||||
|
||||
ufshcd_compl_one_cqe(hba, tag, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_eh_device_reset_handler() - Reset a single logical unit.
|
||||
* @cmd: SCSI command pointer
|
||||
@@ -7574,12 +7604,8 @@ int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *r
|
||||
*/
|
||||
static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
|
||||
{
|
||||
unsigned long flags, pending_reqs = 0, not_cleared = 0;
|
||||
struct Scsi_Host *host;
|
||||
struct ufs_hba *hba;
|
||||
struct ufs_hw_queue *hwq;
|
||||
struct ufshcd_lrb *lrbp;
|
||||
u32 pos, not_cleared_mask = 0;
|
||||
int err;
|
||||
u8 resp = 0xF, lun;
|
||||
|
||||
@@ -7588,50 +7614,16 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
|
||||
|
||||
lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun);
|
||||
err = ufshcd_issue_tm_cmd(hba, lun, 0, UFS_LOGICAL_RESET, &resp);
|
||||
if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
|
||||
if (!err)
|
||||
err = resp;
|
||||
goto out;
|
||||
if (err) {
|
||||
} else if (resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
|
||||
err = resp;
|
||||
} else {
|
||||
/* clear the commands that were pending for corresponding LUN */
|
||||
blk_mq_tagset_busy_iter(&hba->host->tag_set,
|
||||
ufshcd_clear_lu_cmds,
|
||||
&cmd->device->lun);
|
||||
}
|
||||
|
||||
if (hba->mcq_enabled) {
|
||||
for (pos = 0; pos < hba->nutrs; pos++) {
|
||||
lrbp = &hba->lrb[pos];
|
||||
if (ufshcd_cmd_inflight(lrbp->cmd) &&
|
||||
lrbp->lun == lun) {
|
||||
ufshcd_clear_cmd(hba, pos);
|
||||
hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(lrbp->cmd));
|
||||
ufshcd_mcq_poll_cqe_lock(hba, hwq);
|
||||
}
|
||||
}
|
||||
err = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* clear the commands that were pending for corresponding LUN */
|
||||
spin_lock_irqsave(&hba->outstanding_lock, flags);
|
||||
for_each_set_bit(pos, &hba->outstanding_reqs, hba->nutrs)
|
||||
if (hba->lrb[pos].lun == lun)
|
||||
__set_bit(pos, &pending_reqs);
|
||||
hba->outstanding_reqs &= ~pending_reqs;
|
||||
spin_unlock_irqrestore(&hba->outstanding_lock, flags);
|
||||
|
||||
for_each_set_bit(pos, &pending_reqs, hba->nutrs) {
|
||||
if (ufshcd_clear_cmd(hba, pos) < 0) {
|
||||
spin_lock_irqsave(&hba->outstanding_lock, flags);
|
||||
not_cleared = 1U << pos &
|
||||
ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
|
||||
hba->outstanding_reqs |= not_cleared;
|
||||
not_cleared_mask |= not_cleared;
|
||||
spin_unlock_irqrestore(&hba->outstanding_lock, flags);
|
||||
|
||||
dev_err(hba->dev, "%s: failed to clear request %d\n",
|
||||
__func__, pos);
|
||||
}
|
||||
}
|
||||
__ufshcd_transfer_req_compl(hba, pending_reqs & ~not_cleared_mask);
|
||||
|
||||
out:
|
||||
hba->req_abort_count = 0;
|
||||
ufshcd_update_evt_hist(hba, UFS_EVT_DEV_RESET, (u32)err);
|
||||
if (!err) {
|
||||
|
||||
Reference in New Issue
Block a user