aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2016-05-03 12:01:12 -0400
committerDoug Ledford <dledford@redhat.com>2016-05-13 13:37:20 -0400
commit0e353e34e1e740fe575eb479ca0f2a723a4ef51c (patch)
tree0452d113b689f96068ef02e89296c7169aad52bb
parentb99f8e4d7bcd3bfbb3cd965918523299370d0cb2 (diff)
IB/core: add RW API support for signature MRs
Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/core/rw.c228
-rw-r--r--drivers/infiniband/core/verbs.c1
-rw-r--r--include/rdma/ib_verbs.h1
-rw-r--r--include/rdma/rw.h19
4 files changed, 244 insertions, 5 deletions
diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c
index bd700ff6d438..6fc50bf79afe 100644
--- a/drivers/infiniband/core/rw.c
+++ b/drivers/infiniband/core/rw.c
@@ -19,6 +19,7 @@ enum {
19 RDMA_RW_SINGLE_WR, 19 RDMA_RW_SINGLE_WR,
20 RDMA_RW_MULTI_WR, 20 RDMA_RW_MULTI_WR,
21 RDMA_RW_MR, 21 RDMA_RW_MR,
22 RDMA_RW_SIG_MR,
22}; 23};
23 24
24static bool rdma_rw_force_mr; 25static bool rdma_rw_force_mr;
@@ -325,6 +326,146 @@ out_unmap_sg:
325} 326}
326EXPORT_SYMBOL(rdma_rw_ctx_init); 327EXPORT_SYMBOL(rdma_rw_ctx_init);
327 328
329/**
330 * rdma_rw_ctx_signature init - initialize a RW context with signature offload
331 * @ctx: context to initialize
332 * @qp: queue pair to operate on
333 * @port_num: port num to which the connection is bound
334 * @sg: scatterlist to READ/WRITE from/to
335 * @sg_cnt: number of entries in @sg
336 * @prot_sg: scatterlist to READ/WRITE protection information from/to
337 * @prot_sg_cnt: number of entries in @prot_sg
338 * @sig_attrs: signature offloading algorithms
339 * @remote_addr:remote address to read/write (relative to @rkey)
340 * @rkey: remote key to operate on
341 * @dir: %DMA_TO_DEVICE for RDMA WRITE, %DMA_FROM_DEVICE for RDMA READ
342 *
343 * Returns the number of WQEs that will be needed on the workqueue if
344 * successful, or a negative error code.
345 */
346int rdma_rw_ctx_signature_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
347 u8 port_num, struct scatterlist *sg, u32 sg_cnt,
348 struct scatterlist *prot_sg, u32 prot_sg_cnt,
349 struct ib_sig_attrs *sig_attrs,
350 u64 remote_addr, u32 rkey, enum dma_data_direction dir)
351{
352 struct ib_device *dev = qp->pd->device;
353 u32 pages_per_mr = rdma_rw_fr_page_list_len(qp->pd->device);
354 struct ib_rdma_wr *rdma_wr;
355 struct ib_send_wr *prev_wr = NULL;
356 int count = 0, ret;
357
358 if (sg_cnt > pages_per_mr || prot_sg_cnt > pages_per_mr) {
359 pr_err("SG count too large\n");
360 return -EINVAL;
361 }
362
363 ret = ib_dma_map_sg(dev, sg, sg_cnt, dir);
364 if (!ret)
365 return -ENOMEM;
366 sg_cnt = ret;
367
368 ret = ib_dma_map_sg(dev, prot_sg, prot_sg_cnt, dir);
369 if (!ret) {
370 ret = -ENOMEM;
371 goto out_unmap_sg;
372 }
373 prot_sg_cnt = ret;
374
375 ctx->type = RDMA_RW_SIG_MR;
376 ctx->nr_ops = 1;
377 ctx->sig = kcalloc(1, sizeof(*ctx->sig), GFP_KERNEL);
378 if (!ctx->sig) {
379 ret = -ENOMEM;
380 goto out_unmap_prot_sg;
381 }
382
383 ret = rdma_rw_init_one_mr(qp, port_num, &ctx->sig->data, sg, sg_cnt, 0);
384 if (ret < 0)
385 goto out_free_ctx;
386 count += ret;
387 prev_wr = &ctx->sig->data.reg_wr.wr;
388
389 if (prot_sg_cnt) {
390 ret = rdma_rw_init_one_mr(qp, port_num, &ctx->sig->prot,
391 prot_sg, prot_sg_cnt, 0);
392 if (ret < 0)
393 goto out_destroy_data_mr;
394 count += ret;
395
396 if (ctx->sig->prot.inv_wr.next)
397 prev_wr->next = &ctx->sig->prot.inv_wr;
398 else
399 prev_wr->next = &ctx->sig->prot.reg_wr.wr;
400 prev_wr = &ctx->sig->prot.reg_wr.wr;
401 } else {
402 ctx->sig->prot.mr = NULL;
403 }
404
405 ctx->sig->sig_mr = ib_mr_pool_get(qp, &qp->sig_mrs);
406 if (!ctx->sig->sig_mr) {
407 ret = -EAGAIN;
408 goto out_destroy_prot_mr;
409 }
410
411 if (ctx->sig->sig_mr->need_inval) {
412 memset(&ctx->sig->sig_inv_wr, 0, sizeof(ctx->sig->sig_inv_wr));
413
414 ctx->sig->sig_inv_wr.opcode = IB_WR_LOCAL_INV;
415 ctx->sig->sig_inv_wr.ex.invalidate_rkey = ctx->sig->sig_mr->rkey;
416
417 prev_wr->next = &ctx->sig->sig_inv_wr;
418 prev_wr = &ctx->sig->sig_inv_wr;
419 }
420
421 ctx->sig->sig_wr.wr.opcode = IB_WR_REG_SIG_MR;
422 ctx->sig->sig_wr.wr.wr_cqe = NULL;
423 ctx->sig->sig_wr.wr.sg_list = &ctx->sig->data.sge;
424 ctx->sig->sig_wr.wr.num_sge = 1;
425 ctx->sig->sig_wr.access_flags = IB_ACCESS_LOCAL_WRITE;
426 ctx->sig->sig_wr.sig_attrs = sig_attrs;
427 ctx->sig->sig_wr.sig_mr = ctx->sig->sig_mr;
428 if (prot_sg_cnt)
429 ctx->sig->sig_wr.prot = &ctx->sig->prot.sge;
430 prev_wr->next = &ctx->sig->sig_wr.wr;
431 prev_wr = &ctx->sig->sig_wr.wr;
432 count++;
433
434 ctx->sig->sig_sge.addr = 0;
435 ctx->sig->sig_sge.length = ctx->sig->data.sge.length;
436 if (sig_attrs->wire.sig_type != IB_SIG_TYPE_NONE)
437 ctx->sig->sig_sge.length += ctx->sig->prot.sge.length;
438
439 rdma_wr = &ctx->sig->data.wr;
440 rdma_wr->wr.sg_list = &ctx->sig->sig_sge;
441 rdma_wr->wr.num_sge = 1;
442 rdma_wr->remote_addr = remote_addr;
443 rdma_wr->rkey = rkey;
444 if (dir == DMA_TO_DEVICE)
445 rdma_wr->wr.opcode = IB_WR_RDMA_WRITE;
446 else
447 rdma_wr->wr.opcode = IB_WR_RDMA_READ;
448 prev_wr->next = &rdma_wr->wr;
449 prev_wr = &rdma_wr->wr;
450 count++;
451
452 return count;
453
454out_destroy_prot_mr:
455 if (prot_sg_cnt)
456 ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->sig->prot.mr);
457out_destroy_data_mr:
458 ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->sig->data.mr);
459out_free_ctx:
460 kfree(ctx->sig);
461out_unmap_prot_sg:
462 ib_dma_unmap_sg(dev, prot_sg, prot_sg_cnt, dir);
463out_unmap_sg:
464 ib_dma_unmap_sg(dev, sg, sg_cnt, dir);
465 return ret;
466}
467EXPORT_SYMBOL(rdma_rw_ctx_signature_init);
468
328/* 469/*
329 * Now that we are going to post the WRs we can update the lkey and need_inval 470 * Now that we are going to post the WRs we can update the lkey and need_inval
330 * state on the MRs. If we were doing this at init time, we would get double 471 * state on the MRs. If we were doing this at init time, we would get double
@@ -360,6 +501,22 @@ struct ib_send_wr *rdma_rw_ctx_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
360 int i; 501 int i;
361 502
362 switch (ctx->type) { 503 switch (ctx->type) {
504 case RDMA_RW_SIG_MR:
505 rdma_rw_update_lkey(&ctx->sig->data, true);
506 if (ctx->sig->prot.mr)
507 rdma_rw_update_lkey(&ctx->sig->prot, true);
508
509 ctx->sig->sig_mr->need_inval = true;
510 ib_update_fast_reg_key(ctx->sig->sig_mr,
511 ib_inc_rkey(ctx->sig->sig_mr->lkey));
512 ctx->sig->sig_sge.lkey = ctx->sig->sig_mr->lkey;
513
514 if (ctx->sig->data.inv_wr.next)
515 first_wr = &ctx->sig->data.inv_wr;
516 else
517 first_wr = &ctx->sig->data.reg_wr.wr;
518 last_wr = &ctx->sig->data.wr.wr;
519 break;
363 case RDMA_RW_MR: 520 case RDMA_RW_MR:
364 for (i = 0; i < ctx->nr_ops; i++) { 521 for (i = 0; i < ctx->nr_ops; i++) {
365 rdma_rw_update_lkey(&ctx->reg[i], 522 rdma_rw_update_lkey(&ctx->reg[i],
@@ -455,6 +612,39 @@ void rdma_rw_ctx_destroy(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num,
455} 612}
456EXPORT_SYMBOL(rdma_rw_ctx_destroy); 613EXPORT_SYMBOL(rdma_rw_ctx_destroy);
457 614
615/**
616 * rdma_rw_ctx_destroy_signature - release all resources allocated by
617 * rdma_rw_ctx_init_signature
618 * @ctx: context to release
619 * @qp: queue pair to operate on
620 * @port_num: port num to which the connection is bound
621 * @sg: scatterlist that was used for the READ/WRITE
622 * @sg_cnt: number of entries in @sg
623 * @prot_sg: scatterlist that was used for the READ/WRITE of the PI
624 * @prot_sg_cnt: number of entries in @prot_sg
625 * @dir: %DMA_TO_DEVICE for RDMA WRITE, %DMA_FROM_DEVICE for RDMA READ
626 */
627void rdma_rw_ctx_destroy_signature(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
628 u8 port_num, struct scatterlist *sg, u32 sg_cnt,
629 struct scatterlist *prot_sg, u32 prot_sg_cnt,
630 enum dma_data_direction dir)
631{
632 if (WARN_ON_ONCE(ctx->type != RDMA_RW_SIG_MR))
633 return;
634
635 ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->sig->data.mr);
636 ib_dma_unmap_sg(qp->pd->device, sg, sg_cnt, dir);
637
638 if (ctx->sig->prot.mr) {
639 ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->sig->prot.mr);
640 ib_dma_unmap_sg(qp->pd->device, prot_sg, prot_sg_cnt, dir);
641 }
642
643 ib_mr_pool_put(qp, &qp->sig_mrs, ctx->sig->sig_mr);
644 kfree(ctx->sig);
645}
646EXPORT_SYMBOL(rdma_rw_ctx_destroy_signature);
647
458void rdma_rw_init_qp(struct ib_device *dev, struct ib_qp_init_attr *attr) 648void rdma_rw_init_qp(struct ib_device *dev, struct ib_qp_init_attr *attr)
459{ 649{
460 u32 factor; 650 u32 factor;
@@ -474,7 +664,9 @@ void rdma_rw_init_qp(struct ib_device *dev, struct ib_qp_init_attr *attr)
474 * we'll need two additional MRs for the registrations and the 664 * we'll need two additional MRs for the registrations and the
475 * invalidation. 665 * invalidation.
476 */ 666 */
477 if (rdma_rw_can_use_mr(dev, attr->port_num)) 667 if (attr->create_flags & IB_QP_CREATE_SIGNATURE_EN)
668 factor += 6; /* (inv + reg) * (data + prot + sig) */
669 else if (rdma_rw_can_use_mr(dev, attr->port_num))
478 factor += 2; /* inv + reg */ 670 factor += 2; /* inv + reg */
479 671
480 attr->cap.max_send_wr += factor * attr->cap.max_rdma_ctxs; 672 attr->cap.max_send_wr += factor * attr->cap.max_rdma_ctxs;
@@ -490,20 +682,46 @@ void rdma_rw_init_qp(struct ib_device *dev, struct ib_qp_init_attr *attr)
490int rdma_rw_init_mrs(struct ib_qp *qp, struct ib_qp_init_attr *attr) 682int rdma_rw_init_mrs(struct ib_qp *qp, struct ib_qp_init_attr *attr)
491{ 683{
492 struct ib_device *dev = qp->pd->device; 684 struct ib_device *dev = qp->pd->device;
685 u32 nr_mrs = 0, nr_sig_mrs = 0;
493 int ret = 0; 686 int ret = 0;
494 687
495 if (rdma_rw_can_use_mr(dev, attr->port_num)) { 688 if (attr->create_flags & IB_QP_CREATE_SIGNATURE_EN) {
496 ret = ib_mr_pool_init(qp, &qp->rdma_mrs, 689 nr_sig_mrs = attr->cap.max_rdma_ctxs;
497 attr->cap.max_rdma_ctxs, IB_MR_TYPE_MEM_REG, 690 nr_mrs = attr->cap.max_rdma_ctxs * 2;
691 } else if (rdma_rw_can_use_mr(dev, attr->port_num)) {
692 nr_mrs = attr->cap.max_rdma_ctxs;
693 }
694
695 if (nr_mrs) {
696 ret = ib_mr_pool_init(qp, &qp->rdma_mrs, nr_mrs,
697 IB_MR_TYPE_MEM_REG,
498 rdma_rw_fr_page_list_len(dev)); 698 rdma_rw_fr_page_list_len(dev));
499 if (ret) 699 if (ret) {
700 pr_err("%s: failed to allocated %d MRs\n",
701 __func__, nr_mrs);
500 return ret; 702 return ret;
703 }
704 }
705
706 if (nr_sig_mrs) {
707 ret = ib_mr_pool_init(qp, &qp->sig_mrs, nr_sig_mrs,
708 IB_MR_TYPE_SIGNATURE, 2);
709 if (ret) {
710 pr_err("%s: failed to allocated %d SIG MRs\n",
711 __func__, nr_mrs);
712 goto out_free_rdma_mrs;
713 }
501 } 714 }
502 715
716 return 0;
717
718out_free_rdma_mrs:
719 ib_mr_pool_destroy(qp, &qp->rdma_mrs);
503 return ret; 720 return ret;
504} 721}
505 722
506void rdma_rw_cleanup_mrs(struct ib_qp *qp) 723void rdma_rw_cleanup_mrs(struct ib_qp *qp)
507{ 724{
725 ib_mr_pool_destroy(qp, &qp->sig_mrs);
508 ib_mr_pool_destroy(qp, &qp->rdma_mrs); 726 ib_mr_pool_destroy(qp, &qp->rdma_mrs);
509} 727}
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 566bfb31cadb..3d7b266a2dcb 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -776,6 +776,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
776 qp->mrs_used = 0; 776 qp->mrs_used = 0;
777 spin_lock_init(&qp->mr_lock); 777 spin_lock_init(&qp->mr_lock);
778 INIT_LIST_HEAD(&qp->rdma_mrs); 778 INIT_LIST_HEAD(&qp->rdma_mrs);
779 INIT_LIST_HEAD(&qp->sig_mrs);
779 780
780 if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) 781 if (qp_init_attr->qp_type == IB_QPT_XRC_TGT)
781 return ib_create_xrc_qp(qp, qp_init_attr); 782 return ib_create_xrc_qp(qp, qp_init_attr);
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index dd8e15dfc1a8..544c55b4c84a 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1435,6 +1435,7 @@ struct ib_qp {
1435 spinlock_t mr_lock; 1435 spinlock_t mr_lock;
1436 int mrs_used; 1436 int mrs_used;
1437 struct list_head rdma_mrs; 1437 struct list_head rdma_mrs;
1438 struct list_head sig_mrs;
1438 struct ib_srq *srq; 1439 struct ib_srq *srq;
1439 struct ib_xrcd *xrcd; /* XRC TGT QPs only */ 1440 struct ib_xrcd *xrcd; /* XRC TGT QPs only */
1440 struct list_head xrcd_list; 1441 struct list_head xrcd_list;
diff --git a/include/rdma/rw.h b/include/rdma/rw.h
index d3896bb9134b..377d865e506d 100644
--- a/include/rdma/rw.h
+++ b/include/rdma/rw.h
@@ -47,6 +47,15 @@ struct rdma_rw_ctx {
47 struct ib_send_wr inv_wr; 47 struct ib_send_wr inv_wr;
48 struct ib_mr *mr; 48 struct ib_mr *mr;
49 } *reg; 49 } *reg;
50
51 struct {
52 struct rdma_rw_reg_ctx data;
53 struct rdma_rw_reg_ctx prot;
54 struct ib_send_wr sig_inv_wr;
55 struct ib_mr *sig_mr;
56 struct ib_sge sig_sge;
57 struct ib_sig_handover_wr sig_wr;
58 } *sig;
50 }; 59 };
51}; 60};
52 61
@@ -57,6 +66,16 @@ void rdma_rw_ctx_destroy(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num,
57 struct scatterlist *sg, u32 sg_cnt, 66 struct scatterlist *sg, u32 sg_cnt,
58 enum dma_data_direction dir); 67 enum dma_data_direction dir);
59 68
69int rdma_rw_ctx_signature_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
70 u8 port_num, struct scatterlist *sg, u32 sg_cnt,
71 struct scatterlist *prot_sg, u32 prot_sg_cnt,
72 struct ib_sig_attrs *sig_attrs, u64 remote_addr, u32 rkey,
73 enum dma_data_direction dir);
74void rdma_rw_ctx_destroy_signature(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
75 u8 port_num, struct scatterlist *sg, u32 sg_cnt,
76 struct scatterlist *prot_sg, u32 prot_sg_cnt,
77 enum dma_data_direction dir);
78
60struct ib_send_wr *rdma_rw_ctx_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp, 79struct ib_send_wr *rdma_rw_ctx_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
61 u8 port_num, struct ib_cqe *cqe, struct ib_send_wr *chain_wr); 80 u8 port_num, struct ib_cqe *cqe, struct ib_send_wr *chain_wr);
62int rdma_rw_ctx_post(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num, 81int rdma_rw_ctx_post(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num,