@@ -308,5 +308,7 @@ struct ib_uverbs_flow_spec {
IB_UVERBS_DECLARE_EX_CMD(modify_qp);
IB_UVERBS_DECLARE_EX_CMD(modify_cq);
IB_UVERBS_DECLARE_EX_CMD(describe_counter_set);
+IB_UVERBS_DECLARE_EX_CMD(create_counter_set);
+IB_UVERBS_DECLARE_EX_CMD(destroy_counter_set);
#endif /* UVERBS_H */
@@ -3984,3 +3984,120 @@ int ib_uverbs_ex_describe_counter_set(struct ib_uverbs_file *file,
kfree(cs_describe_attr.counters_names_buff);
return ret;
}
+
+int ib_uverbs_ex_create_counter_set(struct ib_uverbs_file *file,
+ struct ib_device *ib_dev,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ struct ib_uverbs_ex_create_counter_set cmd = {};
+ struct ib_uverbs_ex_create_counter_set_resp resp = {};
+ struct ib_counter_set *cs;
+ struct ib_uobject *uobj;
+ size_t required_resp_len;
+ size_t required_cmd_sz;
+ int ret = 0;
+
+ required_cmd_sz = offsetof(typeof(cmd), reserved) +
+ sizeof(cmd.reserved);
+ required_resp_len = offsetof(typeof(resp), reserved) +
+ sizeof(resp.reserved);
+
+ if (ucore->inlen < required_cmd_sz)
+ return -EINVAL;
+
+ if (ucore->outlen < required_resp_len)
+ return -ENOSPC;
+
+ if (ucore->inlen > sizeof(cmd) &&
+ !ib_is_udata_cleared(ucore, sizeof(cmd),
+ ucore->inlen - sizeof(cmd)))
+ return -EOPNOTSUPP;
+
+ ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
+ if (ret)
+ return ret;
+
+ if (cmd.comp_mask || cmd.reserved)
+ return -EOPNOTSUPP;
+
+ uobj = uobj_alloc(uobj_get_type(counter_set), file->ucontext);
+ if (IS_ERR(uobj))
+ return PTR_ERR(uobj);
+
+ cs = ib_dev->create_counter_set(ib_dev, cmd.cs_id, uhw);
+ if (IS_ERR(cs)) {
+ ret = PTR_ERR(cs);
+ goto err_uobj;
+ }
+ uobj->object = cs;
+ cs->device = ib_dev;
+ cs->uobject = uobj;
+ cs->cs_id = cmd.cs_id;
+ atomic_set(&cs->usecnt, 0);
+ resp.cs_handle = uobj->id;
+ resp.response_length = required_resp_len;
+ ret = ib_copy_to_udata(ucore,
+ &resp, required_resp_len);
+ if (ret)
+ goto err_copy;
+
+ uobj_alloc_commit(uobj);
+
+ return 0;
+
+err_copy:
+ ib_destroy_counter_set(cs);
+err_uobj:
+ uobj_alloc_abort(uobj);
+ return ret;
+}
+
+int ib_uverbs_ex_destroy_counter_set(struct ib_uverbs_file *file,
+ struct ib_device *ib_dev,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ struct ib_uverbs_ex_destroy_counter_set cmd = {};
+ struct ib_uverbs_ex_destroy_counter_set_resp resp = {};
+ struct ib_uobject *uobj;
+ size_t required_resp_len;
+ size_t required_cmd_sz;
+ int ret;
+
+ required_cmd_sz = offsetof(typeof(cmd), cs_handle) +
+ sizeof(cmd.cs_handle);
+ required_resp_len = offsetof(typeof(resp), response_length) +
+ sizeof(resp.response_length);
+
+ if (ucore->inlen < required_cmd_sz)
+ return -EINVAL;
+
+ if (ucore->outlen < required_resp_len)
+ return -ENOSPC;
+
+ if (ucore->inlen > sizeof(cmd) &&
+ !ib_is_udata_cleared(ucore, sizeof(cmd),
+ ucore->inlen - sizeof(cmd)))
+ return -EOPNOTSUPP;
+
+ ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
+ if (ret)
+ return ret;
+
+ if (cmd.comp_mask)
+ return -EOPNOTSUPP;
+
+ uobj = uobj_get_write(uobj_get_type(counter_set),
+ cmd.cs_handle,
+ file->ucontext);
+ if (IS_ERR(uobj))
+ return PTR_ERR(uobj);
+
+ ret = uobj_remove_commit(uobj);
+ if (ret)
+ return ret;
+
+ resp.response_length = required_resp_len;
+ return ib_copy_to_udata(ucore, &resp, resp.response_length);
+}
@@ -130,6 +130,8 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file,
[IB_USER_VERBS_EX_CMD_MODIFY_QP] = ib_uverbs_ex_modify_qp,
[IB_USER_VERBS_EX_CMD_MODIFY_CQ] = ib_uverbs_ex_modify_cq,
[IB_USER_VERBS_EX_CMD_DESCRIBE_COUNTER_SET] = ib_uverbs_ex_describe_counter_set,
+ [IB_USER_VERBS_EX_CMD_CREATE_COUNTER_SET] = ib_uverbs_ex_create_counter_set,
+ [IB_USER_VERBS_EX_CMD_DESTROY_COUNTER_SET] = ib_uverbs_ex_destroy_counter_set,
};
static void ib_uverbs_add_one(struct ib_device *device);
@@ -190,6 +190,15 @@ static int uverbs_free_pd(struct ib_uobject *uobject,
return 0;
}
+static int uverbs_free_counter_set(struct ib_uobject *uobject,
+ enum rdma_remove_reason why)
+{
+ struct ib_counter_set *ib_cs =
+ (struct ib_counter_set *)(uobject->object);
+
+ return ib_destroy_counter_set(ib_cs);
+}
+
static int uverbs_hot_unplug_completion_event_file(struct ib_uobject_file *uobj_file,
enum rdma_remove_reason why)
{
@@ -435,6 +444,9 @@ static DECLARE_UVERBS_METHOD(
/* 2 is used in order to free the PD after MRs */
&UVERBS_TYPE_ALLOC_IDR(2, uverbs_free_pd));
+DECLARE_UVERBS_OBJECT(uverbs_object_counter_set, UVERBS_OBJECT_COUNTER_SET,
+ &UVERBS_TYPE_ALLOC_IDR(0, uverbs_free_counter_set));
+
DECLARE_UVERBS_OBJECT(uverbs_object_device, UVERBS_OBJECT_DEVICE, NULL);
DECLARE_UVERBS_OBJECT_TREE(uverbs_default_objects,
@@ -450,4 +462,5 @@ static DECLARE_UVERBS_METHOD(
&uverbs_object_flow,
&uverbs_object_wq,
&uverbs_object_rwq_ind_table,
- &uverbs_object_xrcd);
+ &uverbs_object_xrcd,
+ &uverbs_object_counter_set);
@@ -51,6 +51,7 @@
extern const struct uverbs_object_def uverbs_object_pd;
extern const struct uverbs_object_def uverbs_object_xrcd;
extern const struct uverbs_object_def uverbs_object_device;
+extern const struct uverbs_object_def uverbs_object_counter_set;
extern const struct uverbs_object_tree_def uverbs_default_objects;
static inline const struct uverbs_object_tree_def *uverbs_default_get_objects(void)
@@ -52,6 +52,7 @@ enum uverbs_default_objects {
UVERBS_OBJECT_XRCD,
UVERBS_OBJECT_RWQ_IND_TBL,
UVERBS_OBJECT_WQ,
+ UVERBS_OBJECT_COUNTER_SET,
UVERBS_OBJECT_LAST,
};
@@ -103,6 +103,8 @@ enum {
IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL,
IB_USER_VERBS_EX_CMD_MODIFY_CQ,
IB_USER_VERBS_EX_CMD_DESCRIBE_COUNTER_SET,
+ IB_USER_VERBS_EX_CMD_CREATE_COUNTER_SET,
+ IB_USER_VERBS_EX_CMD_DESTROY_COUNTER_SET,
};
/*
@@ -1187,6 +1189,29 @@ struct ib_uverbs_ex_describe_counter_set_resp {
__u16 reserved;
};
+struct ib_uverbs_ex_create_counter_set {
+ __u32 comp_mask;
+ __u16 cs_id;
+ __u16 reserved;
+};
+
+struct ib_uverbs_ex_create_counter_set_resp {
+ __u32 comp_mask;
+ __u32 response_length;
+ __u32 cs_handle;
+ __u32 reserved;
+};
+
+struct ib_uverbs_ex_destroy_counter_set {
+ __u32 comp_mask;
+ __u32 cs_handle;
+};
+
+struct ib_uverbs_ex_destroy_counter_set_resp {
+ __u32 comp_mask;
+ __u32 response_length;
+};
+
#define IB_DEVICE_NAME_MAX 64
#endif /* IB_USER_VERBS_H */