LCOV - code coverage report
Current view: top level - drivers/net/bnxt/tf_core - tf_em_common.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 402 0.0 %
Date: 2024-04-01 19:00:53 Functions: 0 20 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 194 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2019-2023 Broadcom
       3                 :            :  * All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <string.h>
       7                 :            : #include <math.h>
       8                 :            : #include <sys/param.h>
       9                 :            : #include <rte_common.h>
      10                 :            : #include <rte_errno.h>
      11                 :            : #include <rte_log.h>
      12                 :            : #include "tf_core.h"
      13                 :            : #include "tf_util.h"
      14                 :            : #include "tf_common.h"
      15                 :            : #include "tf_em.h"
      16                 :            : #include "tf_em_common.h"
      17                 :            : #include "tf_msg.h"
      18                 :            : #include "tfp.h"
      19                 :            : #include "tf_device.h"
      20                 :            : #include "tf_ext_flow_handle.h"
      21                 :            : #include "hcapi_cfa.h"
      22                 :            : #include "bnxt.h"
      23                 :            : 
      24                 :            : /** Invalid table scope id */
      25                 :            : #define TF_TBL_SCOPE_INVALID 0xffffffff
      26                 :            : 
      27                 :            : /* Number of pointers per page_size */
      28                 :            : #define MAX_PAGE_PTRS(page_size)  ((page_size) / sizeof(void *))
      29                 :            : 
      30                 :            : /**
      31                 :            :  * Host or system
      32                 :            :  */
      33                 :            : static enum tf_mem_type mem_type;
      34                 :            : 
      35                 :            : /* API defined in tf_em.h */
      36                 :            : int
      37                 :          0 : tf_create_tbl_pool_external(enum tf_dir dir,
      38                 :            :                             struct tf_tbl_scope_cb *tbl_scope_cb,
      39                 :            :                             uint32_t num_entries,
      40                 :            :                             uint32_t entry_sz_bytes)
      41                 :            : {
      42                 :            :         struct tfp_calloc_parms parms;
      43                 :            :         uint32_t i;
      44                 :            :         int32_t j;
      45                 :            :         int rc = 0;
      46                 :          0 :         struct stack *pool = &tbl_scope_cb->ext_act_pool[dir];
      47                 :            : 
      48                 :          0 :         parms.nitems = num_entries;
      49                 :          0 :         parms.size = sizeof(uint32_t);
      50                 :          0 :         parms.alignment = 0;
      51                 :            : 
      52         [ #  # ]:          0 :         if (tfp_calloc(&parms) != 0) {
      53                 :          0 :                 TFP_DRV_LOG(ERR, "%s: TBL: external pool failure %s\n",
      54                 :            :                             tf_dir_2_str(dir), strerror(ENOMEM));
      55                 :          0 :                 return -ENOMEM;
      56                 :            :         }
      57                 :            : 
      58                 :            :         /* Create empty stack
      59                 :            :          */
      60                 :          0 :         rc = stack_init(num_entries, parms.mem_va, pool);
      61                 :            : 
      62         [ #  # ]:          0 :         if (rc != 0) {
      63                 :          0 :                 TFP_DRV_LOG(ERR, "%s: TBL: stack init failure %s\n",
      64                 :            :                             tf_dir_2_str(dir), strerror(-rc));
      65                 :          0 :                 goto cleanup;
      66                 :            :         }
      67                 :            : 
      68                 :            :         /* Save the  malloced memory address so that it can
      69                 :            :          * be freed when the table scope is freed.
      70                 :            :          */
      71                 :          0 :         tbl_scope_cb->ext_act_pool_mem[dir] = (uint32_t *)parms.mem_va;
      72                 :            : 
      73                 :            :         /* Fill pool with indexes in reverse
      74                 :            :          */
      75                 :          0 :         j = (num_entries - 1) * entry_sz_bytes;
      76                 :            : 
      77         [ #  # ]:          0 :         for (i = 0; i < num_entries; i++) {
      78                 :          0 :                 rc = stack_push(pool, j);
      79         [ #  # ]:          0 :                 if (rc != 0) {
      80                 :          0 :                         TFP_DRV_LOG(ERR, "%s TBL: stack failure %s\n",
      81                 :            :                                     tf_dir_2_str(dir), strerror(-rc));
      82                 :          0 :                         goto cleanup;
      83                 :            :                 }
      84                 :            : 
      85         [ #  # ]:          0 :                 if (j < 0) {
      86                 :          0 :                         TFP_DRV_LOG(ERR, "%d TBL: invalid offset (%d)\n",
      87                 :            :                                     dir, j);
      88                 :          0 :                         goto cleanup;
      89                 :            :                 }
      90                 :          0 :                 j -= entry_sz_bytes;
      91                 :            :         }
      92                 :            : 
      93         [ #  # ]:          0 :         if (!stack_is_full(pool)) {
      94                 :            :                 rc = -EINVAL;
      95                 :          0 :                 TFP_DRV_LOG(ERR, "%s TBL: stack failure %s\n",
      96                 :            :                             tf_dir_2_str(dir), strerror(-rc));
      97                 :          0 :                 goto cleanup;
      98                 :            :         }
      99                 :            :         return 0;
     100                 :          0 : cleanup:
     101                 :          0 :         tfp_free((void *)parms.mem_va);
     102                 :          0 :         return rc;
     103                 :            : }
     104                 :            : 
     105                 :            : /**
     106                 :            :  * Destroy External Tbl pool of memory indexes.
     107                 :            :  *
     108                 :            :  * [in] dir
     109                 :            :  *   direction
     110                 :            :  * [in] tbl_scope_cb
     111                 :            :  *   pointer to the table scope
     112                 :            :  */
     113                 :            : void
     114                 :          0 : tf_destroy_tbl_pool_external(enum tf_dir dir,
     115                 :            :                              struct tf_tbl_scope_cb *tbl_scope_cb)
     116                 :            : {
     117                 :          0 :         uint32_t *ext_act_pool_mem =
     118                 :            :                 tbl_scope_cb->ext_act_pool_mem[dir];
     119                 :            : 
     120                 :          0 :         tfp_free(ext_act_pool_mem);
     121                 :          0 : }
     122                 :            : 
     123                 :            : /**
     124                 :            :  * Looks up table scope control block using tbl_scope_id from tf_session.
     125                 :            :  *
     126                 :            :  * [in] tfp
     127                 :            :  *   Pointer to Truflow Handle
     128                 :            :  * [in] tbl_scope_id
     129                 :            :  *   table scope id
     130                 :            :  *
     131                 :            :  * Return:
     132                 :            :  *  - Pointer to the tf_tbl_scope_cb, if found.
     133                 :            :  *  - (NULL) on failure, not found.
     134                 :            :  */
     135                 :            : struct tf_tbl_scope_cb *
     136                 :          0 : tf_em_ext_common_tbl_scope_find(struct tf *tfp,
     137                 :            :                         uint32_t tbl_scope_id)
     138                 :            : {
     139                 :            :         int rc;
     140                 :            :         struct em_ext_db *ext_db;
     141                 :          0 :         void *ext_ptr = NULL;
     142                 :            :         struct tf_tbl_scope_cb *tbl_scope_cb = NULL;
     143                 :            :         struct ll_entry *entry;
     144                 :            : 
     145                 :          0 :         rc = tf_session_get_em_ext_db(tfp, &ext_ptr);
     146         [ #  # ]:          0 :         if (rc)
     147                 :            :                 return NULL;
     148                 :            : 
     149                 :          0 :         ext_db = (struct em_ext_db *)ext_ptr;
     150                 :            : 
     151         [ #  # ]:          0 :         for (entry = ext_db->tbl_scope_ll.head; entry != NULL;
     152                 :          0 :                         entry = entry->next) {
     153                 :            :                 tbl_scope_cb = (struct tf_tbl_scope_cb *)entry;
     154         [ #  # ]:          0 :                 if (tbl_scope_cb->tbl_scope_id == tbl_scope_id)
     155                 :          0 :                         return tbl_scope_cb;
     156                 :            :         }
     157                 :            : 
     158                 :            :         return NULL;
     159                 :            : }
     160                 :            : 
     161                 :            : /**
     162                 :            :  * Allocate External Tbl entry from the scope pool.
     163                 :            :  *
     164                 :            :  * [in] tfp
     165                 :            :  *   Pointer to Truflow Handle
     166                 :            :  * [in] parms
     167                 :            :  *   Allocation parameters
     168                 :            :  *
     169                 :            :  * Return:
     170                 :            :  *  0       - Success, entry allocated - no search support
     171                 :            :  *  -ENOMEM -EINVAL -EOPNOTSUPP
     172                 :            :  *          - Failure, entry not allocated, out of resources
     173                 :            :  */
     174                 :            : int
     175                 :          0 : tf_tbl_ext_alloc(struct tf *tfp,
     176                 :            :                  struct tf_tbl_alloc_parms *parms)
     177                 :            : {
     178                 :            :         int rc;
     179                 :            :         uint32_t index;
     180                 :            :         struct tf_tbl_scope_cb *tbl_scope_cb;
     181                 :            :         struct stack *pool;
     182                 :            : 
     183         [ #  # ]:          0 :         TF_CHECK_PARMS2(tfp, parms);
     184                 :            : 
     185                 :          0 :         tbl_scope_cb = tf_em_ext_common_tbl_scope_find(tfp, parms->tbl_scope_id);
     186         [ #  # ]:          0 :         if (tbl_scope_cb == NULL) {
     187                 :          0 :                 TFP_DRV_LOG(ERR,
     188                 :            :                             "%s, table scope not allocated\n",
     189                 :            :                             tf_dir_2_str(parms->dir));
     190                 :          0 :                 return -EINVAL;
     191                 :            :         }
     192                 :            : 
     193                 :          0 :         pool = &tbl_scope_cb->ext_act_pool[parms->dir];
     194                 :            : 
     195                 :            :         /* Allocate an element
     196                 :            :          */
     197                 :          0 :         rc = stack_pop(pool, &index);
     198                 :            : 
     199         [ #  # ]:          0 :         if (rc != 0) {
     200                 :          0 :                 TFP_DRV_LOG(ERR,
     201                 :            :                    "%s, Allocation failed, type:%d\n",
     202                 :            :                    tf_dir_2_str(parms->dir),
     203                 :            :                    parms->type);
     204                 :          0 :                 return rc;
     205                 :            :         }
     206                 :            : 
     207                 :          0 :         *parms->idx = index;
     208                 :          0 :         return rc;
     209                 :            : }
     210                 :            : 
     211                 :            : /**
     212                 :            :  * Free External Tbl entry to the scope pool.
     213                 :            :  *
     214                 :            :  * [in] tfp
     215                 :            :  *   Pointer to Truflow Handle
     216                 :            :  * [in] parms
     217                 :            :  *   Allocation parameters
     218                 :            :  *
     219                 :            :  * Return:
     220                 :            :  *  0       - Success, entry freed
     221                 :            :  *
     222                 :            :  * - Failure, entry not successfully freed for these reasons
     223                 :            :  *  -ENOMEM
     224                 :            :  *  -EOPNOTSUPP
     225                 :            :  *  -EINVAL
     226                 :            :  */
     227                 :            : int
     228                 :          0 : tf_tbl_ext_free(struct tf *tfp,
     229                 :            :                 struct tf_tbl_free_parms *parms)
     230                 :            : {
     231                 :            :         int rc = 0;
     232                 :            :         uint32_t index;
     233                 :            :         struct tf_tbl_scope_cb *tbl_scope_cb;
     234                 :            :         struct stack *pool;
     235                 :            : 
     236         [ #  # ]:          0 :         TF_CHECK_PARMS2(tfp, parms);
     237                 :            : 
     238                 :          0 :         tbl_scope_cb = tf_em_ext_common_tbl_scope_find(tfp, parms->tbl_scope_id);
     239         [ #  # ]:          0 :         if (tbl_scope_cb == NULL) {
     240                 :          0 :                 TFP_DRV_LOG(ERR,
     241                 :            :                             "%s, table scope error\n",
     242                 :            :                             tf_dir_2_str(parms->dir));
     243                 :          0 :                 return -EINVAL;
     244                 :            :         }
     245                 :          0 :         pool = &tbl_scope_cb->ext_act_pool[parms->dir];
     246                 :            : 
     247                 :          0 :         index = parms->idx;
     248                 :            : 
     249                 :          0 :         rc = stack_push(pool, index);
     250                 :            : 
     251         [ #  # ]:          0 :         if (rc != 0) {
     252                 :          0 :                 TFP_DRV_LOG(ERR,
     253                 :            :                    "%s, consistency error, stack full, type:%d, idx:%d\n",
     254                 :            :                    tf_dir_2_str(parms->dir),
     255                 :            :                    parms->type,
     256                 :            :                    index);
     257                 :            :         }
     258                 :            :         return rc;
     259                 :            : }
     260                 :            : 
     261                 :            : uint32_t
     262                 :          0 : tf_em_get_key_mask(int num_entries)
     263                 :            : {
     264                 :          0 :         uint32_t mask = num_entries - 1;
     265                 :            : 
     266         [ #  # ]:          0 :         if (num_entries & TF_EM_MAX_MASK)
     267                 :            :                 return 0;
     268                 :            : 
     269         [ #  # ]:          0 :         if (num_entries > TF_EM_MAX_ENTRY)
     270                 :          0 :                 return 0;
     271                 :            : 
     272                 :            :         return mask;
     273                 :            : }
     274                 :            : 
     275                 :            : void
     276                 :          0 : tf_em_create_key_entry(struct cfa_p4_eem_entry_hdr *result,
     277                 :            :                        uint8_t *in_key,
     278                 :            :                        struct cfa_p4_eem_64b_entry *key_entry)
     279                 :            : {
     280                 :          0 :         key_entry->hdr.word1 = result->word1;
     281                 :          0 :         key_entry->hdr.pointer = result->pointer;
     282                 :          0 :         memcpy(key_entry->key, in_key, TF_P4_HW_EM_KEY_MAX_SIZE + 4);
     283                 :          0 : }
     284                 :            : 
     285                 :            : /**
     286                 :            :  * Return the number of page table pages needed to
     287                 :            :  * reference the given number of next level pages.
     288                 :            :  *
     289                 :            :  * [in] num_pages
     290                 :            :  *   Number of EM pages
     291                 :            :  *
     292                 :            :  * [in] page_size
     293                 :            :  *   Size of each EM page
     294                 :            :  *
     295                 :            :  * Returns:
     296                 :            :  *   Number of EM page table pages
     297                 :            :  */
     298                 :            : static uint32_t
     299                 :            : tf_em_page_tbl_pgcnt(uint32_t num_pages,
     300                 :            :                      uint32_t page_size)
     301                 :            : {
     302   [ #  #  #  #  :          0 :         return roundup(num_pages, MAX_PAGE_PTRS(page_size)) /
                   #  # ]
     303                 :            :                        MAX_PAGE_PTRS(page_size);
     304                 :            :         return 0;
     305                 :            : }
     306                 :            : 
     307                 :            : /**
     308                 :            :  * Given the number of data pages, page_size and the maximum
     309                 :            :  * number of page table levels (already determined), size
     310                 :            :  * the number of page table pages required at each level.
     311                 :            :  *
     312                 :            :  * [in] max_lvl
     313                 :            :  *   Max number of levels
     314                 :            :  *
     315                 :            :  * [in] num_data_pages
     316                 :            :  *   Number of EM data pages
     317                 :            :  *
     318                 :            :  * [in] page_size
     319                 :            :  *   Size of an EM page
     320                 :            :  *
     321                 :            :  * [out] *page_cnt
     322                 :            :  *   EM page count
     323                 :            :  */
     324                 :            : static void
     325                 :          0 : tf_em_size_page_tbls(int max_lvl,
     326                 :            :                      uint64_t num_data_pages,
     327                 :            :                      uint32_t page_size,
     328                 :            :                      uint32_t *page_cnt)
     329                 :            : {
     330         [ #  # ]:          0 :         if (max_lvl == TF_PT_LVL_0) {
     331                 :          0 :                 page_cnt[TF_PT_LVL_0] = num_data_pages;
     332         [ #  # ]:          0 :         } else if (max_lvl == TF_PT_LVL_1) {
     333         [ #  # ]:          0 :                 page_cnt[TF_PT_LVL_1] = num_data_pages;
     334                 :          0 :                 page_cnt[TF_PT_LVL_0] =
     335                 :            :                 tf_em_page_tbl_pgcnt(page_cnt[TF_PT_LVL_1], page_size);
     336         [ #  # ]:          0 :         } else if (max_lvl == TF_PT_LVL_2) {
     337         [ #  # ]:          0 :                 page_cnt[TF_PT_LVL_2] = num_data_pages;
     338         [ #  # ]:          0 :                 page_cnt[TF_PT_LVL_1] =
     339                 :            :                 tf_em_page_tbl_pgcnt(page_cnt[TF_PT_LVL_2], page_size);
     340                 :          0 :                 page_cnt[TF_PT_LVL_0] =
     341                 :            :                 tf_em_page_tbl_pgcnt(page_cnt[TF_PT_LVL_1], page_size);
     342                 :            :         } else {
     343                 :            :                 return;
     344                 :            :         }
     345                 :            : }
     346                 :            : 
     347                 :            : /**
     348                 :            :  * Given the page size, size of each data item (entry size),
     349                 :            :  * and the total number of entries needed, determine the number
     350                 :            :  * of page table levels and the number of data pages required.
     351                 :            :  *
     352                 :            :  * [in] page_size
     353                 :            :  *   Page size
     354                 :            :  *
     355                 :            :  * [in] entry_size
     356                 :            :  *   Entry size
     357                 :            :  *
     358                 :            :  * [in] num_entries
     359                 :            :  *   Number of entries needed
     360                 :            :  *
     361                 :            :  * [out] num_data_pages
     362                 :            :  *   Number of pages required
     363                 :            :  *
     364                 :            :  * Returns:
     365                 :            :  *   Success  - Number of EM page levels required
     366                 :            :  *   -ENOMEM  - Out of memory
     367                 :            :  */
     368                 :            : static int
     369                 :          0 : tf_em_size_page_tbl_lvl(uint32_t page_size,
     370                 :            :                         uint32_t entry_size,
     371                 :            :                         uint32_t num_entries,
     372                 :            :                         uint64_t *num_data_pages)
     373                 :            : {
     374                 :          0 :         uint64_t lvl_data_size = page_size;
     375                 :            :         int lvl = TF_PT_LVL_0;
     376                 :            :         uint64_t data_size;
     377                 :            : 
     378                 :          0 :         *num_data_pages = 0;
     379                 :          0 :         data_size = (uint64_t)num_entries * entry_size;
     380                 :            : 
     381         [ #  # ]:          0 :         while (lvl_data_size < data_size) {
     382                 :          0 :                 lvl++;
     383                 :            : 
     384         [ #  # ]:          0 :                 if (lvl == TF_PT_LVL_1)
     385                 :          0 :                         lvl_data_size = (uint64_t)MAX_PAGE_PTRS(page_size) *
     386                 :            :                                 page_size;
     387         [ #  # ]:          0 :                 else if (lvl == TF_PT_LVL_2)
     388                 :          0 :                         lvl_data_size = (uint64_t)MAX_PAGE_PTRS(page_size) *
     389                 :            :                                 MAX_PAGE_PTRS(page_size) * page_size;
     390                 :            :                 else
     391                 :            :                         return -ENOMEM;
     392                 :            :         }
     393                 :            : 
     394   [ #  #  #  # ]:          0 :         *num_data_pages = roundup(data_size, page_size) / page_size;
     395                 :            : 
     396                 :          0 :         return lvl;
     397                 :            : }
     398                 :            : 
     399                 :            : /**
     400                 :            :  * Size the EM table based on capabilities
     401                 :            :  *
     402                 :            :  * [in] tbl
     403                 :            :  *   EM table to size
     404                 :            :  *
     405                 :            :  * Returns:
     406                 :            :  *   0        - Success
     407                 :            :  *   - EINVAL - Parameter error
     408                 :            :  *   - ENOMEM - Out of memory
     409                 :            :  */
     410                 :            : int
     411                 :          0 : tf_em_size_table(struct hcapi_cfa_em_table *tbl,
     412                 :            :                  uint32_t page_size)
     413                 :            : {
     414                 :            :         uint64_t num_data_pages;
     415                 :            :         uint32_t *page_cnt;
     416                 :            :         int max_lvl;
     417                 :            :         uint32_t num_entries;
     418                 :            :         uint32_t cnt = TF_EM_MIN_ENTRIES;
     419                 :            : 
     420                 :            :         /* Ignore entry if both size and number are zero */
     421   [ #  #  #  # ]:          0 :         if (!tbl->entry_size && !tbl->num_entries)
     422                 :            :                 return 0;
     423                 :            : 
     424                 :            :         /* If only one is set then error */
     425   [ #  #  #  # ]:          0 :         if (!tbl->entry_size || !tbl->num_entries)
     426                 :            :                 return -EINVAL;
     427                 :            : 
     428                 :            :         /* Determine number of page table levels and the number
     429                 :            :          * of data pages needed to process the given eem table.
     430                 :            :          */
     431         [ #  # ]:          0 :         if (tbl->type == TF_RECORD_TABLE) {
     432                 :            :                 /*
     433                 :            :                  * For action records just a memory size is provided. Work
     434                 :            :                  * backwards to resolve to number of entries
     435                 :            :                  */
     436                 :          0 :                 num_entries = tbl->num_entries / tbl->entry_size;
     437         [ #  # ]:          0 :                 if (num_entries < TF_EM_MIN_ENTRIES) {
     438                 :            :                         num_entries = TF_EM_MIN_ENTRIES;
     439                 :            :                 } else {
     440         [ #  # ]:          0 :                         while (num_entries > cnt && cnt <= TF_EM_MAX_ENTRIES)
     441                 :          0 :                                 cnt *= 2;
     442                 :            :                         num_entries = cnt;
     443                 :            :                 }
     444                 :            :         } else {
     445                 :            :                 num_entries = tbl->num_entries;
     446                 :            :         }
     447                 :            : 
     448                 :          0 :         max_lvl = tf_em_size_page_tbl_lvl(page_size,
     449                 :            :                                           tbl->entry_size,
     450                 :            :                                           tbl->num_entries,
     451                 :            :                                           &num_data_pages);
     452         [ #  # ]:          0 :         if (max_lvl < 0) {
     453                 :          0 :                 TFP_DRV_LOG(WARNING, "EEM: Failed to size page table levels\n");
     454                 :          0 :                 TFP_DRV_LOG(WARNING,
     455                 :            :                             "table: %d data-sz: %016" PRIu64 " page-sz: %u\n",
     456                 :            :                             tbl->type, (uint64_t)num_entries * tbl->entry_size,
     457                 :            :                             page_size);
     458                 :          0 :                 return -ENOMEM;
     459                 :            :         }
     460                 :            : 
     461                 :          0 :         tbl->num_lvl = max_lvl + 1;
     462                 :          0 :         tbl->num_data_pages = num_data_pages;
     463                 :            : 
     464                 :            :         /* Determine the number of pages needed at each level */
     465                 :          0 :         page_cnt = tbl->page_cnt;
     466                 :            :         memset(page_cnt, 0, sizeof(tbl->page_cnt));
     467                 :          0 :         tf_em_size_page_tbls(max_lvl, num_data_pages, page_size,
     468                 :            :                                 page_cnt);
     469                 :            : 
     470                 :          0 :         TFP_DRV_LOG(INFO, "EEM: Sized page table: %d\n", tbl->type);
     471                 :          0 :         TFP_DRV_LOG(INFO,
     472                 :            :                     "EEM: lvls: %d sz: %016" PRIu64 " pgs: %016" PRIu64 \
     473                 :            :                     " l0: %u l1: %u l2: %u\n",
     474                 :            :                     max_lvl + 1,
     475                 :            :                     (uint64_t)num_data_pages * page_size,
     476                 :            :                     num_data_pages,
     477                 :            :                     page_cnt[TF_PT_LVL_0],
     478                 :            :                     page_cnt[TF_PT_LVL_1],
     479                 :            :                     page_cnt[TF_PT_LVL_2]);
     480                 :            : 
     481                 :          0 :         return 0;
     482                 :            : }
     483                 :            : 
     484                 :            : /**
     485                 :            :  * Validates EM number of entries requested
     486                 :            :  *
     487                 :            :  * [in] tbl_scope_cb
     488                 :            :  *   Pointer to table scope control block to be populated
     489                 :            :  *
     490                 :            :  * [in] parms
     491                 :            :  *   Pointer to input parameters
     492                 :            :  *
     493                 :            :  * Returns:
     494                 :            :  *   0       - Success
     495                 :            :  *   -EINVAL - Parameter error
     496                 :            :  */
     497                 :            : int
     498                 :          0 : tf_em_validate_num_entries(struct tf_tbl_scope_cb *tbl_scope_cb,
     499                 :            :                            struct tf_alloc_tbl_scope_parms *parms)
     500                 :            : {
     501                 :            :         uint32_t cnt;
     502                 :            : 
     503         [ #  # ]:          0 :         if (parms->rx_mem_size_in_mb != 0) {
     504                 :          0 :                 uint32_t key_b = 2 * ((parms->rx_max_key_sz_in_bits / 8) + 1);
     505                 :          0 :                 uint32_t action_b = ((parms->rx_max_action_entry_sz_in_bits / 8)
     506                 :          0 :                                      + 1);
     507                 :          0 :                 uint32_t num_entries = (parms->rx_mem_size_in_mb *
     508                 :          0 :                                         TF_MEGABYTE) / (key_b + action_b);
     509                 :            : 
     510         [ #  # ]:          0 :                 if (num_entries < TF_EM_MIN_ENTRIES) {
     511                 :          0 :                         TFP_DRV_LOG(ERR, "EEM: Insufficient memory requested:"
     512                 :            :                                     "%uMB\n",
     513                 :            :                                     parms->rx_mem_size_in_mb);
     514                 :          0 :                         return -EINVAL;
     515                 :            :                 }
     516                 :            : 
     517                 :            :                 cnt = TF_EM_MIN_ENTRIES;
     518                 :          0 :                 while (num_entries > cnt &&
     519         [ #  # ]:          0 :                        cnt <= TF_EM_MAX_ENTRIES)
     520                 :          0 :                         cnt *= 2;
     521                 :            : 
     522         [ #  # ]:          0 :                 if (cnt > TF_EM_MAX_ENTRIES) {
     523                 :          0 :                         TFP_DRV_LOG(ERR, "EEM: Invalid number of Tx requested: "
     524                 :            :                                     "%u\n",
     525                 :            :                        (parms->tx_num_flows_in_k * TF_KILOBYTE));
     526                 :          0 :                         return -EINVAL;
     527                 :            :                 }
     528                 :            : 
     529                 :          0 :                 parms->rx_num_flows_in_k = cnt / TF_KILOBYTE;
     530                 :            :         } else {
     531         [ #  # ]:          0 :                 if ((parms->rx_num_flows_in_k * TF_KILOBYTE) <
     532                 :          0 :                     TF_EM_MIN_ENTRIES ||
     533                 :            :                     (parms->rx_num_flows_in_k * TF_KILOBYTE) >
     534         [ #  # ]:          0 :                     tbl_scope_cb->em_caps[TF_DIR_RX].max_entries_supported) {
     535                 :          0 :                         TFP_DRV_LOG(ERR,
     536                 :            :                                     "EEM: Invalid number of Rx flows "
     537                 :            :                                     "requested:%u max:%u\n",
     538                 :            :                                     parms->rx_num_flows_in_k * TF_KILOBYTE,
     539                 :            :                         tbl_scope_cb->em_caps[TF_DIR_RX].max_entries_supported);
     540                 :          0 :                         return -EINVAL;
     541                 :            :                 }
     542                 :            : 
     543                 :            :                 /* must be a power-of-2 supported value
     544                 :            :                  * in the range 32K - 128M
     545                 :            :                  */
     546                 :            :                 cnt = TF_EM_MIN_ENTRIES;
     547   [ #  #  #  # ]:          0 :                 while ((parms->rx_num_flows_in_k * TF_KILOBYTE) != cnt &&
     548                 :            :                        cnt <= TF_EM_MAX_ENTRIES)
     549                 :          0 :                         cnt *= 2;
     550                 :            : 
     551         [ #  # ]:          0 :                 if (cnt > TF_EM_MAX_ENTRIES) {
     552                 :          0 :                         TFP_DRV_LOG(ERR,
     553                 :            :                                     "EEM: Invalid number of Rx requested: %u\n",
     554                 :            :                                     (parms->rx_num_flows_in_k * TF_KILOBYTE));
     555                 :          0 :                         return -EINVAL;
     556                 :            :                 }
     557                 :            :         }
     558                 :            : 
     559         [ #  # ]:          0 :         if (parms->tx_mem_size_in_mb != 0) {
     560                 :          0 :                 uint32_t key_b = 2 * (parms->tx_max_key_sz_in_bits / 8 + 1);
     561                 :          0 :                 uint32_t action_b = ((parms->tx_max_action_entry_sz_in_bits / 8)
     562                 :          0 :                                      + 1);
     563                 :          0 :                 uint32_t num_entries = (parms->tx_mem_size_in_mb *
     564                 :            :                                         (TF_KILOBYTE * TF_KILOBYTE)) /
     565                 :          0 :                         (key_b + action_b);
     566                 :            : 
     567         [ #  # ]:          0 :                 if (num_entries < TF_EM_MIN_ENTRIES) {
     568                 :          0 :                         TFP_DRV_LOG(ERR,
     569                 :            :                                     "EEM: Insufficient memory requested:%uMB\n",
     570                 :            :                                     parms->rx_mem_size_in_mb);
     571                 :          0 :                         return -EINVAL;
     572                 :            :                 }
     573                 :            : 
     574                 :            :                 cnt = TF_EM_MIN_ENTRIES;
     575                 :          0 :                 while (num_entries > cnt &&
     576         [ #  # ]:          0 :                        cnt <= TF_EM_MAX_ENTRIES)
     577                 :          0 :                         cnt *= 2;
     578                 :            : 
     579         [ #  # ]:          0 :                 if (cnt > TF_EM_MAX_ENTRIES) {
     580                 :          0 :                         TFP_DRV_LOG(ERR,
     581                 :            :                                     "EEM: Invalid number of Tx requested: %u\n",
     582                 :            :                        (parms->tx_num_flows_in_k * TF_KILOBYTE));
     583                 :          0 :                         return -EINVAL;
     584                 :            :                 }
     585                 :            : 
     586                 :          0 :                 parms->tx_num_flows_in_k = cnt / TF_KILOBYTE;
     587                 :            :         } else {
     588         [ #  # ]:          0 :                 if ((parms->tx_num_flows_in_k * TF_KILOBYTE) <
     589                 :          0 :                     TF_EM_MIN_ENTRIES ||
     590                 :            :                     (parms->tx_num_flows_in_k * TF_KILOBYTE) >
     591         [ #  # ]:          0 :                     tbl_scope_cb->em_caps[TF_DIR_TX].max_entries_supported) {
     592                 :          0 :                         TFP_DRV_LOG(ERR,
     593                 :            :                                     "EEM: Invalid number of Tx flows "
     594                 :            :                                     "requested:%u max:%u\n",
     595                 :            :                                     (parms->tx_num_flows_in_k * TF_KILOBYTE),
     596                 :            :                         tbl_scope_cb->em_caps[TF_DIR_TX].max_entries_supported);
     597                 :          0 :                         return -EINVAL;
     598                 :            :                 }
     599                 :            : 
     600                 :            :                 cnt = TF_EM_MIN_ENTRIES;
     601   [ #  #  #  # ]:          0 :                 while ((parms->tx_num_flows_in_k * TF_KILOBYTE) != cnt &&
     602                 :            :                        cnt <= TF_EM_MAX_ENTRIES)
     603                 :          0 :                         cnt *= 2;
     604                 :            : 
     605         [ #  # ]:          0 :                 if (cnt > TF_EM_MAX_ENTRIES) {
     606                 :          0 :                         TFP_DRV_LOG(ERR,
     607                 :            :                                     "EEM: Invalid number of Tx requested: %u\n",
     608                 :            :                        (parms->tx_num_flows_in_k * TF_KILOBYTE));
     609                 :          0 :                         return -EINVAL;
     610                 :            :                 }
     611                 :            :         }
     612                 :            : 
     613         [ #  # ]:          0 :         if (parms->rx_num_flows_in_k != 0 &&
     614         [ #  # ]:          0 :             parms->rx_max_key_sz_in_bits / 8 == 0) {
     615                 :          0 :                 TFP_DRV_LOG(ERR,
     616                 :            :                             "EEM: Rx key size required: %u\n",
     617                 :            :                             (parms->rx_max_key_sz_in_bits));
     618                 :          0 :                 return -EINVAL;
     619                 :            :         }
     620                 :            : 
     621         [ #  # ]:          0 :         if (parms->tx_num_flows_in_k != 0 &&
     622         [ #  # ]:          0 :             parms->tx_max_key_sz_in_bits / 8 == 0) {
     623                 :          0 :                 TFP_DRV_LOG(ERR,
     624                 :            :                             "EEM: Tx key size required: %u\n",
     625                 :            :                             (parms->tx_max_key_sz_in_bits));
     626                 :          0 :                 return -EINVAL;
     627                 :            :         }
     628                 :            :         /* Rx */
     629                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY0_TABLE].num_entries =
     630                 :          0 :                 parms->rx_num_flows_in_k * TF_KILOBYTE;
     631                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY0_TABLE].entry_size =
     632                 :          0 :                 parms->rx_max_key_sz_in_bits / 8;
     633                 :            : 
     634                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY1_TABLE].num_entries =
     635                 :            :                 parms->rx_num_flows_in_k * TF_KILOBYTE;
     636                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY1_TABLE].entry_size =
     637                 :            :                 parms->rx_max_key_sz_in_bits / 8;
     638                 :            : 
     639                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_RECORD_TABLE].num_entries =
     640                 :            :                 parms->rx_num_flows_in_k * TF_KILOBYTE;
     641                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_RECORD_TABLE].entry_size =
     642                 :          0 :                 parms->rx_max_action_entry_sz_in_bits / 8;
     643                 :            : 
     644                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_EFC_TABLE].num_entries =
     645                 :            :                 0;
     646                 :            : 
     647                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_ACTION_TABLE].num_entries =
     648                 :            :                 parms->rx_num_flows_in_k * TF_KILOBYTE;
     649                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_ACTION_TABLE].entry_size =
     650                 :            :                 parms->rx_max_action_entry_sz_in_bits / 8;
     651                 :            : 
     652                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_EM_LKUP_TABLE].num_entries =
     653                 :            :                 parms->rx_num_flows_in_k * TF_KILOBYTE;
     654                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_EM_LKUP_TABLE].entry_size =
     655                 :            :                 parms->rx_max_key_sz_in_bits / 8;
     656                 :            : 
     657                 :            :         /* Tx */
     658                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY0_TABLE].num_entries =
     659                 :          0 :                 parms->tx_num_flows_in_k * TF_KILOBYTE;
     660                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY0_TABLE].entry_size =
     661                 :          0 :                 parms->tx_max_key_sz_in_bits / 8;
     662                 :            : 
     663                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY1_TABLE].num_entries =
     664                 :            :                 parms->tx_num_flows_in_k * TF_KILOBYTE;
     665                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY1_TABLE].entry_size =
     666                 :            :                 parms->tx_max_key_sz_in_bits / 8;
     667                 :            : 
     668                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_RECORD_TABLE].num_entries =
     669                 :            :                 parms->tx_num_flows_in_k * TF_KILOBYTE;
     670                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_RECORD_TABLE].entry_size =
     671                 :          0 :                 parms->tx_max_action_entry_sz_in_bits / 8;
     672                 :            : 
     673                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_EFC_TABLE].num_entries =
     674                 :            :                 0;
     675                 :            : 
     676                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_ACTION_TABLE].num_entries =
     677                 :            :                 parms->rx_num_flows_in_k * TF_KILOBYTE;
     678                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_ACTION_TABLE].entry_size =
     679                 :            :                 parms->tx_max_action_entry_sz_in_bits / 8;
     680                 :            : 
     681                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_EM_LKUP_TABLE].num_entries =
     682                 :            :                 parms->rx_num_flows_in_k * TF_KILOBYTE;
     683                 :          0 :         tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_EM_LKUP_TABLE].entry_size =
     684                 :            :                 parms->tx_max_key_sz_in_bits / 8;
     685                 :            : 
     686                 :          0 :         return 0;
     687                 :            : }
     688                 :            : 
     689                 :            : /** insert EEM entry API
     690                 :            :  *
     691                 :            :  * returns:
     692                 :            :  *  0
     693                 :            :  *  TF_ERR          - unable to get lock
     694                 :            :  *
     695                 :            :  * insert callback returns:
     696                 :            :  *   0
     697                 :            :  *   TF_ERR_EM_DUP  - key is already in table
     698                 :            :  */
     699                 :            : static int
     700                 :          0 : tf_insert_eem_entry(struct tf_dev_info *dev,
     701                 :            :                     struct tf_tbl_scope_cb *tbl_scope_cb,
     702                 :            :                     struct tf_insert_em_entry_parms *parms)
     703                 :            : {
     704                 :            :         uint32_t mask;
     705                 :            :         uint32_t key0_hash;
     706                 :            :         uint32_t key1_hash;
     707                 :            :         uint32_t key0_index;
     708                 :            :         uint32_t key1_index;
     709                 :            :         struct cfa_p4_eem_64b_entry key_entry;
     710                 :            :         uint32_t index;
     711                 :            :         enum hcapi_cfa_em_table_type table_type;
     712                 :            :         uint32_t gfid;
     713                 :            :         struct hcapi_cfa_hwop op;
     714                 :            :         struct hcapi_cfa_key_tbl key_tbl;
     715                 :            :         struct hcapi_cfa_key_data key_obj;
     716                 :            :         struct hcapi_cfa_key_loc key_loc;
     717                 :            :         uint64_t big_hash;
     718                 :            :         int rc;
     719                 :            : 
     720                 :            :         /* Get mask to use on hash */
     721                 :          0 :         mask = tf_em_get_key_mask(tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY0_TABLE].num_entries);
     722                 :            : 
     723         [ #  # ]:          0 :         if (!mask)
     724                 :            :                 return -EINVAL;
     725                 :            : 
     726         [ #  # ]:          0 :         if (dev->ops->tf_dev_cfa_key_hash == NULL)
     727                 :            :                 return -EINVAL;
     728                 :            : 
     729                 :          0 :         big_hash = dev->ops->tf_dev_cfa_key_hash((uint64_t *)parms->key,
     730                 :            :                                          (TF_P4_HW_EM_KEY_MAX_SIZE + 4) * 8);
     731                 :          0 :         key0_hash = (uint32_t)(big_hash >> 32);
     732                 :          0 :         key1_hash = (uint32_t)(big_hash & 0xFFFFFFFF);
     733                 :            : 
     734                 :          0 :         key0_index = key0_hash & mask;
     735                 :          0 :         key1_index = key1_hash & mask;
     736                 :            : 
     737                 :            :         /*
     738                 :            :          * Use the "result" arg to populate all of the key entry then
     739                 :            :          * store the byte swapped "raw" entry in a local copy ready
     740                 :            :          * for insertion in to the table.
     741                 :            :          */
     742                 :          0 :         tf_em_create_key_entry((struct cfa_p4_eem_entry_hdr *)parms->em_record,
     743                 :            :                                 ((uint8_t *)parms->key),
     744                 :            :                                 &key_entry);
     745                 :            : 
     746                 :            :         /*
     747                 :            :          * Try to add to Key0 table, if that does not work then
     748                 :            :          * try the key1 table.
     749                 :            :          */
     750                 :            :         index = key0_index;
     751                 :          0 :         op.opcode = HCAPI_CFA_HWOPS_ADD;
     752                 :          0 :         key_tbl.base0 =
     753                 :          0 :                 (uint8_t *)&tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY0_TABLE];
     754                 :          0 :         key_tbl.page_size = TF_EM_PAGE_SIZE;
     755                 :          0 :         key_obj.offset = index * TF_P4_EM_KEY_RECORD_SIZE;
     756                 :          0 :         key_obj.data = (uint8_t *)&key_entry;
     757                 :          0 :         key_obj.size = TF_P4_EM_KEY_RECORD_SIZE;
     758                 :            : 
     759                 :          0 :         rc = cfa_p4_devops.hcapi_cfa_key_hw_op(&op,
     760                 :            :                                                &key_tbl,
     761                 :            :                                                &key_obj,
     762                 :            :                                                &key_loc);
     763                 :            : 
     764         [ #  # ]:          0 :         if (rc == 0) {
     765                 :            :                 table_type = TF_KEY0_TABLE;
     766                 :            :         } else {
     767                 :            :                 index = key1_index;
     768                 :            : 
     769                 :          0 :                 key_tbl.base0 =
     770                 :          0 :                         (uint8_t *)&tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY1_TABLE];
     771                 :          0 :                 key_obj.offset = index * TF_P4_EM_KEY_RECORD_SIZE;
     772                 :            : 
     773                 :          0 :                 rc = cfa_p4_devops.hcapi_cfa_key_hw_op(&op,
     774                 :            :                                                        &key_tbl,
     775                 :            :                                                        &key_obj,
     776                 :            :                                                        &key_loc);
     777         [ #  # ]:          0 :                 if (rc != 0)
     778                 :            :                         return rc;
     779                 :            : 
     780                 :            :                 table_type = TF_KEY1_TABLE;
     781                 :            :         }
     782                 :            : 
     783                 :          0 :         TF_SET_GFID(gfid,
     784                 :            :                     index,
     785                 :            :                     table_type);
     786                 :          0 :         TF_SET_FLOW_ID(parms->flow_id,
     787                 :            :                        gfid,
     788                 :            :                        TF_GFID_TABLE_EXTERNAL,
     789                 :            :                        parms->dir);
     790                 :          0 :         TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
     791                 :            :                                      0,
     792                 :            :                                      0,
     793                 :            :                                      0,
     794                 :            :                                      index,
     795                 :            :                                      0,
     796                 :            :                                      table_type);
     797                 :            : 
     798                 :          0 :         return 0;
     799                 :            : }
     800                 :            : 
     801                 :            : /** delete EEM hash entry API
     802                 :            :  *
     803                 :            :  * returns:
     804                 :            :  *   0
     805                 :            :  *   -EINVAL      - parameter error
     806                 :            :  *   TF_NO_SESSION    - bad session ID
     807                 :            :  *   TF_ERR_TBL_SCOPE - invalid table scope
     808                 :            :  *   TF_ERR_TBL_IF    - invalid table interface
     809                 :            :  *
     810                 :            :  * insert callback returns
     811                 :            :  *   0
     812                 :            :  *   TF_NO_EM_MATCH - entry not found
     813                 :            :  */
     814                 :            : static int
     815                 :            : tf_delete_eem_entry(struct tf_tbl_scope_cb *tbl_scope_cb,
     816                 :            :                     struct tf_delete_em_entry_parms *parms)
     817                 :            : {
     818                 :            :         enum hcapi_cfa_em_table_type hash_type;
     819                 :            :         uint32_t index;
     820                 :            :         struct hcapi_cfa_hwop op;
     821                 :            :         struct hcapi_cfa_key_tbl key_tbl;
     822                 :            :         struct hcapi_cfa_key_data key_obj;
     823                 :            :         struct hcapi_cfa_key_loc key_loc;
     824                 :            :         int rc;
     825                 :            : 
     826                 :          0 :         TF_GET_HASH_TYPE_FROM_FLOW_HANDLE(parms->flow_handle, hash_type);
     827                 :          0 :         TF_GET_INDEX_FROM_FLOW_HANDLE(parms->flow_handle, index);
     828                 :            : 
     829                 :          0 :         op.opcode = HCAPI_CFA_HWOPS_DEL;
     830                 :          0 :         key_tbl.base0 =
     831                 :          0 :                 (uint8_t *)&tbl_scope_cb->em_ctx_info[parms->dir].em_tables
     832                 :          0 :                         [(hash_type == 0 ? TF_KEY0_TABLE : TF_KEY1_TABLE)];
     833                 :          0 :         key_tbl.page_size = TF_EM_PAGE_SIZE;
     834                 :          0 :         key_obj.offset = index * TF_P4_EM_KEY_RECORD_SIZE;
     835                 :          0 :         key_obj.data = NULL;
     836                 :          0 :         key_obj.size = TF_P4_EM_KEY_RECORD_SIZE;
     837                 :            : 
     838                 :          0 :         rc = cfa_p4_devops.hcapi_cfa_key_hw_op(&op,
     839                 :            :                                                &key_tbl,
     840                 :            :                                                &key_obj,
     841                 :            :                                                &key_loc);
     842                 :            : 
     843                 :            :         if (!rc)
     844                 :            :                 return rc;
     845                 :            : 
     846                 :            :         return 0;
     847                 :            : }
     848                 :            : 
     849                 :            : /** insert EM hash entry API
     850                 :            :  *
     851                 :            :  *    returns:
     852                 :            :  *    0       - Success
     853                 :            :  *    -EINVAL - Error
     854                 :            :  */
     855                 :            : int
     856                 :          0 : tf_em_insert_ext_entry(struct tf *tfp,
     857                 :            :                        struct tf_insert_em_entry_parms *parms)
     858                 :            : {
     859                 :            :         int rc;
     860                 :            :         struct tf_tbl_scope_cb *tbl_scope_cb;
     861                 :            :         struct tf_session *tfs;
     862                 :            :         struct tf_dev_info *dev;
     863                 :            : 
     864                 :          0 :         tbl_scope_cb = tf_em_ext_common_tbl_scope_find(tfp, parms->tbl_scope_id);
     865         [ #  # ]:          0 :         if (tbl_scope_cb == NULL) {
     866                 :          0 :                 TFP_DRV_LOG(ERR, "Invalid tbl_scope_cb\n");
     867                 :          0 :                 return -EINVAL;
     868                 :            :         }
     869                 :            : 
     870                 :            :         /* Retrieve the session information */
     871                 :          0 :         rc = tf_session_get_session_internal(tfp, &tfs);
     872         [ #  # ]:          0 :         if (rc)
     873                 :            :                 return rc;
     874                 :            : 
     875                 :            :         /* Retrieve the device information */
     876                 :          0 :         rc = tf_session_get_device(tfs, &dev);
     877         [ #  # ]:          0 :         if (rc)
     878                 :            :                 return rc;
     879                 :            : 
     880                 :          0 :         return tf_insert_eem_entry
     881                 :            :                 (dev,
     882                 :            :                  tbl_scope_cb,
     883                 :            :                  parms);
     884                 :            : }
     885                 :            : 
     886                 :            : /** Delete EM hash entry API
     887                 :            :  *
     888                 :            :  *    returns:
     889                 :            :  *    0       - Success
     890                 :            :  *    -EINVAL - Error
     891                 :            :  */
     892                 :            : int
     893                 :          0 : tf_em_delete_ext_entry(struct tf *tfp,
     894                 :            :                        struct tf_delete_em_entry_parms *parms)
     895                 :            : {
     896                 :            :         struct tf_tbl_scope_cb *tbl_scope_cb;
     897                 :            : 
     898                 :          0 :         tbl_scope_cb = tf_em_ext_common_tbl_scope_find(tfp, parms->tbl_scope_id);
     899         [ #  # ]:          0 :         if (tbl_scope_cb == NULL) {
     900                 :          0 :                 TFP_DRV_LOG(ERR, "Invalid tbl_scope_cb\n");
     901                 :          0 :                 return -EINVAL;
     902                 :            :         }
     903                 :            : 
     904                 :          0 :         return tf_delete_eem_entry(tbl_scope_cb, parms);
     905                 :            : }
     906                 :            : 
     907                 :            : int
     908                 :          0 : tf_em_ext_common_bind(struct tf *tfp,
     909                 :            :                       struct tf_em_cfg_parms *parms)
     910                 :            : {
     911                 :            :         int rc;
     912                 :            :         int i;
     913                 :          0 :         struct tf_rm_create_db_parms db_cfg = { 0 };
     914                 :            :         struct em_ext_db *ext_db;
     915                 :            :         struct tfp_calloc_parms cparms;
     916                 :            : 
     917         [ #  # ]:          0 :         TF_CHECK_PARMS2(tfp, parms);
     918                 :            : 
     919                 :          0 :         cparms.nitems = 1;
     920                 :          0 :         cparms.size = sizeof(struct em_ext_db);
     921                 :          0 :         cparms.alignment = 0;
     922         [ #  # ]:          0 :         if (tfp_calloc(&cparms) != 0) {
     923                 :          0 :                 TFP_DRV_LOG(ERR, "em_ext_db alloc error %s\n",
     924                 :            :                             strerror(ENOMEM));
     925                 :          0 :                 return -ENOMEM;
     926                 :            :         }
     927                 :            : 
     928                 :          0 :         ext_db = cparms.mem_va;
     929                 :          0 :         ll_init(&ext_db->tbl_scope_ll);
     930         [ #  # ]:          0 :         for (i = 0; i < TF_DIR_MAX; i++)
     931                 :          0 :                 ext_db->eem_db[i] = NULL;
     932                 :          0 :         tf_session_set_em_ext_db(tfp, ext_db);
     933                 :            : 
     934                 :          0 :         db_cfg.module = TF_MODULE_TYPE_EM;
     935                 :          0 :         db_cfg.num_elements = parms->num_elements;
     936                 :          0 :         db_cfg.cfg = parms->cfg;
     937                 :            : 
     938         [ #  # ]:          0 :         for (i = 0; i < TF_DIR_MAX; i++) {
     939                 :          0 :                 db_cfg.dir = i;
     940                 :          0 :                 db_cfg.alloc_cnt = parms->resources->em_cnt[i].cnt;
     941                 :            : 
     942                 :            :                 /* Check if we got any request to support EEM, if so
     943                 :            :                  * we build an EM Ext DB holding Table Scopes.
     944                 :            :                  */
     945         [ #  # ]:          0 :                 if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_TBL_SCOPE] == 0)
     946                 :          0 :                         continue;
     947                 :            : 
     948                 :          0 :                 db_cfg.rm_db = (void *)&ext_db->eem_db[i];
     949                 :          0 :                 rc = tf_rm_create_db(tfp, &db_cfg);
     950         [ #  # ]:          0 :                 if (rc) {
     951                 :          0 :                         TFP_DRV_LOG(ERR,
     952                 :            :                                     "%s: EM Ext DB creation failed\n",
     953                 :            :                                     tf_dir_2_str(i));
     954                 :            : 
     955                 :          0 :                         return rc;
     956                 :            :                 }
     957                 :            :         }
     958                 :            : 
     959                 :          0 :         mem_type = parms->mem_type;
     960                 :            : 
     961                 :          0 :         return 0;
     962                 :            : }
     963                 :            : 
     964                 :            : int
     965                 :          0 : tf_em_ext_common_unbind(struct tf *tfp)
     966                 :            : {
     967                 :            :         int rc;
     968                 :            :         int i;
     969                 :          0 :         struct tf_rm_free_db_parms fparms = { 0 };
     970                 :            :         struct em_ext_db *ext_db = NULL;
     971                 :          0 :         struct tf_session *tfs = NULL;
     972                 :            :         struct tf_dev_info *dev;
     973                 :            :         struct ll_entry *entry;
     974                 :            :         struct tf_tbl_scope_cb *tbl_scope_cb = NULL;
     975                 :          0 :         void *ext_ptr = NULL;
     976                 :          0 :         struct tf_free_tbl_scope_parms tparms = { 0 };
     977                 :            : 
     978         [ #  # ]:          0 :         TF_CHECK_PARMS1(tfp);
     979                 :            : 
     980                 :          0 :         rc = tf_session_get_session_internal(tfp, &tfs);
     981         [ #  # ]:          0 :         if (rc) {
     982                 :          0 :                 TFP_DRV_LOG(ERR, "Failed to get tf_session, rc:%s\n",
     983                 :            :                 strerror(-rc));
     984                 :          0 :                 return rc;
     985                 :            :         }
     986                 :            : 
     987                 :            :         /* Retrieve the device information */
     988                 :          0 :         rc = tf_session_get_device(tfs, &dev);
     989         [ #  # ]:          0 :         if (rc) {
     990                 :          0 :                 TFP_DRV_LOG(ERR,
     991                 :            :                             "Failed to lookup device, rc:%s\n",
     992                 :            :                             strerror(-rc));
     993                 :          0 :                 return rc;
     994                 :            :         }
     995                 :            : 
     996                 :          0 :         rc = tf_session_get_em_ext_db(tfp, &ext_ptr);
     997         [ #  # ]:          0 :         if (rc) {
     998                 :          0 :                 TFP_DRV_LOG(ERR,
     999                 :            :                             "Failed to get em_ext_db from session, rc:%s\n",
    1000                 :            :                             strerror(-rc));
    1001                 :          0 :                 return rc;
    1002                 :            :         }
    1003                 :            : 
    1004                 :          0 :         ext_db = (struct em_ext_db *)ext_ptr;
    1005         [ #  # ]:          0 :         if (ext_db != NULL) {
    1006                 :          0 :                 entry = ext_db->tbl_scope_ll.head;
    1007         [ #  # ]:          0 :                 while (entry != NULL) {
    1008                 :            :                         tbl_scope_cb = (struct tf_tbl_scope_cb *)entry;
    1009                 :          0 :                         entry = entry->next;
    1010                 :          0 :                         tparms.tbl_scope_id =
    1011                 :          0 :                                 tbl_scope_cb->tbl_scope_id;
    1012                 :            : 
    1013         [ #  # ]:          0 :                         if (dev->ops->tf_dev_free_tbl_scope) {
    1014                 :          0 :                                 dev->ops->tf_dev_free_tbl_scope(tfp,
    1015                 :            :                                                                 &tparms);
    1016                 :            :                         } else {
    1017                 :            :                                 /* should not reach here */
    1018                 :          0 :                                 ll_delete(&ext_db->tbl_scope_ll,
    1019                 :            :                                           &tbl_scope_cb->ll_entry);
    1020                 :          0 :                                 tfp_free(tbl_scope_cb);
    1021                 :            :                         }
    1022                 :            :                 }
    1023                 :            : 
    1024         [ #  # ]:          0 :                 for (i = 0; i < TF_DIR_MAX; i++) {
    1025         [ #  # ]:          0 :                         if (ext_db->eem_db[i] == NULL)
    1026                 :          0 :                                 continue;
    1027                 :            : 
    1028                 :          0 :                         fparms.dir = i;
    1029                 :          0 :                         fparms.rm_db = ext_db->eem_db[i];
    1030                 :          0 :                         rc = tf_rm_free_db(tfp, &fparms);
    1031         [ #  # ]:          0 :                         if (rc)
    1032                 :          0 :                                 return rc;
    1033                 :            : 
    1034                 :          0 :                         ext_db->eem_db[i] = NULL;
    1035                 :            :                 }
    1036                 :            : 
    1037                 :          0 :                 tfp_free(ext_db);
    1038                 :            :         }
    1039                 :            : 
    1040                 :          0 :         tf_session_set_em_ext_db(tfp, NULL);
    1041                 :            : 
    1042                 :          0 :         return 0;
    1043                 :            : }
    1044                 :            : 
    1045                 :            : /**
    1046                 :            :  * Sets the specified external table type element.
    1047                 :            :  *
    1048                 :            :  * This API sets the specified element data
    1049                 :            :  *
    1050                 :            :  * [in] tfp
    1051                 :            :  *   Pointer to TF handle
    1052                 :            :  *
    1053                 :            :  * [in] parms
    1054                 :            :  *   Pointer to table set parameters
    1055                 :            :  *
    1056                 :            :  * Returns
    1057                 :            :  *   - (0) if successful.
    1058                 :            :  *   - (-EINVAL) on failure.
    1059                 :            :  */
    1060                 :          0 : int tf_tbl_ext_common_set(struct tf *tfp,
    1061                 :            :                           struct tf_tbl_set_parms *parms)
    1062                 :            : {
    1063                 :            :         int rc = 0;
    1064                 :            :         struct tf_tbl_scope_cb *tbl_scope_cb;
    1065                 :            :         uint32_t tbl_scope_id;
    1066                 :            :         struct hcapi_cfa_hwop op;
    1067                 :            :         struct hcapi_cfa_key_tbl key_tbl;
    1068                 :            :         struct hcapi_cfa_key_data key_obj;
    1069                 :            :         struct hcapi_cfa_key_loc key_loc;
    1070                 :            : 
    1071         [ #  # ]:          0 :         TF_CHECK_PARMS2(tfp, parms);
    1072                 :            : 
    1073         [ #  # ]:          0 :         if (parms->data == NULL) {
    1074                 :          0 :                 TFP_DRV_LOG(ERR,
    1075                 :            :                             "%s, invalid parms->data\n",
    1076                 :            :                             tf_dir_2_str(parms->dir));
    1077                 :          0 :                 return -EINVAL;
    1078                 :            :         }
    1079                 :            : 
    1080                 :          0 :         tbl_scope_id = parms->tbl_scope_id;
    1081                 :            : 
    1082         [ #  # ]:          0 :         if (tbl_scope_id == TF_TBL_SCOPE_INVALID)  {
    1083                 :          0 :                 TFP_DRV_LOG(ERR,
    1084                 :            :                             "%s, Table scope not allocated\n",
    1085                 :            :                             tf_dir_2_str(parms->dir));
    1086                 :          0 :                 return -EINVAL;
    1087                 :            :         }
    1088                 :            : 
    1089                 :          0 :         tbl_scope_cb = tf_em_ext_common_tbl_scope_find(tfp, tbl_scope_id);
    1090         [ #  # ]:          0 :         if (tbl_scope_cb == NULL) {
    1091                 :          0 :                 TFP_DRV_LOG(ERR,
    1092                 :            :                             "%s, table scope error\n",
    1093                 :            :                             tf_dir_2_str(parms->dir));
    1094                 :          0 :                 return -EINVAL;
    1095                 :            :         }
    1096                 :            : 
    1097                 :          0 :         op.opcode = HCAPI_CFA_HWOPS_PUT;
    1098                 :          0 :         key_tbl.base0 =
    1099                 :          0 :                 (uint8_t *)&tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_RECORD_TABLE];
    1100                 :          0 :         key_tbl.page_size = TF_EM_PAGE_SIZE;
    1101                 :          0 :         key_obj.offset = parms->idx;
    1102                 :          0 :         key_obj.data = parms->data;
    1103                 :          0 :         key_obj.size = parms->data_sz_in_bytes;
    1104                 :            : 
    1105                 :          0 :         rc = cfa_p4_devops.hcapi_cfa_key_hw_op(&op,
    1106                 :            :                                                &key_tbl,
    1107                 :            :                                                &key_obj,
    1108                 :            :                                                &key_loc);
    1109                 :            : 
    1110                 :          0 :         return rc;
    1111                 :            : }
    1112                 :            : 
    1113                 :            : int
    1114                 :          0 : tf_em_ext_common_alloc(struct tf *tfp,
    1115                 :            :                        struct tf_alloc_tbl_scope_parms *parms)
    1116                 :            : {
    1117                 :          0 :         return tf_em_ext_alloc(tfp, parms);
    1118                 :            : }
    1119                 :            : 
    1120                 :            : int
    1121                 :          0 : tf_em_ext_common_free(struct tf *tfp,
    1122                 :            :                       struct tf_free_tbl_scope_parms *parms)
    1123                 :            : {
    1124                 :          0 :         return tf_em_ext_free(tfp, parms);
    1125                 :            : }
    1126                 :            : 
    1127                 :          0 : int tf_em_ext_map_tbl_scope(struct tf *tfp,
    1128                 :            :                             struct tf_map_tbl_scope_parms *parms)
    1129                 :            : {
    1130                 :            :         int rc = 0;
    1131                 :            :         struct tf_session *tfs;
    1132                 :            :         struct tf_tbl_scope_cb *tbl_scope_cb;
    1133                 :          0 :         struct tf_global_cfg_parms gcfg_parms = { 0 };
    1134                 :            :         struct tfp_calloc_parms aparms;
    1135                 :            :         uint32_t *data, *mask;
    1136                 :            :         uint32_t sz_in_bytes = 8;
    1137                 :            :         struct tf_dev_info *dev;
    1138                 :            : 
    1139                 :            :         /* Retrieve the session information */
    1140                 :          0 :         rc = tf_session_get_session_internal(tfp, &tfs);
    1141         [ #  # ]:          0 :         if (rc)
    1142                 :            :                 return rc;
    1143                 :            : 
    1144                 :            :         /* Retrieve the device information */
    1145                 :          0 :         rc = tf_session_get_device(tfs, &dev);
    1146         [ #  # ]:          0 :         if (rc)
    1147                 :            :                 return rc;
    1148                 :            : 
    1149                 :          0 :         tbl_scope_cb = tf_em_ext_common_tbl_scope_find(tfp, parms->tbl_scope_id);
    1150         [ #  # ]:          0 :         if (tbl_scope_cb == NULL) {
    1151                 :          0 :                 TFP_DRV_LOG(ERR, "Invalid tbl_scope_cb tbl_scope_id(%d)\n",
    1152                 :            :                             parms->tbl_scope_id);
    1153                 :          0 :                 return -EINVAL;
    1154                 :            :         }
    1155                 :            : 
    1156         [ #  # ]:          0 :         if (dev->ops->tf_dev_map_tbl_scope == NULL) {
    1157                 :            :                 rc = -EOPNOTSUPP;
    1158                 :          0 :                 TFP_DRV_LOG(ERR,
    1159                 :            :                             "Map table scope operation not supported, rc:%s\n",
    1160                 :            :                             strerror(-rc));
    1161                 :          0 :                 return rc;
    1162                 :            :         }
    1163                 :            : 
    1164                 :          0 :         aparms.nitems = 2;
    1165                 :          0 :         aparms.size = sizeof(uint32_t);
    1166                 :          0 :         aparms.alignment = 0;
    1167                 :            : 
    1168         [ #  # ]:          0 :         if (tfp_calloc(&aparms) != 0) {
    1169                 :          0 :                 TFP_DRV_LOG(ERR, "Map tbl scope alloc data error %s\n",
    1170                 :            :                             strerror(ENOMEM));
    1171                 :          0 :                 return -ENOMEM;
    1172                 :            :         }
    1173                 :          0 :         data = aparms.mem_va;
    1174                 :            : 
    1175         [ #  # ]:          0 :         if (tfp_calloc(&aparms) != 0) {
    1176                 :          0 :                 TFP_DRV_LOG(ERR, "Map tbl scope alloc mask error %s\n",
    1177                 :            :                             strerror(ENOMEM));
    1178                 :            :                 rc = -ENOMEM;
    1179                 :          0 :                 goto clean;
    1180                 :            :         }
    1181                 :          0 :         mask = aparms.mem_va;
    1182                 :            : 
    1183                 :          0 :         rc = dev->ops->tf_dev_map_parif(tfp, parms->parif_bitmask,
    1184                 :          0 :                                         tbl_scope_cb->pf,
    1185                 :            :                                         (uint8_t *)data, (uint8_t *)mask,
    1186                 :            :                                         sz_in_bytes);
    1187                 :            : 
    1188         [ #  # ]:          0 :         if (rc) {
    1189                 :          0 :                 TFP_DRV_LOG(ERR,
    1190                 :            :                             "Map table scope config failure, rc:%s\n",
    1191                 :            :                             strerror(-rc));
    1192                 :          0 :                 goto cleaner;
    1193                 :            :         }
    1194                 :            : 
    1195                 :            :         /* Note that TF_GLOBAL_CFG_INTERNAL_PARIF_2_PF is same as below enum */
    1196                 :          0 :         gcfg_parms.type = TF_GLOBAL_CFG_TYPE_MAX;
    1197                 :          0 :         gcfg_parms.offset = 0;
    1198                 :          0 :         gcfg_parms.config = (uint8_t *)data;
    1199                 :          0 :         gcfg_parms.config_mask = (uint8_t *)mask;
    1200                 :          0 :         gcfg_parms.config_sz_in_bytes = sizeof(uint64_t);
    1201                 :            : 
    1202                 :          0 :         rc = tf_msg_set_global_cfg(tfp, &gcfg_parms);
    1203         [ #  # ]:          0 :         if (rc) {
    1204                 :          0 :                 TFP_DRV_LOG(ERR,
    1205                 :            :                             "Map tbl scope, set failed, rc:%s\n",
    1206                 :            :                             strerror(-rc));
    1207                 :            :         }
    1208                 :          0 : cleaner:
    1209                 :          0 :         tfp_free(mask);
    1210                 :          0 : clean:
    1211                 :          0 :         tfp_free(data);
    1212                 :            : 
    1213                 :          0 :         return rc;
    1214                 :            : }

Generated by: LCOV version 1.14