1
0
Fork 0

scsi: kill off the legacy IO path

This removes the legacy (non-mq) IO path for SCSI.

Cc: linux-scsi@vger.kernel.org
Acked-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Tested-by: Ming Lei <ming.lei@redhat.com>
Reviewed-by: Omar Sandoval <osandov@fb.com>
Acked-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
hifive-unleashed-5.1
Jens Axboe 2018-11-01 16:36:27 -06:00
parent 3a7ea2c483
commit f664a3cc17
17 changed files with 77 additions and 680 deletions

View File

@ -97,11 +97,6 @@ parameters may be changed at runtime by the command
allowing boot to proceed. none ignores them, expecting allowing boot to proceed. none ignores them, expecting
user space to do the scan. user space to do the scan.
scsi_mod.use_blk_mq=
[SCSI] use blk-mq I/O path by default
See SCSI_MQ_DEFAULT in drivers/scsi/Kconfig.
Format: <y/n>
sim710= [SCSI,HW] sim710= [SCSI,HW]
See header of drivers/scsi/sim710.c. See header of drivers/scsi/sim710.c.

View File

@ -50,18 +50,6 @@ config SCSI_NETLINK
default n default n
depends on NET depends on NET
config SCSI_MQ_DEFAULT
bool "SCSI: use blk-mq I/O path by default"
default y
depends on SCSI
---help---
This option enables the blk-mq based I/O path for SCSI devices by
default. With this option the scsi_mod.use_blk_mq module/boot
option defaults to Y, without it to N, but it can still be
overridden either way.
If unsure say Y.
config SCSI_PROC_FS config SCSI_PROC_FS
bool "legacy /proc/scsi/ support" bool "legacy /proc/scsi/ support"
depends on SCSI && PROC_FS depends on SCSI && PROC_FS

View File

@ -3088,12 +3088,6 @@ static ssize_t hwq_mode_store(struct device *dev,
return -EINVAL; return -EINVAL;
} }
if ((mode == HWQ_MODE_TAG) && !shost_use_blk_mq(shost)) {
dev_info(cfgdev, "SCSI-MQ is not enabled, use a different "
"HWQ steering mode.\n");
return -EINVAL;
}
afu->hwq_mode = mode; afu->hwq_mode = mode;
return count; return count;

View File

@ -222,18 +222,9 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
if (error) if (error)
goto fail; goto fail;
if (shost_use_blk_mq(shost)) { error = scsi_mq_setup_tags(shost);
error = scsi_mq_setup_tags(shost); if (error)
if (error) goto fail;
goto fail;
} else {
shost->bqt = blk_init_tags(shost->can_queue,
shost->hostt->tag_alloc_policy);
if (!shost->bqt) {
error = -ENOMEM;
goto fail;
}
}
if (!shost->shost_gendev.parent) if (!shost->shost_gendev.parent)
shost->shost_gendev.parent = dev ? dev : &platform_bus; shost->shost_gendev.parent = dev ? dev : &platform_bus;
@ -309,8 +300,7 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
pm_runtime_disable(&shost->shost_gendev); pm_runtime_disable(&shost->shost_gendev);
pm_runtime_set_suspended(&shost->shost_gendev); pm_runtime_set_suspended(&shost->shost_gendev);
pm_runtime_put_noidle(&shost->shost_gendev); pm_runtime_put_noidle(&shost->shost_gendev);
if (shost_use_blk_mq(shost)) scsi_mq_destroy_tags(shost);
scsi_mq_destroy_tags(shost);
fail: fail:
return error; return error;
} }
@ -344,13 +334,8 @@ static void scsi_host_dev_release(struct device *dev)
kfree(dev_name(&shost->shost_dev)); kfree(dev_name(&shost->shost_dev));
} }
if (shost_use_blk_mq(shost)) { if (shost->tag_set.tags)
if (shost->tag_set.tags) scsi_mq_destroy_tags(shost);
scsi_mq_destroy_tags(shost);
} else {
if (shost->bqt)
blk_free_tags(shost->bqt);
}
kfree(shost->shost_data); kfree(shost->shost_data);
@ -472,8 +457,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
else else
shost->dma_boundary = 0xffffffff; shost->dma_boundary = 0xffffffff;
shost->use_blk_mq = scsi_use_blk_mq || shost->hostt->force_blk_mq;
device_initialize(&shost->shost_gendev); device_initialize(&shost->shost_gendev);
dev_set_name(&shost->shost_gendev, "host%d", shost->host_no); dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
shost->shost_gendev.bus = &scsi_bus_type; shost->shost_gendev.bus = &scsi_bus_type;

View File

@ -3914,7 +3914,7 @@ int lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba,
uint32_t tag; uint32_t tag;
uint16_t hwq; uint16_t hwq;
if (cmnd && shost_use_blk_mq(cmnd->device->host)) { if (cmnd) {
tag = blk_mq_unique_tag(cmnd->request); tag = blk_mq_unique_tag(cmnd->request);
hwq = blk_mq_unique_tag_to_hwq(tag); hwq = blk_mq_unique_tag_to_hwq(tag);

View File

@ -644,8 +644,7 @@ static struct qedi_ctx *qedi_host_alloc(struct pci_dev *pdev)
qedi->max_active_conns = ISCSI_MAX_SESS_PER_HBA; qedi->max_active_conns = ISCSI_MAX_SESS_PER_HBA;
qedi->max_sqes = QEDI_SQ_SIZE; qedi->max_sqes = QEDI_SQ_SIZE;
if (shost_use_blk_mq(shost)) shost->nr_hw_queues = MIN_NUM_CPUS_MSIX(qedi);
shost->nr_hw_queues = MIN_NUM_CPUS_MSIX(qedi);
pci_set_drvdata(pdev, qedi); pci_set_drvdata(pdev, qedi);

View File

@ -857,13 +857,9 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
} }
if (ha->mqenable) { if (ha->mqenable) {
if (shost_use_blk_mq(vha->host)) { tag = blk_mq_unique_tag(cmd->request);
tag = blk_mq_unique_tag(cmd->request); hwq = blk_mq_unique_tag_to_hwq(tag);
hwq = blk_mq_unique_tag_to_hwq(tag); qpair = ha->queue_pair_map[hwq];
qpair = ha->queue_pair_map[hwq];
} else if (vha->vp_idx && vha->qpair) {
qpair = vha->qpair;
}
if (qpair) if (qpair)
return qla2xxx_mqueuecommand(host, cmd, qpair); return qla2xxx_mqueuecommand(host, cmd, qpair);
@ -3153,7 +3149,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
goto probe_failed; goto probe_failed;
} }
if (ha->mqenable && shost_use_blk_mq(host)) { if (ha->mqenable) {
/* number of hardware queues supported by blk/scsi-mq*/ /* number of hardware queues supported by blk/scsi-mq*/
host->nr_hw_queues = ha->max_qpairs; host->nr_hw_queues = ha->max_qpairs;
@ -3265,25 +3261,17 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
base_vha->mgmt_svr_loop_id, host->sg_tablesize); base_vha->mgmt_svr_loop_id, host->sg_tablesize);
if (ha->mqenable) { if (ha->mqenable) {
bool mq = false;
bool startit = false; bool startit = false;
if (QLA_TGT_MODE_ENABLED()) { if (QLA_TGT_MODE_ENABLED())
mq = true;
startit = false; startit = false;
}
if ((ql2x_ini_mode == QLA2XXX_INI_MODE_ENABLED) && if (ql2x_ini_mode == QLA2XXX_INI_MODE_ENABLED)
shost_use_blk_mq(host)) {
mq = true;
startit = true; startit = true;
}
if (mq) { /* Create start of day qpairs for Block MQ */
/* Create start of day qpairs for Block MQ */ for (i = 0; i < ha->max_qpairs; i++)
for (i = 0; i < ha->max_qpairs; i++) qla2xxx_create_qpair(base_vha, 5, 0, startit);
qla2xxx_create_qpair(base_vha, 5, 0, startit);
}
} }
if (ha->flags.running_gold_fw) if (ha->flags.running_gold_fw)

View File

