X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fcommon%2Fcnxk%2Froc_nix_tm.c;h=ad54e17a282743393433440a9357f0f254bee2c4;hb=7fb5075a539e806e5f482fa6e3d699a58adbd70f;hp=581de4b5b7d426db51ab9c24454c1a293e37e875;hpb=df405df95eeb691a146dab57a2c204ac406e3ed4;p=dpdk.git diff --git a/drivers/common/cnxk/roc_nix_tm.c b/drivers/common/cnxk/roc_nix_tm.c index 581de4b5b7..ad54e17a28 100644 --- a/drivers/common/cnxk/roc_nix_tm.c +++ b/drivers/common/cnxk/roc_nix_tm.c @@ -30,6 +30,93 @@ nix_tm_clear_shaper_profiles(struct nix *nix) } } +static int +nix_tm_node_reg_conf(struct nix *nix, struct nix_tm_node *node) +{ + uint64_t regval_mask[MAX_REGS_PER_MBOX_MSG]; + uint64_t regval[MAX_REGS_PER_MBOX_MSG]; + struct nix_tm_shaper_profile *profile; + uint64_t reg[MAX_REGS_PER_MBOX_MSG]; + struct mbox *mbox = (&nix->dev)->mbox; + struct nix_txschq_config *req; + int rc = -EFAULT; + uint32_t hw_lvl; + uint8_t k = 0; + + memset(regval, 0, sizeof(regval)); + memset(regval_mask, 0, sizeof(regval_mask)); + + profile = nix_tm_shaper_profile_search(nix, node->shaper_profile_id); + hw_lvl = node->hw_lvl; + + /* Need this trigger to configure TL1 */ + if (!nix_tm_have_tl1_access(nix) && hw_lvl == NIX_TXSCH_LVL_TL2) { + /* Prepare default conf for TL1 */ + req = mbox_alloc_msg_nix_txschq_cfg(mbox); + req->lvl = NIX_TXSCH_LVL_TL1; + + k = nix_tm_tl1_default_prep(node->parent_hw_id, req->reg, + req->regval); + req->num_regs = k; + rc = mbox_process(mbox); + if (rc) + goto error; + } + + /* Prepare topology config */ + k = nix_tm_topology_reg_prep(nix, node, reg, regval, regval_mask); + + /* Prepare schedule config */ + k += nix_tm_sched_reg_prep(nix, node, ®[k], ®val[k]); + + /* Prepare shaping config */ + k += nix_tm_shaper_reg_prep(node, profile, ®[k], ®val[k]); + + if (!k) + return 0; + + /* Copy and send config mbox */ + req = mbox_alloc_msg_nix_txschq_cfg(mbox); + req->lvl = hw_lvl; + req->num_regs = k; + + mbox_memcpy(req->reg, reg, sizeof(uint64_t) * k); + mbox_memcpy(req->regval, regval, sizeof(uint64_t) * k); + mbox_memcpy(req->regval_mask, regval_mask, sizeof(uint64_t) * k); + + rc = mbox_process(mbox); + if (rc) + goto error; + + return 0; +error: + plt_err("Txschq conf failed for node %p, rc=%d", node, rc); + return rc; +} + +int +nix_tm_txsch_reg_config(struct nix *nix, enum roc_nix_tm_tree tree) +{ + struct nix_tm_node_list *list; + struct nix_tm_node *node; + uint32_t hw_lvl; + int rc = 0; + + list = nix_tm_node_list(nix, tree); + + for (hw_lvl = 0; hw_lvl <= nix->tm_root_lvl; hw_lvl++) { + TAILQ_FOREACH(node, list, node) { + if (node->hw_lvl != hw_lvl) + continue; + rc = nix_tm_node_reg_conf(nix, node); + if (rc) + goto exit; + } + } +exit: + return rc; +} + int nix_tm_update_parent_info(struct nix *nix, enum roc_nix_tm_tree tree) { @@ -306,6 +393,7 @@ roc_nix_tm_sq_flush_spin(struct roc_nix_sq *sq) return 0; exit: + roc_nix_tm_dump(sq->roc_nix); roc_nix_queues_ctx_dump(sq->roc_nix); return -EFAULT; } @@ -477,6 +565,66 @@ nix_tm_sq_flush_post(struct roc_nix_sq *sq) return 0; } +int +nix_tm_sq_sched_conf(struct nix *nix, struct nix_tm_node *node, + bool rr_quantum_only) +{ + struct mbox *mbox = (&nix->dev)->mbox; + uint16_t qid = node->id, smq; + uint64_t rr_quantum; + int rc; + + smq = node->parent->hw_id; + rr_quantum = nix_tm_weight_to_rr_quantum(node->weight); + + if (rr_quantum_only) + plt_tm_dbg("Update sq(%u) rr_quantum 0x%" PRIx64, qid, + rr_quantum); + else + plt_tm_dbg("Enabling sq(%u)->smq(%u), rr_quantum 0x%" PRIx64, + qid, smq, rr_quantum); + + if (qid > nix->nb_tx_queues) + return -EFAULT; + + if (roc_model_is_cn9k()) { + struct nix_aq_enq_req *aq; + + aq = mbox_alloc_msg_nix_aq_enq(mbox); + aq->qidx = qid; + aq->ctype = NIX_AQ_CTYPE_SQ; + aq->op = NIX_AQ_INSTOP_WRITE; + + /* smq update only when needed */ + if (!rr_quantum_only) { + aq->sq.smq = smq; + aq->sq_mask.smq = ~aq->sq_mask.smq; + } + aq->sq.smq_rr_quantum = rr_quantum; + aq->sq_mask.smq_rr_quantum = ~aq->sq_mask.smq_rr_quantum; + } else { + struct nix_cn10k_aq_enq_req *aq; + + aq = mbox_alloc_msg_nix_cn10k_aq_enq(mbox); + aq->qidx = qid; + aq->ctype = NIX_AQ_CTYPE_SQ; + aq->op = NIX_AQ_INSTOP_WRITE; + + /* smq update only when needed */ + if (!rr_quantum_only) { + aq->sq.smq = smq; + aq->sq_mask.smq = ~aq->sq_mask.smq; + } + aq->sq.smq_rr_weight = rr_quantum; + aq->sq_mask.smq_rr_weight = ~aq->sq_mask.smq_rr_weight; + } + + rc = mbox_process(mbox); + if (rc) + plt_err("Failed to set smq, rc=%d", rc); + return rc; +} + int nix_tm_release_resources(struct nix *nix, uint8_t hw_lvl, bool contig, bool above_thresh) @@ -941,6 +1089,162 @@ alloc_err: return rc; } +int +nix_tm_prepare_default_tree(struct roc_nix *roc_nix) +{ + struct nix *nix = roc_nix_to_nix_priv(roc_nix); + uint32_t nonleaf_id = nix->nb_tx_queues; + struct nix_tm_node *node = NULL; + uint8_t leaf_lvl, lvl, lvl_end; + uint32_t parent, i; + int rc = 0; + + /* Add ROOT, SCH1, SCH2, SCH3, [SCH4] nodes */ + parent = ROC_NIX_TM_NODE_ID_INVALID; + /* With TL1 access we have an extra level */ + lvl_end = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH4 : + ROC_TM_LVL_SCH3); + + for (lvl = ROC_TM_LVL_ROOT; lvl <= lvl_end; lvl++) { + rc = -ENOMEM; + node = nix_tm_node_alloc(); + if (!node) + goto error; + + node->id = nonleaf_id; + node->parent_id = parent; + node->priority = 0; + node->weight = NIX_TM_DFLT_RR_WT; + node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE; + node->lvl = lvl; + node->tree = ROC_NIX_TM_DEFAULT; + + rc = nix_tm_node_add(roc_nix, node); + if (rc) + goto error; + parent = nonleaf_id; + nonleaf_id++; + } + + parent = nonleaf_id - 1; + leaf_lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_QUEUE : + ROC_TM_LVL_SCH4); + + /* Add leaf nodes */ + for (i = 0; i < nix->nb_tx_queues; i++) { + rc = -ENOMEM; + node = nix_tm_node_alloc(); + if (!node) + goto error; + + node->id = i; + node->parent_id = parent; + node->priority = 0; + node->weight = NIX_TM_DFLT_RR_WT; + node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE; + node->lvl = leaf_lvl; + node->tree = ROC_NIX_TM_DEFAULT; + + rc = nix_tm_node_add(roc_nix, node); + if (rc) + goto error; + } + + return 0; +error: + nix_tm_node_free(node); + return rc; +} + +int +nix_tm_prepare_rate_limited_tree(struct roc_nix *roc_nix) +{ + struct nix *nix = roc_nix_to_nix_priv(roc_nix); + uint32_t nonleaf_id = nix->nb_tx_queues; + struct nix_tm_node *node = NULL; + uint8_t leaf_lvl, lvl, lvl_end; + uint32_t parent, i; + int rc = 0; + + /* Add ROOT, SCH1, SCH2 nodes */ + parent = ROC_NIX_TM_NODE_ID_INVALID; + lvl_end = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH3 : + ROC_TM_LVL_SCH2); + + for (lvl = ROC_TM_LVL_ROOT; lvl <= lvl_end; lvl++) { + rc = -ENOMEM; + node = nix_tm_node_alloc(); + if (!node) + goto error; + + node->id = nonleaf_id; + node->parent_id = parent; + node->priority = 0; + node->weight = NIX_TM_DFLT_RR_WT; + node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE; + node->lvl = lvl; + node->tree = ROC_NIX_TM_RLIMIT; + + rc = nix_tm_node_add(roc_nix, node); + if (rc) + goto error; + parent = nonleaf_id; + nonleaf_id++; + } + + /* SMQ is mapped to SCH4 when we have TL1 access and SCH3 otherwise */ + lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH4 : ROC_TM_LVL_SCH3); + + /* Add per queue SMQ nodes i.e SCH4 / SCH3 */ + for (i = 0; i < nix->nb_tx_queues; i++) { + rc = -ENOMEM; + node = nix_tm_node_alloc(); + if (!node) + goto error; + + node->id = nonleaf_id + i; + node->parent_id = parent; + node->priority = 0; + node->weight = NIX_TM_DFLT_RR_WT; + node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE; + node->lvl = lvl; + node->tree = ROC_NIX_TM_RLIMIT; + + rc = nix_tm_node_add(roc_nix, node); + if (rc) + goto error; + } + + parent = nonleaf_id; + leaf_lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_QUEUE : + ROC_TM_LVL_SCH4); + + /* Add leaf nodes */ + for (i = 0; i < nix->nb_tx_queues; i++) { + rc = -ENOMEM; + node = nix_tm_node_alloc(); + if (!node) + goto error; + + node->id = i; + node->parent_id = parent; + node->priority = 0; + node->weight = NIX_TM_DFLT_RR_WT; + node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE; + node->lvl = leaf_lvl; + node->tree = ROC_NIX_TM_RLIMIT; + + rc = nix_tm_node_add(roc_nix, node); + if (rc) + goto error; + } + + return 0; +error: + nix_tm_node_free(node); + return rc; +} + int nix_tm_free_resources(struct roc_nix *roc_nix, uint32_t tree_mask, bool hw_only) {