FAILED: patch "[PATCH] scsi: ufs: core: Fix task management completion" failed to apply to 5.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From f5ef336fd2e4c36dedae4e7ca66cf5349d6fda62 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <[email protected]>
Date: Wed, 22 Sep 2021 12:10:59 +0300
Subject: [PATCH] scsi: ufs: core: Fix task management completion
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 37f4a24c2469 ("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.
drivers/scsi/ufs/ufshcd.c +22 -30
@@ -6377,27 +6377,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
@@ -6408,18 +6387,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; }/**
@@ -6542,9 +6527,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));
@@ -6585,6 +6570,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);
@@ -9635,6 +9621,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);
drivers/scsi/ufs/ufshcd.h +1 -0
@@ -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;
Quoted 4 lines · On 10/10/21 3:21 AM, [email protected] wrote:
The patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
Hi Adrian,
Please let me know if you don't have the time to work on this yourself.
Thanks,
Bart.