1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2021 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <rte_common.h> 7 #include <rte_cycles.h> 8 #include <rte_malloc.h> 9 #include <rte_log.h> 10 #include <rte_alarm.h> 11 #include "bnxt.h" 12 #include "bnxt_ulp.h" 13 #include "bnxt_tf_common.h" 14 #include "ulp_fc_mgr.h" 15 #include "ulp_flow_db.h" 16 #include "ulp_template_db_enum.h" 17 #include "ulp_template_struct.h" 18 #include "tf_tbl.h" 19 20 static int 21 ulp_fc_mgr_shadow_mem_alloc(struct hw_fc_mem_info *parms, int size) 22 { 23 /* Allocate memory*/ 24 if (!parms) 25 return -EINVAL; 26 27 parms->mem_va = rte_zmalloc("ulp_fc_info", 28 RTE_CACHE_LINE_ROUNDUP(size), 29 4096); 30 if (!parms->mem_va) { 31 BNXT_TF_DBG(ERR, "Allocate failed mem_va\n"); 32 return -ENOMEM; 33 } 34 35 rte_mem_lock_page(parms->mem_va); 36 37 parms->mem_pa = (void *)(uintptr_t)rte_mem_virt2phy(parms->mem_va); 38 if (parms->mem_pa == (void *)RTE_BAD_IOVA) { 39 BNXT_TF_DBG(ERR, "Allocate failed mem_pa\n"); 40 return -ENOMEM; 41 } 42 43 return 0; 44 } 45 46 static void 47 ulp_fc_mgr_shadow_mem_free(struct hw_fc_mem_info *parms) 48 { 49 rte_free(parms->mem_va); 50 } 51 52 /* 53 * Allocate and Initialize all Flow Counter Manager resources for this ulp 54 * context. 55 * 56 * ctxt [in] The ulp context for the Flow Counter manager. 57 * 58 */ 59 int32_t 60 ulp_fc_mgr_init(struct bnxt_ulp_context *ctxt) 61 { 62 struct bnxt_ulp_device_params *dparms; 63 uint32_t dev_id, sw_acc_cntr_tbl_sz, hw_fc_mem_info_sz; 64 struct bnxt_ulp_fc_info *ulp_fc_info; 65 int i, rc; 66 67 if (!ctxt) { 68 BNXT_TF_DBG(DEBUG, "Invalid ULP CTXT\n"); 69 return -EINVAL; 70 } 71 72 if (bnxt_ulp_cntxt_dev_id_get(ctxt, &dev_id)) { 73 BNXT_TF_DBG(DEBUG, "Failed to get device id\n"); 74 return -EINVAL; 75 } 76 77 dparms = bnxt_ulp_device_params_get(dev_id); 78 if (!dparms) { 79 BNXT_TF_DBG(DEBUG, "Failed to device parms\n"); 80 return -EINVAL; 81 } 82 83 ulp_fc_info = rte_zmalloc("ulp_fc_info", sizeof(*ulp_fc_info), 0); 84 if (!ulp_fc_info) 85 goto error; 86 87 rc = pthread_mutex_init(&ulp_fc_info->fc_lock, NULL); 88 if (rc) { 89 PMD_DRV_LOG(ERR, "Failed to initialize fc mutex\n"); 90 goto error; 91 } 92 93 /* Add the FC info tbl to the ulp context. */ 94 bnxt_ulp_cntxt_ptr2_fc_info_set(ctxt, ulp_fc_info); 95 96 ulp_fc_info->num_counters = dparms->flow_count_db_entries; 97 if (!ulp_fc_info->num_counters) { 98 /* No need for software counters, call fw directly */ 99 BNXT_TF_DBG(DEBUG, "Sw flow counter support not enabled\n"); 100 return 0; 101 } 102 103 sw_acc_cntr_tbl_sz = sizeof(struct sw_acc_counter) * 104 dparms->flow_count_db_entries; 105 106 for (i = 0; i < TF_DIR_MAX; i++) { 107 ulp_fc_info->sw_acc_tbl[i] = rte_zmalloc("ulp_sw_acc_cntr_tbl", 108 sw_acc_cntr_tbl_sz, 0); 109 if (!ulp_fc_info->sw_acc_tbl[i]) 110 goto error; 111 } 112 113 hw_fc_mem_info_sz = sizeof(uint64_t) * dparms->flow_count_db_entries; 114 115 for (i = 0; i < TF_DIR_MAX; i++) { 116 rc = ulp_fc_mgr_shadow_mem_alloc(&ulp_fc_info->shadow_hw_tbl[i], 117 hw_fc_mem_info_sz); 118 if (rc) 119 goto error; 120 } 121 122 return 0; 123 124 error: 125 ulp_fc_mgr_deinit(ctxt); 126 BNXT_TF_DBG(DEBUG, 127 "Failed to allocate memory for fc mgr\n"); 128 129 return -ENOMEM; 130 } 131 132 /* 133 * Release all resources in the Flow Counter Manager for this ulp context 134 * 135 * ctxt [in] The ulp context for the Flow Counter manager 136 * 137 */ 138 int32_t 139 ulp_fc_mgr_deinit(struct bnxt_ulp_context *ctxt) 140 { 141 struct bnxt_ulp_fc_info *ulp_fc_info; 142 struct hw_fc_mem_info *shd_info; 143 int i; 144 145 ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ctxt); 146 147 if (!ulp_fc_info) 148 return -EINVAL; 149 150 ulp_fc_mgr_thread_cancel(ctxt); 151 152 pthread_mutex_destroy(&ulp_fc_info->fc_lock); 153 154 if (ulp_fc_info->num_counters) { 155 for (i = 0; i < TF_DIR_MAX; i++) 156 rte_free(ulp_fc_info->sw_acc_tbl[i]); 157 158 for (i = 0; i < TF_DIR_MAX; i++) { 159 shd_info = &ulp_fc_info->shadow_hw_tbl[i]; 160 ulp_fc_mgr_shadow_mem_free(shd_info); 161 } 162 } 163 164 rte_free(ulp_fc_info); 165 166 /* Safe to ignore on deinit */ 167 (void)bnxt_ulp_cntxt_ptr2_fc_info_set(ctxt, NULL); 168 169 return 0; 170 } 171 172 /* 173 * Check if the alarm thread that walks through the flows is started 174 * 175 * ctxt [in] The ulp context for the flow counter manager 176 * 177 */ 178 bool ulp_fc_mgr_thread_isstarted(struct bnxt_ulp_context *ctxt) 179 { 180 struct bnxt_ulp_fc_info *ulp_fc_info; 181 182 ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ctxt); 183 184 if (ulp_fc_info) 185 return !!(ulp_fc_info->flags & ULP_FLAG_FC_THREAD); 186 187 return false; 188 } 189 190 /* 191 * Setup the Flow counter timer thread that will fetch/accumulate raw counter 192 * data from the chip's internal flow counters 193 * 194 * ctxt [in] The ulp context for the flow counter manager 195 * 196 */ 197 int32_t 198 ulp_fc_mgr_thread_start(struct bnxt_ulp_context *ctxt) 199 { 200 struct bnxt_ulp_fc_info *ulp_fc_info; 201 202 ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ctxt); 203 204 if (ulp_fc_info && !(ulp_fc_info->flags & ULP_FLAG_FC_THREAD)) { 205 rte_eal_alarm_set(US_PER_S * ULP_FC_TIMER, 206 ulp_fc_mgr_alarm_cb, NULL); 207 ulp_fc_info->flags |= ULP_FLAG_FC_THREAD; 208 } 209 210 return 0; 211 } 212 213 /* 214 * Cancel the alarm handler 215 * 216 * ctxt [in] The ulp context for the flow counter manager 217 * 218 */ 219 void ulp_fc_mgr_thread_cancel(struct bnxt_ulp_context *ctxt) 220 { 221 struct bnxt_ulp_fc_info *ulp_fc_info; 222 223 ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ctxt); 224 if (!ulp_fc_info) 225 return; 226 227 ulp_fc_info->flags &= ~ULP_FLAG_FC_THREAD; 228 rte_eal_alarm_cancel(ulp_fc_mgr_alarm_cb, NULL); 229 } 230 231 /* 232 * DMA-in the raw counter data from the HW and accumulate in the 233 * local accumulator table using the TF-Core API 234 * 235 * tfp [in] The TF-Core context 236 * 237 * fc_info [in] The ULP Flow counter info ptr 238 * 239 * dir [in] The direction of the flow 240 * 241 * num_counters [in] The number of counters 242 * 243 */ 244 __rte_unused static int32_t 245 ulp_bulk_get_flow_stats(struct tf *tfp, 246 struct bnxt_ulp_fc_info *fc_info, 247 enum tf_dir dir, 248 struct bnxt_ulp_device_params *dparms) 249 /* MARK AS UNUSED FOR NOW TO AVOID COMPILATION ERRORS TILL API is RESOLVED */ 250 { 251 int rc = 0; 252 struct tf_tbl_get_bulk_parms parms = { 0 }; 253 enum tf_tbl_type stype = TF_TBL_TYPE_ACT_STATS_64; /* TBD: Template? */ 254 struct sw_acc_counter *sw_acc_tbl_entry = NULL; 255 uint64_t *stats = NULL; 256 uint16_t i = 0; 257 258 parms.dir = dir; 259 parms.type = stype; 260 parms.starting_idx = fc_info->shadow_hw_tbl[dir].start_idx; 261 parms.num_entries = dparms->flow_count_db_entries / 2; /* direction */ 262 /* 263 * TODO: 264 * Size of an entry needs to obtained from template 265 */ 266 parms.entry_sz_in_bytes = sizeof(uint64_t); 267 stats = (uint64_t *)fc_info->shadow_hw_tbl[dir].mem_va; 268 parms.physical_mem_addr = (uint64_t) 269 ((uintptr_t)(fc_info->shadow_hw_tbl[dir].mem_pa)); 270 271 if (!stats) { 272 PMD_DRV_LOG(ERR, 273 "BULK: Memory not initialized id:0x%x dir:%d\n", 274 parms.starting_idx, dir); 275 return -EINVAL; 276 } 277 278 rc = tf_tbl_bulk_get(tfp, &parms); 279 if (rc) { 280 PMD_DRV_LOG(ERR, 281 "BULK: Get failed for id:0x%x rc:%d\n", 282 parms.starting_idx, rc); 283 return rc; 284 } 285 286 for (i = 0; i < parms.num_entries; i++) { 287 /* TBD - Get PKT/BYTE COUNT SHIFT/MASK from Template */ 288 sw_acc_tbl_entry = &fc_info->sw_acc_tbl[dir][i]; 289 if (!sw_acc_tbl_entry->valid) 290 continue; 291 sw_acc_tbl_entry->pkt_count += FLOW_CNTR_PKTS(stats[i], 292 dparms); 293 sw_acc_tbl_entry->byte_count += FLOW_CNTR_BYTES(stats[i], 294 dparms); 295 } 296 297 return rc; 298 } 299 300 static int32_t 301 ulp_fc_tf_flow_stat_get(struct bnxt_ulp_context *ctxt, 302 struct ulp_flow_db_res_params *res, 303 struct rte_flow_query_count *qcount) 304 { 305 struct tf *tfp; 306 struct bnxt_ulp_device_params *dparms; 307 struct tf_get_tbl_entry_parms parms = { 0 }; 308 struct tf_set_tbl_entry_parms sparms = { 0 }; 309 enum tf_tbl_type stype = TF_TBL_TYPE_ACT_STATS_64; 310 uint64_t stats = 0; 311 uint32_t dev_id = 0; 312 int32_t rc = 0; 313 314 tfp = bnxt_ulp_cntxt_tfp_get(ctxt, BNXT_ULP_SHARED_SESSION_NO); 315 if (!tfp) { 316 BNXT_TF_DBG(ERR, "Failed to get the truflow pointer\n"); 317 return -EINVAL; 318 } 319 320 if (bnxt_ulp_cntxt_dev_id_get(ctxt, &dev_id)) { 321 BNXT_TF_DBG(DEBUG, "Failed to get device id\n"); 322 bnxt_ulp_cntxt_entry_release(); 323 return -EINVAL; 324 } 325 326 dparms = bnxt_ulp_device_params_get(dev_id); 327 if (!dparms) { 328 BNXT_TF_DBG(DEBUG, "Failed to device parms\n"); 329 bnxt_ulp_cntxt_entry_release(); 330 return -EINVAL; 331 } 332 parms.dir = res->direction; 333 parms.type = stype; 334 parms.idx = res->resource_hndl; 335 parms.data_sz_in_bytes = sizeof(uint64_t); 336 parms.data = (uint8_t *)&stats; 337 rc = tf_get_tbl_entry(tfp, &parms); 338 if (rc) { 339 PMD_DRV_LOG(ERR, 340 "Get failed for id:0x%x rc:%d\n", 341 parms.idx, rc); 342 return rc; 343 } 344 qcount->hits = FLOW_CNTR_PKTS(stats, dparms); 345 if (qcount->hits) 346 qcount->hits_set = 1; 347 qcount->bytes = FLOW_CNTR_BYTES(stats, dparms); 348 if (qcount->bytes) 349 qcount->bytes_set = 1; 350 351 if (qcount->reset) { 352 stats = 0; 353 sparms.dir = res->direction; 354 sparms.type = stype; 355 sparms.idx = res->resource_hndl; 356 sparms.data = (uint8_t *)&stats; 357 sparms.data_sz_in_bytes = sizeof(uint64_t); 358 rc = tf_set_tbl_entry(tfp, &sparms); 359 if (rc) { 360 PMD_DRV_LOG(ERR, "Set failed for id:0x%x rc:%d\n", 361 sparms.idx, rc); 362 return rc; 363 } 364 } 365 return rc; 366 } 367 368 static int ulp_get_single_flow_stat(struct bnxt_ulp_context *ctxt, 369 struct tf *tfp, 370 struct bnxt_ulp_fc_info *fc_info, 371 enum tf_dir dir, 372 uint32_t hw_cntr_id, 373 struct bnxt_ulp_device_params *dparms) 374 { 375 int rc = 0; 376 struct tf_get_tbl_entry_parms parms = { 0 }; 377 enum tf_tbl_type stype = TF_TBL_TYPE_ACT_STATS_64; /* TBD:Template? */ 378 struct sw_acc_counter *sw_acc_tbl_entry = NULL, *t_sw; 379 uint64_t stats = 0; 380 uint32_t sw_cntr_indx = 0; 381 382 parms.dir = dir; 383 parms.type = stype; 384 parms.idx = hw_cntr_id; 385 /* 386 * TODO: 387 * Size of an entry needs to obtained from template 388 */ 389 parms.data_sz_in_bytes = sizeof(uint64_t); 390 parms.data = (uint8_t *)&stats; 391 rc = tf_get_tbl_entry(tfp, &parms); 392 if (rc) { 393 PMD_DRV_LOG(ERR, 394 "Get failed for id:0x%x rc:%d\n", 395 parms.idx, rc); 396 return rc; 397 } 398 399 /* TBD - Get PKT/BYTE COUNT SHIFT/MASK from Template */ 400 sw_cntr_indx = hw_cntr_id - fc_info->shadow_hw_tbl[dir].start_idx; 401 sw_acc_tbl_entry = &fc_info->sw_acc_tbl[dir][sw_cntr_indx]; 402 /* Some dpdk applications may accumulate the flow counters while some 403 * may not. In cases where the application is accumulating the counters 404 * the PMD need not do the accumulation itself and viceversa to report 405 * the correct flow counters. 406 */ 407 if (ctxt->cfg_data->accum_stats) { 408 sw_acc_tbl_entry->pkt_count += FLOW_CNTR_PKTS(stats, dparms); 409 sw_acc_tbl_entry->byte_count += FLOW_CNTR_BYTES(stats, dparms); 410 } else { 411 sw_acc_tbl_entry->pkt_count = FLOW_CNTR_PKTS(stats, dparms); 412 sw_acc_tbl_entry->byte_count = FLOW_CNTR_BYTES(stats, dparms); 413 } 414 415 /* Update the parent counters if it is child flow */ 416 if (sw_acc_tbl_entry->pc_flow_idx & FLOW_CNTR_PC_FLOW_VALID) { 417 uint32_t pc_idx; 418 419 /* Update the parent counters */ 420 t_sw = sw_acc_tbl_entry; 421 pc_idx = t_sw->pc_flow_idx & ~FLOW_CNTR_PC_FLOW_VALID; 422 if (ulp_flow_db_parent_flow_count_update(ctxt, pc_idx, 423 t_sw->pkt_count, 424 t_sw->byte_count)) { 425 PMD_DRV_LOG(ERR, "Error updating parent counters\n"); 426 } 427 } 428 429 return rc; 430 } 431 432 /* 433 * Alarm handler that will issue the TF-Core API to fetch 434 * data from the chip's internal flow counters 435 * 436 * ctxt [in] The ulp context for the flow counter manager 437 * 438 */ 439 440 void 441 ulp_fc_mgr_alarm_cb(void *arg __rte_unused) 442 { 443 int rc = 0; 444 unsigned int j; 445 enum tf_dir i; 446 struct bnxt_ulp_context *ctxt; 447 struct bnxt_ulp_fc_info *ulp_fc_info; 448 struct bnxt_ulp_device_params *dparms; 449 struct tf *tfp; 450 uint32_t dev_id, hw_cntr_id = 0, num_entries = 0; 451 452 ctxt = bnxt_ulp_cntxt_entry_acquire(); 453 if (ctxt == NULL) { 454 BNXT_TF_DBG(INFO, "could not get the ulp context lock\n"); 455 rte_eal_alarm_set(US_PER_S * ULP_FC_TIMER, 456 ulp_fc_mgr_alarm_cb, NULL); 457 return; 458 } 459 460 ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ctxt); 461 if (!ulp_fc_info) { 462 bnxt_ulp_cntxt_entry_release(); 463 return; 464 } 465 466 if (bnxt_ulp_cntxt_dev_id_get(ctxt, &dev_id)) { 467 BNXT_TF_DBG(DEBUG, "Failed to get device id\n"); 468 bnxt_ulp_cntxt_entry_release(); 469 return; 470 } 471 472 dparms = bnxt_ulp_device_params_get(dev_id); 473 if (!dparms) { 474 BNXT_TF_DBG(DEBUG, "Failed to device parms\n"); 475 bnxt_ulp_cntxt_entry_release(); 476 return; 477 } 478 479 tfp = bnxt_ulp_cntxt_tfp_get(ctxt, BNXT_ULP_SHARED_SESSION_NO); 480 if (!tfp) { 481 BNXT_TF_DBG(ERR, "Failed to get the truflow pointer\n"); 482 bnxt_ulp_cntxt_entry_release(); 483 return; 484 } 485 486 /* 487 * Take the fc_lock to ensure no flow is destroyed 488 * during the bulk get 489 */ 490 if (pthread_mutex_trylock(&ulp_fc_info->fc_lock)) 491 goto out; 492 493 if (!ulp_fc_info->num_entries) { 494 pthread_mutex_unlock(&ulp_fc_info->fc_lock); 495 ulp_fc_mgr_thread_cancel(ctxt); 496 bnxt_ulp_cntxt_entry_release(); 497 return; 498 } 499 /* 500 * Commented for now till GET_BULK is resolved, just get the first flow 501 * stat for now 502 for (i = 0; i < TF_DIR_MAX; i++) { 503 rc = ulp_bulk_get_flow_stats(tfp, ulp_fc_info, i, 504 dparms->flow_count_db_entries); 505 if (rc) 506 break; 507 } 508 */ 509 510 /* reset the parent accumulation counters before accumulation if any */ 511 ulp_flow_db_parent_flow_count_reset(ctxt); 512 513 num_entries = dparms->flow_count_db_entries / 2; 514 for (i = 0; i < TF_DIR_MAX; i++) { 515 for (j = 0; j < num_entries; j++) { 516 if (!ulp_fc_info->sw_acc_tbl[i][j].valid) 517 continue; 518 hw_cntr_id = ulp_fc_info->sw_acc_tbl[i][j].hw_cntr_id; 519 rc = ulp_get_single_flow_stat(ctxt, tfp, ulp_fc_info, i, 520 hw_cntr_id, dparms); 521 if (rc) 522 break; 523 } 524 } 525 526 pthread_mutex_unlock(&ulp_fc_info->fc_lock); 527 528 /* 529 * If cmd fails once, no need of 530 * invoking again every second 531 */ 532 533 if (rc) { 534 ulp_fc_mgr_thread_cancel(ctxt); 535 bnxt_ulp_cntxt_entry_release(); 536 return; 537 } 538 out: 539 bnxt_ulp_cntxt_entry_release(); 540 rte_eal_alarm_set(US_PER_S * ULP_FC_TIMER, 541 ulp_fc_mgr_alarm_cb, NULL); 542 } 543 544 /* 545 * Set the starting index that indicates the first HW flow 546 * counter ID 547 * 548 * ctxt [in] The ulp context for the flow counter manager 549 * 550 * dir [in] The direction of the flow 551 * 552 * start_idx [in] The HW flow counter ID 553 * 554 */ 555 bool ulp_fc_mgr_start_idx_isset(struct bnxt_ulp_context *ctxt, enum tf_dir dir) 556 { 557 struct bnxt_ulp_fc_info *ulp_fc_info; 558 559 ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ctxt); 560 561 if (ulp_fc_info) 562 return ulp_fc_info->shadow_hw_tbl[dir].start_idx_is_set; 563 564 return false; 565 } 566 567 /* 568 * Set the starting index that indicates the first HW flow 569 * counter ID 570 * 571 * ctxt [in] The ulp context for the flow counter manager 572 * 573 * dir [in] The direction of the flow 574 * 575 * start_idx [in] The HW flow counter ID 576 * 577 */ 578 int32_t ulp_fc_mgr_start_idx_set(struct bnxt_ulp_context *ctxt, enum tf_dir dir, 579 uint32_t start_idx) 580 { 581 struct bnxt_ulp_fc_info *ulp_fc_info; 582 583 ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ctxt); 584 585 if (!ulp_fc_info) 586 return -EIO; 587 588 if (!ulp_fc_info->shadow_hw_tbl[dir].start_idx_is_set) { 589 ulp_fc_info->shadow_hw_tbl[dir].start_idx = start_idx; 590 ulp_fc_info->shadow_hw_tbl[dir].start_idx_is_set = true; 591 } 592 593 return 0; 594 } 595 596 /* 597 * Set the corresponding SW accumulator table entry based on 598 * the difference between this counter ID and the starting 599 * counter ID. Also, keep track of num of active counter enabled 600 * flows. 601 * 602 * ctxt [in] The ulp context for the flow counter manager 603 * 604 * dir [in] The direction of the flow 605 * 606 * hw_cntr_id [in] The HW flow counter ID 607 * 608 */ 609 int32_t ulp_fc_mgr_cntr_set(struct bnxt_ulp_context *ctxt, enum tf_dir dir, 610 uint32_t hw_cntr_id) 611 { 612 struct bnxt_ulp_fc_info *ulp_fc_info; 613 uint32_t sw_cntr_idx; 614 615 ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ctxt); 616 if (!ulp_fc_info) 617 return -EIO; 618 619 if (!ulp_fc_info->num_counters) 620 return 0; 621 622 pthread_mutex_lock(&ulp_fc_info->fc_lock); 623 sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx; 624 ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = true; 625 ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = hw_cntr_id; 626 ulp_fc_info->num_entries++; 627 pthread_mutex_unlock(&ulp_fc_info->fc_lock); 628 629 return 0; 630 } 631 632 /* 633 * Reset the corresponding SW accumulator table entry based on 634 * the difference between this counter ID and the starting 635 * counter ID. 636 * 637 * ctxt [in] The ulp context for the flow counter manager 638 * 639 * dir [in] The direction of the flow 640 * 641 * hw_cntr_id [in] The HW flow counter ID 642 * 643 */ 644 int32_t ulp_fc_mgr_cntr_reset(struct bnxt_ulp_context *ctxt, enum tf_dir dir, 645 uint32_t hw_cntr_id) 646 { 647 struct bnxt_ulp_fc_info *ulp_fc_info; 648 uint32_t sw_cntr_idx; 649 650 ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ctxt); 651 if (!ulp_fc_info) 652 return -EIO; 653 654 if (!ulp_fc_info->num_counters) 655 return 0; 656 657 pthread_mutex_lock(&ulp_fc_info->fc_lock); 658 sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx; 659 ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = false; 660 ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = 0; 661 ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].pkt_count = 0; 662 ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].byte_count = 0; 663 ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].pc_flow_idx = 0; 664 ulp_fc_info->num_entries--; 665 pthread_mutex_unlock(&ulp_fc_info->fc_lock); 666 667 return 0; 668 } 669 670 /* 671 * Fill the rte_flow_query_count 'data' argument passed 672 * in the rte_flow_query() with the values obtained and 673 * accumulated locally. 674 * 675 * ctxt [in] The ulp context for the flow counter manager 676 * 677 * flow_id [in] The HW flow ID 678 * 679 * count [out] The rte_flow_query_count 'data' that is set 680 * 681 */ 682 int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt, 683 uint32_t flow_id, 684 struct rte_flow_query_count *count) 685 { 686 int rc = 0; 687 uint32_t nxt_resource_index = 0; 688 struct bnxt_ulp_fc_info *ulp_fc_info; 689 struct ulp_flow_db_res_params params; 690 enum tf_dir dir; 691 uint32_t hw_cntr_id = 0, sw_cntr_idx = 0; 692 struct sw_acc_counter *sw_acc_tbl_entry; 693 bool found_cntr_resource = false; 694 bool found_parent_flow = false; 695 uint32_t pc_idx = 0; 696 697 ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ctxt); 698 if (!ulp_fc_info) 699 return -ENODEV; 700 701 if (bnxt_ulp_cntxt_acquire_fdb_lock(ctxt)) 702 return -EIO; 703 704 do { 705 rc = ulp_flow_db_resource_get(ctxt, 706 BNXT_ULP_FDB_TYPE_REGULAR, 707 flow_id, 708 &nxt_resource_index, 709 ¶ms); 710 if (params.resource_func == 711 BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE && 712 (params.resource_sub_type == 713 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT || 714 params.resource_sub_type == 715 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_EXT_COUNT)) { 716 found_cntr_resource = true; 717 break; 718 } 719 if (params.resource_func == 720 BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW) { 721 found_parent_flow = true; 722 pc_idx = params.resource_hndl; 723 } 724 725 } while (!rc && nxt_resource_index); 726 727 bnxt_ulp_cntxt_release_fdb_lock(ctxt); 728 729 if (rc || !found_cntr_resource) 730 return rc; 731 732 dir = params.direction; 733 hw_cntr_id = params.resource_hndl; 734 if (!found_parent_flow && 735 params.resource_sub_type == 736 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT) { 737 if (!ulp_fc_info->num_counters) 738 return ulp_fc_tf_flow_stat_get(ctxt, ¶ms, count); 739 740 /* TODO: 741 * Think about optimizing with try_lock later 742 */ 743 pthread_mutex_lock(&ulp_fc_info->fc_lock); 744 sw_cntr_idx = hw_cntr_id - 745 ulp_fc_info->shadow_hw_tbl[dir].start_idx; 746 sw_acc_tbl_entry = &ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx]; 747 if (sw_acc_tbl_entry->pkt_count) { 748 count->hits_set = 1; 749 count->bytes_set = 1; 750 count->hits = sw_acc_tbl_entry->pkt_count; 751 count->bytes = sw_acc_tbl_entry->byte_count; 752 } 753 if (count->reset) { 754 sw_acc_tbl_entry->pkt_count = 0; 755 sw_acc_tbl_entry->byte_count = 0; 756 } 757 pthread_mutex_unlock(&ulp_fc_info->fc_lock); 758 } else if (found_parent_flow && 759 params.resource_sub_type == 760 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT) { 761 /* Get stats from the parent child table */ 762 ulp_flow_db_parent_flow_count_get(ctxt, pc_idx, 763 &count->hits, &count->bytes, 764 count->reset); 765 if (count->hits) 766 count->hits_set = 1; 767 if (count->bytes) 768 count->bytes_set = 1; 769 } else { 770 /* TBD: Handle External counters */ 771 rc = -EINVAL; 772 } 773 774 return rc; 775 } 776 777 /* 778 * Set the parent flow if it is SW accumulation counter entry. 779 * 780 * ctxt [in] The ulp context for the flow counter manager 781 * 782 * dir [in] The direction of the flow 783 * 784 * hw_cntr_id [in] The HW flow counter ID 785 * 786 * pc_idx [in] parent child db index 787 * 788 */ 789 int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt, 790 enum tf_dir dir, 791 uint32_t hw_cntr_id, 792 uint32_t pc_idx) 793 { 794 struct bnxt_ulp_fc_info *ulp_fc_info; 795 uint32_t sw_cntr_idx; 796 int32_t rc = 0; 797 798 ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ctxt); 799 if (!ulp_fc_info) 800 return -EIO; 801 802 pthread_mutex_lock(&ulp_fc_info->fc_lock); 803 sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx; 804 if (ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid) { 805 pc_idx |= FLOW_CNTR_PC_FLOW_VALID; 806 ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].pc_flow_idx = pc_idx; 807 } else { 808 BNXT_TF_DBG(ERR, "Failed to set parent flow id %x:%x\n", 809 hw_cntr_id, pc_idx); 810 rc = -ENOENT; 811 } 812 pthread_mutex_unlock(&ulp_fc_info->fc_lock); 813 814 return rc; 815 } 816