aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatan Barak <matanb@mellanox.com>2014-07-31 04:01:28 -0400
committerRoland Dreier <roland@purestorage.com>2014-08-01 18:11:13 -0400
commit7e6edb9b2e0bcfb2a588db390c44d120213c57ae (patch)
tree9a8699e7cf72bc2c12574e3a2c46ddf10c542cd2
parent64aa90f26c06e1cb2aacfb98a7d0eccfbd6c1a91 (diff)
IB/core: Add user MR re-registration support
Memory re-registration is a feature that enables changing the attributes of a memory region registered by user-space, including PD, translation (address and length) and access flags. Add the required support in uverbs and the kernel verbs API. Signed-off-by: Matan Barak <matanb@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/infiniband/core/uverbs.h1
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c93
-rw-r--r--drivers/infiniband/core/uverbs_main.c1
-rw-r--r--include/rdma/ib_verbs.h10
-rw-r--r--include/uapi/rdma/ib_user_verbs.h16
5 files changed, 120 insertions, 1 deletions
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index a283274a5a09..643c08a025a5 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -221,6 +221,7 @@ IB_UVERBS_DECLARE_CMD(query_port);
221IB_UVERBS_DECLARE_CMD(alloc_pd); 221IB_UVERBS_DECLARE_CMD(alloc_pd);
222IB_UVERBS_DECLARE_CMD(dealloc_pd); 222IB_UVERBS_DECLARE_CMD(dealloc_pd);
223IB_UVERBS_DECLARE_CMD(reg_mr); 223IB_UVERBS_DECLARE_CMD(reg_mr);
224IB_UVERBS_DECLARE_CMD(rereg_mr);
224IB_UVERBS_DECLARE_CMD(dereg_mr); 225IB_UVERBS_DECLARE_CMD(dereg_mr);
225IB_UVERBS_DECLARE_CMD(alloc_mw); 226IB_UVERBS_DECLARE_CMD(alloc_mw);
226IB_UVERBS_DECLARE_CMD(dealloc_mw); 227IB_UVERBS_DECLARE_CMD(dealloc_mw);
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index ea6203ee7bcc..0600c50e6215 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1002,6 +1002,99 @@ err_free:
1002 return ret; 1002 return ret;
1003} 1003}
1004 1004
1005ssize_t ib_uverbs_rereg_mr(struct ib_uverbs_file *file,
1006 const char __user *buf, int in_len,
1007 int out_len)
1008{
1009 struct ib_uverbs_rereg_mr cmd;
1010 struct ib_uverbs_rereg_mr_resp resp;
1011 struct ib_udata udata;
1012 struct ib_pd *pd = NULL;
1013 struct ib_mr *mr;
1014 struct ib_pd *old_pd;
1015 int ret;
1016 struct ib_uobject *uobj;
1017
1018 if (out_len < sizeof(resp))
1019 return -ENOSPC;
1020
1021 if (copy_from_user(&cmd, buf, sizeof(cmd)))
1022 return -EFAULT;
1023
1024 INIT_UDATA(&udata, buf + sizeof(cmd),
1025 (unsigned long) cmd.response + sizeof(resp),
1026 in_len - sizeof(cmd), out_len - sizeof(resp));
1027
1028 if (cmd.flags & ~IB_MR_REREG_SUPPORTED || !cmd.flags)
1029 return -EINVAL;
1030
1031 if ((cmd.flags & IB_MR_REREG_TRANS) &&
1032 (!cmd.start || !cmd.hca_va || 0 >= cmd.length ||
1033 (cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK)))
1034 return -EINVAL;
1035
1036 uobj = idr_write_uobj(&ib_uverbs_mr_idr, cmd.mr_handle,
1037 file->ucontext);
1038
1039 if (!uobj)
1040 return -EINVAL;
1041
1042 mr = uobj->object;
1043
1044 if (cmd.flags & IB_MR_REREG_ACCESS) {
1045 ret = ib_check_mr_access(cmd.access_flags);
1046 if (ret)
1047 goto put_uobjs;
1048 }
1049
1050 if (cmd.flags & IB_MR_REREG_PD) {
1051 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
1052 if (!pd) {
1053 ret = -EINVAL;
1054 goto put_uobjs;
1055 }
1056 }
1057
1058 if (atomic_read(&mr->usecnt)) {
1059 ret = -EBUSY;
1060 goto put_uobj_pd;
1061 }
1062
1063 old_pd = mr->pd;
1064 ret = mr->device->rereg_user_mr(mr, cmd.flags, cmd.start,
1065 cmd.length, cmd.hca_va,
1066 cmd.access_flags, pd, &udata);
1067 if (!ret) {
1068 if (cmd.flags & IB_MR_REREG_PD) {
1069 atomic_inc(&pd->usecnt);
1070 mr->pd = pd;
1071 atomic_dec(&old_pd->usecnt);
1072 }
1073 } else {
1074 goto put_uobj_pd;
1075 }
1076
1077 memset(&resp, 0, sizeof(resp));
1078 resp.lkey = mr->lkey;
1079 resp.rkey = mr->rkey;
1080
1081 if (copy_to_user((void __user *)(unsigned long)cmd.response,
1082 &resp, sizeof(resp)))
1083 ret = -EFAULT;
1084 else
1085 ret = in_len;
1086
1087put_uobj_pd:
1088 if (cmd.flags & IB_MR_REREG_PD)
1089 put_pd_read(pd);
1090
1091put_uobjs:
1092
1093 put_uobj_write(mr->uobject);
1094
1095 return ret;
1096}
1097
1005ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, 1098ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
1006 const char __user *buf, int in_len, 1099 const char __user *buf, int in_len,
1007 int out_len) 1100 int out_len)
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 08219fb3338b..c73b22a257fe 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -87,6 +87,7 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
87 [IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_pd, 87 [IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_pd,
88 [IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd, 88 [IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd,
89 [IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr, 89 [IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr,
90 [IB_USER_VERBS_CMD_REREG_MR] = ib_uverbs_rereg_mr,
90 [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr, 91 [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr,
91 [IB_USER_VERBS_CMD_ALLOC_MW] = ib_uverbs_alloc_mw, 92 [IB_USER_VERBS_CMD_ALLOC_MW] = ib_uverbs_alloc_mw,
92 [IB_USER_VERBS_CMD_DEALLOC_MW] = ib_uverbs_dealloc_mw, 93 [IB_USER_VERBS_CMD_DEALLOC_MW] = ib_uverbs_dealloc_mw,
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 7ccef342f724..ed44cc07a7b3 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1097,7 +1097,8 @@ struct ib_mr_attr {
1097enum ib_mr_rereg_flags { 1097enum ib_mr_rereg_flags {
1098 IB_MR_REREG_TRANS = 1, 1098 IB_MR_REREG_TRANS = 1,
1099 IB_MR_REREG_PD = (1<<1), 1099 IB_MR_REREG_PD = (1<<1),
1100 IB_MR_REREG_ACCESS = (1<<2) 1100 IB_MR_REREG_ACCESS = (1<<2),
1101 IB_MR_REREG_SUPPORTED = ((IB_MR_REREG_ACCESS << 1) - 1)
1101}; 1102};
1102 1103
1103/** 1104/**
@@ -1547,6 +1548,13 @@ struct ib_device {
1547 u64 virt_addr, 1548 u64 virt_addr,
1548 int mr_access_flags, 1549 int mr_access_flags,
1549 struct ib_udata *udata); 1550 struct ib_udata *udata);
1551 int (*rereg_user_mr)(struct ib_mr *mr,
1552 int flags,
1553 u64 start, u64 length,
1554 u64 virt_addr,
1555 int mr_access_flags,
1556 struct ib_pd *pd,
1557 struct ib_udata *udata);
1550 int (*query_mr)(struct ib_mr *mr, 1558 int (*query_mr)(struct ib_mr *mr,
1551 struct ib_mr_attr *mr_attr); 1559 struct ib_mr_attr *mr_attr);
1552 int (*dereg_mr)(struct ib_mr *mr); 1560 int (*dereg_mr)(struct ib_mr *mr);
diff --git a/include/uapi/rdma/ib_user_verbs.h b/include/uapi/rdma/ib_user_verbs.h
index cbfdd4ca9510..26daf55ff76e 100644
--- a/include/uapi/rdma/ib_user_verbs.h
+++ b/include/uapi/rdma/ib_user_verbs.h
@@ -276,6 +276,22 @@ struct ib_uverbs_reg_mr_resp {
276 __u32 rkey; 276 __u32 rkey;
277}; 277};
278 278
279struct ib_uverbs_rereg_mr {
280 __u64 response;
281 __u32 mr_handle;
282 __u32 flags;
283 __u64 start;
284 __u64 length;
285 __u64 hca_va;
286 __u32 pd_handle;
287 __u32 access_flags;
288};
289
290struct ib_uverbs_rereg_mr_resp {
291 __u32 lkey;
292 __u32 rkey;
293};
294
279struct ib_uverbs_dereg_mr { 295struct ib_uverbs_dereg_mr {
280 __u32 mr_handle; 296 __u32 mr_handle;
281}; 297};