fix abort defect
Subsystems (4)
v5 cover fix abort defect
From: Peter Wang <[email protected]>
This series fixes MCQ and SDB abort defect.
V5:
- Change flag name.
- Add err handler check before set flag true.
- Amend comment and patch description.
V4:
- Remove nullify SQ entry abort requeue.
- Add more comment for flag usage and set description.
- Fix build warning.
V3:
- Change comment and use variable(rtc) for error print
- Change flag name and move flag set before ufshcd_clear_cmd
- Add SDB mode clear UTRLCLR tag receive OCS_ABORTED requeue
V2:
- Fix mcq_enabled build error.
Peter Wang (2):
ufs: core: fix the issue of ICU failure
ufs: core: requeue aborted request
drivers/ufs/core/ufs-mcq.c | 15 ++++++++------- drivers/ufs/core/ufshcd.c | 35 ++++++++++++++++++++--------------- include/ufs/ufshcd.h | 3 +++ 3 files changed, 31 insertions(+), 22 deletions(-)
Signature · 1 line
2.45.2
PATCH v5 1/2 ufs: core: fix the issue of ICU failure
From: Peter Wang <[email protected]>
When setting the ICU bit without using read-modify-write, SQRTCy will restart SQ again and receive an RTC return error code 2 (Failure - SQ not stopped).
Additionally, the error log has been modified so that this type of error can be observed.
--- drivers/ufs/core/ufs-mcq.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
drivers/ufs/core/ufs-mcq.c +8 -7
@@ -539,7 +539,7 @@ int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag)struct scsi_cmnd *cmd = lrbp->cmd;struct ufs_hw_queue *hwq;void __iomem *reg, *opr_sqd_base; -u32 nexus, id, val; +u32 nexus, id, val, rtc;int err;if (hba->quirks &UFSHCD_QUIRK_MCQ_BROKEN_RTC )
@@ -569,17 +569,18 @@ int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag) opr_sqd_base =mcq_opr_base (hba,OPR_SQD , id);writel (nexus, opr_sqd_base +REG_SQCTI ); -/* SQRTCy.ICU = 1 */ -writel (SQ_ICU , opr_sqd_base +REG_SQRTC ); +/* Initiate Cleanup */ +writel (readl (opr_sqd_base +REG_SQRTC ) |SQ_ICU , + opr_sqd_base +REG_SQRTC );/* Poll SQRTSy.CUS = 1. Return result from SQRTSy.RTC */ reg = opr_sqd_base +REG_SQRTS ; err =read_poll_timeout (readl, val, val &SQ_CUS ,20 ,MCQ_POLL_US , false, reg); -if (err) -dev_err (hba->dev,"%s: failed. hwq=%d, tag=%d err=%ld\n" , - __func__, id, task_tag, -FIELD_GET (SQ_ICU_ERR_CODE_MASK ,readl (reg))); + rtc =FIELD_GET (SQ_ICU_ERR_CODE_MASK ,readl (reg)); +if (err || rtc) +dev_err (hba->dev,"%s: failed. hwq=%d, tag=%d err=%d RTC=%d\n" , + __func__, id, task_tag, err, rtc);if (ufshcd_mcq_sq_start (hba, hwq)) err = -ETIMEDOUT ;
Signature · 1 line
2.45.2
PATCH v5 2/2 ufs: core: requeue aborted request
In reply to [email protected]From: Peter Wang <[email protected]>
ufshcd_abort_all forcibly aborts all on-going commands and the host controller will automatically fill in the OCS field of the corresponding response with OCS_ABORTED based on different working modes.
MCQ mode: aborts a command using SQ cleanup, The host controller will post a Completion Queue entry with OCS = ABORTED.
SDB mode: aborts a command using UTRLCLR. Task Management response which means a Transfer Request was aborted.
For these two cases, set a flag to notify SCSI to requeue the command after receiving response with OCS_ABORTED.
--- drivers/ufs/core/ufshcd.c | 35 ++++++++++++++++++++--------------- include/ufs/ufshcd.h | 3 +++ 2 files changed, 23 insertions(+), 15 deletions(-)
drivers/ufs/core/ufshcd.c +20 -15
@@ -3006,6 +3006,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)ufshcd_prepare_lrbp_crypto (scsi_cmd_to_rq (cmd), lrbp); lrbp->req_abort_skip = false; + lrbp->abort_initiated_by_eh = false;ufshcd_comp_scsi_upiu (hba, lrbp);
@@ -5404,7 +5405,10 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, }break ;case OCS_ABORTED : - result |=DID_ABORT <<16 ; +if (lrbp->abort_initiated_by_eh) + result |=DID_REQUEUE <<16 ; +else + result |=DID_ABORT <<16 ;break ;case OCS_INVALID_COMMAND_STATUS : result |=DID_REQUEUE <<16 ;
@@ -6471,26 +6475,12 @@ static bool ufshcd_abort_one(struct request *rq, void *priv)struct scsi_device *sdev = cmd->device;struct Scsi_Host *shost = sdev->host;struct ufs_hba *hba =shost_priv (shost); -struct ufshcd_lrb *lrbp = &hba->lrb[tag]; -struct ufs_hw_queue *hwq; -unsigned long flags; *ret =ufshcd_try_to_abort_task (hba, tag);dev_err (hba->dev,"Aborting tag %d / CDB %#02x %s\n" , tag, hba->lrb[tag].cmd ? hba->lrb[tag].cmd->cmnd[0 ] :-1 , *ret ?"failed" :"succeeded" ); -/* Release cmd in MCQ mode if abort succeeds */ -if (hba->mcq_enabled && (*ret ==0 )) { - hwq =ufshcd_mcq_req_to_hwq (hba,scsi_cmd_to_rq (lrbp->cmd)); -if (!hwq) -return 0 ; -spin_lock_irqsave (&hwq->cq_lock, flags); -if (ufshcd_cmd_inflight (lrbp->cmd)) -ufshcd_release_scsi_cmd (hba, lrbp); -spin_unlock_irqrestore (&hwq->cq_lock, flags); - } -return *ret ==0 ; }
@@ -7561,6 +7551,21 @@ int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag) goto out; } +/* +* When the host software receives a "FUNCTION COMPLETE", set flag +* to requeue command after receive response with OCS_ABORTED +* SDB mode: UTRLCLR Task Management response which means a Transfer +* Request was aborted. +* MCQ mode: Host will post to CQ with OCS_ABORTED after SQ cleanup +* +* This flag is set because error handler ufshcd_abort_all forcibly +* aborts all commands, and the host controller will automatically +* fill in the OCS field of the corresponding response with OCS_ABORTED. +* Therefore, upon receiving this response, it needs to be requeued. +*/ +if (!err) + lrbp->abort_initiated_by_eh = true; + err =ufshcd_clear_cmd (hba, tag);if (err) dev_err(hba->dev, "%s: Failed clearing cmd at tag %d, err %d\n",
include/ufs/ufshcd.h +3 -0
@@ -173,6 +173,8 @@ struct ufs_pm_lvl_states {* @crypto_key_slot: the key slot to use for inline crypto (-1 if none) * @data_unit_num: the data unit number for the first block for inline crypto * @req_abort_skip: skip request abort task flag +* @abort_initiated_by_eh: The flag is specifically used to handle +* ufshcd_err_handler forcibly aborts. */ struct ufshcd_lrb {struct utp_transfer_req_desc *utr_descriptor_ptr;
@@ -202,6 +204,7 @@ struct ufshcd_lrb {#endif bool req_abort_skip; +bool abort_initiated_by_eh; };/**
Signature · 1 line
2.45.2