All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] scsi: ufs: Fix task management completion
@ 2021-09-22  9:10 Adrian Hunter
  2021-09-22 20:48 ` Bart Van Assche
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Adrian Hunter @ 2021-09-22  9:10 UTC (permalink / raw)
  To: Martin K . Petersen
  Cc: James E . J . Bottomley, Bean Huo, Avri Altman, Alim Akhtar,
	Can Guo, Asutosh Das, Bart Van Assche, Stanley Chu, Ming Lei,
	Christoph Hellwig, Jens Axboe, linux-scsi

The UFS driver uses blk_mq_tagset_busy_iter() when identifying task
management requests to complete, however blk_mq_tagset_busy_iter()
doesn't work.

blk_mq_tagset_busy_iter() only iterates requests dispatched by the block
layer. That appears as if it might have started since commit 37f4a24c2469a1
("blk-mq: centralise related handling into blk_mq_get_driver_tag") which
removed 'data->hctx->tags->rqs[rq->tag] = rq' from blk_mq_rq_ctx_init()
which gets called:

	blk_get_request
		blk_mq_alloc_request
			__blk_mq_alloc_request
				blk_mq_rq_ctx_init

Since UFS task management requests are not dispatched by the block
layer, hctx->tags->rqs[rq->tag] remains NULL,  and since
blk_mq_tagset_busy_iter() relies on finding requests using
hctx->tags->rqs[rq->tag], UFS task management requests are never found by
blk_mq_tagset_busy_iter().

By using blk_mq_tagset_busy_iter(), the UFS driver was relying on internal
details of the block layer, which was fragile and subsequently got
broken. Fix by removing the use of blk_mq_tagset_busy_iter() and having
the driver keep track of task management requests.

Fixes: 1235fc569e0bf5 ("scsi: ufs: core: Fix task management request completion timeout")
Fixes: 69a6c269c097d7 ("scsi: ufs: Use blk_{get,put}_request() to allocate and free TMFs")
Cc: stable@vger.kernel.org
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/scsi/ufs/ufshcd.c | 52 +++++++++++++++++----------------------
 drivers/scsi/ufs/ufshcd.h |  1 +
 2 files changed, 23 insertions(+), 30 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 029c9631ec2b..1f97818aa0bf 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -6378,27 +6378,6 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status)
 	return retval;
 }
 
-struct ctm_info {
-	struct ufs_hba	*hba;
-	unsigned long	pending;
-	unsigned int	ncpl;
-};
-
-static bool ufshcd_compl_tm(struct request *req, void *priv, bool reserved)
-{
-	struct ctm_info *const ci = priv;
-	struct completion *c;
-
-	WARN_ON_ONCE(reserved);
-	if (test_bit(req->tag, &ci->pending))
-		return true;
-	ci->ncpl++;
-	c = req->end_io_data;
-	if (c)
-		complete(c);
-	return true;
-}
-
 /**
  * ufshcd_tmc_handler - handle task management function completion
  * @hba: per adapter instance
@@ -6409,18 +6388,24 @@ static bool ufshcd_compl_tm(struct request *req, void *priv, bool reserved)
  */
 static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba)
 {
-	unsigned long flags;
-	struct request_queue *q = hba->tmf_queue;
-	struct ctm_info ci = {
-		.hba	 = hba,
-	};
+	unsigned long flags, pending, issued;
+	irqreturn_t ret = IRQ_NONE;
+	int tag;
+
+	pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
 
 	spin_lock_irqsave(hba->host->host_lock, flags);
-	ci.pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
-	blk_mq_tagset_busy_iter(q->tag_set, ufshcd_compl_tm, &ci);
+	issued = hba->outstanding_tasks & ~pending;
+	for_each_set_bit(tag, &issued, hba->nutmrs) {
+		struct request *req = hba->tmf_rqs[tag];
+		struct completion *c = req->end_io_data;
+
+		complete(c);
+		ret = IRQ_HANDLED;
+	}
 	spin_unlock_irqrestore(hba->host->host_lock, flags);
 
-	return ci.ncpl ? IRQ_HANDLED : IRQ_NONE;
+	return ret;
 }
 
 /**
@@ -6543,9 +6528,9 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
 	ufshcd_hold(hba, false);
 
 	spin_lock_irqsave(host->host_lock, flags);
-	blk_mq_start_request(req);
 
 	task_tag = req->tag;
+	hba->tmf_rqs[req->tag] = req;
 	treq->upiu_req.req_header.dword_0 |= cpu_to_be32(task_tag);
 
 	memcpy(hba->utmrdl_base_addr + task_tag, treq, sizeof(*treq));
@@ -6586,6 +6571,7 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
 	}
 
 	spin_lock_irqsave(hba->host->host_lock, flags);
+	hba->tmf_rqs[req->tag] = NULL;
 	__clear_bit(task_tag, &hba->outstanding_tasks);
 	spin_unlock_irqrestore(hba->host->host_lock, flags);
 
@@ -9636,6 +9622,12 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
 		err = PTR_ERR(hba->tmf_queue);
 		goto free_tmf_tag_set;
 	}
+	hba->tmf_rqs = devm_kcalloc(hba->dev, hba->nutmrs,
+				    sizeof(*hba->tmf_rqs), GFP_KERNEL);
+	if (!hba->tmf_rqs) {
+		err = -ENOMEM;
+		goto free_tmf_queue;
+	}
 
 	/* Reset the attached device */
 	ufshcd_device_reset(hba);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index f0da5d3db1fa..41f6e06f9185 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -828,6 +828,7 @@ struct ufs_hba {
 
 	struct blk_mq_tag_set tmf_tag_set;
 	struct request_queue *tmf_queue;
+	struct request **tmf_rqs;
 
 	struct uic_command *active_uic_cmd;
 	struct mutex uic_cmd_mutex;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] scsi: ufs: Fix task management completion
  2021-09-22  9:10 [PATCH] scsi: ufs: Fix task management completion Adrian Hunter
@ 2021-09-22 20:48 ` Bart Van Assche
  2021-09-23  5:44   ` Adrian Hunter
  2021-10-04 17:08 ` Bart Van Assche
  2021-10-05  4:32 ` Martin K. Petersen
  2 siblings, 1 reply; 5+ messages in thread
From: Bart Van Assche @ 2021-09-22 20:48 UTC (permalink / raw)
  To: Adrian Hunter, Martin K . Petersen
  Cc: James E . J . Bottomley, Bean Huo, Avri Altman, Alim Akhtar,
	Can Guo, Asutosh Das, Stanley Chu, Ming Lei, Christoph Hellwig,
	Jens Axboe, linux-scsi

On 9/22/21 2:10 AM, Adrian Hunter wrote:
> The UFS driver uses blk_mq_tagset_busy_iter() when identifying task
> management requests to complete, however blk_mq_tagset_busy_iter()
> doesn't work.
> 
> blk_mq_tagset_busy_iter() only iterates requests dispatched by the block
> layer. That appears as if it might have started since commit 37f4a24c2469a1
> ("blk-mq: centralise related handling into blk_mq_get_driver_tag") which
> removed 'data->hctx->tags->rqs[rq->tag] = rq' from blk_mq_rq_ctx_init()
> which gets called:
> 
> 	blk_get_request
> 		blk_mq_alloc_request
> 			__blk_mq_alloc_request
> 				blk_mq_rq_ctx_init
> 
> Since UFS task management requests are not dispatched by the block
> layer, hctx->tags->rqs[rq->tag] remains NULL,  and since
> blk_mq_tagset_busy_iter() relies on finding requests using
> hctx->tags->rqs[rq->tag], UFS task management requests are never found by
> blk_mq_tagset_busy_iter().
> 
> By using blk_mq_tagset_busy_iter(), the UFS driver was relying on internal
> details of the block layer, which was fragile and subsequently got
> broken. Fix by removing the use of blk_mq_tagset_busy_iter() and having
> the driver keep track of task management requests.

Thanks for the detailed analysis. I agree that using blk_mq_tagset_busy_iter()
no longer works due to recent changes in the block layer. Has it been
considered to export blk_mq_all_tag_iter() and to use that function instead of
blk_mq_tagset_busy_iter()?

Thanks,

Bart.



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] scsi: ufs: Fix task management completion
  2021-09-22 20:48 ` Bart Van Assche
