diff options
-rw-r--r-- | block/blk-mq.c | 29 | ||||
-rw-r--r-- | drivers/block/mtip32xx/mtip32xx.c | 5 | ||||
-rw-r--r-- | drivers/block/null_blk.c | 10 | ||||
-rw-r--r-- | drivers/block/virtio_blk.c | 7 | ||||
-rw-r--r-- | drivers/scsi/scsi_lib.c | 5 | ||||
-rw-r--r-- | include/linux/blk-mq.h | 8 |
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 | ||
3778 | static int mtip_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *rq, | 3778 | static 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 | ||
316 | static int null_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *rq, | 316 | static 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 | ||
161 | static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req, | 161 | static 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 | ||
1861 | static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req, | 1861 | static 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 | ||
82 | typedef int (queue_rq_fn)(struct blk_mq_hw_ctx *, struct request *, bool); | 82 | struct blk_mq_queue_data { |
83 | struct request *rq; | ||
84 | struct list_head *list; | ||
85 | bool last; | ||
86 | }; | ||
87 | |||
88 | typedef int (queue_rq_fn)(struct blk_mq_hw_ctx *, const struct blk_mq_queue_data *); | ||
83 | typedef struct blk_mq_hw_ctx *(map_queue_fn)(struct request_queue *, const int); | 89 | typedef struct blk_mq_hw_ctx *(map_queue_fn)(struct request_queue *, const int); |
84 | typedef enum blk_eh_timer_return (timeout_fn)(struct request *, bool); | 90 | typedef enum blk_eh_timer_return (timeout_fn)(struct request *, bool); |
85 | typedef int (init_hctx_fn)(struct blk_mq_hw_ctx *, void *, unsigned int); | 91 | typedef int (init_hctx_fn)(struct blk_mq_hw_ctx *, void *, unsigned int); |