Message ID | 20221118233717.441298-1-bvanassche@acm.org (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Series | [v2] scsi: ufs: Fix the polling implementation | expand |
On 19/11/22 01:37, Bart Van Assche wrote: > Fix the following issues in ufshcd_poll(): > - If polling succeeds, return a positive value. > - Do not complete polling requests from interrupt context because the > block layer expects these requests to be completed from thread > context. 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. > > Fixes: eaab9b573054 ("scsi: ufs: Implement polling support") > Signed-off-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Adrian Hunter <adrian.hunter@intel.com> > --- > > Changes compared to v1: > - Made sure that polled requests are not completed from interrupt context. > > drivers/ufs/core/ufshcd.c | 28 ++++++++++++++++++++++++++-- > 1 file changed, 26 insertions(+), 2 deletions(-) > > diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c > index 768cb49d269c..b4bf3c3bef0c 100644 > --- a/drivers/ufs/core/ufshcd.c > +++ b/drivers/ufs/core/ufshcd.c > @@ -5344,6 +5344,26 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, > } > } > > +/* Any value that is not an existing queue number is fine for this constant. */ > +enum { > + UFSHCD_POLL_FROM_INTERRUPT_CONTEXT = -1 > +}; > + > +static void ufshcd_clear_polled(struct ufs_hba *hba, > + unsigned long *completed_reqs) > +{ > + int tag; > + > + for_each_set_bit(tag, completed_reqs, hba->nutrs) { > + struct scsi_cmnd *cmd = hba->lrb[tag].cmd; > + > + if (!cmd) > + continue; > + if (scsi_cmd_to_rq(cmd)->cmd_flags & REQ_POLLED) > + __clear_bit(tag, completed_reqs); > + } > +} > + > /* > * Returns > 0 if one or more commands have been completed or 0 if no > * requests have been completed. > @@ -5360,13 +5380,17 @@ 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); > + if (queue_num == UFSHCD_POLL_FROM_INTERRUPT_CONTEXT) { > + /* Do not complete polled requests from interrupt context. */ > + ufshcd_clear_polled(hba, &completed_reqs); > + } > hba->outstanding_reqs &= ~completed_reqs; > spin_unlock_irqrestore(&hba->outstanding_lock, flags); > > if (completed_reqs) > __ufshcd_transfer_req_compl(hba, completed_reqs); > > - return completed_reqs; > + return completed_reqs != 0; > } > > /** > @@ -5397,7 +5421,7 @@ static irqreturn_t ufshcd_transfer_req_compl(struct ufs_hba *hba) > * Ignore the ufshcd_poll() return value and return IRQ_HANDLED since we > * do not want polling to trigger spurious interrupt complaints. > */ > - ufshcd_poll(hba->host, 0); > + ufshcd_poll(hba->host, UFSHCD_POLL_FROM_INTERRUPT_CONTEXT); > > return IRQ_HANDLED; > }
Bart, > Fix the following issues in ufshcd_poll(): > - If polling succeeds, return a positive value. > - Do not complete polling requests from interrupt context because the > block layer expects these requests to be completed from thread > context. From block/bio.c: Applied to 6.2/scsi-staging, thanks!
On Fri, 18 Nov 2022 15:37:03 -0800, Bart Van Assche wrote: > Fix the following issues in ufshcd_poll(): > - If polling succeeds, return a positive value. > - Do not complete polling requests from interrupt context because the > block layer expects these requests to be completed from thread > context. 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. > > [...] Applied to 6.2/scsi-queue, thanks! [1/1] scsi: ufs: Fix the polling implementation https://git.kernel.org/mkp/scsi/c/ee8c88cab4af
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 768cb49d269c..b4bf3c3bef0c 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -5344,6 +5344,26 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, } } +/* Any value that is not an existing queue number is fine for this constant. */ +enum { + UFSHCD_POLL_FROM_INTERRUPT_CONTEXT = -1 +}; + +static void ufshcd_clear_polled(struct ufs_hba *hba, + unsigned long *completed_reqs) +{ + int tag; + + for_each_set_bit(tag, completed_reqs, hba->nutrs) { + struct scsi_cmnd *cmd = hba->lrb[tag].cmd; + + if (!cmd) + continue; + if (scsi_cmd_to_rq(cmd)->cmd_flags & REQ_POLLED) + __clear_bit(tag, completed_reqs); + } +} + /* * Returns > 0 if one or more commands have been completed or 0 if no * requests have been completed. @@ -5360,13 +5380,17 @@ 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); + if (queue_num == UFSHCD_POLL_FROM_INTERRUPT_CONTEXT) { + /* Do not complete polled requests from interrupt context. */ + ufshcd_clear_polled(hba, &completed_reqs); + } hba->outstanding_reqs &= ~completed_reqs; spin_unlock_irqrestore(&hba->outstanding_lock, flags); if (completed_reqs) __ufshcd_transfer_req_compl(hba, completed_reqs); - return completed_reqs; + return completed_reqs != 0; } /** @@ -5397,7 +5421,7 @@ static irqreturn_t ufshcd_transfer_req_compl(struct ufs_hba *hba) * Ignore the ufshcd_poll() return value and return IRQ_HANDLED since we * do not want polling to trigger spurious interrupt complaints. */ - ufshcd_poll(hba->host, 0); + ufshcd_poll(hba->host, UFSHCD_POLL_FROM_INTERRUPT_CONTEXT); return IRQ_HANDLED; }
Fix the following issues in ufshcd_poll(): - If polling succeeds, return a positive value. - Do not complete polling requests from interrupt context because the block layer expects these requests to be completed from thread context. 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. Fixes: eaab9b573054 ("scsi: ufs: Implement polling support") Signed-off-by: Bart Van Assche <bvanassche@acm.org> --- Changes compared to v1: - Made sure that polled requests are not completed from interrupt context. drivers/ufs/core/ufshcd.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)