Commit 7e6edb9b authored by Matan Barak's avatar Matan Barak Committed by Roland Dreier

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: default avatarMatan Barak <matanb@mellanox.com>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 64aa90f2
...@@ -221,6 +221,7 @@ IB_UVERBS_DECLARE_CMD(query_port); ...@@ -221,6 +221,7 @@ IB_UVERBS_DECLARE_CMD(query_port);
IB_UVERBS_DECLARE_CMD(alloc_pd); IB_UVERBS_DECLARE_CMD(alloc_pd);
IB_UVERBS_DECLARE_CMD(dealloc_pd); IB_UVERBS_DECLARE_CMD(dealloc_pd);
IB_UVERBS_DECLARE_CMD(reg_mr); IB_UVERBS_DECLARE_CMD(reg_mr);
IB_UVERBS_DECLARE_CMD(rereg_mr);
IB_UVERBS_DECLARE_CMD(dereg_mr); IB_UVERBS_DECLARE_CMD(dereg_mr);
IB_UVERBS_DECLARE_CMD(alloc_mw); IB_UVERBS_DECLARE_CMD(alloc_mw);
IB_UVERBS_DECLARE_CMD(dealloc_mw); IB_UVERBS_DECLARE_CMD(dealloc_mw);
......
...@@ -1002,6 +1002,99 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, ...@@ -1002,6 +1002,99 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
return ret; return ret;
} }
ssize_t ib_uverbs_rereg_mr(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
{
struct ib_uverbs_rereg_mr cmd;
struct ib_uverbs_rereg_mr_resp resp;
struct ib_udata udata;
struct ib_pd *pd = NULL;
struct ib_mr *mr;
struct ib_pd *old_pd;
int ret;
struct ib_uobject *uobj;
if (out_len < sizeof(resp))
return -ENOSPC;
if (copy_from_user(&cmd, buf, sizeof(cmd)))
return -EFAULT;
INIT_UDATA(&udata, buf + sizeof(cmd),
(unsigned long) cmd.response + sizeof(resp),
in_len - sizeof(cmd), out_len - sizeof(resp));
if (cmd.flags & ~IB_MR_REREG_SUPPORTED || !cmd.flags)
return -EINVAL;
if ((cmd.flags & IB_MR_REREG_TRANS) &&
(!cmd.start || !cmd.hca_va || 0 >= cmd.length ||
(cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK)))
return -EINVAL;
uobj = idr_write_uobj(&ib_uverbs_mr_idr, cmd.mr_handle,
file->ucontext);
if (!uobj)
return -EINVAL;
mr = uobj->object;
if (cmd.flags & IB_MR_REREG_ACCESS) {
ret = ib_check_mr_access(cmd.access_flags);
if (ret)
goto put_uobjs;
}
if (cmd.flags & IB_MR_REREG_PD) {
pd = idr_read_pd(cmd.pd_handle, file->ucontext);
if (!pd) {
ret = -EINVAL;
goto put_uobjs;
}
}
if (atomic_read(&mr->usecnt)) {
ret = -EBUSY;
goto put_uobj_pd;
}
old_pd = mr->pd;
ret = mr->device->rereg_user_mr(mr, cmd.flags, cmd.start,
cmd.length, cmd.hca_va,
cmd.access_flags, pd, &udata);
if (!ret) {
if (cmd.flags & IB_MR_REREG_PD) {
atomic_inc(&pd->usecnt);
mr->pd = pd;
atomic_dec(&old_pd->usecnt);
}
} else {
goto put_uobj_pd;
}
memset(&resp, 0, sizeof(resp));
resp.lkey = mr->lkey;
resp.rkey = mr->rkey;
if (copy_to_user((void __user *)(unsigned long)cmd.response,
&resp, sizeof(resp)))
ret = -EFAULT;
else
ret = in_len;
put_uobj_pd:
if (cmd.flags & IB_MR_REREG_PD)
put_pd_read(pd);
put_uobjs:
put_uobj_write(mr->uobject);
return ret;
}
ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
const char __user *buf, int in_len, const char __user *buf, int in_len,
int out_len) int out_len)
......
...@@ -87,6 +87,7 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file, ...@@ -87,6 +87,7 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
[IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_pd, [IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_pd,
[IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd, [IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd,
[IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr, [IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr,
[IB_USER_VERBS_CMD_REREG_MR] = ib_uverbs_rereg_mr,
[IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr, [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr,
[IB_USER_VERBS_CMD_ALLOC_MW] = ib_uverbs_alloc_mw, [IB_USER_VERBS_CMD_ALLOC_MW] = ib_uverbs_alloc_mw,
[IB_USER_VERBS_CMD_DEALLOC_MW] = ib_uverbs_dealloc_mw, [IB_USER_VERBS_CMD_DEALLOC_MW] = ib_uverbs_dealloc_mw,
......
...@@ -1097,7 +1097,8 @@ struct ib_mr_attr { ...@@ -1097,7 +1097,8 @@ struct ib_mr_attr {
enum ib_mr_rereg_flags { enum ib_mr_rereg_flags {
IB_MR_REREG_TRANS = 1, IB_MR_REREG_TRANS = 1,
IB_MR_REREG_PD = (1<<1), IB_MR_REREG_PD = (1<<1),
IB_MR_REREG_ACCESS = (1<<2) IB_MR_REREG_ACCESS = (1<<2),
IB_MR_REREG_SUPPORTED = ((IB_MR_REREG_ACCESS << 1) - 1)
}; };
/** /**
...@@ -1547,6 +1548,13 @@ struct ib_device { ...@@ -1547,6 +1548,13 @@ struct ib_device {
u64 virt_addr, u64 virt_addr,
int mr_access_flags, int mr_access_flags,
struct ib_udata *udata); struct ib_udata *udata);
int (*rereg_user_mr)(struct ib_mr *mr,
int flags,
u64 start, u64 length,
u64 virt_addr,
int mr_access_flags,
struct ib_pd *pd,
struct ib_udata *udata);
int (*query_mr)(struct ib_mr *mr, int (*query_mr)(struct ib_mr *mr,
struct ib_mr_attr *mr_attr); struct ib_mr_attr *mr_attr);
int (*dereg_mr)(struct ib_mr *mr); int (*dereg_mr)(struct ib_mr *mr);
......
...@@ -276,6 +276,22 @@ struct ib_uverbs_reg_mr_resp { ...@@ -276,6 +276,22 @@ struct ib_uverbs_reg_mr_resp {
__u32 rkey; __u32 rkey;
}; };
struct ib_uverbs_rereg_mr {
__u64 response;
__u32 mr_handle;
__u32 flags;
__u64 start;
__u64 length;
__u64 hca_va;
__u32 pd_handle;
__u32 access_flags;
};
struct ib_uverbs_rereg_mr_resp {
__u32 lkey;
__u32 rkey;
};
struct ib_uverbs_dereg_mr { struct ib_uverbs_dereg_mr {
__u32 mr_handle; __u32 mr_handle;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment