net/enetc: reorder BDR structure
[dpdk.git] / drivers / event / dsw / dsw_xstats.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2019 Ericsson AB
3  */
4
5 #include "dsw_evdev.h"
6
7 #include <stdbool.h>
8 #include <string.h>
9
10 #include <rte_debug.h>
11
12 /* The high bits in the xstats id is used to store an additional
13  * parameter (beyond the queue or port id already in the xstats
14  * interface).
15  */
16 #define DSW_XSTATS_ID_PARAM_BITS (8)
17 #define DSW_XSTATS_ID_STAT_BITS                                 \
18         (sizeof(unsigned int)*CHAR_BIT - DSW_XSTATS_ID_PARAM_BITS)
19 #define DSW_XSTATS_ID_STAT_MASK ((1 << DSW_XSTATS_ID_STAT_BITS) - 1)
20
21 #define DSW_XSTATS_ID_GET_PARAM(id)             \
22         ((id)>>DSW_XSTATS_ID_STAT_BITS)
23
24 #define DSW_XSTATS_ID_GET_STAT(id)              \
25         ((id) & DSW_XSTATS_ID_STAT_MASK)
26
27 #define DSW_XSTATS_ID_CREATE(id, param_value)                   \
28         (((param_value) << DSW_XSTATS_ID_STAT_BITS) | id)
29
30 typedef
31 uint64_t (*dsw_xstats_dev_get_value_fn)(struct dsw_evdev *dsw);
32
33 struct dsw_xstat_dev {
34         const char *name;
35         dsw_xstats_dev_get_value_fn get_value_fn;
36 };
37
38 typedef
39 uint64_t (*dsw_xstats_port_get_value_fn)(struct dsw_evdev *dsw,
40                                          uint8_t port_id, uint8_t queue_id);
41
42 struct dsw_xstats_port {
43         const char *name_fmt;
44         dsw_xstats_port_get_value_fn get_value_fn;
45         bool per_queue;
46 };
47
48 static uint64_t
49 dsw_xstats_dev_credits_on_loan(struct dsw_evdev *dsw)
50 {
51         return rte_atomic32_read(&dsw->credits_on_loan);
52 }
53
54 static struct dsw_xstat_dev dsw_dev_xstats[] = {
55         { "dev_credits_on_loan", dsw_xstats_dev_credits_on_loan }
56 };
57
58 #define DSW_GEN_PORT_ACCESS_FN(_variable)                               \
59         static uint64_t                                                 \
60         dsw_xstats_port_get_ ## _variable(struct dsw_evdev *dsw,        \
61                                           uint8_t port_id,              \
62                                           uint8_t queue_id __rte_unused) \
63         {                                                               \
64                 return dsw->ports[port_id]._variable;                   \
65         }
66
67 DSW_GEN_PORT_ACCESS_FN(new_enqueued)
68 DSW_GEN_PORT_ACCESS_FN(forward_enqueued)
69 DSW_GEN_PORT_ACCESS_FN(release_enqueued)
70
71 static uint64_t
72 dsw_xstats_port_get_queue_enqueued(struct dsw_evdev *dsw, uint8_t port_id,
73                                    uint8_t queue_id)
74 {
75         return dsw->ports[port_id].queue_enqueued[queue_id];
76 }
77
78 DSW_GEN_PORT_ACCESS_FN(dequeued)
79
80 static uint64_t
81 dsw_xstats_port_get_queue_dequeued(struct dsw_evdev *dsw, uint8_t port_id,
82                                    uint8_t queue_id)
83 {
84         return dsw->ports[port_id].queue_dequeued[queue_id];
85 }
86
87 DSW_GEN_PORT_ACCESS_FN(migrations)
88
89 static uint64_t
90 dsw_xstats_port_get_migration_latency(struct dsw_evdev *dsw, uint8_t port_id,
91                                       uint8_t queue_id __rte_unused)
92 {
93         uint64_t total_latency = dsw->ports[port_id].migration_latency;
94         uint64_t num_migrations = dsw->ports[port_id].migrations;
95
96         return num_migrations > 0 ? total_latency / num_migrations : 0;
97 }
98
99 static uint64_t
100 dsw_xstats_port_get_event_proc_latency(struct dsw_evdev *dsw, uint8_t port_id,
101                                        uint8_t queue_id __rte_unused)
102 {
103         uint64_t total_busy_cycles =
104                 dsw->ports[port_id].total_busy_cycles;
105         uint64_t dequeued =
106                 dsw->ports[port_id].dequeued;
107
108         return dequeued > 0 ? total_busy_cycles / dequeued : 0;
109 }
110
111 DSW_GEN_PORT_ACCESS_FN(inflight_credits)
112
113 static uint64_t
114 dsw_xstats_port_get_load(struct dsw_evdev *dsw, uint8_t port_id,
115                          uint8_t queue_id __rte_unused)
116 {
117         int16_t load;
118
119         load = rte_atomic16_read(&dsw->ports[port_id].load);
120
121         return DSW_LOAD_TO_PERCENT(load);
122 }
123
124 DSW_GEN_PORT_ACCESS_FN(last_bg)
125
126 static struct dsw_xstats_port dsw_port_xstats[] = {
127         { "port_%u_new_enqueued", dsw_xstats_port_get_new_enqueued,
128           false },
129         { "port_%u_forward_enqueued", dsw_xstats_port_get_forward_enqueued,
130           false },
131         { "port_%u_release_enqueued", dsw_xstats_port_get_release_enqueued,
132           false },
133         { "port_%u_queue_%u_enqueued", dsw_xstats_port_get_queue_enqueued,
134           true },
135         { "port_%u_dequeued", dsw_xstats_port_get_dequeued,
136           false },
137         { "port_%u_queue_%u_dequeued", dsw_xstats_port_get_queue_dequeued,
138           true },
139         { "port_%u_migrations", dsw_xstats_port_get_migrations,
140           false },
141         { "port_%u_migration_latency", dsw_xstats_port_get_migration_latency,
142           false },
143         { "port_%u_event_proc_latency", dsw_xstats_port_get_event_proc_latency,
144           false },
145         { "port_%u_inflight_credits", dsw_xstats_port_get_inflight_credits,
146           false },
147         { "port_%u_load", dsw_xstats_port_get_load,
148           false },
149         { "port_%u_last_bg", dsw_xstats_port_get_last_bg,
150           false }
151 };
152
153 typedef
154 void (*dsw_xstats_foreach_fn)(const char *xstats_name,
155                               enum rte_event_dev_xstats_mode mode,
156                               uint8_t queue_port_id, unsigned int xstats_id,
157                               void *data);
158
159 static void
160 dsw_xstats_dev_foreach(dsw_xstats_foreach_fn fn, void *fn_data)
161 {
162         unsigned int i;
163
164         for (i = 0; i < RTE_DIM(dsw_dev_xstats); i++)
165                 fn(dsw_dev_xstats[i].name, RTE_EVENT_DEV_XSTATS_DEVICE, 0,
166                    i, fn_data);
167 }
168
169 static void
170 dsw_xstats_port_foreach(struct dsw_evdev *dsw, uint8_t port_id,
171                         dsw_xstats_foreach_fn fn, void *fn_data)
172 {
173         uint8_t queue_id;
174         unsigned int stat_idx;
175
176         for (stat_idx = 0, queue_id = 0;
177              stat_idx < RTE_DIM(dsw_port_xstats);) {
178                 struct dsw_xstats_port *xstat = &dsw_port_xstats[stat_idx];
179                 char xstats_name[RTE_EVENT_DEV_XSTATS_NAME_SIZE];
180                 unsigned int xstats_id;
181
182                 if (xstat->per_queue) {
183                         xstats_id = DSW_XSTATS_ID_CREATE(stat_idx, queue_id);
184                         snprintf(xstats_name, sizeof(xstats_name),
185                                  dsw_port_xstats[stat_idx].name_fmt, port_id,
186                                  queue_id);
187                         queue_id++;
188                 } else {
189                         xstats_id = stat_idx;
190                         snprintf(xstats_name, sizeof(xstats_name),
191                                  dsw_port_xstats[stat_idx].name_fmt, port_id);
192                 }
193
194                 fn(xstats_name, RTE_EVENT_DEV_XSTATS_PORT, port_id,
195                    xstats_id, fn_data);
196
197                 if (!(xstat->per_queue && queue_id < dsw->num_queues)) {
198                         stat_idx++;
199                         queue_id = 0;
200                 }
201         }
202 }
203
204 struct store_ctx {
205         struct rte_event_dev_xstats_name *names;
206         unsigned int *ids;
207         unsigned int count;
208         unsigned int capacity;
209 };
210
211 static void
212 dsw_xstats_store_stat(const char *xstats_name,
213                       enum rte_event_dev_xstats_mode mode,
214                       uint8_t queue_port_id, unsigned int xstats_id,
215                       void *data)
216 {
217         struct store_ctx *ctx = data;
218
219         RTE_SET_USED(mode);
220         RTE_SET_USED(queue_port_id);
221
222         if (ctx->count < ctx->capacity) {
223                 strcpy(ctx->names[ctx->count].name, xstats_name);
224                 ctx->ids[ctx->count] = xstats_id;
225         }
226
227         ctx->count++;
228 }
229
230 int
231 dsw_xstats_get_names(const struct rte_eventdev *dev,
232                      enum rte_event_dev_xstats_mode mode,
233                      uint8_t queue_port_id,
234                      struct rte_event_dev_xstats_name *xstats_names,
235                      unsigned int *ids, unsigned int capacity)
236 {
237         struct dsw_evdev *dsw = dsw_pmd_priv(dev);
238
239         struct store_ctx ctx = {
240                 .names = xstats_names,
241                 .ids = ids,
242                 .capacity = capacity
243         };
244
245         switch (mode) {
246         case RTE_EVENT_DEV_XSTATS_DEVICE:
247                 dsw_xstats_dev_foreach(dsw_xstats_store_stat, &ctx);
248                 return ctx.count;
249         case RTE_EVENT_DEV_XSTATS_PORT:
250                 dsw_xstats_port_foreach(dsw, queue_port_id,
251                                         dsw_xstats_store_stat, &ctx);
252                 return ctx.count;
253         case RTE_EVENT_DEV_XSTATS_QUEUE:
254                 return 0;
255         default:
256                 RTE_ASSERT(false);
257                 return -1;
258         }
259 }
260
261 static int
262 dsw_xstats_dev_get(const struct rte_eventdev *dev,
263                    const unsigned int ids[], uint64_t values[], unsigned int n)
264 {
265         struct dsw_evdev *dsw = dsw_pmd_priv(dev);
266         unsigned int i;
267
268         for (i = 0; i < n; i++) {
269                 unsigned int id = ids[i];
270                 struct dsw_xstat_dev *xstat = &dsw_dev_xstats[id];
271                 values[i] = xstat->get_value_fn(dsw);
272         }
273         return n;
274 }
275
276 static int
277 dsw_xstats_port_get(const struct rte_eventdev *dev, uint8_t port_id,
278                     const unsigned int ids[], uint64_t values[], unsigned int n)
279 {
280         struct dsw_evdev *dsw = dsw_pmd_priv(dev);
281         unsigned int i;
282
283         for (i = 0; i < n; i++) {
284                 unsigned int id = ids[i];
285                 unsigned int stat_idx = DSW_XSTATS_ID_GET_STAT(id);
286                 struct dsw_xstats_port *xstat = &dsw_port_xstats[stat_idx];
287                 uint8_t queue_id = 0;
288
289                 if (xstat->per_queue)
290                         queue_id = DSW_XSTATS_ID_GET_PARAM(id);
291
292                 values[i] = xstat->get_value_fn(dsw, port_id, queue_id);
293         }
294         return n;
295 }
296
297 int
298 dsw_xstats_get(const struct rte_eventdev *dev,
299                enum rte_event_dev_xstats_mode mode, uint8_t queue_port_id,
300                const unsigned int ids[], uint64_t values[], unsigned int n)
301 {
302         switch (mode) {
303         case RTE_EVENT_DEV_XSTATS_DEVICE:
304                 return dsw_xstats_dev_get(dev, ids, values, n);
305         case RTE_EVENT_DEV_XSTATS_PORT:
306                 return dsw_xstats_port_get(dev, queue_port_id, ids, values, n);
307         case RTE_EVENT_DEV_XSTATS_QUEUE:
308                 return 0;
309         default:
310                 RTE_ASSERT(false);
311                 return -1;
312         }
313         return 0;
314 }
315
316 struct find_ctx {
317         const struct rte_eventdev *dev;
318         const char *name;
319         unsigned int *id;
320         uint64_t value;
321 };
322
323 static void
324 dsw_xstats_find_stat(const char *xstats_name,
325                      enum rte_event_dev_xstats_mode mode,
326                      uint8_t queue_port_id, unsigned int xstats_id,
327                      void *data)
328 {
329         struct find_ctx *ctx = data;
330
331         if (strcmp(ctx->name, xstats_name) == 0) {
332                 if (ctx->id != NULL)
333                         *ctx->id = xstats_id;
334                 dsw_xstats_get(ctx->dev, mode, queue_port_id, &xstats_id,
335                                &ctx->value, 1);
336         }
337 }
338
339 uint64_t
340 dsw_xstats_get_by_name(const struct rte_eventdev *dev, const char *name,
341                        unsigned int *id)
342 {
343         struct dsw_evdev *dsw = dsw_pmd_priv(dev);
344         uint16_t port_id;
345
346         struct find_ctx ctx = {
347                 .dev = dev,
348                 .name = name,
349                 .id = id,
350                 .value = -EINVAL
351         };
352
353         dsw_xstats_dev_foreach(dsw_xstats_find_stat, &ctx);
354
355         for (port_id = 0; port_id < dsw->num_ports; port_id++)
356                 dsw_xstats_port_foreach(dsw, port_id, dsw_xstats_find_stat,
357                                         &ctx);
358
359         return ctx.value;
360 }