diff options
author | Matan Barak <matanb@mellanox.com> | 2014-07-31 04:01:28 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2014-08-01 18:11:13 -0400 |
commit | 7e6edb9b2e0bcfb2a588db390c44d120213c57ae (patch) | |
tree | 9a8699e7cf72bc2c12574e3a2c46ddf10c542cd2 | |
parent | 64aa90f26c06e1cb2aacfb98a7d0eccfbd6c1a91 (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.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 93 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs_main.c | 1 | ||||
-rw-r--r-- | include/rdma/ib_verbs.h | 10 | ||||
-rw-r--r-- | include/uapi/rdma/ib_user_verbs.h | 16 |
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); | |||
221 | IB_UVERBS_DECLARE_CMD(alloc_pd); | 221 | IB_UVERBS_DECLARE_CMD(alloc_pd); |
222 | IB_UVERBS_DECLARE_CMD(dealloc_pd); | 222 | IB_UVERBS_DECLARE_CMD(dealloc_pd); |
223 | IB_UVERBS_DECLARE_CMD(reg_mr); | 223 | IB_UVERBS_DECLARE_CMD(reg_mr); |
224 | IB_UVERBS_DECLARE_CMD(rereg_mr); | ||
224 | IB_UVERBS_DECLARE_CMD(dereg_mr); | 225 | IB_UVERBS_DECLARE_CMD(dereg_mr); |
225 | IB_UVERBS_DECLARE_CMD(alloc_mw); | 226 | IB_UVERBS_DECLARE_CMD(alloc_mw); |
226 | IB_UVERBS_DECLARE_CMD(dealloc_mw); | 227 | IB_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 | ||
1005 | ssize_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 | |||
1087 | put_uobj_pd: | ||
1088 | if (cmd.flags & IB_MR_REREG_PD) | ||
1089 | put_pd_read(pd); | ||
1090 | |||
1091 | put_uobjs: | ||
1092 | |||
1093 | put_uobj_write(mr->uobject); | ||
1094 | |||
1095 | return ret; | ||
1096 | } | ||
1097 | |||
1005 | ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, | 1098 | ssize_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 { | |||
1097 | enum ib_mr_rereg_flags { | 1097 | enum 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 | ||
279 | struct 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 | |||
290 | struct ib_uverbs_rereg_mr_resp { | ||
291 | __u32 lkey; | ||
292 | __u32 rkey; | ||
293 | }; | ||
294 | |||
279 | struct ib_uverbs_dereg_mr { | 295 | struct ib_uverbs_dereg_mr { |
280 | __u32 mr_handle; | 296 | __u32 mr_handle; |
281 | }; | 297 | }; |