Skip to content

Commit f5ef336

Browse files
ahunter6martinkpetersen
authored andcommitted
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 37f4a24 ("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. Link: https://lore.kernel.org/r/[email protected] Fixes: 1235fc5 ("scsi: ufs: core: Fix task management request completion timeout") Fixes: 69a6c26 ("scsi: ufs: Use blk_{get,put}_request() to allocate and free TMFs") Cc: [email protected] Tested-by: Bart Van Assche <[email protected]> Reviewed-by: Bart Van Assche <[email protected]> Signed-off-by: Adrian Hunter <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent c533640 commit f5ef336

File tree

2 files changed

+23
-30
lines changed

2 files changed

+23
-30
lines changed

drivers/scsi/ufs/ufshcd.c

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6377,27 +6377,6 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status)
63776377
return retval;
63786378
}
63796379

6380-
struct ctm_info {
6381-
struct ufs_hba *hba;
6382-
unsigned long pending;
6383-
unsigned int ncpl;
6384-
};
6385-
6386-
static bool ufshcd_compl_tm(struct request *req, void *priv, bool reserved)
6387-
{
6388-
struct ctm_info *const ci = priv;
6389-
struct completion *c;
6390-
6391-
WARN_ON_ONCE(reserved);
6392-
if (test_bit(req->tag, &ci->pending))
6393-
return true;
6394-
ci->ncpl++;
6395-
c = req->end_io_data;
6396-
if (c)
6397-
complete(c);
6398-
return true;
6399-
}
6400-
64016380
/**
64026381
* ufshcd_tmc_handler - handle task management function completion
64036382
* @hba: per adapter instance
@@ -6408,18 +6387,24 @@ static bool ufshcd_compl_tm(struct request *req, void *priv, bool reserved)
64086387
*/
64096388
static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba)
64106389
{
6411-
unsigned long flags;
6412-
struct request_queue *q = hba->tmf_queue;
6413-
struct ctm_info ci = {
6414-
.hba = hba,
6415-
};
6390+
unsigned long flags, pending, issued;
6391+
irqreturn_t ret = IRQ_NONE;
6392+
int tag;
6393+
6394+
pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
64166395

64176396
spin_lock_irqsave(hba->host->host_lock, flags);
6418-
ci.pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
6419-
blk_mq_tagset_busy_iter(q->tag_set, ufshcd_compl_tm, &ci);
6397+
issued = hba->outstanding_tasks & ~pending;
6398+
for_each_set_bit(tag, &issued, hba->nutmrs) {
6399+
struct request *req = hba->tmf_rqs[tag];
6400+
struct completion *c = req->end_io_data;
6401+
6402+
complete(c);
6403+
ret = IRQ_HANDLED;
6404+
}
64206405
spin_unlock_irqrestore(hba->host->host_lock, flags);
64216406

6422-
return ci.ncpl ? IRQ_HANDLED : IRQ_NONE;
6407+
return ret;
64236408
}
64246409

64256410
/**
@@ -6542,9 +6527,9 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
65426527
ufshcd_hold(hba, false);
65436528

65446529
spin_lock_irqsave(host->host_lock, flags);
6545-
blk_mq_start_request(req);
65466530

65476531
task_tag = req->tag;
6532+
hba->tmf_rqs[req->tag] = req;
65486533
treq->upiu_req.req_header.dword_0 |= cpu_to_be32(task_tag);
65496534

65506535
memcpy(hba->utmrdl_base_addr + task_tag, treq, sizeof(*treq));
@@ -6585,6 +6570,7 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
65856570
}
65866571

65876572
spin_lock_irqsave(hba->host->host_lock, flags);
6573+
hba->tmf_rqs[req->tag] = NULL;
65886574
__clear_bit(task_tag, &hba->outstanding_tasks);
65896575
spin_unlock_irqrestore(hba->host->host_lock, flags);
65906576

@@ -9635,6 +9621,12 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
96359621
err = PTR_ERR(hba->tmf_queue);
96369622
goto free_tmf_tag_set;
96379623
}
9624+
hba->tmf_rqs = devm_kcalloc(hba->dev, hba->nutmrs,
9625+
sizeof(*hba->tmf_rqs), GFP_KERNEL);
9626+
if (!hba->tmf_rqs) {
9627+
err = -ENOMEM;
9628+
goto free_tmf_queue;
9629+
}
96389630

96399631
/* Reset the attached device */
96409632
ufshcd_device_reset(hba);

drivers/scsi/ufs/ufshcd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,7 @@ struct ufs_hba {
828828

829829
struct blk_mq_tag_set tmf_tag_set;
830830
struct request_queue *tmf_queue;
831+
struct request **tmf_rqs;
831832

832833
struct uic_command *active_uic_cmd;
833834
struct mutex uic_cmd_mutex;

0 commit comments

Comments
 (0)