[v2,12/12] net/bnxt: add parent child flow create and free

Message ID 20201010041153.63921-13-ajit.khaparde@broadcom.com (mailing list archive)
State Accepted, archived
Delegated to: Ajit Khaparde
Headers
Series [v2,01/12] net/bnxt: fix the corruption of the session details |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Ajit Khaparde Oct. 10, 2020, 4:11 a.m. UTC
  From: Kishore Padmanabha <kishore.padmanabha@broadcom.com>

Added support in the ULP mapper to enable parent child flow
creation and destroy. This feature enables support for the vxlan
decap functionality.

Signed-off-by: Kishore Padmanabha <kishore.padmanabha@broadcom.com>
Reviewed-by: Mike Baucom <michael.baucom@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
---
 drivers/net/bnxt/tf_ulp/ulp_flow_db.c         | 177 +++++++++++++++++-
 drivers/net/bnxt/tf_ulp/ulp_flow_db.h         |  36 ++++
 drivers/net/bnxt/tf_ulp/ulp_mapper.c          |  87 ++++++++-
 drivers/net/bnxt/tf_ulp/ulp_mapper.h          |   7 +
 .../net/bnxt/tf_ulp/ulp_template_db_enum.h    |   5 +-
 5 files changed, 302 insertions(+), 10 deletions(-)
  

Patch

diff --git a/drivers/net/bnxt/tf_ulp/ulp_flow_db.c b/drivers/net/bnxt/tf_ulp/ulp_flow_db.c
index a1c39329f..3be748908 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_flow_db.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_flow_db.c
@@ -6,10 +6,10 @@ 
 #include <rte_malloc.h>
 #include "bnxt.h"
 #include "bnxt_tf_common.h"
-#include "ulp_flow_db.h"
 #include "ulp_utils.h"
 #include "ulp_template_struct.h"
 #include "ulp_mapper.h"
+#include "ulp_flow_db.h"
 #include "ulp_fc_mgr.h"
 
 #define ULP_FLOW_DB_RES_DIR_BIT		31
@@ -56,10 +56,10 @@  ulp_flow_db_active_flows_bit_set(struct bnxt_ulp_flow_db *flow_db,
 	} else {
 		if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
 			ULP_INDEX_BITMAP_RESET(f_tbl->active_reg_flows[a_idx],
-					     idx);
+					       idx);
 		else
 			ULP_INDEX_BITMAP_RESET(f_tbl->active_dflt_flows[a_idx],
-					     idx);
+					       idx);
 	}
 }
 
@@ -89,6 +89,13 @@  ulp_flow_db_active_flows_bit_is_set(struct bnxt_ulp_flow_db *flow_db,
 					    idx);
 }
 
