diff options
author | Shani Michaeli <shanim@mellanox.com> | 2013-02-06 11:19:12 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2013-02-21 14:51:45 -0500 |
commit | 7083e42ee2ff43a11481e0e7211ec4f9ac68cb79 (patch) | |
tree | cf2c3f16075fcb37c27bff5ae4524f778df9a482 | |
parent | 836dc9e3fbbab0c30aa6e664417225f5c1fb1c39 (diff) |
IB/core: Add "type 2" memory windows support
This patch enhances the IB core support for Memory Windows (MWs).
MWs allow an application to have better/flexible control over remote
access to memory.
Two types of MWs are supported, with the second type having two flavors:
Type 1 - associated with PD only
Type 2A - associated with QPN only
Type 2B - associated with PD and QPN
Applications can allocate a MW once, and then repeatedly bind the MW
to different ranges in MRs that are associated to the same PD. Type 1
windows are bound through a verb, while type 2 windows are bound by
posting a work request.
The 32-bit memory key is composed of a 24-bit index and an 8-bit
key. The key is changed with each bind, thus allowing more control
over the peer's use of the memory key.
The changes introduced are the following:
* add memory window type enum and a corresponding parameter to ib_alloc_mw.
* type 2 memory window bind work request support.
* create a struct that contains the common part of the bind verb struct
ibv_mw_bind and the bind work request into a single struct.
* add the ib_inc_rkey helper function to advance the tag part of an rkey.
Consumer interface details:
* new device capability flags IB_DEVICE_MEM_WINDOW_TYPE_2A and
IB_DEVICE_MEM_WINDOW_TYPE_2B are added to indicate device support
for these features.
Devices can set either IB_DEVICE_MEM_WINDOW_TYPE_2A or
IB_DEVICE_MEM_WINDOW_TYPE_2B if it supports type 2A or type 2B
memory windows. It can set neither to indicate it doesn't support
type 2 windows at all.
* modify existing provides and consumers code to the new param of
ib_alloc_mw and the ib_mw_bind_info structure
Signed-off-by: Haggai Eran <haggaie@mellanox.com>
Signed-off-by: Shani Michaeli <shanim@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r-- | drivers/infiniband/core/verbs.c | 5 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb3/iwch_provider.c | 5 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb3/iwch_qp.c | 15 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/mem.c | 5 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_iverbs.h | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_mrmw.c | 5 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_verbs.c | 19 | ||||
-rw-r--r-- | include/rdma/ib_verbs.h | 73 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/verbs.c | 20 |
10 files changed, 110 insertions, 41 deletions
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 30f199e8579f..a8fdd3381405 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c | |||
@@ -1099,18 +1099,19 @@ EXPORT_SYMBOL(ib_free_fast_reg_page_list); | |||
1099 | 1099 | ||
1100 | /* Memory windows */ | 1100 | /* Memory windows */ |
1101 | 1101 | ||
1102 | struct ib_mw *ib_alloc_mw(struct ib_pd *pd) | 1102 | struct ib_mw *ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type) |
1103 | { | 1103 | { |
1104 | struct ib_mw *mw; | 1104 | struct ib_mw *mw; |
1105 | 1105 | ||
1106 | if (!pd->device->alloc_mw) | 1106 | if (!pd->device->alloc_mw) |
1107 | return ERR_PTR(-ENOSYS); | 1107 | return ERR_PTR(-ENOSYS); |
1108 | 1108 | ||
1109 | mw = pd->device->alloc_mw(pd); | 1109 | mw = pd->device->alloc_mw(pd, type); |
1110 | if (!IS_ERR(mw)) { | 1110 | if (!IS_ERR(mw)) { |
1111 | mw->device = pd->device; | 1111 | mw->device = pd->device; |
1112 | mw->pd = pd; | 1112 | mw->pd = pd; |
1113 | mw->uobject = NULL; | 1113 | mw->uobject = NULL; |
1114 | mw->type = type; | ||
1114 | atomic_inc(&pd->usecnt); | 1115 | atomic_inc(&pd->usecnt); |
1115 | } | 1116 | } |
1116 | 1117 | ||
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index 0bdf09aa6f42..074d5c25f50b 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c | |||
@@ -738,7 +738,7 @@ static struct ib_mr *iwch_get_dma_mr(struct ib_pd *pd, int acc) | |||
738 | return ibmr; | 738 | return ibmr; |
739 | } | 739 | } |
740 | 740 | ||
741 | static struct ib_mw *iwch_alloc_mw(struct ib_pd *pd) | 741 | static struct ib_mw *iwch_alloc_mw(struct ib_pd *pd, enum ib_mw_type type) |
742 | { | 742 | { |
743 | struct iwch_dev *rhp; | 743 | struct iwch_dev *rhp; |
744 | struct iwch_pd *php; | 744 | struct iwch_pd *php; |
@@ -747,6 +747,9 @@ static struct ib_mw *iwch_alloc_mw(struct ib_pd *pd) | |||
747 | u32 stag = 0; | 747 | u32 stag = 0; |
748 | int ret; | 748 | int ret; |
749 | 749 | ||
750 | if (type != IB_MW_TYPE_1) | ||
751 | return ERR_PTR(-EINVAL); | ||
752 | |||
750 | php = to_iwch_pd(pd); | 753 | php = to_iwch_pd(pd); |
751 | rhp = php->rhp; | 754 | rhp = php->rhp; |
752 | mhp = kzalloc(sizeof(*mhp), GFP_KERNEL); | 755 | mhp = kzalloc(sizeof(*mhp), GFP_KERNEL); |
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c index 6de8463f453b..e5649e8b215d 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_qp.c +++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c | |||
@@ -567,18 +567,19 @@ int iwch_bind_mw(struct ib_qp *qp, | |||
567 | if (mw_bind->send_flags & IB_SEND_SIGNALED) | 567 | if (mw_bind->send_flags & IB_SEND_SIGNALED) |
568 | t3_wr_flags = T3_COMPLETION_FLAG; | 568 | t3_wr_flags = T3_COMPLETION_FLAG; |
569 | 569 | ||
570 | sgl.addr = mw_bind->addr; | 570 | sgl.addr = mw_bind->bind_info.addr; |
571 | sgl.lkey = mw_bind->mr->lkey; | 571 | sgl.lkey = mw_bind->bind_info.mr->lkey; |
572 | sgl.length = mw_bind->length; | 572 | sgl.length = mw_bind->bind_info.length; |
573 | wqe->bind.reserved = 0; | 573 | wqe->bind.reserved = 0; |
574 | wqe->bind.type = TPT_VATO; | 574 | wqe->bind.type = TPT_VATO; |
575 | 575 | ||
576 | /* TBD: check perms */ | 576 | /* TBD: check perms */ |
577 | wqe->bind.perms = iwch_ib_to_tpt_bind_access(mw_bind->mw_access_flags); | 577 | wqe->bind.perms = iwch_ib_to_tpt_bind_access( |
578 | wqe->bind.mr_stag = cpu_to_be32(mw_bind->mr->lkey); | 578 | mw_bind->bind_info.mw_access_flags); |
579 | wqe->bind.mr_stag = cpu_to_be32(mw_bind->bind_info.mr->lkey); | ||
579 | wqe->bind.mw_stag = cpu_to_be32(mw->rkey); | 580 | wqe->bind.mw_stag = cpu_to_be32(mw->rkey); |
580 | wqe->bind.mw_len = cpu_to_be32(mw_bind->length); | 581 | wqe->bind.mw_len = cpu_to_be32(mw_bind->bind_info.length); |
581 | wqe->bind.mw_va = cpu_to_be64(mw_bind->addr); | 582 | wqe->bind.mw_va = cpu_to_be64(mw_bind->bind_info.addr); |
582 | err = iwch_sgl2pbl_map(rhp, &sgl, 1, &pbl_addr, &page_size); | 583 | err = iwch_sgl2pbl_map(rhp, &sgl, 1, &pbl_addr, &page_size); |
583 | if (err) { | 584 | if (err) { |
584 | spin_unlock_irqrestore(&qhp->lock, flag); | 585 | spin_unlock_irqrestore(&qhp->lock, flag); |
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index 9c1644fb0259..c8bd239915d5 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h | |||
@@ -866,7 +866,7 @@ struct ib_fast_reg_page_list *c4iw_alloc_fastreg_pbl( | |||
866 | int page_list_len); | 866 | int page_list_len); |
867 | struct ib_mr *c4iw_alloc_fast_reg_mr(struct ib_pd *pd, int pbl_depth); | 867 | struct ib_mr *c4iw_alloc_fast_reg_mr(struct ib_pd *pd, int pbl_depth); |
868 | int c4iw_dealloc_mw(struct ib_mw *mw); | 868 | int c4iw_dealloc_mw(struct ib_mw *mw); |
869 | struct ib_mw *c4iw_alloc_mw(struct ib_pd *pd); | 869 | struct ib_mw *c4iw_alloc_mw(struct ib_pd *pd, enum ib_mw_type type); |
870 | struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, | 870 | struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, |
871 | u64 length, u64 virt, int acc, | 871 | u64 length, u64 virt, int acc, |
872 | struct ib_udata *udata); | 872 | struct ib_udata *udata); |
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index afd81790ab3c..903a92d6f91d 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c | |||
@@ -650,7 +650,7 @@ err: | |||
650 | return ERR_PTR(err); | 650 | return ERR_PTR(err); |
651 | } | 651 | } |
652 | 652 | ||
653 | struct ib_mw *c4iw_alloc_mw(struct ib_pd *pd) | 653 | struct ib_mw *c4iw_alloc_mw(struct ib_pd *pd, enum ib_mw_type type) |
654 | { | 654 | { |
655 | struct c4iw_dev *rhp; | 655 | struct c4iw_dev *rhp; |
656 | struct c4iw_pd *php; | 656 | struct c4iw_pd *php; |
@@ -659,6 +659,9 @@ struct ib_mw *c4iw_alloc_mw(struct ib_pd *pd) | |||
659 | u32 stag = 0; | 659 | u32 stag = 0; |
660 | int ret; | 660 | int ret; |
661 | 661 | ||
662 | if (type != IB_MW_TYPE_1) | ||
663 | return ERR_PTR(-EINVAL); | ||
664 | |||
662 | php = to_c4iw_pd(pd); | 665 | php = to_c4iw_pd(pd); |
663 | rhp = php->rhp; | 666 | rhp = php->rhp; |
664 | mhp = kzalloc(sizeof(*mhp), GFP_KERNEL); | 667 | mhp = kzalloc(sizeof(*mhp), GFP_KERNEL); |
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h index 8f7f282ead65..22f79afa7fc1 100644 --- a/drivers/infiniband/hw/ehca/ehca_iverbs.h +++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h | |||
@@ -95,7 +95,7 @@ int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr); | |||
95 | 95 | ||
96 | int ehca_dereg_mr(struct ib_mr *mr); | 96 | int ehca_dereg_mr(struct ib_mr *mr); |
97 | 97 | ||
98 | struct ib_mw *ehca_alloc_mw(struct ib_pd *pd); | 98 | struct ib_mw *ehca_alloc_mw(struct ib_pd *pd, enum ib_mw_type type); |
99 | 99 | ||
100 | int ehca_bind_mw(struct ib_qp *qp, struct ib_mw *mw, | 100 | int ehca_bind_mw(struct ib_qp *qp, struct ib_mw *mw, |
101 | struct ib_mw_bind *mw_bind); | 101 | struct ib_mw_bind *mw_bind); |
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c index 87844869dcc2..bcfb0c183620 100644 --- a/drivers/infiniband/hw/ehca/ehca_mrmw.c +++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c | |||
@@ -688,7 +688,7 @@ dereg_mr_exit0: | |||
688 | 688 | ||
689 | /*----------------------------------------------------------------------*/ | 689 | /*----------------------------------------------------------------------*/ |
690 | 690 | ||
691 | struct ib_mw *ehca_alloc_mw(struct ib_pd *pd) | 691 | struct ib_mw *ehca_alloc_mw(struct ib_pd *pd, enum ib_mw_type type) |
692 | { | 692 | { |
693 | struct ib_mw *ib_mw; | 693 | struct ib_mw *ib_mw; |
694 | u64 h_ret; | 694 | u64 h_ret; |
@@ -698,6 +698,9 @@ struct ib_mw *ehca_alloc_mw(struct ib_pd *pd) | |||
698 | container_of(pd->device, struct ehca_shca, ib_device); | 698 | container_of(pd->device, struct ehca_shca, ib_device); |
699 | struct ehca_mw_hipzout_parms hipzout; | 699 | struct ehca_mw_hipzout_parms hipzout; |
700 | 700 | ||
701 | if (type != IB_MW_TYPE_1) | ||
702 | return ERR_PTR(-EINVAL); | ||
703 | |||
701 | e_mw = ehca_mw_new(); | 704 | e_mw = ehca_mw_new(); |
702 | if (!e_mw) { | 705 | if (!e_mw) { |
703 | ib_mw = ERR_PTR(-ENOMEM); | 706 | ib_mw = ERR_PTR(-ENOMEM); |
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 07e4fbad987a..8f67fe2e91e6 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c | |||
@@ -55,7 +55,8 @@ static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev); | |||
55 | /** | 55 | /** |
56 | * nes_alloc_mw | 56 | * nes_alloc_mw |
57 | */ | 57 | */ |
58 | static struct ib_mw *nes_alloc_mw(struct ib_pd *ibpd) { | 58 | static struct ib_mw *nes_alloc_mw(struct ib_pd *ibpd, enum ib_mw_type type) |
59 | { | ||
59 | struct nes_pd *nespd = to_nespd(ibpd); | 60 | struct nes_pd *nespd = to_nespd(ibpd); |
60 | struct nes_vnic *nesvnic = to_nesvnic(ibpd->device); | 61 | struct nes_vnic *nesvnic = to_nesvnic(ibpd->device); |
61 | struct nes_device *nesdev = nesvnic->nesdev; | 62 | struct nes_device *nesdev = nesvnic->nesdev; |
@@ -71,6 +72,9 @@ static struct ib_mw *nes_alloc_mw(struct ib_pd *ibpd) { | |||
71 | u32 driver_key = 0; | 72 | u32 driver_key = 0; |
72 | u8 stag_key = 0; | 73 | u8 stag_key = 0; |
73 | 74 | ||
75 | if (type != IB_MW_TYPE_1) | ||
76 | return ERR_PTR(-EINVAL); | ||
77 | |||
74 | get_random_bytes(&next_stag_index, sizeof(next_stag_index)); | 78 | get_random_bytes(&next_stag_index, sizeof(next_stag_index)); |
75 | stag_key = (u8)next_stag_index; | 79 | stag_key = (u8)next_stag_index; |
76 | 80 | ||
@@ -244,20 +248,19 @@ static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw, | |||
244 | if (ibmw_bind->send_flags & IB_SEND_SIGNALED) | 248 | if (ibmw_bind->send_flags & IB_SEND_SIGNALED) |
245 | wqe_misc |= NES_IWARP_SQ_WQE_SIGNALED_COMPL; | 249 | wqe_misc |= NES_IWARP_SQ_WQE_SIGNALED_COMPL; |
246 | 250 | ||
247 | if (ibmw_bind->mw_access_flags & IB_ACCESS_REMOTE_WRITE) { | 251 | if (ibmw_bind->bind_info.mw_access_flags & IB_ACCESS_REMOTE_WRITE) |
248 | wqe_misc |= NES_CQP_STAG_RIGHTS_REMOTE_WRITE; | 252 | wqe_misc |= NES_CQP_STAG_RIGHTS_REMOTE_WRITE; |
249 | } | 253 | if (ibmw_bind->bind_info.mw_access_flags & IB_ACCESS_REMOTE_READ) |
250 | if (ibmw_bind->mw_access_flags & IB_ACCESS_REMOTE_READ) { | ||
251 | wqe_misc |= NES_CQP_STAG_RIGHTS_REMOTE_READ; | 254 | wqe_misc |= NES_CQP_STAG_RIGHTS_REMOTE_READ; |
252 | } | ||
253 | 255 | ||
254 | set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_MISC_IDX, wqe_misc); | 256 | set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_MISC_IDX, wqe_misc); |
255 | set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_MR_IDX, ibmw_bind->mr->lkey); | 257 | set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_MR_IDX, |
258 | ibmw_bind->bind_info.mr->lkey); | ||
256 | set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_MW_IDX, ibmw->rkey); | 259 | set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_MW_IDX, ibmw->rkey); |
257 | set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_LENGTH_LOW_IDX, | 260 | set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_LENGTH_LOW_IDX, |
258 | ibmw_bind->length); | 261 | ibmw_bind->bind_info.length); |
259 | wqe->wqe_words[NES_IWARP_SQ_BIND_WQE_LENGTH_HIGH_IDX] = 0; | 262 | wqe->wqe_words[NES_IWARP_SQ_BIND_WQE_LENGTH_HIGH_IDX] = 0; |
260 | u64temp = (u64)ibmw_bind->addr; | 263 | u64temp = (u64)ibmw_bind->bind_info.addr; |
261 | set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_VA_FBO_LOW_IDX, u64temp); | 264 | set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_VA_FBO_LOW_IDX, u64temp); |
262 | 265 | ||
263 | head++; | 266 | head++; |
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 46bc045bbe15..98cc4b29fc5b 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h | |||
@@ -115,6 +115,8 @@ enum ib_device_cap_flags { | |||
115 | IB_DEVICE_XRC = (1<<20), | 115 | IB_DEVICE_XRC = (1<<20), |
116 | IB_DEVICE_MEM_MGT_EXTENSIONS = (1<<21), | 116 | IB_DEVICE_MEM_MGT_EXTENSIONS = (1<<21), |
117 | IB_DEVICE_BLOCK_MULTICAST_LOOPBACK = (1<<22), | 117 | IB_DEVICE_BLOCK_MULTICAST_LOOPBACK = (1<<22), |
118 | IB_DEVICE_MEM_WINDOW_TYPE_2A = (1<<23), | ||
119 | IB_DEVICE_MEM_WINDOW_TYPE_2B = (1<<24) | ||
118 | }; | 120 | }; |
119 | 121 | ||
120 | enum ib_atomic_cap { | 122 | enum ib_atomic_cap { |
@@ -715,6 +717,11 @@ enum ib_mig_state { | |||
715 | IB_MIG_ARMED | 717 | IB_MIG_ARMED |
716 | }; | 718 | }; |
717 | 719 | ||
720 | enum ib_mw_type { | ||
721 | IB_MW_TYPE_1 = 1, | ||
722 | IB_MW_TYPE_2 = 2 | ||
723 | }; | ||
724 | |||
718 | struct ib_qp_attr { | 725 | struct ib_qp_attr { |
719 | enum ib_qp_state qp_state; | 726 | enum ib_qp_state qp_state; |
720 | enum ib_qp_state cur_qp_state; | 727 | enum ib_qp_state cur_qp_state; |
@@ -758,6 +765,7 @@ enum ib_wr_opcode { | |||
758 | IB_WR_FAST_REG_MR, | 765 | IB_WR_FAST_REG_MR, |
759 | IB_WR_MASKED_ATOMIC_CMP_AND_SWP, | 766 | IB_WR_MASKED_ATOMIC_CMP_AND_SWP, |
760 | IB_WR_MASKED_ATOMIC_FETCH_AND_ADD, | 767 | IB_WR_MASKED_ATOMIC_FETCH_AND_ADD, |
768 | IB_WR_BIND_MW, | ||
761 | }; | 769 | }; |
762 | 770 | ||
763 | enum ib_send_flags { | 771 | enum ib_send_flags { |
@@ -780,6 +788,23 @@ struct ib_fast_reg_page_list { | |||
780 | unsigned int max_page_list_len; | 788 | unsigned int max_page_list_len; |
781 | }; | 789 | }; |
782 | 790 | ||
791 | /** | ||
792 | * struct ib_mw_bind_info - Parameters for a memory window bind operation. | ||
793 | * @mr: A memory region to bind the memory window to. | ||
794 | * @addr: The address where the memory window should begin. | ||
795 | * @length: The length of the memory window, in bytes. | ||
796 | * @mw_access_flags: Access flags from enum ib_access_flags for the window. | ||
797 | * | ||
798 | * This struct contains the shared parameters for type 1 and type 2 | ||
799 | * memory window bind operations. | ||
800 | */ | ||
801 | struct ib_mw_bind_info { | ||
802 | struct ib_mr *mr; | ||
803 | u64 addr; | ||
804 | u64 length; | ||
805 | int mw_access_flags; | ||
806 | }; | ||
807 | |||
783 | struct ib_send_wr { | 808 | struct ib_send_wr { |
784 | struct ib_send_wr *next; | 809 | struct ib_send_wr *next; |
785 | u64 wr_id; | 810 | u64 wr_id; |
@@ -823,6 +848,12 @@ struct ib_send_wr { | |||
823 | int access_flags; | 848 | int access_flags; |
824 | u32 rkey; | 849 | u32 rkey; |
825 | } fast_reg; | 850 | } fast_reg; |
851 | struct { | ||
852 | struct ib_mw *mw; | ||
853 | /* The new rkey for the memory window. */ | ||
854 | u32 rkey; | ||
855 | struct ib_mw_bind_info bind_info; | ||
856 | } bind_mw; | ||
826 | } wr; | 857 | } wr; |
827 | u32 xrc_remote_srq_num; /* XRC TGT QPs only */ | 858 | u32 xrc_remote_srq_num; /* XRC TGT QPs only */ |
828 | }; | 859 | }; |
@@ -839,7 +870,8 @@ enum ib_access_flags { | |||
839 | IB_ACCESS_REMOTE_WRITE = (1<<1), | 870 | IB_ACCESS_REMOTE_WRITE = (1<<1), |
840 | IB_ACCESS_REMOTE_READ = (1<<2), | 871 | IB_ACCESS_REMOTE_READ = (1<<2), |
841 | IB_ACCESS_REMOTE_ATOMIC = (1<<3), | 872 | IB_ACCESS_REMOTE_ATOMIC = (1<<3), |
842 | IB_ACCESS_MW_BIND = (1<<4) | 873 | IB_ACCESS_MW_BIND = (1<<4), |
874 | IB_ZERO_BASED = (1<<5) | ||
843 | }; | 875 | }; |
844 | 876 | ||
845 | struct ib_phys_buf { | 877 | struct ib_phys_buf { |
@@ -862,13 +894,16 @@ enum ib_mr_rereg_flags { | |||
862 | IB_MR_REREG_ACCESS = (1<<2) | 894 | IB_MR_REREG_ACCESS = (1<<2) |
863 | }; | 895 | }; |
864 | 896 | ||
897 | /** | ||
898 | * struct ib_mw_bind - Parameters for a type 1 memory window bind operation. | ||
899 | * @wr_id: Work request id. | ||
900 | * @send_flags: Flags from ib_send_flags enum. | ||
901 | * @bind_info: More parameters of the bind operation. | ||
902 | */ | ||
865 | struct ib_mw_bind { | 903 | struct ib_mw_bind { |
866 | struct ib_mr *mr; | 904 | u64 wr_id; |
867 | u64 wr_id; | 905 | int send_flags; |
868 | u64 addr; | 906 | struct ib_mw_bind_info bind_info; |
869 | u32 length; | ||
870 | int send_flags; | ||
871 | int mw_access_flags; | ||
872 | }; | 907 | }; |
873 | 908 | ||
874 | struct ib_fmr_attr { | 909 | struct ib_fmr_attr { |
@@ -991,6 +1026,7 @@ struct ib_mw { | |||
991 | struct ib_pd *pd; | 1026 | struct ib_pd *pd; |
992 | struct ib_uobject *uobject; | 1027 | struct ib_uobject *uobject; |
993 | u32 rkey; | 1028 | u32 rkey; |
1029 | enum ib_mw_type type; | ||
994 | }; | 1030 | }; |
995 | 1031 | ||
996 | struct ib_fmr { | 1032 | struct ib_fmr { |
@@ -1202,7 +1238,8 @@ struct ib_device { | |||
1202 | int num_phys_buf, | 1238 | int num_phys_buf, |
1203 | int mr_access_flags, | 1239 | int mr_access_flags, |
1204 | u64 *iova_start); | 1240 | u64 *iova_start); |
1205 | struct ib_mw * (*alloc_mw)(struct ib_pd *pd); | 1241 | struct ib_mw * (*alloc_mw)(struct ib_pd *pd, |
1242 | enum ib_mw_type type); | ||
1206 | int (*bind_mw)(struct ib_qp *qp, | 1243 | int (*bind_mw)(struct ib_qp *qp, |
1207 | struct ib_mw *mw, | 1244 | struct ib_mw *mw, |
1208 | struct ib_mw_bind *mw_bind); | 1245 | struct ib_mw_bind *mw_bind); |
@@ -2019,6 +2056,8 @@ int ib_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr); | |||
2019 | * ib_dereg_mr - Deregisters a memory region and removes it from the | 2056 | * ib_dereg_mr - Deregisters a memory region and removes it from the |
2020 | * HCA translation table. | 2057 | * HCA translation table. |
2021 | * @mr: The memory region to deregister. | 2058 | * @mr: The memory region to deregister. |
2059 | * | ||
2060 | * This function can fail, if the memory region has memory windows bound to it. | ||
2022 | */ | 2061 | */ |
2023 | int ib_dereg_mr(struct ib_mr *mr); | 2062 | int ib_dereg_mr(struct ib_mr *mr); |
2024 | 2063 | ||
@@ -2071,10 +2110,22 @@ static inline void ib_update_fast_reg_key(struct ib_mr *mr, u8 newkey) | |||
2071 | } | 2110 | } |
2072 | 2111 | ||
2073 | /** | 2112 | /** |
2113 | * ib_inc_rkey - increments the key portion of the given rkey. Can be used | ||
2114 | * for calculating a new rkey for type 2 memory windows. | ||
2115 | * @rkey - the rkey to increment. | ||
2116 | */ | ||
2117 | static inline u32 ib_inc_rkey(u32 rkey) | ||
2118 | { | ||
2119 | const u32 mask = 0x000000ff; | ||
2120 | return ((rkey + 1) & mask) | (rkey & ~mask); | ||
2121 | } | ||
2122 | |||
2123 | /** | ||
2074 | * ib_alloc_mw - Allocates a memory window. | 2124 | * ib_alloc_mw - Allocates a memory window. |
2075 | * @pd: The protection domain associated with the memory window. | 2125 | * @pd: The protection domain associated with the memory window. |
2126 | * @type: The type of the memory window (1 or 2). | ||
2076 | */ | 2127 | */ |
2077 | struct ib_mw *ib_alloc_mw(struct ib_pd *pd); | 2128 | struct ib_mw *ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type); |
2078 | 2129 | ||
2079 | /** | 2130 | /** |
2080 | * ib_bind_mw - Posts a work request to the send queue of the specified | 2131 | * ib_bind_mw - Posts a work request to the send queue of the specified |
@@ -2084,6 +2135,10 @@ struct ib_mw *ib_alloc_mw(struct ib_pd *pd); | |||
2084 | * @mw: The memory window to bind. | 2135 | * @mw: The memory window to bind. |
2085 | * @mw_bind: Specifies information about the memory window, including | 2136 | * @mw_bind: Specifies information about the memory window, including |
2086 | * its address range, remote access rights, and associated memory region. | 2137 | * its address range, remote access rights, and associated memory region. |
2138 | * | ||
2139 | * If there is no immediate error, the function will update the rkey member | ||
2140 | * of the mw parameter to its new value. The bind operation can still fail | ||
2141 | * asynchronously. | ||
2087 | */ | 2142 | */ |
2088 | static inline int ib_bind_mw(struct ib_qp *qp, | 2143 | static inline int ib_bind_mw(struct ib_qp *qp, |
2089 | struct ib_mw *mw, | 2144 | struct ib_mw *mw, |
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 745973b729af..93726560eaa8 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -1086,7 +1086,7 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, | |||
1086 | case RPCRDMA_MEMWINDOWS: | 1086 | case RPCRDMA_MEMWINDOWS: |
1087 | /* Allocate one extra request's worth, for full cycling */ | 1087 | /* Allocate one extra request's worth, for full cycling */ |
1088 | for (i = (buf->rb_max_requests+1) * RPCRDMA_MAX_SEGS; i; i--) { | 1088 | for (i = (buf->rb_max_requests+1) * RPCRDMA_MAX_SEGS; i; i--) { |
1089 | r->r.mw = ib_alloc_mw(ia->ri_pd); | 1089 | r->r.mw = ib_alloc_mw(ia->ri_pd, IB_MW_TYPE_1); |
1090 | if (IS_ERR(r->r.mw)) { | 1090 | if (IS_ERR(r->r.mw)) { |
1091 | rc = PTR_ERR(r->r.mw); | 1091 | rc = PTR_ERR(r->r.mw); |
1092 | dprintk("RPC: %s: ib_alloc_mw" | 1092 | dprintk("RPC: %s: ib_alloc_mw" |
@@ -1673,12 +1673,12 @@ rpcrdma_register_memwin_external(struct rpcrdma_mr_seg *seg, | |||
1673 | 1673 | ||
1674 | *nsegs = 1; | 1674 | *nsegs = 1; |
1675 | rpcrdma_map_one(ia, seg, writing); | 1675 | rpcrdma_map_one(ia, seg, writing); |
1676 | param.mr = ia->ri_bind_mem; | 1676 | param.bind_info.mr = ia->ri_bind_mem; |
1677 | param.wr_id = 0ULL; /* no send cookie */ | 1677 | param.wr_id = 0ULL; /* no send cookie */ |
1678 | param.addr = seg->mr_dma; | 1678 | param.bind_info.addr = seg->mr_dma; |
1679 | param.length = seg->mr_len; | 1679 | param.bind_info.length = seg->mr_len; |
1680 | param.send_flags = 0; | 1680 | param.send_flags = 0; |
1681 | param.mw_access_flags = mem_priv; | 1681 | param.bind_info.mw_access_flags = mem_priv; |
1682 | 1682 | ||
1683 | DECR_CQCOUNT(&r_xprt->rx_ep); | 1683 | DECR_CQCOUNT(&r_xprt->rx_ep); |
1684 | rc = ib_bind_mw(ia->ri_id->qp, seg->mr_chunk.rl_mw->r.mw, ¶m); | 1684 | rc = ib_bind_mw(ia->ri_id->qp, seg->mr_chunk.rl_mw->r.mw, ¶m); |
@@ -1690,7 +1690,7 @@ rpcrdma_register_memwin_external(struct rpcrdma_mr_seg *seg, | |||
1690 | rpcrdma_unmap_one(ia, seg); | 1690 | rpcrdma_unmap_one(ia, seg); |
1691 | } else { | 1691 | } else { |
1692 | seg->mr_rkey = seg->mr_chunk.rl_mw->r.mw->rkey; | 1692 | seg->mr_rkey = seg->mr_chunk.rl_mw->r.mw->rkey; |
1693 | seg->mr_base = param.addr; | 1693 | seg->mr_base = param.bind_info.addr; |
1694 | seg->mr_nsegs = 1; | 1694 | seg->mr_nsegs = 1; |
1695 | } | 1695 | } |
1696 | return rc; | 1696 | return rc; |
@@ -1706,10 +1706,10 @@ rpcrdma_deregister_memwin_external(struct rpcrdma_mr_seg *seg, | |||
1706 | int rc; | 1706 | int rc; |
1707 | 1707 | ||
1708 | BUG_ON(seg->mr_nsegs != 1); | 1708 | BUG_ON(seg->mr_nsegs != 1); |
1709 | param.mr = ia->ri_bind_mem; | 1709 | param.bind_info.mr = ia->ri_bind_mem; |
1710 | param.addr = 0ULL; /* unbind */ | 1710 | param.bind_info.addr = 0ULL; /* unbind */ |
1711 | param.length = 0; | 1711 | param.bind_info.length = 0; |
1712 | param.mw_access_flags = 0; | 1712 | param.bind_info.mw_access_flags = 0; |
1713 | if (*r) { | 1713 | if (*r) { |
1714 | param.wr_id = (u64) (unsigned long) *r; | 1714 | param.wr_id = (u64) (unsigned long) *r; |
1715 | param.send_flags = IB_SEND_SIGNALED; | 1715 | param.send_flags = IB_SEND_SIGNALED; |