Commit d120c3c9 authored by Jason Gunthorpe's avatar Jason Gunthorpe

RDMA/uverbs: Convert the write interface to use uverbs_api

This organizes the write commands into objects and links them to the
uverbs_api data structure. The command path is reworked to use uapi
instead of its internal structures.

The command mask is moved from a runtime check to a registration time
check in the uapi.

Since the write interface does not have the object ID as part of the
command, the radix bins are converted into linear lists to support the
lookup.
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
parent 6884c6c4
...@@ -182,5 +182,26 @@ extern const struct uapi_definition uverbs_def_obj_dm[]; ...@@ -182,5 +182,26 @@ extern const struct uapi_definition uverbs_def_obj_dm[];
extern const struct uapi_definition uverbs_def_obj_flow_action[]; extern const struct uapi_definition uverbs_def_obj_flow_action[];
extern const struct uapi_definition uverbs_def_obj_intf[]; extern const struct uapi_definition uverbs_def_obj_intf[];
extern const struct uapi_definition uverbs_def_obj_mr[]; extern const struct uapi_definition uverbs_def_obj_mr[];
extern const struct uapi_definition uverbs_def_write_intf[];
static inline const struct uverbs_api_write_method *
uapi_get_method(const struct uverbs_api *uapi, u32 command)
{
u32 cmd_idx = command & IB_USER_VERBS_CMD_COMMAND_MASK;
if (command & ~(u32)(IB_USER_VERBS_CMD_FLAG_EXTENDED |
IB_USER_VERBS_CMD_COMMAND_MASK))
return ERR_PTR(-EINVAL);
if (command & IB_USER_VERBS_CMD_FLAG_EXTENDED) {
if (cmd_idx >= uapi->num_write_ex)
return ERR_PTR(-EOPNOTSUPP);
return uapi->write_ex_methods[cmd_idx];
}
if (cmd_idx >= uapi->num_write)
return ERR_PTR(-EOPNOTSUPP);
return uapi->write_methods[cmd_idx];
}
#endif /* RDMA_CORE_H */ #endif /* RDMA_CORE_H */
...@@ -161,9 +161,6 @@ struct ib_uverbs_file { ...@@ -161,9 +161,6 @@ struct ib_uverbs_file {
struct mutex umap_lock; struct mutex umap_lock;
struct list_head umaps; struct list_head umaps;
u64 uverbs_cmd_mask;
u64 uverbs_ex_cmd_mask;
struct idr idr; struct idr idr;
/* spinlock protects write access to idr */ /* spinlock protects write access to idr */
spinlock_t idr_lock; spinlock_t idr_lock;
......
...@@ -4126,3 +4126,135 @@ int ib_uverbs_ex_modify_cq(struct ib_uverbs_file *file, ...@@ -4126,3 +4126,135 @@ int ib_uverbs_ex_modify_cq(struct ib_uverbs_file *file,
return ret; return ret;
} }
const struct uapi_definition uverbs_def_write_intf[] = {
DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_AH,
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_AH,
ib_uverbs_create_ah),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_AH,
ib_uverbs_destroy_ah)),
DECLARE_UVERBS_OBJECT(
UVERBS_OBJECT_COMP_CHANNEL,
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL,
ib_uverbs_create_comp_channel)),
DECLARE_UVERBS_OBJECT(
UVERBS_OBJECT_CQ,
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_CQ,
ib_uverbs_create_cq),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_CQ,
ib_uverbs_destroy_cq),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POLL_CQ,
ib_uverbs_poll_cq),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REQ_NOTIFY_CQ,
ib_uverbs_req_notify_cq),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_RESIZE_CQ,
ib_uverbs_resize_cq),
DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_CQ,
ib_uverbs_ex_create_cq),
DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_MODIFY_CQ,
ib_uverbs_ex_modify_cq)),
DECLARE_UVERBS_OBJECT(
UVERBS_OBJECT_DEVICE,
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_GET_CONTEXT,
ib_uverbs_get_context),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_DEVICE,
ib_uverbs_query_device),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_PORT,
ib_uverbs_query_port),
DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_QUERY_DEVICE,
ib_uverbs_ex_query_device)),
DECLARE_UVERBS_OBJECT(
UVERBS_OBJECT_FLOW,
DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_FLOW,
ib_uverbs_ex_create_flow),
DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_DESTROY_FLOW,
ib_uverbs_ex_destroy_flow)),
DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_MR,
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEREG_MR,
ib_uverbs_dereg_mr),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REG_MR,
ib_uverbs_reg_mr),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REREG_MR,
ib_uverbs_rereg_mr)),
DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_MW,
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ALLOC_MW,
ib_uverbs_alloc_mw),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEALLOC_MW,
ib_uverbs_dealloc_mw)),
DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_PD,
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ALLOC_PD,
ib_uverbs_alloc_pd),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEALLOC_PD,
ib_uverbs_dealloc_pd)),
DECLARE_UVERBS_OBJECT(
UVERBS_OBJECT_QP,
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ATTACH_MCAST,
ib_uverbs_attach_mcast),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_QP,
ib_uverbs_create_qp),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_QP,
ib_uverbs_destroy_qp),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DETACH_MCAST,
ib_uverbs_detach_mcast),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_MODIFY_QP,
ib_uverbs_modify_qp),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POST_RECV,
ib_uverbs_post_recv),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POST_SEND,
ib_uverbs_post_send),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_QP,
ib_uverbs_query_qp),
DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_QP,
ib_uverbs_ex_create_qp),
DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_MODIFY_QP,
ib_uverbs_ex_modify_qp)),
DECLARE_UVERBS_OBJECT(
UVERBS_OBJECT_RWQ_IND_TBL,
DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL,
ib_uverbs_ex_create_rwq_ind_table),
DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL,
ib_uverbs_ex_destroy_rwq_ind_table)),
DECLARE_UVERBS_OBJECT(
UVERBS_OBJECT_WQ,
DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_WQ,
ib_uverbs_ex_create_wq),
DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_DESTROY_WQ,
ib_uverbs_ex_destroy_wq),
DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_MODIFY_WQ,
ib_uverbs_ex_modify_wq)),
DECLARE_UVERBS_OBJECT(
UVERBS_OBJECT_SRQ,
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_SRQ,
ib_uverbs_create_srq),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_XSRQ,
ib_uverbs_create_xsrq),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_SRQ,
ib_uverbs_destroy_srq),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_MODIFY_SRQ,
ib_uverbs_modify_srq),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POST_SRQ_RECV,
ib_uverbs_post_srq_recv),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_SRQ,
ib_uverbs_query_srq)),
DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_XRCD,
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CLOSE_XRCD,
ib_uverbs_close_xrcd),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_OPEN_QP,
ib_uverbs_open_qp),
DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_OPEN_XRCD,
ib_uverbs_open_xrcd)),
{},
};
...@@ -74,64 +74,6 @@ static dev_t dynamic_uverbs_dev; ...@@ -74,64 +74,6 @@ static dev_t dynamic_uverbs_dev;
static struct class *uverbs_class; static struct class *uverbs_class;
static DEFINE_IDA(uverbs_ida); static DEFINE_IDA(uverbs_ida);
static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len) = {
[IB_USER_VERBS_CMD_GET_CONTEXT] = ib_uverbs_get_context,
[IB_USER_VERBS_CMD_QUERY_DEVICE] = ib_uverbs_query_device,
[IB_USER_VERBS_CMD_QUERY_PORT] = ib_uverbs_query_port,
[IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_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_REREG_MR] = ib_uverbs_rereg_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_DEALLOC_MW] = ib_uverbs_dealloc_mw,
[IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel,
[IB_USER_VERBS_CMD_CREATE_CQ] = ib_uverbs_create_cq,
[IB_USER_VERBS_CMD_RESIZE_CQ] = ib_uverbs_resize_cq,
[IB_USER_VERBS_CMD_POLL_CQ] = ib_uverbs_poll_cq,
[IB_USER_VERBS_CMD_REQ_NOTIFY_CQ] = ib_uverbs_req_notify_cq,
[IB_USER_VERBS_CMD_DESTROY_CQ] = ib_uverbs_destroy_cq,
[IB_USER_VERBS_CMD_CREATE_QP] = ib_uverbs_create_qp,
[IB_USER_VERBS_CMD_QUERY_QP] = ib_uverbs_query_qp,
[IB_USER_VERBS_CMD_MODIFY_QP] = ib_uverbs_modify_qp,
[IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp,
[IB_USER_VERBS_CMD_POST_SEND] = ib_uverbs_post_send,
[IB_USER_VERBS_CMD_POST_RECV] = ib_uverbs_post_recv,
[IB_USER_VERBS_CMD_POST_SRQ_RECV] = ib_uverbs_post_srq_recv,
[IB_USER_VERBS_CMD_CREATE_AH] = ib_uverbs_create_ah,
[IB_USER_VERBS_CMD_DESTROY_AH] = ib_uverbs_destroy_ah,
[IB_USER_VERBS_CMD_ATTACH_MCAST] = ib_uverbs_attach_mcast,
[IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast,
[IB_USER_VERBS_CMD_CREATE_SRQ] = ib_uverbs_create_srq,
[IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq,
[IB_USER_VERBS_CMD_QUERY_SRQ] = ib_uverbs_query_srq,
[IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq,
[IB_USER_VERBS_CMD_OPEN_XRCD] = ib_uverbs_open_xrcd,
[IB_USER_VERBS_CMD_CLOSE_XRCD] = ib_uverbs_close_xrcd,
[IB_USER_VERBS_CMD_CREATE_XSRQ] = ib_uverbs_create_xsrq,
[IB_USER_VERBS_CMD_OPEN_QP] = ib_uverbs_open_qp,
};
static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file,
struct ib_udata *ucore,
struct ib_udata *uhw) = {
[IB_USER_VERBS_EX_CMD_CREATE_FLOW] = ib_uverbs_ex_create_flow,
[IB_USER_VERBS_EX_CMD_DESTROY_FLOW] = ib_uverbs_ex_destroy_flow,
[IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device,
[IB_USER_VERBS_EX_CMD_CREATE_CQ] = ib_uverbs_ex_create_cq,
[IB_USER_VERBS_EX_CMD_CREATE_QP] = ib_uverbs_ex_create_qp,
[IB_USER_VERBS_EX_CMD_CREATE_WQ] = ib_uverbs_ex_create_wq,
[IB_USER_VERBS_EX_CMD_MODIFY_WQ] = ib_uverbs_ex_modify_wq,
[IB_USER_VERBS_EX_CMD_DESTROY_WQ] = ib_uverbs_ex_destroy_wq,
[IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL] = ib_uverbs_ex_create_rwq_ind_table,
[IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL] = ib_uverbs_ex_destroy_rwq_ind_table,
[IB_USER_VERBS_EX_CMD_MODIFY_QP] = ib_uverbs_ex_modify_qp,
[IB_USER_VERBS_EX_CMD_MODIFY_CQ] = ib_uverbs_ex_modify_cq,
};
static void ib_uverbs_add_one(struct ib_device *device); static void ib_uverbs_add_one(struct ib_device *device);
static void ib_uverbs_remove_one(struct ib_device *device, void *client_data); static void ib_uverbs_remove_one(struct ib_device *device, void *client_data);
...@@ -646,41 +588,6 @@ struct file *ib_uverbs_alloc_async_event_file(struct ib_uverbs_file *uverbs_file ...@@ -646,41 +588,6 @@ struct file *ib_uverbs_alloc_async_event_file(struct ib_uverbs_file *uverbs_file
return filp; return filp;
} }
static bool verify_command_mask(struct ib_uverbs_file *ufile, u32 command,
bool extended)
{
if (!extended)
return ufile->uverbs_cmd_mask & BIT_ULL(command);
return ufile->uverbs_ex_cmd_mask & BIT_ULL(command);
}
static bool verify_command_idx(u32 command, bool extended)
{
if (extended)
return command < ARRAY_SIZE(uverbs_ex_cmd_table) &&
uverbs_ex_cmd_table[command];
return command < ARRAY_SIZE(uverbs_cmd_table) &&
uverbs_cmd_table[command];
}
static ssize_t process_hdr(struct ib_uverbs_cmd_hdr *hdr,
u32 *command, bool *extended)
{
if (hdr->command & ~(u32)(IB_USER_VERBS_CMD_FLAG_EXTENDED |
IB_USER_VERBS_CMD_COMMAND_MASK))
return -EINVAL;
*command = hdr->command & IB_USER_VERBS_CMD_COMMAND_MASK;
*extended = hdr->command & IB_USER_VERBS_CMD_FLAG_EXTENDED;
if (!verify_command_idx(*command, *extended))
return -EOPNOTSUPP;
return 0;
}
static ssize_t verify_hdr(struct ib_uverbs_cmd_hdr *hdr, static ssize_t verify_hdr(struct ib_uverbs_cmd_hdr *hdr,
struct ib_uverbs_ex_cmd_hdr *ex_hdr, struct ib_uverbs_ex_cmd_hdr *ex_hdr,
size_t count, bool extended) size_t count, bool extended)
...@@ -721,11 +628,11 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, ...@@ -721,11 +628,11 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
size_t count, loff_t *pos) size_t count, loff_t *pos)
{ {
struct ib_uverbs_file *file = filp->private_data; struct ib_uverbs_file *file = filp->private_data;
const struct uverbs_api_write_method *method_elm;
struct uverbs_api *uapi = file->device->uapi;
struct ib_uverbs_ex_cmd_hdr ex_hdr; struct ib_uverbs_ex_cmd_hdr ex_hdr;
struct ib_uverbs_cmd_hdr hdr; struct ib_uverbs_cmd_hdr hdr;
bool extended;
int srcu_key; int srcu_key;
u32 command;
ssize_t ret; ssize_t ret;
if (!ib_safe_file_access(filp)) { if (!ib_safe_file_access(filp)) {
...@@ -740,33 +647,27 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, ...@@ -740,33 +647,27 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
if (copy_from_user(&hdr, buf, sizeof(hdr))) if (copy_from_user(&hdr, buf, sizeof(hdr)))
return -EFAULT; return -EFAULT;
ret = process_hdr(&hdr, &command, &extended); method_elm = uapi_get_method(uapi, hdr.command);
if (ret) if (IS_ERR(method_elm))
return ret; return PTR_ERR(method_elm);
if (extended) { if (method_elm->is_ex) {
if (count < (sizeof(hdr) + sizeof(ex_hdr))) if (count < (sizeof(hdr) + sizeof(ex_hdr)))
return -EINVAL; return -EINVAL;
if (copy_from_user(&ex_hdr, buf + sizeof(hdr), sizeof(ex_hdr))) if (copy_from_user(&ex_hdr, buf + sizeof(hdr), sizeof(ex_hdr)))
return -EFAULT; return -EFAULT;
} }
ret = verify_hdr(&hdr, &ex_hdr, count, extended); ret = verify_hdr(&hdr, &ex_hdr, count, method_elm->is_ex);
if (ret) if (ret)
return ret; return ret;
srcu_key = srcu_read_lock(&file->device->disassociate_srcu); srcu_key = srcu_read_lock(&file->device->disassociate_srcu);
if (!verify_command_mask(file, command, extended)) {
ret = -EOPNOTSUPP;
goto out;
}
buf += sizeof(hdr); buf += sizeof(hdr);
if (!extended) { if (!method_elm->is_ex) {
ret = uverbs_cmd_table[command](file, buf, ret = method_elm->handler(file, buf, hdr.in_words * 4,
hdr.in_words * 4,
hdr.out_words * 4); hdr.out_words * 4);
} else { } else {
struct ib_udata ucore; struct ib_udata ucore;
...@@ -784,11 +685,10 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, ...@@ -784,11 +685,10 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
ex_hdr.provider_in_words * 8, ex_hdr.provider_in_words * 8,
ex_hdr.provider_out_words * 8); ex_hdr.provider_out_words * 8);
ret = uverbs_ex_cmd_table[command](file, &ucore, &uhw); ret = method_elm->handler_ex(file, &ucore, &uhw);
ret = (ret) ? : count; ret = (ret) ? : count;
} }
out:
srcu_read_unlock(&file->device->disassociate_srcu, srcu_key); srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
return ret; return ret;
} }
...@@ -1102,9 +1002,6 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) ...@@ -1102,9 +1002,6 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
mutex_unlock(&dev->lists_mutex); mutex_unlock(&dev->lists_mutex);
srcu_read_unlock(&dev->disassociate_srcu, srcu_key); srcu_read_unlock(&dev->disassociate_srcu, srcu_key);
file->uverbs_cmd_mask = ib_dev->uverbs_cmd_mask;
file->uverbs_ex_cmd_mask = ib_dev->uverbs_ex_cmd_mask;
setup_ufile_idr_uobject(file); setup_ufile_idr_uobject(file);
return nonseekable_open(inode, filp); return nonseekable_open(inode, filp);
......
...@@ -587,6 +587,7 @@ static const struct uapi_definition uverbs_core_api[] = { ...@@ -587,6 +587,7 @@ static const struct uapi_definition uverbs_core_api[] = {
UAPI_DEF_CHAIN(uverbs_def_obj_flow_action), UAPI_DEF_CHAIN(uverbs_def_obj_flow_action),
UAPI_DEF_CHAIN(uverbs_def_obj_intf), UAPI_DEF_CHAIN(uverbs_def_obj_intf),
UAPI_DEF_CHAIN(uverbs_def_obj_mr), UAPI_DEF_CHAIN(uverbs_def_obj_mr),
UAPI_DEF_CHAIN(uverbs_def_write_intf),
{}, {},
}; };
......
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