Two fixes for task management request implementation
v4 cover Two fixes for task management request implementation
These fixes are based on Jaegeuk's change - https://git.kernel.org/mkp/scsi/c/eeb1b55b6e25
Change since v3:
- Deleted the 2nd change
- Incorporated Bart's comments
Change since v2:
- Split one change into 3 changes
Change since v1:
- Typo fixed
Can Guo (2):
scsi: ufs: Fix task management request completion timeout
scsi: ufs: Fix wrong Task Tag used in task management request UPIUs
drivers/scsi/ufs/ufshcd.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-)
Signature · 1 line
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
PATCH v4 1/2 scsi: ufs: Fix task management request completion timeout
ufshcd_tmc_handler() calls blk_mq_tagset_busy_iter(fn = ufshcd_compl_tm()), but since blk_mq_tagset_busy_iter() only iterates over all reserved tags and requests which are not in IDLE state, ufshcd_compl_tm() never gets a chance to run. Thus, TMR always ends up with completion timeout. Fix it by calling blk_mq_start_request() in __ufshcd_issue_tm_cmd().
--- drivers/scsi/ufs/ufshcd.c | 1 + 1 file changed, 1 insertion(+)
drivers/scsi/ufs/ufshcd.c +1 -0
@@ -6464,6 +6464,7 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,spin_lock_irqsave (host->host_lock, flags); task_tag = hba->nutrs + free_slot; +blk_mq_start_request (req); treq->req_header.dword_0 |=cpu_to_be32 (task_tag);
Signature · 1 line
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
PATCH v4 2/2 scsi: ufs: Fix wrong Task Tag used in task management request UPIUs
In reply to Can GuoIn __ufshcd_issue_tm_cmd(), it is not right to use hba->nutrs + req->tag as the Task Tag in one TMR UPIU. Directly use req->tag as the Task Tag.
--- drivers/scsi/ufs/ufshcd.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-)
drivers/scsi/ufs/ufshcd.c +13 -16
@@ -6446,38 +6446,35 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,DECLARE_COMPLETION_ONSTACK (wait);struct request *req;unsigned long flags; -int free_slot, task_tag, err; +int task_tag, err;/* -* Get free slot, sleep if slots are unavailable. -* Even though we use wait_event() which sleeps indefinitely, -* the maximum wait time is bounded by %TM_CMD_TIMEOUT. +* blk_get_request() is used here only to get a free tag. */ req =blk_get_request (q,REQ_OP_DRV_OUT ,0 );if (IS_ERR (req))return PTR_ERR (req); req->end_io_data = &wait; - free_slot = req->tag;WARN_ON_ONCE (free_slot <0 || free_slot >= hba->nutmrs);ufshcd_hold (hba, false);spin_lock_irqsave (host->host_lock, flags); - task_tag = hba->nutrs + free_slot;blk_mq_start_request (req); + task_tag = req->tag; treq->req_header.dword_0 |=cpu_to_be32 (task_tag); -memcpy (hba->utmrdl_base_addr + free_slot, treq,sizeof (*treq)); -ufshcd_vops_setup_task_mgmt (hba, free_slot, tm_function); +memcpy (hba->utmrdl_base_addr + task_tag, treq,sizeof (*treq)); +ufshcd_vops_setup_task_mgmt (hba, task_tag, tm_function);/* send command to the controller */ -__set_bit (free_slot, &hba->outstanding_tasks); +__set_bit (task_tag, &hba->outstanding_tasks);/* Make sure descriptors are ready before ringing the task doorbell */ wmb (); -ufshcd_writel (hba,1 << free_slot,REG_UTP_TASK_REQ_DOOR_BELL ); +ufshcd_writel (hba,1 << task_tag,REG_UTP_TASK_REQ_DOOR_BELL );/* Make sure that doorbell is committed immediately */ wmb ();
@@ -6497,24 +6494,24 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,ufshcd_add_tm_upiu_trace (hba, task_tag,UFS_TM_ERR );dev_err (hba->dev,"%s: task management cmd 0x%.2x timed-out\n" , __func__, tm_function); -if (ufshcd_clear_tm_cmd (hba, free_slot)) -dev_WARN (hba->dev,"%s: unable clear tm cmd (slot %d) after timeout\n" , - __func__, free_slot); +if (ufshcd_clear_tm_cmd (hba, task_tag)) +dev_WARN (hba->dev,"%s: unable to clear tm cmd (slot %d) after timeout\n" , + __func__, task_tag); err = -ETIMEDOUT ; }else { err =0 ; -memcpy (treq, hba->utmrdl_base_addr + free_slot,sizeof (*treq)); +memcpy (treq, hba->utmrdl_base_addr + task_tag,sizeof (*treq));ufshcd_add_tm_upiu_trace (hba, task_tag,UFS_TM_COMP ); }spin_lock_irqsave (hba->host->host_lock, flags); -__clear_bit (free_slot, &hba->outstanding_tasks); +__clear_bit (task_tag, &hba->outstanding_tasks);spin_unlock_irqrestore (hba->host->host_lock, flags); +ufshcd_release (hba);blk_put_request (req); -ufshcd_release (hba);return err; }
Signature · 1 line
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
RE: [PATCH v4 1/2] scsi: ufs: Fix task management request completion timeout
In reply to Can GuoQuoted 20 lines
ufshcd_tmc_handler()callsblk_mq_tagset_busy_iter(fn = ufshcd_compl_tm()),
but sinceblk_mq_tagset_busy_iter()only iterates over all reserved tags and requests which are not in IDLE state,ufshcd_compl_tm()never gets a chance to run. Thus, TMR always ends up with completion timeout. Fix it by callingblk_mq_start_request()in__ufshcd_issue_tm_cmd().Fixes 69a6c269c097 ("scsi: ufs: Use blk_{get,put}_request() to allocate andfree TMFs")
Signed-off-by Can Guo <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 1 + 1 file changed, 1 insertion(+)drivers/scsi/ufs/ufshcd.c +0
-0
drivers/scsi/ufs/ufshcd.c static int __ufshcd_issue_tm_cmd(struct ufs_hba · line 6468
Quoted 5 lines
drivers/scsi/ufs/ufshcd.c +1
-0@@ -6464,6 +6464,7 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,spin_lock_irqsave (host->host_lock, flags); task_tag = hba->nutrs + free_slot; +blk_mq_start_request (req);
Maybe just set req->state to MQ_RQ_IN_FLIGHT
Without all other irrelevant initializations such as add timeout etc.
Thanks,
Avri
Quoted 6 lines
drivers/scsi/ufs/ufshcd.c +0
-1treq->req_header.dword_0 |=cpu_to_be32 (task_tag); --Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
Re: [PATCH v4 1/2] scsi: ufs: Fix task management request completion timeout
Quoted 22 lines · Avri Altman
Quoted 22 lines
ufshcd_tmc_handler()callsblk_mq_tagset_busy_iter(fn = ufshcd_compl_tm()),
but sinceblk_mq_tagset_busy_iter()only iterates over all reserved tags and requests which are not in IDLE state,ufshcd_compl_tm()never gets a chance to run. Thus, TMR always ends up with completion timeout. Fix it by callingblk_mq_start_request()in__ufshcd_issue_tm_cmd().Fixes 69a6c269c097 ("scsi: ufs: Use blk_{get,put}_request() to allocate andfree TMFs")
Signed-off-by Can Guo <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 1 + 1 file changed, 1 insertion(+)drivers/scsi/ufs/ufshcd.c +0
-0@@ -6464,6 +6464,7 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
Quoted 6 lines
drivers/scsi/ufs/ufshcd.c static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba, · line 6467
Quoted 3 lines
drivers/scsi/ufs/ufshcd.c +1
-0spin_lock_irqsave (host->host_lock, flags); task_tag = hba->nutrs + free_slot; +blk_mq_start_request (req);Maybe just set
req->statetoMQ_RQ_IN_FLIGHT
Without all other irrelevant initializations such as add timeout etc.
I don't see any other drivers do that, is it appropriate to call WRITE_ONCE(rq->state, MQ_RQ_IN_FLIGHT) outside block layer?
Thanks,
Can Guo.
Quoted 8 lines
Thanks,
AvriQuoted 6 lines
drivers/scsi/ufs/ufshcd.c +0
-1treq->req_header.dword_0 |=cpu_to_be32 (task_tag); --Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
Re: [PATCH v4 1/2] scsi: ufs: Fix task management request completion timeout
In reply to Avri AltmanQuoted 22 lines · Avri Altman
Quoted 22 lines
ufshcd_tmc_handler()callsblk_mq_tagset_busy_iter(fn = ufshcd_compl_tm()),
but sinceblk_mq_tagset_busy_iter()only iterates over all reserved tags and requests which are not in IDLE state,ufshcd_compl_tm()never gets a chance to run. Thus, TMR always ends up with completion timeout. Fix it by callingblk_mq_start_request()in__ufshcd_issue_tm_cmd().Fixes 69a6c269c097 ("scsi: ufs: Use blk_{get,put}_request() to allocate andfree TMFs")
Signed-off-by Can Guo <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 1 + 1 file changed, 1 insertion(+)drivers/scsi/ufs/ufshcd.c +0
-0@@ -6464,6 +6464,7 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
Quoted 5 lines
drivers/scsi/ufs/ufshcd.c static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba, · line 6467
Quoted 3 lines
drivers/scsi/ufs/ufshcd.c +1
-0spin_lock_irqsave (host->host_lock, flags); task_tag = hba->nutrs + free_slot; +blk_mq_start_request (req);Maybe just set
req->statetoMQ_RQ_IN_FLIGHT
Without all other irrelevant initializations such as add timeout etc.
Hmm ... I'm not sure that any of the actions performed by blk_mq_start_request() are irrelevant in this context. Additionally, no other block or SCSI driver sets MQ_RQ_IN_FLIGHT directly.
Thanks,
Bart.