net/mlx5: support flow counters using devx
[dpdk.git] / drivers / net / mlx5 / mlx5_devx_cmds.c
1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright 2018 Mellanox Technologies, Ltd */
3
4 #include <rte_flow_driver.h>
5
6 #include "mlx5.h"
7 #include "mlx5_glue.h"
8 #include "mlx5_prm.h"
9
10 /**
11  * Allocate flow counters via devx interface.
12  *
13  * @param[in] ctx
14  *   ibv contexts returned from mlx5dv_open_device.
15  * @param dcs
16  *   Pointer to counters properties structure to be filled by the routine.
17  *
18  * @return
19  *   0 on success, a negative value otherwise.
20  */
21 int mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx,
22                                      struct mlx5_devx_counter_set *dcs)
23 {
24         uint32_t in[MLX5_ST_SZ_DW(alloc_flow_counter_in)]   = {0};
25         uint32_t out[MLX5_ST_SZ_DW(alloc_flow_counter_out)] = {0};
26         int status, syndrome;
27
28         MLX5_SET(alloc_flow_counter_in, in, opcode,
29                  MLX5_CMD_OP_ALLOC_FLOW_COUNTER);
30         dcs->obj = mlx5_glue->devx_obj_create(ctx, in,
31                                               sizeof(in), out, sizeof(out));
32         if (!dcs->obj)
33                 return -errno;
34         status = MLX5_GET(query_flow_counter_out, out, status);
35         syndrome = MLX5_GET(query_flow_counter_out, out, syndrome);
36         if (status) {
37                 DRV_LOG(DEBUG, "Failed to create devx counters, "
38                         "status %x, syndrome %x", status, syndrome);
39                 return -1;
40         }
41         dcs->id = MLX5_GET(alloc_flow_counter_out,
42                            out, flow_counter_id);
43         return 0;
44 }
45
46 /**
47  * Free flow counters obtained via devx interface.
48  *
49  * @param[in] obj
50  *   devx object that was obtained from mlx5_devx_cmd_fc_alloc.
51  *
52  * @return
53  *   0 on success, a negative value otherwise.
54  */
55 int mlx5_devx_cmd_flow_counter_free(struct mlx5dv_devx_obj *obj)
56 {
57         return mlx5_glue->devx_obj_destroy(obj);
58 }
59
60 /**
61  * Query flow counters values.
62  *
63  * @param[in] dcs
64  *   devx object that was obtained from mlx5_devx_cmd_fc_alloc.
65  * @param[in] clear
66  *   Whether hardware should clear the counters after the query or not.
67  *  @param pkts
68  *   The number of packets that matched the flow.
69  *  @param bytes
70  *    The number of bytes that matched the flow.
71  *
72  * @return
73  *   0 on success, a negative value otherwise.
74  */
75 int
76 mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_counter_set *dcs,
77                                  int clear __rte_unused,
78                                  uint64_t *pkts, uint64_t *bytes)
79 {
80         uint32_t out[MLX5_ST_SZ_BYTES(query_flow_counter_out) +
81                 MLX5_ST_SZ_BYTES(traffic_counter)]   = {0};
82         uint32_t in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {0};
83         void *stats;
84         int status, syndrome, rc;
85
86         MLX5_SET(query_flow_counter_in, in, opcode,
87                  MLX5_CMD_OP_QUERY_FLOW_COUNTER);
88         MLX5_SET(query_flow_counter_in, in, op_mod, 0);
89         MLX5_SET(query_flow_counter_in, in, flow_counter_id, dcs->id);
90         rc = mlx5_glue->devx_obj_query(dcs->obj,
91                                        in, sizeof(in), out, sizeof(out));
92         if (rc)
93                 return rc;
94         status = MLX5_GET(query_flow_counter_out, out, status);
95         syndrome = MLX5_GET(query_flow_counter_out, out, syndrome);
96         if (status) {
97                 DRV_LOG(DEBUG, "Failed to query devx counters, "
98                         "id %d, status %x, syndrome = %x",
99                         status, syndrome, dcs->id);
100                 return -1;
101         }
102         stats = MLX5_ADDR_OF(query_flow_counter_out,
103                              out, flow_statistics);
104         *pkts = MLX5_GET64(traffic_counter, stats, packets);
105         *bytes = MLX5_GET64(traffic_counter, stats, octets);
106         return 0;
107 }