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