With the legacy SCSI core holding the host lock was sufficient to serialize queuecommand() calls and error handling. With scsi-mq a call to blk_mq_quiesce() is required to wait until ongoing queuecommand calls have finished. scsi_target_block() calls blk_mq_quiesce(). Cc: Bean Huo <beanhuo@xxxxxxxxxx> Cc: Avri Altman <avri.altman@xxxxxxx> Cc: Stanley Chu <stanley.chu@xxxxxxxxxxxx> Cc: Tomas Winkler <tomas.winkler@xxxxxxxxx> Fixes: d5038a13eca7 ("scsi: core: switch to scsi-mq by default") Signed-off-by: Bart Van Assche <bvanassche@xxxxxxx> --- drivers/scsi/ufs/ufshcd.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9cbe3b45cf1c..a03538165a12 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5275,6 +5275,8 @@ static bool ufshcd_quirk_dl_nac_errors(struct ufs_hba *hba) static void ufshcd_err_handler(struct work_struct *work) { struct ufs_hba *hba; + struct scsi_device *sdev; + struct scsi_target *starget; unsigned long flags; u32 err_xfer = 0; u32 err_tm = 0; @@ -5283,10 +5285,19 @@ static void ufshcd_err_handler(struct work_struct *work) bool needs_reset = false; hba = container_of(work, struct ufs_hba, eh_work); + sdev = hba->sdev_ufs_device; + starget = sdev ? sdev->sdev_target : NULL; pm_runtime_get_sync(hba->dev); ufshcd_hold(hba, false); + /* + * Wait until ongoing ufshcd_queuecommand() calls have finished + * without waiting for command completion. + */ + if (starget) + scsi_target_block(&starget->dev); + spin_lock_irqsave(hba->host->host_lock, flags); if (hba->ufshcd_state == UFSHCD_STATE_RESET) goto out; @@ -5395,6 +5406,8 @@ static void ufshcd_err_handler(struct work_struct *work) out: spin_unlock_irqrestore(hba->host->host_lock, flags); + if (starget) + scsi_target_unblock(&starget->dev, SDEV_RUNNING); ufshcd_scsi_unblock_requests(hba); ufshcd_release(hba); pm_runtime_put_sync(hba->dev);