else
fc_cfg->rxchan_cfg.enable = false;
- fc_cfg->cq_cfg_valid = false;
+ fc_cfg->type = ROC_NIX_FC_RXCHAN_CFG;
return 0;
}
fc_cfg->cq_cfg.cq_drop = rsp->cq.bp;
fc_cfg->cq_cfg.enable = rsp->cq.bp_ena;
- fc_cfg->cq_cfg_valid = true;
+ fc_cfg->type = ROC_NIX_FC_CQ_CFG;
exit:
return rc;
if (roc_nix_is_vf_or_sdp(roc_nix) && !roc_nix_is_lbk(roc_nix))
return 0;
- if (fc_cfg->cq_cfg_valid)
+ if (fc_cfg->type == ROC_NIX_FC_CQ_CFG)
return nix_fc_cq_config_get(roc_nix, fc_cfg);
- else
+ else if (fc_cfg->type == ROC_NIX_FC_RXCHAN_CFG)
return nix_fc_rxchan_bpid_get(roc_nix, fc_cfg);
+ else if (fc_cfg->type == ROC_NIX_FC_TM_CFG)
+ return nix_tm_bp_config_get(roc_nix, &fc_cfg->tm_cfg.enable);
+
+ return -EINVAL;
}
int
if (roc_nix_is_vf_or_sdp(roc_nix) && !roc_nix_is_lbk(roc_nix))
return 0;
- if (fc_cfg->cq_cfg_valid)
+ if (fc_cfg->type == ROC_NIX_FC_CQ_CFG)
return nix_fc_cq_config_set(roc_nix, fc_cfg);
- else
+ else if (fc_cfg->type == ROC_NIX_FC_RXCHAN_CFG)
return nix_fc_rxchan_bpid_set(roc_nix,
fc_cfg->rxchan_cfg.enable);
+ else if (fc_cfg->type == ROC_NIX_FC_TM_CFG)
+ return nix_tm_bp_config_set(roc_nix, fc_cfg->tm_cfg.enable);
+
+ return -EINVAL;
}
enum roc_nix_fc_mode
nix_tm_txsch_reg_config(struct nix *nix, enum roc_nix_tm_tree tree)
{
struct nix_tm_node_list *list;
+ bool is_pf_or_lbk = false;
struct nix_tm_node *node;
+ bool skip_bp = false;
uint32_t hw_lvl;
int rc = 0;
list = nix_tm_node_list(nix, tree);
+ if ((!dev_is_vf(&nix->dev) || nix->lbk_link) && !nix->sdp_link)
+ is_pf_or_lbk = true;
+
for (hw_lvl = 0; hw_lvl <= nix->tm_root_lvl; hw_lvl++) {
TAILQ_FOREACH(node, list, node) {
if (node->hw_lvl != hw_lvl)
continue;
+
+ /* Only one TL3/TL2 Link config should have BP enable
+ * set per channel only for PF or lbk vf.
+ */
+ node->bp_capa = 0;
+ if (is_pf_or_lbk && !skip_bp &&
+ node->hw_lvl == nix->tm_link_cfg_lvl) {
+ node->bp_capa = 1;
+ skip_bp = true;
+ }
+
rc = nix_tm_node_reg_conf(nix, node);
if (rc)
goto exit;
return 0;
}
+int
+nix_tm_bp_config_set(struct roc_nix *roc_nix, bool enable)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ enum roc_nix_tm_tree tree = nix->tm_tree;
+ struct mbox *mbox = (&nix->dev)->mbox;
+ struct nix_txschq_config *req = NULL;
+ struct nix_tm_node_list *list;
+ struct nix_tm_node *node;
+ uint8_t k = 0;
+ uint16_t link;
+ int rc = 0;
+
+ list = nix_tm_node_list(nix, tree);
+ link = nix->tx_link;
+
+ TAILQ_FOREACH(node, list, node) {
+ if (node->hw_lvl != nix->tm_link_cfg_lvl)
+ continue;
+
+ if (!(node->flags & NIX_TM_NODE_HWRES) || !node->bp_capa)
+ continue;
+
+ if (!req) {
+ req = mbox_alloc_msg_nix_txschq_cfg(mbox);
+ req->lvl = nix->tm_link_cfg_lvl;
+ k = 0;
+ }
+
+ req->reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(node->hw_id, link);
+ req->regval[k] = enable ? BIT_ULL(13) : 0;
+ req->regval_mask[k] = ~BIT_ULL(13);
+ k++;
+
+ if (k >= MAX_REGS_PER_MBOX_MSG) {
+ req->num_regs = k;
+ rc = mbox_process(mbox);
+ if (rc)
+ goto err;
+ req = NULL;
+ }
+ }
+
+ if (req) {
+ req->num_regs = k;
+ rc = mbox_process(mbox);
+ if (rc)
+ goto err;
+ }
+
+ return 0;
+err:
+ plt_err("Failed to %s bp on link %u, rc=%d(%s)",
+ enable ? "enable" : "disable", link, rc, roc_error_msg_get(rc));
+ return rc;
+}
+
+int
+nix_tm_bp_config_get(struct roc_nix *roc_nix, bool *is_enabled)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ struct nix_txschq_config *req = NULL, *rsp;
+ enum roc_nix_tm_tree tree = nix->tm_tree;
+ struct mbox *mbox = (&nix->dev)->mbox;
+ struct nix_tm_node_list *list;
+ struct nix_tm_node *node;
+ bool found = false;
+ uint8_t enable = 1;
+ uint8_t k = 0, i;
+ uint16_t link;
+ int rc = 0;
+
+ list = nix_tm_node_list(nix, tree);
+ link = nix->tx_link;
+
+ TAILQ_FOREACH(node, list, node) {
+ if (node->hw_lvl != nix->tm_link_cfg_lvl)
+ continue;
+
+ if (!(node->flags & NIX_TM_NODE_HWRES) || !node->bp_capa)
+ continue;
+
+ found = true;
+ if (!req) {
+ req = mbox_alloc_msg_nix_txschq_cfg(mbox);
+ req->read = 1;
+ req->lvl = nix->tm_link_cfg_lvl;
+ k = 0;
+ }
+
+ req->reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(node->hw_id, link);
+ k++;
+
+ if (k >= MAX_REGS_PER_MBOX_MSG) {
+ req->num_regs = k;
+ rc = mbox_process_msg(mbox, (void **)&rsp);
+ if (rc || rsp->num_regs != k)
+ goto err;
+ req = NULL;
+
+ /* Report it as enabled only if enabled or all */
+ for (i = 0; i < k; i++)
+ enable &= !!(rsp->regval[i] & BIT_ULL(13));
+ }
+ }
+
+ if (req) {
+ req->num_regs = k;
+ rc = mbox_process(mbox);
+ if (rc)
+ goto err;
+ /* Report it as enabled only if enabled or all */
+ for (i = 0; i < k; i++)
+ enable &= !!(rsp->regval[i] & BIT_ULL(13));
+ }
+
+ *is_enabled = found ? !!enable : false;
+ return 0;
+err:
+ plt_err("Failed to get bp status on link %u, rc=%d(%s)", link, rc,
+ roc_error_msg_get(rc));
+ return rc;
+}
+
int
nix_tm_smq_xoff(struct nix *nix, struct nix_tm_node *node, bool enable)
{
}
}
+ /* Disable backpressure */
+ rc = nix_tm_bp_config_set(roc_nix, false);
+ if (rc) {
+ plt_err("Failed to disable backpressure for flush, rc=%d", rc);
+ return rc;
+ }
+
/* Disable smq xoff for case it was enabled earlier */
rc = nix_tm_smq_xoff(nix, node->parent, false);
if (rc) {
}
}
+ if (!nix->rx_pause)
+ return 0;
+
+ /* Restore backpressure */
+ rc = nix_tm_bp_config_set(roc_nix, true);
+ if (rc) {
+ plt_err("Failed to restore backpressure, rc=%d", rc);
+ return rc;
+ }
+
return 0;
}