+static inline enum tf_dir
+ulp_flow_db_resource_dir_get(struct ulp_fdb_resource_info *res_info)
+{
+	return ((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_DIR_MASK) >>
+		ULP_FLOW_DB_RES_DIR_BIT);
+}
+
 static uint8_t
 ulp_flow_db_resource_func_get(struct ulp_fdb_resource_info *res_info)
 {
@@ -157,11 +164,9 @@  ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info,
 			       struct ulp_flow_db_res_params *params)
 {
 	memset(params, 0, sizeof(struct ulp_flow_db_res_params));
-	params->direction = ((resource_info->nxt_resource_idx &
-				 ULP_FLOW_DB_RES_DIR_MASK) >>
-				 ULP_FLOW_DB_RES_DIR_BIT);
 
 	/* use the helper function to get the resource func */
+	params->direction = ulp_flow_db_resource_dir_get(resource_info);
 	params->resource_func = ulp_flow_db_resource_func_get(resource_info);
 
 	if (params->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
@@ -303,6 +308,9 @@  ulp_flow_db_parent_tbl_init(struct bnxt_ulp_flow_db *flow_db,
 	struct ulp_fdb_parent_child_db *p_db;
 	uint32_t size, idx;
 
+	if (!num_entries)
+		return 0;
+
 	/* update the sizes for the allocation */
 	p_db = &flow_db->parent_child_db;
 	p_db->child_bitset_size = (flow_db->flow_tbl.num_flows /
@@ -1171,6 +1179,12 @@  ulp_flow_db_parent_flow_alloc(struct bnxt_ulp_context *ulp_ctxt,
 		return -EINVAL;
 	}
 
+	/* No support for parent child db then just exit */
+	if (!flow_db->parent_child_db.entries_count) {
+		BNXT_TF_DBG(ERR, "parent child db not supported\n");
+		return -EINVAL;
+	}
+
 	p_pdb = &flow_db->parent_child_db;
 	for (idx = 0; idx <= p_pdb->entries_count; idx++) {
 		if (p_pdb->parent_flow_tbl[idx].parent_fid == fid) {
@@ -1220,6 +1234,12 @@  ulp_flow_db_parent_flow_free(struct bnxt_ulp_context *ulp_ctxt,
 		return -EINVAL;
 	}
 
+	/* No support for parent child db then just exit */
+	if (!flow_db->parent_child_db.entries_count) {
+		BNXT_TF_DBG(ERR, "parent child db not supported\n");
+		return -EINVAL;
+	}
+
 	p_pdb = &flow_db->parent_child_db;
 	for (idx = 0; idx <= p_pdb->entries_count; idx++) {
 		if (p_pdb->parent_flow_tbl[idx].parent_fid == fid) {
@@ -1273,6 +1293,12 @@  ulp_flow_db_parent_child_flow_set(struct bnxt_ulp_context *ulp_ctxt,
 		return -EINVAL;
 	}
 
+	/* No support for parent child db then just exit */
+	if (!flow_db->parent_child_db.entries_count) {
+		BNXT_TF_DBG(ERR, "parent child db not supported\n");
+		return -EINVAL;
+	}
+
 	p_pdb = &flow_db->parent_child_db;
 	a_idx = child_fid / ULP_INDEX_BITMAP_SIZE;
 	for (idx = 0; idx <= p_pdb->entries_count; idx++) {
@@ -1320,6 +1346,12 @@  ulp_flow_db_parent_flow_idx_get(struct bnxt_ulp_context *ulp_ctxt,
 		return -EINVAL;
 	}
 
+	/* No support for parent child db then just exit */
+	if (!flow_db->parent_child_db.entries_count) {
+		BNXT_TF_DBG(ERR, "parent child db not supported\n");
+		return -EINVAL;
+	}
+
 	p_pdb = &flow_db->parent_child_db;
 	for (idx = 0; idx <= p_pdb->entries_count; idx++) {
 		if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
@@ -1392,3 +1424,136 @@  ulp_flow_db_parent_child_flow_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
 	*child_fid = next_fid;
 	return 0;
 }
+
+/*
+ * Orphan the child flow entry
+ * This is called only for child flows that have
+ * BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW resource
+ *
+ * ulp_ctxt [in] Ptr to ulp_context
+ * flow_type [in] Specify it is regular or default flow
+ * fid [in] The index to the flow entry
+ *
+ * Returns 0 on success and negative on failure.
+ */
+int32_t
+ulp_flow_db_child_flow_reset(struct bnxt_ulp_context *ulp_ctxt,
+			     enum bnxt_ulp_fdb_type flow_type,
+			     uint32_t fid)
+{
+	struct bnxt_ulp_flow_db *flow_db;
+	struct bnxt_ulp_flow_tbl *flow_tbl;
+	struct ulp_fdb_resource_info *fid_res;
+	uint32_t res_id = 0;
+
+	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
+	if (!flow_db) {
+		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
+		return -EINVAL;
+	}
+
+	if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
+		BNXT_TF_DBG(ERR, "Invalid flow type\n");
+		return -EINVAL;
+	}
+
+	flow_tbl = &flow_db->flow_tbl;
+	/* check for max flows */
+	if (fid >= flow_tbl->num_flows || !fid) {
+		BNXT_TF_DBG(ERR, "Invalid flow index %x\n", fid);
+		return -EINVAL;
+	}
+
+	/* check if the flow is active or not */
+	if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
+		BNXT_TF_DBG(ERR, "flow does not exist\n");
+		return -EINVAL;
+	}
+
+	/* Iterate the resource to get the resource handle */
+	res_id =  fid;
+	while (res_id) {
+		fid_res = &flow_tbl->flow_resources[res_id];
+		if (ulp_flow_db_resource_func_get(fid_res) ==
+		    BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW) {
+			/* invalidate the resource details */
+			fid_res->resource_hndl = 0;
+			return 0;
+		}
+		res_id = 0;
+		ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
+	}
+	/* failed */
+	return -1;
+}
+
+/*
+ * Create parent flow in the parent flow tbl
+ *
+ * parms [in] Ptr to mapper params
+ *
+ * Returns 0 on success and negative on failure.
+ */
+int32_t
+ulp_flow_db_parent_flow_create(struct bnxt_ulp_mapper_parms *parms)
+{
+	struct ulp_flow_db_res_params fid_parms;
+	int32_t fid_idx;
+
+	/* create the child flow entry in parent flow table */
+	fid_idx = ulp_flow_db_parent_flow_alloc(parms->ulp_ctx, parms->fid);
+	if (fid_idx < 0) {
+		BNXT_TF_DBG(ERR, "Error in creating parent flow fid %x\n",
+			    parms->fid);
+		return -1;
+	}
+
+	/* Add the parent details in the resource list of the flow */
+	memset(&fid_parms, 0, sizeof(fid_parms));
+	fid_parms.resource_func	= BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW;
+	fid_parms.resource_hndl	= fid_idx;
+	fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
+	if (ulp_flow_db_resource_add(parms->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
+				     parms->fid, &fid_parms)) {
+		BNXT_TF_DBG(ERR, "Error in adding flow res for fid %x\n",
+			    parms->fid);
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * Create child flow in the parent flow tbl
+ *
+ * parms [in] Ptr to mapper params
+ *
+ * Returns 0 on success and negative on failure.
+ */
+int32_t
+ulp_flow_db_child_flow_create(struct bnxt_ulp_mapper_parms *parms)
+{
+	struct ulp_flow_db_res_params fid_parms;
+	int32_t rc;
+
+	/* create the parent flow entry in parent flow table */
+	rc = ulp_flow_db_parent_child_flow_set(parms->ulp_ctx,
+					       parms->parent_fid,
+					       parms->fid, 1);
+	if (rc) {
+		BNXT_TF_DBG(ERR, "Error in setting child fid %x\n", parms->fid);
+		return -1;
+	}
+
+	/* Add the parent details in the resource list of the flow */
+	memset(&fid_parms, 0, sizeof(fid_parms));
+	fid_parms.resource_func	= BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW;
+	fid_parms.resource_hndl	= parms->parent_fid;
+	fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
+	if (ulp_flow_db_resource_add(parms->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
+				     parms->fid, &fid_parms)) {
+		BNXT_TF_DBG(ERR, "Error in adding flow res for fid %x\n",
+			    parms->fid);
+		return -1;
+	}
+	return 0;
+}
diff --git a/drivers/net/bnxt/tf_ulp/ulp_flow_db.h b/drivers/net/bnxt/tf_ulp/ulp_flow_db.h
index 87bcd69ae..95fd1992d 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_flow_db.h
+++ b/drivers/net/bnxt/tf_ulp/ulp_flow_db.h
@@ -8,6 +8,7 @@ 
 
 #include "bnxt_ulp.h"
 #include "ulp_template_db_enum.h"
+#include "ulp_mapper.h"
 
 #define BNXT_FLOW_DB_DEFAULT_NUM_FLOWS		512
 #define BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES	8
@@ -319,5 +320,40 @@  ulp_flow_db_parent_child_flow_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
 					     uint32_t parent_idx,
 					     uint32_t *child_fid);
 
+/*
+ * Orphan the child flow entry
+ * This is called only for child flows that have
+ * BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW resource
+ *
+ * ulp_ctxt [in] Ptr to ulp_context
+ * flow_type [in] Specify it is regular or default flow
+ * fid [in] The index to the flow entry
+ *
+ * Returns 0 on success and negative on failure.
+ */
+int32_t
+ulp_flow_db_child_flow_reset(struct bnxt_ulp_context *ulp_ctxt,
+			     enum bnxt_ulp_fdb_type flow_type,
+			     uint32_t fid);
+
+/*
+ * Create parent flow in the parent flow tbl
+ *
+ * parms [in] Ptr to mapper params
+ *
+ * Returns 0 on success and negative on failure.
+ */
+int32_t
+ulp_flow_db_parent_flow_create(struct bnxt_ulp_mapper_parms *parms);
+
+/*
+ * Create child flow in the parent flow tbl
+ *
+ * parms [in] Ptr to mapper params
+ *
+ * Returns 0 on success and negative on failure.
+ */
+int32_t
+ulp_flow_db_child_flow_create(struct bnxt_ulp_mapper_parms *parms);
 
 #endif /* _ULP_FLOW_DB_H_ */
diff --git a/drivers/net/bnxt/tf_ulp/ulp_mapper.c b/drivers/net/bnxt/tf_ulp/ulp_mapper.c
index cd289cc40..b74cb92f5 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_mapper.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_mapper.c
@@ -14,8 +14,8 @@ 
 #include "tfp.h"
 #include "tf_ext_flow_handle.h"
 #include "ulp_mark_mgr.h"
-#include "ulp_flow_db.h"
 #include "ulp_mapper.h"
+#include "ulp_flow_db.h"
 #include "tf_util.h"
 
 static struct bnxt_ulp_glb_resource_info *
@@ -537,6 +537,65 @@  ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
 				    res->resource_hndl);
 }
 
+
+static inline int32_t
+ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp,
+			    uint32_t parent_fid,
+			    struct ulp_flow_db_res_params *res)
+{
+	uint32_t idx, child_fid = 0, parent_idx;
+	struct bnxt_ulp_flow_db *flow_db;
+
+	parent_idx = (uint32_t)res->resource_hndl;
+
+	/* check the validity of the parent fid */
+	if (ulp_flow_db_parent_flow_idx_get(ulp, parent_fid, &idx) ||
+	    idx != parent_idx) {
+		BNXT_TF_DBG(ERR, "invalid parent flow id %x\n", parent_fid);
+		return -EINVAL;
+	}
+
+	/* Clear all the child flows parent index */
+	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp);
+	while (!ulp_flow_db_parent_child_flow_next_entry_get(flow_db, idx,
+							     &child_fid)) {
+		/* update the child flows resource handle */
+		if (ulp_flow_db_child_flow_reset(ulp, BNXT_ULP_FDB_TYPE_REGULAR,
+						 child_fid)) {
+			BNXT_TF_DBG(ERR, "failed to reset child flow %x\n",
+				    child_fid);
+			return -EINVAL;
+		}
+	}
+
+	/* free the parent entry in the parent table flow */
+	if (ulp_flow_db_parent_flow_free(ulp, parent_fid)) {
+		BNXT_TF_DBG(ERR, "failed to free parent flow %x\n", parent_fid);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static inline int32_t
+ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp,
+			   uint32_t child_fid,
+			   struct ulp_flow_db_res_params *res)
+{
+	uint32_t parent_fid;
+
+	parent_fid = (uint32_t)res->resource_hndl;
+	if (!parent_fid)
+		return 0; /* Already freed - orphan child*/
+
+	/* reset the child flow bitset*/
+	if (ulp_flow_db_parent_child_flow_set(ulp, parent_fid, child_fid, 0)) {
+		BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n",
+			    parent_fid, child_fid);
+		return -EINVAL;
+	}
+	return 0;
+}
+
 /*
  * Process the identifier instruction and either store it in the flow database
  * or return it in the val (if not NULL) on success.  If val is NULL, the
@@ -2484,6 +2543,7 @@  ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
 
 static int32_t
 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
+			 uint32_t fid,
 			 struct ulp_flow_db_res_params *res)
 {
 	struct tf *tfp;
@@ -2520,6 +2580,12 @@  ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
 	case BNXT_ULP_RESOURCE_FUNC_HW_FID:
 		rc = ulp_mapper_mark_free(ulp, res);
 		break;
+	case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
+		rc = ulp_mapper_parent_flow_free(ulp, fid, res);
+		break;
+	case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
+		rc = ulp_mapper_child_flow_free(ulp, fid, res);
+		break;
 	default:
 		break;
 	}
@@ -2558,7 +2624,7 @@  ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
 	}
 
 	while (!rc) {
-		trc = ulp_mapper_resource_free(ulp_ctx, &res_parms);
+		trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
 		if (trc)
 			/*
 			 * On fail, we still need to attempt to free the
@@ -2608,7 +2674,7 @@  ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
 			/*convert it from BE to cpu */
 			res.resource_hndl =
 				tfp_be_to_cpu_64(ent->resource_hndl);
-			ulp_mapper_resource_free(ulp_ctx, &res);
+			ulp_mapper_resource_free(ulp_ctx, 0, &res);
 		}
 	}
 }
@@ -2720,6 +2786,8 @@  ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
 	parms.act_tid = cparms->act_tid;
 	parms.class_tid = cparms->class_tid;
 	parms.flow_type = cparms->flow_type;
+	parms.parent_flow = cparms->parent_flow;
+	parms.parent_fid = cparms->parent_fid;
 
 	/* Get the device id from the ulp context */
 	if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
@@ -2797,6 +2865,19 @@  ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
 			goto flow_error;
 	}
 