@ 2021-09-23  5:44   ` Adrian Hunter
  0 siblings, 0 replies; 5+ messages in thread
From: Adrian Hunter @ 2021-09-23  5:44 UTC (permalink / raw)
  To: Bart Van Assche, Martin K . Petersen
  Cc: James E . J . Bottomley, Bean Huo, Avri Altman, Alim Akhtar,
	Can Guo, Asutosh Das, Stanley Chu, Ming Lei, Christoph Hellwig,
	Jens Axboe, linux-scsi

On 22/09/21 11:48 pm, Bart Van Assche wrote:
> On 9/22/21 2:10 AM, Adrian Hunter wrote:
>> The UFS driver uses blk_mq_tagset_busy_iter() when identifying task
>> management requests to complete, however blk_mq_tagset_busy_iter()
>> doesn't work.
>>
>> blk_mq_tagset_busy_iter() only iterates requests dispatched by the block
>> layer. That appears as if it might have started since commit 37f4a24c2469a1
>> ("blk-mq: centralise related handling into blk_mq_get_driver_tag") which
>> removed 'data->hctx->tags->rqs[rq->tag] = rq' from blk_mq_rq_ctx_init()
>> which gets called:
>>
>>     blk_get_request
>>         blk_mq_alloc_request
>>             __blk_mq_alloc_request
>>                 blk_mq_rq_ctx_init
>>
>> Since UFS task management requests are not dispatched by the block
>> layer, hctx->tags->rqs[rq->tag] remains NULL,  and since
>> blk_mq_tagset_busy_iter() relies on finding requests using
>> hctx->tags->rqs[rq->tag], UFS task management requests are never found by
>> blk_mq_tagset_busy_iter().
>>
>> By using blk_mq_tagset_busy_iter(), the UFS driver was relying on internal
>> details of the block layer, which was fragile and subsequently got
>> broken. Fix by removing the use of blk_mq_tagset_busy_iter() and having
>> the driver keep track of task management requests.
> 
> Thanks for the detailed analysis. I agree that using blk_mq_tagset_busy_iter()
> no longer works due to recent changes in the block layer. Has it been
> considered to export blk_mq_all_tag_iter() and to use that function instead of
> blk_mq_tagset_busy_iter()?

It seemed better not to be the only driver using the block layer in a
different way.  Having the UFS driver self-contained in this regard
seemed more robust.  If anything, the code without blk_mq_tagset_busy_iter()
is slightly shorter, so using a block layer iterator doesn't help much.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] scsi: ufs: Fix task management completion
  2021-09-22  9:10 [PATCH] scsi: ufs: Fix task management completion Adrian Hunter
  2021-09-22 20:48 ` Bart Van Assche
