Branch data Line data Source code
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(uint64_t)*CHAR_BIT - DSW_XSTATS_ID_PARAM_BITS)
19 : : #define DSW_XSTATS_ID_STAT_MASK ((UINT64_C(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 : : ((((uint64_t)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 : 0 : dsw_xstats_dev_credits_on_loan(struct dsw_evdev *dsw)
50 : : {
51 : 0 : return rte_atomic_load_explicit(&dsw->credits_on_loan, rte_memory_order_relaxed);
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 : 0 : DSW_GEN_PORT_ACCESS_FN(new_enqueued)
68 : 0 : DSW_GEN_PORT_ACCESS_FN(forward_enqueued)
69 : 0 : DSW_GEN_PORT_ACCESS_FN(release_enqueued)
70 : :
71 : : static uint64_t
72 : 0 : dsw_xstats_port_get_queue_enqueued(struct dsw_evdev *dsw, uint8_t port_id,
73 : : uint8_t queue_id)
74 : : {
75 : 0 : return dsw->ports[port_id].queue_enqueued[queue_id];
76 : : }
77 : :
78 : 0 : DSW_GEN_PORT_ACCESS_FN(dequeued)
79 : :
80 : : static uint64_t
81 : 0 : dsw_xstats_port_get_queue_dequeued(struct dsw_evdev *dsw, uint8_t port_id,
82 : : uint8_t queue_id)
83 : : {
84 : 0 : return dsw->ports[port_id].queue_dequeued[queue_id];
85 : : }
86 : :
87 : 0 : DSW_GEN_PORT_ACCESS_FN(emigrations)
88 : 0 : DSW_GEN_PORT_ACCESS_FN(immigrations)
89 : :
90 : : static uint64_t
91 : 0 : dsw_xstats_port_get_migration_latency(struct dsw_evdev *dsw, uint8_t port_id,
92 : : uint8_t queue_id __rte_unused)
93 : : {
94 : 0 : uint64_t total_latency = dsw->ports[port_id].emigration_latency;
95 : 0 : uint64_t num_emigrations = dsw->ports[port_id].emigrations;
96 : :
97 [ # # ]: 0 : return num_emigrations > 0 ? total_latency / num_emigrations : 0;
98 : : }
99 : :
100 : : static uint64_t
101 : 0 : dsw_xstats_port_get_event_proc_latency(struct dsw_evdev *dsw, uint8_t port_id,
102 : : uint8_t queue_id __rte_unused)
103 : : {
104 : 0 : uint64_t total_busy_cycles =
105 : 0 : dsw->ports[port_id].total_busy_cycles;
106 : 0 : uint64_t dequeued =
107 : : dsw->ports[port_id].dequeued;
108 : :
109 [ # # ]: 0 : return dequeued > 0 ? total_busy_cycles / dequeued : 0;
110 : : }
111 : :
112 : : static uint64_t
113 : 0 : dsw_xstats_port_get_busy_cycles(struct dsw_evdev *dsw, uint8_t port_id,
114 : : uint8_t queue_id __rte_unused)
115 : : {
116 : 0 : return dsw->ports[port_id].total_busy_cycles;
117 : : }
118 : :
119 : 0 : DSW_GEN_PORT_ACCESS_FN(inflight_credits)
120 : :
121 : 0 : DSW_GEN_PORT_ACCESS_FN(pending_releases)
122 : :
123 : : static uint64_t
124 : 0 : dsw_xstats_port_get_load(struct dsw_evdev *dsw, uint8_t port_id,
125 : : uint8_t queue_id __rte_unused)
126 : : {
127 : : int16_t load;
128 : :
129 : 0 : load = rte_atomic_load_explicit(&dsw->ports[port_id].load, rte_memory_order_relaxed);
130 : :
131 : 0 : return DSW_LOAD_TO_PERCENT(load);
132 : : }
133 : :
134 : 0 : DSW_GEN_PORT_ACCESS_FN(last_bg)
135 : :
136 : : static struct dsw_xstats_port dsw_port_xstats[] = {
137 : : { "port_%u_new_enqueued", dsw_xstats_port_get_new_enqueued,
138 : : false },
139 : : { "port_%u_forward_enqueued", dsw_xstats_port_get_forward_enqueued,
140 : : false },
141 : : { "port_%u_release_enqueued", dsw_xstats_port_get_release_enqueued,
142 : : false },
143 : : { "port_%u_queue_%u_enqueued", dsw_xstats_port_get_queue_enqueued,
144 : : true },
145 : : { "port_%u_dequeued", dsw_xstats_port_get_dequeued,
146 : : false },
147 : : { "port_%u_queue_%u_dequeued", dsw_xstats_port_get_queue_dequeued,
148 : : true },
149 : : { "port_%u_emigrations", dsw_xstats_port_get_emigrations,
150 : : false },
151 : : { "port_%u_migration_latency", dsw_xstats_port_get_migration_latency,
152 : : false },
153 : : { "port_%u_immigrations", dsw_xstats_port_get_immigrations,
154 : : false },
155 : : { "port_%u_event_proc_latency", dsw_xstats_port_get_event_proc_latency,
156 : : false },
157 : : { "port_%u_busy_cycles", dsw_xstats_port_get_busy_cycles,
158 : : false },
159 : : { "port_%u_inflight_credits", dsw_xstats_port_get_inflight_credits,
160 : : false },
161 : : { "port_%u_pending_releases", dsw_xstats_port_get_pending_releases,
162 : : false },
163 : : { "port_%u_load", dsw_xstats_port_get_load,
164 : : false },
165 : : { "port_%u_last_bg", dsw_xstats_port_get_last_bg,
166 : : false }
167 : : };
168 : :
169 : : typedef
170 : : void (*dsw_xstats_foreach_fn)(const char *xstats_name,
171 : : enum rte_event_dev_xstats_mode mode,
172 : : uint8_t queue_port_id, uint64_t xstats_id,
173 : : void *data);
174 : :
175 : : static void
176 : : dsw_xstats_dev_foreach(dsw_xstats_foreach_fn fn, void *fn_data)
177 : : {
178 : : unsigned int i;
179 : :
180 : : for (i = 0; i < RTE_DIM(dsw_dev_xstats); i++)
181 : 0 : fn(dsw_dev_xstats[i].name, RTE_EVENT_DEV_XSTATS_DEVICE, 0,
182 : : i, fn_data);
183 : : }
184 : :
185 : : static void
186 : 0 : dsw_xstats_port_foreach(struct dsw_evdev *dsw, uint8_t port_id,
187 : : dsw_xstats_foreach_fn fn, void *fn_data)
188 : : {
189 : : uint8_t queue_id;
190 : : unsigned int stat_idx;
191 : :
192 : 0 : for (stat_idx = 0, queue_id = 0;
193 [ # # ]: 0 : stat_idx < RTE_DIM(dsw_port_xstats);) {
194 : : struct dsw_xstats_port *xstat = &dsw_port_xstats[stat_idx];
195 : : char xstats_name[RTE_EVENT_DEV_XSTATS_NAME_SIZE];
196 : : uint64_t xstats_id;
197 : :
198 [ # # ]: 0 : if (xstat->per_queue) {
199 : 0 : xstats_id = DSW_XSTATS_ID_CREATE(stat_idx, queue_id);
200 : 0 : snprintf(xstats_name, sizeof(xstats_name),
201 : : dsw_port_xstats[stat_idx].name_fmt, port_id,
202 : : queue_id);
203 : 0 : queue_id++;
204 : : } else {
205 : 0 : xstats_id = stat_idx;
206 : 0 : snprintf(xstats_name, sizeof(xstats_name),
207 : : dsw_port_xstats[stat_idx].name_fmt, port_id);
208 : : }
209 : :
210 : 0 : fn(xstats_name, RTE_EVENT_DEV_XSTATS_PORT, port_id,
211 : : xstats_id, fn_data);
212 : :
213 [ # # # # ]: 0 : if (!(xstat->per_queue && queue_id < dsw->num_queues)) {
214 : 0 : stat_idx++;
215 : : queue_id = 0;
216 : : }
217 : : }
218 : 0 : }
219 : :
220 : : struct store_ctx {
221 : : struct rte_event_dev_xstats_name *names;
222 : : uint64_t *ids;
223 : : unsigned int count;
224 : : unsigned int capacity;
225 : : };
226 : :
227 : : static void
228 : 0 : dsw_xstats_store_stat(const char *xstats_name,
229 : : enum rte_event_dev_xstats_mode mode,
230 : : uint8_t queue_port_id, uint64_t xstats_id,
231 : : void *data)
232 : : {
233 : : struct store_ctx *ctx = data;
234 : :
235 : : RTE_SET_USED(mode);
236 : : RTE_SET_USED(queue_port_id);
237 : :
238 [ # # ]: 0 : if (ctx->count < ctx->capacity) {
239 : 0 : strcpy(ctx->names[ctx->count].name, xstats_name);
240 : 0 : ctx->ids[ctx->count] = xstats_id;
241 : : }
242 : :
243 : 0 : ctx->count++;
244 : 0 : }
245 : :
246 : : int
247 [ # # # # ]: 0 : dsw_xstats_get_names(const struct rte_eventdev *dev,
248 : : enum rte_event_dev_xstats_mode mode,
249 : : uint8_t queue_port_id,
250 : : struct rte_event_dev_xstats_name *xstats_names,
251 : : uint64_t *ids, unsigned int capacity)
252 : : {
253 : : struct dsw_evdev *dsw = dsw_pmd_priv(dev);
254 : :
255 : 0 : struct store_ctx ctx = {
256 : : .names = xstats_names,
257 : : .ids = ids,
258 : : .capacity = capacity
259 : : };
260 : :
261 [ # # # # ]: 0 : switch (mode) {
262 : : case RTE_EVENT_DEV_XSTATS_DEVICE:
263 : : dsw_xstats_dev_foreach(dsw_xstats_store_stat, &ctx);
264 : 0 : return ctx.count;
265 : 0 : case RTE_EVENT_DEV_XSTATS_PORT:
266 : 0 : dsw_xstats_port_foreach(dsw, queue_port_id,
267 : : dsw_xstats_store_stat, &ctx);
268 : 0 : return ctx.count;
269 : : case RTE_EVENT_DEV_XSTATS_QUEUE:
270 : : return 0;
271 : 0 : default:
272 : : RTE_ASSERT(false);
273 : 0 : return -1;
274 : : }
275 : : }
276 : :
277 : : static int
278 : : dsw_xstats_dev_get(const struct rte_eventdev *dev,
279 : : const uint64_t ids[], uint64_t values[], unsigned int n)
280 : : {
281 : : struct dsw_evdev *dsw = dsw_pmd_priv(dev);
282 : : unsigned int i;
283 : :
284 [ # # ]: 0 : for (i = 0; i < n; i++) {
285 : 0 : uint64_t id = ids[i];
286 : : struct dsw_xstat_dev *xstat = &dsw_dev_xstats[id];
287 : 0 : values[i] = xstat->get_value_fn(dsw);
288 : : }
289 : 0 : return n;
290 : : }
291 : :
292 : : static int
293 : 0 : dsw_xstats_port_get(const struct rte_eventdev *dev, uint8_t port_id,
294 : : const uint64_t ids[], uint64_t values[], unsigned int n)
295 : : {
296 : : struct dsw_evdev *dsw = dsw_pmd_priv(dev);
297 : : unsigned int i;
298 : :
299 [ # # ]: 0 : for (i = 0; i < n; i++) {
300 : 0 : uint64_t id = ids[i];
301 : 0 : unsigned int stat_idx = DSW_XSTATS_ID_GET_STAT(id);
302 : : struct dsw_xstats_port *xstat = &dsw_port_xstats[stat_idx];
303 : : uint8_t queue_id = 0;
304 : :
305 [ # # ]: 0 : if (xstat->per_queue)
306 : 0 : queue_id = DSW_XSTATS_ID_GET_PARAM(id);
307 : :
308 : 0 : values[i] = xstat->get_value_fn(dsw, port_id, queue_id);
309 : : }
310 : 0 : return n;
311 : : }
312 : :
313 : : int
314 : 0 : dsw_xstats_get(const struct rte_eventdev *dev,
315 : : enum rte_event_dev_xstats_mode mode, uint8_t queue_port_id,
316 : : const uint64_t ids[], uint64_t values[], unsigned int n)
317 : : {
318 [ # # # # ]: 0 : switch (mode) {
319 : : case RTE_EVENT_DEV_XSTATS_DEVICE:
320 : 0 : return dsw_xstats_dev_get(dev, ids, values, n);
321 : 0 : case RTE_EVENT_DEV_XSTATS_PORT:
322 : 0 : return dsw_xstats_port_get(dev, queue_port_id, ids, values, n);
323 : : case RTE_EVENT_DEV_XSTATS_QUEUE:
324 : : return 0;
325 : 0 : default:
326 : : RTE_ASSERT(false);
327 : 0 : return -1;
328 : : }
329 : : return 0;
330 : : }
331 : :
332 : : struct find_ctx {
333 : : const struct rte_eventdev *dev;
334 : : const char *name;
335 : : uint64_t *id;
336 : : uint64_t value;
337 : : };
338 : :
339 : : static void
340 : 0 : dsw_xstats_find_stat(const char *xstats_name,
341 : : enum rte_event_dev_xstats_mode mode,
342 : : uint8_t queue_port_id, uint64_t xstats_id,
343 : : void *data)
344 : : {
345 : : struct find_ctx *ctx = data;
346 : :
347 [ # # ]: 0 : if (strcmp(ctx->name, xstats_name) == 0) {
348 [ # # ]: 0 : if (ctx->id != NULL)
349 : 0 : *ctx->id = xstats_id;
350 : 0 : dsw_xstats_get(ctx->dev, mode, queue_port_id, &xstats_id,
351 : : &ctx->value, 1);
352 : : }
353 : 0 : }
354 : :
355 : : uint64_t
356 : 0 : dsw_xstats_get_by_name(const struct rte_eventdev *dev, const char *name,
357 : : uint64_t *id)
358 : : {
359 : : struct dsw_evdev *dsw = dsw_pmd_priv(dev);
360 : : uint16_t port_id;
361 : :
362 : 0 : struct find_ctx ctx = {
363 : : .dev = dev,
364 : : .name = name,
365 : : .id = id,
366 : : .value = -EINVAL
367 : : };
368 : :
369 : : dsw_xstats_dev_foreach(dsw_xstats_find_stat, &ctx);
370 : :
371 [ # # ]: 0 : for (port_id = 0; port_id < dsw->num_ports; port_id++)
372 : 0 : dsw_xstats_port_foreach(dsw, port_id, dsw_xstats_find_stat,
373 : : &ctx);
374 : :
375 : 0 : return ctx.value;
376 : : }
|