aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/blk-mq.c105
-rw-r--r--drivers/block/virtio_blk.c23
-rw-r--r--include/linux/blk-mq.h14
3 files changed, 55 insertions, 87 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c
index e644feec068c..48d2d8495f5e 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1031,74 +1031,20 @@ static void blk_mq_hctx_notify(void *data, unsigned long action,
1031 blk_mq_put_ctx(ctx); 1031 blk_mq_put_ctx(ctx);
1032} 1032}
1033 1033
1034static int blk_mq_init_hw_commands(struct blk_mq_hw_ctx *hctx, 1034static void blk_mq_free_rq_map(struct blk_mq_hw_ctx *hctx, void *driver_data)
1035 int (*init)(void *, struct blk_mq_hw_ctx *,
1036 struct request *, unsigned int),
1037 void *data)
1038{ 1035{
1039 unsigned int i; 1036 struct page *page;
1040 int ret = 0;
1041
1042 for (i = 0; i < hctx->queue_depth; i++) {
1043 struct request *rq = hctx->rqs[i];
1044
1045 ret = init(data, hctx, rq, i);
1046 if (ret)
1047 break;
1048 }
1049
1050 return ret;
1051}
1052
1053int blk_mq_init_commands(struct request_queue *q,
1054 int (*init)(void *, struct blk_mq_hw_ctx *,
1055 struct request *, unsigned int),
1056 void *data)
1057{
1058 struct blk_mq_hw_ctx *hctx;
1059 unsigned int i;
1060 int ret = 0;
1061
1062 queue_for_each_hw_ctx(q, hctx, i) {
1063 ret = blk_mq_init_hw_commands(hctx, init, data);
1064 if (ret)
1065 break;
1066 }
1067
1068 return ret;
1069}
1070EXPORT_SYMBOL(blk_mq_init_commands);
1071
1072static void blk_mq_free_hw_commands(struct blk_mq_hw_ctx *hctx,
1073 void (*free)(void *, struct blk_mq_hw_ctx *,
1074 struct request *, unsigned int),
1075 void *data)
1076{
1077 unsigned int i;
1078 1037
1079 for (i = 0; i < hctx->queue_depth; i++) { 1038 if (hctx->rqs && hctx->queue->mq_ops->exit_request) {
1080 struct request *rq = hctx->rqs[i]; 1039 int i;
1081 1040
1082 free(data, hctx, rq, i); 1041 for (i = 0; i < hctx->queue_depth; i++) {
1042 if (!hctx->rqs[i])
1043 continue;
1044 hctx->queue->mq_ops->exit_request(driver_data, hctx,
1045 hctx->rqs[i], i);
1046 }
1083 } 1047 }
1084}
1085
1086void blk_mq_free_commands(struct request_queue *q,
1087 void (*free)(void *, struct blk_mq_hw_ctx *,
1088 struct request *, unsigned int),
1089 void *data)
1090{
1091 struct blk_mq_hw_ctx *hctx;
1092 unsigned int i;
1093
1094 queue_for_each_hw_ctx(q, hctx, i)
1095 blk_mq_free_hw_commands(hctx, free, data);
1096}
1097EXPORT_SYMBOL(blk_mq_free_commands);
1098
1099static void blk_mq_free_rq_map(struct blk_mq_hw_ctx *hctx)
1100{
1101 struct page *page;
1102 1048
1103 while (!list_empty(&hctx->page_list)) { 1049 while (!list_empty(&hctx->page_list)) {
1104 page = list_first_entry(&hctx->page_list, struct page, lru); 1050 page = list_first_entry(&hctx->page_list, struct page, lru);
@@ -1123,10 +1069,12 @@ static size_t order_to_size(unsigned int order)
1123} 1069}
1124 1070
1125static int blk_mq_init_rq_map(struct blk_mq_hw_ctx *hctx, 1071static int blk_mq_init_rq_map(struct blk_mq_hw_ctx *hctx,
1126 unsigned int reserved_tags, int node) 1072 struct blk_mq_reg *reg, void *driver_data, int node)
1127{ 1073{
1074 unsigned int reserved_tags = reg->reserved_tags;
1128 unsigned int i, j, entries_per_page, max_order = 4; 1075 unsigned int i, j, entries_per_page, max_order = 4;
1129 size_t rq_size, left; 1076 size_t rq_size, left;
1077 int error;
1130 1078
1131 INIT_LIST_HEAD(&hctx->page_list); 1079 INIT_LIST_HEAD(&hctx->page_list);
1132 1080
@@ -1175,14 +1123,23 @@ static int blk_mq_init_rq_map(struct blk_mq_hw_ctx *hctx,
1175 for (j = 0; j < to_do; j++) { 1123 for (j = 0; j < to_do; j++) {
1176 hctx->rqs[i] = p; 1124 hctx->rqs[i] = p;
1177 blk_rq_init(hctx->queue, hctx->rqs[i]); 1125 blk_rq_init(hctx->queue, hctx->rqs[i]);
1126 if (reg->ops->init_request) {
1127 error = reg->ops->init_request(driver_data,
1128 hctx, hctx->rqs[i], i);
1129 if (error)
1130 goto err_rq_map;
1131 }
1132
1178 p += rq_size; 1133 p += rq_size;
1179 i++; 1134 i++;
1180 } 1135 }
1181 } 1136 }
1182 1137
1183 if (i < (reserved_tags + BLK_MQ_TAG_MIN)) 1138 if (i < (reserved_tags + BLK_MQ_TAG_MIN)) {
1139 error = -ENOMEM;
1184 goto err_rq_map; 1140 goto err_rq_map;
1185 else if (i != hctx->queue_depth) { 1141 }
1142 if (i != hctx->queue_depth) {
1186 hctx->queue_depth = i; 1143 hctx->queue_depth = i;
1187 pr_warn("%s: queue depth set to %u because of low memory\n", 1144 pr_warn("%s: queue depth set to %u because of low memory\n",
1188 __func__, i); 1145 __func__, i);
@@ -1190,12 +1147,14 @@ static int blk_mq_init_rq_map(struct blk_mq_hw_ctx *hctx,
1190 1147
1191 hctx->tags = blk_mq_init_tags(hctx->queue_depth, reserved_tags, node); 1148 hctx->tags = blk_mq_init_tags(hctx->queue_depth, reserved_tags, node);
1192 if (!hctx->tags) { 1149 if (!hctx->tags) {
1193err_rq_map: 1150 error = -ENOMEM;
1194 blk_mq_free_rq_map(hctx); 1151 goto err_rq_map;
1195 return -ENOMEM;
1196 } 1152 }
1197 1153
1198 return 0; 1154 return 0;
1155err_rq_map:
1156 blk_mq_free_rq_map(hctx, driver_data);
1157 return error;
1199} 1158}
1200 1159
1201static int blk_mq_init_hw_queues(struct request_queue *q, 1160static int blk_mq_init_hw_queues(struct request_queue *q,
@@ -1228,7 +1187,7 @@ static int blk_mq_init_hw_queues(struct request_queue *q,
1228 blk_mq_hctx_notify, hctx); 1187 blk_mq_hctx_notify, hctx);
1229 blk_mq_register_cpu_notifier(&hctx->cpu_notifier); 1188 blk_mq_register_cpu_notifier(&hctx->cpu_notifier);
1230 1189
1231 if (blk_mq_init_rq_map(hctx, reg->reserved_tags, node)) 1190 if (blk_mq_init_rq_map(hctx, reg, driver_data, node))
1232 break; 1191 break;
1233 1192
1234 /* 1193 /*
@@ -1268,7 +1227,7 @@ static int blk_mq_init_hw_queues(struct request_queue *q,
1268 reg->ops->exit_hctx(hctx, j); 1227 reg->ops->exit_hctx(hctx, j);
1269 1228
1270 blk_mq_unregister_cpu_notifier(&hctx->cpu_notifier); 1229 blk_mq_unregister_cpu_notifier(&hctx->cpu_notifier);
1271 blk_mq_free_rq_map(hctx); 1230 blk_mq_free_rq_map(hctx, driver_data);
1272 kfree(hctx->ctxs); 1231 kfree(hctx->ctxs);
1273 } 1232 }
1274 1233
@@ -1455,7 +1414,7 @@ void blk_mq_free_queue(struct request_queue *q)
1455 queue_for_each_hw_ctx(q, hctx, i) { 1414 queue_for_each_hw_ctx(q, hctx, i) {
1456 kfree(hctx->ctx_map); 1415 kfree(hctx->ctx_map);
1457 kfree(hctx->ctxs); 1416 kfree(hctx->ctxs);
1458 blk_mq_free_rq_map(hctx); 1417 blk_mq_free_rq_map(hctx, q->queuedata);
1459 blk_mq_unregister_cpu_notifier(&hctx->cpu_notifier); 1418 blk_mq_unregister_cpu_notifier(&hctx->cpu_notifier);
1460 if (q->mq_ops->exit_hctx) 1419 if (q->mq_ops->exit_hctx)
1461 q->mq_ops->exit_hctx(hctx, i); 1420 q->mq_ops->exit_hctx(hctx, i);
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index c7d02bc9d945..d06206abd340 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -480,11 +480,22 @@ static const struct device_attribute dev_attr_cache_type_rw =
480 __ATTR(cache_type, S_IRUGO|S_IWUSR, 480 __ATTR(cache_type, S_IRUGO|S_IWUSR,
481 virtblk_cache_type_show, virtblk_cache_type_store); 481 virtblk_cache_type_show, virtblk_cache_type_store);
482 482
483static int virtblk_init_request(void *data, struct blk_mq_hw_ctx *hctx,
484 struct request *rq, unsigned int nr)
485{
486 struct virtio_blk *vblk = data;
487 struct virtblk_req *vbr = blk_mq_rq_to_pdu(rq);
488
489 sg_init_table(vbr->sg, vblk->sg_elems);
490 return 0;
491}
492
483static struct blk_mq_ops virtio_mq_ops = { 493static struct blk_mq_ops virtio_mq_ops = {
484 .queue_rq = virtio_queue_rq, 494 .queue_rq = virtio_queue_rq,
485 .map_queue = blk_mq_map_queue, 495 .map_queue = blk_mq_map_queue,
486 .alloc_hctx = blk_mq_alloc_single_hw_queue, 496 .alloc_hctx = blk_mq_alloc_single_hw_queue,
487 .free_hctx = blk_mq_free_single_hw_queue, 497 .free_hctx = blk_mq_free_single_hw_queue,
498 .init_request = virtblk_init_request,
488 .complete = virtblk_request_done, 499 .complete = virtblk_request_done,
489}; 500};
490 501
@@ -497,16 +508,6 @@ static struct blk_mq_reg virtio_mq_reg = {
497}; 508};
498module_param_named(queue_depth, virtio_mq_reg.queue_depth, uint, 0444); 509module_param_named(queue_depth, virtio_mq_reg.queue_depth, uint, 0444);
499 510
500static int virtblk_init_vbr(void *data, struct blk_mq_hw_ctx *hctx,
501 struct request *rq, unsigned int nr)
502{
503 struct virtio_blk *vblk = data;
504 struct virtblk_req *vbr = blk_mq_rq_to_pdu(rq);
505
506 sg_init_table(vbr->sg, vblk->sg_elems);
507 return 0;
508}
509
510static int virtblk_probe(struct virtio_device *vdev) 511static int virtblk_probe(struct virtio_device *vdev)
511{ 512{
512 struct virtio_blk *vblk; 513 struct virtio_blk *vblk;
@@ -577,8 +578,6 @@ static int virtblk_probe(struct virtio_device *vdev)
577 goto out_put_disk; 578 goto out_put_disk;
578 } 579 }
579 580
580 blk_mq_init_commands(q, virtblk_init_vbr, vblk);
581
582 q->queuedata = vblk; 581 q->queuedata = vblk;
583 582
584 virtblk_name_format("vd", index, vblk->disk->disk_name, DISK_NAME_LEN); 583 virtblk_name_format("vd", index, vblk->disk->disk_name, DISK_NAME_LEN);
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index b6ee48740458..29c1a6e83814 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -67,6 +67,10 @@ typedef struct blk_mq_hw_ctx *(alloc_hctx_fn)(struct blk_mq_reg *,unsigned int);
67typedef void (free_hctx_fn)(struct blk_mq_hw_ctx *, unsigned int); 67typedef void (free_hctx_fn)(struct blk_mq_hw_ctx *, unsigned int);
68typedef int (init_hctx_fn)(struct blk_mq_hw_ctx *, void *, unsigned int); 68typedef int (init_hctx_fn)(struct blk_mq_hw_ctx *, void *, unsigned int);
69typedef void (exit_hctx_fn)(struct blk_mq_hw_ctx *, unsigned int); 69typedef void (exit_hctx_fn)(struct blk_mq_hw_ctx *, unsigned int);
70typedef int (init_request_fn)(void *, struct blk_mq_hw_ctx *,
71 struct request *, unsigned int);
72typedef void (exit_request_fn)(void *, struct blk_mq_hw_ctx *,
73 struct request *, unsigned int);
70 74
71struct blk_mq_ops { 75struct blk_mq_ops {
72 /* 76 /*
@@ -99,6 +103,14 @@ struct blk_mq_ops {
99 */ 103 */
100 init_hctx_fn *init_hctx; 104 init_hctx_fn *init_hctx;
101 exit_hctx_fn *exit_hctx; 105 exit_hctx_fn *exit_hctx;
106
107 /*
108 * Called for every command allocated by the block layer to allow
109 * the driver to set up driver specific data.
110 * Ditto for exit/teardown.
111 */
112 init_request_fn *init_request;
113 exit_request_fn *exit_request;
102}; 114};
103 115
104enum { 116enum {
@@ -118,8 +130,6 @@ enum {
118struct request_queue *blk_mq_init_queue(struct blk_mq_reg *, void *); 130struct request_queue *blk_mq_init_queue(struct blk_mq_reg *, void *);
119int blk_mq_register_disk(struct gendisk *); 131int blk_mq_register_disk(struct gendisk *);
120void blk_mq_unregister_disk(struct gendisk *); 132void blk_mq_unregister_disk(struct gendisk *);
121int blk_mq_init_commands(struct request_queue *, int (*init)(void *data, struct blk_mq_hw_ctx *, struct request *, unsigned int), void *data);
122void blk_mq_free_commands(struct request_queue *, void (*free)(void *data, struct blk_mq_hw_ctx *, struct request *, unsigned int), void *data);
123 133
124void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule); 134void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule);
125 135