@ 2021-10-04 17:08 ` Bart Van Assche
  2021-10-05  4:32 ` Martin K. Petersen
  2 siblings, 0 replies; 5+ messages in thread
From: Bart Van Assche @ 2021-10-04 17:08 UTC (permalink / raw)
  To: Adrian Hunter, Martin K . Petersen
  Cc: James E . J . Bottomley, Bean Huo, Avri Altman, Alim Akhtar,
	Can Guo, Asutosh Das, Stanley Chu, Ming Lei, Christoph Hellwig,
	Jens Axboe, linux-scsi, Jaegeuk Kim

On 9/22/21 2:10 AM, Adrian Hunter wrote:
> By using blk_mq_tagset_busy_iter(), the UFS driver was relying on internal
> details of the block layer, which was fragile and subsequently got
> broken. Fix by removing the use of blk_mq_tagset_busy_iter() and having
> the driver keep track of task management requests.

Tested-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] scsi: ufs: Fix task management completion
  2021-09-22  9:10 [PATCH] scsi: ufs: Fix task management completion Adrian Hunter
  2021-09-22 20:48 ` Bart Van Assche
  2021-10-04 17:08 ` Bart Van Assche
@ 2021-10-05  4:32 ` Martin K. Petersen
  2 siblings, 0 replies; 5+ messages in thread
From: Martin K. Petersen @ 2021-10-05  4:32 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Martin K . Petersen, Stanley Chu, Ming Lei, linux-scsi,
	Alim Akhtar, Bart Van Assche, Avri Altman,
	James E . J . Bottomley, Can Guo, Jens Axboe, Asutosh Das,
	Bean Huo, Christoph Hellwig

On Wed, 22 Sep 2021 12:10:59 +0300, Adrian Hunter wrote:

> The UFS driver uses blk_mq_tagset_busy_iter() when identifying task
> management requests to complete, however blk_mq_tagset_busy_iter()
> doesn't work.
> 
> blk_mq_tagset_busy_iter() only iterates requests dispatched by the block
> layer. That appears as if it might have started since commit 37f4a24c2469a1
> ("blk-mq: centralise related handling into blk_mq_get_driver_tag") which
> removed 'data->hctx->tags->rqs[rq->tag] = rq' from blk_mq_rq_ctx_init()
> which gets called:
> 
> [...]

Applied to 5.15/scsi-fixes, thanks!

[1/1] scsi: ufs: Fix task management completion
      https://git.kernel.org/mkp/scsi/c/f5ef336fd2e4

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-10-05  4:33 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-22  9:10 [PATCH] scsi: ufs: Fix task management completion Adrian Hunter
2021-09-22 20:48 ` Bart Van Assche
2021-09-23  5:44   ` Adrian Hunter
2021-10-04 17:08 ` Bart Van Assche
2021-10-05  4:32 ` Martin K. Petersen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.