Message ID | 20221114233042.3199381-1-bvanassche@acm.org |
---|---|
State | New |
Headers | show |
Series | scsi: ufs: Fix the polling implementation | expand |
On 11/14/22 15:30, Bart Van Assche wrote: > 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"). Please drop this patch - I plan to send an improved version later. Bart.
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);
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@acm.org> --- drivers/ufs/core/ufshcd.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)