@ -780,11 +780,8 @@ MODULE_LICENSE("GPL");
module_param(scsi_logging_level, int, S_IRUGO|S_IWUSR); module_param(scsi_logging_level, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(scsi_logging_level, "a bit mask of logging levels"); MODULE_PARM_DESC(scsi_logging_level, "a bit mask of logging levels");
#ifdef CONFIG_SCSI_MQ_DEFAULT /* This should go away in the future, it doesn't do anything anymore */
bool scsi_use_blk_mq = true; bool scsi_use_blk_mq = true;
#else
bool scsi_use_blk_mq = false;
#endif
module_param_named(use_blk_mq, scsi_use_blk_mq, bool, S_IWUSR | S_IRUGO); module_param_named(use_blk_mq, scsi_use_blk_mq, bool, S_IWUSR | S_IRUGO);
static int __init init_scsi(void) static int __init init_scsi(void)

View File

@ -5881,8 +5881,7 @@ static int sdebug_driver_probe(struct device *dev)
} }
/* Decide whether to tell scsi subsystem that we want mq */ /* Decide whether to tell scsi subsystem that we want mq */
/* Following should give the same answer for each host */ /* Following should give the same answer for each host */
if (shost_use_blk_mq(hpnt)) hpnt->nr_hw_queues = submit_queues;
hpnt->nr_hw_queues = submit_queues;
sdbg_host->shost = hpnt; sdbg_host->shost = hpnt;
*((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host; *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host;

View File

@ -308,7 +308,7 @@ enum blk_eh_timer_return scsi_times_out(struct request *req)
* error handler. In that case we can return immediately as no * error handler. In that case we can return immediately as no
* further action is required. * further action is required.
*/ */
if (req->q->mq_ops && !blk_mq_mark_complete(req)) if (!blk_mq_mark_complete(req))
return rtn; return rtn;
if (scsi_abort_command(scmd) != SUCCESS) { if (scsi_abort_command(scmd) != SUCCESS) {
set_host_byte(scmd, DID_TIME_OUT); set_host_byte(scmd, DID_TIME_OUT);

View File

@ -168,8 +168,6 @@ static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd)
static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, bool unbusy) static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, bool unbusy)
{ {
struct scsi_device *device = cmd->device; struct scsi_device *device = cmd->device;
struct request_queue *q = device->request_queue;
unsigned long flags;
SCSI_LOG_MLQUEUE(1, scmd_printk(KERN_INFO, cmd, SCSI_LOG_MLQUEUE(1, scmd_printk(KERN_INFO, cmd,
"Inserting command %p into mlqueue\n", cmd)); "Inserting command %p into mlqueue\n", cmd));
@ -190,26 +188,20 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, bool unbusy)
* before blk_cleanup_queue() finishes. * before blk_cleanup_queue() finishes.
*/ */
cmd->result = 0; cmd->result = 0;
if (q->mq_ops) {
/* /*
* Before a SCSI command is dispatched, * Before a SCSI command is dispatched,
* get_device(&sdev->sdev_gendev) is called and the host, * get_device(&sdev->sdev_gendev) is called and the host,
* target and device busy counters are increased. Since * target and device busy counters are increased. Since
* requeuing a request causes these actions to be repeated and * requeuing a request causes these actions to be repeated and
* since scsi_device_unbusy() has already been called, * since scsi_device_unbusy() has already been called,
* put_device(&device->sdev_gendev) must still be called. Call * put_device(&device->sdev_gendev) must still be called. Call
* put_device() after blk_mq_requeue_request() to avoid that * put_device() after blk_mq_requeue_request() to avoid that
* removal of the SCSI device can start before requeueing has * removal of the SCSI device can start before requeueing has
* happened. * happened.
*/ */
blk_mq_requeue_request(cmd->request, true); blk_mq_requeue_request(cmd->request, true);
put_device(&device->sdev_gendev); put_device(&device->sdev_gendev);
return;
}
spin_lock_irqsave(q->queue_lock, flags);
blk_requeue_request(q, cmd->request);
kblockd_schedule_work(&device->requeue_work);
spin_unlock_irqrestore(q->queue_lock, flags);
} }
/* /*
@ -370,10 +362,7 @@ void scsi_device_unbusy(struct scsi_device *sdev)
static void scsi_kick_queue(struct request_queue *q) static void scsi_kick_queue(struct request_queue *q)
{ {
if (q->mq_ops) blk_mq_run_hw_queues(q, false);
blk_mq_run_hw_queues(q, false);
else
blk_run_queue(q);
} }
/* /*
@ -534,10 +523,7 @@ static void scsi_run_queue(struct request_queue *q)
if (!list_empty(&sdev->host->starved_list)) if (!list_empty(&sdev->host->starved_list))
scsi_starved_list_run(sdev->host); scsi_starved_list_run(sdev->host);
if (q->mq_ops) blk_mq_run_hw_queues(q, false);
blk_mq_run_hw_queues(q, false);
else
blk_run_queue(q);
} }
void scsi_requeue_run_queue(struct work_struct *work) void scsi_requeue_run_queue(struct work_struct *work)
@ -550,42 +536,6 @@ void scsi_requeue_run_queue(struct work_struct *work)
scsi_run_queue(q); scsi_run_queue(q);
} }
/*
* Function: scsi_requeue_command()
*
* Purpose: Handle post-processing of completed commands.
*
* Arguments: q - queue to operate on
* cmd - command that may need to be requeued.
*
* Returns: Nothing
*
* Notes: After command completion, there may be blocks left
* over which weren't finished by the previous command
* this can be for a number of reasons - the main one is
* I/O errors in the middle of the request, in which case
* we need to request the blocks that come after the bad
* sector.
* Notes: Upon return, cmd is a stale pointer.
*/
static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
{
struct scsi_device *sdev = cmd->device;
struct request *req = cmd->request;
unsigned long flags;
spin_lock_irqsave(q->queue_lock, flags);
blk_unprep_request(req);
req->special = NULL;
scsi_put_command(cmd);
blk_requeue_request(q, req);
spin_unlock_irqrestore(q->queue_lock, flags);
scsi_run_queue(q);
put_device(&sdev->sdev_gendev);
}
void scsi_run_host_queues(struct Scsi_Host *shost) void scsi_run_host_queues(struct Scsi_Host *shost)
{ {
struct scsi_device *sdev; struct scsi_device *sdev;
@ -626,42 +576,6 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd)
scsi_del_cmd_from_list(cmd); scsi_del_cmd_from_list(cmd);
} }
/*
* Function: scsi_release_buffers()
*
* Purpose: Free resources allocate for a scsi_command.
*
* Arguments: cmd - command that we are bailing.
*
* Lock status: Assumed that no lock is held upon entry.
*
* Returns: Nothing
*
* Notes: In the event that an upper level driver rejects a
* command, we must release resources allocated during
* the __init_io() function. Primarily this would involve
* the scatter-gather table.
*/
static void scsi_release_buffers(struct scsi_cmnd *cmd)
{
if (cmd->sdb.table.nents)
sg_free_table_chained(&cmd->sdb.table, false);
memset(&cmd->sdb, 0, sizeof(cmd->sdb));
if (scsi_prot_sg_count(cmd))
sg_free_table_chained(&cmd->prot_sdb->table, false);
}
static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd)
{
struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special;
sg_free_table_chained(&bidi_sdb->table, false);
kmem_cache_free(scsi_sdb_cache, bidi_sdb);
cmd->request->next_rq->special = NULL;
}
/* Returns false when no more bytes to process, true if there are more */ /* Returns false when no more bytes to process, true if there are more */
static bool scsi_end_request(struct request *req, blk_status_t error, static bool scsi_end_request(struct request *req, blk_status_t error,
unsigned int bytes, unsigned int bidi_bytes) unsigned int bytes, unsigned int bidi_bytes)
@ -687,37 +601,22 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
destroy_rcu_head(&cmd->rcu); destroy_rcu_head(&cmd->rcu);
} }
if (req->mq_ctx) { /*
/* * In the MQ case the command gets freed by __blk_mq_end_request,
* In the MQ case the command gets freed by __blk_mq_end_request, * so we have to do all cleanup that depends on it earlier.
* so we have to do all cleanup that depends on it earlier. *
* * We also can't kick the queues from irq context, so we
* We also can't kick the queues from irq context, so we * will have to defer it to a workqueue.
* will have to defer it to a workqueue. */
*/ scsi_mq_uninit_cmd(cmd);
scsi_mq_uninit_cmd(cmd);
__blk_mq_end_request(req, error); __blk_mq_end_request(req, error);
if (scsi_target(sdev)->single_lun || if (scsi_target(sdev)->single_lun ||
!list_empty(&sdev->host->starved_list)) !list_empty(&sdev->host->starved_list))
kblockd_schedule_work(&sdev->requeue_work); kblockd_schedule_work(&sdev->requeue_work);
else else
blk_mq_run_hw_queues(q, true); blk_mq_run_hw_queues(q, true);
} else {
unsigned long flags;
if (bidi_bytes)
scsi_release_bidi_buffers(cmd);
scsi_release_buffers(cmd);
scsi_put_command(cmd);
spin_lock_irqsave(q->queue_lock, flags);
blk_finish_request(req, error);
spin_unlock_irqrestore(q->queue_lock, flags);
scsi_run_queue(q);
}
put_device(&sdev->sdev_gendev); put_device(&sdev->sdev_gendev);
return false; return false;
@ -766,13 +665,7 @@ static void scsi_io_completion_reprep(struct scsi_cmnd *cmd,
struct request_queue *q) struct request_queue *q)
{ {
/* A new command will be prepared and issued. */ /* A new command will be prepared and issued. */
if (q->mq_ops) { scsi_mq_requeue_cmd(cmd);
scsi_mq_requeue_cmd(cmd);
} else {
/* Unprep request and put it back at head of the queue. */
scsi_release_buffers(cmd);
scsi_requeue_command(q, cmd);
}
} }
/* Helper for scsi_io_completion() when special action required. */ /* Helper for scsi_io_completion() when special action required. */
@ -1147,9 +1040,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb)
*/ */
int scsi_init_io(struct scsi_cmnd *cmd) int scsi_init_io(struct scsi_cmnd *cmd)
{ {
struct scsi_device *sdev = cmd->device;
struct request *rq = cmd->request; struct request *rq = cmd->request;
bool is_mq = (rq->mq_ctx != NULL);
int error = BLKPREP_KILL; int error = BLKPREP_KILL;
if (WARN_ON_ONCE(!blk_rq_nr_phys_segments(rq))) if (WARN_ON_ONCE(!blk_rq_nr_phys_segments(rq)))
@ -1160,17 +1051,6 @@ int scsi_init_io(struct scsi_cmnd *cmd)
goto err_exit; goto err_exit;
if (blk_bidi_rq(rq)) { if (blk_bidi_rq(rq)) {
if (!rq->q->mq_ops) {
struct scsi_data_buffer *bidi_sdb =
kmem_cache_zalloc(scsi_sdb_cache, GFP_ATOMIC);
if (!bidi_sdb) {
error = BLKPREP_DEFER;
goto err_exit;
}
rq->next_rq->special = bidi_sdb;
}
error = scsi_init_sgtable(rq->next_rq, rq->next_rq->special); error = scsi_init_sgtable(rq->next_rq, rq->next_rq->special);
if (error) if (error)
goto err_exit; goto err_exit;
@ -1210,14 +1090,7 @@ int scsi_init_io(struct scsi_cmnd *cmd)
return BLKPREP_OK; return BLKPREP_OK;
err_exit: err_exit:
if (is_mq) { scsi_mq_free_sgtables(cmd);
scsi_mq_free_sgtables(cmd);
} else {
scsi_release_buffers(cmd);
cmd->request->special = NULL;
scsi_put_command(cmd);
put_device(&sdev->sdev_gendev);
}
return error; return error;
} }
EXPORT_SYMBOL(scsi_init_io); EXPORT_SYMBOL(scsi_init_io);
@ -1423,75 +1296,6 @@ scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
return ret; return ret;
} }
static int
scsi_prep_return(struct request_queue *q, struct request *req, int ret)
{
struct scsi_device *sdev = q->queuedata;
switch (ret) {
case BLKPREP_KILL:
case BLKPREP_INVALID:
scsi_req(req)->result = DID_NO_CONNECT << 16;
/* release the command and kill it */
if (req->special) {
struct scsi_cmnd *cmd = req->special;
scsi_release_buffers(cmd);
scsi_put_command(cmd);
put_device(&sdev->sdev_gendev);
req->special = NULL;
}
break;
case BLKPREP_DEFER:
/*
* If we defer, the blk_peek_request() returns NULL, but the
* queue must be restarted, so we schedule a callback to happen
* shortly.
*/
if (atomic_read(&sdev->device_busy) == 0)
blk_delay_queue(q, SCSI_QUEUE_DELAY);
break;
default:
req->rq_flags |= RQF_DONTPREP;
}
return ret;
}
static int scsi_prep_fn(struct request_queue *q, struct request *req)
{
struct scsi_device *sdev = q->queuedata;
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
int ret;
ret = scsi_prep_state_check(sdev, req);
if (ret != BLKPREP_OK)
goto out;
if (!req->special) {
/* Bail if we can't get a reference to the device */
if (unlikely(!get_device(&sdev->sdev_gendev))) {
ret = BLKPREP_DEFER;
goto out;
}
scsi_init_command(sdev, cmd);
req->special = cmd;
}
cmd->tag = req->tag;
cmd->request = req;
cmd->prot_op = SCSI_PROT_NORMAL;
ret = scsi_setup_cmnd(sdev, req);
out:
return scsi_prep_return(q, req, ret);
}
static void scsi_unprep_fn(struct request_queue *q, struct request *req)
{
scsi_uninit_cmd(blk_mq_rq_to_pdu(req));
}
/* /*
* scsi_dev_queue_ready: if we can send requests to sdev, return 1 else * scsi_dev_queue_ready: if we can send requests to sdev, return 1 else
* return 0. * return 0.
@ -1511,14 +1315,8 @@ static inline int scsi_dev_queue_ready(struct request_queue *q,
/* /*
* unblock after device_blocked iterates to zero * unblock after device_blocked iterates to zero
*/ */
if (atomic_dec_return(&sdev->device_blocked) > 0) { if (atomic_dec_return(&sdev->device_blocked) > 0)
/*
* For the MQ case we take care of this in the caller.
*/
if (!q->mq_ops)
blk_delay_queue(q, SCSI_QUEUE_DELAY);
goto out_dec; goto out_dec;
}
SCSI_LOG_MLQUEUE(3, sdev_printk(KERN_INFO, sdev, SCSI_LOG_MLQUEUE(3, sdev_printk(KERN_INFO, sdev,
"unblocking device at zero depth\n")); "unblocking device at zero depth\n"));
} }
@ -1653,13 +1451,13 @@ out_dec:
* needs to return 'not busy'. Otherwise, request stacking drivers * needs to return 'not busy'. Otherwise, request stacking drivers
* may hold requests forever. * may hold requests forever.
*/ */
static int scsi_lld_busy(struct request_queue *q) static bool scsi_mq_lld_busy(struct request_queue *q)
{ {
struct scsi_device *sdev = q->queuedata; struct scsi_device *sdev = q->queuedata;
struct Scsi_Host *shost; struct Scsi_Host *shost;
if (blk_queue_dying(q)) if (blk_queue_dying(q))
return 0; return false;
shost = sdev->host; shost = sdev->host;
@ -1670,48 +1468,9 @@ static int scsi_lld_busy(struct request_queue *q)
* in SCSI layer. * in SCSI layer.
*/ */
if (scsi_host_in_recovery(shost) || scsi_device_is_busy(sdev)) if (scsi_host_in_recovery(shost) || scsi_device_is_busy(sdev))
return 1; return true;
return 0; return false;
}
static bool scsi_mq_lld_busy(struct request_queue *q)
{
return scsi_lld_busy(q);
}
/*
* Kill a request for a dead device
*/
static void scsi_kill_request(struct request *req, struct request_queue *q)
{
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
struct scsi_device *sdev;
struct scsi_target *starget;
struct Scsi_Host *shost;
blk_start_request(req);
scmd_printk(KERN_INFO, cmd, "killing request\n");
sdev = cmd->device;
starget = scsi_target(sdev);
shost = sdev->host;
scsi_init_cmd_errh(cmd);
cmd->result = DID_NO_CONNECT << 16;
atomic_inc(&cmd->device->iorequest_cnt);
/*
* SCSI request completion path will do scsi_device_unbusy(),
* bump busy counts. To bump the counters, we need to dance
* with the locks as normal issue path does.
*/
atomic_inc(&sdev->device_busy);
atomic_inc(&shost->host_busy);
if (starget->can_queue > 0)
atomic_inc(&starget->target_busy);
blk_complete_request(req);
} }
static void scsi_softirq_done(struct request *rq) static void scsi_softirq_done(struct request *rq)
@ -1834,158 +1593,6 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
return 0; return 0;
} }
/**
* scsi_done - Invoke completion on finished SCSI command.
* @cmd: The SCSI Command for which a low-level device driver (LLDD) gives
* ownership back to SCSI Core -- i.e. the LLDD has finished with it.
*
* Description: This function is the mid-level's (SCSI Core) interrupt routine,
* which regains ownership of the SCSI command (de facto) from a LLDD, and
* calls blk_complete_request() for further processing.
*
* This function is interrupt context safe.
*/
static void scsi_done(struct scsi_cmnd *cmd)
{
trace_scsi_dispatch_cmd_done(cmd);
blk_complete_request(cmd->request);
}
/*
* Function: scsi_request_fn()
*
* Purpose: Main strategy routine for SCSI.
*
* Arguments: q - Pointer to actual queue.
*
* Returns: Nothing
*
* Lock status: request queue lock assumed to be held when called.
*
* Note: See sd_zbc.c sd_zbc_write_lock_zone() for write order
* protection for ZBC disks.
*/
static void scsi_request_fn(struct request_queue *q)
__releases(q->queue_lock)
__acquires(q->queue_lock)
{
struct scsi_device *sdev = q->queuedata;
struct Scsi_Host *shost;
struct scsi_cmnd *cmd;
struct request *req;
/*
* To start with, we keep looping until the queue is empty, or until
* the host is no longer able to accept any more requests.
*/
shost = sdev->host;
for (;;) {
int rtn;
/*
* get next queueable request. We do this early to make sure
* that the request is fully prepared even if we cannot
* accept it.
*/
req = blk_peek_request(q);
if (!req)
break;
if (unlikely(!scsi_device_online(sdev))) {
sdev_printk(KERN_ERR, sdev,
"rejecting I/O to offline device\n");
scsi_kill_request(req, q);
continue;
}
if (!scsi_dev_queue_ready(q, sdev))
break;
/*
* Remove the request from the request list.
*/
if (!(blk_queue_tagged(q) && !blk_queue_start_tag(q, req)))
blk_start_request(req);
spin_unlock_irq(q->queue_lock);
cmd = blk_mq_rq_to_pdu(req);
if (cmd != req->special) {
printk(KERN_CRIT "impossible request in %s.\n"
"please mail a stack trace to "
"linux-scsi@vger.kernel.org\n",
__func__);
blk_dump_rq_flags(req, "foo");
BUG();
}
/*
* We hit this when the driver is using a host wide
* tag map. For device level tag maps the queue_depth check
* in the device ready fn would prevent us from trying
* to allocate a tag. Since the map is a shared host resource
* we add the dev to the starved list so it eventually gets
* a run when a tag is freed.
*/
if (blk_queue_tagged(q) && !(req->rq_flags & RQF_QUEUED)) {
spin_lock_irq(shost->host_lock);
if (list_empty(&sdev->starved_entry))
list_add_tail(&sdev->starved_entry,
&shost->starved_list);
spin_unlock_irq(shost->host_lock);
goto not_ready;
}
if (!scsi_target_queue_ready(shost, sdev))
goto not_ready;
if (!scsi_host_queue_ready(q, shost, sdev))
goto host_not_ready;
if (sdev->simple_tags)
cmd->flags |= SCMD_TAGGED;
else
cmd->flags &= ~SCMD_TAGGED;
/*
* Finally, initialize any error handling parameters, and set up
* the timers for timeouts.
*/
scsi_init_cmd_errh(cmd);
/*
* Dispatch the command to the low-level driver.
*/
cmd->scsi_done = scsi_done;
rtn = scsi_dispatch_cmd(cmd);
if (rtn) {
scsi_queue_insert(cmd, rtn);
spin_lock_irq(q->queue_lock);
goto out_delay;
}
spin_lock_irq(q->queue_lock);
}
return;
host_not_ready:
if (scsi_target(sdev)->can_queue > 0)
atomic_dec(&scsi_target(sdev)->target_busy);
not_ready:
/*
* lock q, handle tag, requeue req, and decrement device_busy. We
* must return with queue_lock held.
*
* Decrementing device_busy without checking it is OK, as all such
* cases (host limits or settings) should run the queue at some
* later time.
*/
spin_lock_irq(q->queue_lock);
blk_requeue_request(q, req);
atomic_dec(&sdev->device_busy);
out_delay:
if (!atomic_read(&sdev->device_busy) && !scsi_device_blocked(sdev))
blk_delay_queue(q, SCSI_QUEUE_DELAY);
}
static inline blk_status_t prep_to_mq(int ret) static inline blk_status_t prep_to_mq(int ret)
{ {
switch (ret) { switch (ret) {
@ -2248,77 +1855,6 @@ void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q)
} }
EXPORT_SYMBOL_GPL(__scsi_init_queue); EXPORT_SYMBOL_GPL(__scsi_init_queue);
static int scsi_old_init_rq(struct request_queue *q, struct request *rq,
gfp_t gfp)
{
struct Scsi_Host *shost = q->rq_alloc_data;
const bool unchecked_isa_dma = shost->unchecked_isa_dma;
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
memset(cmd, 0, sizeof(*cmd));
if (unchecked_isa_dma)
cmd->flags |= SCMD_UNCHECKED_ISA_DMA;
cmd->sense_buffer = scsi_alloc_sense_buffer(unchecked_isa_dma, gfp,
NUMA_NO_NODE);
if (!cmd->sense_buffer)
goto fail;
cmd->req.sense = cmd->sense_buffer;
if (scsi_host_get_prot(shost) >= SHOST_DIX_TYPE0_PROTECTION) {
cmd->prot_sdb = kmem_cache_zalloc(scsi_sdb_cache, gfp);
if (!cmd->prot_sdb)
goto fail_free_sense;
}
return 0;
fail_free_sense:
scsi_free_sense_buffer(unchecked_isa_dma, cmd->sense_buffer);
fail:
return -ENOMEM;
}
static void scsi_old_exit_rq(struct request_queue *q, struct request *rq)
{
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
if (cmd->prot_sdb)
kmem_cache_free(scsi_sdb_cache, cmd->prot_sdb);
scsi_free_sense_buffer(cmd->flags & SCMD_UNCHECKED_ISA_DMA,
cmd->sense_buffer);
}
struct request_queue *scsi_old_alloc_queue(struct scsi_device *sdev)
{
struct Scsi_Host *shost = sdev->host;
struct request_queue *q;
q = blk_alloc_queue_node(GFP_KERNEL, NUMA_NO_NODE, NULL);
if (!q)
return NULL;
q->cmd_size = sizeof(struct scsi_cmnd) + shost->hostt->cmd_size;
q->rq_alloc_data = shost;
q->request_fn = scsi_request_fn;
q->init_rq_fn = scsi_old_init_rq;
q->exit_rq_fn = scsi_old_exit_rq;
q->initialize_rq_fn = scsi_initialize_rq;
if (blk_init_allocated_queue(q) < 0) {
blk_cleanup_queue(q);
return NULL;
}
__scsi_init_queue(shost, q);
blk_queue_flag_set(QUEUE_FLAG_SCSI_PASSTHROUGH, q);
blk_queue_prep_rq(q, scsi_prep_fn);
blk_queue_unprep_rq(q, scsi_unprep_fn);
blk_queue_softirq_done(q, scsi_softirq_done);
blk_queue_rq_timed_out(q, scsi_times_out);
blk_queue_lld_busy(q, scsi_lld_busy);
return q;
}
static const struct blk_mq_ops scsi_mq_ops = { static const struct blk_mq_ops scsi_mq_ops = {
.get_budget = scsi_mq_get_budget, .get_budget = scsi_mq_get_budget,
.put_budget = scsi_mq_put_budget, .put_budget = scsi_mq_put_budget,
@ -2386,10 +1922,7 @@ struct scsi_device *scsi_device_from_queue(struct request_queue *q)
{ {
struct scsi_device *sdev = NULL; struct scsi_device *sdev = NULL;
if (q->mq_ops) { if (q->mq_ops == &scsi_mq_ops)
if (q->mq_ops == &scsi_mq_ops)
sdev = q->queuedata;
} else if (q->request_fn == scsi_request_fn)
sdev = q->queuedata; sdev = q->queuedata;
if (!sdev || !get_device(&sdev->sdev_gendev)) if (!sdev || !get_device(&sdev->sdev_gendev))
sdev = NULL; sdev = NULL;
@ -2992,39 +2525,6 @@ void sdev_evt_send_simple(struct scsi_device *sdev,
} }
EXPORT_SYMBOL_GPL(sdev_evt_send_simple); EXPORT_SYMBOL_GPL(sdev_evt_send_simple);
/**
* scsi_request_fn_active() - number of kernel threads inside scsi_request_fn()
* @sdev: SCSI device to count the number of scsi_request_fn() callers for.
*/
static int scsi_request_fn_active(struct scsi_device *sdev)
{
struct request_queue *q = sdev->request_queue;
int request_fn_active;
WARN_ON_ONCE(sdev->host->use_blk_mq);
spin_lock_irq(q->queue_lock);
request_fn_active = q->request_fn_active;
spin_unlock_irq(q->queue_lock);
return request_fn_active;
}
/**
* scsi_wait_for_queuecommand() - wait for ongoing queuecommand() calls
* @sdev: SCSI device pointer.
*
* Wait until the ongoing shost->hostt->queuecommand() calls that are
* invoked from scsi_request_fn() have finished.
*/
static void scsi_wait_for_queuecommand(struct scsi_device *sdev)
{
WARN_ON_ONCE(sdev->host->use_blk_mq);
while (scsi_request_fn_active(sdev))
msleep(20);
}
/** /**
* scsi_device_quiesce - Block user issued commands. * scsi_device_quiesce - Block user issued commands.
* @sdev: scsi device to quiesce. * @sdev: scsi device to quiesce.
@ -3148,7 +2648,6 @@ EXPORT_SYMBOL(scsi_target_resume);
int scsi_internal_device_block_nowait(struct scsi_device *sdev) int scsi_internal_device_block_nowait(struct scsi_device *sdev)
{ {
struct request_queue *q = sdev->request_queue; struct request_queue *q = sdev->request_queue;
unsigned long flags;
int err = 0; int err = 0;
err = scsi_device_set_state(sdev, SDEV_BLOCK); err = scsi_device_set_state(sdev, SDEV_BLOCK);
@ -3164,14 +2663,7 @@ int scsi_internal_device_block_nowait(struct scsi_device *sdev)
* block layer from calling the midlayer with this device's * block layer from calling the midlayer with this device's
* request queue. * request queue.
*/ */
if (q->mq_ops) { blk_mq_quiesce_queue_nowait(q);
blk_mq_quiesce_queue_nowait(q);
} else {
spin_lock_irqsave(q->queue_lock, flags);
blk_stop_queue(q);
spin_unlock_irqrestore(q->queue_lock, flags);
}
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait); EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait);
@ -3202,12 +2694,8 @@ static int scsi_internal_device_block(struct scsi_device *sdev)
mutex_lock(&sdev->state_mutex); mutex_lock(&sdev->state_mutex);
err = scsi_internal_device_block_nowait(sdev); err = scsi_internal_device_block_nowait(sdev);
if (err == 0) { if (err == 0)
if (q->mq_ops) blk_mq_quiesce_queue(q);
blk_mq_quiesce_queue(q);
else
scsi_wait_for_queuecommand(sdev);
}
mutex_unlock(&sdev->state_mutex); mutex_unlock(&sdev->state_mutex);
return err; return err;
@ -3216,15 +2704,8 @@ static int scsi_internal_device_block(struct scsi_device *sdev)
void scsi_start_queue(struct scsi_device *sdev) void scsi_start_queue(struct scsi_device *sdev)
{ {
struct request_queue *q = sdev->request_queue; struct request_queue *q = sdev->request_queue;
unsigned long flags;
if (q->mq_ops) { blk_mq_unquiesce_queue(q);
blk_mq_unquiesce_queue(q);
} else {
spin_lock_irqsave(q->queue_lock, flags);
blk_start_queue(q);
spin_unlock_irqrestore(q->queue_lock, flags);
}
} }
/** /**

View File

@ -92,7 +92,6 @@ extern void scsi_queue_insert(struct scsi_cmnd *cmd, int reason);
extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); extern void scsi_io_completion(struct scsi_cmnd *, unsigned int);
extern void scsi_run_host_queues(struct Scsi_Host *shost); extern void scsi_run_host_queues(struct Scsi_Host *shost);
extern void scsi_requeue_run_queue(struct work_struct *work); extern void scsi_requeue_run_queue(struct work_struct *work);
extern struct request_queue *scsi_old_alloc_queue(struct scsi_device *sdev);
extern struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev); extern struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev);
extern void scsi_start_queue(struct scsi_device *sdev); extern void scsi_start_queue(struct scsi_device *sdev);
extern int scsi_mq_setup_tags(struct Scsi_Host *shost); extern int scsi_mq_setup_tags(struct Scsi_Host *shost);

View File

@ -266,10 +266,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
*/ */
sdev->borken = 1; sdev->borken = 1;
if (shost_use_blk_mq(shost)) sdev->request_queue = scsi_mq_alloc_queue(sdev);
sdev->request_queue = scsi_mq_alloc_queue(sdev);
else
sdev->request_queue = scsi_old_alloc_queue(sdev);
if (!sdev->request_queue) { if (!sdev->request_queue) {
/* release fn is set up in scsi_sysfs_device_initialise, so /* release fn is set up in scsi_sysfs_device_initialise, so
* have to free and put manually here */ * have to free and put manually here */
@ -280,11 +277,6 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
WARN_ON_ONCE(!blk_get_queue(sdev->request_queue)); WARN_ON_ONCE(!blk_get_queue(sdev->request_queue));
sdev->request_queue->queuedata = sdev; sdev->request_queue->queuedata = sdev;
if (!shost_use_blk_mq(sdev->host)) {
blk_queue_init_tags(sdev->request_queue,
sdev->host->cmd_per_lun, shost->bqt,
shost->hostt->tag_alloc_policy);
}
scsi_change_queue_depth(sdev, sdev->host->cmd_per_lun ? scsi_change_queue_depth(sdev, sdev->host->cmd_per_lun ?
sdev->host->cmd_per_lun : 1); sdev->host->cmd_per_lun : 1);

View File

@ -367,7 +367,6 @@ store_shost_eh_deadline(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(eh_deadline, S_IRUGO | S_IWUSR, show_shost_eh_deadline, store_shost_eh_deadline); static DEVICE_ATTR(eh_deadline, S_IRUGO | S_IWUSR, show_shost_eh_deadline, store_shost_eh_deadline);
shost_rd_attr(use_blk_mq, "%d\n");
shost_rd_attr(unique_id, "%u\n"); shost_rd_attr(unique_id, "%u\n");
shost_rd_attr(cmd_per_lun, "%hd\n"); shost_rd_attr(cmd_per_lun, "%hd\n");
shost_rd_attr(can_queue, "%hd\n"); shost_rd_attr(can_queue, "%hd\n");
@ -386,6 +385,13 @@ show_host_busy(struct device *dev, struct device_attribute *attr, char *buf)
} }
static DEVICE_ATTR(host_busy, S_IRUGO, show_host_busy, NULL); static DEVICE_ATTR(host_busy, S_IRUGO, show_host_busy, NULL);
static ssize_t
show_use_blk_mq(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "1\n");
}
static DEVICE_ATTR(use_blk_mq, S_IRUGO, show_use_blk_mq, NULL);
static struct attribute *scsi_sysfs_shost_attrs[] = { static struct attribute *scsi_sysfs_shost_attrs[] = {
&dev_attr_use_blk_mq.attr, &dev_attr_use_blk_mq.attr,
&dev_attr_unique_id.attr, &dev_attr_unique_id.attr,

View File

@ -8100,12 +8100,6 @@ int ufshcd_alloc_host(struct device *dev, struct ufs_hba **hba_handle)
goto out_error; goto out_error;
} }
/*
* Do not use blk-mq at this time because blk-mq does not support
* runtime pm.
*/
host->use_blk_mq = false;
hba = shost_priv(host); hba = shost_priv(host);
hba->host = host; hba->host = host;
hba->dev = dev; hba->dev = dev;

View File

@ -11,7 +11,6 @@
#include <linux/blk-mq.h> #include <linux/blk-mq.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
struct request_queue;
struct block_device; struct block_device;
struct completion; struct completion;
struct module; struct module;
@ -22,7 +21,6 @@ struct scsi_target;
struct Scsi_Host; struct Scsi_Host;
struct scsi_host_cmd_pool; struct scsi_host_cmd_pool;
struct scsi_transport_template; struct scsi_transport_template;
struct blk_queue_tags;
/* /*
@ -547,14 +545,8 @@ struct Scsi_Host {
struct scsi_host_template *hostt; struct scsi_host_template *hostt;
struct scsi_transport_template *transportt; struct scsi_transport_template *transportt;
/* /* Area to keep a shared tag map */
* Area to keep a shared tag map (if needed, will be struct blk_mq_tag_set tag_set;
* NULL if not).
*/
union {
struct blk_queue_tag *bqt;
struct blk_mq_tag_set tag_set;
};
atomic_t host_busy; /* commands actually active on low-level */ atomic_t host_busy; /* commands actually active on low-level */
atomic_t host_blocked; atomic_t host_blocked;
@ -648,7 +640,6 @@ struct Scsi_Host {
/* The controller does not support WRITE SAME */ /* The controller does not support WRITE SAME */
unsigned no_write_same:1; unsigned no_write_same:1;
unsigned use_blk_mq:1;
unsigned use_cmd_list:1; unsigned use_cmd_list:1;
/* Host responded with short (<36 bytes) INQUIRY result */ /* Host responded with short (<36 bytes) INQUIRY result */
@ -742,11 +733,6 @@ static inline int scsi_host_in_recovery(struct Scsi_Host *shost)
shost->tmf_in_progress; shost->tmf_in_progress;
} }
static inline bool shost_use_blk_mq(struct Scsi_Host *shost)
{
return shost->use_blk_mq;
}
extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *); extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *);
extern void scsi_flush_work(struct Scsi_Host *); extern void scsi_flush_work(struct Scsi_Host *);

View File

@ -23,19 +23,15 @@ static inline struct scsi_cmnd *scsi_host_find_tag(struct Scsi_Host *shost,
int tag) int tag)
{ {
struct request *req = NULL; struct request *req = NULL;
u16 hwq;
if (tag == SCSI_NO_TAG) if (tag == SCSI_NO_TAG)
return NULL; return NULL;
if (shost_use_blk_mq(shost)) { hwq = blk_mq_unique_tag_to_hwq(tag);
u16 hwq = blk_mq_unique_tag_to_hwq(tag); if (hwq < shost->tag_set.nr_hw_queues) {
req = blk_mq_tag_to_rq(shost->tag_set.tags[hwq],
if (hwq < shost->tag_set.nr_hw_queues) { blk_mq_unique_tag_to_tag(tag));
req = blk_mq_tag_to_rq(shost->tag_set.tags[hwq],
blk_mq_unique_tag_to_tag(tag));
}
} else {
req = blk_map_queue_find_tag(shost->bqt, tag);
} }
if (!req) if (!req)