xref: /f-stack/dpdk/drivers/event/dsw/dsw_xstats.c (revision 2d9fd380)
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
dsw_xstats_dev_credits_on_loan(struct dsw_evdev * dsw)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)
DSW_GEN_PORT_ACCESS_FN(forward_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 
DSW_GEN_PORT_ACCESS_FN(dequeued)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(emigrations)
DSW_GEN_PORT_ACCESS_FN(immigrations)88 DSW_GEN_PORT_ACCESS_FN(immigrations)
89 
90 static uint64_t
91 dsw_xstats_port_get_migration_latency(struct dsw_evdev *dsw, uint8_t port_id,
92 				      uint8_t queue_id __rte_unused)
93 {
94 	uint64_t total_latency = dsw->ports[port_id].emigration_latency;
95 	uint64_t num_emigrations = dsw->ports[port_id].emigrations;
96 
97 	return num_emigrations > 0 ? total_latency / num_emigrations : 0;
98 }
99 
100 static uint64_t
dsw_xstats_port_get_event_proc_latency(struct dsw_evdev * dsw,uint8_t port_id,uint8_t queue_id __rte_unused)101 dsw_xstats_port_get_event_proc_latency(struct dsw_evdev *dsw, uint8_t port_id,
102 				       uint8_t queue_id __rte_unused)
103 {
104 	uint64_t total_busy_cycles =
105 		dsw->ports[port_id].total_busy_cycles;
106 	uint64_t dequeued =
107 		dsw->ports[port_id].dequeued;
108 
109 	return dequeued > 0 ? total_busy_cycles / dequeued : 0;
110 }
111 
112 static uint64_t
dsw_xstats_port_get_busy_cycles(struct dsw_evdev * dsw,uint8_t port_id,uint8_t queue_id __rte_unused)113 dsw_xstats_port_get_busy_cycles(struct dsw_evdev *dsw, uint8_t port_id,
114 				uint8_t queue_id __rte_unused)
115 {
116 	return dsw->ports[port_id].total_busy_cycles;
117 }
118 
119 DSW_GEN_PORT_ACCESS_FN(inflight_credits)
120 
DSW_GEN_PORT_ACCESS_FN(pending_releases)121 DSW_GEN_PORT_ACCESS_FN(pending_releases)
122 
123 static uint64_t
124 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 	load = rte_atomic16_read(&dsw->ports[port_id].load);
130 
131 	return DSW_LOAD_TO_PERCENT(load);
132 }
133 
134 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, unsigned int xstats_id,
173 			      void *data);
174 
175 static void
dsw_xstats_dev_foreach(dsw_xstats_foreach_fn fn,void * fn_data)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 		fn(dsw_dev_xstats[i].name, RTE_EVENT_DEV_XSTATS_DEVICE, 0,
182 		   i, fn_data);
183 }
184 
185 static void
dsw_xstats_port_foreach(struct dsw_evdev * dsw,uint8_t port_id,dsw_xstats_foreach_fn fn,void * fn_data)186 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 	for (stat_idx = 0, queue_id = 0;
193 	     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 		unsigned int xstats_id;
197 
198 		if (xstat->per_queue) {
199 			xstats_id = DSW_XSTATS_ID_CREATE(stat_idx, queue_id);
200 			snprintf(xstats_name, sizeof(xstats_name),
201 				 dsw_port_xstats[stat_idx].name_fmt, port_id,
202 				 queue_id);
203 			queue_id++;
204 		} else {
205 			xstats_id = stat_idx;
206 			snprintf(xstats_name, sizeof(xstats_name),
207 				 dsw_port_xstats[stat_idx].name_fmt, port_id);
208 		}
209 
210 		fn(xstats_name, RTE_EVENT_DEV_XSTATS_PORT, port_id,
211 		   xstats_id, fn_data);
212 
213 		if (!(xstat->per_queue && queue_id < dsw->num_queues)) {
214 			stat_idx++;
215 			queue_id = 0;
216 		}
217 	}
218 }
219 
220 struct store_ctx {
221 	struct rte_event_dev_xstats_name *names;
222 	unsigned int *ids;
223 	unsigned int count;
224 	unsigned int capacity;
225 };
226 
227 static void
dsw_xstats_store_stat(const char * xstats_name,enum rte_event_dev_xstats_mode mode,uint8_t queue_port_id,unsigned int xstats_id,void * data)228 dsw_xstats_store_stat(const char *xstats_name,
229 		      enum rte_event_dev_xstats_mode mode,
230 		      uint8_t queue_port_id, unsigned int 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 	if (ctx->count < ctx->capacity) {
239 		strcpy(ctx->names[ctx->count].name, xstats_name);
240 		ctx->ids[ctx->count] = xstats_id;
241 	}
242 
243 	ctx->count++;
244 }
245 
246 int
dsw_xstats_get_names(const struct rte_eventdev * dev,enum rte_event_dev_xstats_mode mode,uint8_t queue_port_id,struct rte_event_dev_xstats_name * xstats_names,unsigned int * ids,unsigned int capacity)247 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 		     unsigned int *ids, unsigned int capacity)
252 {
253 	struct dsw_evdev *dsw = dsw_pmd_priv(dev);
254 
255 	struct store_ctx ctx = {
256 		.names = xstats_names,
257 		.ids = ids,
258 		.capacity = capacity
259 	};
260 
261 	switch (mode) {
262 	case RTE_EVENT_DEV_XSTATS_DEVICE:
263 		dsw_xstats_dev_foreach(dsw_xstats_store_stat, &ctx);
264 		return ctx.count;
265 	case RTE_EVENT_DEV_XSTATS_PORT:
266 		dsw_xstats_port_foreach(dsw, queue_port_id,
267 					dsw_xstats_store_stat, &ctx);
268 		return ctx.count;
269 	case RTE_EVENT_DEV_XSTATS_QUEUE:
270 		return 0;
271 	default:
272 		RTE_ASSERT(false);
273 		return -1;
274 	}
275 }
276 
277 static int
dsw_xstats_dev_get(const struct rte_eventdev * dev,const unsigned int ids[],uint64_t values[],unsigned int n)278 dsw_xstats_dev_get(const struct rte_eventdev *dev,
279 		   const unsigned int ids[], uint64_t values[], unsigned int n)
280 {
281 	struct dsw_evdev *dsw = dsw_pmd_priv(dev);
282 	unsigned int i;
283 
284 	for (i = 0; i < n; i++) {
285 		unsigned int id = ids[i];
286 		struct dsw_xstat_dev *xstat = &dsw_dev_xstats[id];
287 		values[i] = xstat->get_value_fn(dsw);
288 	}
289 	return n;
290 }
291 
292 static int
dsw_xstats_port_get(const struct rte_eventdev * dev,uint8_t port_id,const unsigned int ids[],uint64_t values[],unsigned int n)293 dsw_xstats_port_get(const struct rte_eventdev *dev, uint8_t port_id,
294 		    const unsigned int ids[], uint64_t values[], unsigned int n)
295 {
296 	struct dsw_evdev *dsw = dsw_pmd_priv(dev);
297 	unsigned int i;
298 
299 	for (i = 0; i < n; i++) {
300 		unsigned int id = ids[i];
301 		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 		if (xstat->per_queue)
306 			queue_id = DSW_XSTATS_ID_GET_PARAM(id);
307 
308 		values[i] = xstat->get_value_fn(dsw, port_id, queue_id);
309 	}
310 	return n;
311 }
312 
313 int
dsw_xstats_get(const struct rte_eventdev * dev,enum rte_event_dev_xstats_mode mode,uint8_t queue_port_id,const unsigned int ids[],uint64_t values[],unsigned int n)314 dsw_xstats_get(const struct rte_eventdev *dev,
315 	       enum rte_event_dev_xstats_mode mode, uint8_t queue_port_id,
316 	       const unsigned int ids[], uint64_t values[], unsigned int n)
317 {
318 	switch (mode) {
319 	case RTE_EVENT_DEV_XSTATS_DEVICE:
320 		return dsw_xstats_dev_get(dev, ids, values, n);
321 	case RTE_EVENT_DEV_XSTATS_PORT:
322 		return dsw_xstats_port_get(dev, queue_port_id, ids, values, n);
323 	case RTE_EVENT_DEV_XSTATS_QUEUE:
324 		return 0;
325 	default:
326 		RTE_ASSERT(false);
327 		return -1;
328 	}
329 	return 0;
330 }
331 
332 struct find_ctx {
333 	const struct rte_eventdev *dev;
334 	const char *name;
335 	unsigned int *id;
336 	uint64_t value;
337 };
338 
339 static void
dsw_xstats_find_stat(const char * xstats_name,enum rte_event_dev_xstats_mode mode,uint8_t queue_port_id,unsigned int xstats_id,void * data)340 dsw_xstats_find_stat(const char *xstats_name,
341 		     enum rte_event_dev_xstats_mode mode,
342 		     uint8_t queue_port_id, unsigned int xstats_id,
343 		     void *data)
344 {
345 	struct find_ctx *ctx = data;
346 
347 	if (strcmp(ctx->name, xstats_name) == 0) {
348 		if (ctx->id != NULL)
349 			*ctx->id = xstats_id;
350 		dsw_xstats_get(ctx->dev, mode, queue_port_id, &xstats_id,
351 			       &ctx->value, 1);
352 	}
353 }
354 
355 uint64_t
dsw_xstats_get_by_name(const struct rte_eventdev * dev,const char * name,unsigned int * id)356 dsw_xstats_get_by_name(const struct rte_eventdev *dev, const char *name,
357 		       unsigned int *id)
358 {
359 	struct dsw_evdev *dsw = dsw_pmd_priv(dev);
360 	uint16_t port_id;
361 
362 	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 	for (port_id = 0; port_id < dsw->num_ports; port_id++)
372 		dsw_xstats_port_foreach(dsw, port_id, dsw_xstats_find_stat,
373 					&ctx);
374 
375 	return ctx.value;
376 }
377