summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2019-05-30 07:28:10 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2019-07-22 16:44:07 -0400
commit8930a6c207918d5a5675eedab06a71096b1a3d47 (patch)
treeddb7520a1e2648e3cd50530a145ea5e0ee11e913
parentcf949bbe22bee8749078e0b810ee2dc60a983746 (diff)
scsi: core: add support for request batching
This allows a list of requests to be issued, with the LLD only writing the hardware doorbell when necessary, after the last request was prepared. This is more efficient if we have lists of requests to issue, particularly on virtualized hardware, where writing the doorbell is more expensive than on real hardware. The use case for this is plugged IO, where blk-mq flushes a batch of requests all at once. The API is the same as for blk-mq, just with blk-mq concepts tweaked to fit the SCSI subsystem API: the "last" flag in blk_mq_queue_data becomes a flag in scsi_cmnd, while the queue_num in the commit_rqs callback is extracted from the hctx and passed as a parameter. The only complication is that blk-mq uses different plugging heuristics depending on whether commit_rqs is present or not. So we have two different sets of blk_mq_ops and pick one depending on whether the scsi_host template uses commit_rqs or not. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Ming Lei <ming.lei@redhat.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/scsi_lib.c37
-rw-r--r--include/scsi/scsi_cmnd.h1
-rw-r--r--include/scsi/scsi_host.h16
3 files changed, 49 insertions, 5 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 9381171c2fc0..c72bce2f0cf1 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1666,10 +1666,11 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
1666 blk_mq_start_request(req); 1666 blk_mq_start_request(req);
1667 } 1667 }
1668 1668
1669 cmd->flags &= SCMD_PRESERVED_FLAGS;
1669 if (sdev->simple_tags) 1670 if (sdev->simple_tags)
1670 cmd->flags |= SCMD_TAGGED; 1671 cmd->flags |= SCMD_TAGGED;
1671 else 1672 if (bd->last)
1672 cmd->flags &= ~SCMD_TAGGED; 1673 cmd->flags |= SCMD_LAST;
1673 1674
1674 scsi_init_cmd_errh(cmd); 1675 scsi_init_cmd_errh(cmd);
1675 cmd->scsi_done = scsi_mq_done; 1676 cmd->scsi_done = scsi_mq_done;
@@ -1807,10 +1808,37 @@ void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q)
1807} 1808}
1808EXPORT_SYMBOL_GPL(__scsi_init_queue); 1809EXPORT_SYMBOL_GPL(__scsi_init_queue);
1809 1810
1811static const struct blk_mq_ops scsi_mq_ops_no_commit = {
1812 .get_budget = scsi_mq_get_budget,
1813 .put_budget = scsi_mq_put_budget,
1814 .queue_rq = scsi_queue_rq,
1815 .complete = scsi_softirq_done,
1816 .timeout = scsi_timeout,
1817#ifdef CONFIG_BLK_DEBUG_FS
1818 .show_rq = scsi_show_rq,
1819#endif
1820 .init_request = scsi_mq_init_request,
1821 .exit_request = scsi_mq_exit_request,
1822 .initialize_rq_fn = scsi_initialize_rq,
1823 .busy = scsi_mq_lld_busy,
1824 .map_queues = scsi_map_queues,
1825};
1826
1827
1828static void scsi_commit_rqs(struct blk_mq_hw_ctx *hctx)
1829{
1830 struct request_queue *q = hctx->queue;
1831 struct scsi_device *sdev = q->queuedata;
1832 struct Scsi_Host *shost = sdev->host;
1833
1834 shost->hostt->commit_rqs(shost, hctx->queue_num);
1835}
1836
1810static const struct blk_mq_ops scsi_mq_ops = { 1837static const struct blk_mq_ops scsi_mq_ops = {
1811 .get_budget = scsi_mq_get_budget, 1838 .get_budget = scsi_mq_get_budget,
1812 .put_budget = scsi_mq_put_budget, 1839 .put_budget = scsi_mq_put_budget,
1813 .queue_rq = scsi_queue_rq, 1840 .queue_rq = scsi_queue_rq,
1841 .commit_rqs = scsi_commit_rqs,
1814 .complete = scsi_softirq_done, 1842 .complete = scsi_softirq_done,
1815 .timeout = scsi_timeout, 1843 .timeout = scsi_timeout,
1816#ifdef CONFIG_BLK_DEBUG_FS 1844#ifdef CONFIG_BLK_DEBUG_FS
@@ -1846,7 +1874,10 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost)
1846 sizeof(struct scatterlist) * SCSI_INLINE_PROT_SG_CNT; 1874 sizeof(struct scatterlist) * SCSI_INLINE_PROT_SG_CNT;
1847 1875
1848 memset(&shost->tag_set, 0, sizeof(shost->tag_set)); 1876 memset(&shost->tag_set, 0, sizeof(shost->tag_set));
1849 shost->tag_set.ops = &scsi_mq_ops; 1877 if (shost->hostt->commit_rqs)
1878 shost->tag_set.ops = &scsi_mq_ops;
1879 else
1880 shost->tag_set.ops = &scsi_mq_ops_no_commit;
1850 shost->tag_set.nr_hw_queues = shost->nr_hw_queues ? : 1; 1881 shost->tag_set.nr_hw_queues = shost->nr_hw_queues ? : 1;
1851 shost->tag_set.queue_depth = shost->can_queue; 1882 shost->tag_set.queue_depth = shost->can_queue;
1852 shost->tag_set.cmd_size = cmd_size; 1883 shost->tag_set.cmd_size = cmd_size;
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 76ed5e4acd38..91bd749a02f7 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -57,6 +57,7 @@ struct scsi_pointer {
57#define SCMD_TAGGED (1 << 0) 57#define SCMD_TAGGED (1 << 0)
58#define SCMD_UNCHECKED_ISA_DMA (1 << 1) 58#define SCMD_UNCHECKED_ISA_DMA (1 << 1)
59#define SCMD_INITIALIZED (1 << 2) 59#define SCMD_INITIALIZED (1 << 2)
60#define SCMD_LAST (1 << 3)
60/* flags preserved across unprep / reprep */ 61/* flags preserved across unprep / reprep */
61#define SCMD_PRESERVED_FLAGS (SCMD_UNCHECKED_ISA_DMA | SCMD_INITIALIZED) 62#define SCMD_PRESERVED_FLAGS (SCMD_UNCHECKED_ISA_DMA | SCMD_INITIALIZED)
62 63
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index cc139dbd71e5..31e0d6ca1eba 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -80,8 +80,10 @@ struct scsi_host_template {
80 * command block to the LLDD. When the driver finished 80 * command block to the LLDD. When the driver finished
81 * processing the command the done callback is invoked. 81 * processing the command the done callback is invoked.
82 * 82 *
83 * If queuecommand returns 0, then the HBA has accepted the 83 * If queuecommand returns 0, then the driver has accepted the
84 * command. The done() function must be called on the command 84 * command. It must also push it to the HBA if the scsi_cmnd
85 * flag SCMD_LAST is set, or if the driver does not implement
86 * commit_rqs. The done() function must be called on the command
85 * when the driver has finished with it. (you may call done on the 87 * when the driver has finished with it. (you may call done on the
86 * command before queuecommand returns, but in this case you 88 * command before queuecommand returns, but in this case you
87 * *must* return 0 from queuecommand). 89 * *must* return 0 from queuecommand).
@@ -110,6 +112,16 @@ struct scsi_host_template {
110 int (* queuecommand)(struct Scsi_Host *, struct scsi_cmnd *); 112 int (* queuecommand)(struct Scsi_Host *, struct scsi_cmnd *);
111 113
112 /* 114 /*
115 * The commit_rqs function is used to trigger a hardware
116 * doorbell after some requests have been queued with
117 * queuecommand, when an error is encountered before sending
118 * the request with SCMD_LAST set.
119 *
120 * STATUS: OPTIONAL
121 */
122 void (*commit_rqs)(struct Scsi_Host *, u16);
123
124 /*
113 * This is an error handling strategy routine. You don't need to 125 * This is an error handling strategy routine. You don't need to
114 * define one of these if you don't want to - there is a default 126 * define one of these if you don't want to - there is a default
115 * routine that is present that should work in most cases. For those 127 * routine that is present that should work in most cases. For those