diff options
| -rw-r--r-- | drivers/nvme/host/rdma.c | 95 |
1 files changed, 37 insertions, 58 deletions
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 3a952d458e7c..02ef0771f6b9 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <rdma/mr_pool.h> | ||
| 18 | #include <linux/err.h> | 19 | #include <linux/err.h> |
| 19 | #include <linux/string.h> | 20 | #include <linux/string.h> |
| 20 | #include <linux/atomic.h> | 21 | #include <linux/atomic.h> |
| @@ -260,32 +261,6 @@ static int nvme_rdma_create_qp(struct nvme_rdma_queue *queue, const int factor) | |||
| 260 | return ret; | 261 | return ret; |
| 261 | } | 262 | } |
| 262 | 263 | ||
| 263 | static int nvme_rdma_reinit_request(void *data, struct request *rq) | ||
| 264 | { | ||
| 265 | struct nvme_rdma_ctrl *ctrl = data; | ||
| 266 | struct nvme_rdma_device *dev = ctrl->device; | ||
| 267 | struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq); | ||
| 268 | int ret = 0; | ||
| 269 | |||
| 270 | if (WARN_ON_ONCE(!req->mr)) | ||
| 271 | return 0; | ||
| 272 | |||
| 273 | ib_dereg_mr(req->mr); | ||
| 274 | |||
| 275 | req->mr = ib_alloc_mr(dev->pd, IB_MR_TYPE_MEM_REG, | ||
| 276 | ctrl->max_fr_pages); | ||
| 277 | if (IS_ERR(req->mr)) { | ||
| 278 | ret = PTR_ERR(req->mr); | ||
| 279 | req->mr = NULL; | ||
| 280 | goto out; | ||
| 281 | } | ||
| 282 | |||
| 283 | req->mr->need_inval = false; | ||
| 284 | |||
| 285 | out: | ||
| 286 | return ret; | ||
| 287 | } | ||
| 288 | |||
| 289 | static void nvme_rdma_exit_request(struct blk_mq_tag_set *set, | 264 | static void nvme_rdma_exit_request(struct blk_mq_tag_set *set, |
| 290 | struct request *rq, unsigned int hctx_idx) | 265 | struct request *rq, unsigned int hctx_idx) |
| 291 | { | 266 | { |
| @@ -295,9 +270,6 @@ static void nvme_rdma_exit_request(struct blk_mq_tag_set *set, | |||
| 295 | struct nvme_rdma_queue *queue = &ctrl->queues[queue_idx]; | 270 | struct nvme_rdma_queue *queue = &ctrl->queues[queue_idx]; |
| 296 | struct nvme_rdma_device *dev = queue->device; | 271 | struct nvme_rdma_device *dev = queue->device; |
| 297 | 272 | ||
| 298 | if (req->mr) | ||
| 299 | ib_dereg_mr(req->mr); | ||
| 300 | |||
| 301 | nvme_rdma_free_qe(dev->dev, &req->sqe, sizeof(struct nvme_command), | 273 | nvme_rdma_free_qe(dev->dev, &req->sqe, sizeof(struct nvme_command), |
| 302 | DMA_TO_DEVICE); | 274 | DMA_TO_DEVICE); |
| 303 | } | 275 | } |
| @@ -319,21 +291,9 @@ static int nvme_rdma_init_request(struct blk_mq_tag_set *set, | |||
| 319 | if (ret) | 291 | if (ret) |
| 320 | return ret; | 292 | return ret; |
| 321 | 293 | ||
| 322 | req->mr = ib_alloc_mr(dev->pd, IB_MR_TYPE_MEM_REG, | ||
| 323 | ctrl->max_fr_pages); | ||
| 324 | if (IS_ERR(req->mr)) { | ||
| 325 | ret = PTR_ERR(req->mr); | ||
| 326 | goto out_free_qe; | ||
| 327 | } | ||
| 328 | |||
| 329 | req->queue = queue; | 294 | req->queue = queue; |
| 330 | 295 | ||
| 331 | return 0; | 296 | return 0; |
| 332 | |||
| 333 | out_free_qe: | ||
| 334 | nvme_rdma_free_qe(dev->dev, &req->sqe, sizeof(struct nvme_command), | ||
| 335 | DMA_TO_DEVICE); | ||
| 336 | return -ENOMEM; | ||
| 337 | } | 297 | } |
| 338 | 298 | ||
| 339 | static int nvme_rdma_init_hctx(struct blk_mq_hw_ctx *hctx, void *data, | 299 | static int nvme_rdma_init_hctx(struct blk_mq_hw_ctx *hctx, void *data, |
| @@ -433,6 +393,8 @@ static void nvme_rdma_destroy_queue_ib(struct nvme_rdma_queue *queue) | |||
| 433 | struct nvme_rdma_device *dev = queue->device; | 393 | struct nvme_rdma_device *dev = queue->device; |
| 434 | struct ib_device *ibdev = dev->dev; | 394 | struct ib_device *ibdev = dev->dev; |
| 435 | 395 | ||
| 396 | ib_mr_pool_destroy(queue->qp, &queue->qp->rdma_mrs); | ||
| 397 | |||
| 436 | rdma_destroy_qp(queue->cm_id); | 398 | rdma_destroy_qp(queue->cm_id); |
| 437 | ib_free_cq(queue->ib_cq); | 399 | ib_free_cq(queue->ib_cq); |
| 438 | 400 | ||
| @@ -442,6 +404,12 @@ static void nvme_rdma_destroy_queue_ib(struct nvme_rdma_queue *queue) | |||
| 442 | nvme_rdma_dev_put(dev); | 404 | nvme_rdma_dev_put(dev); |
| 443 | } | 405 | } |
| 444 | 406 | ||
| 407 | static int nvme_rdma_get_max_fr_pages(struct ib_device *ibdev) | ||
| 408 | { | ||
| 409 | return min_t(u32, NVME_RDMA_MAX_SEGMENTS, | ||
| 410 | ibdev->attrs.max_fast_reg_page_list_len); | ||
| 411 | } | ||
| 412 | |||
| 445 | static int nvme_rdma_create_queue_ib(struct nvme_rdma_queue *queue) | 413 | static int nvme_rdma_create_queue_ib(struct nvme_rdma_queue *queue) |
| 446 | { | 414 | { |
| 447 | struct ib_device *ibdev; | 415 | struct ib_device *ibdev; |
| @@ -484,8 +452,22 @@ static int nvme_rdma_create_queue_ib(struct nvme_rdma_queue *queue) | |||
| 484 | goto out_destroy_qp; | 452 | goto out_destroy_qp; |
| 485 | } | 453 | } |
| 486 | 454 | ||
| 455 | ret = ib_mr_pool_init(queue->qp, &queue->qp->rdma_mrs, | ||
| 456 | queue->queue_size, | ||
| 457 | IB_MR_TYPE_MEM_REG, | ||
| 458 | nvme_rdma_get_max_fr_pages(ibdev)); | ||
| 459 | if (ret) { | ||
| 460 | dev_err(queue->ctrl->ctrl.device, | ||
| 461 | "failed to initialize MR pool sized %d for QID %d\n", | ||
| 462 | queue->queue_size, idx); | ||
| 463 | goto out_destroy_ring; | ||
| 464 | } | ||
| 465 | |||
| 487 | return 0; | 466 | return 0; |
| 488 | 467 | ||
| 468 | out_destroy_ring: | ||
| 469 | nvme_rdma_free_ring(ibdev, queue->rsp_ring, queue->queue_size, | ||
| 470 | sizeof(struct nvme_completion), DMA_FROM_DEVICE); | ||
| 489 | out_destroy_qp: | 471 | out_destroy_qp: |
| 490 | rdma_destroy_qp(queue->cm_id); | 472 | rdma_destroy_qp(queue->cm_id); |
| 491 | out_destroy_ib_cq: | 473 | out_destroy_ib_cq: |
| @@ -757,8 +739,7 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl, | |||
| 757 | 739 | ||
| 758 | ctrl->device = ctrl->queues[0].device; | 740 | ctrl->device = ctrl->queues[0].device; |
| 759 | 741 | ||
| 760 | ctrl->max_fr_pages = min_t(u32, NVME_RDMA_MAX_SEGMENTS, | 742 | ctrl->max_fr_pages = nvme_rdma_get_max_fr_pages(ctrl->device->dev); |
| 761 | ctrl->device->dev->attrs.max_fast_reg_page_list_len); | ||
| 762 | 743 | ||
| 763 | if (new) { | 744 | if (new) { |
| 764 | ctrl->ctrl.admin_tagset = nvme_rdma_alloc_tagset(&ctrl->ctrl, true); | 745 | ctrl->ctrl.admin_tagset = nvme_rdma_alloc_tagset(&ctrl->ctrl, true); |
| @@ -772,10 +753,6 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl, | |||
| 772 | error = PTR_ERR(ctrl->ctrl.admin_q); | 753 | error = PTR_ERR(ctrl->ctrl.admin_q); |
| 773 | goto out_free_tagset; | 754 | goto out_free_tagset; |
| 774 | } | 755 | } |
| 775 | } else { | ||
| 776 | error = nvme_reinit_tagset(&ctrl->ctrl, ctrl->ctrl.admin_tagset); | ||
| 777 | if (error) | ||
| 778 | goto out_free_queue; | ||
| 779 | } | 756 | } |
| 780 | 757 | ||
| 781 | error = nvme_rdma_start_queue(ctrl, 0); | 758 | error = nvme_rdma_start_queue(ctrl, 0); |
| @@ -855,10 +832,6 @@ static int nvme_rdma_configure_io_queues(struct nvme_rdma_ctrl *ctrl, bool new) | |||
| 855 | goto out_free_tag_set; | 832 | goto out_free_tag_set; |
| 856 | } | 833 | } |
| 857 | } else { | 834 | } else { |
| 858 | ret = nvme_reinit_tagset(&ctrl->ctrl, ctrl->ctrl.tagset); | ||
| 859 | if (ret) | ||
| 860 | goto out_free_io_queues; | ||
| 861 | |||
| 862 | blk_mq_update_nr_hw_queues(&ctrl->tag_set, | 835 | blk_mq_update_nr_hw_queues(&ctrl->tag_set, |
| 863 | ctrl->ctrl.queue_count - 1); | 836 | ctrl->ctrl.queue_count - 1); |
| 864 | } | 837 | } |
| @@ -1061,6 +1034,11 @@ static void nvme_rdma_unmap_data(struct nvme_rdma_queue *queue, | |||
| 1061 | if (!blk_rq_bytes(rq)) | 1034 | if (!blk_rq_bytes(rq)) |
| 1062 | return; | 1035 | return; |
| 1063 | 1036 | ||
| 1037 | if (req->mr) { | ||
| 1038 | ib_mr_pool_put(queue->qp, &queue->qp->rdma_mrs, req->mr); | ||
| 1039 | req->mr = NULL; | ||
| 1040 | } | ||
| 1041 | |||
| 1064 | ib_dma_unmap_sg(ibdev, req->sg_table.sgl, | 1042 | ib_dma_unmap_sg(ibdev, req->sg_table.sgl, |
| 1065 | req->nents, rq_data_dir(rq) == | 1043 | req->nents, rq_data_dir(rq) == |
| 1066 | WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | 1044 | WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE); |
| @@ -1117,12 +1095,18 @@ static int nvme_rdma_map_sg_fr(struct nvme_rdma_queue *queue, | |||
| 1117 | struct nvme_keyed_sgl_desc *sg = &c->common.dptr.ksgl; | 1095 | struct nvme_keyed_sgl_desc *sg = &c->common.dptr.ksgl; |
| 1118 | int nr; | 1096 | int nr; |
| 1119 | 1097 | ||
| 1098 | req->mr = ib_mr_pool_get(queue->qp, &queue->qp->rdma_mrs); | ||
| 1099 | if (WARN_ON_ONCE(!req->mr)) | ||
| 1100 | return -EAGAIN; | ||
| 1101 | |||
| 1120 | /* | 1102 | /* |
| 1121 | * Align the MR to a 4K page size to match the ctrl page size and | 1103 | * Align the MR to a 4K page size to match the ctrl page size and |
| 1122 | * the block virtual boundary. | 1104 | * the block virtual boundary. |
| 1123 | */ | 1105 | */ |
| 1124 | nr = ib_map_mr_sg(req->mr, req->sg_table.sgl, count, NULL, SZ_4K); | 1106 | nr = ib_map_mr_sg(req->mr, req->sg_table.sgl, count, NULL, SZ_4K); |
| 1125 | if (unlikely(nr < count)) { | 1107 | if (unlikely(nr < count)) { |
| 1108 | ib_mr_pool_put(queue->qp, &queue->qp->rdma_mrs, req->mr); | ||
| 1109 | req->mr = NULL; | ||
| 1126 | if (nr < 0) | 1110 | if (nr < 0) |
| 1127 | return nr; | 1111 | return nr; |
| 1128 | return -EINVAL; | 1112 | return -EINVAL; |
| @@ -1141,8 +1125,6 @@ static int nvme_rdma_map_sg_fr(struct nvme_rdma_queue *queue, | |||
| 1141 | IB_ACCESS_REMOTE_READ | | 1125 | IB_ACCESS_REMOTE_READ | |
| 1142 | IB_ACCESS_REMOTE_WRITE; | 1126 | IB_ACCESS_REMOTE_WRITE; |
| 1143 | 1127 | ||
| 1144 | req->mr->need_inval = true; | ||
| 1145 | |||
| 1146 | sg->addr = cpu_to_le64(req->mr->iova); | 1128 | sg->addr = cpu_to_le64(req->mr->iova); |
| 1147 | put_unaligned_le24(req->mr->length, sg->length); | 1129 | put_unaligned_le24(req->mr->length, sg->length); |
| 1148 | put_unaligned_le32(req->mr->rkey, sg->key); | 1130 | put_unaligned_le32(req->mr->rkey, sg->key); |
| @@ -1162,7 +1144,6 @@ static int nvme_rdma_map_data(struct nvme_rdma_queue *queue, | |||
| 1162 | 1144 | ||
| 1163 | req->num_sge = 1; | 1145 | req->num_sge = 1; |
| 1164 | req->inline_data = false; | 1146 | req->inline_data = false; |
| 1165 | req->mr->need_inval = false; | ||
| 1166 | refcount_set(&req->ref, 2); /* send and recv completions */ | 1147 | refcount_set(&req->ref, 2); /* send and recv completions */ |
| 1167 | 1148 | ||
| 1168 | c->common.flags |= NVME_CMD_SGL_METABUF; | 1149 | c->common.flags |= NVME_CMD_SGL_METABUF; |
| @@ -1341,8 +1322,7 @@ static int nvme_rdma_process_nvme_rsp(struct nvme_rdma_queue *queue, | |||
| 1341 | req->mr->rkey); | 1322 | req->mr->rkey); |
| 1342 | nvme_rdma_error_recovery(queue->ctrl); | 1323 | nvme_rdma_error_recovery(queue->ctrl); |
| 1343 | } | 1324 | } |
| 1344 | req->mr->need_inval = false; | 1325 | } else if (req->mr) { |
| 1345 | } else if (req->mr->need_inval) { | ||
| 1346 | ret = nvme_rdma_inv_rkey(queue, req); | 1326 | ret = nvme_rdma_inv_rkey(queue, req); |
| 1347 | if (unlikely(ret < 0)) { | 1327 | if (unlikely(ret < 0)) { |
| 1348 | dev_err(queue->ctrl->ctrl.device, | 1328 | dev_err(queue->ctrl->ctrl.device, |
| @@ -1650,7 +1630,7 @@ static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx, | |||
| 1650 | sizeof(struct nvme_command), DMA_TO_DEVICE); | 1630 | sizeof(struct nvme_command), DMA_TO_DEVICE); |
| 1651 | 1631 | ||
| 1652 | err = nvme_rdma_post_send(queue, sqe, req->sge, req->num_sge, | 1632 | err = nvme_rdma_post_send(queue, sqe, req->sge, req->num_sge, |
| 1653 | req->mr->need_inval ? &req->reg_wr.wr : NULL); | 1633 | req->mr ? &req->reg_wr.wr : NULL); |
| 1654 | if (unlikely(err)) { | 1634 | if (unlikely(err)) { |
| 1655 | nvme_rdma_unmap_data(queue, rq); | 1635 | nvme_rdma_unmap_data(queue, rq); |
| 1656 | goto err; | 1636 | goto err; |
| @@ -1798,7 +1778,6 @@ static const struct nvme_ctrl_ops nvme_rdma_ctrl_ops = { | |||
| 1798 | .submit_async_event = nvme_rdma_submit_async_event, | 1778 | .submit_async_event = nvme_rdma_submit_async_event, |
| 1799 | .delete_ctrl = nvme_rdma_delete_ctrl, | 1779 | .delete_ctrl = nvme_rdma_delete_ctrl, |
| 1800 | .get_address = nvmf_get_address, | 1780 | .get_address = nvmf_get_address, |
| 1801 | .reinit_request = nvme_rdma_reinit_request, | ||
| 1802 | }; | 1781 | }; |
| 1803 | 1782 | ||
| 1804 | static inline bool | 1783 | static inline bool |
