[04/12] common/cnxk: support same TC value across multiple queues

Message ID 20220616070743.30658-4-ndabilpuram@marvell.com (mailing list archive)
State Changes Requested, archived
Delegated to: Jerin Jacob
Headers
Series [01/12] common/cnxk: use computed value for wqe skip |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Nithin Dabilpuram June 16, 2022, 7:07 a.m. UTC
  From: Harman Kalra <hkalra@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 <hkalra@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(-)
  

Patch

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;