From: Harman Kalra <hka...@marvell.com>

User may want to configure same TC value across multiple queues, but
for that all queues should have a common TL3 where this TC value will
get configured.

Changed the pfc_tc_cq_map/pfc_tc_sq_map array indexing to qid and store
TC values in the array. As multiple queues may have same TC value.

Signed-off-by: Harman Kalra <hka...@marvell.com>
---
 drivers/common/cnxk/roc_dev.c        | 18 ++++++++
 drivers/common/cnxk/roc_nix.h        |  4 +-
 drivers/common/cnxk/roc_nix_fc.c     |  2 +-
 drivers/common/cnxk/roc_nix_priv.h   |  3 +-
 drivers/common/cnxk/roc_nix_tm.c     | 87 ++++++++++++++++++++++++------------
 drivers/common/cnxk/roc_nix_tm_ops.c |  3 +-
 6 files changed, 84 insertions(+), 33 deletions(-)

diff --git a/drivers/common/cnxk/roc_dev.c b/drivers/common/cnxk/roc_dev.c
index 09199ac..59128a3 100644
--- a/drivers/common/cnxk/roc_dev.c
+++ b/drivers/common/cnxk/roc_dev.c
@@ -421,6 +421,24 @@ process_msgs(struct dev *dev, struct mbox *mbox)
                        /* Get our identity */
                        dev->pf_func = msg->pcifunc;
                        break;
+               case MBOX_MSG_CGX_PRIO_FLOW_CTRL_CFG:
+                       /* Handling the case where one VF tries to disable PFC
+                        * while PFC already configured on other VFs. This is
+                        * not an error but a warning which can be ignored.
+                        */
+#define LMAC_AF_ERR_PERM_DENIED -1103
+                       if (msg->rc) {
+                               if (msg->rc == LMAC_AF_ERR_PERM_DENIED) {
+                                       plt_mbox_dbg(
+                                               "Receive Flow control disable 
not permitted "
+                                               "as its used by other PFVFs");
+                                       msg->rc = 0;
+                               } else {
+                                       plt_err("Message (%s) response has 
err=%d",
+                                               mbox_id2name(msg->id), msg->rc);
+                               }
+                       }
+                       break;
 
                default:
                        if (msg->rc)
diff --git a/drivers/common/cnxk/roc_nix.h b/drivers/common/cnxk/roc_nix.h
index f0d7fc8..4e5cf05 100644
--- a/drivers/common/cnxk/roc_nix.h
+++ b/drivers/common/cnxk/roc_nix.h
@@ -11,7 +11,8 @@
 #define ROC_NIX_BPF_LEVEL_IDX_INVALID 0xFF
 #define ROC_NIX_BPF_LEVEL_MAX        3
 #define ROC_NIX_BPF_STATS_MAX        12
-#define ROC_NIX_MTR_ID_INVALID       UINT32_MAX
+#define ROC_NIX_MTR_ID_INVALID       UINT32_MAX
+#define ROC_NIX_PFC_CLASS_INVALID     UINT8_MAX
 
 enum roc_nix_rss_reta_sz {
        ROC_NIX_RSS_RETA_SZ_64 = 64,
@@ -349,6 +350,7 @@ struct roc_nix_sq {
        void *lmt_addr;
        void *sqe_mem;
        void *fc;
+       uint8_t tc;
 };
 
 struct roc_nix_link_info {
diff --git a/drivers/common/cnxk/roc_nix_fc.c b/drivers/common/cnxk/roc_nix_fc.c
index daae285..f4cfa11 100644
--- a/drivers/common/cnxk/roc_nix_fc.c
+++ b/drivers/common/cnxk/roc_nix_fc.c
@@ -312,7 +312,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);
+                                           fc_cfg->tm_cfg.enable, false);
 
        return -EINVAL;
 }
diff --git a/drivers/common/cnxk/roc_nix_priv.h 
b/drivers/common/cnxk/roc_nix_priv.h
index 5e865f8..5b0522c 100644
--- a/drivers/common/cnxk/roc_nix_priv.h
+++ b/drivers/common/cnxk/roc_nix_priv.h
@@ -100,6 +100,7 @@ struct nix_tm_node {
        /* Last stats */
        uint64_t last_pkts;
        uint64_t last_bytes;
+       uint32_t tc_refcnt;
 };
 
 struct nix_tm_shaper_profile {
@@ -402,7 +403,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 enable, bool force_flush);
 void nix_rq_vwqe_flush(struct roc_nix_rq *rq, uint16_t vwqe_interval);
 int nix_tm_mark_init(struct nix *nix);
 
