[PATCH] scsi: ufs: Fix the polling implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Certain code in the block layer assumes that requests submitted on a
polling queue (HCTX_TYPE_POLL) are completed in thread context. Hence
this patch that modifies ufshcd_poll() such that only requests are
completed for the hardware queue that is being examined instead of all
hardware queues. The block layer code that makes this assumption is the
bio caching code. From block/bio.c:

    If REQ_ALLOC_CACHE is set, the final put of the bio MUST be done
    from process context, not hard/soft IRQ.

The REQ_ALLOC_CACHE flag is set for polled I/O (REQ_POLLED) since
kernel v5.15. See also commit be4d234d7aeb ("bio: add allocation cache
abstraction").

Fixes: eaab9b573054 ("scsi: ufs: Implement polling support")
Signed-off-by: Bart Van Assche <bvanassche@xxxxxxx>
---
 drivers/ufs/core/ufshcd.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 05925939af35..f80d09aea669 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -5430,6 +5430,7 @@ static int ufshcd_poll(struct Scsi_Host *shost, unsigned int queue_num)
 	struct ufs_hba *hba = shost_priv(shost);
 	unsigned long completed_reqs, flags;
 	u32 tr_doorbell;
+	int tag;
 
 	spin_lock_irqsave(&hba->outstanding_lock, flags);
 	tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
@@ -5437,6 +5438,18 @@ static int ufshcd_poll(struct Scsi_Host *shost, unsigned int queue_num)
 	WARN_ONCE(completed_reqs & ~hba->outstanding_reqs,
 		  "completed: %#lx; outstanding: %#lx\n", completed_reqs,
 		  hba->outstanding_reqs);
+	for_each_set_bit(tag, &completed_reqs, hba->nutrs) {
+		struct ufshcd_lrb *lrbp = &hba->lrb[tag];
+
+		if (lrbp->cmd) {
+			struct request *rq = scsi_cmd_to_rq(lrbp->cmd);
+			u32 unique_tag = blk_mq_unique_tag(rq);
+			u16 hwq = blk_mq_unique_tag_to_hwq(unique_tag);
+
+			if (hwq != queue_num)
+				__clear_bit(tag, &completed_reqs);
+		}
+	}
 	hba->outstanding_reqs &= ~completed_reqs;
 	spin_unlock_irqrestore(&hba->outstanding_lock, flags);
 



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux