105d727e8SNithin Dabilpuram /* SPDX-License-Identifier: BSD-3-Clause 205d727e8SNithin Dabilpuram * Copyright(C) 2021 Marvell. 305d727e8SNithin Dabilpuram */ 405d727e8SNithin Dabilpuram 505d727e8SNithin Dabilpuram #include "roc_api.h" 605d727e8SNithin Dabilpuram #include "roc_priv.h" 705d727e8SNithin Dabilpuram 8df405df9SNithin Dabilpuram static inline int 9df405df9SNithin Dabilpuram bitmap_ctzll(uint64_t slab) 10df405df9SNithin Dabilpuram { 11df405df9SNithin Dabilpuram if (slab == 0) 12df405df9SNithin Dabilpuram return 0; 13df405df9SNithin Dabilpuram 14354bf671SJerin Jacob return plt_ctz64(slab); 15df405df9SNithin Dabilpuram } 16df405df9SNithin Dabilpuram 17c2460d14SSatha Rao void 18c2460d14SSatha Rao nix_tm_clear_shaper_profiles(struct nix *nix) 19c2460d14SSatha Rao { 206a78d41eSGowrishankar Muthukrishnan struct nix_tm_shaper_profile *shaper_profile, *tmp; 216a78d41eSGowrishankar Muthukrishnan struct nix_tm_shaper_profile_list *list; 22c2460d14SSatha Rao 236a78d41eSGowrishankar Muthukrishnan list = &nix->shaper_profile_list; 246a78d41eSGowrishankar Muthukrishnan PLT_TAILQ_FOREACH_SAFE(shaper_profile, list, shaper, tmp) { 25c2460d14SSatha Rao if (shaper_profile->ref_cnt) 26c2460d14SSatha Rao plt_warn("Shaper profile %u has non zero references", 27c2460d14SSatha Rao shaper_profile->id); 28c2460d14SSatha Rao TAILQ_REMOVE(&nix->shaper_profile_list, shaper_profile, shaper); 29c2460d14SSatha Rao nix_tm_shaper_profile_free(shaper_profile); 30c2460d14SSatha Rao } 31c2460d14SSatha Rao } 32c2460d14SSatha Rao 330885429cSNithin Dabilpuram static int 340885429cSNithin Dabilpuram nix_tm_node_reg_conf(struct nix *nix, struct nix_tm_node *node) 350885429cSNithin Dabilpuram { 360885429cSNithin Dabilpuram uint64_t regval_mask[MAX_REGS_PER_MBOX_MSG]; 370885429cSNithin Dabilpuram uint64_t regval[MAX_REGS_PER_MBOX_MSG]; 380885429cSNithin Dabilpuram struct nix_tm_shaper_profile *profile; 390885429cSNithin Dabilpuram uint64_t reg[MAX_REGS_PER_MBOX_MSG]; 400885429cSNithin Dabilpuram struct mbox *mbox = (&nix->dev)->mbox; 410885429cSNithin Dabilpuram struct nix_txschq_config *req; 420885429cSNithin Dabilpuram int rc = -EFAULT; 430885429cSNithin Dabilpuram uint32_t hw_lvl; 440885429cSNithin Dabilpuram uint8_t k = 0; 450885429cSNithin Dabilpuram 460885429cSNithin Dabilpuram memset(regval, 0, sizeof(regval)); 470885429cSNithin Dabilpuram memset(regval_mask, 0, sizeof(regval_mask)); 480885429cSNithin Dabilpuram 490885429cSNithin Dabilpuram profile = nix_tm_shaper_profile_search(nix, node->shaper_profile_id); 500885429cSNithin Dabilpuram hw_lvl = node->hw_lvl; 510885429cSNithin Dabilpuram 520885429cSNithin Dabilpuram /* Need this trigger to configure TL1 */ 530885429cSNithin Dabilpuram if (!nix_tm_have_tl1_access(nix) && hw_lvl == NIX_TXSCH_LVL_TL2) { 540885429cSNithin Dabilpuram /* Prepare default conf for TL1 */ 5544a9307cSRakesh Kudurumalla req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox)); 560885429cSNithin Dabilpuram req->lvl = NIX_TXSCH_LVL_TL1; 570885429cSNithin Dabilpuram 58f0b9158cSNithin Dabilpuram k = nix_tm_tl1_default_prep(nix, node->parent_hw_id, req->reg, 590885429cSNithin Dabilpuram req->regval); 600885429cSNithin Dabilpuram req->num_regs = k; 610885429cSNithin Dabilpuram rc = mbox_process(mbox); 6244a9307cSRakesh Kudurumalla mbox_put(mbox); 630885429cSNithin Dabilpuram if (rc) 640885429cSNithin Dabilpuram goto error; 650885429cSNithin Dabilpuram } 660885429cSNithin Dabilpuram 670885429cSNithin Dabilpuram /* Prepare topology config */ 680885429cSNithin Dabilpuram k = nix_tm_topology_reg_prep(nix, node, reg, regval, regval_mask); 690885429cSNithin Dabilpuram 700885429cSNithin Dabilpuram /* Prepare schedule config */ 710885429cSNithin Dabilpuram k += nix_tm_sched_reg_prep(nix, node, ®[k], ®val[k]); 720885429cSNithin Dabilpuram 730885429cSNithin Dabilpuram /* Prepare shaping config */ 740885429cSNithin Dabilpuram k += nix_tm_shaper_reg_prep(node, profile, ®[k], ®val[k]); 750885429cSNithin Dabilpuram 760885429cSNithin Dabilpuram if (!k) 770885429cSNithin Dabilpuram return 0; 780885429cSNithin Dabilpuram 790885429cSNithin Dabilpuram /* Copy and send config mbox */ 8044a9307cSRakesh Kudurumalla req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox)); 810885429cSNithin Dabilpuram req->lvl = hw_lvl; 820885429cSNithin Dabilpuram req->num_regs = k; 830885429cSNithin Dabilpuram 840885429cSNithin Dabilpuram mbox_memcpy(req->reg, reg, sizeof(uint64_t) * k); 850885429cSNithin Dabilpuram mbox_memcpy(req->regval, regval, sizeof(uint64_t) * k); 860885429cSNithin Dabilpuram mbox_memcpy(req->regval_mask, regval_mask, sizeof(uint64_t) * k); 870885429cSNithin Dabilpuram 880885429cSNithin Dabilpuram rc = mbox_process(mbox); 8944a9307cSRakesh Kudurumalla mbox_put(mbox); 900885429cSNithin Dabilpuram if (rc) 910885429cSNithin Dabilpuram goto error; 920885429cSNithin Dabilpuram 930885429cSNithin Dabilpuram return 0; 940885429cSNithin Dabilpuram error: 950885429cSNithin Dabilpuram plt_err("Txschq conf failed for node %p, rc=%d", node, rc); 960885429cSNithin Dabilpuram return rc; 970885429cSNithin Dabilpuram } 980885429cSNithin Dabilpuram 990885429cSNithin Dabilpuram int 1000885429cSNithin Dabilpuram nix_tm_txsch_reg_config(struct nix *nix, enum roc_nix_tm_tree tree) 1010885429cSNithin Dabilpuram { 1020885429cSNithin Dabilpuram struct nix_tm_node_list *list; 1030885429cSNithin Dabilpuram struct nix_tm_node *node; 1040885429cSNithin Dabilpuram uint32_t hw_lvl; 1050885429cSNithin Dabilpuram int rc = 0; 1060885429cSNithin Dabilpuram 1070885429cSNithin Dabilpuram list = nix_tm_node_list(nix, tree); 1080885429cSNithin Dabilpuram 1090885429cSNithin Dabilpuram for (hw_lvl = 0; hw_lvl <= nix->tm_root_lvl; hw_lvl++) { 1100885429cSNithin Dabilpuram TAILQ_FOREACH(node, list, node) { 1110885429cSNithin Dabilpuram if (node->hw_lvl != hw_lvl) 1120885429cSNithin Dabilpuram continue; 11358debb81SNithin Dabilpuram 11458debb81SNithin Dabilpuram /* Only one TL3/TL2 Link config should have BP enable 11558debb81SNithin Dabilpuram * set per channel only for PF or lbk vf. 11658debb81SNithin Dabilpuram */ 11758debb81SNithin Dabilpuram node->bp_capa = 0; 11878fb5efeSNithin Dabilpuram if (!nix->sdp_link && node->hw_lvl == nix->tm_link_cfg_lvl) 11958debb81SNithin Dabilpuram node->bp_capa = 1; 12058debb81SNithin Dabilpuram 1210885429cSNithin Dabilpuram rc = nix_tm_node_reg_conf(nix, node); 1220885429cSNithin Dabilpuram if (rc) 1230885429cSNithin Dabilpuram goto exit; 1240885429cSNithin Dabilpuram } 1250885429cSNithin Dabilpuram } 1260885429cSNithin Dabilpuram exit: 1270885429cSNithin Dabilpuram return rc; 1280885429cSNithin Dabilpuram } 1290885429cSNithin Dabilpuram 130be3009e7SNithin Dabilpuram int 131df405df9SNithin Dabilpuram nix_tm_update_parent_info(struct nix *nix, enum roc_nix_tm_tree tree) 132df405df9SNithin Dabilpuram { 133df405df9SNithin Dabilpuram struct nix_tm_node *child, *parent; 134df405df9SNithin Dabilpuram struct nix_tm_node_list *list; 135df405df9SNithin Dabilpuram uint32_t rr_prio, max_prio; 136df405df9SNithin Dabilpuram uint32_t rr_num = 0; 137df405df9SNithin Dabilpuram 138df405df9SNithin Dabilpuram list = nix_tm_node_list(nix, tree); 139df405df9SNithin Dabilpuram 140df405df9SNithin Dabilpuram /* Release all the node hw resources locally 141df405df9SNithin Dabilpuram * if parent marked as dirty and resource exists. 142df405df9SNithin Dabilpuram */ 143df405df9SNithin Dabilpuram TAILQ_FOREACH(child, list, node) { 144df405df9SNithin Dabilpuram /* Release resource only if parent direct hierarchy changed */ 145df405df9SNithin Dabilpuram if (child->flags & NIX_TM_NODE_HWRES && child->parent && 146df405df9SNithin Dabilpuram child->parent->child_realloc) { 147df405df9SNithin Dabilpuram nix_tm_free_node_resource(nix, child); 148df405df9SNithin Dabilpuram } 149df405df9SNithin Dabilpuram child->max_prio = UINT32_MAX; 150df405df9SNithin Dabilpuram } 151df405df9SNithin Dabilpuram 152df405df9SNithin Dabilpuram TAILQ_FOREACH(parent, list, node) { 153df405df9SNithin Dabilpuram /* Count group of children of same priority i.e are RR */ 154df405df9SNithin Dabilpuram rr_num = nix_tm_check_rr(nix, parent->id, tree, &rr_prio, 155df405df9SNithin Dabilpuram &max_prio); 156df405df9SNithin Dabilpuram 157df405df9SNithin Dabilpuram /* Assuming that multiple RR groups are 158df405df9SNithin Dabilpuram * not configured based on capability. 159df405df9SNithin Dabilpuram */ 160df405df9SNithin Dabilpuram parent->rr_prio = rr_prio; 161df405df9SNithin Dabilpuram parent->rr_num = rr_num; 162df405df9SNithin Dabilpuram parent->max_prio = max_prio; 163df405df9SNithin Dabilpuram } 164df405df9SNithin Dabilpuram 165df405df9SNithin Dabilpuram return 0; 166df405df9SNithin Dabilpuram } 167df405df9SNithin Dabilpuram 168f9dbd4a5SSatha Rao static int 169f9dbd4a5SSatha Rao nix_tm_root_node_get(struct nix *nix, int tree) 170f9dbd4a5SSatha Rao { 171f9dbd4a5SSatha Rao struct nix_tm_node_list *list = nix_tm_node_list(nix, tree); 172f9dbd4a5SSatha Rao struct nix_tm_node *tm_node; 173f9dbd4a5SSatha Rao 174f9dbd4a5SSatha Rao TAILQ_FOREACH(tm_node, list, node) { 175f9dbd4a5SSatha Rao if (tm_node->hw_lvl == nix->tm_root_lvl) 176f9dbd4a5SSatha Rao return 1; 177f9dbd4a5SSatha Rao } 178f9dbd4a5SSatha Rao 179f9dbd4a5SSatha Rao return 0; 180f9dbd4a5SSatha Rao } 181f9dbd4a5SSatha Rao 182df405df9SNithin Dabilpuram int 183be3009e7SNithin Dabilpuram nix_tm_node_add(struct roc_nix *roc_nix, struct nix_tm_node *node) 184be3009e7SNithin Dabilpuram { 185be3009e7SNithin Dabilpuram struct nix *nix = roc_nix_to_nix_priv(roc_nix); 186be3009e7SNithin Dabilpuram struct nix_tm_shaper_profile *profile; 187be3009e7SNithin Dabilpuram uint32_t node_id, parent_id, lvl; 188be3009e7SNithin Dabilpuram struct nix_tm_node *parent_node; 189be3009e7SNithin Dabilpuram uint32_t priority, profile_id; 190be3009e7SNithin Dabilpuram uint8_t hw_lvl, exp_next_lvl; 191be3009e7SNithin Dabilpuram enum roc_nix_tm_tree tree; 192be3009e7SNithin Dabilpuram int rc; 193be3009e7SNithin Dabilpuram 194be3009e7SNithin Dabilpuram node_id = node->id; 195be3009e7SNithin Dabilpuram priority = node->priority; 196be3009e7SNithin Dabilpuram parent_id = node->parent_id; 197be3009e7SNithin Dabilpuram profile_id = node->shaper_profile_id; 198be3009e7SNithin Dabilpuram lvl = node->lvl; 199be3009e7SNithin Dabilpuram tree = node->tree; 200be3009e7SNithin Dabilpuram 201be3009e7SNithin Dabilpuram plt_tm_dbg("Add node %s lvl %u id %u, prio 0x%x weight 0x%x " 202be3009e7SNithin Dabilpuram "parent %u profile 0x%x tree %u", 203be3009e7SNithin Dabilpuram nix_tm_hwlvl2str(nix_tm_lvl2nix(nix, lvl)), lvl, node_id, 204be3009e7SNithin Dabilpuram priority, node->weight, parent_id, profile_id, tree); 205be3009e7SNithin Dabilpuram 206be3009e7SNithin Dabilpuram if (tree >= ROC_NIX_TM_TREE_MAX) 207be3009e7SNithin Dabilpuram return NIX_ERR_PARAM; 208be3009e7SNithin Dabilpuram 209be3009e7SNithin Dabilpuram /* Translate sw level id's to nix hw level id's */ 210be3009e7SNithin Dabilpuram hw_lvl = nix_tm_lvl2nix(nix, lvl); 211be3009e7SNithin Dabilpuram if (hw_lvl == NIX_TXSCH_LVL_CNT && !nix_tm_is_leaf(nix, lvl)) 212be3009e7SNithin Dabilpuram return NIX_ERR_TM_INVALID_LVL; 213be3009e7SNithin Dabilpuram 214be3009e7SNithin Dabilpuram /* Leaf nodes have to be same priority */ 215be3009e7SNithin Dabilpuram if (nix_tm_is_leaf(nix, lvl) && priority != 0) 216be3009e7SNithin Dabilpuram return NIX_ERR_TM_INVALID_PRIO; 217be3009e7SNithin Dabilpuram 218be3009e7SNithin Dabilpuram parent_node = nix_tm_node_search(nix, parent_id, tree); 219be3009e7SNithin Dabilpuram 220be3009e7SNithin Dabilpuram if (node_id < nix->nb_tx_queues) 221be3009e7SNithin Dabilpuram exp_next_lvl = NIX_TXSCH_LVL_SMQ; 222be3009e7SNithin Dabilpuram else 223be3009e7SNithin Dabilpuram exp_next_lvl = hw_lvl + 1; 224be3009e7SNithin Dabilpuram 225be3009e7SNithin Dabilpuram /* Check if there is no parent node yet */ 226be3009e7SNithin Dabilpuram if (hw_lvl != nix->tm_root_lvl && 227be3009e7SNithin Dabilpuram (!parent_node || parent_node->hw_lvl != exp_next_lvl)) 228be3009e7SNithin Dabilpuram return NIX_ERR_TM_INVALID_PARENT; 229be3009e7SNithin Dabilpuram 230be3009e7SNithin Dabilpuram /* Check if a node already exists */ 231be3009e7SNithin Dabilpuram if (nix_tm_node_search(nix, node_id, tree)) 232be3009e7SNithin Dabilpuram return NIX_ERR_TM_NODE_EXISTS; 233be3009e7SNithin Dabilpuram 234f9dbd4a5SSatha Rao /* Check if root node exists */ 235f9dbd4a5SSatha Rao if (hw_lvl == nix->tm_root_lvl && nix_tm_root_node_get(nix, tree)) 236f9dbd4a5SSatha Rao return NIX_ERR_TM_NODE_EXISTS; 237f9dbd4a5SSatha Rao 238be3009e7SNithin Dabilpuram profile = nix_tm_shaper_profile_search(nix, profile_id); 239be3009e7SNithin Dabilpuram if (!nix_tm_is_leaf(nix, lvl)) { 240be3009e7SNithin Dabilpuram /* Check if shaper profile exists for non leaf node */ 241be3009e7SNithin Dabilpuram if (!profile && profile_id != ROC_NIX_TM_SHAPER_PROFILE_NONE) 242be3009e7SNithin Dabilpuram return NIX_ERR_TM_INVALID_SHAPER_PROFILE; 243be3009e7SNithin Dabilpuram 244be3009e7SNithin Dabilpuram /* Packet mode in profile should match with that of tm node */ 245be3009e7SNithin Dabilpuram if (profile && profile->pkt_mode != node->pkt_mode) 246be3009e7SNithin Dabilpuram return NIX_ERR_TM_PKT_MODE_MISMATCH; 247be3009e7SNithin Dabilpuram } 248be3009e7SNithin Dabilpuram 249be3009e7SNithin Dabilpuram /* Check if there is second DWRR already in siblings or holes in prio */ 250be3009e7SNithin Dabilpuram rc = nix_tm_validate_prio(nix, lvl, parent_id, priority, tree); 251be3009e7SNithin Dabilpuram if (rc) 252be3009e7SNithin Dabilpuram return rc; 253be3009e7SNithin Dabilpuram 2546fe49f10SNithin Dabilpuram if (node->weight > roc_nix_tm_max_sched_wt_get()) 255be3009e7SNithin Dabilpuram return NIX_ERR_TM_WEIGHT_EXCEED; 256be3009e7SNithin Dabilpuram 257be3009e7SNithin Dabilpuram node->hw_lvl = nix_tm_lvl2nix(nix, lvl); 258be3009e7SNithin Dabilpuram node->rr_prio = 0xF; 259be3009e7SNithin Dabilpuram node->max_prio = UINT32_MAX; 260be3009e7SNithin Dabilpuram node->hw_id = NIX_TM_HW_ID_INVALID; 261be3009e7SNithin Dabilpuram node->flags = 0; 262be3009e7SNithin Dabilpuram 263be3009e7SNithin Dabilpuram if (profile) 264be3009e7SNithin Dabilpuram profile->ref_cnt++; 265be3009e7SNithin Dabilpuram 266be3009e7SNithin Dabilpuram node->parent = parent_node; 267be3009e7SNithin Dabilpuram if (parent_node) 268be3009e7SNithin Dabilpuram parent_node->child_realloc = true; 269be3009e7SNithin Dabilpuram node->parent_hw_id = NIX_TM_HW_ID_INVALID; 270be3009e7SNithin Dabilpuram 271be3009e7SNithin Dabilpuram TAILQ_INSERT_TAIL(&nix->trees[tree], node, node); 272be3009e7SNithin Dabilpuram plt_tm_dbg("Added node %s lvl %u id %u (%p)", 273be3009e7SNithin Dabilpuram nix_tm_hwlvl2str(node->hw_lvl), lvl, node_id, node); 274be3009e7SNithin Dabilpuram return 0; 275be3009e7SNithin Dabilpuram } 27605d727e8SNithin Dabilpuram 27705d727e8SNithin Dabilpuram int 27805d727e8SNithin Dabilpuram nix_tm_clear_path_xoff(struct nix *nix, struct nix_tm_node *node) 27905d727e8SNithin Dabilpuram { 28044a9307cSRakesh Kudurumalla struct mbox *mbox = mbox_get((&nix->dev)->mbox); 28105d727e8SNithin Dabilpuram struct nix_txschq_config *req; 28205d727e8SNithin Dabilpuram struct nix_tm_node *p; 28305d727e8SNithin Dabilpuram int rc; 28405d727e8SNithin Dabilpuram 28505d727e8SNithin Dabilpuram /* Enable nodes in path for flush to succeed */ 28605d727e8SNithin Dabilpuram if (!nix_tm_is_leaf(nix, node->lvl)) 28705d727e8SNithin Dabilpuram p = node; 28805d727e8SNithin Dabilpuram else 28905d727e8SNithin Dabilpuram p = node->parent; 29005d727e8SNithin Dabilpuram while (p) { 29105d727e8SNithin Dabilpuram if (!(p->flags & NIX_TM_NODE_ENABLED) && 29205d727e8SNithin Dabilpuram (p->flags & NIX_TM_NODE_HWRES)) { 29305d727e8SNithin Dabilpuram req = mbox_alloc_msg_nix_txschq_cfg(mbox); 29405d727e8SNithin Dabilpuram req->lvl = p->hw_lvl; 29505d727e8SNithin Dabilpuram req->num_regs = nix_tm_sw_xoff_prep(p, false, req->reg, 29605d727e8SNithin Dabilpuram req->regval); 29705d727e8SNithin Dabilpuram rc = mbox_process(mbox); 29805d727e8SNithin Dabilpuram if (rc) 29944a9307cSRakesh Kudurumalla goto exit; 30005d727e8SNithin Dabilpuram 30105d727e8SNithin Dabilpuram p->flags |= NIX_TM_NODE_ENABLED; 30205d727e8SNithin Dabilpuram } 30305d727e8SNithin Dabilpuram p = p->parent; 30405d727e8SNithin Dabilpuram } 30505d727e8SNithin Dabilpuram 30644a9307cSRakesh Kudurumalla rc = 0; 30744a9307cSRakesh Kudurumalla exit: 30844a9307cSRakesh Kudurumalla mbox_put(mbox); 30944a9307cSRakesh Kudurumalla return rc; 31005d727e8SNithin Dabilpuram } 31105d727e8SNithin Dabilpuram 31205d727e8SNithin Dabilpuram int 31320d02329SSunil Kumar Kori nix_tm_bp_config_set(struct roc_nix *roc_nix, uint16_t sq, uint16_t tc, 31478fb5efeSNithin Dabilpuram bool enable) 31558debb81SNithin Dabilpuram { 31658debb81SNithin Dabilpuram struct nix *nix = roc_nix_to_nix_priv(roc_nix); 31758debb81SNithin Dabilpuram enum roc_nix_tm_tree tree = nix->tm_tree; 31858debb81SNithin Dabilpuram struct mbox *mbox = (&nix->dev)->mbox; 31958debb81SNithin Dabilpuram struct nix_txschq_config *req = NULL; 32058debb81SNithin Dabilpuram struct nix_tm_node_list *list; 321d120c089SSatha Rao uint16_t link = nix->tx_link; 32220d02329SSunil Kumar Kori struct nix_tm_node *sq_node; 32320d02329SSunil Kumar Kori struct nix_tm_node *parent; 32458debb81SNithin Dabilpuram struct nix_tm_node *node; 325cc90e35bSHarman Kalra struct roc_nix_sq *sq_s; 32678fb5efeSNithin Dabilpuram uint16_t rel_chan = 0; 327174f2f35SSunil Kumar Kori uint8_t parent_lvl; 32858debb81SNithin Dabilpuram uint8_t k = 0; 32978fb5efeSNithin Dabilpuram int rc = 0, i; 33058debb81SNithin Dabilpuram 33148054ca3SHarman Kalra if (roc_nix_is_sdp(roc_nix)) 33248054ca3SHarman Kalra return 0; 33348054ca3SHarman Kalra 334cc90e35bSHarman Kalra sq_s = nix->sqs[sq]; 335cc90e35bSHarman Kalra if (!sq_s) 336cc90e35bSHarman Kalra return -ENOENT; 337cc90e35bSHarman Kalra 33820d02329SSunil Kumar Kori sq_node = nix_tm_node_search(nix, sq, nix->tm_tree); 339d120c089SSatha Rao if (!sq_node) 340d120c089SSatha Rao return -ENOENT; 341d120c089SSatha Rao 342174f2f35SSunil Kumar Kori parent_lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH2 : 343174f2f35SSunil Kumar Kori ROC_TM_LVL_SCH1); 344174f2f35SSunil Kumar Kori 34520d02329SSunil Kumar Kori parent = sq_node->parent; 34620d02329SSunil Kumar Kori while (parent) { 347174f2f35SSunil Kumar Kori if (parent->lvl == parent_lvl) 34820d02329SSunil Kumar Kori break; 34920d02329SSunil Kumar Kori 35020d02329SSunil Kumar Kori parent = parent->parent; 35120d02329SSunil Kumar Kori } 352d120c089SSatha Rao if (!parent) 353d120c089SSatha Rao return -ENOENT; 35420d02329SSunil Kumar Kori 35558debb81SNithin Dabilpuram list = nix_tm_node_list(nix, tree); 35658debb81SNithin Dabilpuram 35778fb5efeSNithin Dabilpuram /* Get relative channel if loopback */ 35878fb5efeSNithin Dabilpuram if (roc_nix_is_lbk(roc_nix)) 35978fb5efeSNithin Dabilpuram rel_chan = nix_tm_lbk_relchan_get(nix); 36078fb5efeSNithin Dabilpuram else 36178fb5efeSNithin Dabilpuram rel_chan = tc; 36278fb5efeSNithin Dabilpuram 363cc90e35bSHarman Kalra /* Enable request, parent rel chan already configured */ 364cc90e35bSHarman Kalra if (enable && parent->rel_chan != NIX_TM_CHAN_INVALID && 36578fb5efeSNithin Dabilpuram parent->rel_chan != rel_chan) { 36678fb5efeSNithin Dabilpuram plt_err("SQ %d: parent node TL3 id %d already has rel_chan %d set", 36778fb5efeSNithin Dabilpuram sq, parent->hw_id, parent->rel_chan); 36820d02329SSunil Kumar Kori rc = -EINVAL; 36920d02329SSunil Kumar Kori goto err; 37020d02329SSunil Kumar Kori } 37120d02329SSunil Kumar Kori 372cc90e35bSHarman Kalra /* No action if enable request for a non participating SQ. This case is 373cc90e35bSHarman Kalra * required to handle post flush where TCs should be reconfigured after 374cc90e35bSHarman Kalra * pre flush. 375cc90e35bSHarman Kalra */ 376cc90e35bSHarman Kalra if (enable && sq_s->tc == ROC_NIX_PFC_CLASS_INVALID && 377cc90e35bSHarman Kalra tc == ROC_NIX_PFC_CLASS_INVALID) 378cc90e35bSHarman Kalra return 0; 379cc90e35bSHarman Kalra 380cc90e35bSHarman Kalra /* Find the parent TL3 */ 38158debb81SNithin Dabilpuram TAILQ_FOREACH(node, list, node) { 38258debb81SNithin Dabilpuram if (node->hw_lvl != nix->tm_link_cfg_lvl) 38358debb81SNithin Dabilpuram continue; 38458debb81SNithin Dabilpuram 38558debb81SNithin Dabilpuram if (!(node->flags & NIX_TM_NODE_HWRES) || !node->bp_capa) 38658debb81SNithin Dabilpuram continue; 38758debb81SNithin Dabilpuram 388cc90e35bSHarman Kalra /* Restrict sharing of TL3 across the queues */ 38978fb5efeSNithin Dabilpuram if (enable && node != parent && node->rel_chan == rel_chan) { 39078fb5efeSNithin Dabilpuram plt_warn("SQ %d: siblng node TL3 %d already has %d(%d) tc value set", 39178fb5efeSNithin Dabilpuram sq, node->hw_id, tc, rel_chan); 39278fb5efeSNithin Dabilpuram return -EEXIST; 393cc90e35bSHarman Kalra } 394cc90e35bSHarman Kalra } 39520d02329SSunil Kumar Kori 39678fb5efeSNithin Dabilpuram /* Allocating TL3 request */ 39744a9307cSRakesh Kudurumalla req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox)); 39858debb81SNithin Dabilpuram req->lvl = nix->tm_link_cfg_lvl; 39958debb81SNithin Dabilpuram k = 0; 40058debb81SNithin Dabilpuram 40178fb5efeSNithin Dabilpuram /* Enable PFC/pause on the identified TL3 */ 402cc90e35bSHarman Kalra req->reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(parent->hw_id, link); 40378fb5efeSNithin Dabilpuram req->regval[k] = enable ? rel_chan : 0; 40420d02329SSunil Kumar Kori req->regval[k] |= enable ? BIT_ULL(13) : 0; 40520d02329SSunil Kumar Kori req->regval_mask[k] = ~(BIT_ULL(13) | GENMASK_ULL(7, 0)); 40658debb81SNithin Dabilpuram k++; 40758debb81SNithin Dabilpuram 40858debb81SNithin Dabilpuram req->num_regs = k; 40958debb81SNithin Dabilpuram rc = mbox_process(mbox); 41058debb81SNithin Dabilpuram if (rc) 41158debb81SNithin Dabilpuram goto err; 41258debb81SNithin Dabilpuram 41378fb5efeSNithin Dabilpuram parent->rel_chan = enable ? rel_chan : NIX_TM_CHAN_INVALID; 41478fb5efeSNithin Dabilpuram sq_s->tc = enable ? tc : ROC_NIX_PFC_CLASS_INVALID; 41578fb5efeSNithin Dabilpuram /* Clear other SQ's with same TC i.e same parent node */ 41678fb5efeSNithin Dabilpuram for (i = 0; !enable && i < nix->nb_tx_queues; i++) { 41778fb5efeSNithin Dabilpuram if (nix->sqs[i] && nix->sqs[i]->tc == tc) 41878fb5efeSNithin Dabilpuram nix->sqs[i]->tc = ROC_NIX_PFC_CLASS_INVALID; 41978fb5efeSNithin Dabilpuram } 420cc90e35bSHarman Kalra 42144a9307cSRakesh Kudurumalla rc = 0; 42278fb5efeSNithin Dabilpuram plt_tm_dbg("SQ %u: TL3 %d TC %u %s", 42378fb5efeSNithin Dabilpuram sq, parent->hw_id, tc, enable ? "enabled" : "disabled"); 42444a9307cSRakesh Kudurumalla goto exit; 42558debb81SNithin Dabilpuram err: 42658debb81SNithin Dabilpuram plt_err("Failed to %s bp on link %u, rc=%d(%s)", 42758debb81SNithin Dabilpuram enable ? "enable" : "disable", link, rc, roc_error_msg_get(rc)); 42844a9307cSRakesh Kudurumalla exit: 42944a9307cSRakesh Kudurumalla mbox_put(mbox); 43058debb81SNithin Dabilpuram return rc; 43158debb81SNithin Dabilpuram } 43258debb81SNithin Dabilpuram 43358debb81SNithin Dabilpuram int 43458debb81SNithin Dabilpuram nix_tm_bp_config_get(struct roc_nix *roc_nix, bool *is_enabled) 43558debb81SNithin Dabilpuram { 43658debb81SNithin Dabilpuram struct nix *nix = roc_nix_to_nix_priv(roc_nix); 43758debb81SNithin Dabilpuram struct nix_txschq_config *req = NULL, *rsp; 43858debb81SNithin Dabilpuram enum roc_nix_tm_tree tree = nix->tm_tree; 43944a9307cSRakesh Kudurumalla struct mbox *mbox = mbox_get((&nix->dev)->mbox); 44058debb81SNithin Dabilpuram struct nix_tm_node_list *list; 44158debb81SNithin Dabilpuram struct nix_tm_node *node; 44258debb81SNithin Dabilpuram bool found = false; 44358debb81SNithin Dabilpuram uint8_t enable = 1; 44458debb81SNithin Dabilpuram uint8_t k = 0, i; 44558debb81SNithin Dabilpuram uint16_t link; 44658debb81SNithin Dabilpuram int rc = 0; 44758debb81SNithin Dabilpuram 44858debb81SNithin Dabilpuram list = nix_tm_node_list(nix, tree); 44958debb81SNithin Dabilpuram link = nix->tx_link; 45058debb81SNithin Dabilpuram 45158debb81SNithin Dabilpuram TAILQ_FOREACH(node, list, node) { 45258debb81SNithin Dabilpuram if (node->hw_lvl != nix->tm_link_cfg_lvl) 45358debb81SNithin Dabilpuram continue; 45458debb81SNithin Dabilpuram 45558debb81SNithin Dabilpuram if (!(node->flags & NIX_TM_NODE_HWRES) || !node->bp_capa) 45658debb81SNithin Dabilpuram continue; 45758debb81SNithin Dabilpuram 45858debb81SNithin Dabilpuram found = true; 45958debb81SNithin Dabilpuram if (!req) { 46058debb81SNithin Dabilpuram req = mbox_alloc_msg_nix_txschq_cfg(mbox); 46158debb81SNithin Dabilpuram req->read = 1; 46258debb81SNithin Dabilpuram req->lvl = nix->tm_link_cfg_lvl; 46358debb81SNithin Dabilpuram k = 0; 46458debb81SNithin Dabilpuram } 46558debb81SNithin Dabilpuram 46658debb81SNithin Dabilpuram req->reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(node->hw_id, link); 46758debb81SNithin Dabilpuram k++; 46858debb81SNithin Dabilpuram 46958debb81SNithin Dabilpuram if (k >= MAX_REGS_PER_MBOX_MSG) { 47058debb81SNithin Dabilpuram req->num_regs = k; 47158debb81SNithin Dabilpuram rc = mbox_process_msg(mbox, (void **)&rsp); 47258debb81SNithin Dabilpuram if (rc || rsp->num_regs != k) 47358debb81SNithin Dabilpuram goto err; 47458debb81SNithin Dabilpuram req = NULL; 47558debb81SNithin Dabilpuram 47658debb81SNithin Dabilpuram /* Report it as enabled only if enabled or all */ 47758debb81SNithin Dabilpuram for (i = 0; i < k; i++) 47858debb81SNithin Dabilpuram enable &= !!(rsp->regval[i] & BIT_ULL(13)); 47958debb81SNithin Dabilpuram } 48058debb81SNithin Dabilpuram } 48158debb81SNithin Dabilpuram 48258debb81SNithin Dabilpuram if (req) { 48358debb81SNithin Dabilpuram req->num_regs = k; 484a3b48642SNithin Dabilpuram rc = mbox_process_msg(mbox, (void **)&rsp); 48558debb81SNithin Dabilpuram if (rc) 48658debb81SNithin Dabilpuram goto err; 48758debb81SNithin Dabilpuram /* Report it as enabled only if enabled or all */ 48858debb81SNithin Dabilpuram for (i = 0; i < k; i++) 48958debb81SNithin Dabilpuram enable &= !!(rsp->regval[i] & BIT_ULL(13)); 49058debb81SNithin Dabilpuram } 49158debb81SNithin Dabilpuram 49258debb81SNithin Dabilpuram *is_enabled = found ? !!enable : false; 49344a9307cSRakesh Kudurumalla rc = 0; 49444a9307cSRakesh Kudurumalla goto exit; 49558debb81SNithin Dabilpuram err: 49658debb81SNithin Dabilpuram plt_err("Failed to get bp status on link %u, rc=%d(%s)", link, rc, 49758debb81SNithin Dabilpuram roc_error_msg_get(rc)); 49844a9307cSRakesh Kudurumalla exit: 49944a9307cSRakesh Kudurumalla mbox_put(mbox); 50058debb81SNithin Dabilpuram return rc; 50158debb81SNithin Dabilpuram } 50258debb81SNithin Dabilpuram 50358debb81SNithin Dabilpuram int 50405d727e8SNithin Dabilpuram nix_tm_smq_xoff(struct nix *nix, struct nix_tm_node *node, bool enable) 50505d727e8SNithin Dabilpuram { 50605d727e8SNithin Dabilpuram struct mbox *mbox = (&nix->dev)->mbox; 50705d727e8SNithin Dabilpuram struct nix_txschq_config *req; 50805d727e8SNithin Dabilpuram uint16_t smq; 50905d727e8SNithin Dabilpuram int rc; 51005d727e8SNithin Dabilpuram 51105d727e8SNithin Dabilpuram smq = node->hw_id; 51205d727e8SNithin Dabilpuram plt_tm_dbg("Setting SMQ %u XOFF/FLUSH to %s", smq, 51305d727e8SNithin Dabilpuram enable ? "enable" : "disable"); 51405d727e8SNithin Dabilpuram 51505d727e8SNithin Dabilpuram rc = nix_tm_clear_path_xoff(nix, node); 51605d727e8SNithin Dabilpuram if (rc) 51705d727e8SNithin Dabilpuram return rc; 51805d727e8SNithin Dabilpuram 51944a9307cSRakesh Kudurumalla req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox)); 52005d727e8SNithin Dabilpuram req->lvl = NIX_TXSCH_LVL_SMQ; 52105d727e8SNithin Dabilpuram req->num_regs = 1; 52205d727e8SNithin Dabilpuram 52305d727e8SNithin Dabilpuram req->reg[0] = NIX_AF_SMQX_CFG(smq); 52405d727e8SNithin Dabilpuram req->regval[0] = enable ? (BIT_ULL(50) | BIT_ULL(49)) : 0; 52505d727e8SNithin Dabilpuram req->regval_mask[0] = 52605d727e8SNithin Dabilpuram enable ? ~(BIT_ULL(50) | BIT_ULL(49)) : ~BIT_ULL(50); 52705d727e8SNithin Dabilpuram 52844a9307cSRakesh Kudurumalla rc = mbox_process(mbox); 52944a9307cSRakesh Kudurumalla mbox_put(mbox); 53044a9307cSRakesh Kudurumalla return rc; 53105d727e8SNithin Dabilpuram } 53205d727e8SNithin Dabilpuram 53305d727e8SNithin Dabilpuram int 53405d727e8SNithin Dabilpuram nix_tm_leaf_data_get(struct nix *nix, uint16_t sq, uint32_t *rr_quantum, 53505d727e8SNithin Dabilpuram uint16_t *smq) 53605d727e8SNithin Dabilpuram { 53705d727e8SNithin Dabilpuram struct nix_tm_node *node; 53805d727e8SNithin Dabilpuram int rc; 53905d727e8SNithin Dabilpuram 54005d727e8SNithin Dabilpuram node = nix_tm_node_search(nix, sq, nix->tm_tree); 54105d727e8SNithin Dabilpuram 54205d727e8SNithin Dabilpuram /* Check if we found a valid leaf node */ 54305d727e8SNithin Dabilpuram if (!node || !nix_tm_is_leaf(nix, node->lvl) || !node->parent || 54405d727e8SNithin Dabilpuram node->parent->hw_id == NIX_TM_HW_ID_INVALID) { 54505d727e8SNithin Dabilpuram return -EIO; 54605d727e8SNithin Dabilpuram } 54705d727e8SNithin Dabilpuram 54805d727e8SNithin Dabilpuram /* Get SMQ Id of leaf node's parent */ 54905d727e8SNithin Dabilpuram *smq = node->parent->hw_id; 55005d727e8SNithin Dabilpuram *rr_quantum = nix_tm_weight_to_rr_quantum(node->weight); 55105d727e8SNithin Dabilpuram 55205d727e8SNithin Dabilpuram rc = nix_tm_smq_xoff(nix, node->parent, false); 55305d727e8SNithin Dabilpuram if (rc) 55405d727e8SNithin Dabilpuram return rc; 55505d727e8SNithin Dabilpuram node->flags |= NIX_TM_NODE_ENABLED; 55605d727e8SNithin Dabilpuram return 0; 55705d727e8SNithin Dabilpuram } 55805d727e8SNithin Dabilpuram 55905d727e8SNithin Dabilpuram int 56005d727e8SNithin Dabilpuram roc_nix_tm_sq_flush_spin(struct roc_nix_sq *sq) 56105d727e8SNithin Dabilpuram { 56205d727e8SNithin Dabilpuram struct nix *nix = roc_nix_to_nix_priv(sq->roc_nix); 56305d727e8SNithin Dabilpuram uint16_t sqb_cnt, head_off, tail_off; 56405d727e8SNithin Dabilpuram uint64_t wdata, val, prev; 56505d727e8SNithin Dabilpuram uint16_t qid = sq->qid; 56605d727e8SNithin Dabilpuram int64_t *regaddr; 56705d727e8SNithin Dabilpuram uint64_t timeout; /* 10's of usec */ 56805d727e8SNithin Dabilpuram 56905d727e8SNithin Dabilpuram /* Wait for enough time based on shaper min rate */ 57005d727e8SNithin Dabilpuram timeout = (sq->nb_desc * roc_nix_max_pkt_len(sq->roc_nix) * 8 * 1E5); 57105d727e8SNithin Dabilpuram /* Wait for worst case scenario of this SQ being last priority 57205d727e8SNithin Dabilpuram * and so have to wait for all other SQ's drain out by their own. 57305d727e8SNithin Dabilpuram */ 57405d727e8SNithin Dabilpuram timeout = timeout * nix->nb_tx_queues; 57505d727e8SNithin Dabilpuram timeout = timeout / nix->tm_rate_min; 57605d727e8SNithin Dabilpuram if (!timeout) 57705d727e8SNithin Dabilpuram timeout = 10000; 57805d727e8SNithin Dabilpuram 57905d727e8SNithin Dabilpuram wdata = ((uint64_t)qid << 32); 58005d727e8SNithin Dabilpuram regaddr = (int64_t *)(nix->base + NIX_LF_SQ_OP_STATUS); 58105d727e8SNithin Dabilpuram val = roc_atomic64_add_nosync(wdata, regaddr); 58205d727e8SNithin Dabilpuram 58305d727e8SNithin Dabilpuram /* Spin multiple iterations as "sq->fc_cache_pkts" can still 58405d727e8SNithin Dabilpuram * have space to send pkts even though fc_mem is disabled 58505d727e8SNithin Dabilpuram */ 58605d727e8SNithin Dabilpuram 58705d727e8SNithin Dabilpuram while (true) { 58805d727e8SNithin Dabilpuram prev = val; 58905d727e8SNithin Dabilpuram plt_delay_us(10); 59005d727e8SNithin Dabilpuram val = roc_atomic64_add_nosync(wdata, regaddr); 59105d727e8SNithin Dabilpuram /* Continue on error */ 59205d727e8SNithin Dabilpuram if (val & BIT_ULL(63)) 59305d727e8SNithin Dabilpuram continue; 59405d727e8SNithin Dabilpuram 59505d727e8SNithin Dabilpuram if (prev != val) 59605d727e8SNithin Dabilpuram continue; 59705d727e8SNithin Dabilpuram 59805d727e8SNithin Dabilpuram sqb_cnt = val & 0xFFFF; 59905d727e8SNithin Dabilpuram head_off = (val >> 20) & 0x3F; 60005d727e8SNithin Dabilpuram tail_off = (val >> 28) & 0x3F; 60105d727e8SNithin Dabilpuram 60205d727e8SNithin Dabilpuram /* SQ reached quiescent state */ 60305d727e8SNithin Dabilpuram if (sqb_cnt <= 1 && head_off == tail_off && 6041134d758SPavan Nikhilesh (*(volatile uint64_t *)sq->fc == sq->aura_sqb_bufs)) { 60505d727e8SNithin Dabilpuram break; 60605d727e8SNithin Dabilpuram } 60705d727e8SNithin Dabilpuram 60805d727e8SNithin Dabilpuram /* Timeout */ 60905d727e8SNithin Dabilpuram if (!timeout) 61005d727e8SNithin Dabilpuram goto exit; 61105d727e8SNithin Dabilpuram timeout--; 61205d727e8SNithin Dabilpuram } 61305d727e8SNithin Dabilpuram 61405d727e8SNithin Dabilpuram return 0; 61505d727e8SNithin Dabilpuram exit: 61605d727e8SNithin Dabilpuram return -EFAULT; 61705d727e8SNithin Dabilpuram } 61805d727e8SNithin Dabilpuram 619b7c31b6dSSatha Rao void 620b7c31b6dSSatha Rao nix_tm_sq_free_sqe_buffer(uint64_t *sqe, int head_off, int end_off, int instr_sz) 621b7c31b6dSSatha Rao { 622b7c31b6dSSatha Rao int i, j, inc = (8 * (0x2 >> instr_sz)), segs; 623b7c31b6dSSatha Rao struct nix_send_hdr_s *send_hdr; 624b7c31b6dSSatha Rao uint64_t *ptr, aura_handle; 625b7c31b6dSSatha Rao struct idev_cfg *idev; 626b7c31b6dSSatha Rao 627b7c31b6dSSatha Rao if (!sqe) 628b7c31b6dSSatha Rao return; 629b7c31b6dSSatha Rao 630b7c31b6dSSatha Rao idev = idev_get_cfg(); 631b7c31b6dSSatha Rao if (idev == NULL) 632b7c31b6dSSatha Rao return; 633b7c31b6dSSatha Rao 634b7c31b6dSSatha Rao ptr = sqe + (head_off * inc); 635b7c31b6dSSatha Rao for (i = head_off; i < end_off; i++) { 636b7c31b6dSSatha Rao ptr = sqe + (i * inc); 637b7c31b6dSSatha Rao send_hdr = (struct nix_send_hdr_s *)(ptr); 638b7c31b6dSSatha Rao aura_handle = roc_npa_aura_handle_gen(send_hdr->w0.aura, idev->npa->base); 639b7c31b6dSSatha Rao ptr += 2; 640b7c31b6dSSatha Rao if (((*ptr >> 60) & 0xF) == NIX_SUBDC_EXT) 641b7c31b6dSSatha Rao ptr += 2; 642b7c31b6dSSatha Rao if (((*ptr >> 60) & 0xF) == NIX_SUBDC_AGE_AND_STATS) 643b7c31b6dSSatha Rao ptr += 2; 644b7c31b6dSSatha Rao if (((*ptr >> 60) & 0xF) == NIX_SUBDC_JUMP) { 645b7c31b6dSSatha Rao ptr += 1; 646b7c31b6dSSatha Rao ptr = (uint64_t *)*ptr; 647b7c31b6dSSatha Rao } 648b7c31b6dSSatha Rao if (((*ptr >> 60) & 0xF) == NIX_SUBDC_CRC) 649b7c31b6dSSatha Rao ptr += 2; 650b7c31b6dSSatha Rao /* We are not parsing immediate send descriptor */ 651b7c31b6dSSatha Rao if (((*ptr >> 60) & 0xF) == NIX_SUBDC_IMM) 652b7c31b6dSSatha Rao continue; 653b7c31b6dSSatha Rao while (1) { 654b7c31b6dSSatha Rao if (((*ptr >> 60) & 0xF) == NIX_SUBDC_SG) { 655b7c31b6dSSatha Rao segs = (*ptr >> 48) & 0x3; 656b7c31b6dSSatha Rao ptr += 1; 657b7c31b6dSSatha Rao for (j = 0; j < segs; j++) { 658b7c31b6dSSatha Rao roc_npa_aura_op_free(aura_handle, 0, *ptr); 659b7c31b6dSSatha Rao ptr += 1; 660b7c31b6dSSatha Rao } 661b7c31b6dSSatha Rao if (segs == 2) 662b7c31b6dSSatha Rao ptr += 1; 663b7c31b6dSSatha Rao } else if (((*ptr >> 60) & 0xF) == NIX_SUBDC_SG2) { 664b7c31b6dSSatha Rao uint64_t aura = (*ptr >> 16) & 0xFFFFF; 665b7c31b6dSSatha Rao 666b7c31b6dSSatha Rao aura = roc_npa_aura_handle_gen(aura, idev->npa->base); 667b7c31b6dSSatha Rao ptr += 1; 668b7c31b6dSSatha Rao roc_npa_aura_op_free(aura, 0, *ptr); 669b7c31b6dSSatha Rao ptr += 1; 670b7c31b6dSSatha Rao } else 671b7c31b6dSSatha Rao break; 672b7c31b6dSSatha Rao } 673b7c31b6dSSatha Rao } 674b7c31b6dSSatha Rao } 675b7c31b6dSSatha Rao 676b7c31b6dSSatha Rao int 677b7c31b6dSSatha Rao roc_nix_tm_sq_free_pending_sqe(struct nix *nix, int q) 678b7c31b6dSSatha Rao { 679b7c31b6dSSatha Rao int head_off, count, rc = 0, tail_off; 680b7c31b6dSSatha Rao struct roc_nix_sq *sq = nix->sqs[q]; 681b7c31b6dSSatha Rao void *sqb_buf, *dat, *tail_sqb; 682b7c31b6dSSatha Rao struct dev *dev = &nix->dev; 683b7c31b6dSSatha Rao struct ndc_sync_op *ndc_req; 684b7c31b6dSSatha Rao uint16_t sqes_per_sqb; 685b7c31b6dSSatha Rao struct mbox *mbox; 686b7c31b6dSSatha Rao 687b7c31b6dSSatha Rao mbox = dev->mbox; 688b7c31b6dSSatha Rao /* Sync NDC-NIX-TX for LF */ 68944a9307cSRakesh Kudurumalla ndc_req = mbox_alloc_msg_ndc_sync_op(mbox_get(mbox)); 69044a9307cSRakesh Kudurumalla if (ndc_req == NULL) { 69144a9307cSRakesh Kudurumalla mbox_put(mbox); 692b7c31b6dSSatha Rao return -EFAULT; 69344a9307cSRakesh Kudurumalla } 694b7c31b6dSSatha Rao 695b7c31b6dSSatha Rao ndc_req->nix_lf_tx_sync = 1; 696b7c31b6dSSatha Rao if (mbox_process(mbox)) 697b7c31b6dSSatha Rao rc |= NIX_ERR_NDC_SYNC; 69844a9307cSRakesh Kudurumalla mbox_put(mbox); 699b7c31b6dSSatha Rao 700b7c31b6dSSatha Rao if (rc) 701b7c31b6dSSatha Rao plt_err("NDC_SYNC failed rc %d", rc); 702b7c31b6dSSatha Rao 703b7c31b6dSSatha Rao rc = nix_q_ctx_get(dev, NIX_AQ_CTYPE_SQ, q, (void *)&dat); 704b7c31b6dSSatha Rao 705b7c31b6dSSatha Rao if (roc_model_is_cn9k()) { 706b7c31b6dSSatha Rao volatile struct nix_sq_ctx_s *ctx = (struct nix_sq_ctx_s *)dat; 707b7c31b6dSSatha Rao 708b7c31b6dSSatha Rao /* We will cleanup SQE buffers only when we received MNQ interrupt */ 709b7c31b6dSSatha Rao if (!ctx->mnq_dis) 710b7c31b6dSSatha Rao return -EFAULT; 711b7c31b6dSSatha Rao 712b7c31b6dSSatha Rao count = ctx->sqb_count; 713b7c31b6dSSatha Rao sqb_buf = (void *)ctx->head_sqb; 714b7c31b6dSSatha Rao tail_sqb = (void *)ctx->tail_sqb; 715b7c31b6dSSatha Rao head_off = ctx->head_offset; 716b7c31b6dSSatha Rao tail_off = ctx->tail_offset; 717b7c31b6dSSatha Rao } else { 718b7c31b6dSSatha Rao volatile struct nix_cn10k_sq_ctx_s *ctx = (struct nix_cn10k_sq_ctx_s *)dat; 719b7c31b6dSSatha Rao 720b7c31b6dSSatha Rao /* We will cleanup SQE buffers only when we received MNQ interrupt */ 721b7c31b6dSSatha Rao if (!ctx->mnq_dis) 722b7c31b6dSSatha Rao return -EFAULT; 723b7c31b6dSSatha Rao 724b7c31b6dSSatha Rao count = ctx->sqb_count; 725b7c31b6dSSatha Rao /* Free SQB's that are used */ 726b7c31b6dSSatha Rao sqb_buf = (void *)ctx->head_sqb; 727b7c31b6dSSatha Rao tail_sqb = (void *)ctx->tail_sqb; 728b7c31b6dSSatha Rao head_off = ctx->head_offset; 729b7c31b6dSSatha Rao tail_off = ctx->tail_offset; 730b7c31b6dSSatha Rao } 731b7c31b6dSSatha Rao sqes_per_sqb = 1 << sq->sqes_per_sqb_log2; 732b7c31b6dSSatha Rao /* Free SQB's that are used */ 733b7c31b6dSSatha Rao while (count) { 734b7c31b6dSSatha Rao void *next_sqb; 735b7c31b6dSSatha Rao 736b7c31b6dSSatha Rao if (sqb_buf == tail_sqb) 737b7c31b6dSSatha Rao nix_tm_sq_free_sqe_buffer(sqb_buf, head_off, tail_off, sq->max_sqe_sz); 738b7c31b6dSSatha Rao else 739b7c31b6dSSatha Rao nix_tm_sq_free_sqe_buffer(sqb_buf, head_off, (sqes_per_sqb - 1), 740b7c31b6dSSatha Rao sq->max_sqe_sz); 741b7c31b6dSSatha Rao next_sqb = *(void **)((uint64_t *)sqb_buf + 742b7c31b6dSSatha Rao (uint32_t)((sqes_per_sqb - 1) * (0x2 >> sq->max_sqe_sz) * 8)); 743b7c31b6dSSatha Rao roc_npa_aura_op_free(sq->aura_handle, 1, (uint64_t)sqb_buf); 744b7c31b6dSSatha Rao sqb_buf = next_sqb; 745b7c31b6dSSatha Rao head_off = 0; 746b7c31b6dSSatha Rao count--; 747b7c31b6dSSatha Rao } 748b7c31b6dSSatha Rao 749b7c31b6dSSatha Rao return 0; 750b7c31b6dSSatha Rao } 751b7c31b6dSSatha Rao 75209c3b99cSSatha Rao static inline int 75309c3b99cSSatha Rao nix_tm_sdp_sq_drop_pkts(struct roc_nix *roc_nix, struct roc_nix_sq *sq) 75409c3b99cSSatha Rao { 75509c3b99cSSatha Rao struct nix *nix = roc_nix_to_nix_priv(roc_nix); 75609c3b99cSSatha Rao struct mbox *mbox = mbox_get((&nix->dev)->mbox); 75709c3b99cSSatha Rao struct nix_txschq_config *req = NULL, *rsp; 75809c3b99cSSatha Rao enum roc_nix_tm_tree tree = nix->tm_tree; 75909c3b99cSSatha Rao int rc = 0, qid = sq->qid; 76009c3b99cSSatha Rao struct nix_tm_node *node; 76109c3b99cSSatha Rao uint64_t regval; 76209c3b99cSSatha Rao 76309c3b99cSSatha Rao /* Find the node for this SQ */ 76409c3b99cSSatha Rao node = nix_tm_node_search(nix, qid, tree); 76509c3b99cSSatha Rao while (node) { 76609c3b99cSSatha Rao if (node->hw_lvl != NIX_TXSCH_LVL_TL4) { 76709c3b99cSSatha Rao node = node->parent; 76809c3b99cSSatha Rao continue; 76909c3b99cSSatha Rao } 77009c3b99cSSatha Rao break; 77109c3b99cSSatha Rao } 77209c3b99cSSatha Rao if (!node) { 77309c3b99cSSatha Rao plt_err("Invalid node/state for sq %u", qid); 77409c3b99cSSatha Rao return -EFAULT; 77509c3b99cSSatha Rao } 77609c3b99cSSatha Rao 77709c3b99cSSatha Rao /* Get present link config */ 77809c3b99cSSatha Rao req = mbox_alloc_msg_nix_txschq_cfg(mbox); 77909c3b99cSSatha Rao req->read = 1; 78009c3b99cSSatha Rao req->lvl = NIX_TXSCH_LVL_TL4; 78109c3b99cSSatha Rao req->reg[0] = NIX_AF_TL4X_SDP_LINK_CFG(node->hw_id); 78209c3b99cSSatha Rao req->num_regs = 1; 78309c3b99cSSatha Rao rc = mbox_process_msg(mbox, (void **)&rsp); 78409c3b99cSSatha Rao if (rc || rsp->num_regs != 1) 78509c3b99cSSatha Rao goto err; 78609c3b99cSSatha Rao regval = rsp->regval[0]; 78709c3b99cSSatha Rao /* Disable BP_ENA in SDP link config */ 78809c3b99cSSatha Rao req = mbox_alloc_msg_nix_txschq_cfg(mbox); 78909c3b99cSSatha Rao req->lvl = NIX_TXSCH_LVL_TL4; 79009c3b99cSSatha Rao req->reg[0] = NIX_AF_TL4X_SDP_LINK_CFG(node->hw_id); 79109c3b99cSSatha Rao req->regval[0] = 0x0ull; 79209c3b99cSSatha Rao req->regval_mask[0] = ~(BIT_ULL(13)); 79309c3b99cSSatha Rao req->num_regs = 1; 79409c3b99cSSatha Rao rc = mbox_process(mbox); 79509c3b99cSSatha Rao if (rc) 79609c3b99cSSatha Rao goto err; 79709c3b99cSSatha Rao mbox_put(mbox); 79809c3b99cSSatha Rao /* Flush SQ to drop all packets */ 79909c3b99cSSatha Rao rc = roc_nix_tm_sq_flush_spin(sq); 80009c3b99cSSatha Rao if (rc) 80109c3b99cSSatha Rao plt_nix_dbg("SQ flush failed with link reset config rc %d", rc); 80209c3b99cSSatha Rao mbox = mbox_get((&nix->dev)->mbox); 80309c3b99cSSatha Rao /* Restore link config */ 80409c3b99cSSatha Rao req = mbox_alloc_msg_nix_txschq_cfg(mbox); 80509c3b99cSSatha Rao req->reg[0] = NIX_AF_TL4X_SDP_LINK_CFG(node->hw_id); 80609c3b99cSSatha Rao req->lvl = NIX_TXSCH_LVL_TL4; 80709c3b99cSSatha Rao req->regval[0] = regval; 80809c3b99cSSatha Rao req->regval_mask[0] = ~(BIT_ULL(13) | BIT_ULL(12) | GENMASK_ULL(7, 0)); 80909c3b99cSSatha Rao req->num_regs = 1; 81009c3b99cSSatha Rao rc = mbox_process(mbox); 81109c3b99cSSatha Rao err: 81209c3b99cSSatha Rao mbox_put(mbox); 81309c3b99cSSatha Rao return rc; 81409c3b99cSSatha Rao } 81509c3b99cSSatha Rao 81605d727e8SNithin Dabilpuram /* Flush and disable tx queue and its parent SMQ */ 81705d727e8SNithin Dabilpuram int 81805d727e8SNithin Dabilpuram nix_tm_sq_flush_pre(struct roc_nix_sq *sq) 81905d727e8SNithin Dabilpuram { 82005d727e8SNithin Dabilpuram struct roc_nix *roc_nix = sq->roc_nix; 82105d727e8SNithin Dabilpuram struct nix_tm_node *node, *sibling; 82205d727e8SNithin Dabilpuram struct nix_tm_node_list *list; 82305d727e8SNithin Dabilpuram enum roc_nix_tm_tree tree; 824e746aec1SSatha Rao struct msg_req *req; 82505d727e8SNithin Dabilpuram struct mbox *mbox; 82605d727e8SNithin Dabilpuram struct nix *nix; 82705d727e8SNithin Dabilpuram uint16_t qid; 82805d727e8SNithin Dabilpuram int rc; 82905d727e8SNithin Dabilpuram 83005d727e8SNithin Dabilpuram nix = roc_nix_to_nix_priv(roc_nix); 83105d727e8SNithin Dabilpuram 83205d727e8SNithin Dabilpuram /* Need not do anything if tree is in disabled state */ 83305d727e8SNithin Dabilpuram if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA)) 83405d727e8SNithin Dabilpuram return 0; 83505d727e8SNithin Dabilpuram 83605d727e8SNithin Dabilpuram mbox = (&nix->dev)->mbox; 83705d727e8SNithin Dabilpuram qid = sq->qid; 83805d727e8SNithin Dabilpuram 83905d727e8SNithin Dabilpuram tree = nix->tm_tree; 84005d727e8SNithin Dabilpuram list = nix_tm_node_list(nix, tree); 84105d727e8SNithin Dabilpuram 84205d727e8SNithin Dabilpuram /* Find the node for this SQ */ 84305d727e8SNithin Dabilpuram node = nix_tm_node_search(nix, qid, tree); 844b7c31b6dSSatha Rao if (!node) { 84505d727e8SNithin Dabilpuram plt_err("Invalid node/state for sq %u", qid); 84605d727e8SNithin Dabilpuram return -EFAULT; 84705d727e8SNithin Dabilpuram } 84805d727e8SNithin Dabilpuram 84905d727e8SNithin Dabilpuram /* Enable CGX RXTX to drain pkts */ 85005d727e8SNithin Dabilpuram if (!roc_nix->io_enabled) { 85105d727e8SNithin Dabilpuram /* Though it enables both RX MCAM Entries and CGX Link 85205d727e8SNithin Dabilpuram * we assume all the rx queues are stopped way back. 85305d727e8SNithin Dabilpuram */ 85444a9307cSRakesh Kudurumalla mbox_alloc_msg_nix_lf_start_rx(mbox_get(mbox)); 85505d727e8SNithin Dabilpuram rc = mbox_process(mbox); 85605d727e8SNithin Dabilpuram if (rc) { 85744a9307cSRakesh Kudurumalla mbox_put(mbox); 85805d727e8SNithin Dabilpuram plt_err("cgx start failed, rc=%d", rc); 85905d727e8SNithin Dabilpuram return rc; 86005d727e8SNithin Dabilpuram } 86144a9307cSRakesh Kudurumalla mbox_put(mbox); 86205d727e8SNithin Dabilpuram } 86305d727e8SNithin Dabilpuram 86458debb81SNithin Dabilpuram /* Disable backpressure */ 86578fb5efeSNithin Dabilpuram rc = nix_tm_bp_config_set(roc_nix, sq->qid, 0, false); 86658debb81SNithin Dabilpuram if (rc) { 86758debb81SNithin Dabilpuram plt_err("Failed to disable backpressure for flush, rc=%d", rc); 86858debb81SNithin Dabilpuram return rc; 86958debb81SNithin Dabilpuram } 87058debb81SNithin Dabilpuram 87105d727e8SNithin Dabilpuram /* Disable smq xoff for case it was enabled earlier */ 87205d727e8SNithin Dabilpuram rc = nix_tm_smq_xoff(nix, node->parent, false); 87305d727e8SNithin Dabilpuram if (rc) { 87405d727e8SNithin Dabilpuram plt_err("Failed to enable smq %u, rc=%d", node->parent->hw_id, 87505d727e8SNithin Dabilpuram rc); 87605d727e8SNithin Dabilpuram return rc; 87705d727e8SNithin Dabilpuram } 87805d727e8SNithin Dabilpuram 87905d727e8SNithin Dabilpuram /* As per HRM, to disable an SQ, all other SQ's 88005d727e8SNithin Dabilpuram * that feed to same SMQ must be paused before SMQ flush. 88105d727e8SNithin Dabilpuram */ 88205d727e8SNithin Dabilpuram TAILQ_FOREACH(sibling, list, node) { 88305d727e8SNithin Dabilpuram if (sibling->parent != node->parent) 88405d727e8SNithin Dabilpuram continue; 88505d727e8SNithin Dabilpuram if (!(sibling->flags & NIX_TM_NODE_ENABLED)) 88605d727e8SNithin Dabilpuram continue; 88705d727e8SNithin Dabilpuram 88805d727e8SNithin Dabilpuram qid = sibling->id; 88905d727e8SNithin Dabilpuram sq = nix->sqs[qid]; 89005d727e8SNithin Dabilpuram if (!sq) 89105d727e8SNithin Dabilpuram continue; 89205d727e8SNithin Dabilpuram 893f6e0d835SRakesh Kudurumalla if (sq->enable) { 89405d727e8SNithin Dabilpuram rc = roc_nix_tm_sq_aura_fc(sq, false); 89505d727e8SNithin Dabilpuram if (rc) { 89605d727e8SNithin Dabilpuram plt_err("Failed to disable sqb aura fc, rc=%d", rc); 89705d727e8SNithin Dabilpuram goto cleanup; 89805d727e8SNithin Dabilpuram } 899f6e0d835SRakesh Kudurumalla } 90005d727e8SNithin Dabilpuram 90105d727e8SNithin Dabilpuram /* Wait for sq entries to be flushed */ 90205d727e8SNithin Dabilpuram rc = roc_nix_tm_sq_flush_spin(sq); 90305d727e8SNithin Dabilpuram if (rc) { 90409c3b99cSSatha Rao if (nix->sdp_link) 90509c3b99cSSatha Rao rc = nix_tm_sdp_sq_drop_pkts(roc_nix, sq); 90609c3b99cSSatha Rao else 907b7c31b6dSSatha Rao rc = roc_nix_tm_sq_free_pending_sqe(nix, sq->qid); 908b7c31b6dSSatha Rao if (rc) { 90909c3b99cSSatha Rao roc_nix_tm_dump(sq->roc_nix, NULL); 91009c3b99cSSatha Rao roc_nix_queues_ctx_dump(sq->roc_nix, NULL); 911f665790aSDavid Marchand plt_err("Failed to drain sq %u, rc=%d", sq->qid, rc); 91205d727e8SNithin Dabilpuram return rc; 91305d727e8SNithin Dabilpuram } 914b7c31b6dSSatha Rao /* Freed all pending SQEs for this SQ, so disable this node */ 915b7c31b6dSSatha Rao sibling->flags &= ~NIX_TM_NODE_ENABLED; 916b7c31b6dSSatha Rao } 91705d727e8SNithin Dabilpuram } 91805d727e8SNithin Dabilpuram 91905d727e8SNithin Dabilpuram node->flags &= ~NIX_TM_NODE_ENABLED; 92005d727e8SNithin Dabilpuram 92105d727e8SNithin Dabilpuram /* Disable and flush */ 92205d727e8SNithin Dabilpuram rc = nix_tm_smq_xoff(nix, node->parent, true); 92305d727e8SNithin Dabilpuram if (rc) { 92405d727e8SNithin Dabilpuram plt_err("Failed to disable smq %u, rc=%d", node->parent->hw_id, 92505d727e8SNithin Dabilpuram rc); 92605d727e8SNithin Dabilpuram goto cleanup; 92705d727e8SNithin Dabilpuram } 928e746aec1SSatha Rao 92944a9307cSRakesh Kudurumalla req = mbox_alloc_msg_nix_rx_sw_sync(mbox_get(mbox)); 93044a9307cSRakesh Kudurumalla if (!req) { 93144a9307cSRakesh Kudurumalla mbox_put(mbox); 932e746aec1SSatha Rao return -ENOSPC; 93344a9307cSRakesh Kudurumalla } 934e746aec1SSatha Rao 935e746aec1SSatha Rao rc = mbox_process(mbox); 93644a9307cSRakesh Kudurumalla mbox_put(mbox); 93705d727e8SNithin Dabilpuram cleanup: 93805d727e8SNithin Dabilpuram /* Restore cgx state */ 93905d727e8SNithin Dabilpuram if (!roc_nix->io_enabled) { 94044a9307cSRakesh Kudurumalla mbox_alloc_msg_nix_lf_stop_rx(mbox_get(mbox)); 94105d727e8SNithin Dabilpuram rc |= mbox_process(mbox); 94244a9307cSRakesh Kudurumalla mbox_put(mbox); 94305d727e8SNithin Dabilpuram } 94405d727e8SNithin Dabilpuram 94505d727e8SNithin Dabilpuram return rc; 94605d727e8SNithin Dabilpuram } 94705d727e8SNithin Dabilpuram 94805d727e8SNithin Dabilpuram int 94905d727e8SNithin Dabilpuram nix_tm_sq_flush_post(struct roc_nix_sq *sq) 95005d727e8SNithin Dabilpuram { 95105d727e8SNithin Dabilpuram struct roc_nix *roc_nix = sq->roc_nix; 95205d727e8SNithin Dabilpuram struct nix_tm_node *node, *sibling; 95305d727e8SNithin Dabilpuram struct nix_tm_node_list *list; 95405d727e8SNithin Dabilpuram enum roc_nix_tm_tree tree; 95505d727e8SNithin Dabilpuram struct roc_nix_sq *s_sq; 95605d727e8SNithin Dabilpuram bool once = false; 95705d727e8SNithin Dabilpuram uint16_t qid, s_qid; 95805d727e8SNithin Dabilpuram struct nix *nix; 95905d727e8SNithin Dabilpuram int rc; 96005d727e8SNithin Dabilpuram 96105d727e8SNithin Dabilpuram nix = roc_nix_to_nix_priv(roc_nix); 96205d727e8SNithin Dabilpuram 96305d727e8SNithin Dabilpuram /* Need not do anything if tree is in disabled state */ 96405d727e8SNithin Dabilpuram if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA)) 96505d727e8SNithin Dabilpuram return 0; 96605d727e8SNithin Dabilpuram 96705d727e8SNithin Dabilpuram qid = sq->qid; 96805d727e8SNithin Dabilpuram tree = nix->tm_tree; 96905d727e8SNithin Dabilpuram list = nix_tm_node_list(nix, tree); 97005d727e8SNithin Dabilpuram 97105d727e8SNithin Dabilpuram /* Find the node for this SQ */ 97205d727e8SNithin Dabilpuram node = nix_tm_node_search(nix, qid, tree); 97305d727e8SNithin Dabilpuram if (!node) { 97405d727e8SNithin Dabilpuram plt_err("Invalid node for sq %u", qid); 97505d727e8SNithin Dabilpuram return -EFAULT; 97605d727e8SNithin Dabilpuram } 97705d727e8SNithin Dabilpuram 97805d727e8SNithin Dabilpuram /* Enable all the siblings back */ 97905d727e8SNithin Dabilpuram TAILQ_FOREACH(sibling, list, node) { 98005d727e8SNithin Dabilpuram if (sibling->parent != node->parent) 98105d727e8SNithin Dabilpuram continue; 98205d727e8SNithin Dabilpuram 98305d727e8SNithin Dabilpuram if (sibling->id == qid) 98405d727e8SNithin Dabilpuram continue; 98505d727e8SNithin Dabilpuram 98605d727e8SNithin Dabilpuram if (!(sibling->flags & NIX_TM_NODE_ENABLED)) 98705d727e8SNithin Dabilpuram continue; 98805d727e8SNithin Dabilpuram 98905d727e8SNithin Dabilpuram s_qid = sibling->id; 99005d727e8SNithin Dabilpuram s_sq = nix->sqs[s_qid]; 99105d727e8SNithin Dabilpuram if (!s_sq) 99205d727e8SNithin Dabilpuram continue; 99305d727e8SNithin Dabilpuram 99405d727e8SNithin Dabilpuram if (!once) { 99505d727e8SNithin Dabilpuram /* Enable back if any SQ is still present */ 99605d727e8SNithin Dabilpuram rc = nix_tm_smq_xoff(nix, node->parent, false); 99705d727e8SNithin Dabilpuram if (rc) { 99805d727e8SNithin Dabilpuram plt_err("Failed to enable smq %u, rc=%d", 99905d727e8SNithin Dabilpuram node->parent->hw_id, rc); 100005d727e8SNithin Dabilpuram return rc; 100105d727e8SNithin Dabilpuram } 100205d727e8SNithin Dabilpuram once = true; 100305d727e8SNithin Dabilpuram } 100405d727e8SNithin Dabilpuram 1005f6e0d835SRakesh Kudurumalla if (s_sq->enable) { 100605d727e8SNithin Dabilpuram rc = roc_nix_tm_sq_aura_fc(s_sq, true); 100705d727e8SNithin Dabilpuram if (rc) { 100805d727e8SNithin Dabilpuram plt_err("Failed to enable sqb aura fc, rc=%d", rc); 100905d727e8SNithin Dabilpuram return rc; 101005d727e8SNithin Dabilpuram } 101105d727e8SNithin Dabilpuram } 1012f6e0d835SRakesh Kudurumalla } 101305d727e8SNithin Dabilpuram 101405d727e8SNithin Dabilpuram return 0; 101505d727e8SNithin Dabilpuram } 101605d727e8SNithin Dabilpuram 101705d727e8SNithin Dabilpuram int 10180885429cSNithin Dabilpuram nix_tm_sq_sched_conf(struct nix *nix, struct nix_tm_node *node, 10190885429cSNithin Dabilpuram bool rr_quantum_only) 10200885429cSNithin Dabilpuram { 102144a9307cSRakesh Kudurumalla struct mbox *mbox = mbox_get((&nix->dev)->mbox); 10220885429cSNithin Dabilpuram uint16_t qid = node->id, smq; 10230885429cSNithin Dabilpuram uint64_t rr_quantum; 10240885429cSNithin Dabilpuram int rc; 10250885429cSNithin Dabilpuram 10260885429cSNithin Dabilpuram smq = node->parent->hw_id; 10270885429cSNithin Dabilpuram rr_quantum = nix_tm_weight_to_rr_quantum(node->weight); 10280885429cSNithin Dabilpuram 10290885429cSNithin Dabilpuram if (rr_quantum_only) 10300885429cSNithin Dabilpuram plt_tm_dbg("Update sq(%u) rr_quantum 0x%" PRIx64, qid, 10310885429cSNithin Dabilpuram rr_quantum); 10320885429cSNithin Dabilpuram else 10330885429cSNithin Dabilpuram plt_tm_dbg("Enabling sq(%u)->smq(%u), rr_quantum 0x%" PRIx64, 10340885429cSNithin Dabilpuram qid, smq, rr_quantum); 10350885429cSNithin Dabilpuram 103644a9307cSRakesh Kudurumalla if (qid > nix->nb_tx_queues) { 103744a9307cSRakesh Kudurumalla rc = -EFAULT; 103844a9307cSRakesh Kudurumalla goto exit; 103944a9307cSRakesh Kudurumalla } 10400885429cSNithin Dabilpuram 10410885429cSNithin Dabilpuram if (roc_model_is_cn9k()) { 10420885429cSNithin Dabilpuram struct nix_aq_enq_req *aq; 10430885429cSNithin Dabilpuram 10440885429cSNithin Dabilpuram aq = mbox_alloc_msg_nix_aq_enq(mbox); 104544a9307cSRakesh Kudurumalla if (!aq) { 104644a9307cSRakesh Kudurumalla rc = -ENOSPC; 104744a9307cSRakesh Kudurumalla goto exit; 104844a9307cSRakesh Kudurumalla } 1049da718c19SNithin Dabilpuram 10500885429cSNithin Dabilpuram aq->qidx = qid; 10510885429cSNithin Dabilpuram aq->ctype = NIX_AQ_CTYPE_SQ; 10520885429cSNithin Dabilpuram aq->op = NIX_AQ_INSTOP_WRITE; 10530885429cSNithin Dabilpuram 10540885429cSNithin Dabilpuram /* smq update only when needed */ 10550885429cSNithin Dabilpuram if (!rr_quantum_only) { 10560885429cSNithin Dabilpuram aq->sq.smq = smq; 10570885429cSNithin Dabilpuram aq->sq_mask.smq = ~aq->sq_mask.smq; 10580885429cSNithin Dabilpuram } 10590885429cSNithin Dabilpuram aq->sq.smq_rr_quantum = rr_quantum; 10600885429cSNithin Dabilpuram aq->sq_mask.smq_rr_quantum = ~aq->sq_mask.smq_rr_quantum; 1061*4785c406SSatha Rao } else if (roc_model_is_cn10k()) { 10620885429cSNithin Dabilpuram struct nix_cn10k_aq_enq_req *aq; 10630885429cSNithin Dabilpuram 10640885429cSNithin Dabilpuram aq = mbox_alloc_msg_nix_cn10k_aq_enq(mbox); 106544a9307cSRakesh Kudurumalla if (!aq) { 106644a9307cSRakesh Kudurumalla rc = -ENOSPC; 106744a9307cSRakesh Kudurumalla goto exit; 106844a9307cSRakesh Kudurumalla } 1069da718c19SNithin Dabilpuram 10700885429cSNithin Dabilpuram aq->qidx = qid; 10710885429cSNithin Dabilpuram aq->ctype = NIX_AQ_CTYPE_SQ; 10720885429cSNithin Dabilpuram aq->op = NIX_AQ_INSTOP_WRITE; 10730885429cSNithin Dabilpuram 10740885429cSNithin Dabilpuram /* smq update only when needed */ 10750885429cSNithin Dabilpuram if (!rr_quantum_only) { 10760885429cSNithin Dabilpuram aq->sq.smq = smq; 10770885429cSNithin Dabilpuram aq->sq_mask.smq = ~aq->sq_mask.smq; 10780885429cSNithin Dabilpuram } 10790885429cSNithin Dabilpuram aq->sq.smq_rr_weight = rr_quantum; 10800885429cSNithin Dabilpuram aq->sq_mask.smq_rr_weight = ~aq->sq_mask.smq_rr_weight; 1081*4785c406SSatha Rao } else { 1082*4785c406SSatha Rao struct nix_cn20k_aq_enq_req *aq; 1083*4785c406SSatha Rao 1084*4785c406SSatha Rao aq = mbox_alloc_msg_nix_cn20k_aq_enq(mbox); 1085*4785c406SSatha Rao if (!aq) { 1086*4785c406SSatha Rao rc = -ENOSPC; 1087*4785c406SSatha Rao goto exit; 1088*4785c406SSatha Rao } 1089*4785c406SSatha Rao 1090*4785c406SSatha Rao aq->qidx = qid; 1091*4785c406SSatha Rao aq->ctype = NIX_AQ_CTYPE_SQ; 1092*4785c406SSatha Rao aq->op = NIX_AQ_INSTOP_WRITE; 1093*4785c406SSatha Rao 1094*4785c406SSatha Rao /* smq update only when needed */ 1095*4785c406SSatha Rao if (!rr_quantum_only) { 1096*4785c406SSatha Rao aq->sq.smq = smq; 1097*4785c406SSatha Rao aq->sq_mask.smq = ~aq->sq_mask.smq; 1098*4785c406SSatha Rao } 1099*4785c406SSatha Rao aq->sq.smq_rr_weight = rr_quantum; 1100*4785c406SSatha Rao aq->sq_mask.smq_rr_weight = ~aq->sq_mask.smq_rr_weight; 11010885429cSNithin Dabilpuram } 11020885429cSNithin Dabilpuram 11030885429cSNithin Dabilpuram rc = mbox_process(mbox); 11040885429cSNithin Dabilpuram if (rc) 11050885429cSNithin Dabilpuram plt_err("Failed to set smq, rc=%d", rc); 110644a9307cSRakesh Kudurumalla exit: 110744a9307cSRakesh Kudurumalla mbox_put(mbox); 11080885429cSNithin Dabilpuram return rc; 11090885429cSNithin Dabilpuram } 11100885429cSNithin Dabilpuram 11110885429cSNithin Dabilpuram int 1112df405df9SNithin Dabilpuram nix_tm_release_resources(struct nix *nix, uint8_t hw_lvl, bool contig, 1113df405df9SNithin Dabilpuram bool above_thresh) 1114df405df9SNithin Dabilpuram { 1115df405df9SNithin Dabilpuram uint16_t avail, thresh, to_free = 0, schq; 1116df405df9SNithin Dabilpuram struct mbox *mbox = (&nix->dev)->mbox; 1117df405df9SNithin Dabilpuram struct nix_txsch_free_req *req; 1118df405df9SNithin Dabilpuram struct plt_bitmap *bmp; 1119df405df9SNithin Dabilpuram uint64_t slab = 0; 1120df405df9SNithin Dabilpuram uint32_t pos = 0; 1121df405df9SNithin Dabilpuram int rc = -ENOSPC; 1122df405df9SNithin Dabilpuram 1123df405df9SNithin Dabilpuram bmp = contig ? nix->schq_contig_bmp[hw_lvl] : nix->schq_bmp[hw_lvl]; 1124df405df9SNithin Dabilpuram thresh = 1125df405df9SNithin Dabilpuram contig ? nix->contig_rsvd[hw_lvl] : nix->discontig_rsvd[hw_lvl]; 1126df405df9SNithin Dabilpuram plt_bitmap_scan_init(bmp); 1127df405df9SNithin Dabilpuram 1128df405df9SNithin Dabilpuram avail = nix_tm_resource_avail(nix, hw_lvl, contig); 1129df405df9SNithin Dabilpuram 1130df405df9SNithin Dabilpuram if (above_thresh) { 1131df405df9SNithin Dabilpuram /* Release only above threshold */ 1132df405df9SNithin Dabilpuram if (avail > thresh) 1133df405df9SNithin Dabilpuram to_free = avail - thresh; 1134df405df9SNithin Dabilpuram } else { 1135df405df9SNithin Dabilpuram /* Release everything */ 1136df405df9SNithin Dabilpuram to_free = avail; 1137df405df9SNithin Dabilpuram } 1138df405df9SNithin Dabilpuram 1139df405df9SNithin Dabilpuram /* Now release resources to AF */ 1140df405df9SNithin Dabilpuram while (to_free) { 1141df405df9SNithin Dabilpuram if (!slab && !plt_bitmap_scan(bmp, &pos, &slab)) 1142df405df9SNithin Dabilpuram break; 1143df405df9SNithin Dabilpuram 1144df405df9SNithin Dabilpuram schq = bitmap_ctzll(slab); 1145df405df9SNithin Dabilpuram slab &= ~(1ULL << schq); 1146df405df9SNithin Dabilpuram schq += pos; 1147df405df9SNithin Dabilpuram 1148df405df9SNithin Dabilpuram /* Free to AF */ 114944a9307cSRakesh Kudurumalla req = mbox_alloc_msg_nix_txsch_free(mbox_get(mbox)); 115044a9307cSRakesh Kudurumalla if (req == NULL) { 115144a9307cSRakesh Kudurumalla mbox_put(mbox); 1152df405df9SNithin Dabilpuram return rc; 115344a9307cSRakesh Kudurumalla } 1154df405df9SNithin Dabilpuram req->flags = 0; 1155df405df9SNithin Dabilpuram req->schq_lvl = hw_lvl; 1156df405df9SNithin Dabilpuram req->schq = schq; 1157df405df9SNithin Dabilpuram rc = mbox_process(mbox); 1158df405df9SNithin Dabilpuram if (rc) { 1159df405df9SNithin Dabilpuram plt_err("failed to release hwres %s(%u) rc %d", 1160df405df9SNithin Dabilpuram nix_tm_hwlvl2str(hw_lvl), schq, rc); 116144a9307cSRakesh Kudurumalla mbox_put(mbox); 1162df405df9SNithin Dabilpuram return rc; 1163df405df9SNithin Dabilpuram } 116444a9307cSRakesh Kudurumalla mbox_put(mbox); 1165df405df9SNithin Dabilpuram plt_tm_dbg("Released hwres %s(%u)", nix_tm_hwlvl2str(hw_lvl), 1166df405df9SNithin Dabilpuram schq); 1167df405df9SNithin Dabilpuram plt_bitmap_clear(bmp, schq); 1168df405df9SNithin Dabilpuram to_free--; 1169df405df9SNithin Dabilpuram } 1170df405df9SNithin Dabilpuram 1171df405df9SNithin Dabilpuram if (to_free) { 1172df405df9SNithin Dabilpuram plt_err("resource inconsistency for %s(%u)", 1173df405df9SNithin Dabilpuram nix_tm_hwlvl2str(hw_lvl), contig); 1174df405df9SNithin Dabilpuram return -EFAULT; 1175df405df9SNithin Dabilpuram } 1176df405df9SNithin Dabilpuram return 0; 1177df405df9SNithin Dabilpuram } 1178df405df9SNithin Dabilpuram 1179df405df9SNithin Dabilpuram int 1180be3009e7SNithin Dabilpuram nix_tm_free_node_resource(struct nix *nix, struct nix_tm_node *node) 1181be3009e7SNithin Dabilpuram { 118244a9307cSRakesh Kudurumalla struct mbox *mbox = mbox_get((&nix->dev)->mbox); 1183be3009e7SNithin Dabilpuram struct nix_txsch_free_req *req; 1184be3009e7SNithin Dabilpuram struct plt_bitmap *bmp; 1185be3009e7SNithin Dabilpuram uint16_t avail, hw_id; 1186be3009e7SNithin Dabilpuram uint8_t hw_lvl; 1187be3009e7SNithin Dabilpuram int rc = -ENOSPC; 1188be3009e7SNithin Dabilpuram 1189be3009e7SNithin Dabilpuram hw_lvl = node->hw_lvl; 1190be3009e7SNithin Dabilpuram hw_id = node->hw_id; 1191be3009e7SNithin Dabilpuram bmp = nix->schq_bmp[hw_lvl]; 1192be3009e7SNithin Dabilpuram /* Free specific HW resource */ 1193be3009e7SNithin Dabilpuram plt_tm_dbg("Free hwres %s(%u) lvl %u id %u (%p)", 1194be3009e7SNithin Dabilpuram nix_tm_hwlvl2str(node->hw_lvl), hw_id, node->lvl, node->id, 1195be3009e7SNithin Dabilpuram node); 1196be3009e7SNithin Dabilpuram 1197be3009e7SNithin Dabilpuram avail = nix_tm_resource_avail(nix, hw_lvl, false); 1198be3009e7SNithin Dabilpuram /* Always for now free to discontiguous queue when avail 1199be3009e7SNithin Dabilpuram * is not sufficient. 1200be3009e7SNithin Dabilpuram */ 1201be3009e7SNithin Dabilpuram if (nix->discontig_rsvd[hw_lvl] && 1202be3009e7SNithin Dabilpuram avail < nix->discontig_rsvd[hw_lvl]) { 1203be3009e7SNithin Dabilpuram PLT_ASSERT(hw_id < NIX_TM_MAX_HW_TXSCHQ); 1204be3009e7SNithin Dabilpuram PLT_ASSERT(plt_bitmap_get(bmp, hw_id) == 0); 1205be3009e7SNithin Dabilpuram plt_bitmap_set(bmp, hw_id); 1206be3009e7SNithin Dabilpuram node->hw_id = NIX_TM_HW_ID_INVALID; 1207be3009e7SNithin Dabilpuram node->flags &= ~NIX_TM_NODE_HWRES; 120844a9307cSRakesh Kudurumalla rc = 0; 120944a9307cSRakesh Kudurumalla goto exit; 1210be3009e7SNithin Dabilpuram } 1211be3009e7SNithin Dabilpuram 1212be3009e7SNithin Dabilpuram /* Free to AF */ 1213be3009e7SNithin Dabilpuram req = mbox_alloc_msg_nix_txsch_free(mbox); 1214be3009e7SNithin Dabilpuram if (req == NULL) 121544a9307cSRakesh Kudurumalla goto exit; 1216be3009e7SNithin Dabilpuram req->flags = 0; 1217be3009e7SNithin Dabilpuram req->schq_lvl = node->hw_lvl; 1218be3009e7SNithin Dabilpuram req->schq = hw_id; 1219be3009e7SNithin Dabilpuram rc = mbox_process(mbox); 1220be3009e7SNithin Dabilpuram if (rc) { 1221be3009e7SNithin Dabilpuram plt_err("failed to release hwres %s(%u) rc %d", 1222be3009e7SNithin Dabilpuram nix_tm_hwlvl2str(node->hw_lvl), hw_id, rc); 122344a9307cSRakesh Kudurumalla goto exit; 1224be3009e7SNithin Dabilpuram } 1225be3009e7SNithin Dabilpuram 1226be3009e7SNithin Dabilpuram /* Mark parent as dirty for reallocing it's children */ 1227be3009e7SNithin Dabilpuram if (node->parent) 1228be3009e7SNithin Dabilpuram node->parent->child_realloc = true; 1229be3009e7SNithin Dabilpuram 1230be3009e7SNithin Dabilpuram node->hw_id = NIX_TM_HW_ID_INVALID; 1231be3009e7SNithin Dabilpuram node->flags &= ~NIX_TM_NODE_HWRES; 1232be3009e7SNithin Dabilpuram plt_tm_dbg("Released hwres %s(%u) to af", 1233be3009e7SNithin Dabilpuram nix_tm_hwlvl2str(node->hw_lvl), hw_id); 123444a9307cSRakesh Kudurumalla rc = 0; 123544a9307cSRakesh Kudurumalla exit: 123644a9307cSRakesh Kudurumalla mbox_put(mbox); 123744a9307cSRakesh Kudurumalla return rc; 1238be3009e7SNithin Dabilpuram } 1239be3009e7SNithin Dabilpuram 1240be3009e7SNithin Dabilpuram int 1241be3009e7SNithin Dabilpuram nix_tm_node_delete(struct roc_nix *roc_nix, uint32_t node_id, 1242be3009e7SNithin Dabilpuram enum roc_nix_tm_tree tree, bool free) 1243be3009e7SNithin Dabilpuram { 1244be3009e7SNithin Dabilpuram struct nix *nix = roc_nix_to_nix_priv(roc_nix); 1245be3009e7SNithin Dabilpuram struct nix_tm_shaper_profile *profile; 1246be3009e7SNithin Dabilpuram struct nix_tm_node *node, *child; 1247be3009e7SNithin Dabilpuram struct nix_tm_node_list *list; 1248be3009e7SNithin Dabilpuram uint32_t profile_id; 1249be3009e7SNithin Dabilpuram int rc; 1250be3009e7SNithin Dabilpuram 1251be3009e7SNithin Dabilpuram plt_tm_dbg("Delete node id %u tree %u", node_id, tree); 1252be3009e7SNithin Dabilpuram 1253be3009e7SNithin Dabilpuram node = nix_tm_node_search(nix, node_id, tree); 1254be3009e7SNithin Dabilpuram if (!node) 1255be3009e7SNithin Dabilpuram return NIX_ERR_TM_INVALID_NODE; 1256be3009e7SNithin Dabilpuram 1257be3009e7SNithin Dabilpuram list = nix_tm_node_list(nix, tree); 1258be3009e7SNithin Dabilpuram /* Check for any existing children */ 1259be3009e7SNithin Dabilpuram TAILQ_FOREACH(child, list, node) { 1260be3009e7SNithin Dabilpuram if (child->parent == node) 1261be3009e7SNithin Dabilpuram return NIX_ERR_TM_CHILD_EXISTS; 1262be3009e7SNithin Dabilpuram } 1263be3009e7SNithin Dabilpuram 1264be3009e7SNithin Dabilpuram /* Remove shaper profile reference */ 1265be3009e7SNithin Dabilpuram profile_id = node->shaper_profile_id; 1266be3009e7SNithin Dabilpuram profile = nix_tm_shaper_profile_search(nix, profile_id); 1267be3009e7SNithin Dabilpuram 1268be3009e7SNithin Dabilpuram /* Free hw resource locally */ 1269be3009e7SNithin Dabilpuram if (node->flags & NIX_TM_NODE_HWRES) { 1270be3009e7SNithin Dabilpuram rc = nix_tm_free_node_resource(nix, node); 1271be3009e7SNithin Dabilpuram if (rc) 1272be3009e7SNithin Dabilpuram return rc; 1273be3009e7SNithin Dabilpuram } 1274be3009e7SNithin Dabilpuram 1275be3009e7SNithin Dabilpuram if (profile) 1276be3009e7SNithin Dabilpuram profile->ref_cnt--; 1277be3009e7SNithin Dabilpuram 1278be3009e7SNithin Dabilpuram TAILQ_REMOVE(list, node, node); 1279be3009e7SNithin Dabilpuram 1280be3009e7SNithin Dabilpuram plt_tm_dbg("Deleted node %s lvl %u id %u, prio 0x%x weight 0x%x " 1281be3009e7SNithin Dabilpuram "parent %u profile 0x%x tree %u (%p)", 1282be3009e7SNithin Dabilpuram nix_tm_hwlvl2str(node->hw_lvl), node->lvl, node->id, 1283be3009e7SNithin Dabilpuram node->priority, node->weight, 1284be3009e7SNithin Dabilpuram node->parent ? node->parent->id : UINT32_MAX, 1285be3009e7SNithin Dabilpuram node->shaper_profile_id, tree, node); 1286be3009e7SNithin Dabilpuram /* Free only if requested */ 1287be3009e7SNithin Dabilpuram if (free) 1288be3009e7SNithin Dabilpuram nix_tm_node_free(node); 1289be3009e7SNithin Dabilpuram return 0; 1290be3009e7SNithin Dabilpuram } 1291be3009e7SNithin Dabilpuram 1292df405df9SNithin Dabilpuram static int 1293df405df9SNithin Dabilpuram nix_tm_assign_hw_id(struct nix *nix, struct nix_tm_node *parent, 1294df405df9SNithin Dabilpuram uint16_t *contig_id, int *contig_cnt, 1295df405df9SNithin Dabilpuram struct nix_tm_node_list *list) 1296df405df9SNithin Dabilpuram { 1297df405df9SNithin Dabilpuram struct nix_tm_node *child; 1298df405df9SNithin Dabilpuram struct plt_bitmap *bmp; 1299df405df9SNithin Dabilpuram uint8_t child_hw_lvl; 1300df405df9SNithin Dabilpuram int spare_schq = -1; 1301df405df9SNithin Dabilpuram uint32_t pos = 0; 1302df405df9SNithin Dabilpuram uint64_t slab; 1303df405df9SNithin Dabilpuram uint16_t schq; 1304df405df9SNithin Dabilpuram 1305df405df9SNithin Dabilpuram child_hw_lvl = parent->hw_lvl - 1; 1306df405df9SNithin Dabilpuram bmp = nix->schq_bmp[child_hw_lvl]; 1307df405df9SNithin Dabilpuram plt_bitmap_scan_init(bmp); 1308df405df9SNithin Dabilpuram slab = 0; 1309df405df9SNithin Dabilpuram 1310df405df9SNithin Dabilpuram /* Save spare schq if it is case of RR + SP */ 1311df405df9SNithin Dabilpuram if (parent->rr_prio != 0xf && *contig_cnt > 1) 1312df405df9SNithin Dabilpuram spare_schq = *contig_id + parent->rr_prio; 1313df405df9SNithin Dabilpuram 1314df405df9SNithin Dabilpuram TAILQ_FOREACH(child, list, node) { 1315df405df9SNithin Dabilpuram if (!child->parent) 1316df405df9SNithin Dabilpuram continue; 1317df405df9SNithin Dabilpuram if (child->parent->id != parent->id) 1318df405df9SNithin Dabilpuram continue; 1319df405df9SNithin Dabilpuram 1320df405df9SNithin Dabilpuram /* Resource never expected to be present */ 1321df405df9SNithin Dabilpuram if (child->flags & NIX_TM_NODE_HWRES) { 1322df405df9SNithin Dabilpuram plt_err("Resource exists for child (%s)%u, id %u (%p)", 1323df405df9SNithin Dabilpuram nix_tm_hwlvl2str(child->hw_lvl), child->hw_id, 1324df405df9SNithin Dabilpuram child->id, child); 1325df405df9SNithin Dabilpuram return -EFAULT; 1326df405df9SNithin Dabilpuram } 1327df405df9SNithin Dabilpuram 132866d485fbSNithin Dabilpuram if (!slab) 132966d485fbSNithin Dabilpuram plt_bitmap_scan(bmp, &pos, &slab); 1330df405df9SNithin Dabilpuram 1331df405df9SNithin Dabilpuram if (child->priority == parent->rr_prio && spare_schq != -1) { 1332df405df9SNithin Dabilpuram /* Use spare schq first if present */ 1333df405df9SNithin Dabilpuram schq = spare_schq; 1334df405df9SNithin Dabilpuram spare_schq = -1; 1335df405df9SNithin Dabilpuram *contig_cnt = *contig_cnt - 1; 1336df405df9SNithin Dabilpuram 1337df405df9SNithin Dabilpuram } else if (child->priority == parent->rr_prio) { 1338df405df9SNithin Dabilpuram /* Assign a discontiguous queue */ 1339df405df9SNithin Dabilpuram if (!slab) { 1340df405df9SNithin Dabilpuram plt_err("Schq not found for Child %u " 1341df405df9SNithin Dabilpuram "lvl %u (%p)", 1342df405df9SNithin Dabilpuram child->id, child->lvl, child); 1343df405df9SNithin Dabilpuram return -ENOENT; 1344df405df9SNithin Dabilpuram } 1345df405df9SNithin Dabilpuram 1346df405df9SNithin Dabilpuram schq = bitmap_ctzll(slab); 1347df405df9SNithin Dabilpuram slab &= ~(1ULL << schq); 1348df405df9SNithin Dabilpuram schq += pos; 1349df405df9SNithin Dabilpuram plt_bitmap_clear(bmp, schq); 1350df405df9SNithin Dabilpuram } else { 1351df405df9SNithin Dabilpuram /* Assign a contiguous queue */ 1352df405df9SNithin Dabilpuram schq = *contig_id + child->priority; 1353df405df9SNithin Dabilpuram *contig_cnt = *contig_cnt - 1; 1354df405df9SNithin Dabilpuram } 1355df405df9SNithin Dabilpuram 1356df405df9SNithin Dabilpuram plt_tm_dbg("Resource %s(%u), for lvl %u id %u(%p)", 1357df405df9SNithin Dabilpuram nix_tm_hwlvl2str(child->hw_lvl), schq, child->lvl, 1358df405df9SNithin Dabilpuram child->id, child); 1359df405df9SNithin Dabilpuram 1360df405df9SNithin Dabilpuram child->hw_id = schq; 1361df405df9SNithin Dabilpuram child->parent_hw_id = parent->hw_id; 1362df405df9SNithin Dabilpuram child->flags |= NIX_TM_NODE_HWRES; 1363df405df9SNithin Dabilpuram } 1364df405df9SNithin Dabilpuram 1365df405df9SNithin Dabilpuram return 0; 1366df405df9SNithin Dabilpuram } 1367df405df9SNithin Dabilpuram 1368df405df9SNithin Dabilpuram int 1369df405df9SNithin Dabilpuram nix_tm_assign_resources(struct nix *nix, enum roc_nix_tm_tree tree) 1370df405df9SNithin Dabilpuram { 1371df405df9SNithin Dabilpuram struct nix_tm_node *parent, *root = NULL; 1372df405df9SNithin Dabilpuram struct plt_bitmap *bmp, *bmp_contig; 1373df405df9SNithin Dabilpuram struct nix_tm_node_list *list; 1374df405df9SNithin Dabilpuram uint8_t child_hw_lvl, hw_lvl; 1375df405df9SNithin Dabilpuram uint16_t contig_id, j; 1376df405df9SNithin Dabilpuram uint64_t slab = 0; 1377df405df9SNithin Dabilpuram uint32_t pos = 0; 1378df405df9SNithin Dabilpuram int cnt, rc; 1379df405df9SNithin Dabilpuram 1380df405df9SNithin Dabilpuram list = nix_tm_node_list(nix, tree); 1381df405df9SNithin Dabilpuram /* Walk from TL1 to TL4 parents */ 1382df405df9SNithin Dabilpuram for (hw_lvl = NIX_TXSCH_LVL_TL1; hw_lvl > 0; hw_lvl--) { 1383df405df9SNithin Dabilpuram TAILQ_FOREACH(parent, list, node) { 1384df405df9SNithin Dabilpuram child_hw_lvl = parent->hw_lvl - 1; 1385df405df9SNithin Dabilpuram if (parent->hw_lvl != hw_lvl) 1386df405df9SNithin Dabilpuram continue; 1387df405df9SNithin Dabilpuram 1388df405df9SNithin Dabilpuram /* Remember root for future */ 1389df405df9SNithin Dabilpuram if (parent->hw_lvl == nix->tm_root_lvl) 1390df405df9SNithin Dabilpuram root = parent; 1391df405df9SNithin Dabilpuram 1392df405df9SNithin Dabilpuram if (!parent->child_realloc) { 1393df405df9SNithin Dabilpuram /* Skip when parent is not dirty */ 1394df405df9SNithin Dabilpuram if (nix_tm_child_res_valid(list, parent)) 1395df405df9SNithin Dabilpuram continue; 1396df405df9SNithin Dabilpuram plt_err("Parent not dirty but invalid " 1397df405df9SNithin Dabilpuram "child res parent id %u(lvl %u)", 1398df405df9SNithin Dabilpuram parent->id, parent->lvl); 1399df405df9SNithin Dabilpuram return -EFAULT; 1400df405df9SNithin Dabilpuram } 1401df405df9SNithin Dabilpuram 1402df405df9SNithin Dabilpuram bmp_contig = nix->schq_contig_bmp[child_hw_lvl]; 1403df405df9SNithin Dabilpuram 1404df405df9SNithin Dabilpuram /* Prealloc contiguous indices for a parent */ 1405df405df9SNithin Dabilpuram contig_id = NIX_TM_MAX_HW_TXSCHQ; 1406df405df9SNithin Dabilpuram cnt = (int)parent->max_prio + 1; 1407df405df9SNithin Dabilpuram if (cnt > 0) { 1408df405df9SNithin Dabilpuram plt_bitmap_scan_init(bmp_contig); 1409df405df9SNithin Dabilpuram if (!plt_bitmap_scan(bmp_contig, &pos, &slab)) { 1410df405df9SNithin Dabilpuram plt_err("Contig schq not found"); 1411df405df9SNithin Dabilpuram return -ENOENT; 1412df405df9SNithin Dabilpuram } 1413df405df9SNithin Dabilpuram contig_id = pos + bitmap_ctzll(slab); 1414df405df9SNithin Dabilpuram 1415df405df9SNithin Dabilpuram /* Check if we have enough */ 1416df405df9SNithin Dabilpuram for (j = contig_id; j < contig_id + cnt; j++) { 1417df405df9SNithin Dabilpuram if (!plt_bitmap_get(bmp_contig, j)) 1418df405df9SNithin Dabilpuram break; 1419df405df9SNithin Dabilpuram } 1420df405df9SNithin Dabilpuram 1421df405df9SNithin Dabilpuram if (j != contig_id + cnt) { 1422df405df9SNithin Dabilpuram plt_err("Contig schq not sufficient"); 1423df405df9SNithin Dabilpuram return -ENOENT; 1424df405df9SNithin Dabilpuram } 1425df405df9SNithin Dabilpuram 1426df405df9SNithin Dabilpuram for (j = contig_id; j < contig_id + cnt; j++) 1427df405df9SNithin Dabilpuram plt_bitmap_clear(bmp_contig, j); 1428df405df9SNithin Dabilpuram } 1429df405df9SNithin Dabilpuram 1430df405df9SNithin Dabilpuram /* Assign hw id to all children */ 1431df405df9SNithin Dabilpuram rc = nix_tm_assign_hw_id(nix, parent, &contig_id, &cnt, 1432df405df9SNithin Dabilpuram list); 1433df405df9SNithin Dabilpuram if (cnt || rc) { 1434df405df9SNithin Dabilpuram plt_err("Unexpected err, contig res alloc, " 1435df405df9SNithin Dabilpuram "parent %u, of %s, rc=%d, cnt=%d", 1436df405df9SNithin Dabilpuram parent->id, nix_tm_hwlvl2str(hw_lvl), 1437df405df9SNithin Dabilpuram rc, cnt); 1438df405df9SNithin Dabilpuram return -EFAULT; 1439df405df9SNithin Dabilpuram } 1440df405df9SNithin Dabilpuram 1441df405df9SNithin Dabilpuram /* Clear the dirty bit as children's 1442df405df9SNithin Dabilpuram * resources are reallocated. 1443df405df9SNithin Dabilpuram */ 1444df405df9SNithin Dabilpuram parent->child_realloc = false; 1445df405df9SNithin Dabilpuram } 1446df405df9SNithin Dabilpuram } 1447df405df9SNithin Dabilpuram 1448df405df9SNithin Dabilpuram /* Root is always expected to be there */ 1449df405df9SNithin Dabilpuram if (!root) 1450df405df9SNithin Dabilpuram return -EFAULT; 1451df405df9SNithin Dabilpuram 1452df405df9SNithin Dabilpuram if (root->flags & NIX_TM_NODE_HWRES) 1453df405df9SNithin Dabilpuram return 0; 1454df405df9SNithin Dabilpuram 1455df405df9SNithin Dabilpuram /* Process root node */ 1456df405df9SNithin Dabilpuram bmp = nix->schq_bmp[nix->tm_root_lvl]; 1457df405df9SNithin Dabilpuram plt_bitmap_scan_init(bmp); 1458df405df9SNithin Dabilpuram if (!plt_bitmap_scan(bmp, &pos, &slab)) { 1459df405df9SNithin Dabilpuram plt_err("Resource not allocated for root"); 1460df405df9SNithin Dabilpuram return -EIO; 1461df405df9SNithin Dabilpuram } 1462df405df9SNithin Dabilpuram 1463df405df9SNithin Dabilpuram root->hw_id = pos + bitmap_ctzll(slab); 1464df405df9SNithin Dabilpuram root->flags |= NIX_TM_NODE_HWRES; 1465df405df9SNithin Dabilpuram plt_bitmap_clear(bmp, root->hw_id); 1466df405df9SNithin Dabilpuram 1467df405df9SNithin Dabilpuram /* Get TL1 id as well when root is not TL1 */ 1468df405df9SNithin Dabilpuram if (!nix_tm_have_tl1_access(nix)) { 1469df405df9SNithin Dabilpuram bmp = nix->schq_bmp[NIX_TXSCH_LVL_TL1]; 1470df405df9SNithin Dabilpuram 1471df405df9SNithin Dabilpuram plt_bitmap_scan_init(bmp); 1472df405df9SNithin Dabilpuram if (!plt_bitmap_scan(bmp, &pos, &slab)) { 1473df405df9SNithin Dabilpuram plt_err("Resource not found for TL1"); 1474df405df9SNithin Dabilpuram return -EIO; 1475df405df9SNithin Dabilpuram } 1476df405df9SNithin Dabilpuram root->parent_hw_id = pos + bitmap_ctzll(slab); 1477df405df9SNithin Dabilpuram plt_bitmap_clear(bmp, root->parent_hw_id); 1478df405df9SNithin Dabilpuram } 1479df405df9SNithin Dabilpuram 1480df405df9SNithin Dabilpuram plt_tm_dbg("Resource %s(%u) for root(id %u) (%p)", 1481df405df9SNithin Dabilpuram nix_tm_hwlvl2str(root->hw_lvl), root->hw_id, root->id, root); 1482df405df9SNithin Dabilpuram 1483df405df9SNithin Dabilpuram return 0; 1484df405df9SNithin Dabilpuram } 1485df405df9SNithin Dabilpuram 1486df405df9SNithin Dabilpuram void 1487df405df9SNithin Dabilpuram nix_tm_copy_rsp_to_nix(struct nix *nix, struct nix_txsch_alloc_rsp *rsp) 1488df405df9SNithin Dabilpuram { 1489df405df9SNithin Dabilpuram uint8_t lvl; 1490df405df9SNithin Dabilpuram uint16_t i; 1491df405df9SNithin Dabilpuram 1492df405df9SNithin Dabilpuram for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) { 1493df405df9SNithin Dabilpuram for (i = 0; i < rsp->schq[lvl]; i++) 1494df405df9SNithin Dabilpuram plt_bitmap_set(nix->schq_bmp[lvl], 1495df405df9SNithin Dabilpuram rsp->schq_list[lvl][i]); 1496df405df9SNithin Dabilpuram 1497df405df9SNithin Dabilpuram for (i = 0; i < rsp->schq_contig[lvl]; i++) 1498df405df9SNithin Dabilpuram plt_bitmap_set(nix->schq_contig_bmp[lvl], 1499df405df9SNithin Dabilpuram rsp->schq_contig_list[lvl][i]); 1500df405df9SNithin Dabilpuram } 1501df405df9SNithin Dabilpuram } 1502df405df9SNithin Dabilpuram 1503df405df9SNithin Dabilpuram int 1504df405df9SNithin Dabilpuram nix_tm_alloc_txschq(struct nix *nix, enum roc_nix_tm_tree tree) 1505df405df9SNithin Dabilpuram { 1506df405df9SNithin Dabilpuram uint16_t schq_contig[NIX_TXSCH_LVL_CNT]; 1507df405df9SNithin Dabilpuram struct mbox *mbox = (&nix->dev)->mbox; 1508df405df9SNithin Dabilpuram uint16_t schq[NIX_TXSCH_LVL_CNT]; 1509df405df9SNithin Dabilpuram struct nix_txsch_alloc_req *req; 1510df405df9SNithin Dabilpuram struct nix_txsch_alloc_rsp *rsp; 1511df405df9SNithin Dabilpuram uint8_t hw_lvl, i; 1512df405df9SNithin Dabilpuram bool pend; 1513df405df9SNithin Dabilpuram int rc; 1514df405df9SNithin Dabilpuram 1515df405df9SNithin Dabilpuram memset(schq, 0, sizeof(schq)); 1516df405df9SNithin Dabilpuram memset(schq_contig, 0, sizeof(schq_contig)); 1517df405df9SNithin Dabilpuram 1518df405df9SNithin Dabilpuram /* Estimate requirement */ 1519df405df9SNithin Dabilpuram rc = nix_tm_resource_estimate(nix, schq_contig, schq, tree); 1520df405df9SNithin Dabilpuram if (!rc) 1521df405df9SNithin Dabilpuram return 0; 1522df405df9SNithin Dabilpuram 1523df405df9SNithin Dabilpuram /* Release existing contiguous resources when realloc requested 1524df405df9SNithin Dabilpuram * as there is no way to guarantee continuity of old with new. 1525df405df9SNithin Dabilpuram */ 1526df405df9SNithin Dabilpuram for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) { 1527df405df9SNithin Dabilpuram if (schq_contig[hw_lvl]) 1528df405df9SNithin Dabilpuram nix_tm_release_resources(nix, hw_lvl, true, false); 1529df405df9SNithin Dabilpuram } 1530df405df9SNithin Dabilpuram 1531df405df9SNithin Dabilpuram /* Alloc as needed */ 1532df405df9SNithin Dabilpuram do { 1533df405df9SNithin Dabilpuram pend = false; 153444a9307cSRakesh Kudurumalla req = mbox_alloc_msg_nix_txsch_alloc(mbox_get(mbox)); 1535df405df9SNithin Dabilpuram if (!req) { 153644a9307cSRakesh Kudurumalla mbox_put(mbox); 1537df405df9SNithin Dabilpuram rc = -ENOMEM; 1538df405df9SNithin Dabilpuram goto alloc_err; 1539df405df9SNithin Dabilpuram } 1540df405df9SNithin Dabilpuram mbox_memcpy(req->schq, schq, sizeof(req->schq)); 1541df405df9SNithin Dabilpuram mbox_memcpy(req->schq_contig, schq_contig, 1542df405df9SNithin Dabilpuram sizeof(req->schq_contig)); 1543df405df9SNithin Dabilpuram 1544df405df9SNithin Dabilpuram /* Each alloc can be at max of MAX_TXSCHQ_PER_FUNC per level. 1545df405df9SNithin Dabilpuram * So split alloc to multiple requests. 1546df405df9SNithin Dabilpuram */ 1547df405df9SNithin Dabilpuram for (i = 0; i < NIX_TXSCH_LVL_CNT; i++) { 1548df405df9SNithin Dabilpuram if (req->schq[i] > MAX_TXSCHQ_PER_FUNC) 1549df405df9SNithin Dabilpuram req->schq[i] = MAX_TXSCHQ_PER_FUNC; 1550df405df9SNithin Dabilpuram schq[i] -= req->schq[i]; 1551df405df9SNithin Dabilpuram 1552df405df9SNithin Dabilpuram if (req->schq_contig[i] > MAX_TXSCHQ_PER_FUNC) 1553df405df9SNithin Dabilpuram req->schq_contig[i] = MAX_TXSCHQ_PER_FUNC; 1554df405df9SNithin Dabilpuram schq_contig[i] -= req->schq_contig[i]; 1555df405df9SNithin Dabilpuram 1556df405df9SNithin Dabilpuram if (schq[i] || schq_contig[i]) 1557df405df9SNithin Dabilpuram pend = true; 1558df405df9SNithin Dabilpuram } 1559df405df9SNithin Dabilpuram 1560df405df9SNithin Dabilpuram rc = mbox_process_msg(mbox, (void *)&rsp); 156144a9307cSRakesh Kudurumalla if (rc) { 156244a9307cSRakesh Kudurumalla mbox_put(mbox); 1563df405df9SNithin Dabilpuram goto alloc_err; 156444a9307cSRakesh Kudurumalla } 1565df405df9SNithin Dabilpuram 1566df405df9SNithin Dabilpuram nix_tm_copy_rsp_to_nix(nix, rsp); 156744a9307cSRakesh Kudurumalla mbox_put(mbox); 1568df405df9SNithin Dabilpuram } while (pend); 1569df405df9SNithin Dabilpuram 1570df405df9SNithin Dabilpuram nix->tm_link_cfg_lvl = rsp->link_cfg_lvl; 1571f0b9158cSNithin Dabilpuram nix->tm_aggr_lvl_rr_prio = rsp->aggr_lvl_rr_prio; 1572df405df9SNithin Dabilpuram return 0; 1573df405df9SNithin Dabilpuram alloc_err: 1574df405df9SNithin Dabilpuram for (i = 0; i < NIX_TXSCH_LVL_CNT; i++) { 1575df405df9SNithin Dabilpuram if (nix_tm_release_resources(nix, i, true, false)) 1576df405df9SNithin Dabilpuram plt_err("Failed to release contig resources of " 1577df405df9SNithin Dabilpuram "lvl %d on error", 1578df405df9SNithin Dabilpuram i); 1579df405df9SNithin Dabilpuram if (nix_tm_release_resources(nix, i, false, false)) 1580df405df9SNithin Dabilpuram plt_err("Failed to release discontig resources of " 1581df405df9SNithin Dabilpuram "lvl %d on error", 1582df405df9SNithin Dabilpuram i); 1583df405df9SNithin Dabilpuram } 1584df405df9SNithin Dabilpuram return rc; 1585df405df9SNithin Dabilpuram } 1586df405df9SNithin Dabilpuram 1587df405df9SNithin Dabilpuram int 15885a960e26SNithin Dabilpuram nix_tm_prepare_default_tree(struct roc_nix *roc_nix) 15895a960e26SNithin Dabilpuram { 15905a960e26SNithin Dabilpuram struct nix *nix = roc_nix_to_nix_priv(roc_nix); 15915a960e26SNithin Dabilpuram uint32_t nonleaf_id = nix->nb_tx_queues; 15925a960e26SNithin Dabilpuram struct nix_tm_node *node = NULL; 15935a960e26SNithin Dabilpuram uint8_t leaf_lvl, lvl, lvl_end; 15945a960e26SNithin Dabilpuram uint32_t parent, i; 15955a960e26SNithin Dabilpuram int rc = 0; 15965a960e26SNithin Dabilpuram 15975a960e26SNithin Dabilpuram /* Add ROOT, SCH1, SCH2, SCH3, [SCH4] nodes */ 15985a960e26SNithin Dabilpuram parent = ROC_NIX_TM_NODE_ID_INVALID; 15995a960e26SNithin Dabilpuram /* With TL1 access we have an extra level */ 16005a960e26SNithin Dabilpuram lvl_end = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH4 : 16015a960e26SNithin Dabilpuram ROC_TM_LVL_SCH3); 16025a960e26SNithin Dabilpuram 16035a960e26SNithin Dabilpuram for (lvl = ROC_TM_LVL_ROOT; lvl <= lvl_end; lvl++) { 16045a960e26SNithin Dabilpuram rc = -ENOMEM; 16055a960e26SNithin Dabilpuram node = nix_tm_node_alloc(); 16065a960e26SNithin Dabilpuram if (!node) 16075a960e26SNithin Dabilpuram goto error; 16085a960e26SNithin Dabilpuram 16095a960e26SNithin Dabilpuram node->id = nonleaf_id; 16105a960e26SNithin Dabilpuram node->parent_id = parent; 16115a960e26SNithin Dabilpuram node->priority = 0; 1612eac95048SSatha Rao /* Default VF root RR_QUANTUM is in sync with kernel */ 1613eac95048SSatha Rao if (lvl == ROC_TM_LVL_ROOT && !nix_tm_have_tl1_access(nix)) 1614eac95048SSatha Rao node->weight = roc_nix->root_sched_weight; 1615eac95048SSatha Rao else 16165a960e26SNithin Dabilpuram node->weight = NIX_TM_DFLT_RR_WT; 16175a960e26SNithin Dabilpuram node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE; 16185a960e26SNithin Dabilpuram node->lvl = lvl; 16195a960e26SNithin Dabilpuram node->tree = ROC_NIX_TM_DEFAULT; 162020d02329SSunil Kumar Kori node->rel_chan = NIX_TM_CHAN_INVALID; 16215a960e26SNithin Dabilpuram 16225a960e26SNithin Dabilpuram rc = nix_tm_node_add(roc_nix, node); 16235a960e26SNithin Dabilpuram if (rc) 16245a960e26SNithin Dabilpuram goto error; 16255a960e26SNithin Dabilpuram parent = nonleaf_id; 16265a960e26SNithin Dabilpuram nonleaf_id++; 16275a960e26SNithin Dabilpuram } 16285a960e26SNithin Dabilpuram 16295a960e26SNithin Dabilpuram parent = nonleaf_id - 1; 16305a960e26SNithin Dabilpuram leaf_lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_QUEUE : 16315a960e26SNithin Dabilpuram ROC_TM_LVL_SCH4); 16325a960e26SNithin Dabilpuram 16335a960e26SNithin Dabilpuram /* Add leaf nodes */ 16345a960e26SNithin Dabilpuram for (i = 0; i < nix->nb_tx_queues; i++) { 16355a960e26SNithin Dabilpuram rc = -ENOMEM; 16365a960e26SNithin Dabilpuram node = nix_tm_node_alloc(); 16375a960e26SNithin Dabilpuram if (!node) 16385a960e26SNithin Dabilpuram goto error; 16395a960e26SNithin Dabilpuram 16405a960e26SNithin Dabilpuram node->id = i; 16415a960e26SNithin Dabilpuram node->parent_id = parent; 16425a960e26SNithin Dabilpuram node->priority = 0; 16435a960e26SNithin Dabilpuram node->weight = NIX_TM_DFLT_RR_WT; 16445a960e26SNithin Dabilpuram node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE; 16455a960e26SNithin Dabilpuram node->lvl = leaf_lvl; 16465a960e26SNithin Dabilpuram node->tree = ROC_NIX_TM_DEFAULT; 164720d02329SSunil Kumar Kori node->rel_chan = NIX_TM_CHAN_INVALID; 16485a960e26SNithin Dabilpuram 16495a960e26SNithin Dabilpuram rc = nix_tm_node_add(roc_nix, node); 16505a960e26SNithin Dabilpuram if (rc) 16515a960e26SNithin Dabilpuram goto error; 16525a960e26SNithin Dabilpuram } 16535a960e26SNithin Dabilpuram 16545a960e26SNithin Dabilpuram return 0; 16555a960e26SNithin Dabilpuram error: 16565a960e26SNithin Dabilpuram nix_tm_node_free(node); 16575a960e26SNithin Dabilpuram return rc; 16585a960e26SNithin Dabilpuram } 16595a960e26SNithin Dabilpuram 16605a960e26SNithin Dabilpuram int 1661f9dbd4a5SSatha Rao roc_nix_tm_prepare_rate_limited_tree(struct roc_nix *roc_nix) 16625a960e26SNithin Dabilpuram { 16635a960e26SNithin Dabilpuram struct nix *nix = roc_nix_to_nix_priv(roc_nix); 16645a960e26SNithin Dabilpuram uint32_t nonleaf_id = nix->nb_tx_queues; 16655a960e26SNithin Dabilpuram struct nix_tm_node *node = NULL; 16665a960e26SNithin Dabilpuram uint8_t leaf_lvl, lvl, lvl_end; 16675a960e26SNithin Dabilpuram uint32_t parent, i; 16685a960e26SNithin Dabilpuram int rc = 0; 16695a960e26SNithin Dabilpuram 16705a960e26SNithin Dabilpuram /* Add ROOT, SCH1, SCH2 nodes */ 16715a960e26SNithin Dabilpuram parent = ROC_NIX_TM_NODE_ID_INVALID; 16725a960e26SNithin Dabilpuram lvl_end = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH3 : 16735a960e26SNithin Dabilpuram ROC_TM_LVL_SCH2); 16745a960e26SNithin Dabilpuram 16755a960e26SNithin Dabilpuram for (lvl = ROC_TM_LVL_ROOT; lvl <= lvl_end; lvl++) { 16765a960e26SNithin Dabilpuram rc = -ENOMEM; 16775a960e26SNithin Dabilpuram node = nix_tm_node_alloc(); 16785a960e26SNithin Dabilpuram if (!node) 16795a960e26SNithin Dabilpuram goto error; 16805a960e26SNithin Dabilpuram 16815a960e26SNithin Dabilpuram node->id = nonleaf_id; 16825a960e26SNithin Dabilpuram node->parent_id = parent; 16835a960e26SNithin Dabilpuram node->priority = 0; 16845a960e26SNithin Dabilpuram node->weight = NIX_TM_DFLT_RR_WT; 16855a960e26SNithin Dabilpuram node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE; 16865a960e26SNithin Dabilpuram node->lvl = lvl; 16875a960e26SNithin Dabilpuram node->tree = ROC_NIX_TM_RLIMIT; 168820d02329SSunil Kumar Kori node->rel_chan = NIX_TM_CHAN_INVALID; 16895a960e26SNithin Dabilpuram 16905a960e26SNithin Dabilpuram rc = nix_tm_node_add(roc_nix, node); 16915a960e26SNithin Dabilpuram if (rc) 16925a960e26SNithin Dabilpuram goto error; 16935a960e26SNithin Dabilpuram parent = nonleaf_id; 16945a960e26SNithin Dabilpuram nonleaf_id++; 16955a960e26SNithin Dabilpuram } 16965a960e26SNithin Dabilpuram 16975a960e26SNithin Dabilpuram /* SMQ is mapped to SCH4 when we have TL1 access and SCH3 otherwise */ 16985a960e26SNithin Dabilpuram lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH4 : ROC_TM_LVL_SCH3); 16995a960e26SNithin Dabilpuram 17005a960e26SNithin Dabilpuram /* Add per queue SMQ nodes i.e SCH4 / SCH3 */ 17015a960e26SNithin Dabilpuram for (i = 0; i < nix->nb_tx_queues; i++) { 17025a960e26SNithin Dabilpuram rc = -ENOMEM; 17035a960e26SNithin Dabilpuram node = nix_tm_node_alloc(); 17045a960e26SNithin Dabilpuram if (!node) 17055a960e26SNithin Dabilpuram goto error; 17065a960e26SNithin Dabilpuram 17075a960e26SNithin Dabilpuram node->id = nonleaf_id + i; 17085a960e26SNithin Dabilpuram node->parent_id = parent; 17095a960e26SNithin Dabilpuram node->priority = 0; 17105a960e26SNithin Dabilpuram node->weight = NIX_TM_DFLT_RR_WT; 17115a960e26SNithin Dabilpuram node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE; 17125a960e26SNithin Dabilpuram node->lvl = lvl; 17135a960e26SNithin Dabilpuram node->tree = ROC_NIX_TM_RLIMIT; 171420d02329SSunil Kumar Kori node->rel_chan = NIX_TM_CHAN_INVALID; 17155a960e26SNithin Dabilpuram 17165a960e26SNithin Dabilpuram rc = nix_tm_node_add(roc_nix, node); 17175a960e26SNithin Dabilpuram if (rc) 17185a960e26SNithin Dabilpuram goto error; 17195a960e26SNithin Dabilpuram } 17205a960e26SNithin Dabilpuram 17215a960e26SNithin Dabilpuram parent = nonleaf_id; 17225a960e26SNithin Dabilpuram leaf_lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_QUEUE : 17235a960e26SNithin Dabilpuram ROC_TM_LVL_SCH4); 17245a960e26SNithin Dabilpuram 17255a960e26SNithin Dabilpuram /* Add leaf nodes */ 17265a960e26SNithin Dabilpuram for (i = 0; i < nix->nb_tx_queues; i++) { 17275a960e26SNithin Dabilpuram rc = -ENOMEM; 17285a960e26SNithin Dabilpuram node = nix_tm_node_alloc(); 17295a960e26SNithin Dabilpuram if (!node) 17305a960e26SNithin Dabilpuram goto error; 17315a960e26SNithin Dabilpuram 17325a960e26SNithin Dabilpuram node->id = i; 1733f9dbd4a5SSatha Rao node->parent_id = parent + i; 17345a960e26SNithin Dabilpuram node->priority = 0; 17355a960e26SNithin Dabilpuram node->weight = NIX_TM_DFLT_RR_WT; 17365a960e26SNithin Dabilpuram node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE; 17375a960e26SNithin Dabilpuram node->lvl = leaf_lvl; 17385a960e26SNithin Dabilpuram node->tree = ROC_NIX_TM_RLIMIT; 173920d02329SSunil Kumar Kori node->rel_chan = NIX_TM_CHAN_INVALID; 174020d02329SSunil Kumar Kori 174120d02329SSunil Kumar Kori rc = nix_tm_node_add(roc_nix, node); 174220d02329SSunil Kumar Kori if (rc) 174320d02329SSunil Kumar Kori goto error; 174420d02329SSunil Kumar Kori } 174520d02329SSunil Kumar Kori 174620d02329SSunil Kumar Kori return 0; 174720d02329SSunil Kumar Kori error: 174820d02329SSunil Kumar Kori nix_tm_node_free(node); 174920d02329SSunil Kumar Kori return rc; 175020d02329SSunil Kumar Kori } 175120d02329SSunil Kumar Kori 175220d02329SSunil Kumar Kori int 175320d02329SSunil Kumar Kori roc_nix_tm_pfc_prepare_tree(struct roc_nix *roc_nix) 175420d02329SSunil Kumar Kori { 175520d02329SSunil Kumar Kori struct nix *nix = roc_nix_to_nix_priv(roc_nix); 1756174f2f35SSunil Kumar Kori uint8_t leaf_lvl, lvl, lvl_start, lvl_end; 175720d02329SSunil Kumar Kori uint32_t nonleaf_id = nix->nb_tx_queues; 175820d02329SSunil Kumar Kori struct nix_tm_node *node = NULL; 175920d02329SSunil Kumar Kori uint32_t tl2_node_id; 176020d02329SSunil Kumar Kori uint32_t parent, i; 176120d02329SSunil Kumar Kori int rc = -ENOMEM; 176220d02329SSunil Kumar Kori 176320d02329SSunil Kumar Kori parent = ROC_NIX_TM_NODE_ID_INVALID; 1764174f2f35SSunil Kumar Kori lvl_end = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH3 : 1765174f2f35SSunil Kumar Kori ROC_TM_LVL_SCH2); 1766174f2f35SSunil Kumar Kori leaf_lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_QUEUE : 1767174f2f35SSunil Kumar Kori ROC_TM_LVL_SCH4); 176820d02329SSunil Kumar Kori 176920d02329SSunil Kumar Kori /* TL1 node */ 177020d02329SSunil Kumar Kori node = nix_tm_node_alloc(); 177120d02329SSunil Kumar Kori if (!node) 177220d02329SSunil Kumar Kori goto error; 177320d02329SSunil Kumar Kori 177420d02329SSunil Kumar Kori node->id = nonleaf_id; 177520d02329SSunil Kumar Kori node->parent_id = parent; 177620d02329SSunil Kumar Kori node->priority = 0; 177720d02329SSunil Kumar Kori node->weight = NIX_TM_DFLT_RR_WT; 177820d02329SSunil Kumar Kori node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE; 177920d02329SSunil Kumar Kori node->lvl = ROC_TM_LVL_ROOT; 178020d02329SSunil Kumar Kori node->tree = ROC_NIX_TM_PFC; 178120d02329SSunil Kumar Kori node->rel_chan = NIX_TM_CHAN_INVALID; 178220d02329SSunil Kumar Kori 178320d02329SSunil Kumar Kori rc = nix_tm_node_add(roc_nix, node); 178420d02329SSunil Kumar Kori if (rc) 178520d02329SSunil Kumar Kori goto error; 178620d02329SSunil Kumar Kori 178720d02329SSunil Kumar Kori parent = nonleaf_id; 178820d02329SSunil Kumar Kori nonleaf_id++; 178920d02329SSunil Kumar Kori 1790174f2f35SSunil Kumar Kori lvl_start = ROC_TM_LVL_SCH1; 1791174f2f35SSunil Kumar Kori if (roc_nix_is_pf(roc_nix)) { 179220d02329SSunil Kumar Kori /* TL2 node */ 179320d02329SSunil Kumar Kori rc = -ENOMEM; 179420d02329SSunil Kumar Kori node = nix_tm_node_alloc(); 179520d02329SSunil Kumar Kori if (!node) 179620d02329SSunil Kumar Kori goto error; 179720d02329SSunil Kumar Kori 179820d02329SSunil Kumar Kori node->id = nonleaf_id; 179920d02329SSunil Kumar Kori node->parent_id = parent; 180020d02329SSunil Kumar Kori node->priority = 0; 180120d02329SSunil Kumar Kori node->weight = NIX_TM_DFLT_RR_WT; 180220d02329SSunil Kumar Kori node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE; 180320d02329SSunil Kumar Kori node->lvl = ROC_TM_LVL_SCH1; 180420d02329SSunil Kumar Kori node->tree = ROC_NIX_TM_PFC; 180520d02329SSunil Kumar Kori node->rel_chan = NIX_TM_CHAN_INVALID; 180620d02329SSunil Kumar Kori 180720d02329SSunil Kumar Kori rc = nix_tm_node_add(roc_nix, node); 180820d02329SSunil Kumar Kori if (rc) 180920d02329SSunil Kumar Kori goto error; 181020d02329SSunil Kumar Kori 1811174f2f35SSunil Kumar Kori lvl_start = ROC_TM_LVL_SCH2; 181220d02329SSunil Kumar Kori tl2_node_id = nonleaf_id; 181320d02329SSunil Kumar Kori nonleaf_id++; 1814174f2f35SSunil Kumar Kori } else { 1815174f2f35SSunil Kumar Kori tl2_node_id = parent; 1816174f2f35SSunil Kumar Kori } 181720d02329SSunil Kumar Kori 181820d02329SSunil Kumar Kori for (i = 0; i < nix->nb_tx_queues; i++) { 181920d02329SSunil Kumar Kori parent = tl2_node_id; 1820174f2f35SSunil Kumar Kori for (lvl = lvl_start; lvl <= lvl_end; lvl++) { 182120d02329SSunil Kumar Kori rc = -ENOMEM; 182220d02329SSunil Kumar Kori node = nix_tm_node_alloc(); 182320d02329SSunil Kumar Kori if (!node) 182420d02329SSunil Kumar Kori goto error; 182520d02329SSunil Kumar Kori 182620d02329SSunil Kumar Kori node->id = nonleaf_id; 182720d02329SSunil Kumar Kori node->parent_id = parent; 182820d02329SSunil Kumar Kori node->priority = 0; 182920d02329SSunil Kumar Kori node->weight = NIX_TM_DFLT_RR_WT; 183020d02329SSunil Kumar Kori node->shaper_profile_id = 183120d02329SSunil Kumar Kori ROC_NIX_TM_SHAPER_PROFILE_NONE; 183220d02329SSunil Kumar Kori node->lvl = lvl; 183320d02329SSunil Kumar Kori node->tree = ROC_NIX_TM_PFC; 183420d02329SSunil Kumar Kori node->rel_chan = NIX_TM_CHAN_INVALID; 183520d02329SSunil Kumar Kori 183620d02329SSunil Kumar Kori rc = nix_tm_node_add(roc_nix, node); 183720d02329SSunil Kumar Kori if (rc) 183820d02329SSunil Kumar Kori goto error; 183920d02329SSunil Kumar Kori 184020d02329SSunil Kumar Kori parent = nonleaf_id; 184120d02329SSunil Kumar Kori nonleaf_id++; 184220d02329SSunil Kumar Kori } 184320d02329SSunil Kumar Kori 1844174f2f35SSunil Kumar Kori lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH4 : 1845174f2f35SSunil Kumar Kori ROC_TM_LVL_SCH3); 184620d02329SSunil Kumar Kori 184720d02329SSunil Kumar Kori rc = -ENOMEM; 184820d02329SSunil Kumar Kori node = nix_tm_node_alloc(); 184920d02329SSunil Kumar Kori if (!node) 185020d02329SSunil Kumar Kori goto error; 185120d02329SSunil Kumar Kori 185220d02329SSunil Kumar Kori node->id = nonleaf_id; 185320d02329SSunil Kumar Kori node->parent_id = parent; 185420d02329SSunil Kumar Kori node->priority = 0; 185520d02329SSunil Kumar Kori node->weight = NIX_TM_DFLT_RR_WT; 185620d02329SSunil Kumar Kori node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE; 185720d02329SSunil Kumar Kori node->lvl = lvl; 185820d02329SSunil Kumar Kori node->tree = ROC_NIX_TM_PFC; 185920d02329SSunil Kumar Kori node->rel_chan = NIX_TM_CHAN_INVALID; 186020d02329SSunil Kumar Kori 186120d02329SSunil Kumar Kori rc = nix_tm_node_add(roc_nix, node); 186220d02329SSunil Kumar Kori if (rc) 186320d02329SSunil Kumar Kori goto error; 186420d02329SSunil Kumar Kori 186520d02329SSunil Kumar Kori parent = nonleaf_id; 186620d02329SSunil Kumar Kori nonleaf_id++; 186720d02329SSunil Kumar Kori 186820d02329SSunil Kumar Kori rc = -ENOMEM; 186920d02329SSunil Kumar Kori node = nix_tm_node_alloc(); 187020d02329SSunil Kumar Kori if (!node) 187120d02329SSunil Kumar Kori goto error; 187220d02329SSunil Kumar Kori 187320d02329SSunil Kumar Kori node->id = i; 187420d02329SSunil Kumar Kori node->parent_id = parent; 187520d02329SSunil Kumar Kori node->priority = 0; 187620d02329SSunil Kumar Kori node->weight = NIX_TM_DFLT_RR_WT; 187720d02329SSunil Kumar Kori node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE; 187820d02329SSunil Kumar Kori node->lvl = leaf_lvl; 187920d02329SSunil Kumar Kori node->tree = ROC_NIX_TM_PFC; 188020d02329SSunil Kumar Kori node->rel_chan = NIX_TM_CHAN_INVALID; 18815a960e26SNithin Dabilpuram 18825a960e26SNithin Dabilpuram rc = nix_tm_node_add(roc_nix, node); 18835a960e26SNithin Dabilpuram if (rc) 18845a960e26SNithin Dabilpuram goto error; 18855a960e26SNithin Dabilpuram } 18865a960e26SNithin Dabilpuram 18875a960e26SNithin Dabilpuram return 0; 18885a960e26SNithin Dabilpuram error: 18895a960e26SNithin Dabilpuram nix_tm_node_free(node); 18905a960e26SNithin Dabilpuram return rc; 18915a960e26SNithin Dabilpuram } 18925a960e26SNithin Dabilpuram 18935a960e26SNithin Dabilpuram int 1894df405df9SNithin Dabilpuram nix_tm_free_resources(struct roc_nix *roc_nix, uint32_t tree_mask, bool hw_only) 1895df405df9SNithin Dabilpuram { 1896df405df9SNithin Dabilpuram struct nix *nix = roc_nix_to_nix_priv(roc_nix); 1897df405df9SNithin Dabilpuram struct nix_tm_shaper_profile *profile; 1898df405df9SNithin Dabilpuram struct nix_tm_node *node, *next_node; 1899df405df9SNithin Dabilpuram struct nix_tm_node_list *list; 1900df405df9SNithin Dabilpuram enum roc_nix_tm_tree tree; 1901df405df9SNithin Dabilpuram uint32_t profile_id; 1902df405df9SNithin Dabilpuram int rc = 0; 1903a5abf68cSNithin Dabilpuram int hw_lvl; 1904df405df9SNithin Dabilpuram 1905df405df9SNithin Dabilpuram for (tree = 0; tree < ROC_NIX_TM_TREE_MAX; tree++) { 1906df405df9SNithin Dabilpuram if (!(tree_mask & BIT(tree))) 1907df405df9SNithin Dabilpuram continue; 1908df405df9SNithin Dabilpuram 1909df405df9SNithin Dabilpuram plt_tm_dbg("Freeing resources of tree %u", tree); 1910df405df9SNithin Dabilpuram 1911df405df9SNithin Dabilpuram list = nix_tm_node_list(nix, tree); 1912a5abf68cSNithin Dabilpuram /* Flush and free resources from leaf */ 1913a5abf68cSNithin Dabilpuram for (hw_lvl = NIX_TXSCH_LVL_SMQ; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) { 1914df405df9SNithin Dabilpuram next_node = TAILQ_FIRST(list); 1915df405df9SNithin Dabilpuram while (next_node) { 1916df405df9SNithin Dabilpuram node = next_node; 1917df405df9SNithin Dabilpuram next_node = TAILQ_NEXT(node, node); 1918a5abf68cSNithin Dabilpuram if (node->hw_lvl != hw_lvl) 1919a5abf68cSNithin Dabilpuram continue; 1920df405df9SNithin Dabilpuram 1921df405df9SNithin Dabilpuram if (!nix_tm_is_leaf(nix, node->lvl) && 1922df405df9SNithin Dabilpuram node->flags & NIX_TM_NODE_HWRES) { 1923df405df9SNithin Dabilpuram /* Clear xoff in path for flush to succeed */ 1924df405df9SNithin Dabilpuram rc = nix_tm_clear_path_xoff(nix, node); 1925df405df9SNithin Dabilpuram if (rc) 1926df405df9SNithin Dabilpuram return rc; 1927df405df9SNithin Dabilpuram rc = nix_tm_free_node_resource(nix, node); 1928df405df9SNithin Dabilpuram if (rc) 1929df405df9SNithin Dabilpuram return rc; 1930df405df9SNithin Dabilpuram } 1931df405df9SNithin Dabilpuram } 1932a5abf68cSNithin Dabilpuram } 1933df405df9SNithin Dabilpuram 1934df405df9SNithin Dabilpuram /* Leave software elements if needed */ 1935df405df9SNithin Dabilpuram if (hw_only) 1936df405df9SNithin Dabilpuram continue; 1937df405df9SNithin Dabilpuram 1938df405df9SNithin Dabilpuram next_node = TAILQ_FIRST(list); 1939df405df9SNithin Dabilpuram while (next_node) { 1940df405df9SNithin Dabilpuram node = next_node; 1941df405df9SNithin Dabilpuram next_node = TAILQ_NEXT(node, node); 1942df405df9SNithin Dabilpuram 1943df405df9SNithin Dabilpuram plt_tm_dbg("Free node lvl %u id %u (%p)", node->lvl, 1944df405df9SNithin Dabilpuram node->id, node); 1945df405df9SNithin Dabilpuram 1946df405df9SNithin Dabilpuram profile_id = node->shaper_profile_id; 1947df405df9SNithin Dabilpuram profile = nix_tm_shaper_profile_search(nix, profile_id); 1948df405df9SNithin Dabilpuram if (profile) 1949df405df9SNithin Dabilpuram profile->ref_cnt--; 1950df405df9SNithin Dabilpuram 1951df405df9SNithin Dabilpuram TAILQ_REMOVE(list, node, node); 1952df405df9SNithin Dabilpuram nix_tm_node_free(node); 1953df405df9SNithin Dabilpuram } 1954df405df9SNithin Dabilpuram } 1955df405df9SNithin Dabilpuram return rc; 1956df405df9SNithin Dabilpuram } 1957df405df9SNithin Dabilpuram 1958be3009e7SNithin Dabilpuram int 195905d727e8SNithin Dabilpuram nix_tm_conf_init(struct roc_nix *roc_nix) 196005d727e8SNithin Dabilpuram { 196105d727e8SNithin Dabilpuram struct nix *nix = roc_nix_to_nix_priv(roc_nix); 196205d727e8SNithin Dabilpuram uint32_t bmp_sz, hw_lvl; 196305d727e8SNithin Dabilpuram void *bmp_mem; 196405d727e8SNithin Dabilpuram int rc, i; 196505d727e8SNithin Dabilpuram 1966be3009e7SNithin Dabilpuram PLT_STATIC_ASSERT(sizeof(struct nix_tm_node) <= ROC_NIX_TM_NODE_SZ); 1967c2460d14SSatha Rao PLT_STATIC_ASSERT(sizeof(struct nix_tm_shaper_profile) <= 1968c2460d14SSatha Rao ROC_NIX_TM_SHAPER_PROFILE_SZ); 1969be3009e7SNithin Dabilpuram 197005d727e8SNithin Dabilpuram nix->tm_flags = 0; 197105d727e8SNithin Dabilpuram for (i = 0; i < ROC_NIX_TM_TREE_MAX; i++) 197205d727e8SNithin Dabilpuram TAILQ_INIT(&nix->trees[i]); 197305d727e8SNithin Dabilpuram 197405d727e8SNithin Dabilpuram TAILQ_INIT(&nix->shaper_profile_list); 197505d727e8SNithin Dabilpuram nix->tm_rate_min = 1E9; /* 1Gbps */ 197605d727e8SNithin Dabilpuram 197705d727e8SNithin Dabilpuram rc = -ENOMEM; 197805d727e8SNithin Dabilpuram bmp_sz = plt_bitmap_get_memory_footprint(NIX_TM_MAX_HW_TXSCHQ); 197905d727e8SNithin Dabilpuram bmp_mem = plt_zmalloc(bmp_sz * NIX_TXSCH_LVL_CNT * 2, 0); 198005d727e8SNithin Dabilpuram if (!bmp_mem) 198105d727e8SNithin Dabilpuram return rc; 198205d727e8SNithin Dabilpuram nix->schq_bmp_mem = bmp_mem; 198305d727e8SNithin Dabilpuram 198405d727e8SNithin Dabilpuram /* Init contiguous and discontiguous bitmap per lvl */ 198505d727e8SNithin Dabilpuram rc = -EIO; 198605d727e8SNithin Dabilpuram for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) { 198705d727e8SNithin Dabilpuram /* Bitmap for discontiguous resource */ 198805d727e8SNithin Dabilpuram nix->schq_bmp[hw_lvl] = 198905d727e8SNithin Dabilpuram plt_bitmap_init(NIX_TM_MAX_HW_TXSCHQ, bmp_mem, bmp_sz); 199005d727e8SNithin Dabilpuram if (!nix->schq_bmp[hw_lvl]) 199105d727e8SNithin Dabilpuram goto exit; 199205d727e8SNithin Dabilpuram 199305d727e8SNithin Dabilpuram bmp_mem = PLT_PTR_ADD(bmp_mem, bmp_sz); 199405d727e8SNithin Dabilpuram 199505d727e8SNithin Dabilpuram /* Bitmap for contiguous resource */ 199605d727e8SNithin Dabilpuram nix->schq_contig_bmp[hw_lvl] = 199705d727e8SNithin Dabilpuram plt_bitmap_init(NIX_TM_MAX_HW_TXSCHQ, bmp_mem, bmp_sz); 199805d727e8SNithin Dabilpuram if (!nix->schq_contig_bmp[hw_lvl]) 199905d727e8SNithin Dabilpuram goto exit; 200005d727e8SNithin Dabilpuram 200105d727e8SNithin Dabilpuram bmp_mem = PLT_PTR_ADD(bmp_mem, bmp_sz); 200205d727e8SNithin Dabilpuram } 200305d727e8SNithin Dabilpuram 20040b7e667eSSatha Rao rc = nix_tm_mark_init(nix); 20050b7e667eSSatha Rao if (rc) 20060b7e667eSSatha Rao goto exit; 20070b7e667eSSatha Rao 200805d727e8SNithin Dabilpuram /* Disable TL1 Static Priority when VF's are enabled 200905d727e8SNithin Dabilpuram * as otherwise VF's TL2 reallocation will be needed 201005d727e8SNithin Dabilpuram * runtime to support a specific topology of PF. 201105d727e8SNithin Dabilpuram */ 201205d727e8SNithin Dabilpuram if (nix->pci_dev->max_vfs) 201305d727e8SNithin Dabilpuram nix->tm_flags |= NIX_TM_TL1_NO_SP; 201405d727e8SNithin Dabilpuram 201505d727e8SNithin Dabilpuram /* TL1 access is only for PF's */ 201605d727e8SNithin Dabilpuram if (roc_nix_is_pf(roc_nix)) { 201705d727e8SNithin Dabilpuram nix->tm_flags |= NIX_TM_TL1_ACCESS; 201805d727e8SNithin Dabilpuram nix->tm_root_lvl = NIX_TXSCH_LVL_TL1; 201905d727e8SNithin Dabilpuram } else { 202005d727e8SNithin Dabilpuram nix->tm_root_lvl = NIX_TXSCH_LVL_TL2; 202105d727e8SNithin Dabilpuram } 202205d727e8SNithin Dabilpuram 202305d727e8SNithin Dabilpuram return 0; 202405d727e8SNithin Dabilpuram exit: 202505d727e8SNithin Dabilpuram nix_tm_conf_fini(roc_nix); 202605d727e8SNithin Dabilpuram return rc; 202705d727e8SNithin Dabilpuram } 202805d727e8SNithin Dabilpuram 202905d727e8SNithin Dabilpuram void 203005d727e8SNithin Dabilpuram nix_tm_conf_fini(struct roc_nix *roc_nix) 203105d727e8SNithin Dabilpuram { 203205d727e8SNithin Dabilpuram struct nix *nix = roc_nix_to_nix_priv(roc_nix); 203305d727e8SNithin Dabilpuram uint16_t hw_lvl; 203405d727e8SNithin Dabilpuram 203505d727e8SNithin Dabilpuram for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) { 203605d727e8SNithin Dabilpuram plt_bitmap_free(nix->schq_bmp[hw_lvl]); 203705d727e8SNithin Dabilpuram plt_bitmap_free(nix->schq_contig_bmp[hw_lvl]); 203805d727e8SNithin Dabilpuram } 203905d727e8SNithin Dabilpuram plt_free(nix->schq_bmp_mem); 204005d727e8SNithin Dabilpuram } 2041