diff --git a/drivers/common/cnxk/roc_nix_tm.c b/drivers/common/cnxk/roc_nix_tm.c
index 151e217..a31abde 100644
--- a/drivers/common/cnxk/roc_nix_tm.c
+++ b/drivers/common/cnxk/roc_nix_tm.c
@@ -314,7 +314,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 enable, bool force_flush)
 {
        struct nix *nix = roc_nix_to_nix_priv(roc_nix);
        enum roc_nix_tm_tree tree = nix->tm_tree;
@@ -325,10 +325,15 @@ nix_tm_bp_config_set(struct roc_nix *roc_nix, uint16_t 
sq, uint16_t tc,
        struct nix_tm_node *sq_node;
        struct nix_tm_node *parent;
        struct nix_tm_node *node;
+       struct roc_nix_sq *sq_s;
        uint8_t parent_lvl;
        uint8_t k = 0;
        int rc = 0;
 
+       sq_s = nix->sqs[sq];
+       if (!sq_s)
+               return -ENOENT;
+
        sq_node = nix_tm_node_search(nix, sq, nix->tm_tree);
        if (!sq_node)
                return -ENOENT;
@@ -348,11 +353,22 @@ nix_tm_bp_config_set(struct roc_nix *roc_nix, uint16_t 
sq, uint16_t tc,
 
        list = nix_tm_node_list(nix, tree);
 
-       if (parent->rel_chan != NIX_TM_CHAN_INVALID && parent->rel_chan != tc) {
+       /* Enable request, parent rel chan already configured */
+       if (enable && parent->rel_chan != NIX_TM_CHAN_INVALID &&
+           parent->rel_chan != tc) {
                rc = -EINVAL;
                goto err;
        }
 
+       /* No action if enable request for a non participating SQ. This case is
+        * required to handle post flush where TCs should be reconfigured after
+        * pre flush.
+        */
+       if (enable && sq_s->tc == ROC_NIX_PFC_CLASS_INVALID &&
+           tc == ROC_NIX_PFC_CLASS_INVALID)
+               return 0;
+
+       /* Find the parent TL3 */
        TAILQ_FOREACH(node, list, node) {
                if (node->hw_lvl != nix->tm_link_cfg_lvl)
                        continue;
@@ -360,38 +376,51 @@ nix_tm_bp_config_set(struct roc_nix *roc_nix, uint16_t 
sq, uint16_t tc,
                if (!(node->flags & NIX_TM_NODE_HWRES) || !node->bp_capa)
                        continue;
 
-               if (node->hw_id != parent->hw_id)
-                       continue;
-
-               if (!req) {
-                       req = mbox_alloc_msg_nix_txschq_cfg(mbox);
-                       req->lvl = nix->tm_link_cfg_lvl;
-                       k = 0;
+               /* 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;
                }
+       }
 
-               req->reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(node->hw_id, link);
-               req->regval[k] = enable ? tc : 0;
-               req->regval[k] |= enable ? BIT_ULL(13) : 0;
-               req->regval_mask[k] = ~(BIT_ULL(13) | GENMASK_ULL(7, 0));
-               k++;
-
-               if (k >= MAX_REGS_PER_MBOX_MSG) {
-                       req->num_regs = k;
-                       rc = mbox_process(mbox);
-                       if (rc)
-                               goto err;
-                       req = NULL;
-               }
+       /* 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;
        }
 
-       if (req) {
-               req->num_regs = k;
-               rc = mbox_process(mbox);
-               if (rc)
-                       goto err;
+       /* Allocating TL3 resources */
+       if (!req) {
+               req = mbox_alloc_msg_nix_txschq_cfg(mbox);
+               req->lvl = nix->tm_link_cfg_lvl;
+               k = 0;
        }
 
+       /* Enable PFC 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 ? BIT_ULL(13) : 0;
+       req->regval_mask[k] = ~(BIT_ULL(13) | GENMASK_ULL(7, 0));
+       k++;
+
+       req->num_regs = k;
+       rc = mbox_process(mbox);
+       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++;
+
        return 0;
 err:
        plt_err("Failed to %s bp on link %u, rc=%d(%s)",
@@ -629,7 +658,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);
+       rc = nix_tm_bp_config_set(roc_nix, sq->qid, 0, false, true);
        if (rc) {
                plt_err("Failed to disable backpressure for flush, rc=%d", rc);
                return rc;
@@ -764,7 +793,7 @@ nix_tm_sq_flush_post(struct roc_nix_sq *sq)
                return 0;
 
        /* Restore backpressure */
-       rc = nix_tm_bp_config_set(roc_nix, sq->qid, 0, true);
+       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;
diff --git a/drivers/common/cnxk/roc_nix_tm_ops.c 
b/drivers/common/cnxk/roc_nix_tm_ops.c
index 5884ce5..4aa5500 100644
--- a/drivers/common/cnxk/roc_nix_tm_ops.c
+++ b/drivers/common/cnxk/roc_nix_tm_ops.c
@@ -292,6 +292,7 @@ roc_nix_tm_node_add(struct roc_nix *roc_nix, struct 
roc_nix_tm_node *roc_node)
        node->pkt_mode_set = roc_node->pkt_mode_set;
        node->free_fn = roc_node->free_fn;
        node->tree = ROC_NIX_TM_USER;
+       node->rel_chan = NIX_TM_CHAN_INVALID;
 
        return nix_tm_node_add(roc_nix, node);
 }
@@ -473,7 +474,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);
+               rc = nix_tm_bp_config_set(roc_nix, sq->qid, 0, false, false);
                if (rc && rc != -ENOENT) {
                        plt_err("Failed to disable backpressure, rc=%d", rc);
                        goto cleanup;
-- 
2.8.4

Reply via email to