xref: /dpdk/drivers/net/ntnic/nthw/stat/nthw_stat.c (revision 37dda90ee15b7098bc48356868a87d34f727eecc)
1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * Copyright(c) 2023 Napatech A/S
4  */
5 
6 #include "nt_util.h"
7 #include "ntlog.h"
8 
9 #include "nthw_drv.h"
10 #include "nthw_register.h"
11 
12 #include "ntnic_stat.h"
13 
14 #include <malloc.h>
15 
16 nthw_stat_t *nthw_stat_new(void)
17 {
18 	nthw_stat_t *p = malloc(sizeof(nthw_stat_t));
19 
20 	if (p)
21 		memset(p, 0, sizeof(nthw_stat_t));
22 
23 	return p;
24 }
25 
26 void nthw_stat_delete(nthw_stat_t *p)
27 {
28 	free(p);
29 }
30 
31 int nthw_stat_init(nthw_stat_t *p, nthw_fpga_t *p_fpga, int n_instance)
32 {
33 	const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
34 	uint64_t n_module_version_packed64 = -1;
35 	nthw_module_t *mod = nthw_fpga_query_module(p_fpga, MOD_STA, n_instance);
36 
37 	if (p == NULL)
38 		return mod == NULL ? -1 : 0;
39 
40 	if (mod == NULL) {
41 		NT_LOG(ERR, NTHW, "%s: STAT %d: no such instance", p_adapter_id_str, n_instance);
42 		return -1;
43 	}
44 
45 	p->mp_fpga = p_fpga;
46 	p->mn_instance = n_instance;
47 	p->mp_mod_stat = mod;
48 
49 	n_module_version_packed64 = nthw_module_get_version_packed64(p->mp_mod_stat);
50 	NT_LOG(DBG, NTHW, "%s: STAT %d: version=0x%08lX", p_adapter_id_str, p->mn_instance,
51 		n_module_version_packed64);
52 
53 	{
54 		nthw_register_t *p_reg;
55 		/* STA_CFG register */
56 		p_reg = nthw_module_get_register(p->mp_mod_stat, STA_CFG);
57 		p->mp_fld_dma_ena = nthw_register_get_field(p_reg, STA_CFG_DMA_ENA);
58 		p->mp_fld_cnt_clear = nthw_register_get_field(p_reg, STA_CFG_CNT_CLEAR);
59 
60 		/* CFG: fields NOT available from v. 3 */
61 		p->mp_fld_tx_disable = nthw_register_query_field(p_reg, STA_CFG_TX_DISABLE);
62 		p->mp_fld_cnt_freeze = nthw_register_query_field(p_reg, STA_CFG_CNT_FRZ);
63 
64 		/* STA_STATUS register */
65 		p_reg = nthw_module_get_register(p->mp_mod_stat, STA_STATUS);
66 		p->mp_fld_stat_toggle_missed =
67 			nthw_register_get_field(p_reg, STA_STATUS_STAT_TOGGLE_MISSED);
68 
69 		/* HOST_ADR registers */
70 		p_reg = nthw_module_get_register(p->mp_mod_stat, STA_HOST_ADR_LSB);
71 		p->mp_fld_dma_lsb = nthw_register_get_field(p_reg, STA_HOST_ADR_LSB_LSB);
72 
73 		p_reg = nthw_module_get_register(p->mp_mod_stat, STA_HOST_ADR_MSB);
74 		p->mp_fld_dma_msb = nthw_register_get_field(p_reg, STA_HOST_ADR_MSB_MSB);
75 
76 		/* Binning cycles */
77 		p_reg = nthw_module_query_register(p->mp_mod_stat, STA_LOAD_BIN);
78 
79 		if (p_reg) {
80 			p->mp_fld_load_bin = nthw_register_get_field(p_reg, STA_LOAD_BIN_BIN);
81 
82 			/* Bandwidth load for RX port 0 */
83 			p_reg = nthw_module_query_register(p->mp_mod_stat, STA_LOAD_BPS_RX_0);
84 
85 			if (p_reg) {
86 				p->mp_fld_load_bps_rx0 =
87 					nthw_register_get_field(p_reg, STA_LOAD_BPS_RX_0_BPS);
88 
89 			} else {
90 				p->mp_fld_load_bps_rx0 = NULL;
91 			}
92 
93 			/* Bandwidth load for RX port 1 */
94 			p_reg = nthw_module_query_register(p->mp_mod_stat, STA_LOAD_BPS_RX_1);
95 
96 			if (p_reg) {
97 				p->mp_fld_load_bps_rx1 =
98 					nthw_register_get_field(p_reg, STA_LOAD_BPS_RX_1_BPS);
99 
100 			} else {
101 				p->mp_fld_load_bps_rx1 = NULL;
102 			}
103 
104 			/* Bandwidth load for TX port 0 */
105 			p_reg = nthw_module_query_register(p->mp_mod_stat, STA_LOAD_BPS_TX_0);
106 
107 			if (p_reg) {
108 				p->mp_fld_load_bps_tx0 =
109 					nthw_register_get_field(p_reg, STA_LOAD_BPS_TX_0_BPS);
110 
111 			} else {
112 				p->mp_fld_load_bps_tx0 = NULL;
113 			}
114 
115 			/* Bandwidth load for TX port 1 */
116 			p_reg = nthw_module_query_register(p->mp_mod_stat, STA_LOAD_BPS_TX_1);
117 
118 			if (p_reg) {
119 				p->mp_fld_load_bps_tx1 =
120 					nthw_register_get_field(p_reg, STA_LOAD_BPS_TX_1_BPS);
121 
122 			} else {
123 				p->mp_fld_load_bps_tx1 = NULL;
124 			}
125 
126 			/* Packet load for RX port 0 */
127 			p_reg = nthw_module_query_register(p->mp_mod_stat, STA_LOAD_PPS_RX_0);
128 
129 			if (p_reg) {
130 				p->mp_fld_load_pps_rx0 =
131 					nthw_register_get_field(p_reg, STA_LOAD_PPS_RX_0_PPS);
132 
133 			} else {
134 				p->mp_fld_load_pps_rx0 = NULL;
135 			}
136 
137 			/* Packet load for RX port 1 */
138 			p_reg = nthw_module_query_register(p->mp_mod_stat, STA_LOAD_PPS_RX_1);
139 
140 			if (p_reg) {
141 				p->mp_fld_load_pps_rx1 =
142 					nthw_register_get_field(p_reg, STA_LOAD_PPS_RX_1_PPS);
143 
144 			} else {
145 				p->mp_fld_load_pps_rx1 = NULL;
146 			}
147 
148 			/* Packet load for TX port 0 */
149 			p_reg = nthw_module_query_register(p->mp_mod_stat, STA_LOAD_PPS_TX_0);
150 
151 			if (p_reg) {
152 				p->mp_fld_load_pps_tx0 =
153 					nthw_register_get_field(p_reg, STA_LOAD_PPS_TX_0_PPS);
154 
155 			} else {
156 				p->mp_fld_load_pps_tx0 = NULL;
157 			}
158 
159 			/* Packet load for TX port 1 */
160 			p_reg = nthw_module_query_register(p->mp_mod_stat, STA_LOAD_PPS_TX_1);
161 
162 			if (p_reg) {
163 				p->mp_fld_load_pps_tx1 =
164 					nthw_register_get_field(p_reg, STA_LOAD_PPS_TX_1_PPS);
165 
166 			} else {
167 				p->mp_fld_load_pps_tx1 = NULL;
168 			}
169 
170 		} else {
171 			p->mp_fld_load_bin = NULL;
172 			p->mp_fld_load_bps_rx0 = NULL;
173 			p->mp_fld_load_bps_rx1 = NULL;
174 			p->mp_fld_load_bps_tx0 = NULL;
175 			p->mp_fld_load_bps_tx1 = NULL;
176 			p->mp_fld_load_pps_rx0 = NULL;
177 			p->mp_fld_load_pps_rx1 = NULL;
178 			p->mp_fld_load_pps_tx0 = NULL;
179 			p->mp_fld_load_pps_tx1 = NULL;
180 		}
181 	}
182 
183 	/* Params */
184 	p->m_nb_nim_ports = nthw_fpga_get_product_param(p_fpga, NT_NIMS, 0);
185 	p->m_nb_phy_ports = nthw_fpga_get_product_param(p_fpga, NT_PHY_PORTS, 0);
186 
187 	/* VSWITCH */
188 	p->m_nb_rx_ports = nthw_fpga_get_product_param(p_fpga, NT_STA_RX_PORTS, -1);
189 
190 	if (p->m_nb_rx_ports == -1) {
191 		/* non-VSWITCH */
192 		p->m_nb_rx_ports = nthw_fpga_get_product_param(p_fpga, NT_RX_PORTS, -1);
193 
194 		if (p->m_nb_rx_ports == -1) {
195 			/* non-VSWITCH */
196 			p->m_nb_rx_ports = nthw_fpga_get_product_param(p_fpga, NT_PORTS, 0);
197 		}
198 	}
199 
200 	p->m_nb_rpp_per_ps = nthw_fpga_get_product_param(p_fpga, NT_RPP_PER_PS, 0);
201 
202 	p->m_nb_tx_ports = nthw_fpga_get_product_param(p_fpga, NT_TX_PORTS, 0);
203 	p->m_rx_port_replicate = nthw_fpga_get_product_param(p_fpga, NT_RX_PORT_REPLICATE, 0);
204 
205 	/* VSWITCH */
206 	p->m_nb_color_counters = nthw_fpga_get_product_param(p_fpga, NT_STA_COLORS, 64) * 2;
207 
208 	if (p->m_nb_color_counters == 0) {
209 		/* non-VSWITCH */
210 		p->m_nb_color_counters = nthw_fpga_get_product_param(p_fpga, NT_CAT_FUNCS, 0) * 2;
211 	}
212 
213 	p->m_nb_rx_host_buffers = nthw_fpga_get_product_param(p_fpga, NT_QUEUES, 0);
214 	p->m_nb_tx_host_buffers = p->m_nb_rx_host_buffers;
215 
216 	p->m_dbs_present = nthw_fpga_get_product_param(p_fpga, NT_DBS_PRESENT, 0);
217 
218 	p->m_nb_rx_hb_counters = (p->m_nb_rx_host_buffers * (6 + 2 *
219 				(n_module_version_packed64 >= VERSION_PACKED64(0, 6) ?
220 					p->m_dbs_present : 0)));
221 
222 	p->m_nb_tx_hb_counters = 0;
223 
224 	p->m_nb_rx_port_counters = 42 +
225 		2 * (n_module_version_packed64 >= VERSION_PACKED64(0, 6) ? p->m_dbs_present : 0);
226 	p->m_nb_tx_port_counters = 0;
227 
228 	p->m_nb_counters =
229 		p->m_nb_color_counters + p->m_nb_rx_hb_counters + p->m_nb_tx_hb_counters;
230 
231 	p->mn_stat_layout_version = 0;
232 
233 	if (n_module_version_packed64 >= VERSION_PACKED64(0, 9)) {
234 		p->mn_stat_layout_version = 7;
235 
236 	} else if (n_module_version_packed64 >= VERSION_PACKED64(0, 8)) {
237 		p->mn_stat_layout_version = 6;
238 
239 	} else if (n_module_version_packed64 >= VERSION_PACKED64(0, 6)) {
240 		p->mn_stat_layout_version = 5;
241 
242 	} else if (n_module_version_packed64 >= VERSION_PACKED64(0, 4)) {
243 		p->mn_stat_layout_version = 4;
244 
245 	} else if (n_module_version_packed64 >= VERSION_PACKED64(0, 3)) {
246 		p->mn_stat_layout_version = 3;
247 
248 	} else if (n_module_version_packed64 >= VERSION_PACKED64(0, 2)) {
249 		p->mn_stat_layout_version = 2;
250 
251 	} else if (n_module_version_packed64 > VERSION_PACKED64(0, 0)) {
252 		p->mn_stat_layout_version = 1;
253 
254 	} else {
255 		p->mn_stat_layout_version = 0;
256 		NT_LOG(ERR, NTHW, "%s: unknown module_version 0x%08lX layout=%d",
257 			p_adapter_id_str, n_module_version_packed64, p->mn_stat_layout_version);
258 	}
259 
260 	assert(p->mn_stat_layout_version);
261 
262 	/* STA module 0.2+ adds IPF counters per port (Rx feature) */
263 	if (n_module_version_packed64 >= VERSION_PACKED64(0, 2))
264 		p->m_nb_rx_port_counters += 6;
265 
266 	/* STA module 0.3+ adds TX stats */
267 	if (n_module_version_packed64 >= VERSION_PACKED64(0, 3) || p->m_nb_tx_ports >= 1)
268 		p->mb_has_tx_stats = true;
269 
270 	/* STA module 0.3+ adds TX stat counters */
271 	if (n_module_version_packed64 >= VERSION_PACKED64(0, 3))
272 		p->m_nb_tx_port_counters += 22;
273 
274 	/* STA module 0.4+ adds TX drop event counter */
275 	if (n_module_version_packed64 >= VERSION_PACKED64(0, 4))
276 		p->m_nb_tx_port_counters += 1;	/* TX drop event counter */
277 
278 	/*
279 	 * STA module 0.6+ adds pkt filter drop octets+pkts, retransmit and
280 	 * duplicate counters
281 	 */
282 	if (n_module_version_packed64 >= VERSION_PACKED64(0, 6)) {
283 		p->m_nb_rx_port_counters += 4;
284 		p->m_nb_tx_port_counters += 1;
285 	}
286 
287 	p->m_nb_counters += (p->m_nb_rx_ports * p->m_nb_rx_port_counters);
288 
289 	if (p->mb_has_tx_stats)
290 		p->m_nb_counters += (p->m_nb_tx_ports * p->m_nb_tx_port_counters);
291 
292 	/* Output params (debug) */
293 	NT_LOG(DBG, NTHW, "%s: nims=%d rxports=%d txports=%d rxrepl=%d colors=%d queues=%d",
294 		p_adapter_id_str, p->m_nb_nim_ports, p->m_nb_rx_ports, p->m_nb_tx_ports,
295 		p->m_rx_port_replicate, p->m_nb_color_counters, p->m_nb_rx_host_buffers);
296 	NT_LOG(DBG, NTHW, "%s: hbs=%d hbcounters=%d rxcounters=%d txcounters=%d",
297 		p_adapter_id_str, p->m_nb_rx_host_buffers, p->m_nb_rx_hb_counters,
298 		p->m_nb_rx_port_counters, p->m_nb_tx_port_counters);
299 	NT_LOG(DBG, NTHW, "%s: layout=%d", p_adapter_id_str, p->mn_stat_layout_version);
300 	NT_LOG(DBG, NTHW, "%s: counters=%d (0x%X)", p_adapter_id_str, p->m_nb_counters,
301 		p->m_nb_counters);
302 
303 	/* Init */
304 	if (p->mp_fld_tx_disable)
305 		nthw_field_set_flush(p->mp_fld_tx_disable);
306 
307 	nthw_field_update_register(p->mp_fld_cnt_clear);
308 	nthw_field_set_flush(p->mp_fld_cnt_clear);
309 	nthw_field_clr_flush(p->mp_fld_cnt_clear);
310 
311 	nthw_field_update_register(p->mp_fld_stat_toggle_missed);
312 	nthw_field_set_flush(p->mp_fld_stat_toggle_missed);
313 
314 	nthw_field_update_register(p->mp_fld_dma_ena);
315 	nthw_field_clr_flush(p->mp_fld_dma_ena);
316 	nthw_field_update_register(p->mp_fld_dma_ena);
317 
318 	/* Set the sliding windows size for port load */
319 	if (p->mp_fld_load_bin) {
320 		uint32_t rpp = nthw_fpga_get_product_param(p_fpga, NT_RPP_PER_PS, 0);
321 		uint32_t bin =
322 			(uint32_t)(((PORT_LOAD_WINDOWS_SIZE * 1000000000000ULL) / (32ULL * rpp)) -
323 				1ULL);
324 		nthw_field_set_val_flush32(p->mp_fld_load_bin, bin);
325 	}
326 
327 	return 0;
328 }
329 
330 int nthw_stat_set_dma_address(nthw_stat_t *p, uint64_t stat_dma_physical,
331 	uint32_t *p_stat_dma_virtual)
332 {
333 	assert(p_stat_dma_virtual);
334 	p->mp_timestamp = NULL;
335 
336 	p->m_stat_dma_physical = stat_dma_physical;
337 	p->mp_stat_dma_virtual = p_stat_dma_virtual;
338 
339 	memset(p->mp_stat_dma_virtual, 0, (p->m_nb_counters * sizeof(uint32_t)));
340 
341 	nthw_field_set_val_flush32(p->mp_fld_dma_msb,
342 		(uint32_t)((p->m_stat_dma_physical >> 32) & 0xffffffff));
343 	nthw_field_set_val_flush32(p->mp_fld_dma_lsb,
344 		(uint32_t)(p->m_stat_dma_physical & 0xffffffff));
345 
346 	p->mp_timestamp = (uint64_t *)(p->mp_stat_dma_virtual + p->m_nb_counters);
347 	NT_LOG(DBG, NTHW,
348 		"stat_dma_physical=%" PRIX64 " p_stat_dma_virtual=%" PRIX64
349 		" mp_timestamp=%" PRIX64 "", p->m_stat_dma_physical,
350 		(uint64_t)p->mp_stat_dma_virtual, (uint64_t)p->mp_timestamp);
351 	*p->mp_timestamp = (uint64_t)(int64_t)-1;
352 	return 0;
353 }
354 
355 int nthw_stat_trigger(nthw_stat_t *p)
356 {
357 	int n_toggle_miss = nthw_field_get_updated(p->mp_fld_stat_toggle_missed);
358 
359 	if (n_toggle_miss)
360 		nthw_field_set_flush(p->mp_fld_stat_toggle_missed);
361 
362 	if (p->mp_timestamp)
363 		*p->mp_timestamp = -1;	/* Clear old ts */
364 
365 	nthw_field_update_register(p->mp_fld_dma_ena);
366 	nthw_field_set_flush(p->mp_fld_dma_ena);
367 
368 	return 0;
369 }
370 
371 int nthw_stat_get_load_bps_rx(nthw_stat_t *p, uint8_t port, uint32_t *val)
372 {
373 	switch (port) {
374 	case 0:
375 		if (p->mp_fld_load_bps_rx0) {
376 			*val = nthw_field_get_updated(p->mp_fld_load_bps_rx0);
377 			return 0;
378 
379 		} else {
380 			*val = 0;
381 			return -1;
382 		}
383 
384 		break;
385 
386 	case 1:
387 		if (p->mp_fld_load_bps_rx1) {
388 			*val = nthw_field_get_updated(p->mp_fld_load_bps_rx1);
389 			return 0;
390 
391 		} else {
392 			*val = 0;
393 			return -1;
394 		}
395 
396 		break;
397 
398 	default:
399 		return -1;
400 	}
401 }
402 
403 int nthw_stat_get_load_bps_tx(nthw_stat_t *p, uint8_t port, uint32_t *val)
404 {
405 	switch (port) {
406 	case 0:
407 		if (p->mp_fld_load_bps_tx0) {
408 			*val = nthw_field_get_updated(p->mp_fld_load_bps_tx0);
409 			return 0;
410 
411 		} else {
412 			*val = 0;
413 			return -1;
414 		}
415 
416 		break;
417 
418 	case 1:
419 		if (p->mp_fld_load_bps_tx1) {
420 			*val = nthw_field_get_updated(p->mp_fld_load_bps_tx1);
421 			return 0;
422 
423 		} else {
424 			*val = 0;
425 			return -1;
426 		}
427 
428 		break;
429 
430 	default:
431 		return -1;
432 	}
433 }
434 
435 int nthw_stat_get_load_pps_rx(nthw_stat_t *p, uint8_t port, uint32_t *val)
436 {
437 	switch (port) {
438 	case 0:
439 		if (p->mp_fld_load_pps_rx0) {
440 			*val = nthw_field_get_updated(p->mp_fld_load_pps_rx0);
441 			return 0;
442 
443 		} else {
444 			*val = 0;
445 			return -1;
446 		}
447 
448 		break;
449 
450 	case 1:
451 		if (p->mp_fld_load_pps_rx1) {
452 			*val = nthw_field_get_updated(p->mp_fld_load_pps_rx1);
453 			return 0;
454 
455 		} else {
456 			*val = 0;
457 			return -1;
458 		}
459 
460 		break;
461 
462 	default:
463 		return -1;
464 	}
465 }
466 
467 int nthw_stat_get_load_pps_tx(nthw_stat_t *p, uint8_t port, uint32_t *val)
468 {
469 	switch (port) {
470 	case 0:
471 		if (p->mp_fld_load_pps_tx0) {
472 			*val = nthw_field_get_updated(p->mp_fld_load_pps_tx0);
473 			return 0;
474 
475 		} else {
476 			*val = 0;
477 			return -1;
478 		}
479 
480 		break;
481 
482 	case 1:
483 		if (p->mp_fld_load_pps_tx1) {
484 			*val = nthw_field_get_updated(p->mp_fld_load_pps_tx1);
485 			return 0;
486 
487 		} else {
488 			*val = 0;
489 			return -1;
490 		}
491 
492 		break;
493 
494 	default:
495 		return -1;
496 	}
497 }
498