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