+
+/**
+ * Create general object of type FLOW_HIT_ASO using DevX API.
+ *
+ * @param[in] ctx
+ * Context returned from mlx5 open_device() glue function.
+ * @param [in] pd
+ * PD value to associate the FLOW_HIT_ASO object with.
+ *
+ * @return
+ * The DevX object created, NULL otherwise and rte_errno is set.
+ */
+struct mlx5_devx_obj *
+mlx5_devx_cmd_create_flow_hit_aso_obj(void *ctx, uint32_t pd)
+{
+ uint32_t in[MLX5_ST_SZ_DW(create_flow_hit_aso_in)] = {0};
+ uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
+ struct mlx5_devx_obj *flow_hit_aso_obj = NULL;
+ void *ptr = NULL;
+
+ flow_hit_aso_obj = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*flow_hit_aso_obj),
+ 0, SOCKET_ID_ANY);
+ if (!flow_hit_aso_obj) {
+ DRV_LOG(ERR, "Failed to allocate FLOW_HIT_ASO object data");
+ rte_errno = ENOMEM;
+ return NULL;
+ }
+ ptr = MLX5_ADDR_OF(create_flow_hit_aso_in, in, hdr);
+ MLX5_SET(general_obj_in_cmd_hdr, ptr, opcode,
+ MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
+ MLX5_SET(general_obj_in_cmd_hdr, ptr, obj_type,
+ MLX5_GENERAL_OBJ_TYPE_FLOW_HIT_ASO);
+ ptr = MLX5_ADDR_OF(create_flow_hit_aso_in, in, flow_hit_aso);
+ MLX5_SET(flow_hit_aso, ptr, access_pd, pd);
+ flow_hit_aso_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in),
+ out, sizeof(out));
+ if (!flow_hit_aso_obj->obj) {
+ rte_errno = errno;
+ DRV_LOG(ERR, "Failed to create FLOW_HIT_ASO obj using DevX.");
+ mlx5_free(flow_hit_aso_obj);
+ return NULL;
+ }
+ flow_hit_aso_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
+ return flow_hit_aso_obj;
+}
+
+/*
+ * Create PD using DevX API.
+ *
+ * @param[in] ctx
+ * Context returned from mlx5 open_device() glue function.
+ *
+ * @return
+ * The DevX object created, NULL otherwise and rte_errno is set.
+ */
+struct mlx5_devx_obj *
+mlx5_devx_cmd_alloc_pd(void *ctx)
+{
+ struct mlx5_devx_obj *ppd =
+ mlx5_malloc(MLX5_MEM_ZERO, sizeof(*ppd), 0, SOCKET_ID_ANY);
+ u32 in[MLX5_ST_SZ_DW(alloc_pd_in)] = {0};
+ u32 out[MLX5_ST_SZ_DW(alloc_pd_out)] = {0};
+
+ if (!ppd) {
+ DRV_LOG(ERR, "Failed to allocate PD data.");
+ rte_errno = ENOMEM;
+ return NULL;
+ }
+ MLX5_SET(alloc_pd_in, in, opcode, MLX5_CMD_OP_ALLOC_PD);
+ ppd->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in),
+ out, sizeof(out));
+ if (!ppd->obj) {
+ mlx5_free(ppd);
+ DRV_LOG(ERR, "Failed to allocate PD Obj using DevX.");
+ rte_errno = errno;
+ return NULL;
+ }
+ ppd->id = MLX5_GET(alloc_pd_out, out, pd);
+ return ppd;
+}
+
+/**
+ * Create general object of type GENEVE TLV option using DevX API.
+ *
+ * @param[in] ctx
+ * Context returned from mlx5 open_device() glue function.
+ * @param [in] class
+ * TLV option variable value of class
+ * @param [in] type
+ * TLV option variable value of type
+ * @param [in] len
+ * TLV option variable value of len
+ *
+ * @return
+ * The DevX object created, NULL otherwise and rte_errno is set.
+ */
+struct mlx5_devx_obj *
+mlx5_devx_cmd_create_geneve_tlv_option(void *ctx,
+ uint16_t class, uint8_t type, uint8_t len)
+{
+ uint32_t in[MLX5_ST_SZ_DW(create_geneve_tlv_option_in)] = {0};
+ uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
+ struct mlx5_devx_obj *geneve_tlv_opt_obj = mlx5_malloc(MLX5_MEM_ZERO,
+ sizeof(*geneve_tlv_opt_obj),
+ 0, SOCKET_ID_ANY);
+
+ if (!geneve_tlv_opt_obj) {
+ DRV_LOG(ERR, "Failed to allocate geneve tlv option object.");
+ rte_errno = ENOMEM;
+ return NULL;
+ }
+ void *hdr = MLX5_ADDR_OF(create_geneve_tlv_option_in, in, hdr);
+ void *opt = MLX5_ADDR_OF(create_geneve_tlv_option_in, in,
+ geneve_tlv_opt);
+ MLX5_SET(general_obj_in_cmd_hdr, hdr, opcode,
+ MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
+ MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_type,
+ MLX5_OBJ_TYPE_GENEVE_TLV_OPT);
+ MLX5_SET(geneve_tlv_option, opt, option_class,
+ rte_be_to_cpu_16(class));
+ MLX5_SET(geneve_tlv_option, opt, option_type, type);
+ MLX5_SET(geneve_tlv_option, opt, option_data_length, len);
+ geneve_tlv_opt_obj->obj = mlx5_glue->devx_obj_create(ctx, in,
+ sizeof(in), out, sizeof(out));
+ if (!geneve_tlv_opt_obj->obj) {
+ rte_errno = errno;
+ DRV_LOG(ERR, "Failed to create Geneve tlv option "
+ "Obj using DevX.");
+ mlx5_free(geneve_tlv_opt_obj);
+ return NULL;
+ }
+ geneve_tlv_opt_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
+ return geneve_tlv_opt_obj;
+}
+
+int
+mlx5_devx_cmd_wq_query(void *wq, uint32_t *counter_set_id)
+{
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+ uint32_t in[MLX5_ST_SZ_DW(query_rq_in)] = {0};
+ uint32_t out[MLX5_ST_SZ_DW(query_rq_out)] = {0};
+ int rc;
+ void *rq_ctx;
+
+ MLX5_SET(query_rq_in, in, opcode, MLX5_CMD_OP_QUERY_RQ);
+ MLX5_SET(query_rq_in, in, rqn, ((struct ibv_wq *)wq)->wq_num);
+ rc = mlx5_glue->devx_wq_query(wq, in, sizeof(in), out, sizeof(out));
+ if (rc) {
+ rte_errno = errno;
+ DRV_LOG(ERR, "Failed to query WQ counter set ID using DevX - "
+ "rc = %d, errno = %d.", rc, errno);
+ return -rc;
+ };
+ rq_ctx = MLX5_ADDR_OF(query_rq_out, out, rq_context);
+ *counter_set_id = MLX5_GET(rqc, rq_ctx, counter_set_id);
+ return 0;
+#else
+ (void)wq;
+ (void)counter_set_id;
+ return -ENOTSUP;
+#endif
+}
+
+/*
+ * Allocate queue counters via devx interface.
+ *
+ * @param[in] ctx
+ * Context returned from mlx5 open_device() glue function.
+ *
+ * @return
+ * Pointer to counter object on success, a NULL value otherwise and
+ * rte_errno is set.
+ */
+struct mlx5_devx_obj *
+mlx5_devx_cmd_queue_counter_alloc(void *ctx)
+{
+ struct mlx5_devx_obj *dcs = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*dcs), 0,
+ SOCKET_ID_ANY);
+ uint32_t in[MLX5_ST_SZ_DW(alloc_q_counter_in)] = {0};
+ uint32_t out[MLX5_ST_SZ_DW(alloc_q_counter_out)] = {0};
+
+ if (!dcs) {
+ rte_errno = ENOMEM;
+ return NULL;
+ }
+ MLX5_SET(alloc_q_counter_in, in, opcode, MLX5_CMD_OP_ALLOC_Q_COUNTER);
+ dcs->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out,
+ sizeof(out));
+ if (!dcs->obj) {
+ DRV_LOG(DEBUG, "Can't allocate q counter set by DevX - error "
+ "%d.", errno);
+ rte_errno = errno;
+ mlx5_free(dcs);
+ return NULL;
+ }
+ dcs->id = MLX5_GET(alloc_q_counter_out, out, counter_set_id);
+ return dcs;
+}
+
+/**
+ * Query queue counters values.
+ *
+ * @param[in] dcs
+ * devx object of the queue counter set.
+ * @param[in] clear
+ * Whether hardware should clear the counters after the query or not.
+ * @param[out] out_of_buffers
+ * Number of dropped occurred due to lack of WQE for the associated QPs/RQs.
+ *
+ * @return
+ * 0 on success, a negative value otherwise.
+ */
+int
+mlx5_devx_cmd_queue_counter_query(struct mlx5_devx_obj *dcs, int clear,
+ uint32_t *out_of_buffers)
+{
+ uint32_t out[MLX5_ST_SZ_BYTES(query_q_counter_out)] = {0};
+ uint32_t in[MLX5_ST_SZ_DW(query_q_counter_in)] = {0};
+ int rc;
+
+ MLX5_SET(query_q_counter_in, in, opcode,
+ MLX5_CMD_OP_QUERY_Q_COUNTER);
+ MLX5_SET(query_q_counter_in, in, op_mod, 0);
+ MLX5_SET(query_q_counter_in, in, counter_set_id, dcs->id);
+ MLX5_SET(query_q_counter_in, in, clear, !!clear);
+ rc = mlx5_glue->devx_obj_query(dcs->obj, in, sizeof(in), out,
+ sizeof(out));
+ if (rc) {
+ DRV_LOG(ERR, "Failed to query devx q counter set - rc %d", rc);
+ rte_errno = rc;
+ return -rc;
+ }
+ *out_of_buffers = MLX5_GET(query_q_counter_out, out, out_of_buffer);
+ return 0;
+}