Skip to content

Commit f1304d4

Browse files
Bao D. Nguyenmartinkpetersen
authored andcommitted
scsi: ufs: mcq: Added ufshcd_mcq_abort()
Add ufshcd_mcq_abort() to support UFS abort in MCQ mode. Signed-off-by: Bao D. Nguyen <[email protected]> Link: https://lore.kernel.org/r/c80c0adadf09ac1d909ed53b36d54737f62c2332.1685396241.git.quic_nguyenb@quicinc.com Reviewed-by: Stanley Chu <[email protected]> Tested-by: Stanley Chu <[email protected]> Reviewed-by: Can Guo <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent adf4526 commit f1304d4

File tree

3 files changed

+71
-5
lines changed

3 files changed

+71
-5
lines changed

drivers/ufs/core/ufs-mcq.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,3 +596,63 @@ static bool ufshcd_mcq_sqe_search(struct ufs_hba *hba,
596596
mutex_unlock(&hwq->sq_mutex);
597597
return ret;
598598
}
599+
600+
/**
601+
* ufshcd_mcq_abort - Abort the command in MCQ.
602+
* @cmd - The command to be aborted.
603+
*
604+
* Returns SUCCESS or FAILED error codes
605+
*/
606+
int ufshcd_mcq_abort(struct scsi_cmnd *cmd)
607+
{
608+
struct Scsi_Host *host = cmd->device->host;
609+
struct ufs_hba *hba = shost_priv(host);
610+
int tag = scsi_cmd_to_rq(cmd)->tag;
611+
struct ufshcd_lrb *lrbp = &hba->lrb[tag];
612+
struct ufs_hw_queue *hwq;
613+
int err = FAILED;
614+
615+
if (!ufshcd_cmd_inflight(lrbp->cmd)) {
616+
dev_err(hba->dev,
617+
"%s: skip abort. cmd at tag %d already completed.\n",
618+
__func__, tag);
619+
goto out;
620+
}
621+
622+
/* Skip task abort in case previous aborts failed and report failure */
623+
if (lrbp->req_abort_skip) {
624+
dev_err(hba->dev, "%s: skip abort. tag %d failed earlier\n",
625+
__func__, tag);
626+
goto out;
627+
}
628+
629+
hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd));
630+
631+
if (ufshcd_mcq_sqe_search(hba, hwq, tag)) {
632+
/*
633+
* Failure. The command should not be "stuck" in SQ for
634+
* a long time which resulted in command being aborted.
635+
*/
636+
dev_err(hba->dev, "%s: cmd found in sq. hwq=%d, tag=%d\n",
637+
__func__, hwq->id, tag);
638+
goto out;
639+
}
640+
641+
/*
642+
* The command is not in the submission queue, and it is not
643+
* in the completion queue either. Query the device to see if
644+
* the command is being processed in the device.
645+
*/
646+
if (ufshcd_try_to_abort_task(hba, tag)) {
647+
dev_err(hba->dev, "%s: device abort failed %d\n", __func__, err);
648+
lrbp->req_abort_skip = true;
649+
goto out;
650+
}
651+
652+
err = SUCCESS;
653+
if (ufshcd_cmd_inflight(lrbp->cmd))
654+
ufshcd_release_scsi_cmd(hba, lrbp);
655+
656+
out:
657+
return err;
658+
}

drivers/ufs/core/ufshcd-priv.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba,
8080

8181
bool ufshcd_cmd_inflight(struct scsi_cmnd *cmd);
8282
int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag);
83+
int ufshcd_mcq_abort(struct scsi_cmnd *cmd);
84+
int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag);
85+
void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
86+
struct ufshcd_lrb *lrbp);
8387

8488
#define UFSHCD_MCQ_IO_QUEUE_OFFSET 1
8589
#define SD_ASCII_STD true

drivers/ufs/core/ufshcd.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,6 @@ static int ufshcd_setup_hba_vreg(struct ufs_hba *hba, bool on);
300300
static int ufshcd_setup_vreg(struct ufs_hba *hba, bool on);
301301
static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
302302
struct ufs_vreg *vreg);
303-
static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag);
304303
static void ufshcd_wb_toggle_buf_flush_during_h8(struct ufs_hba *hba,
305304
bool enable);
306305
static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba);
@@ -5450,8 +5449,8 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
54505449
}
54515450

54525451
/* Release the resources allocated for processing a SCSI command. */
5453-
static void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
5454-
struct ufshcd_lrb *lrbp)
5452+
void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
5453+
struct ufshcd_lrb *lrbp)
54555454
{
54565455
struct scsi_cmnd *cmd = lrbp->cmd;
54575456

@@ -7389,7 +7388,7 @@ static void ufshcd_set_req_abort_skip(struct ufs_hba *hba, unsigned long bitmap)
73897388
*
73907389
* Returns zero on success, non-zero on failure
73917390
*/
7392-
static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag)
7391+
int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag)
73937392
{
73947393
struct ufshcd_lrb *lrbp = &hba->lrb[tag];
73957394
int err = 0;
@@ -7552,8 +7551,11 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
75527551
goto release;
75537552
}
75547553

7555-
if (is_mcq_enabled(hba))
7554+
if (is_mcq_enabled(hba)) {
7555+
/* MCQ mode. Branch off to handle abort for mcq mode */
7556+
err = ufshcd_mcq_abort(cmd);
75567557
goto release;
7558+
}
75577559

75587560
/* Skip task abort in case previous aborts failed and report failure */
75597561
if (lrbp->req_abort_skip) {

0 commit comments

Comments
 (0)