@@ -214,6 +214,13 @@ roc_nix_lf_alloc(struct roc_nix *roc_nix, uint32_t nb_rxq, uint32_t nb_txq,
nix->tx_link = rsp->tx_link;
nix->nb_rx_queues = nb_rxq;
nix->nb_tx_queues = nb_txq;
+
+ nix->rqs = plt_zmalloc(sizeof(struct roc_nix_rq *) * nb_rxq, 0);
+ if (!nix->rqs) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
nix->sqs = plt_zmalloc(sizeof(struct roc_nix_sq *) * nb_txq, 0);
if (!nix->sqs) {
rc = -ENOMEM;
@@ -235,7 +242,9 @@ roc_nix_lf_free(struct roc_nix *roc_nix)
struct ndc_sync_op *ndc_req;
int rc = -ENOSPC;
+ plt_free(nix->rqs);
plt_free(nix->sqs);
+ nix->rqs = NULL;
nix->sqs = NULL;
/* Sync NDC-NIX for LF */
@@ -456,15 +465,6 @@ roc_nix_dev_init(struct roc_nix *roc_nix)
nix->reta_sz = reta_sz;
nix->mtu = ROC_NIX_DEFAULT_HW_FRS;
- /* Always start with full FC for LBK */
- if (nix->lbk_link) {
- nix->rx_pause = 1;
- nix->tx_pause = 1;
- } else if (!roc_nix_is_vf_or_sdp(roc_nix)) {
- /* Get the current state of flow control */
- roc_nix_fc_mode_get(roc_nix);
- }
-
/* Register error and ras interrupts */
rc = nix_register_irqs(nix);
if (rc)
@@ -328,6 +328,7 @@ struct roc_nix_rq {
struct roc_nix *roc_nix;
uint64_t meta_aura_handle;
uint16_t inl_dev_refs;
+ uint8_t tc;
};
struct roc_nix_cq {
@@ -879,6 +879,7 @@ roc_nix_rq_dump(struct roc_nix_rq *rq, FILE *file)
nix_dump(file, " vwqe_aura_handle = %ld", rq->vwqe_aura_handle);
nix_dump(file, " roc_nix = %p", rq->roc_nix);
nix_dump(file, " inl_dev_refs = %d", rq->inl_dev_refs);
+ nix_dump(file, " tc = %d", rq->tc);
}
void
@@ -911,6 +912,7 @@ roc_nix_sq_dump(struct roc_nix_sq *sq, FILE *file)
nix_dump(file, " lmt_addr = %p", sq->lmt_addr);
nix_dump(file, " sqe_mem = %p", sq->sqe_mem);
nix_dump(file, " fc = %p", sq->fc);
+ nix_dump(file, " tc = %d", sq->tc);
};
static uint8_t
@@ -278,9 +278,12 @@ nix_fc_cq_config_set(struct roc_nix *roc_nix, struct roc_nix_fc_cfg *fc_cfg)
static int
nix_fc_rq_config_set(struct roc_nix *roc_nix, struct roc_nix_fc_cfg *fc_cfg)
{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
struct roc_nix_fc_cfg tmp;
- int sso_ena = 0;
+ struct roc_nix_rq *rq;
+ int sso_ena = 0, rc;
+ rq = nix->rqs[fc_cfg->rq_cfg.rq];
/* Check whether RQ is connected to SSO or not */
sso_ena = roc_nix_rq_is_sso_enable(roc_nix, fc_cfg->rq_cfg.rq);
if (sso_ena < 0)
@@ -299,7 +302,14 @@ nix_fc_rq_config_set(struct roc_nix *roc_nix, struct roc_nix_fc_cfg *fc_cfg)
tmp.cq_cfg.cq_drop = fc_cfg->rq_cfg.cq_drop;
tmp.cq_cfg.enable = fc_cfg->rq_cfg.enable;
- return nix_fc_cq_config_set(roc_nix, &tmp);
+ rc = nix_fc_cq_config_set(roc_nix, &tmp);
+ if (rc)
+ return rc;
+
+ rq->tc = fc_cfg->rq_cfg.enable ? fc_cfg->rq_cfg.tc : ROC_NIX_PFC_CLASS_INVALID;
+ plt_nix_dbg("RQ %u: TC %u %s", fc_cfg->rq_cfg.rq, fc_cfg->rq_cfg.tc,
+ fc_cfg->rq_cfg.enable ? "enabled" : "disabled");
+ return 0;
}
int
@@ -334,7 +344,7 @@ roc_nix_fc_config_set(struct roc_nix *roc_nix, struct roc_nix_fc_cfg *fc_cfg)
else if (fc_cfg->type == ROC_NIX_FC_TM_CFG)
return nix_tm_bp_config_set(roc_nix, fc_cfg->tm_cfg.sq,
fc_cfg->tm_cfg.tc,
- fc_cfg->tm_cfg.enable, false);
+ fc_cfg->tm_cfg.enable);
return -EINVAL;
}
@@ -343,50 +353,17 @@ enum roc_nix_fc_mode
roc_nix_fc_mode_get(struct roc_nix *roc_nix)
{
struct nix *nix = roc_nix_to_nix_priv(roc_nix);
- struct dev *dev = &nix->dev;
- struct mbox *mbox = mbox_get(dev->mbox);
- struct cgx_pause_frm_cfg *req, *rsp;
enum roc_nix_fc_mode mode;
- int rc = -ENOSPC;
- /* Flow control on LBK link is always available */
- if (roc_nix_is_lbk(roc_nix)) {
- if (nix->tx_pause && nix->rx_pause)
- rc = ROC_NIX_FC_FULL;
- else if (nix->rx_pause)
- rc = ROC_NIX_FC_RX;
- else if (nix->tx_pause)
- rc = ROC_NIX_FC_TX;
- else
- rc = ROC_NIX_FC_NONE;
- goto exit;
- }
-
- req = mbox_alloc_msg_cgx_cfg_pause_frm(mbox);
- if (req == NULL)
- goto exit;
- req->set = 0;
-
- rc = mbox_process_msg(mbox, (void *)&rsp);
- if (rc)
- goto exit;
-
- if (rsp->rx_pause && rsp->tx_pause)
+ if (nix->tx_pause && nix->rx_pause)
mode = ROC_NIX_FC_FULL;
- else if (rsp->rx_pause)
+ else if (nix->rx_pause)
mode = ROC_NIX_FC_RX;
- else if (rsp->tx_pause)
+ else if (nix->tx_pause)
mode = ROC_NIX_FC_TX;
else
mode = ROC_NIX_FC_NONE;
-
- nix->rx_pause = rsp->rx_pause;
- nix->tx_pause = rsp->tx_pause;
- rc = mode;
-
-exit:
- mbox_put(mbox);
- return rc;
+ return mode;
}
int
@@ -570,8 +547,8 @@ roc_nix_pfc_mode_set(struct roc_nix *roc_nix, struct roc_nix_pfc_cfg *pfc_cfg)
if (rc)
goto exit;
- nix->rx_pause = rsp->rx_pause;
- nix->tx_pause = rsp->tx_pause;
+ nix->pfc_rx_pause = rsp->rx_pause;
+ nix->pfc_tx_pause = rsp->tx_pause;
if (rsp->tx_pause)
nix->cev |= BIT(pfc_cfg->tc);
else
@@ -592,11 +569,11 @@ roc_nix_pfc_mode_get(struct roc_nix *roc_nix, struct roc_nix_pfc_cfg *pfc_cfg)
pfc_cfg->tc = nix->cev;
- if (nix->rx_pause && nix->tx_pause)
+ if (nix->pfc_rx_pause && nix->pfc_tx_pause)
pfc_cfg->mode = ROC_NIX_FC_FULL;
- else if (nix->rx_pause)
+ else if (nix->pfc_rx_pause)
pfc_cfg->mode = ROC_NIX_FC_RX;
- else if (nix->tx_pause)
+ else if (nix->pfc_tx_pause)
pfc_cfg->mode = ROC_NIX_FC_TX;
else
pfc_cfg->mode = ROC_NIX_FC_NONE;
@@ -102,7 +102,6 @@ struct nix_tm_node {
/* Last stats */
uint64_t last_pkts;
uint64_t last_bytes;
- uint32_t tc_refcnt;
};
struct nix_tm_shaper_profile {
@@ -131,6 +130,7 @@ struct nix {
struct nix_qint *cints_mem;
uint8_t configured_qints;
uint8_t configured_cints;
+ struct roc_nix_rq **rqs;
struct roc_nix_sq **sqs;
uint16_t vwqe_interval;
uint16_t tx_chan_base;
@@ -158,6 +158,8 @@ struct nix {
uint16_t msixoff;
uint8_t rx_pause;
uint8_t tx_pause;
+ uint8_t pfc_rx_pause;
+ uint8_t pfc_tx_pause;
uint16_t cev;
uint64_t rx_cfg;
struct dev dev;
@@ -407,7 +409,7 @@ int nix_rq_cfg(struct dev *dev, struct roc_nix_rq *rq, uint16_t qints, bool cfg,
int nix_rq_ena_dis(struct dev *dev, struct roc_nix_rq *rq, bool enable);
int nix_tm_bp_config_get(struct roc_nix *roc_nix, bool *is_enabled);
int nix_tm_bp_config_set(struct roc_nix *roc_nix, uint16_t sq, uint16_t tc,
- bool enable, bool force_flush);
+ bool enable);
void nix_rq_vwqe_flush(struct roc_nix_rq *rq, uint16_t vwqe_interval);
int nix_tm_mark_init(struct nix *nix);
void nix_tm_sq_free_sqe_buffer(uint64_t *sqe, int head_off, int end_off, int instr_sz);
@@ -469,6 +471,7 @@ int nix_lf_int_reg_dump(uintptr_t nix_lf_base, uint64_t *data, uint16_t qints,
uint16_t cints);
int nix_q_ctx_get(struct dev *dev, uint8_t ctype, uint16_t qid,
__io void **ctx_p);
+uint8_t nix_tm_lbk_relchan_get(struct nix *nix);
/*
* Telemetry
@@ -667,6 +667,7 @@ roc_nix_rq_init(struct roc_nix *roc_nix, struct roc_nix_rq *rq, bool ena)
}
rq->roc_nix = roc_nix;
+ rq->tc = ROC_NIX_PFC_CLASS_INVALID;
if (is_cn9k)
rc = nix_rq_cn9k_cfg(dev, rq, nix->qints, false, ena);
@@ -695,6 +696,7 @@ roc_nix_rq_init(struct roc_nix *roc_nix, struct roc_nix_rq *rq, bool ena)
return rc;
}
+ nix->rqs[rq->qid] = rq;
return nix_tel_node_add_rq(rq);
}
@@ -718,6 +720,7 @@ roc_nix_rq_modify(struct roc_nix *roc_nix, struct roc_nix_rq *rq, bool ena)
nix_rq_aura_buf_type_update(rq, false);
rq->roc_nix = roc_nix;
+ rq->tc = ROC_NIX_PFC_CLASS_INVALID;
mbox = mbox_get(m_box);
if (is_cn9k)
@@ -779,6 +782,7 @@ roc_nix_rq_cman_config(struct roc_nix *roc_nix, struct roc_nix_rq *rq)
int
roc_nix_rq_fini(struct roc_nix_rq *rq)
{
+ struct nix *nix = roc_nix_to_nix_priv(rq->roc_nix);
int rc;
/* Disabling RQ is sufficient */
@@ -788,6 +792,8 @@ roc_nix_rq_fini(struct roc_nix_rq *rq)
/* Update aura attribute to indicate its use for */
nix_rq_aura_buf_type_update(rq, false);
+
+ nix->rqs[rq->qid] = NULL;
return 0;
}
@@ -895,14 +901,6 @@ roc_nix_cq_init(struct roc_nix *roc_nix, struct roc_nix_cq *cq)
}
}
- /* TX pause frames enable flow ctrl on RX side */
- if (nix->tx_pause) {
- /* Single BPID is allocated for all rx channels for now */
- cq_ctx->bpid = nix->bpid[0];
- cq_ctx->bp = cq->drop_thresh;
- cq_ctx->bp_ena = 1;
- }
-
rc = mbox_process(mbox);
mbox_put(mbox);
if (rc)
@@ -101,7 +101,6 @@ 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;
- bool skip_bp = false;
uint32_t hw_lvl;
int rc = 0;
@@ -116,11 +115,8 @@ nix_tm_txsch_reg_config(struct nix *nix, enum roc_nix_tm_tree tree)
* set per channel only for PF or lbk vf.
*/
node->bp_capa = 0;
- if (!nix->sdp_link && !skip_bp &&
- node->hw_lvl == nix->tm_link_cfg_lvl) {
+ if (!nix->sdp_link && node->hw_lvl == nix->tm_link_cfg_lvl)
node->bp_capa = 1;
- skip_bp = false;
- }
rc = nix_tm_node_reg_conf(nix, node);
if (rc)
@@ -315,7 +311,7 @@ nix_tm_clear_path_xoff(struct nix *nix, struct nix_tm_node *node)
int
nix_tm_bp_config_set(struct roc_nix *roc_nix, uint16_t sq, uint16_t tc,
- bool enable, bool force_flush)
+ bool enable)
{
struct nix *nix = roc_nix_to_nix_priv(roc_nix);
enum roc_nix_tm_tree tree = nix->tm_tree;
@@ -327,9 +323,10 @@ nix_tm_bp_config_set(struct roc_nix *roc_nix, uint16_t sq, uint16_t tc,
struct nix_tm_node *parent;
struct nix_tm_node *node;
struct roc_nix_sq *sq_s;
+ uint16_t rel_chan = 0;
uint8_t parent_lvl;
uint8_t k = 0;
- int rc = 0;
+ int rc = 0, i;
sq_s = nix->sqs[sq];
if (!sq_s)
@@ -354,9 +351,17 @@ nix_tm_bp_config_set(struct roc_nix *roc_nix, uint16_t sq, uint16_t tc,
list = nix_tm_node_list(nix, tree);
+ /* Get relative channel if loopback */
+ if (roc_nix_is_lbk(roc_nix))
+ rel_chan = nix_tm_lbk_relchan_get(nix);
+ else
+ rel_chan = tc;
+
/* Enable request, parent rel chan already configured */
if (enable && parent->rel_chan != NIX_TM_CHAN_INVALID &&
- parent->rel_chan != tc) {
+ parent->rel_chan != rel_chan) {
+ plt_err("SQ %d: parent node TL3 id %d already has rel_chan %d set",
+ sq, parent->hw_id, parent->rel_chan);
rc = -EINVAL;
goto err;
}
@@ -378,36 +383,21 @@ nix_tm_bp_config_set(struct roc_nix *roc_nix, uint16_t sq, uint16_t tc,
continue;
/* Restrict sharing of TL3 across the queues */
- if (enable && node != parent && node->rel_chan == tc) {
- plt_err("SQ %d node TL3 id %d already has %d tc value set",
- sq, node->hw_id, tc);
- return -EINVAL;
+ if (enable && node != parent && node->rel_chan == rel_chan) {
+ plt_warn("SQ %d: siblng node TL3 %d already has %d(%d) tc value set",
+ sq, node->hw_id, tc, rel_chan);
+ return -EEXIST;
}
}
- /* In case of user tree i.e. multiple SQs may share a TL3, disabling PFC
- * on one of such SQ should not hamper the traffic control on other SQs.
- * Maitaining a reference count scheme to account no of SQs sharing the
- * TL3 before disabling PFC on it.
- */
- if (!force_flush && !enable &&
- parent->rel_chan != NIX_TM_CHAN_INVALID) {
- if (sq_s->tc != ROC_NIX_PFC_CLASS_INVALID)
- parent->tc_refcnt--;
- if (parent->tc_refcnt > 0)
- return 0;
- }
+ /* Allocating TL3 request */
+ req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
+ req->lvl = nix->tm_link_cfg_lvl;
+ k = 0;
- /* Allocating TL3 resources */
- if (!req) {
- req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
- req->lvl = nix->tm_link_cfg_lvl;
- k = 0;
- }
-
- /* Enable PFC on the identified TL3 */
+ /* Enable PFC/pause on the identified TL3 */
req->reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(parent->hw_id, link);
- req->regval[k] = enable ? tc : 0;
+ req->regval[k] = enable ? rel_chan : 0;
req->regval[k] |= enable ? BIT_ULL(13) : 0;
req->regval_mask[k] = ~(BIT_ULL(13) | GENMASK_ULL(7, 0));
k++;
@@ -417,12 +407,17 @@ nix_tm_bp_config_set(struct roc_nix *roc_nix, uint16_t sq, uint16_t tc,
if (rc)
goto err;
- parent->rel_chan = enable ? tc : NIX_TM_CHAN_INVALID;
- /* Increase reference count for parent TL3 */
- if (enable && sq_s->tc == ROC_NIX_PFC_CLASS_INVALID)
- parent->tc_refcnt++;
+ parent->rel_chan = enable ? rel_chan : NIX_TM_CHAN_INVALID;
+ sq_s->tc = enable ? tc : ROC_NIX_PFC_CLASS_INVALID;
+ /* Clear other SQ's with same TC i.e same parent node */
+ for (i = 0; !enable && i < nix->nb_tx_queues; i++) {
+ if (nix->sqs[i] && nix->sqs[i]->tc == tc)
+ nix->sqs[i]->tc = ROC_NIX_PFC_CLASS_INVALID;
+ }
rc = 0;
+ plt_tm_dbg("SQ %u: TL3 %d TC %u %s",
+ sq, parent->hw_id, tc, enable ? "enabled" : "disabled");
goto exit;
err:
plt_err("Failed to %s bp on link %u, rc=%d(%s)",
@@ -802,7 +797,7 @@ nix_tm_sq_flush_pre(struct roc_nix_sq *sq)
}
/* Disable backpressure */
- rc = nix_tm_bp_config_set(roc_nix, sq->qid, 0, false, true);
+ rc = nix_tm_bp_config_set(roc_nix, sq->qid, 0, false);
if (rc) {
plt_err("Failed to disable backpressure for flush, rc=%d", rc);
return rc;
@@ -942,16 +937,6 @@ nix_tm_sq_flush_post(struct roc_nix_sq *sq)
}
}
- if (!nix->rx_pause)
- return 0;
-
- /* Restore backpressure */
- rc = nix_tm_bp_config_set(roc_nix, sq->qid, sq->tc, true, false);
- if (rc) {
- plt_err("Failed to restore backpressure, rc=%d", rc);
- return rc;
- }
-
return 0;
}
@@ -481,7 +481,7 @@ roc_nix_tm_hierarchy_disable(struct roc_nix *roc_nix)
if (!sq)
continue;
- rc = nix_tm_bp_config_set(roc_nix, sq->qid, 0, false, false);
+ rc = nix_tm_bp_config_set(roc_nix, sq->qid, 0, false);
if (rc && rc != -ENOENT) {
plt_err("Failed to disable backpressure, rc=%d", rc);
goto cleanup;
@@ -72,8 +72,8 @@ nix_tm_lvl2nix(struct nix *nix, uint32_t lvl)
return nix_tm_lvl2nix_tl2_root(lvl);
}
-static uint8_t
-nix_tm_relchan_get(struct nix *nix)
+uint8_t
+nix_tm_lbk_relchan_get(struct nix *nix)
{
return nix->tx_chan_base & 0xff;
}
@@ -531,7 +531,7 @@ nix_tm_topology_reg_prep(struct nix *nix, struct nix_tm_node *node,
parent = node->parent->hw_id;
link = nix->tx_link;
- relchan = nix_tm_relchan_get(nix);
+ relchan = roc_nix_is_lbk(roc_nix) ? nix_tm_lbk_relchan_get(nix) : 0;
if (hw_lvl != NIX_TXSCH_LVL_SMQ)
child = nix_tm_find_prio_anchor(nix, node->id, tree);
@@ -602,10 +602,6 @@ nix_tm_topology_reg_prep(struct nix *nix, struct nix_tm_node *node,
nix->tm_link_cfg_lvl == NIX_TXSCH_LVL_TL3) {
reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, link);
regval[k] = BIT_ULL(12) | relchan;
- /* Enable BP if node is BP capable and rx_pause is set
- */
- if (nix->rx_pause && node->bp_capa)
- regval[k] |= BIT_ULL(13);
k++;
}
@@ -625,10 +621,6 @@ nix_tm_topology_reg_prep(struct nix *nix, struct nix_tm_node *node,
nix->tm_link_cfg_lvl == NIX_TXSCH_LVL_TL2) {
reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, link);
regval[k] = BIT_ULL(12) | relchan;
- /* Enable BP if node is BP capable and rx_pause is set
- */
- if (nix->rx_pause && node->bp_capa)
- regval[k] |= BIT_ULL(13);
k++;
}