diff options
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index d1a0b15d4514..496bdfc19c95 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1984,6 +1984,8 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost) tag_set->flags = BLK_MQ_F_SHOULD_MERGE; tag_set->flags |= BLK_ALLOC_POLICY_TO_MQ_FLAG(shost->hostt->tag_alloc_policy); + if (shost->queuecommand_may_block) + tag_set->flags |= BLK_MQ_F_BLOCKING; tag_set->driver_data = shost; if (shost->host_tagset) tag_set->flags |= BLK_MQ_F_TAG_HCTX_SHARED; @@ -2943,11 +2945,20 @@ scsi_target_unblock(struct device *dev, enum scsi_device_state new_state) } EXPORT_SYMBOL_GPL(scsi_target_unblock); +/** + * scsi_host_block - Try to transition all logical units to the SDEV_BLOCK state + * @shost: device to block + * + * Pause SCSI command processing for all logical units associated with the SCSI + * host and wait until pending scsi_queue_rq() calls have finished. + * + * Returns zero if successful or a negative error code upon failure. + */ int scsi_host_block(struct Scsi_Host *shost) { struct scsi_device *sdev; - int ret = 0; + int ret; /* * Call scsi_internal_device_block_nowait so we can avoid @@ -2959,20 +2970,14 @@ scsi_host_block(struct Scsi_Host *shost) mutex_unlock(&sdev->state_mutex); if (ret) { scsi_device_put(sdev); - break; + return ret; } } - /* - * SCSI never enables blk-mq's BLK_MQ_F_BLOCKING flag so - * calling synchronize_rcu() once is enough. - */ - WARN_ON_ONCE(shost->tag_set.flags & BLK_MQ_F_BLOCKING); + /* Wait for ongoing scsi_queue_rq() calls to finish. */ + blk_mq_wait_quiesce_done(&shost->tag_set); - if (!ret) - synchronize_rcu(); - - return ret; + return 0; } EXPORT_SYMBOL_GPL(scsi_host_block); |