+	/* setup the parent-child details */
+	if (parms.parent_flow) {
+		/* create a parent flow details */
+		rc = ulp_flow_db_parent_flow_create(&parms);
+		if (rc)
+			goto flow_error;
+	} else if (parms.parent_fid) {
+		/* create a child flow details */
+		rc = ulp_flow_db_child_flow_create(&parms);
+		if (rc)
+			goto flow_error;
+	}
+
 	*flowid = parms.fid;
 	bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
 
diff --git a/drivers/net/bnxt/tf_ulp/ulp_mapper.h b/drivers/net/bnxt/tf_ulp/ulp_mapper.h
index 6f93bcdc1..542e41e5a 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_mapper.h
+++ b/drivers/net/bnxt/tf_ulp/ulp_mapper.h
@@ -76,6 +76,8 @@  struct bnxt_ulp_mapper_parms {
 	enum bnxt_ulp_cache_table_opc		tcam_tbl_opc;
 	struct bnxt_ulp_mapper_cache_entry	*cache_ptr;
 	struct bnxt_ulp_device_params           *device_params;
+	uint32_t				parent_fid;
+	uint32_t				parent_flow;
 };
 
 struct bnxt_ulp_mapper_create_parms {
@@ -90,6 +92,11 @@  struct bnxt_ulp_mapper_create_parms {
 	uint16_t			func_id;
 	uint32_t			dir_attr;
 	enum bnxt_ulp_fdb_type		flow_type;
+
+	/* if set then create it as a child flow with parent as parent_fid */
+	uint32_t			parent_fid;
+	/* if set then create a parent flow */
+	uint32_t			parent_flow;
 };
 
 /* Function to initialize any dynamic mapper data. */
diff --git a/drivers/net/bnxt/tf_ulp/ulp_template_db_enum.h b/drivers/net/bnxt/tf_ulp/ulp_template_db_enum.h
index 81da34e3a..168e308c2 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_template_db_enum.h
+++ b/drivers/net/bnxt/tf_ulp/ulp_template_db_enum.h
@@ -321,7 +321,10 @@  enum bnxt_ulp_resource_func {
 	BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE = 0x82,
 	BNXT_ULP_RESOURCE_FUNC_IDENTIFIER = 0x83,
 	BNXT_ULP_RESOURCE_FUNC_IF_TABLE = 0x84,
-	BNXT_ULP_RESOURCE_FUNC_HW_FID = 0x85
+	BNXT_ULP_RESOURCE_FUNC_HW_FID = 0x85,
+	BNXT_ULP_RESOURCE_FUNC_SHARED_TABLE = 0x86,
+	BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW = 0x87,
+	BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW = 0x88
 };
 
 enum bnxt_ulp_resource_sub_type {