LCOV - code coverage report
Current view: top level - drivers/net/bnxt/tf_ulp - ulp_fc_mgr.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 281 0.0 %
Date: 2024-01-22 15:35:40 Functions: 0 15 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 140 0.0 %

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

Generated by: LCOV version 1.14