summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/blk-mq.c29
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c5
-rw-r--r--drivers/block/null_blk.c10
-rw-r--r--drivers/block/virtio_blk.c7
-rw-r--r--drivers/scsi/scsi_lib.c5
-rw-r--r--include/linux/blk-mq.h8
6 files changed, 49 insertions, 15 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 68929bad9a6a..7e5303820452 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -680,6 +680,8 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
680 struct request_queue *q = hctx->queue; 680 struct request_queue *q = hctx->queue;
681 struct request *rq; 681 struct request *rq;
682 LIST_HEAD(rq_list); 682 LIST_HEAD(rq_list);
683 LIST_HEAD(driver_list);
684 struct list_head *dptr;
683 int queued; 685 int queued;
684 686
685 WARN_ON(!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask)); 687 WARN_ON(!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask));
@@ -706,16 +708,27 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
706 } 708 }
707 709
708 /* 710 /*
711 * Start off with dptr being NULL, so we start the first request
712 * immediately, even if we have more pending.
713 */
714 dptr = NULL;
715
716 /*
709 * Now process all the entries, sending them to the driver. 717 * Now process all the entries, sending them to the driver.
710 */ 718 */
711 queued = 0; 719 queued = 0;
712 while (!list_empty(&rq_list)) { 720 while (!list_empty(&rq_list)) {
721 struct blk_mq_queue_data bd;
713 int ret; 722 int ret;
714 723
715 rq = list_first_entry(&rq_list, struct request, queuelist); 724 rq = list_first_entry(&rq_list, struct request, queuelist);
716 list_del_init(&rq->queuelist); 725 list_del_init(&rq->queuelist);
717 726
718 ret = q->mq_ops->queue_rq(hctx, rq, list_empty(&rq_list)); 727 bd.rq = rq;
728 bd.list = dptr;
729 bd.last = list_empty(&rq_list);
730
731 ret = q->mq_ops->queue_rq(hctx, &bd);
719 switch (ret) { 732 switch (ret) {
720 case BLK_MQ_RQ_QUEUE_OK: 733 case BLK_MQ_RQ_QUEUE_OK:
721 queued++; 734 queued++;
@@ -734,6 +747,13 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
734 747
735 if (ret == BLK_MQ_RQ_QUEUE_BUSY) 748 if (ret == BLK_MQ_RQ_QUEUE_BUSY)
736 break; 749 break;
750
751 /*
752 * We've done the first request. If we have more than 1
753 * left in the list, set dptr to defer issue.
754 */
755 if (!dptr && rq_list.next != rq_list.prev)
756 dptr = &driver_list;
737 } 757 }
738 758
739 if (!queued) 759 if (!queued)
@@ -1153,6 +1173,11 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio)
1153 } 1173 }
1154 1174
1155 if (is_sync) { 1175 if (is_sync) {
1176 struct blk_mq_queue_data bd = {
1177 .rq = rq,
1178 .list = NULL,
1179 .last = 1
1180 };
1156 int ret; 1181 int ret;
1157 1182
1158 blk_mq_bio_to_request(rq, bio); 1183 blk_mq_bio_to_request(rq, bio);
@@ -1162,7 +1187,7 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio)
1162 * error (busy), just add it to our list as we previously 1187 * error (busy), just add it to our list as we previously
1163 * would have done 1188 * would have done
1164 */ 1189 */
1165 ret = q->mq_ops->queue_rq(data.hctx, rq, true); 1190 ret = q->mq_ops->queue_rq(data.hctx, &bd);
1166 if (ret == BLK_MQ_RQ_QUEUE_OK) 1191 if (ret == BLK_MQ_RQ_QUEUE_OK)
1167 goto done; 1192 goto done;
1168 else { 1193 else {
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 1bd5f523f8fd..3bd7ca9853a8 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -3775,9 +3775,10 @@ static bool mtip_check_unal_depth(struct blk_mq_hw_ctx *hctx,
3775 return false; 3775 return false;
3776} 3776}
3777 3777
3778static int mtip_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *rq, 3778static int mtip_queue_rq(struct blk_mq_hw_ctx *hctx,
3779 bool last) 3779 const struct blk_mq_queue_data *bd)
3780{ 3780{
3781 struct request *rq = bd->rq;
3781 int ret; 3782 int ret;
3782 3783
3783 if (unlikely(mtip_check_unal_depth(hctx, rq))) 3784 if (unlikely(mtip_check_unal_depth(hctx, rq)))
diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c
index 2671a3f02f0c..8433bc8ead3d 100644
--- a/drivers/block/null_blk.c
+++ b/drivers/block/null_blk.c
@@ -313,15 +313,15 @@ static void null_request_fn(struct request_queue *q)
313 } 313 }
314} 314}
315 315
316static int null_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *rq, 316static int null_queue_rq(struct blk_mq_hw_ctx *hctx,
317 bool last) 317 const struct blk_mq_queue_data *bd)
318{ 318{
319 struct nullb_cmd *cmd = blk_mq_rq_to_pdu(rq); 319 struct nullb_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
320 320
321 cmd->rq = rq; 321 cmd->rq = bd->rq;
322 cmd->nq = hctx->driver_data; 322 cmd->nq = hctx->driver_data;
323 323
324 blk_mq_start_request(rq); 324 blk_mq_start_request(bd->rq);
325 325
326 null_handle_cmd(cmd); 326 null_handle_cmd(cmd);
327 return BLK_MQ_RQ_QUEUE_OK; 327 return BLK_MQ_RQ_QUEUE_OK;
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index c6a27d54ad62..cecd3f983e49 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -158,10 +158,11 @@ static void virtblk_done(struct virtqueue *vq)
158 spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags); 158 spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
159} 159}
160 160
161static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req, 161static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
162 bool last) 162 const struct blk_mq_queue_data *bd)
163{ 163{
164 struct virtio_blk *vblk = hctx->queue->queuedata; 164 struct virtio_blk *vblk = hctx->queue->queuedata;
165 struct request *req = bd->rq;
165 struct virtblk_req *vbr = blk_mq_rq_to_pdu(req); 166 struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
166 unsigned long flags; 167 unsigned long flags;
167 unsigned int num; 168 unsigned int num;
@@ -222,7 +223,7 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req,
222 return BLK_MQ_RQ_QUEUE_ERROR; 223 return BLK_MQ_RQ_QUEUE_ERROR;
223 } 224 }
224 225
225 if (last && virtqueue_kick_prepare(vblk->vqs[qid].vq)) 226 if (bd->last && virtqueue_kick_prepare(vblk->vqs[qid].vq))
226 notify = true; 227 notify = true;
227 spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags); 228 spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
228 229
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 9eff8a375132..161dcc93ac75 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1858,9 +1858,10 @@ static void scsi_mq_done(struct scsi_cmnd *cmd)
1858 blk_mq_complete_request(cmd->request); 1858 blk_mq_complete_request(cmd->request);
1859} 1859}
1860 1860
1861static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req, 1861static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
1862 bool last) 1862 const struct blk_mq_queue_data *bd)
1863{ 1863{
1864 struct request *req = bd->rq;
1864 struct request_queue *q = req->q; 1865 struct request_queue *q = req->q;
1865 struct scsi_device *sdev = q->queuedata; 1866 struct scsi_device *sdev = q->queuedata;
1866 struct Scsi_Host *shost = sdev->host; 1867 struct Scsi_Host *shost = sdev->host;
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index c9be1589415a..be01d7a687d4 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -79,7 +79,13 @@ struct blk_mq_tag_set {
79 struct list_head tag_list; 79 struct list_head tag_list;
80}; 80};
81 81
82typedef int (queue_rq_fn)(struct blk_mq_hw_ctx *, struct request *, bool); 82struct blk_mq_queue_data {
83 struct request *rq;
84 struct list_head *list;
85 bool last;
86};
87
88typedef int (queue_rq_fn)(struct blk_mq_hw_ctx *, const struct blk_mq_queue_data *);
83typedef struct blk_mq_hw_ctx *(map_queue_fn)(struct request_queue *, const int); 89typedef struct blk_mq_hw_ctx *(map_queue_fn)(struct request_queue *, const int);
84typedef enum blk_eh_timer_return (timeout_fn)(struct request *, bool); 90typedef enum blk_eh_timer_return (timeout_fn)(struct request *, bool);
85typedef int (init_hctx_fn)(struct blk_mq_hw_ctx *, void *, unsigned int); 91typedef int (init_hctx_fn)(struct blk_mq_hw_ctx *, void *, unsigned int);