1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2023 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <rte_bitops.h> 7 #include <rte_malloc.h> 8 9 #include "bnxt.h" 10 #include "bnxt_tf_common.h" 11 #include "bnxt_ulp_utils.h" 12 #include "ulp_template_struct.h" 13 #include "ulp_mapper.h" 14 #include "ulp_flow_db.h" 15 #include "ulp_fc_mgr.h" 16 #include "ulp_sc_mgr.h" 17 #include "ulp_tun.h" 18 #ifdef TF_FLOW_SCALE_QUERY 19 #include "tf_resources.h" 20 #include "tfc_resources.h" 21 #endif /* TF_FLOW_SCALE_QUERY */ 22 23 #define ULP_FLOW_DB_RES_DIR_BIT 31 24 #define ULP_FLOW_DB_RES_DIR_MASK 0x80000000 25 #define ULP_FLOW_DB_RES_NXT_MASK 0x7FFFFFFF 26 27 /* Macro to copy the nxt_resource_idx */ 28 #define ULP_FLOW_DB_RES_NXT_SET(dst, src) {(dst) |= ((src) &\ 29 ULP_FLOW_DB_RES_NXT_MASK); } 30 #define ULP_FLOW_DB_RES_NXT_RESET(dst) ((dst) &= ~(ULP_FLOW_DB_RES_NXT_MASK)) 31 32 /* 33 * Helper function to set the bit in the active flows 34 * No validation is done in this function. 35 * 36 * flow_db [in] Ptr to flow database 37 * flow_type [in] - specify default or regular 38 * idx [in] The index to bit to be set or reset. 39 * flag [in] 1 to set and 0 to reset. 40 * 41 * returns none 42 */ 43 static void 44 ulp_flow_db_active_flows_bit_set(struct bnxt_ulp_flow_db *flow_db, 45 enum bnxt_ulp_fdb_type flow_type, 46 uint32_t idx, 47 uint32_t flag) 48 { 49 struct bnxt_ulp_flow_tbl *f_tbl = &flow_db->flow_tbl; 50 uint32_t a_idx = idx / ULP_INDEX_BITMAP_SIZE; 51 52 if (flag) { 53 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR || flow_type == 54 BNXT_ULP_FDB_TYPE_RID) 55 ULP_INDEX_BITMAP_SET(f_tbl->active_reg_flows[a_idx], 56 idx); 57 if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT || flow_type == 58 BNXT_ULP_FDB_TYPE_RID) 59 ULP_INDEX_BITMAP_SET(f_tbl->active_dflt_flows[a_idx], 60 idx); 61 } else { 62 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR || flow_type == 63 BNXT_ULP_FDB_TYPE_RID) 64 ULP_INDEX_BITMAP_RESET(f_tbl->active_reg_flows[a_idx], 65 idx); 66 if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT || flow_type == 67 BNXT_ULP_FDB_TYPE_RID) 68 ULP_INDEX_BITMAP_RESET(f_tbl->active_dflt_flows[a_idx], 69 idx); 70 } 71 } 72 73 /* 74 * Helper function to check if given fid is active flow. 75 * No validation being done in this function. 76 * 77 * flow_db [in] Ptr to flow database 78 * flow_type [in] - specify default or regular 79 * idx [in] The index to bit to be set or reset. 80 * 81 * returns 1 on set or 0 if not set. 82 */ 83 static int32_t 84 ulp_flow_db_active_flows_bit_is_set(struct bnxt_ulp_flow_db *flow_db, 85 enum bnxt_ulp_fdb_type flow_type, 86 uint32_t idx) 87 { 88 struct bnxt_ulp_flow_tbl *f_tbl = &flow_db->flow_tbl; 89 uint32_t a_idx = idx / ULP_INDEX_BITMAP_SIZE; 90 uint32_t reg, dflt; 91 92 reg = ULP_INDEX_BITMAP_GET(f_tbl->active_reg_flows[a_idx], idx); 93 dflt = ULP_INDEX_BITMAP_GET(f_tbl->active_dflt_flows[a_idx], idx); 94 95 switch (flow_type) { 96 case BNXT_ULP_FDB_TYPE_REGULAR: 97 return (reg && !dflt); 98 case BNXT_ULP_FDB_TYPE_DEFAULT: 99 return (!reg && dflt); 100 case BNXT_ULP_FDB_TYPE_RID: 101 return (reg && dflt); 102 default: 103 return 0; 104 } 105 } 106 107 static inline enum tf_dir 108 ulp_flow_db_resource_dir_get(struct ulp_fdb_resource_info *res_info) 109 { 110 return ((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_DIR_MASK) >> 111 ULP_FLOW_DB_RES_DIR_BIT); 112 } 113 114 static inline uint8_t 115 ulp_flow_db_resource_func_get(struct ulp_fdb_resource_info *res_info) 116 { 117 return res_info->resource_func; 118 } 119 120 /* 121 * Helper function to copy the resource params to resource info 122 * No validation being done in this function. 123 * 124 * resource_info [out] Ptr to resource information 125 * params [in] The input params from the caller 126 * returns none 127 */ 128 static void 129 ulp_flow_db_res_params_to_info(struct ulp_fdb_resource_info *resource_info, 130 struct ulp_flow_db_res_params *params) 131 { 132 resource_info->nxt_resource_idx |= ((params->direction << 133 ULP_FLOW_DB_RES_DIR_BIT) & 134 ULP_FLOW_DB_RES_DIR_MASK); 135 resource_info->resource_func = params->resource_func; 136 resource_info->resource_type = params->resource_type; 137 resource_info->resource_sub_type = params->resource_sub_type; 138 resource_info->fdb_flags = params->fdb_flags; 139 resource_info->resource_hndl = params->resource_hndl; 140 } 141 142 /* 143 * Helper function to copy the resource params to resource info 144 * No validation being done in this function. 145 * 146 * resource_info [in] Ptr to resource information 147 * params [out] The output params to the caller 148 * 149 * returns none 150 */ 151 static void 152 ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info, 153 struct ulp_flow_db_res_params *params) 154 { 155 memset(params, 0, sizeof(struct ulp_flow_db_res_params)); 156 /* use the helper function to get the resource func */ 157 params->direction = ulp_flow_db_resource_dir_get(resource_info); 158 params->resource_func = ulp_flow_db_resource_func_get(resource_info); 159 params->resource_type = resource_info->resource_type; 160 params->resource_sub_type = resource_info->resource_sub_type; 161 params->fdb_flags = resource_info->fdb_flags; 162 params->resource_hndl = resource_info->resource_hndl; 163 } 164 165 /* 166 * Helper function to allocate the flow table and initialize 167 * the stack for allocation operations. 168 * 169 * flow_db [in] Ptr to flow database structure 170 * 171 * Returns 0 on success or negative number on failure. 172 */ 173 static int32_t 174 ulp_flow_db_alloc_resource(struct bnxt_ulp_flow_db *flow_db) 175 { 176 uint32_t idx = 0; 177 struct bnxt_ulp_flow_tbl *flow_tbl; 178 uint32_t size; 179 180 flow_tbl = &flow_db->flow_tbl; 181 182 size = sizeof(struct ulp_fdb_resource_info) * flow_tbl->num_resources; 183 flow_tbl->flow_resources = 184 rte_zmalloc("ulp_fdb_resource_info", size, 0); 185 186 if (!flow_tbl->flow_resources) { 187 BNXT_DRV_DBG(ERR, "Failed to alloc memory for flow table\n"); 188 return -ENOMEM; 189 } 190 size = sizeof(uint32_t) * flow_tbl->num_resources; 191 flow_tbl->flow_tbl_stack = rte_zmalloc("flow_tbl_stack", size, 0); 192 if (!flow_tbl->flow_tbl_stack) { 193 BNXT_DRV_DBG(ERR, "Failed to alloc memory flow tbl stack\n"); 194 return -ENOMEM; 195 } 196 size = (flow_tbl->num_flows / sizeof(uint64_t)) + 1; 197 size = ULP_BYTE_ROUND_OFF_8(size); 198 flow_tbl->active_reg_flows = rte_zmalloc("active reg flows", size, 199 ULP_BUFFER_ALIGN_64_BYTE); 200 if (!flow_tbl->active_reg_flows) { 201 BNXT_DRV_DBG(ERR, "Failed to alloc memory active reg flows\n"); 202 return -ENOMEM; 203 } 204 205 flow_tbl->active_dflt_flows = rte_zmalloc("active dflt flows", size, 206 ULP_BUFFER_ALIGN_64_BYTE); 207 if (!flow_tbl->active_dflt_flows) { 208 BNXT_DRV_DBG(ERR, "Failed to alloc memory active dflt flows\n"); 209 return -ENOMEM; 210 } 211 212 /* Initialize the stack table. */ 213 for (idx = 0; idx < flow_tbl->num_resources; idx++) 214 flow_tbl->flow_tbl_stack[idx] = idx; 215 216 /* Ignore the first element in the list. */ 217 flow_tbl->head_index = 1; 218 /* Tail points to the last entry in the list. */ 219 flow_tbl->tail_index = flow_tbl->num_resources - 1; 220 return 0; 221 } 222 223 /* 224 * Helper function to deallocate the flow table. 225 * 226 * flow_db [in] Ptr to flow database structure 227 * 228 * Returns none. 229 */ 230 static void 231 ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db) 232 { 233 struct bnxt_ulp_flow_tbl *flow_tbl = &flow_db->flow_tbl; 234 235 /* Free all the allocated tables in the flow table. */ 236 if (flow_tbl->active_reg_flows) { 237 rte_free(flow_tbl->active_reg_flows); 238 flow_tbl->active_reg_flows = NULL; 239 } 240 if (flow_tbl->active_dflt_flows) { 241 rte_free(flow_tbl->active_dflt_flows); 242 flow_tbl->active_dflt_flows = NULL; 243 } 244 245 if (flow_tbl->flow_tbl_stack) { 246 rte_free(flow_tbl->flow_tbl_stack); 247 flow_tbl->flow_tbl_stack = NULL; 248 } 249 250 if (flow_tbl->flow_resources) { 251 rte_free(flow_tbl->flow_resources); 252 flow_tbl->flow_resources = NULL; 253 } 254 } 255 256 /* 257 * Helper function to add function id to the flow table 258 * 259 * flow_db [in] Ptr to flow table 260 * flow_id [in] The flow id of the flow 261 * func_id [in] The func_id to be set, for reset pass zero 262 * 263 * returns none 264 */ 265 static void 266 ulp_flow_db_func_id_set(struct bnxt_ulp_flow_db *flow_db, 267 uint32_t flow_id, 268 uint32_t func_id) 269 { 270 /* set the function id in the function table */ 271 if (flow_id < flow_db->func_id_tbl_size) 272 flow_db->func_id_tbl[flow_id] = func_id; 273 else /* This should never happen */ 274 BNXT_DRV_DBG(ERR, "Invalid flow id, flowdb corrupt\n"); 275 } 276 277 /* 278 * Initialize the parent-child database. Memory is allocated in this 279 * call and assigned to the database 280 * 281 * flow_db [in] Ptr to flow table 282 * num_entries[in] - number of entries to allocate 283 * 284 * Returns 0 on success or negative number on failure. 285 */ 286 static int32_t 287 ulp_flow_db_parent_tbl_init(struct bnxt_ulp_flow_db *flow_db, 288 uint32_t num_entries) 289 { 290 struct ulp_fdb_parent_child_db *p_db; 291 uint32_t size, idx; 292 293 if (!num_entries) 294 return 0; 295 296 /* update the sizes for the allocation */ 297 p_db = &flow_db->parent_child_db; 298 p_db->child_bitset_size = (flow_db->flow_tbl.num_flows / 299 sizeof(uint64_t)) + 1; /* size in bytes */ 300 p_db->child_bitset_size = ULP_BYTE_ROUND_OFF_8(p_db->child_bitset_size); 301 p_db->entries_count = num_entries; 302 303 /* allocate the memory */ 304 p_db->parent_flow_tbl = rte_zmalloc("fdb parent flow tbl", 305 sizeof(struct ulp_fdb_parent_info) * 306 p_db->entries_count, 0); 307 if (!p_db->parent_flow_tbl) { 308 BNXT_DRV_DBG(ERR, 309 "Failed to allocate memory fdb parent flow tbl\n"); 310 return -ENOMEM; 311 } 312 size = p_db->child_bitset_size * p_db->entries_count; 313 314 /* 315 * allocate the big chunk of memory to be statically carved into 316 * child_fid_bitset pointer. 317 */ 318 p_db->parent_flow_tbl_mem = rte_zmalloc("fdb parent flow tbl mem", 319 size, 320 ULP_BUFFER_ALIGN_64_BYTE); 321 if (!p_db->parent_flow_tbl_mem) { 322 BNXT_DRV_DBG(ERR, 323 "Failed to allocate memory fdb parent flow mem\n"); 324 return -ENOMEM; 325 } 326 327 /* set the pointers in parent table to their offsets */ 328 for (idx = 0 ; idx < p_db->entries_count; idx++) { 329 p_db->parent_flow_tbl[idx].child_fid_bitset = 330 (uint64_t *)&p_db->parent_flow_tbl_mem[idx * 331 p_db->child_bitset_size]; 332 } 333 /* success */ 334 return 0; 335 } 336 337 /* 338 * Deinitialize the parent-child database. Memory is deallocated in 339 * this call and all flows should have been purged before this 340 * call. 341 * 342 * flow_db [in] Ptr to flow table 343 * 344 * Returns none 345 */ 346 static void 347 ulp_flow_db_parent_tbl_deinit(struct bnxt_ulp_flow_db *flow_db) 348 { 349 /* free the memory related to parent child database */ 350 if (flow_db->parent_child_db.parent_flow_tbl_mem) { 351 rte_free(flow_db->parent_child_db.parent_flow_tbl_mem); 352 flow_db->parent_child_db.parent_flow_tbl_mem = NULL; 353 } 354 if (flow_db->parent_child_db.parent_flow_tbl) { 355 rte_free(flow_db->parent_child_db.parent_flow_tbl); 356 flow_db->parent_child_db.parent_flow_tbl = NULL; 357 } 358 } 359 360 /* 361 * Initialize the flow database. Memory is allocated in this 362 * call and assigned to the flow database. 363 * 364 * ulp_ctxt [in] Ptr to ulp context 365 * 366 * Returns 0 on success or negative number on failure. 367 */ 368 int32_t 369 ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt) 370 { 371 struct bnxt_ulp_device_params *dparms; 372 struct bnxt_ulp_flow_tbl *flow_tbl; 373 struct bnxt_ulp_flow_db *flow_db; 374 uint32_t dev_id, num_flows; 375 enum bnxt_ulp_flow_mem_type mtype; 376 377 /* Get the dev specific number of flows that needed to be supported. */ 378 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) { 379 BNXT_DRV_DBG(ERR, "Invalid device id\n"); 380 return -EINVAL; 381 } 382 383 dparms = bnxt_ulp_device_params_get(dev_id); 384 if (!dparms) { 385 BNXT_DRV_DBG(ERR, "could not fetch the device params\n"); 386 return -ENODEV; 387 } 388 389 flow_db = rte_zmalloc("bnxt_ulp_flow_db", 390 sizeof(struct bnxt_ulp_flow_db), 0); 391 if (!flow_db) { 392 BNXT_DRV_DBG(ERR, 393 "Failed to allocate memory for flow table ptr\n"); 394 return -ENOMEM; 395 } 396 397 /* Attach the flow database to the ulp context. */ 398 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db); 399 400 /* Determine the number of flows based on EM type */ 401 if (bnxt_ulp_cntxt_mem_type_get(ulp_ctxt, &mtype)) 402 goto error_free; 403 404 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) 405 num_flows = dparms->int_flow_db_num_entries; 406 else 407 num_flows = dparms->ext_flow_db_num_entries; 408 409 /* Populate the regular flow table limits. */ 410 flow_tbl = &flow_db->flow_tbl; 411 flow_tbl->num_flows = num_flows + 1; 412 flow_tbl->num_resources = ((num_flows + 1) * 413 dparms->num_resources_per_flow); 414 415 /* Include the default flow table limits. */ 416 flow_tbl->num_flows += (BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1); 417 flow_tbl->num_resources += ((BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1) * 418 BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES); 419 420 /* Allocate the resource for the flow table. */ 421 if (ulp_flow_db_alloc_resource(flow_db)) 422 goto error_free; 423 424 /* add 1 since we are not using index 0 for flow id */ 425 flow_db->func_id_tbl_size = flow_tbl->num_flows + 1; 426 /* Allocate the function Id table */ 427 flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table", 428 flow_db->func_id_tbl_size * 429 sizeof(uint16_t), 0); 430 if (!flow_db->func_id_tbl) { 431 BNXT_DRV_DBG(ERR, 432 "Failed to allocate mem for flow table func id\n"); 433 goto error_free; 434 } 435 /* initialize the parent child database */ 436 if (ulp_flow_db_parent_tbl_init(flow_db, 437 dparms->fdb_parent_flow_entries)) { 438 BNXT_DRV_DBG(ERR, 439 "Failed to allocate mem for parent child db\n"); 440 goto error_free; 441 } 442 443 /* All good so return. */ 444 BNXT_DRV_DBG(DEBUG, "FlowDB initialized with %d flows.\n", 445 flow_tbl->num_flows); 446 return 0; 447 error_free: 448 ulp_flow_db_deinit(ulp_ctxt); 449 return -ENOMEM; 450 } 451 452 /* 453 * Deinitialize the flow database. Memory is deallocated in 454 * this call and all flows should have been purged before this 455 * call. 456 * 457 * ulp_ctxt [in] Ptr to ulp context 458 * 459 * Returns 0 on success. 460 */ 461 int32_t 462 ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt) 463 { 464 struct bnxt_ulp_flow_db *flow_db; 465 466 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 467 if (!flow_db) 468 return -EINVAL; 469 470 /* Detach the flow database from the ulp context. */ 471 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL); 472 473 /* Free up all the memory. */ 474 ulp_flow_db_parent_tbl_deinit(flow_db); 475 ulp_flow_db_dealloc_resource(flow_db); 476 rte_free(flow_db->func_id_tbl); 477 rte_free(flow_db); 478 479 return 0; 480 } 481 482 /* 483 * Allocate the flow database entry 484 * 485 * ulp_ctxt [in] Ptr to ulp_context 486 * flow_type [in] - specify default or regular 487 * func_id [in].function id of the ingress port 488 * fid [out] The index to the flow entry 489 * 490 * returns 0 on success and negative on failure. 491 */ 492 int32_t 493 ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt, 494 enum bnxt_ulp_fdb_type flow_type, 495 uint16_t func_id, 496 uint32_t *fid) 497 { 498 struct bnxt_ulp_flow_db *flow_db; 499 struct bnxt_ulp_flow_tbl *flow_tbl; 500 501 *fid = 0; /* Initialize fid to invalid value */ 502 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 503 if (!flow_db) { 504 BNXT_DRV_DBG(ERR, "Invalid Arguments\n"); 505 return -EINVAL; 506 } 507 508 if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) { 509 BNXT_DRV_DBG(ERR, "Invalid flow type\n"); 510 return -EINVAL; 511 } 512 513 flow_tbl = &flow_db->flow_tbl; 514 /* check for max flows */ 515 if (flow_tbl->num_flows <= flow_tbl->head_index) { 516 BNXT_DRV_DBG(ERR, "Flow database has reached max flows\n"); 517 return -ENOMEM; 518 } 519 if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) { 520 BNXT_DRV_DBG(ERR, "Flow database has reached max resources\n"); 521 return -ENOMEM; 522 } 523 *fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index]; 524 flow_tbl->head_index++; 525 526 /* Set the flow type */ 527 ulp_flow_db_active_flows_bit_set(flow_db, flow_type, *fid, 1); 528 529 /* function id update is only valid for regular flow table */ 530 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR) 531 ulp_flow_db_func_id_set(flow_db, *fid, func_id); 532 533 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 534 BNXT_DRV_DBG(DEBUG, "flow_id = %u:%u allocated\n", flow_type, *fid); 535 #endif 536 /* return success */ 537 return 0; 538 } 539 540 /* 541 * Allocate the flow database entry. 542 * The params->critical_resource has to be set to 0 to allocate a new resource. 543 * 544 * ulp_ctxt [in] Ptr to ulp_context 545 * flow_type [in] Specify it is regular or default flow 546 * fid [in] The index to the flow entry 547 * params [in] The contents to be copied into resource 548 * 549 * returns 0 on success and negative on failure. 550 */ 551 int32_t 552 ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt, 553 enum bnxt_ulp_fdb_type flow_type, 554 uint32_t fid, 555 struct ulp_flow_db_res_params *params) 556 { 557 struct bnxt_ulp_flow_db *flow_db; 558 struct bnxt_ulp_flow_tbl *flow_tbl; 559 struct ulp_fdb_resource_info *resource, *fid_resource; 560 struct bnxt_ulp_fc_info *ulp_fc_info; 561 uint32_t idx; 562 563 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 564 if (!flow_db) { 565 BNXT_DRV_DBG(ERR, "Invalid Arguments\n"); 566 return -EINVAL; 567 } 568 569 if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) { 570 BNXT_DRV_DBG(ERR, "Invalid flow type\n"); 571 return -EINVAL; 572 } 573 574 flow_tbl = &flow_db->flow_tbl; 575 /* check for max flows */ 576 if (fid >= flow_tbl->num_flows || !fid) { 577 BNXT_DRV_DBG(ERR, "Invalid flow index\n"); 578 return -EINVAL; 579 } 580 581 /* check if the flow is active or not */ 582 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) { 583 BNXT_DRV_DBG(ERR, "flow does not exist %x:%x\n", flow_type, 584 fid); 585 return -EINVAL; 586 } 587 588 /* check for max resource */ 589 if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) { 590 BNXT_DRV_DBG(ERR, "Flow db has reached max resources\n"); 591 return -ENOMEM; 592 } 593 fid_resource = &flow_tbl->flow_resources[fid]; 594 595 if (params->critical_resource && (fid_resource->fdb_flags & 596 ULP_FDB_FLAG_CRITICAL_RES)) { 597 BNXT_DRV_DBG(DEBUG, "Ignore multiple critical resources\n"); 598 /* Ignore the multiple critical resources */ 599 params->critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 600 } 601 602 if (!params->critical_resource) { 603 /* Not the critical_resource so allocate a resource */ 604 idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index]; 605 resource = &flow_tbl->flow_resources[idx]; 606 flow_tbl->tail_index--; 607 608 /* Update the chain list of resource*/ 609 ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx, 610 fid_resource->nxt_resource_idx); 611 /* update the contents */ 612 ulp_flow_db_res_params_to_info(resource, params); 613 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx); 614 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx, 615 idx); 616 } else { 617 /* critical resource. Just update the fid resource */ 618 ulp_flow_db_res_params_to_info(fid_resource, params); 619 fid_resource->fdb_flags |= ULP_FDB_FLAG_CRITICAL_RES; 620 } 621 622 ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ulp_ctxt); 623 if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 && 624 params->resource_sub_type == 625 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT && 626 ulp_fc_info && ulp_fc_info->num_counters) { 627 /* Store the first HW counter ID for this table */ 628 if (!ulp_fc_mgr_start_idx_isset(ulp_ctxt, params->direction)) 629 ulp_fc_mgr_start_idx_set(ulp_ctxt, params->direction, 630 params->resource_hndl); 631 632 ulp_fc_mgr_cntr_set(ulp_ctxt, params->direction, 633 params->resource_hndl, 634 ulp_flow_db_shared_session_get(params)); 635 636 if (!ulp_fc_mgr_thread_isstarted(ulp_ctxt)) 637 ulp_fc_mgr_thread_start(ulp_ctxt); 638 639 if (!ulp_sc_mgr_thread_isstarted(ulp_ctxt)) 640 ulp_sc_mgr_thread_start(ulp_ctxt); 641 } 642 643 /* all good, return success */ 644 return 0; 645 } 646 647 /* 648 * Free the flow database entry. 649 * The params->critical_resource has to be set to 1 to free the first resource. 650 * 651 * ulp_ctxt [in] Ptr to ulp_context 652 * flow_type [in] Specify it is regular or default flow 653 * fid [in] The index to the flow entry 654 * params [in/out] The contents to be copied into params. 655 * Only the critical_resource needs to be set by the caller. 656 * 657 * Returns 0 on success and negative on failure. 658 */ 659 int32_t 660 ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt, 661 enum bnxt_ulp_fdb_type flow_type, 662 uint32_t fid, 663 struct ulp_flow_db_res_params *params) 664 { 665 struct bnxt_ulp_flow_db *flow_db; 666 struct bnxt_ulp_flow_tbl *flow_tbl; 667 struct ulp_fdb_resource_info *nxt_resource, *fid_resource; 668 uint32_t nxt_idx = 0; 669 670 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 671 if (!flow_db) { 672 BNXT_DRV_DBG(ERR, "Invalid Arguments\n"); 673 return -EINVAL; 674 } 675 676 if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) { 677 BNXT_DRV_DBG(ERR, "Invalid flow type\n"); 678 return -EINVAL; 679 } 680 681 flow_tbl = &flow_db->flow_tbl; 682 /* check for max flows */ 683 if (fid >= flow_tbl->num_flows || !fid) { 684 BNXT_DRV_DBG(ERR, "Invalid flow index %x\n", fid); 685 return -EINVAL; 686 } 687 688 /* check if the flow is active or not */ 689 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) { 690 BNXT_DRV_DBG(ERR, "flow does not exist %x:%x\n", flow_type, 691 fid); 692 return -EINVAL; 693 } 694 695 fid_resource = &flow_tbl->flow_resources[fid]; 696 if (!params->critical_resource) { 697 /* Not the critical resource so free the resource */ 698 ULP_FLOW_DB_RES_NXT_SET(nxt_idx, 699 fid_resource->nxt_resource_idx); 700 if (!nxt_idx) { 701 /* reached end of resources */ 702 return -ENOENT; 703 } 704 nxt_resource = &flow_tbl->flow_resources[nxt_idx]; 705 706 /* connect the fid resource to the next resource */ 707 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx); 708 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx, 709 nxt_resource->nxt_resource_idx); 710 711 /* update the contents to be given to caller */ 712 ulp_flow_db_res_info_to_params(nxt_resource, params); 713 714 /* Delete the nxt_resource */ 715 memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info)); 716 717 /* add it to the free list */ 718 flow_tbl->tail_index++; 719 if (flow_tbl->tail_index >= flow_tbl->num_resources) { 720 BNXT_DRV_DBG(ERR, "FlowDB:Tail reached max\n"); 721 return -ENOENT; 722 } 723 flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx; 724 725 } else { 726 /* Critical resource. copy the contents and exit */ 727 ulp_flow_db_res_info_to_params(fid_resource, params); 728 ULP_FLOW_DB_RES_NXT_SET(nxt_idx, 729 fid_resource->nxt_resource_idx); 730 memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info)); 731 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx, 732 nxt_idx); 733 } 734 735 /* Now that the HW Flow counter resource is deleted, reset it's 736 * corresponding slot in the SW accumulation table in the Flow Counter 737 * manager 738 */ 739 if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 && 740 params->resource_sub_type == 741 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT) { 742 ulp_fc_mgr_cntr_reset(ulp_ctxt, params->direction, 743 params->resource_hndl); 744 } 745 746 /* all good, return success */ 747 return 0; 748 } 749 750 /* 751 * Free the flow database entry 752 * 753 * ulp_ctxt [in] Ptr to ulp_context 754 * flow_type [in] - specify default or regular 755 * fid [in] The index to the flow entry 756 * 757 * returns 0 on success and negative on failure. 758 */ 759 int32_t 760 ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt, 761 enum bnxt_ulp_fdb_type flow_type, 762 uint32_t fid) 763 { 764 struct bnxt_ulp_flow_tbl *flow_tbl; 765 struct bnxt_ulp_flow_db *flow_db; 766 767 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 768 if (!flow_db) { 769 BNXT_DRV_DBG(ERR, "Invalid Arguments\n"); 770 return -EINVAL; 771 } 772 773 if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) { 774 BNXT_DRV_DBG(ERR, "Invalid flow type\n"); 775 return -EINVAL; 776 } 777 778 flow_tbl = &flow_db->flow_tbl; 779 780 /* check for limits of fid */ 781 if (fid >= flow_tbl->num_flows || !fid) { 782 BNXT_DRV_DBG(ERR, "Invalid flow index\n"); 783 return -EINVAL; 784 } 785 786 /* check if the flow is active or not */ 787 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) { 788 BNXT_DRV_DBG(ERR, "flow does not exist %x:%x\n", flow_type, 789 fid); 790 return -EINVAL; 791 } 792 flow_tbl->head_index--; 793 if (!flow_tbl->head_index) { 794 BNXT_DRV_DBG(ERR, "FlowDB: Head Ptr is zero\n"); 795 return -ENOENT; 796 } 797 798 flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid; 799 800 /* Clear the flows bitmap */ 801 ulp_flow_db_active_flows_bit_set(flow_db, flow_type, fid, 0); 802 803 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR) 804 ulp_flow_db_func_id_set(flow_db, fid, 0); 805 806 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 807 BNXT_DRV_DBG(DEBUG, "flow_id = %u:%u freed\n", flow_type, fid); 808 #endif 809 /* all good, return success */ 810 return 0; 811 } 812 813 /* 814 *Get the flow database entry details 815 * 816 * ulp_ctxt [in] Ptr to ulp_context 817 * flow_type [in] - specify default or regular 818 * fid [in] The index to the flow entry 819 * nxt_idx [in/out] the index to the next entry 820 * params [out] The contents to be copied into params. 821 * 822 * returns 0 on success and negative on failure. 823 */ 824 int32_t 825 ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt, 826 enum bnxt_ulp_fdb_type flow_type, 827 uint32_t fid, 828 uint32_t *nxt_idx, 829 struct ulp_flow_db_res_params *params) 830 { 831 struct bnxt_ulp_flow_db *flow_db; 832 struct bnxt_ulp_flow_tbl *flow_tbl; 833 struct ulp_fdb_resource_info *nxt_resource, *fid_resource; 834 835 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 836 if (!flow_db) { 837 BNXT_DRV_DBG(ERR, "Invalid Arguments\n"); 838 return -EINVAL; 839 } 840 841 if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) { 842 BNXT_DRV_DBG(ERR, "Invalid flow type\n"); 843 return -EINVAL; 844 } 845 846 flow_tbl = &flow_db->flow_tbl; 847 848 /* check for limits of fid */ 849 if (fid >= flow_tbl->num_flows || !fid) { 850 BNXT_DRV_DBG(ERR, "Invalid flow index\n"); 851 return -EINVAL; 852 } 853 854 /* check if the flow is active or not */ 855 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) { 856 BNXT_DRV_DBG(ERR, "flow does not exist\n"); 857 return -EINVAL; 858 } 859 860 if (!*nxt_idx) { 861 fid_resource = &flow_tbl->flow_resources[fid]; 862 ulp_flow_db_res_info_to_params(fid_resource, params); 863 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx, 864 fid_resource->nxt_resource_idx); 865 } else { 866 nxt_resource = &flow_tbl->flow_resources[*nxt_idx]; 867 ulp_flow_db_res_info_to_params(nxt_resource, params); 868 *nxt_idx = 0; 869 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx, 870 nxt_resource->nxt_resource_idx); 871 } 872 873 /* all good, return success */ 874 return 0; 875 } 876 877 /* 878 * Get the flow database entry iteratively 879 * 880 * flow_tbl [in] Ptr to flow table 881 * flow_type [in] - specify default or regular 882 * fid [in/out] The index to the flow entry 883 * 884 * returns 0 on success and negative on failure. 885 */ 886 static int32_t 887 ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_db *flow_db, 888 enum bnxt_ulp_fdb_type flow_type, 889 uint32_t *fid) 890 { 891 uint32_t lfid = *fid; 892 uint32_t idx, s_idx, mod_fid; 893 uint64_t bs; 894 uint64_t *active_flows; 895 struct bnxt_ulp_flow_tbl *flowtbl = &flow_db->flow_tbl; 896 897 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR) { 898 active_flows = flowtbl->active_reg_flows; 899 } else if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT) { 900 active_flows = flowtbl->active_dflt_flows; 901 } else { 902 BNXT_DRV_DBG(ERR, "Invalid flow type %x\n", flow_type); 903 return -EINVAL; 904 } 905 906 do { 907 /* increment the flow id to find the next valid flow id */ 908 lfid++; 909 if (lfid >= flowtbl->num_flows) 910 return -ENOENT; 911 idx = lfid / ULP_INDEX_BITMAP_SIZE; 912 mod_fid = lfid % ULP_INDEX_BITMAP_SIZE; 913 s_idx = idx; 914 while (!(bs = active_flows[idx])) { 915 idx++; 916 if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows) 917 return -ENOENT; 918 } 919 /* 920 * remove the previous bits in the bitset bs to find the 921 * next non zero bit in the bitset. This needs to be done 922 * only if the idx is same as he one you started. 923 */ 924 if (s_idx == idx) 925 bs &= (-1UL >> mod_fid); 926 lfid = (idx * ULP_INDEX_BITMAP_SIZE) + rte_clz64(bs); 927 if (*fid >= lfid) { 928 BNXT_DRV_DBG(ERR, "Flow Database is corrupt\n"); 929 return -ENOENT; 930 } 931 } while (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, 932 lfid)); 933 934 /* all good, return success */ 935 *fid = lfid; 936 return 0; 937 } 938 939 /* 940 * Flush all flows in the flow database. 941 * 942 * ulp_ctxt [in] Ptr to ulp context 943 * flow_type [in] - specify default or regular 944 * 945 * returns 0 on success or negative number on failure 946 */ 947 int32_t 948 ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx, 949 enum bnxt_ulp_fdb_type flow_type) 950 { 951 uint32_t fid = 0; 952 struct bnxt_ulp_flow_db *flow_db; 953 954 if (!ulp_ctx) { 955 BNXT_DRV_DBG(ERR, "Invalid Argument\n"); 956 return -EINVAL; 957 } 958 959 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx); 960 if (!flow_db) { 961 BNXT_DRV_DBG(ERR, "Flow database not found\n"); 962 return -EINVAL; 963 } 964 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) { 965 BNXT_DRV_DBG(ERR, "Flow db lock acquire failed\n"); 966 return -EINVAL; 967 } 968 969 #ifdef TF_FLOW_SCALE_QUERY 970 tf_resc_pause_usage_update(); 971 #endif 972 973 while (!ulp_flow_db_next_entry_get(flow_db, flow_type, &fid)) 974 ulp_mapper_resources_free(ulp_ctx, flow_type, fid, NULL); 975 976 #ifdef TF_FLOW_SCALE_QUERY 977 ulp_resc_usage_sync(ulp_ctx); 978 #endif 979 980 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 981 982 return 0; 983 } 984 985 /* 986 * Flush all flows in the flow database that belong to a device function. 987 * 988 * ulp_ctxt [in] Ptr to ulp context 989 * func_id [in] - The port function id 990 * 991 * returns 0 on success or negative number on failure 992 */ 993 int32_t 994 ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx, 995 uint16_t func_id) 996 { 997 uint32_t flow_id = 0; 998 struct bnxt_ulp_flow_db *flow_db; 999 1000 if (!ulp_ctx || !func_id) { 1001 BNXT_DRV_DBG(ERR, "Invalid Argument\n"); 1002 return -EINVAL; 1003 } 1004 1005 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx); 1006 if (!flow_db) { 1007 BNXT_DRV_DBG(ERR, "Flow database not found\n"); 1008 return -EINVAL; 1009 } 1010 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) { 1011 BNXT_DRV_DBG(ERR, "Flow db lock acquire failed\n"); 1012 return -EINVAL; 1013 } 1014 1015 #ifdef TF_FLOW_SCALE_QUERY 1016 tf_resc_pause_usage_update(); 1017 #endif 1018 while (!ulp_flow_db_next_entry_get(flow_db, BNXT_ULP_FDB_TYPE_REGULAR, 1019 &flow_id)) { 1020 if (flow_db->func_id_tbl[flow_id] == func_id) 1021 ulp_mapper_resources_free(ulp_ctx, 1022 BNXT_ULP_FDB_TYPE_REGULAR, 1023 flow_id, 1024 NULL); 1025 } 1026 #ifdef TF_FLOW_SCALE_QUERY 1027 ulp_resc_usage_sync(ulp_ctx); 1028 #endif 1029 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 1030 return 0; 1031 } 1032 1033 /* 1034 * Flush all flows in the flow database that are associated with the session. 1035 * 1036 * ulp_ctxt [in] Ptr to ulp context 1037 * 1038 * returns 0 on success or negative number on failure 1039 */ 1040 int32_t 1041 ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx) 1042 { 1043 /* 1044 * TBD: Tf core implementation of FW session flush shall change this 1045 * implementation. 1046 */ 1047 return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR); 1048 } 1049 1050 /* 1051 * Check that flow id matches the function id or not 1052 * 1053 * ulp_ctxt [in] Ptr to ulp context 1054 * flow_db [in] Ptr to flow table 1055 * func_id [in] The func_id to be set, for reset pass zero. 1056 * 1057 * returns true on success or false on failure 1058 */ 1059 bool 1060 ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx, 1061 uint32_t flow_id, 1062 uint32_t func_id) 1063 { 1064 struct bnxt_ulp_flow_db *flow_db; 1065 1066 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx); 1067 if (!flow_db) { 1068 BNXT_DRV_DBG(ERR, "Flow database not found\n"); 1069 return false; 1070 } 1071 1072 /* set the function id in the function table */ 1073 if (flow_id < flow_db->func_id_tbl_size && func_id && 1074 flow_db->func_id_tbl[flow_id] == func_id) 1075 return true; 1076 1077 return false; 1078 } 1079 1080 /* 1081 * Internal api to traverse the resource list within a flow 1082 * and match a resource based on resource func and resource 1083 * sub type. This api should be used only for resources that 1084 * are unique and do not have multiple instances of resource 1085 * func and sub type combination since it will return only 1086 * the first match. 1087 */ 1088 static int32_t 1089 ulp_flow_db_resource_params_get(struct bnxt_ulp_context *ulp_ctx, 1090 enum bnxt_ulp_fdb_type flow_type, 1091 uint32_t flow_id, 1092 uint32_t resource_func, 1093 uint32_t res_subtype, 1094 struct ulp_flow_db_res_params *params) 1095 { 1096 struct bnxt_ulp_flow_db *flow_db; 1097 struct bnxt_ulp_flow_tbl *flow_tbl; 1098 struct ulp_fdb_resource_info *fid_res; 1099 uint32_t res_id; 1100 1101 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx); 1102 if (!flow_db) { 1103 BNXT_DRV_DBG(ERR, "Flow database not found\n"); 1104 return -EINVAL; 1105 } 1106 1107 if (!params) { 1108 BNXT_DRV_DBG(ERR, "invalid argument\n"); 1109 return -EINVAL; 1110 } 1111 1112 if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) { 1113 BNXT_DRV_DBG(ERR, "Invalid flow type\n"); 1114 return -EINVAL; 1115 } 1116 1117 flow_tbl = &flow_db->flow_tbl; 1118 1119 /* check for limits of fid */ 1120 if (flow_id >= flow_tbl->num_flows || !flow_id) { 1121 BNXT_DRV_DBG(ERR, "Invalid flow index\n"); 1122 return -EINVAL; 1123 } 1124 1125 /* check if the flow is active or not */ 1126 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, flow_id)) { 1127 BNXT_DRV_DBG(ERR, "flow does not exist\n"); 1128 return -EINVAL; 1129 } 1130 /* Iterate the resource to get the resource handle */ 1131 res_id = flow_id; 1132 memset(params, 0, sizeof(struct ulp_flow_db_res_params)); 1133 while (res_id) { 1134 fid_res = &flow_tbl->flow_resources[res_id]; 1135 if (ulp_flow_db_resource_func_get(fid_res) == resource_func && 1136 fid_res->resource_sub_type == res_subtype) { 1137 ulp_flow_db_res_info_to_params(fid_res, params); 1138 return 0; 1139 } 1140 res_id = 0; 1141 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx); 1142 } 1143 return -ENOENT; 1144 } 1145 1146 /* 1147 * Api to get the cfa action pointer from a flow. 1148 * 1149 * ulp_ctxt [in] Ptr to ulp context 1150 * flow_id [in] flow id 1151 * cfa_action [out] The resource handle stored in the flow database 1152 * 1153 * returns 0 on success 1154 */ 1155 int32_t 1156 ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx, 1157 uint32_t flow_id, 1158 uint32_t *cfa_action) 1159 { 1160 uint8_t sub_typ = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_VFR_CFA_ACTION; 1161 struct ulp_flow_db_res_params params; 1162 int32_t rc; 1163 1164 rc = ulp_flow_db_resource_params_get(ulp_ctx, 1165 BNXT_ULP_FDB_TYPE_DEFAULT, 1166 flow_id, 1167 BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE, 1168 sub_typ, ¶ms); 1169 if (rc) { 1170 BNXT_DRV_DBG(DEBUG, "CFA Action ptr not found for flow id %u\n", 1171 flow_id); 1172 return -ENOENT; 1173 } 1174 *cfa_action = params.resource_hndl; 1175 return 0; 1176 } 1177 1178 /* internal validation function for parent flow tbl */ 1179 struct ulp_fdb_parent_info * 1180 ulp_flow_db_pc_db_entry_get(struct bnxt_ulp_context *ulp_ctxt, 1181 uint32_t pc_idx) 1182 { 1183 struct bnxt_ulp_flow_db *flow_db; 1184 1185 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 1186 if (!flow_db) { 1187 BNXT_DRV_DBG(ERR, "Invalid Arguments\n"); 1188 return NULL; 1189 } 1190 1191 /* check for max flows */ 1192 if (pc_idx >= BNXT_ULP_MAX_TUN_CACHE_ENTRIES) { 1193 BNXT_DRV_DBG(ERR, "Invalid tunnel index\n"); 1194 return NULL; 1195 } 1196 1197 /* No support for parent child db then just exit */ 1198 if (!flow_db->parent_child_db.entries_count) { 1199 BNXT_DRV_DBG(ERR, "parent child db not supported\n"); 1200 return NULL; 1201 } 1202 if (!flow_db->parent_child_db.parent_flow_tbl[pc_idx].valid) { 1203 BNXT_DRV_DBG(ERR, "Not a valid tunnel index\n"); 1204 return NULL; 1205 } 1206 1207 return &flow_db->parent_child_db.parent_flow_tbl[pc_idx]; 1208 } 1209 1210 /* internal validation function for parent flow tbl */ 1211 static struct bnxt_ulp_flow_db * 1212 ulp_flow_db_parent_arg_validation(struct bnxt_ulp_context *ulp_ctxt, 1213 uint32_t tun_idx) 1214 { 1215 struct bnxt_ulp_flow_db *flow_db; 1216 1217 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 1218 if (!flow_db) { 1219 BNXT_DRV_DBG(ERR, "Invalid Arguments\n"); 1220 return NULL; 1221 } 1222 1223 /* check for max flows */ 1224 if (tun_idx >= BNXT_ULP_MAX_TUN_CACHE_ENTRIES) { 1225 BNXT_DRV_DBG(ERR, "Invalid tunnel index\n"); 1226 return NULL; 1227 } 1228 1229 /* No support for parent child db then just exit */ 1230 if (!flow_db->parent_child_db.entries_count) { 1231 BNXT_DRV_DBG(ERR, "parent child db not supported\n"); 1232 return NULL; 1233 } 1234 1235 return flow_db; 1236 } 1237 1238 /* 1239 * Allocate the entry in the parent-child database 1240 * 1241 * ulp_ctxt [in] Ptr to ulp_context 1242 * tun_idx [in] The tunnel index of the flow entry 1243 * 1244 * returns index on success and negative on failure. 1245 */ 1246 static int32_t 1247 ulp_flow_db_pc_db_idx_alloc(struct bnxt_ulp_context *ulp_ctxt, 1248 uint32_t tun_idx) 1249 { 1250 struct bnxt_ulp_flow_db *flow_db; 1251 struct ulp_fdb_parent_child_db *p_pdb; 1252 uint32_t idx, free_idx = 0; 1253 1254 /* validate the arguments */ 1255 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, tun_idx); 1256 if (!flow_db) { 1257 BNXT_DRV_DBG(ERR, "parent child db validation failed\n"); 1258 return -EINVAL; 1259 } 1260 1261 p_pdb = &flow_db->parent_child_db; 1262 for (idx = 0; idx < p_pdb->entries_count; idx++) { 1263 if (p_pdb->parent_flow_tbl[idx].valid && 1264 p_pdb->parent_flow_tbl[idx].tun_idx == tun_idx) { 1265 return idx; 1266 } 1267 if (!p_pdb->parent_flow_tbl[idx].valid && !free_idx) 1268 free_idx = idx + 1; 1269 } 1270 /* no free slots */ 1271 if (!free_idx) { 1272 BNXT_DRV_DBG(ERR, "parent child db is full\n"); 1273 return -ENOMEM; 1274 } 1275 1276 free_idx -= 1; 1277 /* set the Fid in the parent child */ 1278 p_pdb->parent_flow_tbl[free_idx].tun_idx = tun_idx; 1279 p_pdb->parent_flow_tbl[free_idx].valid = 1; 1280 return free_idx; 1281 } 1282 1283 /* 1284 * Free the entry in the parent-child database 1285 * 1286 * pc_entry [in] Ptr to parent child db entry 1287 * 1288 * returns none. 1289 */ 1290 static void 1291 ulp_flow_db_pc_db_entry_free(struct bnxt_ulp_context *ulp_ctxt, 1292 struct ulp_fdb_parent_info *pc_entry) 1293 { 1294 struct bnxt_tun_cache_entry *tun_tbl; 1295 struct bnxt_ulp_flow_db *flow_db; 1296 uint64_t *tmp_bitset; 1297 1298 /* free the tunnel entry */ 1299 tun_tbl = bnxt_ulp_cntxt_ptr2_tun_tbl_get(ulp_ctxt); 1300 if (tun_tbl) 1301 ulp_tunnel_offload_entry_clear(tun_tbl, pc_entry->tun_idx); 1302 1303 /* free the child bitset*/ 1304 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 1305 if (flow_db) 1306 memset(pc_entry->child_fid_bitset, 0, 1307 flow_db->parent_child_db.child_bitset_size); 1308 1309 /* free the contents */ 1310 tmp_bitset = pc_entry->child_fid_bitset; 1311 memset(pc_entry, 0, sizeof(struct ulp_fdb_parent_info)); 1312 pc_entry->child_fid_bitset = tmp_bitset; 1313 } 1314 1315 /* 1316 * Set or reset the parent flow in the parent-child database 1317 * 1318 * ulp_ctxt [in] Ptr to ulp_context 1319 * pc_idx [in] The index to parent child db 1320 * parent_fid [in] The flow id of the parent flow entry 1321 * set_flag [in] Use 1 for setting child, 0 to reset 1322 * 1323 * returns zero on success and negative on failure. 1324 */ 1325 int32_t 1326 ulp_flow_db_pc_db_parent_flow_set(struct bnxt_ulp_context *ulp_ctxt, 1327 uint32_t pc_idx, 1328 uint32_t parent_fid, 1329 uint32_t set_flag) 1330 { 1331 struct ulp_fdb_parent_info *pc_entry; 1332 struct bnxt_ulp_flow_db *flow_db; 1333 1334 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 1335 if (!flow_db) { 1336 BNXT_DRV_DBG(ERR, "parent child db validation failed\n"); 1337 return -EINVAL; 1338 } 1339 1340 /* check for fid validity */ 1341 if (parent_fid >= flow_db->flow_tbl.num_flows || !parent_fid) { 1342 BNXT_DRV_DBG(ERR, "Invalid parent flow index %x\n", parent_fid); 1343 return -EINVAL; 1344 } 1345 1346 /* validate the arguments and parent child entry */ 1347 pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx); 1348 if (!pc_entry) { 1349 BNXT_DRV_DBG(ERR, "failed to get the parent child entry\n"); 1350 return -EINVAL; 1351 } 1352 1353 if (set_flag) { 1354 pc_entry->parent_fid = parent_fid; 1355 pc_entry->parent_ref_cnt++; 1356 } else { 1357 if (pc_entry->parent_ref_cnt > 0) 1358 pc_entry->parent_ref_cnt--; 1359 /* Free the parent child db entry if no user present */ 1360 if (!pc_entry->parent_ref_cnt && !pc_entry->f2_cnt) 1361 ulp_flow_db_pc_db_entry_free(ulp_ctxt, pc_entry); 1362 } 1363 return 0; 1364 } 1365 1366 /* 1367 * Set or reset the child flow in the parent-child database 1368 * 1369 * ulp_ctxt [in] Ptr to ulp_context 1370 * pc_idx [in] The index to parent child db 1371 * child_fid [in] The flow id of the child flow entry 1372 * set_flag [in] Use 1 for setting child, 0 to reset 1373 * 1374 * returns zero on success and negative on failure. 1375 */ 1376 int32_t 1377 ulp_flow_db_pc_db_child_flow_set(struct bnxt_ulp_context *ulp_ctxt, 1378 uint32_t pc_idx, 1379 uint32_t child_fid, 1380 uint32_t set_flag) 1381 { 1382 struct ulp_fdb_parent_info *pc_entry; 1383 struct bnxt_ulp_flow_db *flow_db; 1384 uint32_t a_idx; 1385 uint64_t *t; 1386 1387 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 1388 if (!flow_db) { 1389 BNXT_DRV_DBG(ERR, "parent child db validation failed\n"); 1390 return -EINVAL; 1391 } 1392 1393 /* check for fid validity */ 1394 if (child_fid >= flow_db->flow_tbl.num_flows || !child_fid) { 1395 BNXT_DRV_DBG(ERR, "Invalid child flow index %x\n", child_fid); 1396 return -EINVAL; 1397 } 1398 1399 /* validate the arguments and parent child entry */ 1400 pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx); 1401 if (!pc_entry) { 1402 BNXT_DRV_DBG(ERR, "failed to get the parent child entry\n"); 1403 return -EINVAL; 1404 } 1405 1406 a_idx = child_fid / ULP_INDEX_BITMAP_SIZE; 1407 t = pc_entry->child_fid_bitset; 1408 if (set_flag) { 1409 ULP_INDEX_BITMAP_SET(t[a_idx], child_fid); 1410 pc_entry->f2_cnt++; 1411 } else { 1412 ULP_INDEX_BITMAP_RESET(t[a_idx], child_fid); 1413 if (pc_entry->f2_cnt) 1414 pc_entry->f2_cnt--; 1415 if (!pc_entry->f2_cnt && !pc_entry->parent_ref_cnt) 1416 ulp_flow_db_pc_db_entry_free(ulp_ctxt, pc_entry); 1417 } 1418 return 0; 1419 } 1420 1421 /* 1422 * Get the next child flow in the parent-child database 1423 * 1424 * ulp_ctxt [in] Ptr to ulp_context 1425 * parent_fid [in] The flow id of the parent flow entry 1426 * child_fid [in/out] The flow id of the child flow entry 1427 * 1428 * returns zero on success and negative on failure. 1429 * Pass child_fid as zero for first entry. 1430 */ 1431 int32_t 1432 ulp_flow_db_parent_child_flow_next_entry_get(struct bnxt_ulp_flow_db *flow_db, 1433 uint32_t parent_idx, 1434 uint32_t *child_fid) 1435 { 1436 struct ulp_fdb_parent_child_db *p_pdb; 1437 uint32_t idx, s_idx, mod_fid; 1438 uint32_t next_fid = *child_fid; 1439 uint64_t *child_bitset; 1440 uint64_t bs; 1441 1442 /* check for fid validity */ 1443 p_pdb = &flow_db->parent_child_db; 1444 if (parent_idx >= p_pdb->entries_count || 1445 !p_pdb->parent_flow_tbl[parent_idx].parent_fid) { 1446 BNXT_DRV_DBG(ERR, "Invalid parent flow index %x\n", parent_idx); 1447 return -EINVAL; 1448 } 1449 1450 child_bitset = p_pdb->parent_flow_tbl[parent_idx].child_fid_bitset; 1451 do { 1452 /* increment the flow id to find the next valid flow id */ 1453 next_fid++; 1454 if (next_fid >= flow_db->flow_tbl.num_flows) 1455 return -ENOENT; 1456 idx = next_fid / ULP_INDEX_BITMAP_SIZE; 1457 mod_fid = next_fid % ULP_INDEX_BITMAP_SIZE; 1458 s_idx = idx; 1459 while (!(bs = child_bitset[idx])) { 1460 idx++; 1461 if ((idx * ULP_INDEX_BITMAP_SIZE) >= 1462 flow_db->flow_tbl.num_flows) 1463 return -ENOENT; 1464 } 1465 /* 1466 * remove the previous bits in the bitset bs to find the 1467 * next non zero bit in the bitset. This needs to be done 1468 * only if the idx is same as he one you started. 1469 */ 1470 if (s_idx == idx) 1471 bs &= (-1UL >> mod_fid); 1472 next_fid = (idx * ULP_INDEX_BITMAP_SIZE) + rte_clz64(bs); 1473 if (*child_fid >= next_fid) { 1474 BNXT_DRV_DBG(ERR, "Parent Child Database is corrupt\n"); 1475 return -ENOENT; 1476 } 1477 idx = next_fid / ULP_INDEX_BITMAP_SIZE; 1478 } while (!ULP_INDEX_BITMAP_GET(child_bitset[idx], next_fid)); 1479 *child_fid = next_fid; 1480 return 0; 1481 } 1482 1483 /* 1484 * Set the counter accumulation in the parent flow 1485 * 1486 * ulp_ctxt [in] Ptr to ulp_context 1487 * pc_idx [in] The parent child index of the parent flow entry 1488 * 1489 * returns index on success and negative on failure. 1490 */ 1491 static int32_t 1492 ulp_flow_db_parent_flow_count_accum_set(struct bnxt_ulp_context *ulp_ctxt, 1493 uint32_t pc_idx) 1494 { 1495 struct bnxt_ulp_flow_db *flow_db; 1496 struct ulp_fdb_parent_child_db *p_pdb; 1497 1498 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 1499 if (!flow_db) { 1500 BNXT_DRV_DBG(ERR, "Invalid Arguments\n"); 1501 return -EINVAL; 1502 } 1503 1504 /* check for parent idx validity */ 1505 p_pdb = &flow_db->parent_child_db; 1506 if (pc_idx >= p_pdb->entries_count || 1507 !p_pdb->parent_flow_tbl[pc_idx].parent_ref_cnt) { 1508 BNXT_DRV_DBG(ERR, "Invalid parent child index %x\n", pc_idx); 1509 return -EINVAL; 1510 } 1511 1512 p_pdb->parent_flow_tbl[pc_idx].counter_acc = 1; 1513 return 0; 1514 } 1515 1516 /* 1517 * Orphan the child flow entry 1518 * This is called only for child flows that have 1519 * BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW resource 1520 * 1521 * ulp_ctxt [in] Ptr to ulp_context 1522 * flow_type [in] Specify it is regular or default flow 1523 * fid [in] The index to the flow entry 1524 * 1525 * Returns 0 on success and negative on failure. 1526 */ 1527 int32_t 1528 ulp_flow_db_child_flow_reset(struct bnxt_ulp_context *ulp_ctxt, 1529 enum bnxt_ulp_fdb_type flow_type, 1530 uint32_t fid) 1531 { 1532 struct bnxt_ulp_flow_db *flow_db; 1533 struct bnxt_ulp_flow_tbl *flow_tbl; 1534 struct ulp_fdb_resource_info *fid_res; 1535 uint32_t res_id = 0; 1536 1537 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 1538 if (!flow_db) { 1539 BNXT_DRV_DBG(ERR, "Invalid Arguments\n"); 1540 return -EINVAL; 1541 } 1542 1543 if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) { 1544 BNXT_DRV_DBG(ERR, "Invalid flow type\n"); 1545 return -EINVAL; 1546 } 1547 1548 flow_tbl = &flow_db->flow_tbl; 1549 /* check for max flows */ 1550 if (fid >= flow_tbl->num_flows || !fid) { 1551 BNXT_DRV_DBG(ERR, "Invalid flow index %x\n", fid); 1552 return -EINVAL; 1553 } 1554 1555 /* check if the flow is active or not */ 1556 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) { 1557 BNXT_DRV_DBG(ERR, "flow does not exist\n"); 1558 return -EINVAL; 1559 } 1560 1561 /* Iterate the resource to get the resource handle */ 1562 res_id = fid; 1563 while (res_id) { 1564 fid_res = &flow_tbl->flow_resources[res_id]; 1565 if (ulp_flow_db_resource_func_get(fid_res) == 1566 BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW) { 1567 /* invalidate the resource details */ 1568 fid_res->resource_hndl = 0; 1569 return 0; 1570 } 1571 res_id = 0; 1572 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx); 1573 } 1574 /* failed */ 1575 return -1; 1576 } 1577 1578 /* 1579 * Create parent flow in the parent flow tbl 1580 * 1581 * parms [in] Ptr to mapper params 1582 * 1583 * Returns 0 on success and negative on failure. 1584 */ 1585 int32_t 1586 ulp_flow_db_parent_flow_create(struct bnxt_ulp_mapper_parms *parms) 1587 { 1588 struct ulp_flow_db_res_params fid_parms; 1589 uint32_t sub_typ = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT; 1590 struct ulp_flow_db_res_params res_params; 1591 int32_t pc_idx; 1592 1593 /* create or get the parent child database */ 1594 pc_idx = ulp_flow_db_pc_db_idx_alloc(parms->ulp_ctx, parms->tun_idx); 1595 if (pc_idx < 0) { 1596 BNXT_DRV_DBG(ERR, "Error in getting parent child db %x\n", 1597 parms->tun_idx); 1598 return -EINVAL; 1599 } 1600 1601 /* Update the parent fid */ 1602 if (ulp_flow_db_pc_db_parent_flow_set(parms->ulp_ctx, pc_idx, 1603 parms->flow_id, 1)) { 1604 BNXT_DRV_DBG(ERR, "Error in setting parent fid %x\n", 1605 parms->tun_idx); 1606 return -EINVAL; 1607 } 1608 1609 /* Add the parent details in the resource list of the flow */ 1610 memset(&fid_parms, 0, sizeof(fid_parms)); 1611 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW; 1612 fid_parms.resource_hndl = pc_idx; 1613 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 1614 if (ulp_flow_db_resource_add(parms->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR, 1615 parms->flow_id, &fid_parms)) { 1616 BNXT_DRV_DBG(ERR, "Error in adding flow res for flow id %x\n", 1617 parms->flow_id); 1618 return -1; 1619 } 1620 1621 /* check of the flow has internal counter accumulation enabled */ 1622 if (!ulp_flow_db_resource_params_get(parms->ulp_ctx, 1623 BNXT_ULP_FDB_TYPE_REGULAR, 1624 parms->flow_id, 1625 BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE, 1626 sub_typ, 1627 &res_params)) { 1628 /* Enable the counter accumulation in parent entry */ 1629 if (ulp_flow_db_parent_flow_count_accum_set(parms->ulp_ctx, 1630 pc_idx)) { 1631 BNXT_DRV_DBG(ERR, "Error in setting counter acc %x\n", 1632 parms->flow_id); 1633 return -1; 1634 } 1635 } 1636 1637 /* Set parent flow entry idx in stats cache entry */ 1638 ulp_sc_mgr_set_pc_idx(parms->ulp_ctx, parms->flow_id, pc_idx); 1639 return 0; 1640 } 1641 1642 /* 1643 * Create child flow in the parent flow tbl 1644 * 1645 * parms [in] Ptr to mapper params 1646 * 1647 * Returns 0 on success and negative on failure. 1648 */ 1649 int32_t 1650 ulp_flow_db_child_flow_create(struct bnxt_ulp_mapper_parms *parms) 1651 { 1652 struct ulp_flow_db_res_params fid_parms; 1653 uint32_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT; 1654 enum bnxt_ulp_resource_func res_fun; 1655 struct ulp_flow_db_res_params res_p; 1656 int32_t rc, pc_idx; 1657 1658 /* create or get the parent child database */ 1659 pc_idx = ulp_flow_db_pc_db_idx_alloc(parms->ulp_ctx, parms->tun_idx); 1660 if (pc_idx < 0) { 1661 BNXT_DRV_DBG(ERR, "Error in getting parent child db %x\n", 1662 parms->tun_idx); 1663 return -1; 1664 } 1665 1666 /* create the parent flow entry in parent flow table */ 1667 rc = ulp_flow_db_pc_db_child_flow_set(parms->ulp_ctx, pc_idx, 1668 parms->flow_id, 1); 1669 if (rc) { 1670 BNXT_DRV_DBG(ERR, "Error in setting child fid %x\n", 1671 parms->flow_id); 1672 return rc; 1673 } 1674 1675 /* Add the parent details in the resource list of the flow */ 1676 memset(&fid_parms, 0, sizeof(fid_parms)); 1677 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW; 1678 fid_parms.resource_hndl = pc_idx; 1679 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 1680 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1681 BNXT_ULP_FDB_TYPE_REGULAR, 1682 parms->flow_id, &fid_parms); 1683 if (rc) { 1684 BNXT_DRV_DBG(ERR, "Error in adding flow res for flow id %x\n", 1685 parms->flow_id); 1686 return rc; 1687 } 1688 1689 /* check if internal count action included for this flow.*/ 1690 res_fun = BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE; 1691 rc = ulp_flow_db_resource_params_get(parms->ulp_ctx, 1692 BNXT_ULP_FDB_TYPE_REGULAR, 1693 parms->flow_id, 1694 res_fun, 1695 sub_type, 1696 &res_p); 1697 if (!rc) { 1698 /* update the counter manager to include parent fid */ 1699 if (ulp_fc_mgr_cntr_parent_flow_set(parms->ulp_ctx, 1700 res_p.direction, 1701 res_p.resource_hndl, 1702 pc_idx)) { 1703 BNXT_DRV_DBG(ERR, "Error in setting child %x\n", 1704 parms->flow_id); 1705 return -1; 1706 } 1707 } 1708 1709 /* return success */ 1710 return 0; 1711 } 1712 1713 /* 1714 * Update the parent counters 1715 * 1716 * ulp_ctxt [in] Ptr to ulp_context 1717 * pc_idx [in] The parent flow entry idx 1718 * packet_count [in] - packet count 1719 * byte_count [in] - byte count 1720 * 1721 * returns 0 on success 1722 */ 1723 int32_t 1724 ulp_flow_db_parent_flow_count_update(struct bnxt_ulp_context *ulp_ctxt, 1725 uint32_t pc_idx, 1726 uint64_t packet_count, 1727 uint64_t byte_count) 1728 { 1729 struct ulp_fdb_parent_info *pc_entry; 1730 1731 /* validate the arguments and get parent child entry */ 1732 pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx); 1733 if (!pc_entry) { 1734 BNXT_DRV_DBG(ERR, "failed to get the parent child entry\n"); 1735 return -EINVAL; 1736 } 1737 1738 if (pc_entry->counter_acc) { 1739 pc_entry->pkt_count += packet_count; 1740 pc_entry->byte_count += byte_count; 1741 } 1742 return 0; 1743 } 1744 1745 /* 1746 * Get the parent accumulation counters 1747 * 1748 * ulp_ctxt [in] Ptr to ulp_context 1749 * pc_idx [in] The parent flow entry idx 1750 * packet_count [out] - packet count 1751 * byte_count [out] - byte count 1752 * 1753 * returns 0 on success 1754 */ 1755 int32_t 1756 ulp_flow_db_parent_flow_count_get(struct bnxt_ulp_context *ulp_ctxt, 1757 uint32_t flow_id, 1758 uint32_t pc_idx, uint64_t *packet_count, 1759 uint64_t *byte_count, uint8_t count_reset) 1760 { 1761 struct ulp_fdb_parent_info *pc_entry; 1762 1763 /* validate the arguments and get parent child entry */ 1764 pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx); 1765 if (!pc_entry) { 1766 BNXT_DRV_DBG(ERR, "failed to get the parent child entry\n"); 1767 return -EINVAL; 1768 } 1769 1770 /* stale parent fid */ 1771 if (flow_id != pc_entry->parent_fid) { 1772 *packet_count = 0; 1773 *byte_count = 0; 1774 return 0; 1775 } 1776 1777 if (pc_entry->counter_acc) { 1778 *packet_count = pc_entry->pkt_count; 1779 *byte_count = pc_entry->byte_count; 1780 if (count_reset) { 1781 pc_entry->pkt_count = 0; 1782 pc_entry->byte_count = 0; 1783 } 1784 } 1785 return 0; 1786 } 1787 1788 /* 1789 * reset the parent accumulation counters 1790 * 1791 * ulp_ctxt [in] Ptr to ulp_context 1792 * 1793 * returns none 1794 */ 1795 void 1796 ulp_flow_db_parent_flow_count_reset(struct bnxt_ulp_context *ulp_ctxt) 1797 { 1798 struct bnxt_ulp_flow_db *flow_db; 1799 struct ulp_fdb_parent_child_db *p_pdb; 1800 uint32_t idx; 1801 1802 /* validate the arguments */ 1803 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 1804 if (!flow_db) { 1805 BNXT_DRV_DBG(ERR, "parent child db validation failed\n"); 1806 return; 1807 } 1808 1809 p_pdb = &flow_db->parent_child_db; 1810 for (idx = 0; idx < p_pdb->entries_count; idx++) { 1811 if (p_pdb->parent_flow_tbl[idx].valid && 1812 p_pdb->parent_flow_tbl[idx].counter_acc) { 1813 p_pdb->parent_flow_tbl[idx].pkt_count = 0; 1814 p_pdb->parent_flow_tbl[idx].byte_count = 0; 1815 } 1816 } 1817 } 1818 1819 /* 1820 * Set the shared bit for the flow db entry 1821 * 1822 * res [in] Ptr to fdb entry 1823 * shared [in] shared flag 1824 * 1825 * returns none 1826 */ 1827 void ulp_flow_db_shared_session_set(struct ulp_flow_db_res_params *res, 1828 enum bnxt_ulp_session_type s_type) 1829 { 1830 if (res && (s_type & BNXT_ULP_SESSION_TYPE_SHARED)) 1831 res->fdb_flags |= ULP_FDB_FLAG_SHARED_SESSION; 1832 else if (res && (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC)) 1833 res->fdb_flags |= ULP_FDB_FLAG_SHARED_WC_SESSION; 1834 } 1835 1836 /* 1837 * get the shared bit for the flow db entry 1838 * 1839 * res [in] Ptr to fdb entry 1840 * 1841 * returns session type 1842 */ 1843 enum bnxt_ulp_session_type 1844 ulp_flow_db_shared_session_get(struct ulp_flow_db_res_params *res) 1845 { 1846 enum bnxt_ulp_session_type stype = BNXT_ULP_SESSION_TYPE_DEFAULT; 1847 1848 if (res && (res->fdb_flags & ULP_FDB_FLAG_SHARED_SESSION)) 1849 stype = BNXT_ULP_SESSION_TYPE_SHARED; 1850 else if (res && (res->fdb_flags & ULP_FDB_FLAG_SHARED_WC_SESSION)) 1851 stype = BNXT_ULP_SESSION_TYPE_SHARED_WC; 1852 1853 return stype; 1854 } 1855