@@ -307,5 +307,6 @@ struct ib_uverbs_flow_spec {
IB_UVERBS_DECLARE_EX_CMD(destroy_rwq_ind_table);
IB_UVERBS_DECLARE_EX_CMD(modify_qp);
IB_UVERBS_DECLARE_EX_CMD(modify_cq);
+IB_UVERBS_DECLARE_EX_CMD(describe_counter_set);
#endif /* UVERBS_H */
@@ -3909,3 +3909,78 @@ int ib_uverbs_ex_modify_cq(struct ib_uverbs_file *file,
return ret;
}
+
+int ib_uverbs_ex_describe_counter_set(struct ib_uverbs_file *file,
+ struct ib_device *ib_dev,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ struct ib_uverbs_ex_describe_counter_set cmd = {};
+ struct ib_uverbs_ex_describe_counter_set_resp resp = {};
+ struct ib_counter_set_describe_attr cs_describe_attr = {};
+ size_t required_resp_len;
+ size_t required_cmd_sz;
+ u16 buff_len;
+ int ret = 0;
+
+ required_cmd_sz = offsetof(typeof(cmd), cs_id) +
+ sizeof(cmd.cs_id);
+ 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)
+ return -EOPNOTSUPP;
+
+ if (cmd.counters_names_resp) {
+ /* Prevent memory allocation rather than max expected size */
+ buff_len = min_t(u16, cmd.counters_names_max,
+ MAX_COUNTER_SET_BUFF_LEN);
+ cs_describe_attr.counters_names_buff =
+ kzalloc(buff_len, GFP_KERNEL);
+ if (!cs_describe_attr.counters_names_buff)
+ return -ENOMEM;
+
+ cs_describe_attr.counters_names_len = buff_len;
+ }
+
+ ret = ib_dev->describe_counter_set(ib_dev, cmd.cs_id,
+ &cs_describe_attr, uhw);
+ if (ret)
+ goto err;
+
+ if (cmd.counters_names_resp) {
+ if (copy_to_user(u64_to_user_ptr(cmd.counters_names_resp),
+ cs_describe_attr.counters_names_buff,
+ cs_describe_attr.entries_count *
+ IB_COUNTER_NAME_LEN)) {
+ ret = -EFAULT;
+ goto err;
+ }
+ }
+
+ resp.num_of_cs = cs_describe_attr.num_of_cs;
+ resp.attributes = cs_describe_attr.attributes;
+ resp.counted_type = cs_describe_attr.counted_type;
+ resp.entries_count = cs_describe_attr.entries_count;
+ resp.response_length = required_resp_len;
+ ret = ib_copy_to_udata(ucore, &resp, resp.response_length);
+
+err:
+ kfree(cs_describe_attr.counters_names_buff);
+ return ret;
+}
@@ -129,6 +129,7 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file,
[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,
+ [IB_USER_VERBS_EX_CMD_DESCRIBE_COUNTER_SET] = ib_uverbs_ex_describe_counter_set,
};
static void ib_uverbs_add_one(struct ib_device *device);
@@ -101,7 +101,8 @@ enum {
IB_USER_VERBS_EX_CMD_DESTROY_WQ,
IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL,
IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL,
- IB_USER_VERBS_EX_CMD_MODIFY_CQ
+ IB_USER_VERBS_EX_CMD_MODIFY_CQ,
+ IB_USER_VERBS_EX_CMD_DESCRIBE_COUNTER_SET,
};
/*
@@ -1168,6 +1169,24 @@ struct ib_uverbs_ex_modify_cq {
__u32 comp_mask;
};
+#define MAX_COUNTER_SET_BUFF_LEN 4096
+struct ib_uverbs_ex_describe_counter_set {
+ __u64 counters_names_resp;
+ __u32 comp_mask;
+ __u16 counters_names_max;
+ __u16 cs_id;
+};
+
+struct ib_uverbs_ex_describe_counter_set_resp {
+ __u64 num_of_cs;
+ __u32 comp_mask;
+ __u32 response_length;
+ __u32 attributes;
+ __u8 counted_type;
+ __u8 entries_count;
+ __u16 reserved;
+};
+
#define IB_DEVICE_NAME_MAX 64
#endif /* IB_USER_VERBS_H */