LCOV - code coverage report
Current view: top level - drivers/common/cnxk - roc_nix_tm_ops.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 606 0.0 %
Date: 2024-04-01 19:00:53 Functions: 0 28 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 434 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(C) 2021 Marvell.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "roc_api.h"
       6                 :            : #include "roc_priv.h"
       7                 :            : 
       8                 :            : int
       9                 :          0 : roc_nix_tm_sq_aura_fc(struct roc_nix_sq *sq, bool enable)
      10                 :            : {
      11                 :            :         struct npa_aq_enq_req *req;
      12                 :            :         struct npa_aq_enq_rsp *rsp;
      13                 :            :         uint64_t aura_handle;
      14                 :            :         struct npa_lf *lf;
      15                 :            :         struct mbox *mbox;
      16                 :            :         int rc = -ENOSPC;
      17                 :            : 
      18         [ #  # ]:          0 :         plt_tm_dbg("Setting SQ %u SQB aura FC to %s", sq->qid,
      19                 :            :                    enable ? "enable" : "disable");
      20                 :            : 
      21                 :          0 :         lf = idev_npa_obj_get();
      22         [ #  # ]:          0 :         if (!lf)
      23                 :            :                 return NPA_ERR_DEVICE_NOT_BOUNDED;
      24                 :            : 
      25                 :          0 :         mbox = mbox_get(lf->mbox);
      26                 :            :         /* Set/clear sqb aura fc_ena */
      27                 :          0 :         aura_handle = sq->aura_handle;
      28                 :          0 :         req = mbox_alloc_msg_npa_aq_enq(mbox);
      29         [ #  # ]:          0 :         if (req == NULL)
      30                 :          0 :                 goto exit;
      31                 :            : 
      32                 :          0 :         req->aura_id = roc_npa_aura_handle_to_aura(aura_handle);
      33                 :          0 :         req->ctype = NPA_AQ_CTYPE_AURA;
      34                 :          0 :         req->op = NPA_AQ_INSTOP_WRITE;
      35                 :            :         /* Below is not needed for aura writes but AF driver needs it */
      36                 :            :         /* AF will translate to associated poolctx */
      37                 :          0 :         req->aura.pool_addr = req->aura_id;
      38                 :            : 
      39                 :          0 :         req->aura.fc_ena = enable;
      40         [ #  # ]:          0 :         req->aura_mask.fc_ena = 1;
      41   [ #  #  #  # ]:          0 :         if (roc_model_is_cn9k() || roc_errata_npa_has_no_fc_stype_ststp()) {
      42                 :          0 :                 req->aura.fc_stype = 0x0;      /* STF */
      43                 :          0 :                 req->aura_mask.fc_stype = 0x0; /* STF */
      44                 :            :         } else {
      45                 :          0 :                 req->aura.fc_stype = 0x3;      /* STSTP */
      46                 :          0 :                 req->aura_mask.fc_stype = 0x3; /* STSTP */
      47                 :            :         }
      48                 :            : 
      49                 :          0 :         rc = mbox_process(mbox);
      50         [ #  # ]:          0 :         if (rc)
      51                 :          0 :                 goto exit;
      52                 :            : 
      53                 :            :         /* Read back npa aura ctx */
      54         [ #  # ]:          0 :         if (enable) {
      55                 :          0 :                 req = mbox_alloc_msg_npa_aq_enq(mbox);
      56         [ #  # ]:          0 :                 if (req == NULL) {
      57                 :            :                         rc = -ENOSPC;
      58                 :          0 :                         goto exit;
      59                 :            :                 }
      60                 :            : 
      61                 :          0 :                 req->aura_id = roc_npa_aura_handle_to_aura(aura_handle);
      62                 :          0 :                 req->ctype = NPA_AQ_CTYPE_AURA;
      63                 :          0 :                 req->op = NPA_AQ_INSTOP_READ;
      64                 :            : 
      65                 :            :                 rc = mbox_process_msg(mbox, (void *)&rsp);
      66         [ #  # ]:          0 :                 if (rc)
      67                 :          0 :                         goto exit;
      68                 :            : 
      69                 :            :                 /* Init when enabled as there might be no triggers */
      70                 :          0 :                 *(volatile uint64_t *)sq->fc = rsp->aura.count;
      71                 :            :         } else {
      72                 :          0 :                 *(volatile uint64_t *)sq->fc = sq->aura_sqb_bufs;
      73                 :            :         }
      74                 :            :         /* Sync write barrier */
      75                 :            :         plt_wmb();
      76                 :            :         rc = 0;
      77                 :          0 : exit:
      78                 :            :         mbox_put(mbox);
      79                 :          0 :         return rc;
      80                 :            : }
      81                 :            : 
      82                 :            : int
      83                 :          0 : roc_nix_tm_free_resources(struct roc_nix *roc_nix, bool hw_only)
      84                 :            : {
      85                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
      86                 :            : 
      87         [ #  # ]:          0 :         if (nix->tm_flags & NIX_TM_HIERARCHY_ENA)
      88                 :            :                 return -EBUSY;
      89                 :            : 
      90                 :          0 :         return nix_tm_free_resources(roc_nix, BIT(ROC_NIX_TM_USER), hw_only);
      91                 :            : }
      92                 :            : 
      93                 :            : static int
      94                 :          0 : nix_tm_adjust_shaper_pps_rate(struct nix_tm_shaper_profile *profile)
      95                 :            : {
      96                 :          0 :         uint64_t min_rate = profile->commit.rate;
      97                 :            : 
      98         [ #  # ]:          0 :         if (!profile->pkt_mode)
      99                 :            :                 return 0;
     100                 :            : 
     101                 :          0 :         profile->pkt_mode_adj = 1;
     102                 :            : 
     103         [ #  # ]:          0 :         if (profile->commit.rate &&
     104                 :            :             (profile->commit.rate < NIX_TM_MIN_SHAPER_PPS_RATE ||
     105                 :            :              profile->commit.rate > NIX_TM_MAX_SHAPER_PPS_RATE))
     106                 :            :                 return NIX_ERR_TM_INVALID_COMMIT_RATE;
     107                 :            : 
     108         [ #  # ]:          0 :         if (profile->peak.rate &&
     109                 :            :             (profile->peak.rate < NIX_TM_MIN_SHAPER_PPS_RATE ||
     110                 :            :              profile->peak.rate > NIX_TM_MAX_SHAPER_PPS_RATE))
     111                 :            :                 return NIX_ERR_TM_INVALID_PEAK_RATE;
     112                 :            : 
     113         [ #  # ]:          0 :         if (profile->peak.rate && min_rate > profile->peak.rate)
     114                 :            :                 min_rate = profile->peak.rate;
     115                 :            : 
     116                 :            :         /* Each packet accumulate single count, whereas HW
     117                 :            :          * considers each unit as Byte, so we need convert
     118                 :            :          * user pps to bps
     119                 :            :          */
     120                 :          0 :         profile->commit.rate = profile->commit.rate * 8;
     121                 :          0 :         profile->peak.rate = profile->peak.rate * 8;
     122                 :          0 :         min_rate = min_rate * 8;
     123                 :            : 
     124         [ #  # ]:          0 :         if (min_rate && (min_rate < NIX_TM_MIN_SHAPER_RATE)) {
     125                 :          0 :                 int adjust = NIX_TM_MIN_SHAPER_RATE / min_rate;
     126                 :            : 
     127                 :            :                 if (adjust > NIX_TM_LENGTH_ADJUST_MAX)
     128                 :            :                         return NIX_ERR_TM_SHAPER_PKT_LEN_ADJUST;
     129                 :            : 
     130                 :          0 :                 profile->pkt_mode_adj += adjust;
     131                 :          0 :                 profile->commit.rate += (adjust * profile->commit.rate);
     132                 :          0 :                 profile->peak.rate += (adjust * profile->peak.rate);
     133                 :            :                 /* Number of tokens freed after scheduling was proportional
     134                 :            :                  * to adjust value
     135                 :            :                  */
     136                 :          0 :                 profile->commit.size *= adjust;
     137                 :          0 :                 profile->peak.size *= adjust;
     138                 :            :         }
     139                 :            : 
     140                 :            :         return 0;
     141                 :            : }
     142                 :            : 
     143                 :            : static int
     144                 :          0 : nix_tm_shaper_profile_add(struct roc_nix *roc_nix,
     145                 :            :                           struct nix_tm_shaper_profile *profile, int skip_ins)
     146                 :            : {
     147                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
     148                 :            :         uint64_t commit_rate, commit_sz;
     149                 :            :         uint64_t min_burst, max_burst;
     150                 :            :         uint64_t peak_rate, peak_sz;
     151                 :            :         uint32_t id;
     152                 :            :         int rc;
     153                 :            : 
     154                 :          0 :         id = profile->id;
     155                 :          0 :         rc = nix_tm_adjust_shaper_pps_rate(profile);
     156         [ #  # ]:          0 :         if (rc)
     157                 :            :                 return rc;
     158                 :            : 
     159                 :          0 :         commit_rate = profile->commit.rate;
     160                 :          0 :         commit_sz = profile->commit.size;
     161                 :          0 :         peak_rate = profile->peak.rate;
     162         [ #  # ]:          0 :         peak_sz = profile->peak.size;
     163                 :            : 
     164                 :            :         min_burst = NIX_TM_MIN_SHAPER_BURST;
     165                 :            :         max_burst = roc_nix_tm_max_shaper_burst_get();
     166                 :            : 
     167   [ #  #  #  # ]:          0 :         if (nix_tm_shaper_profile_search(nix, id) && !skip_ins)
     168                 :            :                 return NIX_ERR_TM_SHAPER_PROFILE_EXISTS;
     169                 :            : 
     170         [ #  # ]:          0 :         if (profile->pkt_len_adj < NIX_TM_LENGTH_ADJUST_MIN ||
     171                 :            :             profile->pkt_len_adj > NIX_TM_LENGTH_ADJUST_MAX)
     172                 :            :                 return NIX_ERR_TM_SHAPER_PKT_LEN_ADJUST;
     173                 :            : 
     174                 :            :         /* We cannot support both pkt length adjust and pkt mode */
     175   [ #  #  #  # ]:          0 :         if (profile->pkt_mode && profile->pkt_len_adj)
     176                 :            :                 return NIX_ERR_TM_SHAPER_PKT_LEN_ADJUST;
     177                 :            : 
     178                 :            :         /* commit rate and burst size can be enabled/disabled */
     179         [ #  # ]:          0 :         if (commit_rate || commit_sz) {
     180         [ #  # ]:          0 :                 if (commit_sz < min_burst || commit_sz > max_burst)
     181                 :            :                         return NIX_ERR_TM_INVALID_COMMIT_SZ;
     182         [ #  # ]:          0 :                 else if (!nix_tm_shaper_rate_conv(commit_rate, NULL, NULL, NULL,
     183                 :          0 :                                                   profile->accuracy))
     184                 :            :                         return NIX_ERR_TM_INVALID_COMMIT_RATE;
     185                 :            :         }
     186                 :            : 
     187                 :            :         /* Peak rate and burst size can be enabled/disabled */
     188         [ #  # ]:          0 :         if (peak_sz || peak_rate) {
     189         [ #  # ]:          0 :                 if (peak_sz < min_burst || peak_sz > max_burst)
     190                 :            :                         return NIX_ERR_TM_INVALID_PEAK_SZ;
     191         [ #  # ]:          0 :                 else if (!nix_tm_shaper_rate_conv(peak_rate, NULL, NULL, NULL,
     192                 :          0 :                                                   profile->accuracy))
     193                 :            :                         return NIX_ERR_TM_INVALID_PEAK_RATE;
     194                 :            :         }
     195                 :            : 
     196                 :            :         /* If PIR and CIR are requested, PIR should always be larger than CIR */
     197   [ #  #  #  # ]:          0 :         if (peak_rate && commit_rate && (commit_rate > peak_rate))
     198                 :            :                 return NIX_ERR_TM_INVALID_PEAK_RATE;
     199                 :            : 
     200         [ #  # ]:          0 :         if (!skip_ins)
     201                 :          0 :                 TAILQ_INSERT_TAIL(&nix->shaper_profile_list, profile, shaper);
     202                 :            : 
     203                 :          0 :         plt_tm_dbg("Added TM shaper profile %u, "
     204                 :            :                    " pir %" PRIu64 " , pbs %" PRIu64 ", cir %" PRIu64
     205                 :            :                    ", cbs %" PRIu64 " , adj %u, pkt_mode %u",
     206                 :            :                    id, profile->peak.rate, profile->peak.size,
     207                 :            :                    profile->commit.rate, profile->commit.size,
     208                 :            :                    profile->pkt_len_adj, profile->pkt_mode);
     209                 :            : 
     210                 :            :         /* Always use PIR for single rate shaping */
     211         [ #  # ]:          0 :         if (!peak_rate && commit_rate) {
     212                 :          0 :                 profile->peak.rate = profile->commit.rate;
     213                 :          0 :                 profile->peak.size = profile->commit.size;
     214                 :          0 :                 profile->commit.rate = 0;
     215                 :          0 :                 profile->commit.size = 0;
     216                 :            :         }
     217                 :            : 
     218                 :            :         /* update min rate */
     219                 :          0 :         nix->tm_rate_min = nix_tm_shaper_profile_rate_min(nix);
     220                 :          0 :         return 0;
     221                 :            : }
     222                 :            : 
     223                 :            : int
     224                 :          0 : roc_nix_tm_shaper_profile_add(struct roc_nix *roc_nix,
     225                 :            :                               struct roc_nix_tm_shaper_profile *roc_profile)
     226                 :            : {
     227                 :            :         struct nix_tm_shaper_profile *profile;
     228                 :            : 
     229                 :          0 :         profile = (struct nix_tm_shaper_profile *)roc_profile->reserved;
     230                 :            : 
     231                 :          0 :         profile->ref_cnt = 0;
     232                 :          0 :         profile->id = roc_profile->id;
     233                 :          0 :         profile->commit.rate = roc_profile->commit_rate;
     234                 :          0 :         profile->peak.rate = roc_profile->peak_rate;
     235                 :          0 :         profile->commit.size = roc_profile->commit_sz;
     236                 :          0 :         profile->peak.size = roc_profile->peak_sz;
     237                 :          0 :         profile->pkt_len_adj = roc_profile->pkt_len_adj;
     238                 :          0 :         profile->pkt_mode = roc_profile->pkt_mode;
     239                 :          0 :         profile->free_fn = roc_profile->free_fn;
     240                 :          0 :         profile->accuracy = roc_profile->accuracy;
     241                 :            : 
     242                 :          0 :         return nix_tm_shaper_profile_add(roc_nix, profile, 0);
     243                 :            : }
     244                 :            : 
     245                 :            : int
     246                 :          0 : roc_nix_tm_shaper_profile_update(struct roc_nix *roc_nix,
     247                 :            :                                  struct roc_nix_tm_shaper_profile *roc_profile)
     248                 :            : {
     249                 :            :         struct nix_tm_shaper_profile *profile;
     250                 :            : 
     251                 :          0 :         profile = (struct nix_tm_shaper_profile *)roc_profile->reserved;
     252                 :            : 
     253                 :          0 :         profile->commit.rate = roc_profile->commit_rate;
     254                 :          0 :         profile->peak.rate = roc_profile->peak_rate;
     255                 :          0 :         profile->commit.size = roc_profile->commit_sz;
     256                 :          0 :         profile->peak.size = roc_profile->peak_sz;
     257                 :          0 :         profile->pkt_len_adj = roc_profile->pkt_len_adj;
     258                 :          0 :         profile->accuracy = roc_profile->accuracy;
     259                 :            : 
     260                 :          0 :         return nix_tm_shaper_profile_add(roc_nix, profile, 1);
     261                 :            : }
     262                 :            : 
     263                 :            : int
     264                 :          0 : roc_nix_tm_shaper_profile_delete(struct roc_nix *roc_nix, uint32_t id)
     265                 :            : {
     266                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
     267                 :            :         struct nix_tm_shaper_profile *profile;
     268                 :            : 
     269                 :          0 :         profile = nix_tm_shaper_profile_search(nix, id);
     270         [ #  # ]:          0 :         if (!profile)
     271                 :            :                 return NIX_ERR_TM_INVALID_SHAPER_PROFILE;
     272                 :            : 
     273         [ #  # ]:          0 :         if (profile->ref_cnt)
     274                 :            :                 return NIX_ERR_TM_SHAPER_PROFILE_IN_USE;
     275                 :            : 
     276                 :          0 :         plt_tm_dbg("Removing TM shaper profile %u", id);
     277         [ #  # ]:          0 :         TAILQ_REMOVE(&nix->shaper_profile_list, profile, shaper);
     278                 :          0 :         nix_tm_shaper_profile_free(profile);
     279                 :            : 
     280                 :            :         /* update min rate */
     281                 :          0 :         nix->tm_rate_min = nix_tm_shaper_profile_rate_min(nix);
     282                 :          0 :         return 0;
     283                 :            : }
     284                 :            : 
     285                 :            : int
     286                 :          0 : roc_nix_tm_node_add(struct roc_nix *roc_nix, struct roc_nix_tm_node *roc_node)
     287                 :            : {
     288                 :            :         struct nix_tm_node *node;
     289                 :            : 
     290                 :          0 :         node = (struct nix_tm_node *)&roc_node->reserved;
     291                 :          0 :         node->id = roc_node->id;
     292                 :          0 :         node->priority = roc_node->priority;
     293                 :          0 :         node->weight = roc_node->weight;
     294                 :          0 :         node->lvl = roc_node->lvl;
     295                 :          0 :         node->parent_id = roc_node->parent_id;
     296                 :          0 :         node->shaper_profile_id = roc_node->shaper_profile_id;
     297                 :          0 :         node->pkt_mode = roc_node->pkt_mode;
     298                 :          0 :         node->pkt_mode_set = roc_node->pkt_mode_set;
     299                 :          0 :         node->free_fn = roc_node->free_fn;
     300                 :          0 :         node->tree = ROC_NIX_TM_USER;
     301                 :          0 :         node->rel_chan = NIX_TM_CHAN_INVALID;
     302                 :            : 
     303                 :          0 :         return nix_tm_node_add(roc_nix, node);
     304                 :            : }
     305                 :            : 
     306                 :            : int
     307                 :          0 : roc_nix_tm_node_pkt_mode_update(struct roc_nix *roc_nix, uint32_t node_id,
     308                 :            :                                 bool pkt_mode)
     309                 :            : {
     310                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
     311                 :            :         struct nix_tm_node *node, *child;
     312                 :            :         struct nix_tm_node_list *list;
     313                 :            :         int num_children = 0;
     314                 :            : 
     315                 :          0 :         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
     316         [ #  # ]:          0 :         if (!node)
     317                 :            :                 return NIX_ERR_TM_INVALID_NODE;
     318                 :            : 
     319         [ #  # ]:          0 :         if (node->pkt_mode == pkt_mode) {
     320                 :          0 :                 node->pkt_mode_set = true;
     321                 :          0 :                 return 0;
     322                 :            :         }
     323                 :            : 
     324                 :            :         /* Check for any existing children, if there are any,
     325                 :            :          * then we cannot update the pkt mode as children's quantum
     326                 :            :          * are already taken in.
     327                 :            :          */
     328                 :            :         list = nix_tm_node_list(nix, ROC_NIX_TM_USER);
     329         [ #  # ]:          0 :         TAILQ_FOREACH(child, list, node) {
     330         [ #  # ]:          0 :                 if (child->parent == node)
     331                 :          0 :                         num_children++;
     332                 :            :         }
     333                 :            : 
     334                 :            :         /* Cannot update mode if it has children or tree is enabled */
     335   [ #  #  #  # ]:          0 :         if ((nix->tm_flags & NIX_TM_HIERARCHY_ENA) && num_children)
     336                 :            :                 return -EBUSY;
     337                 :            : 
     338   [ #  #  #  # ]:          0 :         if (node->pkt_mode_set && num_children)
     339                 :            :                 return NIX_ERR_TM_PKT_MODE_MISMATCH;
     340                 :            : 
     341                 :          0 :         node->pkt_mode = pkt_mode;
     342                 :          0 :         node->pkt_mode_set = true;
     343                 :            : 
     344                 :          0 :         return 0;
     345                 :            : }
     346                 :            : 
     347                 :            : int
     348                 :          0 : roc_nix_tm_node_name_get(struct roc_nix *roc_nix, uint32_t node_id, char *buf,
     349                 :            :                          size_t buflen)
     350                 :            : {
     351                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
     352                 :            :         struct nix_tm_node *node;
     353                 :            : 
     354                 :          0 :         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
     355         [ #  # ]:          0 :         if (!node) {
     356                 :            :                 plt_strlcpy(buf, "???", buflen);
     357                 :          0 :                 return NIX_ERR_TM_INVALID_NODE;
     358                 :            :         }
     359                 :            : 
     360         [ #  # ]:          0 :         if (node->hw_lvl == NIX_TXSCH_LVL_CNT)
     361                 :          0 :                 snprintf(buf, buflen, "SQ_%d", node->id);
     362                 :            :         else
     363   [ #  #  #  #  :          0 :                 snprintf(buf, buflen, "%s_%d", nix_tm_hwlvl2str(node->hw_lvl),
                   #  # ]
     364                 :            :                          node->hw_id);
     365                 :            :         return 0;
     366                 :            : }
     367                 :            : 
     368                 :            : int
     369                 :          0 : roc_nix_tm_node_delete(struct roc_nix *roc_nix, uint32_t node_id, bool free)
     370                 :            : {
     371                 :          0 :         return nix_tm_node_delete(roc_nix, node_id, ROC_NIX_TM_USER, free);
     372                 :            : }
     373                 :            : 
     374                 :            : int
     375         [ #  # ]:          0 : roc_nix_smq_flush(struct roc_nix *roc_nix)
     376                 :            : {
     377                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
     378                 :            :         struct nix_tm_node_list *list;
     379                 :            :         enum roc_nix_tm_tree tree;
     380                 :            :         struct nix_tm_node *node;
     381                 :            :         int rc = 0;
     382                 :            : 
     383         [ #  # ]:          0 :         if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
     384                 :            :                 return 0;
     385                 :            : 
     386                 :          0 :         tree = nix->tm_tree;
     387                 :            :         list = nix_tm_node_list(nix, tree);
     388                 :            : 
     389                 :            :         /* XOFF & Flush all SMQ's. HRM mandates
     390                 :            :          * all SQ's empty before SMQ flush is issued.
     391                 :            :          */
     392         [ #  # ]:          0 :         TAILQ_FOREACH(node, list, node) {
     393         [ #  # ]:          0 :                 if (node->hw_lvl != NIX_TXSCH_LVL_SMQ)
     394                 :          0 :                         continue;
     395         [ #  # ]:          0 :                 if (!(node->flags & NIX_TM_NODE_HWRES))
     396                 :          0 :                         continue;
     397                 :            : 
     398                 :          0 :                 rc = nix_tm_smq_xoff(nix, node, true);
     399         [ #  # ]:          0 :                 if (rc) {
     400                 :          0 :                         plt_err("Failed to enable smq %u, rc=%d", node->hw_id,
     401                 :            :                                 rc);
     402                 :          0 :                         goto exit;
     403                 :            :                 }
     404                 :            :         }
     405                 :            : 
     406                 :            :         /* XON all SMQ's */
     407         [ #  # ]:          0 :         TAILQ_FOREACH(node, list, node) {
     408         [ #  # ]:          0 :                 if (node->hw_lvl != NIX_TXSCH_LVL_SMQ)
     409                 :          0 :                         continue;
     410         [ #  # ]:          0 :                 if (!(node->flags & NIX_TM_NODE_HWRES))
     411                 :          0 :                         continue;
     412                 :            : 
     413                 :          0 :                 rc = nix_tm_smq_xoff(nix, node, false);
     414         [ #  # ]:          0 :                 if (rc) {
     415                 :          0 :                         plt_err("Failed to enable smq %u, rc=%d", node->hw_id,
     416                 :            :                                 rc);
     417                 :          0 :                         goto exit;
     418                 :            :                 }
     419                 :            :         }
     420                 :          0 : exit:
     421                 :            :         return rc;
     422                 :            : }
     423                 :            : 
     424                 :            : int
     425         [ #  # ]:          0 : roc_nix_tm_hierarchy_disable(struct roc_nix *roc_nix)
     426                 :            : {
     427                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
     428                 :            :         uint16_t sqb_cnt, head_off, tail_off;
     429                 :          0 :         uint16_t sq_cnt = nix->nb_tx_queues;
     430                 :          0 :         struct mbox *mbox = (&nix->dev)->mbox;
     431                 :            :         struct nix_tm_node_list *list;
     432                 :            :         enum roc_nix_tm_tree tree;
     433                 :            :         struct nix_tm_node *node;
     434                 :            :         struct roc_nix_sq *sq;
     435                 :            :         uint64_t wdata, val;
     436                 :            :         uintptr_t regaddr;
     437                 :            :         int rc = -1, i;
     438                 :            : 
     439         [ #  # ]:          0 :         if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
     440                 :            :                 return 0;
     441                 :            : 
     442                 :          0 :         plt_tm_dbg("Disabling hierarchy on %s", nix->pci_dev->name);
     443                 :            : 
     444                 :          0 :         tree = nix->tm_tree;
     445                 :            :         list = nix_tm_node_list(nix, tree);
     446                 :            : 
     447                 :            :         /* Enable CGX RXTX to drain pkts */
     448         [ #  # ]:          0 :         if (!roc_nix->io_enabled) {
     449                 :            :                 /* Though it enables both RX MCAM Entries and CGX Link
     450                 :            :                  * we assume all the rx queues are stopped way back.
     451                 :            :                  */
     452                 :          0 :                 mbox_alloc_msg_nix_lf_start_rx(mbox_get(mbox));
     453                 :          0 :                 rc = mbox_process(mbox);
     454         [ #  # ]:          0 :                 if (rc) {
     455                 :            :                         mbox_put(mbox);
     456                 :          0 :                         plt_err("cgx start failed, rc=%d", rc);
     457                 :          0 :                         return rc;
     458                 :            :                 }
     459                 :            :                 mbox_put(mbox);
     460                 :            :         }
     461                 :            : 
     462                 :            :         /* XON all SMQ's */
     463         [ #  # ]:          0 :         TAILQ_FOREACH(node, list, node) {
     464         [ #  # ]:          0 :                 if (node->hw_lvl != NIX_TXSCH_LVL_SMQ)
     465                 :          0 :                         continue;
     466         [ #  # ]:          0 :                 if (!(node->flags & NIX_TM_NODE_HWRES))
     467                 :          0 :                         continue;
     468                 :            : 
     469                 :          0 :                 rc = nix_tm_smq_xoff(nix, node, false);
     470         [ #  # ]:          0 :                 if (rc) {
     471                 :          0 :                         plt_err("Failed to enable smq %u, rc=%d", node->hw_id,
     472                 :            :                                 rc);
     473                 :          0 :                         goto cleanup;
     474                 :            :                 }
     475                 :            :         }
     476                 :            : 
     477                 :            :         /* Disable backpressure, it will be enabled back if needed on
     478                 :            :          * hierarchy enable
     479                 :            :          */
     480         [ #  # ]:          0 :         for (i = 0; i < sq_cnt; i++) {
     481                 :          0 :                 sq = nix->sqs[i];
     482         [ #  # ]:          0 :                 if (!sq)
     483                 :          0 :                         continue;
     484                 :            : 
     485                 :          0 :                 rc = nix_tm_bp_config_set(roc_nix, sq->qid, 0, false);
     486         [ #  # ]:          0 :                 if (rc && rc != -ENOENT) {
     487                 :          0 :                         plt_err("Failed to disable backpressure, rc=%d", rc);
     488                 :          0 :                         goto cleanup;
     489                 :            :                 }
     490                 :            :         }
     491                 :            : 
     492                 :            :         /* Flush all tx queues */
     493         [ #  # ]:          0 :         for (i = 0; i < sq_cnt; i++) {
     494                 :          0 :                 sq = nix->sqs[i];
     495         [ #  # ]:          0 :                 if (!sq)
     496                 :          0 :                         continue;
     497                 :            : 
     498                 :          0 :                 rc = roc_nix_sq_ena_dis(sq, false);
     499         [ #  # ]:          0 :                 if (rc) {
     500                 :          0 :                         plt_err("Failed to disable sqb aura fc, rc=%d", rc);
     501                 :          0 :                         goto cleanup;
     502                 :            :                 }
     503                 :            : 
     504                 :            :                 /* Wait for sq entries to be flushed */
     505                 :          0 :                 rc = roc_nix_tm_sq_flush_spin(sq);
     506         [ #  # ]:          0 :                 if (rc) {
     507                 :          0 :                         plt_err("Failed to drain sq, rc=%d\n", rc);
     508                 :          0 :                         goto cleanup;
     509                 :            :                 }
     510                 :            :         }
     511                 :            : 
     512                 :            :         /* XOFF & Flush all SMQ's. HRM mandates
     513                 :            :          * all SQ's empty before SMQ flush is issued.
     514                 :            :          */
     515         [ #  # ]:          0 :         TAILQ_FOREACH(node, list, node) {
     516         [ #  # ]:          0 :                 if (node->hw_lvl != NIX_TXSCH_LVL_SMQ)
     517                 :          0 :                         continue;
     518         [ #  # ]:          0 :                 if (!(node->flags & NIX_TM_NODE_HWRES))
     519                 :          0 :                         continue;
     520                 :            : 
     521                 :          0 :                 rc = nix_tm_smq_xoff(nix, node, true);
     522         [ #  # ]:          0 :                 if (rc) {
     523                 :          0 :                         plt_err("Failed to enable smq %u, rc=%d", node->hw_id,
     524                 :            :                                 rc);
     525                 :          0 :                         goto cleanup;
     526                 :            :                 }
     527                 :            : 
     528                 :          0 :                 node->flags &= ~NIX_TM_NODE_ENABLED;
     529                 :            :         }
     530                 :            : 
     531                 :            :         /* Verify sanity of all tx queues */
     532         [ #  # ]:          0 :         for (i = 0; i < sq_cnt; i++) {
     533                 :          0 :                 sq = nix->sqs[i];
     534         [ #  # ]:          0 :                 if (!sq)
     535                 :          0 :                         continue;
     536                 :            : 
     537                 :          0 :                 wdata = ((uint64_t)sq->qid << 32);
     538                 :            :                 regaddr = nix->base + NIX_LF_SQ_OP_STATUS;
     539                 :            :                 val = roc_atomic64_add_nosync(wdata, (int64_t *)regaddr);
     540                 :            : 
     541                 :            :                 sqb_cnt = val & 0xFFFF;
     542                 :            :                 head_off = (val >> 20) & 0x3F;
     543                 :            :                 tail_off = (val >> 28) & 0x3F;
     544                 :            : 
     545                 :          0 :                 if (sqb_cnt > 1 || head_off != tail_off ||
     546         [ #  # ]:          0 :                     (*(uint64_t *)sq->fc != sq->aura_sqb_bufs))
     547                 :          0 :                         plt_err("Failed to gracefully flush sq %u", sq->qid);
     548                 :            :         }
     549                 :            : 
     550                 :          0 :         nix->tm_flags &= ~NIX_TM_HIERARCHY_ENA;
     551                 :          0 : cleanup:
     552                 :            :         /* Restore cgx state */
     553         [ #  # ]:          0 :         if (!roc_nix->io_enabled) {
     554                 :          0 :                 mbox_alloc_msg_nix_lf_stop_rx(mbox_get(mbox));
     555                 :          0 :                 rc |= mbox_process(mbox);
     556                 :            :                 mbox_put(mbox);
     557                 :            :         }
     558                 :            :         return rc;
     559                 :            : }
     560                 :            : 
     561                 :            : int
     562         [ #  # ]:          0 : roc_nix_tm_hierarchy_xmit_enable(struct roc_nix *roc_nix, enum roc_nix_tm_tree tree)
     563                 :            : {
     564                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
     565                 :            :         struct nix_tm_node_list *list;
     566                 :            :         struct nix_tm_node *node;
     567                 :            :         struct roc_nix_sq *sq;
     568                 :            :         uint16_t sq_id;
     569                 :            :         int rc;
     570                 :            : 
     571         [ #  # ]:          0 :         if (tree >= ROC_NIX_TM_TREE_MAX)
     572                 :            :                 return NIX_ERR_PARAM;
     573                 :            : 
     574                 :            :         list = nix_tm_node_list(nix, tree);
     575                 :            : 
     576                 :            :         /* Update SQ Sched Data while SQ is idle */
     577         [ #  # ]:          0 :         TAILQ_FOREACH(node, list, node) {
     578   [ #  #  #  # ]:          0 :                 if (!nix_tm_is_leaf(nix, node->lvl))
     579                 :          0 :                         continue;
     580                 :            : 
     581                 :          0 :                 rc = nix_tm_sq_sched_conf(nix, node, false);
     582         [ #  # ]:          0 :                 if (rc) {
     583                 :          0 :                         plt_err("SQ %u sched update failed, rc=%d", node->id,
     584                 :            :                                 rc);
     585                 :          0 :                         return rc;
     586                 :            :                 }
     587                 :            :         }
     588                 :            : 
     589                 :            :         /* Finally XON all SMQ's */
     590         [ #  # ]:          0 :         TAILQ_FOREACH(node, list, node) {
     591         [ #  # ]:          0 :                 if (node->hw_lvl != NIX_TXSCH_LVL_SMQ)
     592                 :          0 :                         continue;
     593                 :            : 
     594                 :          0 :                 rc = nix_tm_smq_xoff(nix, node, false);
     595         [ #  # ]:          0 :                 if (rc) {
     596                 :          0 :                         plt_err("Failed to enable smq %u, rc=%d", node->hw_id,
     597                 :            :                                 rc);
     598                 :          0 :                         return rc;
     599                 :            :                 }
     600                 :            :         }
     601                 :            : 
     602                 :            :         /* Enable xmit as all the topology is ready */
     603         [ #  # ]:          0 :         TAILQ_FOREACH(node, list, node) {
     604   [ #  #  #  # ]:          0 :                 if (!nix_tm_is_leaf(nix, node->lvl))
     605                 :          0 :                         continue;
     606                 :            : 
     607                 :          0 :                 sq_id = node->id;
     608                 :          0 :                 sq = nix->sqs[sq_id];
     609                 :            : 
     610                 :          0 :                 rc = roc_nix_sq_ena_dis(sq, true);
     611         [ #  # ]:          0 :                 if (rc) {
     612                 :          0 :                         plt_err("TM sw xon failed on SQ %u, rc=%d", node->id,
     613                 :            :                                 rc);
     614                 :          0 :                         return rc;
     615                 :            :                 }
     616                 :          0 :                 node->flags |= NIX_TM_NODE_ENABLED;
     617                 :            :         }
     618                 :            : 
     619                 :            :         return 0;
     620                 :            : }
     621                 :            : 
     622                 :            : int
     623         [ #  # ]:          0 : roc_nix_tm_hierarchy_enable(struct roc_nix *roc_nix, enum roc_nix_tm_tree tree,
     624                 :            :                             bool xmit_enable)
     625                 :            : {
     626                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
     627                 :            :         struct nix_tm_node_list *list;
     628                 :            :         struct nix_tm_node *node;
     629                 :            :         uint32_t tree_mask;
     630                 :            :         int rc;
     631                 :            : 
     632         [ #  # ]:          0 :         if (tree >= ROC_NIX_TM_TREE_MAX)
     633                 :            :                 return NIX_ERR_PARAM;
     634                 :            : 
     635         [ #  # ]:          0 :         if (nix->tm_flags & NIX_TM_HIERARCHY_ENA) {
     636         [ #  # ]:          0 :                 if (nix->tm_tree != tree)
     637                 :            :                         return -EBUSY;
     638                 :          0 :                 return 0;
     639                 :            :         }
     640                 :            : 
     641                 :          0 :         plt_tm_dbg("Enabling hierarchy on %s, xmit_ena %u, tree %u",
     642                 :            :                    nix->pci_dev->name, xmit_enable, tree);
     643                 :            : 
     644                 :            :         /* Free hw resources of other trees */
     645                 :            :         tree_mask = NIX_TM_TREE_MASK_ALL;
     646                 :          0 :         tree_mask &= ~BIT(tree);
     647                 :            : 
     648                 :          0 :         rc = nix_tm_free_resources(roc_nix, tree_mask, true);
     649         [ #  # ]:          0 :         if (rc) {
     650                 :          0 :                 plt_err("failed to free resources of other trees, rc=%d", rc);
     651                 :          0 :                 return rc;
     652                 :            :         }
     653                 :            : 
     654                 :            :         /* Update active tree before starting to do anything */
     655                 :          0 :         nix->tm_tree = tree;
     656                 :            : 
     657                 :          0 :         nix_tm_update_parent_info(nix, tree);
     658                 :            : 
     659                 :          0 :         rc = nix_tm_alloc_txschq(nix, tree);
     660         [ #  # ]:          0 :         if (rc) {
     661                 :          0 :                 plt_err("TM failed to alloc tm resources=%d", rc);
     662                 :          0 :                 return rc;
     663                 :            :         }
     664                 :            : 
     665                 :          0 :         rc = nix_tm_assign_resources(nix, tree);
     666         [ #  # ]:          0 :         if (rc) {
     667                 :          0 :                 plt_err("TM failed to assign tm resources=%d", rc);
     668                 :          0 :                 return rc;
     669                 :            :         }
     670                 :            : 
     671                 :          0 :         rc = nix_tm_txsch_reg_config(nix, tree);
     672         [ #  # ]:          0 :         if (rc) {
     673                 :          0 :                 plt_err("TM failed to configure sched registers=%d", rc);
     674                 :          0 :                 return rc;
     675                 :            :         }
     676                 :            : 
     677                 :            :         list = nix_tm_node_list(nix, tree);
     678                 :            :         /* Mark all non-leaf's as enabled */
     679         [ #  # ]:          0 :         TAILQ_FOREACH(node, list, node) {
     680   [ #  #  #  # ]:          0 :                 if (!nix_tm_is_leaf(nix, node->lvl))
     681                 :          0 :                         node->flags |= NIX_TM_NODE_ENABLED;
     682                 :            :         }
     683                 :            : 
     684         [ #  # ]:          0 :         if (xmit_enable)
     685                 :          0 :                 rc = roc_nix_tm_hierarchy_xmit_enable(roc_nix, tree);
     686                 :            : 
     687         [ #  # ]:          0 :         if (!rc)
     688                 :          0 :                 nix->tm_flags |= NIX_TM_HIERARCHY_ENA;
     689                 :            :         return rc;
     690                 :            : }
     691                 :            : 
     692                 :            : int
     693                 :          0 : roc_nix_tm_node_suspend_resume(struct roc_nix *roc_nix, uint32_t node_id,
     694                 :            :                                bool suspend)
     695                 :            : {
     696                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
     697                 :          0 :         struct mbox *mbox = (&nix->dev)->mbox;
     698                 :            :         struct nix_txschq_config *req;
     699                 :            :         struct nix_tm_node *node;
     700                 :            :         uint16_t flags;
     701                 :            :         int rc;
     702                 :            : 
     703                 :          0 :         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
     704         [ #  # ]:          0 :         if (!node)
     705                 :            :                 return NIX_ERR_TM_INVALID_NODE;
     706                 :            : 
     707                 :          0 :         flags = node->flags;
     708         [ #  # ]:          0 :         flags = suspend ? (flags & ~NIX_TM_NODE_ENABLED) :
     709                 :            :                                 (flags | NIX_TM_NODE_ENABLED);
     710                 :            : 
     711         [ #  # ]:          0 :         if (node->flags == flags)
     712                 :            :                 return 0;
     713                 :            : 
     714                 :            :         /* send mbox for state change */
     715                 :          0 :         req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
     716                 :            : 
     717                 :          0 :         req->lvl = node->hw_lvl;
     718                 :          0 :         req->num_regs =
     719                 :          0 :                 nix_tm_sw_xoff_prep(node, suspend, req->reg, req->regval);
     720                 :          0 :         rc = mbox_process(mbox);
     721                 :            :         mbox_put(mbox);
     722         [ #  # ]:          0 :         if (!rc)
     723                 :          0 :                 node->flags = flags;
     724                 :            :         return rc;
     725                 :            : }
     726                 :            : 
     727                 :            : int
     728                 :          0 : roc_nix_tm_prealloc_res(struct roc_nix *roc_nix, uint8_t lvl,
     729                 :            :                         uint16_t discontig, uint16_t contig)
     730                 :            : {
     731                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
     732                 :          0 :         struct mbox *mbox = (&nix->dev)->mbox;
     733                 :            :         struct nix_txsch_alloc_req *req;
     734                 :            :         struct nix_txsch_alloc_rsp *rsp;
     735                 :            :         uint8_t hw_lvl;
     736                 :            :         int rc = -ENOSPC;
     737                 :            : 
     738                 :          0 :         hw_lvl = nix_tm_lvl2nix(nix, lvl);
     739         [ #  # ]:          0 :         if (hw_lvl == NIX_TXSCH_LVL_CNT)
     740                 :            :                 return -EINVAL;
     741                 :            : 
     742                 :            :         /* Preallocate contiguous */
     743         [ #  # ]:          0 :         if (nix->contig_rsvd[hw_lvl] < contig) {
     744                 :          0 :                 req = mbox_alloc_msg_nix_txsch_alloc(mbox_get(mbox));
     745         [ #  # ]:          0 :                 if (req == NULL) {
     746                 :            :                         mbox_put(mbox);
     747                 :          0 :                         return rc;
     748                 :            :                 }
     749                 :          0 :                 req->schq_contig[hw_lvl] = contig - nix->contig_rsvd[hw_lvl];
     750                 :            : 
     751                 :            :                 rc = mbox_process_msg(mbox, (void *)&rsp);
     752         [ #  # ]:          0 :                 if (rc) {
     753                 :            :                         mbox_put(mbox);
     754                 :          0 :                         return rc;
     755                 :            :                 }
     756                 :            : 
     757                 :          0 :                 nix_tm_copy_rsp_to_nix(nix, rsp);
     758                 :            :                 mbox_put(mbox);
     759                 :            :         }
     760                 :            : 
     761                 :            :         /* Preallocate contiguous */
     762         [ #  # ]:          0 :         if (nix->discontig_rsvd[hw_lvl] < discontig) {
     763                 :          0 :                 req = mbox_alloc_msg_nix_txsch_alloc(mbox_get(mbox));
     764         [ #  # ]:          0 :                 if (req == NULL) {
     765                 :            :                         mbox_put(mbox);
     766                 :          0 :                         return -ENOSPC;
     767                 :            :                 }
     768                 :          0 :                 req->schq[hw_lvl] = discontig - nix->discontig_rsvd[hw_lvl];
     769                 :            : 
     770                 :            :                 rc = mbox_process_msg(mbox, (void *)&rsp);
     771         [ #  # ]:          0 :                 if (rc) {
     772                 :            :                         mbox_put(mbox);
     773                 :          0 :                         return rc;
     774                 :            :                 }
     775                 :            : 
     776                 :          0 :                 nix_tm_copy_rsp_to_nix(nix, rsp);
     777                 :            :                 mbox_put(mbox);
     778                 :            :         }
     779                 :            : 
     780                 :            :         /* Save thresholds */
     781                 :          0 :         nix->contig_rsvd[hw_lvl] = contig;
     782                 :          0 :         nix->discontig_rsvd[hw_lvl] = discontig;
     783                 :            :         /* Release anything present above thresholds */
     784                 :          0 :         nix_tm_release_resources(nix, hw_lvl, true, true);
     785                 :          0 :         nix_tm_release_resources(nix, hw_lvl, false, true);
     786                 :          0 :         return 0;
     787                 :            : }
     788                 :            : 
     789                 :            : int
     790                 :          0 : roc_nix_tm_node_shaper_update(struct roc_nix *roc_nix, uint32_t node_id,
     791                 :            :                               uint32_t profile_id, bool force_update)
     792                 :            : {
     793                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
     794                 :            :         struct nix_tm_shaper_profile *profile = NULL;
     795                 :          0 :         struct mbox *mbox = (&nix->dev)->mbox;
     796                 :            :         struct nix_txschq_config *req;
     797                 :            :         struct nix_tm_node *node;
     798                 :            :         uint8_t k;
     799                 :            :         int rc;
     800                 :            : 
     801                 :            :         /* Shaper updates valid only for user nodes */
     802                 :          0 :         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
     803   [ #  #  #  #  :          0 :         if (!node || nix_tm_is_leaf(nix, node->lvl))
                   #  # ]
     804                 :            :                 return NIX_ERR_TM_INVALID_NODE;
     805                 :            : 
     806         [ #  # ]:          0 :         if (profile_id != ROC_NIX_TM_SHAPER_PROFILE_NONE) {
     807                 :          0 :                 profile = nix_tm_shaper_profile_search(nix, profile_id);
     808         [ #  # ]:          0 :                 if (!profile)
     809                 :            :                         return NIX_ERR_TM_INVALID_SHAPER_PROFILE;
     810                 :            :         }
     811                 :            : 
     812                 :            :         /* Pkt mode should match existing node's pkt mode */
     813         [ #  # ]:          0 :         if (profile && profile->pkt_mode != node->pkt_mode)
     814                 :            :                 return NIX_ERR_TM_PKT_MODE_MISMATCH;
     815                 :            : 
     816   [ #  #  #  # ]:          0 :         if ((profile_id == node->shaper_profile_id) && !force_update) {
     817                 :            :                 return 0;
     818         [ #  # ]:          0 :         } else if (profile_id != node->shaper_profile_id) {
     819                 :            :                 struct nix_tm_shaper_profile *old;
     820                 :            : 
     821                 :            :                 /* Find old shaper profile and reduce ref count */
     822                 :          0 :                 old = nix_tm_shaper_profile_search(nix,
     823                 :            :                                                    node->shaper_profile_id);
     824         [ #  # ]:          0 :                 if (old)
     825                 :          0 :                         old->ref_cnt--;
     826                 :            : 
     827         [ #  # ]:          0 :                 if (profile)
     828                 :          0 :                         profile->ref_cnt++;
     829                 :            : 
     830                 :            :                 /* Reduce older shaper ref count and increase new one */
     831                 :          0 :                 node->shaper_profile_id = profile_id;
     832                 :            :         }
     833                 :            : 
     834                 :            :         /* Nothing to do if hierarchy not yet enabled */
     835         [ #  # ]:          0 :         if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
     836                 :            :                 return 0;
     837                 :            : 
     838                 :          0 :         node->flags &= ~NIX_TM_NODE_ENABLED;
     839                 :            : 
     840                 :            :         /* Flush the specific node with SW_XOFF */
     841                 :          0 :         req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
     842                 :          0 :         req->lvl = node->hw_lvl;
     843                 :          0 :         k = nix_tm_sw_xoff_prep(node, true, req->reg, req->regval);
     844                 :          0 :         req->num_regs = k;
     845                 :            : 
     846                 :          0 :         rc = mbox_process(mbox);
     847         [ #  # ]:          0 :         if (rc) {
     848                 :            :                 mbox_put(mbox);
     849                 :          0 :                 return rc;
     850                 :            :         }
     851                 :            :         mbox_put(mbox);
     852                 :            : 
     853                 :            :         /* Update the PIR/CIR and clear SW XOFF */
     854                 :          0 :         req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
     855                 :          0 :         req->lvl = node->hw_lvl;
     856                 :            : 
     857                 :          0 :         k = nix_tm_shaper_reg_prep(node, profile, req->reg, req->regval);
     858                 :            : 
     859                 :          0 :         k += nix_tm_sw_xoff_prep(node, false, &req->reg[k], &req->regval[k]);
     860                 :            : 
     861                 :          0 :         req->num_regs = k;
     862                 :          0 :         rc = mbox_process(mbox);
     863                 :            :         mbox_put(mbox);
     864         [ #  # ]:          0 :         if (!rc)
     865                 :          0 :                 node->flags |= NIX_TM_NODE_ENABLED;
     866                 :            :         return rc;
     867                 :            : }
     868                 :            : 
     869                 :            : int
     870                 :          0 : roc_nix_tm_node_parent_update(struct roc_nix *roc_nix, uint32_t node_id,
     871                 :            :                               uint32_t new_parent_id, uint32_t priority,
     872                 :            :                               uint32_t weight)
     873                 :            : {
     874                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
     875                 :          0 :         struct mbox *mbox = (&nix->dev)->mbox;
     876                 :            :         struct nix_tm_node *node, *sibling;
     877                 :            :         struct nix_tm_node *new_parent;
     878                 :            :         struct nix_txschq_config *req;
     879                 :            :         struct nix_tm_node_list *list;
     880                 :            :         uint8_t k;
     881                 :            :         int rc;
     882                 :            : 
     883                 :          0 :         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
     884         [ #  # ]:          0 :         if (!node)
     885                 :            :                 return NIX_ERR_TM_INVALID_NODE;
     886                 :            : 
     887                 :            :         /* Parent id valid only for non root nodes */
     888         [ #  # ]:          0 :         if (node->hw_lvl != nix->tm_root_lvl) {
     889                 :            :                 new_parent =
     890                 :          0 :                         nix_tm_node_search(nix, new_parent_id, ROC_NIX_TM_USER);
     891         [ #  # ]:          0 :                 if (!new_parent)
     892                 :            :                         return NIX_ERR_TM_INVALID_PARENT;
     893                 :            : 
     894                 :            :                 /* Current support is only for dynamic weight update */
     895   [ #  #  #  # ]:          0 :                 if (node->parent != new_parent || node->priority != priority)
     896                 :            :                         return NIX_ERR_TM_PARENT_PRIO_UPDATE;
     897                 :            :         }
     898                 :            : 
     899                 :            :         list = nix_tm_node_list(nix, ROC_NIX_TM_USER);
     900                 :            :         /* Skip if no change */
     901         [ #  # ]:          0 :         if (node->weight == weight)
     902                 :            :                 return 0;
     903                 :            : 
     904                 :          0 :         node->weight = weight;
     905                 :            : 
     906                 :            :         /* Nothing to do if hierarchy not yet enabled */
     907         [ #  # ]:          0 :         if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
     908                 :            :                 return 0;
     909                 :            : 
     910                 :            :         /* For leaf nodes, SQ CTX needs update */
     911   [ #  #  #  # ]:          0 :         if (nix_tm_is_leaf(nix, node->lvl)) {
     912                 :            :                 /* Update SQ quantum data on the fly */
     913                 :          0 :                 rc = nix_tm_sq_sched_conf(nix, node, true);
     914         [ #  # ]:          0 :                 if (rc)
     915                 :          0 :                         return NIX_ERR_TM_SQ_UPDATE_FAIL;
     916                 :            :         } else {
     917                 :            :                 /* XOFF Parent node */
     918                 :          0 :                 req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
     919                 :          0 :                 req->lvl = node->parent->hw_lvl;
     920                 :          0 :                 req->num_regs = nix_tm_sw_xoff_prep(node->parent, true,
     921                 :          0 :                                                     req->reg, req->regval);
     922                 :          0 :                 rc = mbox_process(mbox);
     923                 :            :                 mbox_put(mbox);
     924         [ #  # ]:          0 :                 if (rc)
     925                 :            :                         return rc;
     926                 :            : 
     927                 :            :                 /* XOFF this node and all other siblings */
     928                 :          0 :                 req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
     929                 :          0 :                 req->lvl = node->hw_lvl;
     930                 :            : 
     931                 :            :                 k = 0;
     932         [ #  # ]:          0 :                 TAILQ_FOREACH(sibling, list, node) {
     933         [ #  # ]:          0 :                         if (sibling->parent != node->parent)
     934                 :          0 :                                 continue;
     935                 :          0 :                         k += nix_tm_sw_xoff_prep(sibling, true, &req->reg[k], &req->regval[k]);
     936         [ #  # ]:          0 :                         if (k >= MAX_REGS_PER_MBOX_MSG) {
     937                 :          0 :                                 req->num_regs = k;
     938                 :          0 :                                 rc = mbox_process(mbox);
     939                 :            :                                 mbox_put(mbox);
     940         [ #  # ]:          0 :                                 if (rc)
     941                 :          0 :                                         return rc;
     942                 :            :                                 k = 0;
     943                 :          0 :                                 req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
     944                 :          0 :                                 req->lvl = node->hw_lvl;
     945                 :            :                         }
     946                 :            :                 }
     947                 :            : 
     948         [ #  # ]:          0 :                 if (k) {
     949                 :          0 :                         req->num_regs = k;
     950                 :          0 :                         rc = mbox_process(mbox);
     951                 :            :                         mbox_put(mbox);
     952         [ #  # ]:          0 :                         if (rc)
     953                 :            :                                 return rc;
     954                 :            :                         /* Update new weight for current node */
     955                 :          0 :                         req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
     956                 :            :                 }
     957                 :            : 
     958                 :          0 :                 req->lvl = node->hw_lvl;
     959                 :          0 :                 req->num_regs = nix_tm_sched_reg_prep(nix, node, req->reg, req->regval);
     960                 :          0 :                 rc = mbox_process(mbox);
     961                 :            :                 mbox_put(mbox);
     962         [ #  # ]:          0 :                 if (rc)
     963                 :            :                         return rc;
     964                 :            : 
     965                 :            :                 /* XON this node and all other siblings */
     966                 :          0 :                 req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
     967                 :          0 :                 req->lvl = node->hw_lvl;
     968                 :            : 
     969                 :            :                 k = 0;
     970         [ #  # ]:          0 :                 TAILQ_FOREACH(sibling, list, node) {
     971         [ #  # ]:          0 :                         if (sibling->parent != node->parent)
     972                 :          0 :                                 continue;
     973                 :          0 :                         k += nix_tm_sw_xoff_prep(sibling, false, &req->reg[k], &req->regval[k]);
     974         [ #  # ]:          0 :                         if (k >= MAX_REGS_PER_MBOX_MSG) {
     975                 :          0 :                                 req->num_regs = k;
     976                 :          0 :                                 rc = mbox_process(mbox);
     977                 :            :                                 mbox_put(mbox);
     978         [ #  # ]:          0 :                                 if (rc)
     979                 :          0 :                                         return rc;
     980                 :            :                                 k = 0;
     981                 :          0 :                                 req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
     982                 :          0 :                                 req->lvl = node->hw_lvl;
     983                 :            :                         }
     984                 :            :                 }
     985                 :            : 
     986         [ #  # ]:          0 :                 if (k) {
     987                 :          0 :                         req->num_regs = k;
     988                 :          0 :                         rc = mbox_process(mbox);
     989                 :            :                         mbox_put(mbox);
     990         [ #  # ]:          0 :                         if (rc)
     991                 :            :                                 return rc;
     992                 :            :                         /* XON Parent node */
     993                 :          0 :                         req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
     994                 :            :                 }
     995                 :            : 
     996                 :          0 :                 req->lvl = node->parent->hw_lvl;
     997                 :          0 :                 req->num_regs = nix_tm_sw_xoff_prep(node->parent, false, req->reg, req->regval);
     998                 :          0 :                 rc = mbox_process(mbox);
     999                 :            :                 mbox_put(mbox);
    1000         [ #  # ]:          0 :                 if (rc)
    1001                 :          0 :                         return rc;
    1002                 :            :         }
    1003                 :            :         return 0;
    1004                 :            : }
    1005                 :            : 
    1006                 :            : int
    1007                 :          0 : roc_nix_tm_init(struct roc_nix *roc_nix)
    1008                 :            : {
    1009                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
    1010                 :            :         uint32_t tree_mask;
    1011                 :            :         int rc;
    1012                 :            : 
    1013         [ #  # ]:          0 :         if (nix->tm_flags & NIX_TM_HIERARCHY_ENA) {
    1014                 :          0 :                 plt_err("Cannot init while existing hierarchy is enabled");
    1015                 :          0 :                 return -EBUSY;
    1016                 :            :         }
    1017                 :            : 
    1018                 :            :         /* Free up all user resources already held */
    1019                 :            :         tree_mask = NIX_TM_TREE_MASK_ALL;
    1020                 :          0 :         rc = nix_tm_free_resources(roc_nix, tree_mask, false);
    1021         [ #  # ]:          0 :         if (rc) {
    1022                 :          0 :                 plt_err("Failed to freeup all nodes and resources, rc=%d", rc);
    1023                 :          0 :                 return rc;
    1024                 :            :         }
    1025                 :            : 
    1026                 :            :         /* Prepare default tree */
    1027                 :          0 :         rc = nix_tm_prepare_default_tree(roc_nix);
    1028         [ #  # ]:          0 :         if (rc) {
    1029                 :          0 :                 plt_err("failed to prepare default tm tree, rc=%d", rc);
    1030                 :          0 :                 return rc;
    1031                 :            :         }
    1032                 :            : 
    1033                 :            :         return rc;
    1034                 :            : }
    1035                 :            : 
    1036                 :            : int
    1037         [ #  # ]:          0 : roc_nix_tm_pfc_rlimit_sq(struct roc_nix *roc_nix, uint16_t qid, uint64_t rate)
    1038                 :            : {
    1039                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
    1040                 :            :         struct nix_tm_shaper_profile profile;
    1041                 :          0 :         struct mbox *mbox = (&nix->dev)->mbox;
    1042                 :            :         struct nix_tm_node *node, *parent;
    1043                 :            :         struct roc_nix_link_info link_info;
    1044                 :            : 
    1045                 :            :         volatile uint64_t *reg, *regval;
    1046                 :            :         struct nix_txschq_config *req;
    1047                 :            :         uint64_t tl2_rate = 0;
    1048                 :            :         uint16_t flags;
    1049                 :            :         uint8_t k = 0;
    1050                 :            :         int rc;
    1051                 :            : 
    1052   [ #  #  #  # ]:          0 :         if ((nix->tm_tree != ROC_NIX_TM_PFC) || !(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
    1053                 :            :                 return NIX_ERR_TM_INVALID_TREE;
    1054                 :            : 
    1055                 :          0 :         node = nix_tm_node_search(nix, qid, nix->tm_tree);
    1056                 :            : 
    1057                 :            :         /* check if we found a valid leaf node */
    1058   [ #  #  #  #  :          0 :         if (!node || !nix_tm_is_leaf(nix, node->lvl) || !node->parent ||
             #  #  #  # ]
    1059         [ #  # ]:          0 :             node->parent->hw_id == NIX_TM_HW_ID_INVALID) {
    1060                 :            :                 return NIX_ERR_TM_INVALID_NODE;
    1061                 :            :         }
    1062                 :            : 
    1063                 :            :         /* Get the link Speed */
    1064         [ #  # ]:          0 :         if (roc_nix_mac_link_info_get(roc_nix, &link_info))
    1065                 :            :                 return -EINVAL;
    1066                 :            : 
    1067         [ #  # ]:          0 :         if (link_info.status)
    1068                 :          0 :                 tl2_rate = link_info.speed * (uint64_t)1E6;
    1069                 :            : 
    1070                 :            :         /* Configure TL3 of leaf node with requested rate */
    1071                 :          0 :         parent = node->parent;        /* SMQ/MDQ */
    1072                 :          0 :         parent = parent->parent; /* TL4 */
    1073                 :          0 :         parent = parent->parent; /* TL3 */
    1074                 :          0 :         flags = parent->flags;
    1075                 :            : 
    1076                 :          0 :         req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
    1077                 :          0 :         req->lvl = parent->hw_lvl;
    1078                 :          0 :         reg = req->reg;
    1079                 :          0 :         regval = req->regval;
    1080                 :            : 
    1081         [ #  # ]:          0 :         if (rate == 0) {
    1082                 :          0 :                 k += nix_tm_sw_xoff_prep(parent, true, &reg[k], &regval[k]);
    1083                 :          0 :                 flags &= ~NIX_TM_NODE_ENABLED;
    1084                 :          0 :                 goto exit;
    1085                 :            :         }
    1086                 :            : 
    1087         [ #  # ]:          0 :         if (!(flags & NIX_TM_NODE_ENABLED)) {
    1088                 :          0 :                 k += nix_tm_sw_xoff_prep(parent, false, &reg[k], &regval[k]);
    1089                 :          0 :                 flags |= NIX_TM_NODE_ENABLED;
    1090                 :            :         }
    1091                 :            : 
    1092                 :            :         /* Use only PIR for rate limit */
    1093                 :            :         memset(&profile, 0, sizeof(profile));
    1094                 :          0 :         profile.peak.rate = rate;
    1095                 :            :         /* Minimum burst of ~4us Bytes of Tx */
    1096                 :          0 :         profile.peak.size =
    1097                 :          0 :                 PLT_MAX((uint64_t)roc_nix_max_pkt_len(roc_nix), (4ul * rate) / ((uint64_t)1E6 * 8));
    1098   [ #  #  #  # ]:          0 :         if (!nix->tm_rate_min || nix->tm_rate_min > rate)
    1099                 :          0 :                 nix->tm_rate_min = rate;
    1100                 :            : 
    1101                 :          0 :         k += nix_tm_shaper_reg_prep(parent, &profile, &reg[k], &regval[k]);
    1102                 :          0 : exit:
    1103                 :          0 :         req->num_regs = k;
    1104                 :          0 :         rc = mbox_process(mbox);
    1105                 :            :         mbox_put(mbox);
    1106         [ #  # ]:          0 :         if (rc)
    1107                 :            :                 return rc;
    1108                 :            : 
    1109                 :          0 :         parent->flags = flags;
    1110                 :            : 
    1111                 :            :         /* If link is up then configure TL2 with link speed */
    1112   [ #  #  #  # ]:          0 :         if (tl2_rate && (flags & NIX_TM_NODE_ENABLED)) {
    1113                 :            :                 k = 0;
    1114                 :          0 :                 parent = parent->parent;
    1115                 :          0 :                 req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
    1116                 :          0 :                 req->lvl = parent->hw_lvl;
    1117                 :          0 :                 reg = req->reg;
    1118                 :          0 :                 regval = req->regval;
    1119                 :            : 
    1120                 :            :                 /* Use only PIR for rate limit */
    1121                 :            :                 memset(&profile, 0, sizeof(profile));
    1122                 :          0 :                 profile.peak.rate = tl2_rate;
    1123                 :            :                 /* Minimum burst of ~4us Bytes of Tx */
    1124                 :          0 :                 profile.peak.size = PLT_MAX((uint64_t)roc_nix_max_pkt_len(roc_nix),
    1125                 :            :                                             (4ul * tl2_rate) / ((uint64_t)1E6 * 8));
    1126                 :          0 :                 k += nix_tm_shaper_reg_prep(parent, &profile, &reg[k], &regval[k]);
    1127                 :          0 :                 req->num_regs = k;
    1128                 :          0 :                 rc = mbox_process(mbox);
    1129                 :            :                 mbox_put(mbox);
    1130                 :            :         }
    1131                 :            :         return rc;
    1132                 :            : }
    1133                 :            : 
    1134                 :            : int
    1135         [ #  # ]:          0 : roc_nix_tm_rlimit_sq(struct roc_nix *roc_nix, uint16_t qid, uint64_t rate)
    1136                 :            : {
    1137                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
    1138                 :            :         struct nix_tm_shaper_profile profile;
    1139                 :          0 :         struct mbox *mbox = (&nix->dev)->mbox;
    1140                 :            :         struct nix_tm_node *node, *parent;
    1141                 :            : 
    1142                 :            :         volatile uint64_t *reg, *regval;
    1143                 :            :         struct nix_txschq_config *req;
    1144                 :            :         uint16_t flags;
    1145                 :            :         uint8_t k = 0;
    1146                 :            :         int rc;
    1147                 :            : 
    1148         [ #  # ]:          0 :         if ((nix->tm_tree == ROC_NIX_TM_USER) ||
    1149         [ #  # ]:          0 :             !(nix->tm_flags & NIX_TM_HIERARCHY_ENA)) {
    1150                 :            :                 return NIX_ERR_TM_INVALID_TREE;
    1151                 :            :         }
    1152                 :            : 
    1153                 :          0 :         node = nix_tm_node_search(nix, qid, nix->tm_tree);
    1154                 :            : 
    1155                 :            :         /* check if we found a valid leaf node */
    1156   [ #  #  #  #  :          0 :         if (!node || !nix_tm_is_leaf(nix, node->lvl) || !node->parent ||
             #  #  #  # ]
    1157         [ #  # ]:          0 :             node->parent->hw_id == NIX_TM_HW_ID_INVALID) {
    1158                 :            :                 return NIX_ERR_TM_INVALID_NODE;
    1159                 :            :         }
    1160                 :            : 
    1161                 :            :         parent = node->parent;
    1162                 :          0 :         flags = parent->flags;
    1163                 :            : 
    1164                 :          0 :         req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
    1165                 :          0 :         req->lvl = NIX_TXSCH_LVL_MDQ;
    1166                 :          0 :         reg = req->reg;
    1167                 :          0 :         regval = req->regval;
    1168                 :            : 
    1169         [ #  # ]:          0 :         if (rate == 0) {
    1170                 :          0 :                 k += nix_tm_sw_xoff_prep(parent, true, &reg[k], &regval[k]);
    1171                 :          0 :                 flags &= ~NIX_TM_NODE_ENABLED;
    1172                 :          0 :                 goto exit;
    1173                 :            :         }
    1174                 :            : 
    1175         [ #  # ]:          0 :         if (!(flags & NIX_TM_NODE_ENABLED)) {
    1176                 :          0 :                 k += nix_tm_sw_xoff_prep(parent, false, &reg[k], &regval[k]);
    1177                 :          0 :                 flags |= NIX_TM_NODE_ENABLED;
    1178                 :            :         }
    1179                 :            : 
    1180                 :            :         /* Use only PIR for rate limit */
    1181                 :            :         memset(&profile, 0, sizeof(profile));
    1182                 :          0 :         profile.peak.rate = rate;
    1183                 :            :         /* Minimum burst of ~4us Bytes of Tx */
    1184                 :          0 :         profile.peak.size = PLT_MAX((uint64_t)roc_nix_max_pkt_len(roc_nix),
    1185                 :            :                                     (4ul * rate) / ((uint64_t)1E6 * 8));
    1186   [ #  #  #  # ]:          0 :         if (!nix->tm_rate_min || nix->tm_rate_min > rate)
    1187                 :          0 :                 nix->tm_rate_min = rate;
    1188                 :            : 
    1189                 :          0 :         k += nix_tm_shaper_reg_prep(parent, &profile, &reg[k], &regval[k]);
    1190                 :          0 : exit:
    1191                 :          0 :         req->num_regs = k;
    1192                 :          0 :         rc = mbox_process(mbox);
    1193                 :            :         mbox_put(mbox);
    1194         [ #  # ]:          0 :         if (rc)
    1195                 :            :                 return rc;
    1196                 :            : 
    1197                 :          0 :         parent->flags = flags;
    1198                 :          0 :         return 0;
    1199                 :            : }
    1200                 :            : 
    1201                 :            : void
    1202                 :          0 : roc_nix_tm_fini(struct roc_nix *roc_nix)
    1203                 :            : {
    1204                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
    1205                 :          0 :         struct mbox *mbox = (&nix->dev)->mbox;
    1206                 :            :         struct nix_txsch_free_req *req;
    1207                 :            :         uint32_t tree_mask;
    1208                 :            :         uint8_t hw_lvl;
    1209                 :            :         int rc;
    1210                 :            : 
    1211                 :            :         /* Xmit is assumed to be disabled */
    1212                 :            :         /* Free up resources already held */
    1213                 :            :         tree_mask = NIX_TM_TREE_MASK_ALL;
    1214                 :          0 :         rc = nix_tm_free_resources(roc_nix, tree_mask, false);
    1215         [ #  # ]:          0 :         if (rc)
    1216                 :          0 :                 plt_err("Failed to freeup existing nodes or rsrcs, rc=%d", rc);
    1217                 :            : 
    1218                 :            :         /* Free all other hw resources */
    1219                 :          0 :         req = mbox_alloc_msg_nix_txsch_free(mbox_get(mbox));
    1220         [ #  # ]:          0 :         if (req == NULL) {
    1221                 :            :                 mbox_put(mbox);
    1222                 :          0 :                 return;
    1223                 :            :         }
    1224                 :            : 
    1225                 :          0 :         req->flags = TXSCHQ_FREE_ALL;
    1226                 :          0 :         rc = mbox_process(mbox);
    1227         [ #  # ]:          0 :         if (rc)
    1228                 :          0 :                 plt_err("Failed to freeup all res, rc=%d", rc);
    1229                 :            :         mbox_put(mbox);
    1230                 :            : 
    1231         [ #  # ]:          0 :         for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
    1232                 :          0 :                 plt_bitmap_reset(nix->schq_bmp[hw_lvl]);
    1233                 :          0 :                 plt_bitmap_reset(nix->schq_contig_bmp[hw_lvl]);
    1234                 :          0 :                 nix->contig_rsvd[hw_lvl] = 0;
    1235                 :          0 :                 nix->discontig_rsvd[hw_lvl] = 0;
    1236                 :            :         }
    1237                 :            : 
    1238                 :            :         /* Clear shaper profiles */
    1239                 :          0 :         nix_tm_clear_shaper_profiles(nix);
    1240                 :          0 :         nix->tm_tree = 0;
    1241                 :          0 :         nix->tm_flags &= ~NIX_TM_HIERARCHY_ENA;
    1242                 :            : }
    1243                 :            : 
    1244                 :            : int
    1245                 :          0 : roc_nix_tm_rsrc_count(struct roc_nix *roc_nix, uint16_t schq[ROC_TM_LVL_MAX])
    1246                 :            : {
    1247                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
    1248                 :          0 :         struct mbox *mbox = mbox_get((&nix->dev)->mbox);
    1249                 :            :         struct free_rsrcs_rsp *rsp;
    1250                 :            :         uint8_t hw_lvl;
    1251                 :            :         int rc, i;
    1252                 :            : 
    1253                 :            :         /* Get the current free resources */
    1254                 :          0 :         mbox_alloc_msg_free_rsrc_cnt(mbox);
    1255                 :            :         rc = mbox_process_msg(mbox, (void *)&rsp);
    1256         [ #  # ]:          0 :         if (rc)
    1257                 :          0 :                 goto exit;
    1258                 :            : 
    1259         [ #  # ]:          0 :         for (i = 0; i < ROC_TM_LVL_MAX; i++) {
    1260                 :          0 :                 hw_lvl = nix_tm_lvl2nix(nix, i);
    1261         [ #  # ]:          0 :                 if (hw_lvl == NIX_TXSCH_LVL_CNT)
    1262                 :          0 :                         continue;
    1263                 :            : 
    1264         [ #  # ]:          0 :                 schq[i] = (nix->is_nix1 ? rsp->schq_nix1[hw_lvl] :
    1265                 :          0 :                                                 rsp->schq[hw_lvl]);
    1266                 :            :         }
    1267                 :            : 
    1268                 :            :         rc = 0;
    1269                 :          0 : exit:
    1270                 :            :         mbox_put(mbox);
    1271                 :          0 :         return rc;
    1272                 :            : }
    1273                 :            : 
    1274                 :            : void
    1275                 :          0 : roc_nix_tm_rsrc_max(bool pf, uint16_t schq[ROC_TM_LVL_MAX])
    1276                 :            : {
    1277                 :            :         uint8_t hw_lvl, i;
    1278                 :            :         uint16_t max;
    1279                 :            : 
    1280         [ #  # ]:          0 :         for (i = 0; i < ROC_TM_LVL_MAX; i++) {
    1281         [ #  # ]:          0 :                 hw_lvl = pf ? nix_tm_lvl2nix_tl1_root(i) :
    1282                 :          0 :                                     nix_tm_lvl2nix_tl2_root(i);
    1283                 :            : 
    1284   [ #  #  #  #  :          0 :                 switch (hw_lvl) {
                   #  # ]
    1285                 :            :                 case NIX_TXSCH_LVL_SMQ:
    1286         [ #  # ]:          0 :                         max = (roc_model_is_cn9k() ?
    1287                 :            :                                              NIX_CN9K_TXSCH_LVL_SMQ_MAX :
    1288                 :            :                                              NIX_TXSCH_LVL_SMQ_MAX);
    1289                 :            :                         break;
    1290                 :            :                 case NIX_TXSCH_LVL_TL4:
    1291                 :            :                         max = NIX_TXSCH_LVL_TL4_MAX;
    1292                 :            :                         break;
    1293                 :          0 :                 case NIX_TXSCH_LVL_TL3:
    1294                 :            :                         max = NIX_TXSCH_LVL_TL3_MAX;
    1295                 :          0 :                         break;
    1296                 :          0 :                 case NIX_TXSCH_LVL_TL2:
    1297         [ #  # ]:          0 :                         max = pf ? NIX_TXSCH_LVL_TL2_MAX : 1;
    1298                 :            :                         break;
    1299                 :          0 :                 case NIX_TXSCH_LVL_TL1:
    1300                 :          0 :                         max = pf ? 1 : 0;
    1301                 :          0 :                         break;
    1302                 :          0 :                 default:
    1303                 :            :                         max = 0;
    1304                 :          0 :                         break;
    1305                 :            :                 }
    1306                 :          0 :                 schq[i] = max;
    1307                 :            :         }
    1308                 :          0 : }
    1309                 :            : 
    1310                 :            : bool
    1311                 :          0 : roc_nix_tm_root_has_sp(struct roc_nix *roc_nix)
    1312                 :            : {
    1313                 :            :         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
    1314                 :            : 
    1315         [ #  # ]:          0 :         if (nix->tm_flags & NIX_TM_TL1_NO_SP)
    1316                 :          0 :                 return false;
    1317                 :            :         return true;
    1318                 :            : }
    1319                 :            : 
    1320                 :            : static inline struct nix *
    1321                 :          0 : pf_func_to_nix_get(uint16_t pf_func)
    1322                 :            : {
    1323                 :            :         struct roc_nix *roc_nix_tmp = NULL;
    1324                 :            :         struct roc_nix_list *nix_list;
    1325                 :            : 
    1326                 :          0 :         nix_list = roc_idev_nix_list_get();
    1327         [ #  # ]:          0 :         if (nix_list == NULL)
    1328                 :            :                 return NULL;
    1329                 :            : 
    1330                 :            :         /* Find the NIX of given pf_func */
    1331         [ #  # ]:          0 :         TAILQ_FOREACH(roc_nix_tmp, nix_list, next) {
    1332                 :            :                 struct nix *nix = roc_nix_to_nix_priv(roc_nix_tmp);
    1333                 :            : 
    1334         [ #  # ]:          0 :                 if (nix->dev.pf_func == pf_func)
    1335                 :          0 :                         return nix;
    1336                 :            :         }
    1337                 :            : 
    1338                 :            :         return NULL;
    1339                 :            : }
    1340                 :            : 
    1341                 :            : int
    1342                 :          0 : roc_nix_tm_egress_link_cfg_set(struct roc_nix *roc_nix, uint64_t dst_pf_func, bool enable)
    1343                 :            : {
    1344                 :            :         struct nix *src_nix = roc_nix_to_nix_priv(roc_nix), *dst_nix;
    1345                 :          0 :         struct mbox *mbox = (&src_nix->dev)->mbox;
    1346                 :            :         struct nix_txschq_config *req = NULL;
    1347                 :            :         struct nix_tm_node_list *list;
    1348                 :            :         struct nix_tm_node *node;
    1349                 :            :         int rc = 0, k;
    1350                 :            : 
    1351                 :          0 :         dst_nix = pf_func_to_nix_get(dst_pf_func);
    1352         [ #  # ]:          0 :         if (!dst_nix)
    1353                 :            :                 return -EINVAL;
    1354                 :            : 
    1355         [ #  # ]:          0 :         if (dst_nix == src_nix)
    1356                 :            :                 return 0;
    1357                 :            : 
    1358                 :          0 :         list = nix_tm_node_list(src_nix, src_nix->tm_tree);
    1359         [ #  # ]:          0 :         TAILQ_FOREACH(node, list, node) {
    1360         [ #  # ]:          0 :                 if (node->hw_lvl != src_nix->tm_link_cfg_lvl)
    1361                 :          0 :                         continue;
    1362                 :            : 
    1363         [ #  # ]:          0 :                 if (!(node->flags & NIX_TM_NODE_HWRES))
    1364                 :          0 :                         continue;
    1365                 :            : 
    1366                 :            :                 /* Allocating TL3 request */
    1367                 :          0 :                 req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
    1368                 :          0 :                 req->lvl = src_nix->tm_link_cfg_lvl;
    1369                 :            :                 k = 0;
    1370                 :            : 
    1371                 :            :                 /* Enable PFC/pause on the identified TL3 */
    1372                 :          0 :                 req->reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(node->hw_id, dst_nix->tx_link);
    1373         [ #  # ]:          0 :                 if (enable)
    1374                 :          0 :                         req->regval[k] |= BIT_ULL(12);
    1375                 :            :                 else
    1376                 :          0 :                         req->regval[k] &= ~(BIT_ULL(12));
    1377                 :          0 :                 req->regval_mask[k] = ~(BIT_ULL(12));
    1378                 :            :                 k++;
    1379                 :            : 
    1380                 :          0 :                 req->num_regs = k;
    1381                 :          0 :                 rc = mbox_process(mbox);
    1382                 :            :                 mbox_put(mbox);
    1383         [ #  # ]:          0 :                 if (rc)
    1384                 :          0 :                         goto err;
    1385                 :            :         }
    1386                 :          0 : err:
    1387                 :            :         return rc;
    1388                 :            : }

Generated by: LCOV version 1.14