xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_flow_db.c (revision a089734a026a316994674e3f405ee4d56a114efc)
1313ac35aSVenkat Duvvuru /* SPDX-License-Identifier: BSD-3-Clause
2d9e70b1dSRandy Schacher  * Copyright(c) 2014-2023 Broadcom
3313ac35aSVenkat Duvvuru  * All rights reserved.
4313ac35aSVenkat Duvvuru  */
5313ac35aSVenkat Duvvuru 
6191128d7SDavid Marchand #include <rte_bitops.h>
7313ac35aSVenkat Duvvuru #include <rte_malloc.h>
8191128d7SDavid Marchand 
9313ac35aSVenkat Duvvuru #include "bnxt.h"
10313ac35aSVenkat Duvvuru #include "bnxt_tf_common.h"
110c036a14SPeter Spreadborough #include "bnxt_ulp_utils.h"
12313ac35aSVenkat Duvvuru #include "ulp_template_struct.h"
13696843ccSMike Baucom #include "ulp_mapper.h"
14be8acb27SKishore Padmanabha #include "ulp_flow_db.h"
159cf9c838SSomnath Kotur #include "ulp_fc_mgr.h"
160513f0afSPeter Spreadborough #include "ulp_sc_mgr.h"
17675e31d8SVenkat Duvvuru #include "ulp_tun.h"
18288becfbSShuanglin Wang #ifdef TF_FLOW_SCALE_QUERY
19288becfbSShuanglin Wang #include "tf_resources.h"
20ffbc3529SShuanglin Wang #include "tfc_resources.h"
21288becfbSShuanglin Wang #endif /* TF_FLOW_SCALE_QUERY */
22696843ccSMike Baucom 
23696843ccSMike Baucom #define ULP_FLOW_DB_RES_DIR_BIT		31
24696843ccSMike Baucom #define ULP_FLOW_DB_RES_DIR_MASK	0x80000000
25f6e12015SKishore Padmanabha #define ULP_FLOW_DB_RES_NXT_MASK	0x7FFFFFFF
26696843ccSMike Baucom 
27696843ccSMike Baucom /* Macro to copy the nxt_resource_idx */
28696843ccSMike Baucom #define ULP_FLOW_DB_RES_NXT_SET(dst, src)	{(dst) |= ((src) &\
29696843ccSMike Baucom 					 ULP_FLOW_DB_RES_NXT_MASK); }
30696843ccSMike Baucom #define ULP_FLOW_DB_RES_NXT_RESET(dst)	((dst) &= ~(ULP_FLOW_DB_RES_NXT_MASK))
31696843ccSMike Baucom 
32696843ccSMike Baucom /*
3330683082SKishore Padmanabha  * Helper function to set the bit in the active flows
3405a11d7dSMike Baucom  * No validation is done in this function.
3505a11d7dSMike Baucom  *
3630683082SKishore Padmanabha  * flow_db [in] Ptr to flow database
3730683082SKishore Padmanabha  * flow_type [in] - specify default or regular
3805a11d7dSMike Baucom  * idx [in] The index to bit to be set or reset.
3905a11d7dSMike Baucom  * flag [in] 1 to set and 0 to reset.
4005a11d7dSMike Baucom  *
4105a11d7dSMike Baucom  * returns none
4205a11d7dSMike Baucom  */
4305a11d7dSMike Baucom static void
4430683082SKishore Padmanabha ulp_flow_db_active_flows_bit_set(struct bnxt_ulp_flow_db *flow_db,
4530683082SKishore Padmanabha 				 enum bnxt_ulp_fdb_type flow_type,
4605a11d7dSMike Baucom 				 uint32_t idx,
4705a11d7dSMike Baucom 				 uint32_t flag)
4805a11d7dSMike Baucom {
4930683082SKishore Padmanabha 	struct bnxt_ulp_flow_tbl *f_tbl = &flow_db->flow_tbl;
5030683082SKishore Padmanabha 	uint32_t a_idx = idx / ULP_INDEX_BITMAP_SIZE;
5105a11d7dSMike Baucom 
5230683082SKishore Padmanabha 	if (flag) {
53ddaf0afaSKishore Padmanabha 		if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR || flow_type ==
54ddaf0afaSKishore Padmanabha 		    BNXT_ULP_FDB_TYPE_RID)
5530683082SKishore Padmanabha 			ULP_INDEX_BITMAP_SET(f_tbl->active_reg_flows[a_idx],
5605a11d7dSMike Baucom 					     idx);
57ddaf0afaSKishore Padmanabha 		if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT || flow_type ==
58ddaf0afaSKishore Padmanabha 		    BNXT_ULP_FDB_TYPE_RID)
5930683082SKishore Padmanabha 			ULP_INDEX_BITMAP_SET(f_tbl->active_dflt_flows[a_idx],
6005a11d7dSMike Baucom 					     idx);
6130683082SKishore Padmanabha 	} else {
62ddaf0afaSKishore Padmanabha 		if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR || flow_type ==
63ddaf0afaSKishore Padmanabha 		    BNXT_ULP_FDB_TYPE_RID)
6430683082SKishore Padmanabha 			ULP_INDEX_BITMAP_RESET(f_tbl->active_reg_flows[a_idx],
6530683082SKishore Padmanabha 					       idx);
66ddaf0afaSKishore Padmanabha 		if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT || flow_type ==
67ddaf0afaSKishore Padmanabha 		    BNXT_ULP_FDB_TYPE_RID)
6830683082SKishore Padmanabha 			ULP_INDEX_BITMAP_RESET(f_tbl->active_dflt_flows[a_idx],
6930683082SKishore Padmanabha 					       idx);
7030683082SKishore Padmanabha 	}
7105a11d7dSMike Baucom }
7205a11d7dSMike Baucom 
7305a11d7dSMike Baucom /*
7430683082SKishore Padmanabha  * Helper function to check if given fid is active flow.
7530683082SKishore Padmanabha  * No validation being done in this function.
76696843ccSMike Baucom  *
7730683082SKishore Padmanabha  * flow_db [in] Ptr to flow database
7830683082SKishore Padmanabha  * flow_type [in] - specify default or regular
79696843ccSMike Baucom  * idx [in] The index to bit to be set or reset.
80696843ccSMike Baucom  *
81696843ccSMike Baucom  * returns 1 on set or 0 if not set.
82696843ccSMike Baucom  */
83696843ccSMike Baucom static int32_t
8430683082SKishore Padmanabha ulp_flow_db_active_flows_bit_is_set(struct bnxt_ulp_flow_db *flow_db,
8530683082SKishore Padmanabha 				    enum bnxt_ulp_fdb_type flow_type,
86696843ccSMike Baucom 				    uint32_t idx)
87696843ccSMike Baucom {
8830683082SKishore Padmanabha 	struct bnxt_ulp_flow_tbl *f_tbl = &flow_db->flow_tbl;
8930683082SKishore Padmanabha 	uint32_t a_idx = idx / ULP_INDEX_BITMAP_SIZE;
90ddaf0afaSKishore Padmanabha 	uint32_t reg, dflt;
91696843ccSMike Baucom 
92ddaf0afaSKishore Padmanabha 	reg = ULP_INDEX_BITMAP_GET(f_tbl->active_reg_flows[a_idx], idx);
93ddaf0afaSKishore Padmanabha 	dflt = ULP_INDEX_BITMAP_GET(f_tbl->active_dflt_flows[a_idx], idx);
94ddaf0afaSKishore Padmanabha 
95ddaf0afaSKishore Padmanabha 	switch (flow_type) {
96ddaf0afaSKishore Padmanabha 	case BNXT_ULP_FDB_TYPE_REGULAR:
97ddaf0afaSKishore Padmanabha 		return (reg && !dflt);
98ddaf0afaSKishore Padmanabha 	case BNXT_ULP_FDB_TYPE_DEFAULT:
99ddaf0afaSKishore Padmanabha 		return (!reg && dflt);
100ddaf0afaSKishore Padmanabha 	case BNXT_ULP_FDB_TYPE_RID:
101ddaf0afaSKishore Padmanabha 		return (reg && dflt);
102ddaf0afaSKishore Padmanabha 	default:
103ddaf0afaSKishore Padmanabha 		return 0;
104ddaf0afaSKishore Padmanabha 	}
105696843ccSMike Baucom }
106696843ccSMike Baucom 
107be8acb27SKishore Padmanabha static inline enum tf_dir
108be8acb27SKishore Padmanabha ulp_flow_db_resource_dir_get(struct ulp_fdb_resource_info *res_info)
109be8acb27SKishore Padmanabha {
110be8acb27SKishore Padmanabha 	return ((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_DIR_MASK) >>
111be8acb27SKishore Padmanabha 		ULP_FLOW_DB_RES_DIR_BIT);
112be8acb27SKishore Padmanabha }
113be8acb27SKishore Padmanabha 
114f6e12015SKishore Padmanabha static inline uint8_t
115d310d59cSKishore Padmanabha ulp_flow_db_resource_func_get(struct ulp_fdb_resource_info *res_info)
116d310d59cSKishore Padmanabha {
117f6e12015SKishore Padmanabha 	return res_info->resource_func;
118d310d59cSKishore Padmanabha }
119d310d59cSKishore Padmanabha 
120696843ccSMike Baucom /*
121696843ccSMike Baucom  * Helper function to copy the resource params to resource info
122696843ccSMike Baucom  *  No validation being done in this function.
123696843ccSMike Baucom  *
124696843ccSMike Baucom  * resource_info [out] Ptr to resource information
125696843ccSMike Baucom  * params [in] The input params from the caller
126696843ccSMike Baucom  * returns none
127696843ccSMike Baucom  */
128696843ccSMike Baucom static void
129696843ccSMike Baucom ulp_flow_db_res_params_to_info(struct ulp_fdb_resource_info *resource_info,
130696843ccSMike Baucom 			       struct ulp_flow_db_res_params *params)
131696843ccSMike Baucom {
132696843ccSMike Baucom 	resource_info->nxt_resource_idx |= ((params->direction <<
133696843ccSMike Baucom 				      ULP_FLOW_DB_RES_DIR_BIT) &
134696843ccSMike Baucom 				     ULP_FLOW_DB_RES_DIR_MASK);
135f6e12015SKishore Padmanabha 	resource_info->resource_func = params->resource_func;
136696843ccSMike Baucom 	resource_info->resource_type = params->resource_type;
137efcb502fSKishore Padmanabha 	resource_info->resource_sub_type = params->resource_sub_type;
13819994cc7SKishore Padmanabha 	resource_info->fdb_flags = params->fdb_flags;
139f6e12015SKishore Padmanabha 	resource_info->resource_hndl = params->resource_hndl;
140696843ccSMike Baucom }
141313ac35aSVenkat Duvvuru 
142313ac35aSVenkat Duvvuru /*
14305a11d7dSMike Baucom  * Helper function to copy the resource params to resource info
14405a11d7dSMike Baucom  *  No validation being done in this function.
14505a11d7dSMike Baucom  *
14605a11d7dSMike Baucom  * resource_info [in] Ptr to resource information
14705a11d7dSMike Baucom  * params [out] The output params to the caller
14805a11d7dSMike Baucom  *
14905a11d7dSMike Baucom  * returns none
15005a11d7dSMike Baucom  */
15105a11d7dSMike Baucom static void
15205a11d7dSMike Baucom ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info,
15305a11d7dSMike Baucom 			       struct ulp_flow_db_res_params *params)
15405a11d7dSMike Baucom {
15505a11d7dSMike Baucom 	memset(params, 0, sizeof(struct ulp_flow_db_res_params));
156d310d59cSKishore Padmanabha 	/* use the helper function to get the resource func */
157be8acb27SKishore Padmanabha 	params->direction = ulp_flow_db_resource_dir_get(resource_info);
158d310d59cSKishore Padmanabha 	params->resource_func = ulp_flow_db_resource_func_get(resource_info);
15905a11d7dSMike Baucom 	params->resource_type = resource_info->resource_type;
160efcb502fSKishore Padmanabha 	params->resource_sub_type = resource_info->resource_sub_type;
16119994cc7SKishore Padmanabha 	params->fdb_flags = resource_info->fdb_flags;
162f6e12015SKishore Padmanabha 	params->resource_hndl = resource_info->resource_hndl;
16305a11d7dSMike Baucom }
16405a11d7dSMike Baucom 
16505a11d7dSMike Baucom /*
166313ac35aSVenkat Duvvuru  * Helper function to allocate the flow table and initialize
167313ac35aSVenkat Duvvuru  * the stack for allocation operations.
168313ac35aSVenkat Duvvuru  *
169313ac35aSVenkat Duvvuru  * flow_db [in] Ptr to flow database structure
170313ac35aSVenkat Duvvuru  *
171313ac35aSVenkat Duvvuru  * Returns 0 on success or negative number on failure.
172313ac35aSVenkat Duvvuru  */
173313ac35aSVenkat Duvvuru static int32_t
17430683082SKishore Padmanabha ulp_flow_db_alloc_resource(struct bnxt_ulp_flow_db *flow_db)
175313ac35aSVenkat Duvvuru {
176313ac35aSVenkat Duvvuru 	uint32_t			idx = 0;
177313ac35aSVenkat Duvvuru 	struct bnxt_ulp_flow_tbl	*flow_tbl;
178313ac35aSVenkat Duvvuru 	uint32_t			size;
179313ac35aSVenkat Duvvuru 
18030683082SKishore Padmanabha 	flow_tbl = &flow_db->flow_tbl;
181313ac35aSVenkat Duvvuru 
182313ac35aSVenkat Duvvuru 	size = sizeof(struct ulp_fdb_resource_info) * flow_tbl->num_resources;
183313ac35aSVenkat Duvvuru 	flow_tbl->flow_resources =
184313ac35aSVenkat Duvvuru 			rte_zmalloc("ulp_fdb_resource_info", size, 0);
185313ac35aSVenkat Duvvuru 
186313ac35aSVenkat Duvvuru 	if (!flow_tbl->flow_resources) {
187dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to alloc memory for flow table\n");
188313ac35aSVenkat Duvvuru 		return -ENOMEM;
189313ac35aSVenkat Duvvuru 	}
190313ac35aSVenkat Duvvuru 	size = sizeof(uint32_t) * flow_tbl->num_resources;
191313ac35aSVenkat Duvvuru 	flow_tbl->flow_tbl_stack = rte_zmalloc("flow_tbl_stack", size, 0);
192313ac35aSVenkat Duvvuru 	if (!flow_tbl->flow_tbl_stack) {
193dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to alloc memory flow tbl stack\n");
194313ac35aSVenkat Duvvuru 		return -ENOMEM;
195313ac35aSVenkat Duvvuru 	}
196313ac35aSVenkat Duvvuru 	size = (flow_tbl->num_flows / sizeof(uint64_t)) + 1;
197f4a4421cSKishore Padmanabha 	size = ULP_BYTE_ROUND_OFF_8(size);
198f4a4421cSKishore Padmanabha 	flow_tbl->active_reg_flows = rte_zmalloc("active reg flows", size,
199f4a4421cSKishore Padmanabha 						 ULP_BUFFER_ALIGN_64_BYTE);
20030683082SKishore Padmanabha 	if (!flow_tbl->active_reg_flows) {
201dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to alloc memory active reg flows\n");
20230683082SKishore Padmanabha 		return -ENOMEM;
20330683082SKishore Padmanabha 	}
20430683082SKishore Padmanabha 
205f4a4421cSKishore Padmanabha 	flow_tbl->active_dflt_flows = rte_zmalloc("active dflt flows", size,
206f4a4421cSKishore Padmanabha 						  ULP_BUFFER_ALIGN_64_BYTE);
20730683082SKishore Padmanabha 	if (!flow_tbl->active_dflt_flows) {
208dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to alloc memory active dflt flows\n");
209313ac35aSVenkat Duvvuru 		return -ENOMEM;
210313ac35aSVenkat Duvvuru 	}
211313ac35aSVenkat Duvvuru 
212313ac35aSVenkat Duvvuru 	/* Initialize the stack table. */
213313ac35aSVenkat Duvvuru 	for (idx = 0; idx < flow_tbl->num_resources; idx++)
214313ac35aSVenkat Duvvuru 		flow_tbl->flow_tbl_stack[idx] = idx;
215313ac35aSVenkat Duvvuru 
216313ac35aSVenkat Duvvuru 	/* Ignore the first element in the list. */
217313ac35aSVenkat Duvvuru 	flow_tbl->head_index = 1;
218313ac35aSVenkat Duvvuru 	/* Tail points to the last entry in the list. */
219313ac35aSVenkat Duvvuru 	flow_tbl->tail_index = flow_tbl->num_resources - 1;
220313ac35aSVenkat Duvvuru 	return 0;
221313ac35aSVenkat Duvvuru }
222313ac35aSVenkat Duvvuru 
223313ac35aSVenkat Duvvuru /*
224313ac35aSVenkat Duvvuru  * Helper function to deallocate the flow table.
225313ac35aSVenkat Duvvuru  *
226313ac35aSVenkat Duvvuru  * flow_db [in] Ptr to flow database structure
227313ac35aSVenkat Duvvuru  *
228313ac35aSVenkat Duvvuru  * Returns none.
229313ac35aSVenkat Duvvuru  */
230313ac35aSVenkat Duvvuru static void
23130683082SKishore Padmanabha ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db)
232313ac35aSVenkat Duvvuru {
23330683082SKishore Padmanabha 	struct bnxt_ulp_flow_tbl *flow_tbl = &flow_db->flow_tbl;
234313ac35aSVenkat Duvvuru 
235313ac35aSVenkat Duvvuru 	/* Free all the allocated tables in the flow table. */
23630683082SKishore Padmanabha 	if (flow_tbl->active_reg_flows) {
23730683082SKishore Padmanabha 		rte_free(flow_tbl->active_reg_flows);
23830683082SKishore Padmanabha 		flow_tbl->active_reg_flows = NULL;
23930683082SKishore Padmanabha 	}
24030683082SKishore Padmanabha 	if (flow_tbl->active_dflt_flows) {
24130683082SKishore Padmanabha 		rte_free(flow_tbl->active_dflt_flows);
24230683082SKishore Padmanabha 		flow_tbl->active_dflt_flows = NULL;
243313ac35aSVenkat Duvvuru 	}
244313ac35aSVenkat Duvvuru 
245313ac35aSVenkat Duvvuru 	if (flow_tbl->flow_tbl_stack) {
246313ac35aSVenkat Duvvuru 		rte_free(flow_tbl->flow_tbl_stack);
247313ac35aSVenkat Duvvuru 		flow_tbl->flow_tbl_stack = NULL;
248313ac35aSVenkat Duvvuru 	}
249313ac35aSVenkat Duvvuru 
250313ac35aSVenkat Duvvuru 	if (flow_tbl->flow_resources) {
251313ac35aSVenkat Duvvuru 		rte_free(flow_tbl->flow_resources);
252313ac35aSVenkat Duvvuru 		flow_tbl->flow_resources = NULL;
253313ac35aSVenkat Duvvuru 	}
254313ac35aSVenkat Duvvuru }
255313ac35aSVenkat Duvvuru 
256313ac35aSVenkat Duvvuru /*
25774bcfc06SKishore Padmanabha  * Helper function to add function id to the flow table
25874bcfc06SKishore Padmanabha  *
25974bcfc06SKishore Padmanabha  * flow_db [in] Ptr to flow table
26074bcfc06SKishore Padmanabha  * flow_id [in] The flow id of the flow
26174bcfc06SKishore Padmanabha  * func_id [in] The func_id to be set, for reset pass zero
26274bcfc06SKishore Padmanabha  *
26374bcfc06SKishore Padmanabha  * returns none
26474bcfc06SKishore Padmanabha  */
26574bcfc06SKishore Padmanabha static void
26674bcfc06SKishore Padmanabha ulp_flow_db_func_id_set(struct bnxt_ulp_flow_db *flow_db,
26774bcfc06SKishore Padmanabha 			uint32_t flow_id,
26874bcfc06SKishore Padmanabha 			uint32_t func_id)
26974bcfc06SKishore Padmanabha {
27074bcfc06SKishore Padmanabha 	/* set the function id in the function table */
27174bcfc06SKishore Padmanabha 	if (flow_id < flow_db->func_id_tbl_size)
27274bcfc06SKishore Padmanabha 		flow_db->func_id_tbl[flow_id] = func_id;
27374bcfc06SKishore Padmanabha 	else /* This should never happen */
274dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow id, flowdb corrupt\n");
27574bcfc06SKishore Padmanabha }
27674bcfc06SKishore Padmanabha 
27774bcfc06SKishore Padmanabha /*
278f4a4421cSKishore Padmanabha  * Initialize the parent-child database. Memory is allocated in this
279f4a4421cSKishore Padmanabha  * call and assigned to the database
280f4a4421cSKishore Padmanabha  *
281f4a4421cSKishore Padmanabha  * flow_db [in] Ptr to flow table
282f4a4421cSKishore Padmanabha  * num_entries[in] - number of entries to allocate
283f4a4421cSKishore Padmanabha  *
284f4a4421cSKishore Padmanabha  * Returns 0 on success or negative number on failure.
285f4a4421cSKishore Padmanabha  */
286f4a4421cSKishore Padmanabha static int32_t
287f4a4421cSKishore Padmanabha ulp_flow_db_parent_tbl_init(struct bnxt_ulp_flow_db *flow_db,
288f4a4421cSKishore Padmanabha 			    uint32_t num_entries)
289f4a4421cSKishore Padmanabha {
290f4a4421cSKishore Padmanabha 	struct ulp_fdb_parent_child_db *p_db;
291f4a4421cSKishore Padmanabha 	uint32_t size, idx;
292f4a4421cSKishore Padmanabha 
293be8acb27SKishore Padmanabha 	if (!num_entries)
294be8acb27SKishore Padmanabha 		return 0;
295be8acb27SKishore Padmanabha 
296f4a4421cSKishore Padmanabha 	/* update the sizes for the allocation */
297f4a4421cSKishore Padmanabha 	p_db = &flow_db->parent_child_db;
298f4a4421cSKishore Padmanabha 	p_db->child_bitset_size = (flow_db->flow_tbl.num_flows /
299f4a4421cSKishore Padmanabha 				   sizeof(uint64_t)) + 1; /* size in bytes */
300f4a4421cSKishore Padmanabha 	p_db->child_bitset_size = ULP_BYTE_ROUND_OFF_8(p_db->child_bitset_size);
301f4a4421cSKishore Padmanabha 	p_db->entries_count = num_entries;
302f4a4421cSKishore Padmanabha 
303f4a4421cSKishore Padmanabha 	/* allocate the memory */
304f4a4421cSKishore Padmanabha 	p_db->parent_flow_tbl = rte_zmalloc("fdb parent flow tbl",
305f4a4421cSKishore Padmanabha 					    sizeof(struct ulp_fdb_parent_info) *
306f4a4421cSKishore Padmanabha 					    p_db->entries_count, 0);
307f4a4421cSKishore Padmanabha 	if (!p_db->parent_flow_tbl) {
308dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR,
309f4a4421cSKishore Padmanabha 			     "Failed to allocate memory fdb parent flow tbl\n");
310f4a4421cSKishore Padmanabha 		return -ENOMEM;
311f4a4421cSKishore Padmanabha 	}
312f4a4421cSKishore Padmanabha 	size = p_db->child_bitset_size * p_db->entries_count;
313f4a4421cSKishore Padmanabha 
314f4a4421cSKishore Padmanabha 	/*
315f4a4421cSKishore Padmanabha 	 * allocate the big chunk of memory to be statically carved into
316f4a4421cSKishore Padmanabha 	 * child_fid_bitset pointer.
317f4a4421cSKishore Padmanabha 	 */
318f4a4421cSKishore Padmanabha 	p_db->parent_flow_tbl_mem = rte_zmalloc("fdb parent flow tbl mem",
319f4a4421cSKishore Padmanabha 						size,
320f4a4421cSKishore Padmanabha 						ULP_BUFFER_ALIGN_64_BYTE);
321f4a4421cSKishore Padmanabha 	if (!p_db->parent_flow_tbl_mem) {
322dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR,
323f4a4421cSKishore Padmanabha 			     "Failed to allocate memory fdb parent flow mem\n");
324f4a4421cSKishore Padmanabha 		return -ENOMEM;
325f4a4421cSKishore Padmanabha 	}
326f4a4421cSKishore Padmanabha 
327f4a4421cSKishore Padmanabha 	/* set the pointers in parent table to their offsets */
328f4a4421cSKishore Padmanabha 	for (idx = 0 ; idx < p_db->entries_count; idx++) {
329f4a4421cSKishore Padmanabha 		p_db->parent_flow_tbl[idx].child_fid_bitset =
330f4a4421cSKishore Padmanabha 			(uint64_t *)&p_db->parent_flow_tbl_mem[idx *
331f4a4421cSKishore Padmanabha 			p_db->child_bitset_size];
332f4a4421cSKishore Padmanabha 	}
333f4a4421cSKishore Padmanabha 	/* success */
334f4a4421cSKishore Padmanabha 	return 0;
335f4a4421cSKishore Padmanabha }
336f4a4421cSKishore Padmanabha 
337f4a4421cSKishore Padmanabha /*
338f4a4421cSKishore Padmanabha  * Deinitialize the parent-child database. Memory is deallocated in
339f4a4421cSKishore Padmanabha  * this call and all flows should have been purged before this
340f4a4421cSKishore Padmanabha  * call.
341f4a4421cSKishore Padmanabha  *
342f4a4421cSKishore Padmanabha  * flow_db [in] Ptr to flow table
343f4a4421cSKishore Padmanabha  *
344f4a4421cSKishore Padmanabha  * Returns none
345f4a4421cSKishore Padmanabha  */
346f4a4421cSKishore Padmanabha static void
347f4a4421cSKishore Padmanabha ulp_flow_db_parent_tbl_deinit(struct bnxt_ulp_flow_db *flow_db)
348f4a4421cSKishore Padmanabha {
349f4a4421cSKishore Padmanabha 	/* free the memory related to parent child database */
350f4a4421cSKishore Padmanabha 	if (flow_db->parent_child_db.parent_flow_tbl_mem) {
351f4a4421cSKishore Padmanabha 		rte_free(flow_db->parent_child_db.parent_flow_tbl_mem);
352f4a4421cSKishore Padmanabha 		flow_db->parent_child_db.parent_flow_tbl_mem = NULL;
353f4a4421cSKishore Padmanabha 	}
354f4a4421cSKishore Padmanabha 	if (flow_db->parent_child_db.parent_flow_tbl) {
355f4a4421cSKishore Padmanabha 		rte_free(flow_db->parent_child_db.parent_flow_tbl);
356f4a4421cSKishore Padmanabha 		flow_db->parent_child_db.parent_flow_tbl = NULL;
357f4a4421cSKishore Padmanabha 	}
358f4a4421cSKishore Padmanabha }
359f4a4421cSKishore Padmanabha 
360f4a4421cSKishore Padmanabha /*
361313ac35aSVenkat Duvvuru  * Initialize the flow database. Memory is allocated in this
362313ac35aSVenkat Duvvuru  * call and assigned to the flow database.
363313ac35aSVenkat Duvvuru  *
364313ac35aSVenkat Duvvuru  * ulp_ctxt [in] Ptr to ulp context
365313ac35aSVenkat Duvvuru  *
366313ac35aSVenkat Duvvuru  * Returns 0 on success or negative number on failure.
367313ac35aSVenkat Duvvuru  */
36830683082SKishore Padmanabha int32_t
36930683082SKishore Padmanabha ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
370313ac35aSVenkat Duvvuru {
371313ac35aSVenkat Duvvuru 	struct bnxt_ulp_device_params *dparms;
372313ac35aSVenkat Duvvuru 	struct bnxt_ulp_flow_tbl *flow_tbl;
373313ac35aSVenkat Duvvuru 	struct bnxt_ulp_flow_db *flow_db;
374191f19ceSMike Baucom 	uint32_t dev_id, num_flows;
375191f19ceSMike Baucom 	enum bnxt_ulp_flow_mem_type mtype;
376313ac35aSVenkat Duvvuru 
377313ac35aSVenkat Duvvuru 	/* Get the dev specific number of flows that needed to be supported. */
378313ac35aSVenkat Duvvuru 	if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) {
379dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid device id\n");
380313ac35aSVenkat Duvvuru 		return -EINVAL;
381313ac35aSVenkat Duvvuru 	}
382313ac35aSVenkat Duvvuru 
383313ac35aSVenkat Duvvuru 	dparms = bnxt_ulp_device_params_get(dev_id);
384313ac35aSVenkat Duvvuru 	if (!dparms) {
385dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "could not fetch the device params\n");
386313ac35aSVenkat Duvvuru 		return -ENODEV;
387313ac35aSVenkat Duvvuru 	}
388313ac35aSVenkat Duvvuru 
389313ac35aSVenkat Duvvuru 	flow_db = rte_zmalloc("bnxt_ulp_flow_db",
390313ac35aSVenkat Duvvuru 			      sizeof(struct bnxt_ulp_flow_db), 0);
391313ac35aSVenkat Duvvuru 	if (!flow_db) {
392dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR,
393313ac35aSVenkat Duvvuru 			     "Failed to allocate memory for flow table ptr\n");
39474bcfc06SKishore Padmanabha 		return -ENOMEM;
395313ac35aSVenkat Duvvuru 	}
396313ac35aSVenkat Duvvuru 
397313ac35aSVenkat Duvvuru 	/* Attach the flow database to the ulp context. */
398313ac35aSVenkat Duvvuru 	bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db);
399313ac35aSVenkat Duvvuru 
400191f19ceSMike Baucom 	/* Determine the number of flows based on EM type */
4013fe124d2SKishore Padmanabha 	if (bnxt_ulp_cntxt_mem_type_get(ulp_ctxt, &mtype))
4023fe124d2SKishore Padmanabha 		goto error_free;
4033fe124d2SKishore Padmanabha 
404191f19ceSMike Baucom 	if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
405191f19ceSMike Baucom 		num_flows = dparms->int_flow_db_num_entries;
406191f19ceSMike Baucom 	else
407191f19ceSMike Baucom 		num_flows = dparms->ext_flow_db_num_entries;
408191f19ceSMike Baucom 
409313ac35aSVenkat Duvvuru 	/* Populate the regular flow table limits. */
41030683082SKishore Padmanabha 	flow_tbl = &flow_db->flow_tbl;
411191f19ceSMike Baucom 	flow_tbl->num_flows = num_flows + 1;
412191f19ceSMike Baucom 	flow_tbl->num_resources = ((num_flows + 1) *
413313ac35aSVenkat Duvvuru 				   dparms->num_resources_per_flow);
414313ac35aSVenkat Duvvuru 
41530683082SKishore Padmanabha 	/* Include the default flow table limits. */
41630683082SKishore Padmanabha 	flow_tbl->num_flows += (BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1);
41730683082SKishore Padmanabha 	flow_tbl->num_resources += ((BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1) *
418313ac35aSVenkat Duvvuru 				    BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES);
419313ac35aSVenkat Duvvuru 
42030683082SKishore Padmanabha 	/* Allocate the resource for the flow table. */
42130683082SKishore Padmanabha 	if (ulp_flow_db_alloc_resource(flow_db))
422313ac35aSVenkat Duvvuru 		goto error_free;
423313ac35aSVenkat Duvvuru 
42474bcfc06SKishore Padmanabha 	/* add 1 since we are not using index 0 for flow id */
42530683082SKishore Padmanabha 	flow_db->func_id_tbl_size = flow_tbl->num_flows + 1;
42674bcfc06SKishore Padmanabha 	/* Allocate the function Id table */
42774bcfc06SKishore Padmanabha 	flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table",
42874bcfc06SKishore Padmanabha 					   flow_db->func_id_tbl_size *
42974bcfc06SKishore Padmanabha 					   sizeof(uint16_t), 0);
43074bcfc06SKishore Padmanabha 	if (!flow_db->func_id_tbl) {
431dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR,
43274bcfc06SKishore Padmanabha 			     "Failed to allocate mem for flow table func id\n");
43374bcfc06SKishore Padmanabha 		goto error_free;
43474bcfc06SKishore Padmanabha 	}
435f4a4421cSKishore Padmanabha 	/* initialize the parent child database */
436f4a4421cSKishore Padmanabha 	if (ulp_flow_db_parent_tbl_init(flow_db,
437f4a4421cSKishore Padmanabha 					dparms->fdb_parent_flow_entries)) {
438dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR,
439f4a4421cSKishore Padmanabha 			     "Failed to allocate mem for parent child db\n");
440f4a4421cSKishore Padmanabha 		goto error_free;
441f4a4421cSKishore Padmanabha 	}
442f4a4421cSKishore Padmanabha 
443313ac35aSVenkat Duvvuru 	/* All good so return. */
444dd0191d5SShuanglin Wang 	BNXT_DRV_DBG(DEBUG, "FlowDB initialized with %d flows.\n",
445191f19ceSMike Baucom 		     flow_tbl->num_flows);
446313ac35aSVenkat Duvvuru 	return 0;
447313ac35aSVenkat Duvvuru error_free:
448313ac35aSVenkat Duvvuru 	ulp_flow_db_deinit(ulp_ctxt);
449313ac35aSVenkat Duvvuru 	return -ENOMEM;
450313ac35aSVenkat Duvvuru }
451313ac35aSVenkat Duvvuru 
452313ac35aSVenkat Duvvuru /*
453313ac35aSVenkat Duvvuru  * Deinitialize the flow database. Memory is deallocated in
454313ac35aSVenkat Duvvuru  * this call and all flows should have been purged before this
455313ac35aSVenkat Duvvuru  * call.
456313ac35aSVenkat Duvvuru  *
457313ac35aSVenkat Duvvuru  * ulp_ctxt [in] Ptr to ulp context
458313ac35aSVenkat Duvvuru  *
459313ac35aSVenkat Duvvuru  * Returns 0 on success.
460313ac35aSVenkat Duvvuru  */
46130683082SKishore Padmanabha int32_t
46230683082SKishore Padmanabha ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
463313ac35aSVenkat Duvvuru {
464313ac35aSVenkat Duvvuru 	struct bnxt_ulp_flow_db *flow_db;
465313ac35aSVenkat Duvvuru 
466313ac35aSVenkat Duvvuru 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
46709b23f8bSKishore Padmanabha 	if (!flow_db)
468313ac35aSVenkat Duvvuru 		return -EINVAL;
469313ac35aSVenkat Duvvuru 
470313ac35aSVenkat Duvvuru 	/* Detach the flow database from the ulp context. */
471313ac35aSVenkat Duvvuru 	bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
472313ac35aSVenkat Duvvuru 
473313ac35aSVenkat Duvvuru 	/* Free up all the memory. */
474f4a4421cSKishore Padmanabha 	ulp_flow_db_parent_tbl_deinit(flow_db);
47530683082SKishore Padmanabha 	ulp_flow_db_dealloc_resource(flow_db);
47674bcfc06SKishore Padmanabha 	rte_free(flow_db->func_id_tbl);
477313ac35aSVenkat Duvvuru 	rte_free(flow_db);
478313ac35aSVenkat Duvvuru 
479313ac35aSVenkat Duvvuru 	return 0;
480313ac35aSVenkat Duvvuru }
481696843ccSMike Baucom 
482696843ccSMike Baucom /*
4838f153057SMike Baucom  * Allocate the flow database entry
4848f153057SMike Baucom  *
4858f153057SMike Baucom  * ulp_ctxt [in] Ptr to ulp_context
48630683082SKishore Padmanabha  * flow_type [in] - specify default or regular
48730683082SKishore Padmanabha  * func_id [in].function id of the ingress port
4888f153057SMike Baucom  * fid [out] The index to the flow entry
4898f153057SMike Baucom  *
4908f153057SMike Baucom  * returns 0 on success and negative on failure.
4918f153057SMike Baucom  */
49230683082SKishore Padmanabha int32_t
49330683082SKishore Padmanabha ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
49430683082SKishore Padmanabha 		      enum bnxt_ulp_fdb_type flow_type,
49574bcfc06SKishore Padmanabha 		      uint16_t func_id,
4968f153057SMike Baucom 		      uint32_t *fid)
4978f153057SMike Baucom {
4988f153057SMike Baucom 	struct bnxt_ulp_flow_db *flow_db;
4998f153057SMike Baucom 	struct bnxt_ulp_flow_tbl *flow_tbl;
5008f153057SMike Baucom 
5018f153057SMike Baucom 	*fid = 0; /* Initialize fid to invalid value */
5028f153057SMike Baucom 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
5038f153057SMike Baucom 	if (!flow_db) {
504dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
5058f153057SMike Baucom 		return -EINVAL;
5068f153057SMike Baucom 	}
5078f153057SMike Baucom 
508ddaf0afaSKishore Padmanabha 	if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
509dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow type\n");
51030683082SKishore Padmanabha 		return -EINVAL;
51130683082SKishore Padmanabha 	}
51230683082SKishore Padmanabha 
51330683082SKishore Padmanabha 	flow_tbl = &flow_db->flow_tbl;
5148f153057SMike Baucom 	/* check for max flows */
5158f153057SMike Baucom 	if (flow_tbl->num_flows <= flow_tbl->head_index) {
516dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Flow database has reached max flows\n");
5178f153057SMike Baucom 		return -ENOMEM;
5188f153057SMike Baucom 	}
5195a640d00SMike Baucom 	if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) {
520dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Flow database has reached max resources\n");
5215a640d00SMike Baucom 		return -ENOMEM;
5225a640d00SMike Baucom 	}
5238f153057SMike Baucom 	*fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index];
5248f153057SMike Baucom 	flow_tbl->head_index++;
5258f153057SMike Baucom 
52630683082SKishore Padmanabha 	/* Set the flow type */
52730683082SKishore Padmanabha 	ulp_flow_db_active_flows_bit_set(flow_db, flow_type, *fid, 1);
52830683082SKishore Padmanabha 
52930683082SKishore Padmanabha 	/* function id update is only valid for regular flow table */
53030683082SKishore Padmanabha 	if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
53174bcfc06SKishore Padmanabha 		ulp_flow_db_func_id_set(flow_db, *fid, func_id);
53274bcfc06SKishore Padmanabha 
533dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
534dd0191d5SShuanglin Wang 	BNXT_DRV_DBG(DEBUG, "flow_id = %u:%u allocated\n", flow_type, *fid);
535dd0191d5SShuanglin Wang #endif
53630683082SKishore Padmanabha 	/* return success */
5378f153057SMike Baucom 	return 0;
5388f153057SMike Baucom }
5398f153057SMike Baucom 
5408f153057SMike Baucom /*
541696843ccSMike Baucom  * Allocate the flow database entry.
542696843ccSMike Baucom  * The params->critical_resource has to be set to 0 to allocate a new resource.
543696843ccSMike Baucom  *
544696843ccSMike Baucom  * ulp_ctxt [in] Ptr to ulp_context
54530683082SKishore Padmanabha  * flow_type [in] Specify it is regular or default flow
546696843ccSMike Baucom  * fid [in] The index to the flow entry
547696843ccSMike Baucom  * params [in] The contents to be copied into resource
548696843ccSMike Baucom  *
549696843ccSMike Baucom  * returns 0 on success and negative on failure.
550696843ccSMike Baucom  */
55130683082SKishore Padmanabha int32_t
55230683082SKishore Padmanabha ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt,
55330683082SKishore Padmanabha 			 enum bnxt_ulp_fdb_type flow_type,
554696843ccSMike Baucom 			 uint32_t fid,
555696843ccSMike Baucom 			 struct ulp_flow_db_res_params *params)
556696843ccSMike Baucom {
557696843ccSMike Baucom 	struct bnxt_ulp_flow_db *flow_db;
558696843ccSMike Baucom 	struct bnxt_ulp_flow_tbl *flow_tbl;
559696843ccSMike Baucom 	struct ulp_fdb_resource_info *resource, *fid_resource;
5603fe124d2SKishore Padmanabha 	struct bnxt_ulp_fc_info *ulp_fc_info;
561696843ccSMike Baucom 	uint32_t idx;
562696843ccSMike Baucom 
563696843ccSMike Baucom 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
564696843ccSMike Baucom 	if (!flow_db) {
565dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
566696843ccSMike Baucom 		return -EINVAL;
567696843ccSMike Baucom 	}
568696843ccSMike Baucom 
569ddaf0afaSKishore Padmanabha 	if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
570dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow type\n");
571696843ccSMike Baucom 		return -EINVAL;
572696843ccSMike Baucom 	}
573696843ccSMike Baucom 
57430683082SKishore Padmanabha 	flow_tbl = &flow_db->flow_tbl;
575696843ccSMike Baucom 	/* check for max flows */
576696843ccSMike Baucom 	if (fid >= flow_tbl->num_flows || !fid) {
577dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow index\n");
578696843ccSMike Baucom 		return -EINVAL;
579696843ccSMike Baucom 	}
580696843ccSMike Baucom 
581696843ccSMike Baucom 	/* check if the flow is active or not */
58230683082SKishore Padmanabha 	if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
583dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "flow does not exist %x:%x\n", flow_type,
584dd0191d5SShuanglin Wang 			     fid);
585696843ccSMike Baucom 		return -EINVAL;
586696843ccSMike Baucom 	}
587696843ccSMike Baucom 
588696843ccSMike Baucom 	/* check for max resource */
5895a640d00SMike Baucom 	if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) {
590dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Flow db has reached max resources\n");
591696843ccSMike Baucom 		return -ENOMEM;
592696843ccSMike Baucom 	}
593696843ccSMike Baucom 	fid_resource = &flow_tbl->flow_resources[fid];
594696843ccSMike Baucom 
595f6e12015SKishore Padmanabha 	if (params->critical_resource && (fid_resource->fdb_flags &
596f6e12015SKishore Padmanabha 					  ULP_FDB_FLAG_CRITICAL_RES)) {
597dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(DEBUG, "Ignore multiple critical resources\n");
5981993b267SShahaji Bhosle 		/* Ignore the multiple critical resources */
5991993b267SShahaji Bhosle 		params->critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
6001993b267SShahaji Bhosle 	}
6011993b267SShahaji Bhosle 
602696843ccSMike Baucom 	if (!params->critical_resource) {
603696843ccSMike Baucom 		/* Not the critical_resource so allocate a resource */
604696843ccSMike Baucom 		idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index];
605696843ccSMike Baucom 		resource = &flow_tbl->flow_resources[idx];
606696843ccSMike Baucom 		flow_tbl->tail_index--;
607696843ccSMike Baucom 
608696843ccSMike Baucom 		/* Update the chain list of resource*/
609696843ccSMike Baucom 		ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx,
610696843ccSMike Baucom 					fid_resource->nxt_resource_idx);
611696843ccSMike Baucom 		/* update the contents */
612696843ccSMike Baucom 		ulp_flow_db_res_params_to_info(resource, params);
613696843ccSMike Baucom 		ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
614696843ccSMike Baucom 		ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
615696843ccSMike Baucom 					idx);
616696843ccSMike Baucom 	} else {
617696843ccSMike Baucom 		/* critical resource. Just update the fid resource */
618696843ccSMike Baucom 		ulp_flow_db_res_params_to_info(fid_resource, params);
619f6e12015SKishore Padmanabha 		fid_resource->fdb_flags |= ULP_FDB_FLAG_CRITICAL_RES;
620696843ccSMike Baucom 	}
621696843ccSMike Baucom 
6223fe124d2SKishore Padmanabha 	ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ulp_ctxt);
6239cf9c838SSomnath Kotur 	if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
6249cf9c838SSomnath Kotur 	    params->resource_sub_type ==
6253fe124d2SKishore Padmanabha 	    BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT &&
6261993b267SShahaji Bhosle 	    ulp_fc_info && ulp_fc_info->num_counters) {
6279cf9c838SSomnath Kotur 		/* Store the first HW counter ID for this table */
6289cf9c838SSomnath Kotur 		if (!ulp_fc_mgr_start_idx_isset(ulp_ctxt, params->direction))
6299cf9c838SSomnath Kotur 			ulp_fc_mgr_start_idx_set(ulp_ctxt, params->direction,
6309cf9c838SSomnath Kotur 						 params->resource_hndl);
6319cf9c838SSomnath Kotur 
6329cf9c838SSomnath Kotur 		ulp_fc_mgr_cntr_set(ulp_ctxt, params->direction,
633d9e70b1dSRandy Schacher 				    params->resource_hndl,
634d9e70b1dSRandy Schacher 				    ulp_flow_db_shared_session_get(params));
6359cf9c838SSomnath Kotur 
6369cf9c838SSomnath Kotur 		if (!ulp_fc_mgr_thread_isstarted(ulp_ctxt))
6379cf9c838SSomnath Kotur 			ulp_fc_mgr_thread_start(ulp_ctxt);
6380513f0afSPeter Spreadborough 
6390513f0afSPeter Spreadborough 		if (!ulp_sc_mgr_thread_isstarted(ulp_ctxt))
6400513f0afSPeter Spreadborough 			ulp_sc_mgr_thread_start(ulp_ctxt);
6419cf9c838SSomnath Kotur 	}
6429cf9c838SSomnath Kotur 
643696843ccSMike Baucom 	/* all good, return success */
644696843ccSMike Baucom 	return 0;
645696843ccSMike Baucom }
64605a11d7dSMike Baucom 
64705a11d7dSMike Baucom /*
64805a11d7dSMike Baucom  * Free the flow database entry.
64905a11d7dSMike Baucom  * The params->critical_resource has to be set to 1 to free the first resource.
65005a11d7dSMike Baucom  *
65105a11d7dSMike Baucom  * ulp_ctxt [in] Ptr to ulp_context
65230683082SKishore Padmanabha  * flow_type [in] Specify it is regular or default flow
65305a11d7dSMike Baucom  * fid [in] The index to the flow entry
65405a11d7dSMike Baucom  * params [in/out] The contents to be copied into params.
65505a11d7dSMike Baucom  * Only the critical_resource needs to be set by the caller.
65605a11d7dSMike Baucom  *
65705a11d7dSMike Baucom  * Returns 0 on success and negative on failure.
65805a11d7dSMike Baucom  */
65930683082SKishore Padmanabha int32_t
66030683082SKishore Padmanabha ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,
66130683082SKishore Padmanabha 			 enum bnxt_ulp_fdb_type flow_type,
66205a11d7dSMike Baucom 			 uint32_t fid,
66305a11d7dSMike Baucom 			 struct ulp_flow_db_res_params *params)
66405a11d7dSMike Baucom {
66505a11d7dSMike Baucom 	struct bnxt_ulp_flow_db *flow_db;
66605a11d7dSMike Baucom 	struct bnxt_ulp_flow_tbl *flow_tbl;
66705a11d7dSMike Baucom 	struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
66805a11d7dSMike Baucom 	uint32_t nxt_idx = 0;
66905a11d7dSMike Baucom 
67005a11d7dSMike Baucom 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
67105a11d7dSMike Baucom 	if (!flow_db) {
672dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
67305a11d7dSMike Baucom 		return -EINVAL;
67405a11d7dSMike Baucom 	}
67505a11d7dSMike Baucom 
676ddaf0afaSKishore Padmanabha 	if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
677dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow type\n");
67805a11d7dSMike Baucom 		return -EINVAL;
67905a11d7dSMike Baucom 	}
68005a11d7dSMike Baucom 
68130683082SKishore Padmanabha 	flow_tbl = &flow_db->flow_tbl;
68205a11d7dSMike Baucom 	/* check for max flows */
68305a11d7dSMike Baucom 	if (fid >= flow_tbl->num_flows || !fid) {
684dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow index %x\n", fid);
68505a11d7dSMike Baucom 		return -EINVAL;
68605a11d7dSMike Baucom 	}
68705a11d7dSMike Baucom 
68805a11d7dSMike Baucom 	/* check if the flow is active or not */
68930683082SKishore Padmanabha 	if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
690dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "flow does not exist %x:%x\n", flow_type,
691dd0191d5SShuanglin Wang 			     fid);
69205a11d7dSMike Baucom 		return -EINVAL;
69305a11d7dSMike Baucom 	}
69405a11d7dSMike Baucom 
69505a11d7dSMike Baucom 	fid_resource = &flow_tbl->flow_resources[fid];
69605a11d7dSMike Baucom 	if (!params->critical_resource) {
69705a11d7dSMike Baucom 		/* Not the critical resource so free the resource */
69805a11d7dSMike Baucom 		ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
69905a11d7dSMike Baucom 					fid_resource->nxt_resource_idx);
70005a11d7dSMike Baucom 		if (!nxt_idx) {
70105a11d7dSMike Baucom 			/* reached end of resources */
70205a11d7dSMike Baucom 			return -ENOENT;
70305a11d7dSMike Baucom 		}
70405a11d7dSMike Baucom 		nxt_resource = &flow_tbl->flow_resources[nxt_idx];
70505a11d7dSMike Baucom 
70605a11d7dSMike Baucom 		/* connect the fid resource to the next resource */
70705a11d7dSMike Baucom 		ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
70805a11d7dSMike Baucom 		ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
70905a11d7dSMike Baucom 					nxt_resource->nxt_resource_idx);
71005a11d7dSMike Baucom 
71105a11d7dSMike Baucom 		/* update the contents to be given to caller */
71205a11d7dSMike Baucom 		ulp_flow_db_res_info_to_params(nxt_resource, params);
71305a11d7dSMike Baucom 
71405a11d7dSMike Baucom 		/* Delete the nxt_resource */
71505a11d7dSMike Baucom 		memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info));
71605a11d7dSMike Baucom 
71705a11d7dSMike Baucom 		/* add it to the free list */
71805a11d7dSMike Baucom 		flow_tbl->tail_index++;
71905a11d7dSMike Baucom 		if (flow_tbl->tail_index >= flow_tbl->num_resources) {
720dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "FlowDB:Tail reached max\n");
72105a11d7dSMike Baucom 			return -ENOENT;
72205a11d7dSMike Baucom 		}
72305a11d7dSMike Baucom 		flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx;
72405a11d7dSMike Baucom 
72505a11d7dSMike Baucom 	} else {
72605a11d7dSMike Baucom 		/* Critical resource. copy the contents and exit */
72705a11d7dSMike Baucom 		ulp_flow_db_res_info_to_params(fid_resource, params);
72805a11d7dSMike Baucom 		ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
72905a11d7dSMike Baucom 					fid_resource->nxt_resource_idx);
73005a11d7dSMike Baucom 		memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info));
73105a11d7dSMike Baucom 		ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
73205a11d7dSMike Baucom 					nxt_idx);
73305a11d7dSMike Baucom 	}
73405a11d7dSMike Baucom 
7359cf9c838SSomnath Kotur 	/* Now that the HW Flow counter resource is deleted, reset it's
7369cf9c838SSomnath Kotur 	 * corresponding slot in the SW accumulation table in the Flow Counter
7379cf9c838SSomnath Kotur 	 * manager
7389cf9c838SSomnath Kotur 	 */
7399cf9c838SSomnath Kotur 	if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
7409cf9c838SSomnath Kotur 	    params->resource_sub_type ==
7419cbfa4cfSKishore Padmanabha 	    BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT) {
7429cf9c838SSomnath Kotur 		ulp_fc_mgr_cntr_reset(ulp_ctxt, params->direction,
7439cf9c838SSomnath Kotur 				      params->resource_hndl);
7449cf9c838SSomnath Kotur 	}
7459cf9c838SSomnath Kotur 
74605a11d7dSMike Baucom 	/* all good, return success */
74705a11d7dSMike Baucom 	return 0;
74805a11d7dSMike Baucom }
74905a11d7dSMike Baucom 
75005a11d7dSMike Baucom /*
75105a11d7dSMike Baucom  * Free the flow database entry
75205a11d7dSMike Baucom  *
75305a11d7dSMike Baucom  * ulp_ctxt [in] Ptr to ulp_context
75430683082SKishore Padmanabha  * flow_type [in] - specify default or regular
75505a11d7dSMike Baucom  * fid [in] The index to the flow entry
75605a11d7dSMike Baucom  *
75705a11d7dSMike Baucom  * returns 0 on success and negative on failure.
75805a11d7dSMike Baucom  */
75930683082SKishore Padmanabha int32_t
76030683082SKishore Padmanabha ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,
76130683082SKishore Padmanabha 		     enum bnxt_ulp_fdb_type flow_type,
76205a11d7dSMike Baucom 		     uint32_t fid)
76305a11d7dSMike Baucom {
764a2417601SKishore Padmanabha 	struct bnxt_ulp_flow_tbl *flow_tbl;
765ddaf0afaSKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
76605a11d7dSMike Baucom 
76705a11d7dSMike Baucom 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
76805a11d7dSMike Baucom 	if (!flow_db) {
769dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
77005a11d7dSMike Baucom 		return -EINVAL;
77105a11d7dSMike Baucom 	}
77205a11d7dSMike Baucom 
773ddaf0afaSKishore Padmanabha 	if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
774dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow type\n");
77505a11d7dSMike Baucom 		return -EINVAL;
77605a11d7dSMike Baucom 	}
77705a11d7dSMike Baucom 
77830683082SKishore Padmanabha 	flow_tbl = &flow_db->flow_tbl;
77905a11d7dSMike Baucom 
78005a11d7dSMike Baucom 	/* check for limits of fid */
78105a11d7dSMike Baucom 	if (fid >= flow_tbl->num_flows || !fid) {
782dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow index\n");
78305a11d7dSMike Baucom 		return -EINVAL;
78405a11d7dSMike Baucom 	}
78505a11d7dSMike Baucom 
78605a11d7dSMike Baucom 	/* check if the flow is active or not */
78730683082SKishore Padmanabha 	if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
788dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "flow does not exist %x:%x\n", flow_type,
789dd0191d5SShuanglin Wang 			     fid);
79005a11d7dSMike Baucom 		return -EINVAL;
79105a11d7dSMike Baucom 	}
79205a11d7dSMike Baucom 	flow_tbl->head_index--;
79305a11d7dSMike Baucom 	if (!flow_tbl->head_index) {
794dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "FlowDB: Head Ptr is zero\n");
79505a11d7dSMike Baucom 		return -ENOENT;
79605a11d7dSMike Baucom 	}
797ddaf0afaSKishore Padmanabha 
79805a11d7dSMike Baucom 	flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;
79930683082SKishore Padmanabha 
80030683082SKishore Padmanabha 	/* Clear the flows bitmap */
80130683082SKishore Padmanabha 	ulp_flow_db_active_flows_bit_set(flow_db, flow_type, fid, 0);
80230683082SKishore Padmanabha 
80330683082SKishore Padmanabha 	if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
80474bcfc06SKishore Padmanabha 		ulp_flow_db_func_id_set(flow_db, fid, 0);
80505a11d7dSMike Baucom 
806dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
807dd0191d5SShuanglin Wang 	BNXT_DRV_DBG(DEBUG, "flow_id = %u:%u freed\n", flow_type, fid);
808dd0191d5SShuanglin Wang #endif
80905a11d7dSMike Baucom 	/* all good, return success */
81005a11d7dSMike Baucom 	return 0;
81105a11d7dSMike Baucom }
812edc6ca0cSKishore Padmanabha 
813cd7c298aSKishore Padmanabha /*
814cd7c298aSKishore Padmanabha  *Get the flow database entry details
815cd7c298aSKishore Padmanabha  *
816cd7c298aSKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp_context
81730683082SKishore Padmanabha  * flow_type [in] - specify default or regular
818cd7c298aSKishore Padmanabha  * fid [in] The index to the flow entry
819cd7c298aSKishore Padmanabha  * nxt_idx [in/out] the index to the next entry
820cd7c298aSKishore Padmanabha  * params [out] The contents to be copied into params.
821cd7c298aSKishore Padmanabha  *
822cd7c298aSKishore Padmanabha  * returns 0 on success and negative on failure.
823cd7c298aSKishore Padmanabha  */
82430683082SKishore Padmanabha int32_t
82530683082SKishore Padmanabha ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt,
82630683082SKishore Padmanabha 			 enum bnxt_ulp_fdb_type flow_type,
827cd7c298aSKishore Padmanabha 			 uint32_t fid,
828cd7c298aSKishore Padmanabha 			 uint32_t *nxt_idx,
829cd7c298aSKishore Padmanabha 			 struct ulp_flow_db_res_params *params)
830cd7c298aSKishore Padmanabha {
831cd7c298aSKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
832cd7c298aSKishore Padmanabha 	struct bnxt_ulp_flow_tbl *flow_tbl;
833cd7c298aSKishore Padmanabha 	struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
834cd7c298aSKishore Padmanabha 
835cd7c298aSKishore Padmanabha 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
836cd7c298aSKishore Padmanabha 	if (!flow_db) {
837dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
838cd7c298aSKishore Padmanabha 		return -EINVAL;
839cd7c298aSKishore Padmanabha 	}
840cd7c298aSKishore Padmanabha 
841ddaf0afaSKishore Padmanabha 	if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
842dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow type\n");
843cd7c298aSKishore Padmanabha 		return -EINVAL;
844cd7c298aSKishore Padmanabha 	}
845cd7c298aSKishore Padmanabha 
84630683082SKishore Padmanabha 	flow_tbl = &flow_db->flow_tbl;
847cd7c298aSKishore Padmanabha 
848cd7c298aSKishore Padmanabha 	/* check for limits of fid */
849cd7c298aSKishore Padmanabha 	if (fid >= flow_tbl->num_flows || !fid) {
850dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow index\n");
851cd7c298aSKishore Padmanabha 		return -EINVAL;
852cd7c298aSKishore Padmanabha 	}
853cd7c298aSKishore Padmanabha 
854cd7c298aSKishore Padmanabha 	/* check if the flow is active or not */
85530683082SKishore Padmanabha 	if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
856dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "flow does not exist\n");
857cd7c298aSKishore Padmanabha 		return -EINVAL;
858cd7c298aSKishore Padmanabha 	}
859cd7c298aSKishore Padmanabha 
860cd7c298aSKishore Padmanabha 	if (!*nxt_idx) {
861cd7c298aSKishore Padmanabha 		fid_resource = &flow_tbl->flow_resources[fid];
862cd7c298aSKishore Padmanabha 		ulp_flow_db_res_info_to_params(fid_resource, params);
863cd7c298aSKishore Padmanabha 		ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
864cd7c298aSKishore Padmanabha 					fid_resource->nxt_resource_idx);
865cd7c298aSKishore Padmanabha 	} else {
866cd7c298aSKishore Padmanabha 		nxt_resource = &flow_tbl->flow_resources[*nxt_idx];
867cd7c298aSKishore Padmanabha 		ulp_flow_db_res_info_to_params(nxt_resource, params);
868cd7c298aSKishore Padmanabha 		*nxt_idx = 0;
869cd7c298aSKishore Padmanabha 		ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
870cd7c298aSKishore Padmanabha 					nxt_resource->nxt_resource_idx);
871cd7c298aSKishore Padmanabha 	}
872cd7c298aSKishore Padmanabha 
873cd7c298aSKishore Padmanabha 	/* all good, return success */
874cd7c298aSKishore Padmanabha 	return 0;
875cd7c298aSKishore Padmanabha }
876cd7c298aSKishore Padmanabha 
877cd7c298aSKishore Padmanabha /*
878cd7c298aSKishore Padmanabha  * Get the flow database entry iteratively
879edc6ca0cSKishore Padmanabha  *
880edc6ca0cSKishore Padmanabha  * flow_tbl [in] Ptr to flow table
88130683082SKishore Padmanabha  * flow_type [in] - specify default or regular
882edc6ca0cSKishore Padmanabha  * fid [in/out] The index to the flow entry
883edc6ca0cSKishore Padmanabha  *
884edc6ca0cSKishore Padmanabha  * returns 0 on success and negative on failure.
885edc6ca0cSKishore Padmanabha  */
886edc6ca0cSKishore Padmanabha static int32_t
88730683082SKishore Padmanabha ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
88830683082SKishore Padmanabha 			   enum bnxt_ulp_fdb_type flow_type,
889edc6ca0cSKishore Padmanabha 			   uint32_t *fid)
890edc6ca0cSKishore Padmanabha {
891edc6ca0cSKishore Padmanabha 	uint32_t lfid = *fid;
89274bcfc06SKishore Padmanabha 	uint32_t idx, s_idx, mod_fid;
893edc6ca0cSKishore Padmanabha 	uint64_t bs;
89430683082SKishore Padmanabha 	uint64_t *active_flows;
89530683082SKishore Padmanabha 	struct bnxt_ulp_flow_tbl *flowtbl = &flow_db->flow_tbl;
89630683082SKishore Padmanabha 
897ddaf0afaSKishore Padmanabha 	if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR) {
89830683082SKishore Padmanabha 		active_flows = flowtbl->active_reg_flows;
899ddaf0afaSKishore Padmanabha 	} else if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT) {
90030683082SKishore Padmanabha 		active_flows = flowtbl->active_dflt_flows;
901ddaf0afaSKishore Padmanabha 	} else {
902dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow type %x\n", flow_type);
903ddaf0afaSKishore Padmanabha 			return -EINVAL;
904ddaf0afaSKishore Padmanabha 	}
905edc6ca0cSKishore Padmanabha 
906edc6ca0cSKishore Padmanabha 	do {
90774bcfc06SKishore Padmanabha 		/* increment the flow id to find the next valid flow id */
908edc6ca0cSKishore Padmanabha 		lfid++;
909edc6ca0cSKishore Padmanabha 		if (lfid >= flowtbl->num_flows)
910edc6ca0cSKishore Padmanabha 			return -ENOENT;
911edc6ca0cSKishore Padmanabha 		idx = lfid / ULP_INDEX_BITMAP_SIZE;
91274bcfc06SKishore Padmanabha 		mod_fid = lfid % ULP_INDEX_BITMAP_SIZE;
91374bcfc06SKishore Padmanabha 		s_idx = idx;
91430683082SKishore Padmanabha 		while (!(bs = active_flows[idx])) {
915edc6ca0cSKishore Padmanabha 			idx++;
916edc6ca0cSKishore Padmanabha 			if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows)
917edc6ca0cSKishore Padmanabha 				return -ENOENT;
918edc6ca0cSKishore Padmanabha 		}
91974bcfc06SKishore Padmanabha 		/*
92074bcfc06SKishore Padmanabha 		 * remove the previous bits in the bitset bs to find the
92174bcfc06SKishore Padmanabha 		 * next non zero bit in the bitset. This needs to be done
92274bcfc06SKishore Padmanabha 		 * only if the idx is same as he one you started.
92374bcfc06SKishore Padmanabha 		 */
92474bcfc06SKishore Padmanabha 		if (s_idx == idx)
92574bcfc06SKishore Padmanabha 			bs &= (-1UL >> mod_fid);
926191128d7SDavid Marchand 		lfid = (idx * ULP_INDEX_BITMAP_SIZE) + rte_clz64(bs);
927edc6ca0cSKishore Padmanabha 		if (*fid >= lfid) {
928dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Flow Database is corrupt\n");
929edc6ca0cSKishore Padmanabha 			return -ENOENT;
930edc6ca0cSKishore Padmanabha 		}
93130683082SKishore Padmanabha 	} while (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type,
93230683082SKishore Padmanabha 						      lfid));
933edc6ca0cSKishore Padmanabha 
934edc6ca0cSKishore Padmanabha 	/* all good, return success */
935edc6ca0cSKishore Padmanabha 	*fid = lfid;
936edc6ca0cSKishore Padmanabha 	return 0;
937edc6ca0cSKishore Padmanabha }
938edc6ca0cSKishore Padmanabha 
939edc6ca0cSKishore Padmanabha /*
940edc6ca0cSKishore Padmanabha  * Flush all flows in the flow database.
941edc6ca0cSKishore Padmanabha  *
942edc6ca0cSKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp context
94330683082SKishore Padmanabha  * flow_type [in] - specify default or regular
944edc6ca0cSKishore Padmanabha  *
945edc6ca0cSKishore Padmanabha  * returns 0 on success or negative number on failure
946edc6ca0cSKishore Padmanabha  */
94730683082SKishore Padmanabha int32_t
94830683082SKishore Padmanabha ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
94930683082SKishore Padmanabha 			enum bnxt_ulp_fdb_type flow_type)
950edc6ca0cSKishore Padmanabha {
951edc6ca0cSKishore Padmanabha 	uint32_t fid = 0;
952edc6ca0cSKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
953edc6ca0cSKishore Padmanabha 
954edc6ca0cSKishore Padmanabha 	if (!ulp_ctx) {
955dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid Argument\n");
956edc6ca0cSKishore Padmanabha 		return -EINVAL;
957edc6ca0cSKishore Padmanabha 	}
958edc6ca0cSKishore Padmanabha 
959edc6ca0cSKishore Padmanabha 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
960edc6ca0cSKishore Padmanabha 	if (!flow_db) {
961dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Flow database not found\n");
962edc6ca0cSKishore Padmanabha 		return -EINVAL;
963edc6ca0cSKishore Padmanabha 	}
9646c7cbc80SKishore Padmanabha 	if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
965dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Flow db lock acquire failed\n");
9666c7cbc80SKishore Padmanabha 		return -EINVAL;
9676c7cbc80SKishore Padmanabha 	}
9686c7cbc80SKishore Padmanabha 
969288becfbSShuanglin Wang #ifdef TF_FLOW_SCALE_QUERY
970288becfbSShuanglin Wang 	tf_resc_pause_usage_update();
971288becfbSShuanglin Wang #endif
972ffbc3529SShuanglin Wang 
97330683082SKishore Padmanabha 	while (!ulp_flow_db_next_entry_get(flow_db, flow_type, &fid))
974dd0191d5SShuanglin Wang 		ulp_mapper_resources_free(ulp_ctx, flow_type, fid, NULL);
975ffbc3529SShuanglin Wang 
976288becfbSShuanglin Wang #ifdef TF_FLOW_SCALE_QUERY
977ffbc3529SShuanglin Wang 	ulp_resc_usage_sync(ulp_ctx);
978288becfbSShuanglin Wang #endif
979edc6ca0cSKishore Padmanabha 
9806c7cbc80SKishore Padmanabha 	bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
9816c7cbc80SKishore Padmanabha 
982edc6ca0cSKishore Padmanabha 	return 0;
983edc6ca0cSKishore Padmanabha }
98474bcfc06SKishore Padmanabha 
98574bcfc06SKishore Padmanabha /*
98674bcfc06SKishore Padmanabha  * Flush all flows in the flow database that belong to a device function.
98774bcfc06SKishore Padmanabha  *
98874bcfc06SKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp context
98930683082SKishore Padmanabha  * func_id [in] - The port function id
99074bcfc06SKishore Padmanabha  *
99174bcfc06SKishore Padmanabha  * returns 0 on success or negative number on failure
99274bcfc06SKishore Padmanabha  */
99374bcfc06SKishore Padmanabha int32_t
99474bcfc06SKishore Padmanabha ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
99574bcfc06SKishore Padmanabha 				uint16_t func_id)
99674bcfc06SKishore Padmanabha {
99774bcfc06SKishore Padmanabha 	uint32_t flow_id = 0;
99874bcfc06SKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
99974bcfc06SKishore Padmanabha 
100074bcfc06SKishore Padmanabha 	if (!ulp_ctx || !func_id) {
1001dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid Argument\n");
100274bcfc06SKishore Padmanabha 		return -EINVAL;
100374bcfc06SKishore Padmanabha 	}
100474bcfc06SKishore Padmanabha 
100574bcfc06SKishore Padmanabha 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
100674bcfc06SKishore Padmanabha 	if (!flow_db) {
1007dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Flow database not found\n");
100874bcfc06SKishore Padmanabha 		return -EINVAL;
100974bcfc06SKishore Padmanabha 	}
10106c7cbc80SKishore Padmanabha 	if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
1011dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Flow db lock acquire failed\n");
10126c7cbc80SKishore Padmanabha 		return -EINVAL;
10136c7cbc80SKishore Padmanabha 	}
101430683082SKishore Padmanabha 
1015288becfbSShuanglin Wang #ifdef TF_FLOW_SCALE_QUERY
1016288becfbSShuanglin Wang 	tf_resc_pause_usage_update();
1017288becfbSShuanglin Wang #endif
101830683082SKishore Padmanabha 	while (!ulp_flow_db_next_entry_get(flow_db, BNXT_ULP_FDB_TYPE_REGULAR,
101930683082SKishore Padmanabha 					   &flow_id)) {
102074bcfc06SKishore Padmanabha 		if (flow_db->func_id_tbl[flow_id] == func_id)
102130683082SKishore Padmanabha 			ulp_mapper_resources_free(ulp_ctx,
102230683082SKishore Padmanabha 						  BNXT_ULP_FDB_TYPE_REGULAR,
1023dd0191d5SShuanglin Wang 						  flow_id,
1024dd0191d5SShuanglin Wang 						  NULL);
102574bcfc06SKishore Padmanabha 	}
1026288becfbSShuanglin Wang #ifdef TF_FLOW_SCALE_QUERY
1027ffbc3529SShuanglin Wang 	ulp_resc_usage_sync(ulp_ctx);
1028288becfbSShuanglin Wang #endif
10296c7cbc80SKishore Padmanabha 	bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
103074bcfc06SKishore Padmanabha 	return 0;
103174bcfc06SKishore Padmanabha }
103274bcfc06SKishore Padmanabha 
103374bcfc06SKishore Padmanabha /*
103474bcfc06SKishore Padmanabha  * Flush all flows in the flow database that are associated with the session.
103574bcfc06SKishore Padmanabha  *
103674bcfc06SKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp context
103774bcfc06SKishore Padmanabha  *
103874bcfc06SKishore Padmanabha  * returns 0 on success or negative number on failure
103974bcfc06SKishore Padmanabha  */
104074bcfc06SKishore Padmanabha int32_t
104174bcfc06SKishore Padmanabha ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx)
104274bcfc06SKishore Padmanabha {
104374bcfc06SKishore Padmanabha 	/*
104474bcfc06SKishore Padmanabha 	 * TBD: Tf core implementation of FW session flush shall change this
104574bcfc06SKishore Padmanabha 	 * implementation.
104674bcfc06SKishore Padmanabha 	 */
104730683082SKishore Padmanabha 	return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR);
104874bcfc06SKishore Padmanabha }
104974bcfc06SKishore Padmanabha 
105074bcfc06SKishore Padmanabha /*
105174bcfc06SKishore Padmanabha  * Check that flow id matches the function id or not
105274bcfc06SKishore Padmanabha  *
105374bcfc06SKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp context
105474bcfc06SKishore Padmanabha  * flow_db [in] Ptr to flow table
105574bcfc06SKishore Padmanabha  * func_id [in] The func_id to be set, for reset pass zero.
105674bcfc06SKishore Padmanabha  *
105774bcfc06SKishore Padmanabha  * returns true on success or false on failure
105874bcfc06SKishore Padmanabha  */
105974bcfc06SKishore Padmanabha bool
106074bcfc06SKishore Padmanabha ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
106174bcfc06SKishore Padmanabha 			       uint32_t flow_id,
106274bcfc06SKishore Padmanabha 			       uint32_t func_id)
106374bcfc06SKishore Padmanabha {
106474bcfc06SKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
106574bcfc06SKishore Padmanabha 
106674bcfc06SKishore Padmanabha 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
106774bcfc06SKishore Padmanabha 	if (!flow_db) {
1068dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Flow database not found\n");
106974bcfc06SKishore Padmanabha 		return false;
107074bcfc06SKishore Padmanabha 	}
107174bcfc06SKishore Padmanabha 
107274bcfc06SKishore Padmanabha 	/* set the function id in the function table */
107374bcfc06SKishore Padmanabha 	if (flow_id < flow_db->func_id_tbl_size && func_id &&
107474bcfc06SKishore Padmanabha 	    flow_db->func_id_tbl[flow_id] == func_id)
107574bcfc06SKishore Padmanabha 		return true;
107674bcfc06SKishore Padmanabha 
107774bcfc06SKishore Padmanabha 	return false;
107874bcfc06SKishore Padmanabha }
1079d310d59cSKishore Padmanabha 
1080d310d59cSKishore Padmanabha /*
1081d310d59cSKishore Padmanabha  * Internal api to traverse the resource list within a flow
1082d310d59cSKishore Padmanabha  * and match a resource based on resource func and resource
1083d310d59cSKishore Padmanabha  * sub type. This api should be used only for resources that
1084d310d59cSKishore Padmanabha  * are unique and do not have multiple instances of resource
1085d310d59cSKishore Padmanabha  * func and sub type combination since it will return only
1086d310d59cSKishore Padmanabha  * the first match.
1087d310d59cSKishore Padmanabha  */
1088d310d59cSKishore Padmanabha static int32_t
1089640bfd23SKishore Padmanabha ulp_flow_db_resource_params_get(struct bnxt_ulp_context *ulp_ctx,
109030683082SKishore Padmanabha 				enum bnxt_ulp_fdb_type flow_type,
1091d310d59cSKishore Padmanabha 				uint32_t flow_id,
1092d310d59cSKishore Padmanabha 				uint32_t resource_func,
1093d310d59cSKishore Padmanabha 				uint32_t res_subtype,
1094640bfd23SKishore Padmanabha 				struct ulp_flow_db_res_params *params)
1095d310d59cSKishore Padmanabha {
1096d310d59cSKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
1097d310d59cSKishore Padmanabha 	struct bnxt_ulp_flow_tbl *flow_tbl;
1098d310d59cSKishore Padmanabha 	struct ulp_fdb_resource_info *fid_res;
1099d310d59cSKishore Padmanabha 	uint32_t res_id;
1100d310d59cSKishore Padmanabha 
1101d310d59cSKishore Padmanabha 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1102d310d59cSKishore Padmanabha 	if (!flow_db) {
1103dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Flow database not found\n");
1104d310d59cSKishore Padmanabha 		return -EINVAL;
1105d310d59cSKishore Padmanabha 	}
1106d310d59cSKishore Padmanabha 
1107640bfd23SKishore Padmanabha 	if (!params) {
1108dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid argument\n");
1109640bfd23SKishore Padmanabha 		return -EINVAL;
1110640bfd23SKishore Padmanabha 	}
1111640bfd23SKishore Padmanabha 
1112ddaf0afaSKishore Padmanabha 	if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
1113dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow type\n");
111430683082SKishore Padmanabha 		return -EINVAL;
111530683082SKishore Padmanabha 	}
111630683082SKishore Padmanabha 
111730683082SKishore Padmanabha 	flow_tbl = &flow_db->flow_tbl;
1118d310d59cSKishore Padmanabha 
1119d310d59cSKishore Padmanabha 	/* check for limits of fid */
1120d310d59cSKishore Padmanabha 	if (flow_id >= flow_tbl->num_flows || !flow_id) {
1121dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow index\n");
1122d310d59cSKishore Padmanabha 		return -EINVAL;
1123d310d59cSKishore Padmanabha 	}
1124d310d59cSKishore Padmanabha 
1125d310d59cSKishore Padmanabha 	/* check if the flow is active or not */
112630683082SKishore Padmanabha 	if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, flow_id)) {
1127dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "flow does not exist\n");
1128d310d59cSKishore Padmanabha 		return -EINVAL;
1129d310d59cSKishore Padmanabha 	}
1130d310d59cSKishore Padmanabha 	/* Iterate the resource to get the resource handle */
1131d310d59cSKishore Padmanabha 	res_id =  flow_id;
1132640bfd23SKishore Padmanabha 	memset(params, 0, sizeof(struct ulp_flow_db_res_params));
1133d310d59cSKishore Padmanabha 	while (res_id) {
1134d310d59cSKishore Padmanabha 		fid_res = &flow_tbl->flow_resources[res_id];
1135f6e12015SKishore Padmanabha 		if (ulp_flow_db_resource_func_get(fid_res) == resource_func &&
1136f6e12015SKishore Padmanabha 		    fid_res->resource_sub_type == res_subtype) {
1137f6e12015SKishore Padmanabha 			ulp_flow_db_res_info_to_params(fid_res, params);
1138d310d59cSKishore Padmanabha 			return 0;
1139d310d59cSKishore Padmanabha 		}
1140d310d59cSKishore Padmanabha 		res_id = 0;
1141d310d59cSKishore Padmanabha 		ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
1142d310d59cSKishore Padmanabha 	}
1143d310d59cSKishore Padmanabha 	return -ENOENT;
1144d310d59cSKishore Padmanabha }
1145d310d59cSKishore Padmanabha 
1146d310d59cSKishore Padmanabha /*
1147d310d59cSKishore Padmanabha  * Api to get the cfa action pointer from a flow.
1148d310d59cSKishore Padmanabha  *
1149d310d59cSKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp context
1150d310d59cSKishore Padmanabha  * flow_id [in] flow id
1151d310d59cSKishore Padmanabha  * cfa_action [out] The resource handle stored in the flow database
1152d310d59cSKishore Padmanabha  *
1153d310d59cSKishore Padmanabha  * returns 0 on success
1154d310d59cSKishore Padmanabha  */
1155d310d59cSKishore Padmanabha int32_t
1156d310d59cSKishore Padmanabha ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx,
1157d310d59cSKishore Padmanabha 				   uint32_t flow_id,
1158dd0191d5SShuanglin Wang 				   uint32_t *cfa_action)
1159d310d59cSKishore Padmanabha {
11609cbfa4cfSKishore Padmanabha 	uint8_t sub_typ = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_VFR_CFA_ACTION;
1161640bfd23SKishore Padmanabha 	struct ulp_flow_db_res_params params;
1162d310d59cSKishore Padmanabha 	int32_t rc;
1163d310d59cSKishore Padmanabha 
1164640bfd23SKishore Padmanabha 	rc = ulp_flow_db_resource_params_get(ulp_ctx,
116530683082SKishore Padmanabha 					     BNXT_ULP_FDB_TYPE_DEFAULT,
1166d310d59cSKishore Padmanabha 					     flow_id,
1167d310d59cSKishore Padmanabha 					     BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
11689cbfa4cfSKishore Padmanabha 					     sub_typ, &params);
1169d310d59cSKishore Padmanabha 	if (rc) {
117061a7ca1fSKishore Padmanabha 		BNXT_DRV_DBG(DEBUG, "CFA Action ptr not found for flow id %u\n",
1171d310d59cSKishore Padmanabha 			     flow_id);
1172d310d59cSKishore Padmanabha 		return -ENOENT;
1173d310d59cSKishore Padmanabha 	}
1174640bfd23SKishore Padmanabha 	*cfa_action = params.resource_hndl;
1175d310d59cSKishore Padmanabha 	return 0;
1176d310d59cSKishore Padmanabha }
1177f4a4421cSKishore Padmanabha 
1178bdf4a3c6SKishore Padmanabha /* internal validation function for parent flow tbl */
1179*a089734aSShuanglin Wang struct ulp_fdb_parent_info *
1180bdf4a3c6SKishore Padmanabha ulp_flow_db_pc_db_entry_get(struct bnxt_ulp_context *ulp_ctxt,
1181bdf4a3c6SKishore Padmanabha 			    uint32_t pc_idx)
1182bdf4a3c6SKishore Padmanabha {
1183bdf4a3c6SKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
1184bdf4a3c6SKishore Padmanabha 
1185bdf4a3c6SKishore Padmanabha 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1186bdf4a3c6SKishore Padmanabha 	if (!flow_db) {
1187dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
1188bdf4a3c6SKishore Padmanabha 		return NULL;
1189bdf4a3c6SKishore Padmanabha 	}
1190bdf4a3c6SKishore Padmanabha 
1191bdf4a3c6SKishore Padmanabha 	/* check for max flows */
1192bdf4a3c6SKishore Padmanabha 	if (pc_idx >= BNXT_ULP_MAX_TUN_CACHE_ENTRIES) {
1193dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid tunnel index\n");
1194bdf4a3c6SKishore Padmanabha 		return NULL;
1195bdf4a3c6SKishore Padmanabha 	}
1196bdf4a3c6SKishore Padmanabha 
1197bdf4a3c6SKishore Padmanabha 	/* No support for parent child db then just exit */
1198bdf4a3c6SKishore Padmanabha 	if (!flow_db->parent_child_db.entries_count) {
1199dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "parent child db not supported\n");
1200bdf4a3c6SKishore Padmanabha 		return NULL;
1201bdf4a3c6SKishore Padmanabha 	}
1202bdf4a3c6SKishore Padmanabha 	if (!flow_db->parent_child_db.parent_flow_tbl[pc_idx].valid) {
1203dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Not a valid tunnel index\n");
1204bdf4a3c6SKishore Padmanabha 		return NULL;
1205bdf4a3c6SKishore Padmanabha 	}
1206bdf4a3c6SKishore Padmanabha 
1207bdf4a3c6SKishore Padmanabha 	return &flow_db->parent_child_db.parent_flow_tbl[pc_idx];
1208bdf4a3c6SKishore Padmanabha }
1209bdf4a3c6SKishore Padmanabha 
1210bdf4a3c6SKishore Padmanabha /* internal validation function for parent flow tbl */
1211bdf4a3c6SKishore Padmanabha static struct bnxt_ulp_flow_db *
1212bdf4a3c6SKishore Padmanabha ulp_flow_db_parent_arg_validation(struct bnxt_ulp_context *ulp_ctxt,
1213bdf4a3c6SKishore Padmanabha 				  uint32_t tun_idx)
1214bdf4a3c6SKishore Padmanabha {
1215bdf4a3c6SKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
1216bdf4a3c6SKishore Padmanabha 
1217bdf4a3c6SKishore Padmanabha 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1218bdf4a3c6SKishore Padmanabha 	if (!flow_db) {
1219dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
1220bdf4a3c6SKishore Padmanabha 		return NULL;
1221bdf4a3c6SKishore Padmanabha 	}
1222bdf4a3c6SKishore Padmanabha 
1223bdf4a3c6SKishore Padmanabha 	/* check for max flows */
1224bdf4a3c6SKishore Padmanabha 	if (tun_idx >= BNXT_ULP_MAX_TUN_CACHE_ENTRIES) {
1225dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid tunnel index\n");
1226bdf4a3c6SKishore Padmanabha 		return NULL;
1227bdf4a3c6SKishore Padmanabha 	}
1228bdf4a3c6SKishore Padmanabha 
1229bdf4a3c6SKishore Padmanabha 	/* No support for parent child db then just exit */
1230bdf4a3c6SKishore Padmanabha 	if (!flow_db->parent_child_db.entries_count) {
1231dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "parent child db not supported\n");
1232bdf4a3c6SKishore Padmanabha 		return NULL;
1233bdf4a3c6SKishore Padmanabha 	}
1234bdf4a3c6SKishore Padmanabha 
1235bdf4a3c6SKishore Padmanabha 	return flow_db;
1236bdf4a3c6SKishore Padmanabha }
1237bdf4a3c6SKishore Padmanabha 
1238f4a4421cSKishore Padmanabha /*
1239f4a4421cSKishore Padmanabha  * Allocate the entry in the parent-child database
1240f4a4421cSKishore Padmanabha  *
1241f4a4421cSKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp_context
1242bdf4a3c6SKishore Padmanabha  * tun_idx [in] The tunnel index of the flow entry
1243f4a4421cSKishore Padmanabha  *
1244f4a4421cSKishore Padmanabha  * returns index on success and negative on failure.
1245f4a4421cSKishore Padmanabha  */
1246bdf4a3c6SKishore Padmanabha static int32_t
1247bdf4a3c6SKishore Padmanabha ulp_flow_db_pc_db_idx_alloc(struct bnxt_ulp_context *ulp_ctxt,
1248bdf4a3c6SKishore Padmanabha 			    uint32_t tun_idx)
1249f4a4421cSKishore Padmanabha {
1250f4a4421cSKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
1251f4a4421cSKishore Padmanabha 	struct ulp_fdb_parent_child_db *p_pdb;
1252f4a4421cSKishore Padmanabha 	uint32_t idx, free_idx = 0;
1253f4a4421cSKishore Padmanabha 
1254640bfd23SKishore Padmanabha 	/* validate the arguments */
1255bdf4a3c6SKishore Padmanabha 	flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, tun_idx);
1256f4a4421cSKishore Padmanabha 	if (!flow_db) {
1257dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "parent child db validation failed\n");
1258be8acb27SKishore Padmanabha 		return -EINVAL;
1259be8acb27SKishore Padmanabha 	}
1260be8acb27SKishore Padmanabha 
1261f4a4421cSKishore Padmanabha 	p_pdb = &flow_db->parent_child_db;
1262640bfd23SKishore Padmanabha 	for (idx = 0; idx < p_pdb->entries_count; idx++) {
1263bdf4a3c6SKishore Padmanabha 		if (p_pdb->parent_flow_tbl[idx].valid &&
1264bdf4a3c6SKishore Padmanabha 		    p_pdb->parent_flow_tbl[idx].tun_idx == tun_idx) {
1265bdf4a3c6SKishore Padmanabha 			return idx;
1266f4a4421cSKishore Padmanabha 		}
1267bdf4a3c6SKishore Padmanabha 		if (!p_pdb->parent_flow_tbl[idx].valid && !free_idx)
1268f4a4421cSKishore Padmanabha 			free_idx = idx + 1;
1269f4a4421cSKishore Padmanabha 	}
1270f4a4421cSKishore Padmanabha 	/* no free slots */
1271f4a4421cSKishore Padmanabha 	if (!free_idx) {
1272dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "parent child db is full\n");
1273f4a4421cSKishore Padmanabha 		return -ENOMEM;
1274f4a4421cSKishore Padmanabha 	}
1275f4a4421cSKishore Padmanabha 
1276f4a4421cSKishore Padmanabha 	free_idx -= 1;
1277f4a4421cSKishore Padmanabha 	/* set the Fid in the parent child */
1278bdf4a3c6SKishore Padmanabha 	p_pdb->parent_flow_tbl[free_idx].tun_idx = tun_idx;
1279bdf4a3c6SKishore Padmanabha 	p_pdb->parent_flow_tbl[free_idx].valid = 1;
1280f4a4421cSKishore Padmanabha 	return free_idx;
1281f4a4421cSKishore Padmanabha }
1282f4a4421cSKishore Padmanabha 
1283f4a4421cSKishore Padmanabha /*
1284f4a4421cSKishore Padmanabha  * Free the entry in the parent-child database
1285f4a4421cSKishore Padmanabha  *
1286bdf4a3c6SKishore Padmanabha  * pc_entry [in] Ptr to parent child db entry
1287f4a4421cSKishore Padmanabha  *
1288bdf4a3c6SKishore Padmanabha  * returns none.
1289bdf4a3c6SKishore Padmanabha  */
1290bdf4a3c6SKishore Padmanabha static void
1291bdf4a3c6SKishore Padmanabha ulp_flow_db_pc_db_entry_free(struct bnxt_ulp_context *ulp_ctxt,
1292bdf4a3c6SKishore Padmanabha 			     struct ulp_fdb_parent_info *pc_entry)
1293bdf4a3c6SKishore Padmanabha {
1294bdf4a3c6SKishore Padmanabha 	struct bnxt_tun_cache_entry *tun_tbl;
1295bdf4a3c6SKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
1296bdf4a3c6SKishore Padmanabha 	uint64_t *tmp_bitset;
1297bdf4a3c6SKishore Padmanabha 
1298bdf4a3c6SKishore Padmanabha 	/* free the tunnel entry */
1299bdf4a3c6SKishore Padmanabha 	tun_tbl = bnxt_ulp_cntxt_ptr2_tun_tbl_get(ulp_ctxt);
1300bdf4a3c6SKishore Padmanabha 	if (tun_tbl)
1301bdf4a3c6SKishore Padmanabha 		ulp_tunnel_offload_entry_clear(tun_tbl, pc_entry->tun_idx);
1302bdf4a3c6SKishore Padmanabha 
1303bdf4a3c6SKishore Padmanabha 	/* free the child bitset*/
1304bdf4a3c6SKishore Padmanabha 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1305bdf4a3c6SKishore Padmanabha 	if (flow_db)
1306bdf4a3c6SKishore Padmanabha 		memset(pc_entry->child_fid_bitset, 0,
1307bdf4a3c6SKishore Padmanabha 		       flow_db->parent_child_db.child_bitset_size);
1308bdf4a3c6SKishore Padmanabha 
1309bdf4a3c6SKishore Padmanabha 	/* free the contents */
1310bdf4a3c6SKishore Padmanabha 	tmp_bitset = pc_entry->child_fid_bitset;
1311bdf4a3c6SKishore Padmanabha 	memset(pc_entry, 0, sizeof(struct ulp_fdb_parent_info));
1312bdf4a3c6SKishore Padmanabha 	pc_entry->child_fid_bitset = tmp_bitset;
1313bdf4a3c6SKishore Padmanabha }
1314bdf4a3c6SKishore Padmanabha 
1315bdf4a3c6SKishore Padmanabha /*
1316bdf4a3c6SKishore Padmanabha  * Set or reset the parent flow in the parent-child database
1317bdf4a3c6SKishore Padmanabha  *
1318bdf4a3c6SKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp_context
1319bdf4a3c6SKishore Padmanabha  * pc_idx [in] The index to parent child db
1320bdf4a3c6SKishore Padmanabha  * parent_fid [in] The flow id of the parent flow entry
1321bdf4a3c6SKishore Padmanabha  * set_flag [in] Use 1 for setting child, 0 to reset
1322bdf4a3c6SKishore Padmanabha  *
1323bdf4a3c6SKishore Padmanabha  * returns zero on success and negative on failure.
1324f4a4421cSKishore Padmanabha  */
1325f4a4421cSKishore Padmanabha int32_t
1326bdf4a3c6SKishore Padmanabha ulp_flow_db_pc_db_parent_flow_set(struct bnxt_ulp_context *ulp_ctxt,
1327bdf4a3c6SKishore Padmanabha 				  uint32_t pc_idx,
1328bdf4a3c6SKishore Padmanabha 				  uint32_t parent_fid,
1329bdf4a3c6SKishore Padmanabha 				  uint32_t set_flag)
1330f4a4421cSKishore Padmanabha {
1331bdf4a3c6SKishore Padmanabha 	struct ulp_fdb_parent_info *pc_entry;
1332f4a4421cSKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
1333f4a4421cSKishore Padmanabha 
1334bdf4a3c6SKishore Padmanabha 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1335f4a4421cSKishore Padmanabha 	if (!flow_db) {
1336dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "parent child db validation failed\n");
1337be8acb27SKishore Padmanabha 		return -EINVAL;
1338be8acb27SKishore Padmanabha 	}
1339be8acb27SKishore Padmanabha 
1340bdf4a3c6SKishore Padmanabha 	/* check for fid validity */
1341bdf4a3c6SKishore Padmanabha 	if (parent_fid >= flow_db->flow_tbl.num_flows || !parent_fid) {
1342dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid parent flow index %x\n", parent_fid);
1343f4a4421cSKishore Padmanabha 		return -EINVAL;
1344f4a4421cSKishore Padmanabha 	}
1345f4a4421cSKishore Padmanabha 
1346bdf4a3c6SKishore Padmanabha 	/* validate the arguments and parent child entry */
1347bdf4a3c6SKishore Padmanabha 	pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx);
1348bdf4a3c6SKishore Padmanabha 	if (!pc_entry) {
1349dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "failed to get the parent child entry\n");
1350bdf4a3c6SKishore Padmanabha 		return -EINVAL;
1351bdf4a3c6SKishore Padmanabha 	}
1352bdf4a3c6SKishore Padmanabha 
1353bdf4a3c6SKishore Padmanabha 	if (set_flag) {
1354bdf4a3c6SKishore Padmanabha 		pc_entry->parent_fid = parent_fid;
13558782e4deSKishore Padmanabha 		pc_entry->parent_ref_cnt++;
1356bdf4a3c6SKishore Padmanabha 	} else {
13578782e4deSKishore Padmanabha 		if (pc_entry->parent_ref_cnt > 0)
13588782e4deSKishore Padmanabha 			pc_entry->parent_ref_cnt--;
1359bdf4a3c6SKishore Padmanabha 		/* Free the parent child db entry if no user present */
13608782e4deSKishore Padmanabha 		if (!pc_entry->parent_ref_cnt && !pc_entry->f2_cnt)
1361bdf4a3c6SKishore Padmanabha 			ulp_flow_db_pc_db_entry_free(ulp_ctxt, pc_entry);
1362bdf4a3c6SKishore Padmanabha 	}
1363bdf4a3c6SKishore Padmanabha 	return 0;
1364bdf4a3c6SKishore Padmanabha }
1365bdf4a3c6SKishore Padmanabha 
1366f4a4421cSKishore Padmanabha /*
1367f4a4421cSKishore Padmanabha  * Set or reset the child flow in the parent-child database
1368f4a4421cSKishore Padmanabha  *
1369f4a4421cSKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp_context
1370bdf4a3c6SKishore Padmanabha  * pc_idx [in] The index to parent child db
1371f4a4421cSKishore Padmanabha  * child_fid [in] The flow id of the child flow entry
1372f4a4421cSKishore Padmanabha  * set_flag [in] Use 1 for setting child, 0 to reset
1373f4a4421cSKishore Padmanabha  *
1374f4a4421cSKishore Padmanabha  * returns zero on success and negative on failure.
1375f4a4421cSKishore Padmanabha  */
1376f4a4421cSKishore Padmanabha int32_t
1377bdf4a3c6SKishore Padmanabha ulp_flow_db_pc_db_child_flow_set(struct bnxt_ulp_context *ulp_ctxt,
1378bdf4a3c6SKishore Padmanabha 				 uint32_t pc_idx,
1379f4a4421cSKishore Padmanabha 				 uint32_t child_fid,
1380f4a4421cSKishore Padmanabha 				 uint32_t set_flag)
1381f4a4421cSKishore Padmanabha {
1382bdf4a3c6SKishore Padmanabha 	struct ulp_fdb_parent_info *pc_entry;
1383f4a4421cSKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
1384bdf4a3c6SKishore Padmanabha 	uint32_t a_idx;
1385f4a4421cSKishore Padmanabha 	uint64_t *t;
1386f4a4421cSKishore Padmanabha 
1387bdf4a3c6SKishore Padmanabha 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1388f4a4421cSKishore Padmanabha 	if (!flow_db) {
1389dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "parent child db validation failed\n");
1390f4a4421cSKishore Padmanabha 		return -EINVAL;
1391f4a4421cSKishore Padmanabha 	}
1392f4a4421cSKishore Padmanabha 
1393f4a4421cSKishore Padmanabha 	/* check for fid validity */
1394f4a4421cSKishore Padmanabha 	if (child_fid >= flow_db->flow_tbl.num_flows || !child_fid) {
1395dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid child flow index %x\n", child_fid);
1396f4a4421cSKishore Padmanabha 		return -EINVAL;
1397f4a4421cSKishore Padmanabha 	}
1398f4a4421cSKishore Padmanabha 
1399bdf4a3c6SKishore Padmanabha 	/* validate the arguments and parent child entry */
1400bdf4a3c6SKishore Padmanabha 	pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx);
1401bdf4a3c6SKishore Padmanabha 	if (!pc_entry) {
1402dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "failed to get the parent child entry\n");
1403be8acb27SKishore Padmanabha 		return -EINVAL;
1404be8acb27SKishore Padmanabha 	}
1405be8acb27SKishore Padmanabha 
1406bdf4a3c6SKishore Padmanabha 	a_idx = child_fid / ULP_INDEX_BITMAP_SIZE;
1407bdf4a3c6SKishore Padmanabha 	t = pc_entry->child_fid_bitset;
1408bdf4a3c6SKishore Padmanabha 	if (set_flag) {
1409bdf4a3c6SKishore Padmanabha 		ULP_INDEX_BITMAP_SET(t[a_idx], child_fid);
1410bdf4a3c6SKishore Padmanabha 		pc_entry->f2_cnt++;
1411bdf4a3c6SKishore Padmanabha 	} else {
1412bdf4a3c6SKishore Padmanabha 		ULP_INDEX_BITMAP_RESET(t[a_idx], child_fid);
1413bdf4a3c6SKishore Padmanabha 		if (pc_entry->f2_cnt)
1414bdf4a3c6SKishore Padmanabha 			pc_entry->f2_cnt--;
14158782e4deSKishore Padmanabha 		if (!pc_entry->f2_cnt && !pc_entry->parent_ref_cnt)
1416bdf4a3c6SKishore Padmanabha 			ulp_flow_db_pc_db_entry_free(ulp_ctxt, pc_entry);
1417bdf4a3c6SKishore Padmanabha 	}
1418f4a4421cSKishore Padmanabha 	return 0;
1419f4a4421cSKishore Padmanabha }
1420f4a4421cSKishore Padmanabha 
1421f4a4421cSKishore Padmanabha /*
1422f4a4421cSKishore Padmanabha  * Get the next child flow in the parent-child database
1423f4a4421cSKishore Padmanabha  *
1424f4a4421cSKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp_context
1425f4a4421cSKishore Padmanabha  * parent_fid [in] The flow id of the parent flow entry
1426f4a4421cSKishore Padmanabha  * child_fid [in/out] The flow id of the child flow entry
1427f4a4421cSKishore Padmanabha  *
1428f4a4421cSKishore Padmanabha  * returns zero on success and negative on failure.
1429f4a4421cSKishore Padmanabha  * Pass child_fid as zero for first entry.
1430f4a4421cSKishore Padmanabha  */
1431f4a4421cSKishore Padmanabha int32_t
1432f4a4421cSKishore Padmanabha ulp_flow_db_parent_child_flow_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
1433f4a4421cSKishore Padmanabha 					     uint32_t parent_idx,
1434f4a4421cSKishore Padmanabha 					     uint32_t *child_fid)
1435f4a4421cSKishore Padmanabha {
1436f4a4421cSKishore Padmanabha 	struct ulp_fdb_parent_child_db *p_pdb;
1437f4a4421cSKishore Padmanabha 	uint32_t idx, s_idx, mod_fid;
1438f4a4421cSKishore Padmanabha 	uint32_t next_fid = *child_fid;
1439f4a4421cSKishore Padmanabha 	uint64_t *child_bitset;
1440f4a4421cSKishore Padmanabha 	uint64_t bs;
1441f4a4421cSKishore Padmanabha 
1442f4a4421cSKishore Padmanabha 	/* check for fid validity */
1443f4a4421cSKishore Padmanabha 	p_pdb = &flow_db->parent_child_db;
1444f4a4421cSKishore Padmanabha 	if (parent_idx >= p_pdb->entries_count ||
1445f4a4421cSKishore Padmanabha 	    !p_pdb->parent_flow_tbl[parent_idx].parent_fid) {
1446dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid parent flow index %x\n", parent_idx);
1447f4a4421cSKishore Padmanabha 		return -EINVAL;
1448f4a4421cSKishore Padmanabha 	}
1449f4a4421cSKishore Padmanabha 
1450f4a4421cSKishore Padmanabha 	child_bitset = p_pdb->parent_flow_tbl[parent_idx].child_fid_bitset;
1451f4a4421cSKishore Padmanabha 	do {
1452f4a4421cSKishore Padmanabha 		/* increment the flow id to find the next valid flow id */
1453f4a4421cSKishore Padmanabha 		next_fid++;
1454f4a4421cSKishore Padmanabha 		if (next_fid >= flow_db->flow_tbl.num_flows)
1455f4a4421cSKishore Padmanabha 			return -ENOENT;
1456f4a4421cSKishore Padmanabha 		idx = next_fid / ULP_INDEX_BITMAP_SIZE;
1457f4a4421cSKishore Padmanabha 		mod_fid = next_fid % ULP_INDEX_BITMAP_SIZE;
1458f4a4421cSKishore Padmanabha 		s_idx = idx;
1459f4a4421cSKishore Padmanabha 		while (!(bs = child_bitset[idx])) {
1460f4a4421cSKishore Padmanabha 			idx++;
1461f4a4421cSKishore Padmanabha 			if ((idx * ULP_INDEX_BITMAP_SIZE) >=
1462f4a4421cSKishore Padmanabha 			    flow_db->flow_tbl.num_flows)
1463f4a4421cSKishore Padmanabha 				return -ENOENT;
1464f4a4421cSKishore Padmanabha 		}
1465f4a4421cSKishore Padmanabha 		/*
1466f4a4421cSKishore Padmanabha 		 * remove the previous bits in the bitset bs to find the
1467f4a4421cSKishore Padmanabha 		 * next non zero bit in the bitset. This needs to be done
1468f4a4421cSKishore Padmanabha 		 * only if the idx is same as he one you started.
1469f4a4421cSKishore Padmanabha 		 */
1470f4a4421cSKishore Padmanabha 		if (s_idx == idx)
1471f4a4421cSKishore Padmanabha 			bs &= (-1UL >> mod_fid);
1472191128d7SDavid Marchand 		next_fid = (idx * ULP_INDEX_BITMAP_SIZE) + rte_clz64(bs);
1473f4a4421cSKishore Padmanabha 		if (*child_fid >= next_fid) {
1474dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Parent Child Database is corrupt\n");
1475f4a4421cSKishore Padmanabha 			return -ENOENT;
1476f4a4421cSKishore Padmanabha 		}
1477f4a4421cSKishore Padmanabha 		idx = next_fid / ULP_INDEX_BITMAP_SIZE;
1478f4a4421cSKishore Padmanabha 	} while (!ULP_INDEX_BITMAP_GET(child_bitset[idx], next_fid));
1479f4a4421cSKishore Padmanabha 	*child_fid = next_fid;
1480f4a4421cSKishore Padmanabha 	return 0;
1481f4a4421cSKishore Padmanabha }
1482be8acb27SKishore Padmanabha 
1483be8acb27SKishore Padmanabha /*
1484640bfd23SKishore Padmanabha  * Set the counter accumulation in the parent flow
1485640bfd23SKishore Padmanabha  *
1486640bfd23SKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp_context
1487bdf4a3c6SKishore Padmanabha  * pc_idx [in] The parent child index of the parent flow entry
1488640bfd23SKishore Padmanabha  *
1489640bfd23SKishore Padmanabha  * returns index on success and negative on failure.
1490640bfd23SKishore Padmanabha  */
1491640bfd23SKishore Padmanabha static int32_t
1492640bfd23SKishore Padmanabha ulp_flow_db_parent_flow_count_accum_set(struct bnxt_ulp_context *ulp_ctxt,
1493bdf4a3c6SKishore Padmanabha 					uint32_t pc_idx)
1494640bfd23SKishore Padmanabha {
1495640bfd23SKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
1496640bfd23SKishore Padmanabha 	struct ulp_fdb_parent_child_db *p_pdb;
1497640bfd23SKishore Padmanabha 
1498640bfd23SKishore Padmanabha 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1499640bfd23SKishore Padmanabha 	if (!flow_db) {
1500dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
1501640bfd23SKishore Padmanabha 		return -EINVAL;
1502640bfd23SKishore Padmanabha 	}
1503640bfd23SKishore Padmanabha 
1504640bfd23SKishore Padmanabha 	/* check for parent idx validity */
1505640bfd23SKishore Padmanabha 	p_pdb = &flow_db->parent_child_db;
1506bdf4a3c6SKishore Padmanabha 	if (pc_idx >= p_pdb->entries_count ||
15078782e4deSKishore Padmanabha 	    !p_pdb->parent_flow_tbl[pc_idx].parent_ref_cnt) {
1508dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid parent child index %x\n", pc_idx);
1509640bfd23SKishore Padmanabha 		return -EINVAL;
1510640bfd23SKishore Padmanabha 	}
1511640bfd23SKishore Padmanabha 
1512bdf4a3c6SKishore Padmanabha 	p_pdb->parent_flow_tbl[pc_idx].counter_acc = 1;
1513640bfd23SKishore Padmanabha 	return 0;
1514640bfd23SKishore Padmanabha }
1515640bfd23SKishore Padmanabha 
1516640bfd23SKishore Padmanabha /*
1517be8acb27SKishore Padmanabha  * Orphan the child flow entry
1518be8acb27SKishore Padmanabha  * This is called only for child flows that have
1519be8acb27SKishore Padmanabha  * BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW resource
1520be8acb27SKishore Padmanabha  *
1521be8acb27SKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp_context
1522be8acb27SKishore Padmanabha  * flow_type [in] Specify it is regular or default flow
1523be8acb27SKishore Padmanabha  * fid [in] The index to the flow entry
1524be8acb27SKishore Padmanabha  *
1525be8acb27SKishore Padmanabha  * Returns 0 on success and negative on failure.
1526be8acb27SKishore Padmanabha  */
1527be8acb27SKishore Padmanabha int32_t
1528be8acb27SKishore Padmanabha ulp_flow_db_child_flow_reset(struct bnxt_ulp_context *ulp_ctxt,
1529be8acb27SKishore Padmanabha 			     enum bnxt_ulp_fdb_type flow_type,
1530be8acb27SKishore Padmanabha 			     uint32_t fid)
1531be8acb27SKishore Padmanabha {
1532be8acb27SKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
1533be8acb27SKishore Padmanabha 	struct bnxt_ulp_flow_tbl *flow_tbl;
1534be8acb27SKishore Padmanabha 	struct ulp_fdb_resource_info *fid_res;
1535be8acb27SKishore Padmanabha 	uint32_t res_id = 0;
1536be8acb27SKishore Padmanabha 
1537be8acb27SKishore Padmanabha 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1538be8acb27SKishore Padmanabha 	if (!flow_db) {
1539dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
1540be8acb27SKishore Padmanabha 		return -EINVAL;
1541be8acb27SKishore Padmanabha 	}
1542be8acb27SKishore Padmanabha 
1543ddaf0afaSKishore Padmanabha 	if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
1544dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow type\n");
1545be8acb27SKishore Padmanabha 		return -EINVAL;
1546be8acb27SKishore Padmanabha 	}
1547be8acb27SKishore Padmanabha 
1548be8acb27SKishore Padmanabha 	flow_tbl = &flow_db->flow_tbl;
1549be8acb27SKishore Padmanabha 	/* check for max flows */
1550be8acb27SKishore Padmanabha 	if (fid >= flow_tbl->num_flows || !fid) {
1551dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid flow index %x\n", fid);
1552be8acb27SKishore Padmanabha 		return -EINVAL;
1553be8acb27SKishore Padmanabha 	}
1554be8acb27SKishore Padmanabha 
1555be8acb27SKishore Padmanabha 	/* check if the flow is active or not */
1556be8acb27SKishore Padmanabha 	if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
1557dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "flow does not exist\n");
1558be8acb27SKishore Padmanabha 		return -EINVAL;
1559be8acb27SKishore Padmanabha 	}
1560be8acb27SKishore Padmanabha 
1561be8acb27SKishore Padmanabha 	/* Iterate the resource to get the resource handle */
1562be8acb27SKishore Padmanabha 	res_id =  fid;
1563be8acb27SKishore Padmanabha 	while (res_id) {
1564be8acb27SKishore Padmanabha 		fid_res = &flow_tbl->flow_resources[res_id];
1565be8acb27SKishore Padmanabha 		if (ulp_flow_db_resource_func_get(fid_res) ==
1566be8acb27SKishore Padmanabha 		    BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW) {
1567be8acb27SKishore Padmanabha 			/* invalidate the resource details */
1568be8acb27SKishore Padmanabha 			fid_res->resource_hndl = 0;
1569be8acb27SKishore Padmanabha 			return 0;
1570be8acb27SKishore Padmanabha 		}
1571be8acb27SKishore Padmanabha 		res_id = 0;
1572be8acb27SKishore Padmanabha 		ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
1573be8acb27SKishore Padmanabha 	}
1574be8acb27SKishore Padmanabha 	/* failed */
1575be8acb27SKishore Padmanabha 	return -1;
1576be8acb27SKishore Padmanabha }
1577be8acb27SKishore Padmanabha 
1578be8acb27SKishore Padmanabha /*
1579be8acb27SKishore Padmanabha  * Create parent flow in the parent flow tbl
1580be8acb27SKishore Padmanabha  *
1581be8acb27SKishore Padmanabha  * parms [in] Ptr to mapper params
1582be8acb27SKishore Padmanabha  *
1583be8acb27SKishore Padmanabha  * Returns 0 on success and negative on failure.
1584be8acb27SKishore Padmanabha  */
1585be8acb27SKishore Padmanabha int32_t
1586be8acb27SKishore Padmanabha ulp_flow_db_parent_flow_create(struct bnxt_ulp_mapper_parms *parms)
1587be8acb27SKishore Padmanabha {
1588be8acb27SKishore Padmanabha 	struct ulp_flow_db_res_params fid_parms;
1589bdf4a3c6SKishore Padmanabha 	uint32_t sub_typ = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT;
1590640bfd23SKishore Padmanabha 	struct ulp_flow_db_res_params res_params;
1591bdf4a3c6SKishore Padmanabha 	int32_t pc_idx;
1592be8acb27SKishore Padmanabha 
1593bdf4a3c6SKishore Padmanabha 	/* create or get the parent child database */
1594bdf4a3c6SKishore Padmanabha 	pc_idx = ulp_flow_db_pc_db_idx_alloc(parms->ulp_ctx, parms->tun_idx);
1595bdf4a3c6SKishore Padmanabha 	if (pc_idx < 0) {
1596dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Error in getting parent child db %x\n",
1597bdf4a3c6SKishore Padmanabha 			     parms->tun_idx);
1598bdf4a3c6SKishore Padmanabha 		return -EINVAL;
1599bdf4a3c6SKishore Padmanabha 	}
1600bdf4a3c6SKishore Padmanabha 
1601bdf4a3c6SKishore Padmanabha 	/* Update the parent fid */
1602bdf4a3c6SKishore Padmanabha 	if (ulp_flow_db_pc_db_parent_flow_set(parms->ulp_ctx, pc_idx,
1603dd0191d5SShuanglin Wang 					      parms->flow_id, 1)) {
1604dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Error in setting parent fid %x\n",
1605bdf4a3c6SKishore Padmanabha 			     parms->tun_idx);
1606bdf4a3c6SKishore Padmanabha 		return -EINVAL;
1607be8acb27SKishore Padmanabha 	}
1608be8acb27SKishore Padmanabha 
1609be8acb27SKishore Padmanabha 	/* Add the parent details in the resource list of the flow */
1610be8acb27SKishore Padmanabha 	memset(&fid_parms, 0, sizeof(fid_parms));
1611be8acb27SKishore Padmanabha 	fid_parms.resource_func	= BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW;
1612bdf4a3c6SKishore Padmanabha 	fid_parms.resource_hndl	= pc_idx;
1613be8acb27SKishore Padmanabha 	fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1614be8acb27SKishore Padmanabha 	if (ulp_flow_db_resource_add(parms->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
1615dd0191d5SShuanglin Wang 				     parms->flow_id, &fid_parms)) {
1616dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Error in adding flow res for flow id %x\n",
1617dd0191d5SShuanglin Wang 			     parms->flow_id);
1618be8acb27SKishore Padmanabha 		return -1;
1619be8acb27SKishore Padmanabha 	}
1620640bfd23SKishore Padmanabha 
1621640bfd23SKishore Padmanabha 	/* check of the flow has internal counter accumulation enabled */
1622640bfd23SKishore Padmanabha 	if (!ulp_flow_db_resource_params_get(parms->ulp_ctx,
1623640bfd23SKishore Padmanabha 					     BNXT_ULP_FDB_TYPE_REGULAR,
1624dd0191d5SShuanglin Wang 					     parms->flow_id,
1625640bfd23SKishore Padmanabha 					     BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
16269cbfa4cfSKishore Padmanabha 					     sub_typ,
1627640bfd23SKishore Padmanabha 					     &res_params)) {
1628640bfd23SKishore Padmanabha 		/* Enable the counter accumulation in parent entry */
1629640bfd23SKishore Padmanabha 		if (ulp_flow_db_parent_flow_count_accum_set(parms->ulp_ctx,
1630bdf4a3c6SKishore Padmanabha 							    pc_idx)) {
1631dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Error in setting counter acc %x\n",
1632dd0191d5SShuanglin Wang 				     parms->flow_id);
1633640bfd23SKishore Padmanabha 			return -1;
1634640bfd23SKishore Padmanabha 		}
1635640bfd23SKishore Padmanabha 	}
1636675e31d8SVenkat Duvvuru 
1637*a089734aSShuanglin Wang 	/* Set parent flow entry idx in stats cache entry */
1638*a089734aSShuanglin Wang 	ulp_sc_mgr_set_pc_idx(parms->ulp_ctx, parms->flow_id, pc_idx);
1639be8acb27SKishore Padmanabha 	return 0;
1640be8acb27SKishore Padmanabha }
1641be8acb27SKishore Padmanabha 
1642be8acb27SKishore Padmanabha /*
1643be8acb27SKishore Padmanabha  * Create child flow in the parent flow tbl
1644be8acb27SKishore Padmanabha  *
1645be8acb27SKishore Padmanabha  * parms [in] Ptr to mapper params
1646be8acb27SKishore Padmanabha  *
1647be8acb27SKishore Padmanabha  * Returns 0 on success and negative on failure.
1648be8acb27SKishore Padmanabha  */
1649be8acb27SKishore Padmanabha int32_t
1650be8acb27SKishore Padmanabha ulp_flow_db_child_flow_create(struct bnxt_ulp_mapper_parms *parms)
1651be8acb27SKishore Padmanabha {
1652be8acb27SKishore Padmanabha 	struct ulp_flow_db_res_params fid_parms;
16539cbfa4cfSKishore Padmanabha 	uint32_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT;
1654640bfd23SKishore Padmanabha 	enum bnxt_ulp_resource_func res_fun;
1655640bfd23SKishore Padmanabha 	struct ulp_flow_db_res_params res_p;
1656bdf4a3c6SKishore Padmanabha 	int32_t rc, pc_idx;
1657bdf4a3c6SKishore Padmanabha 
1658bdf4a3c6SKishore Padmanabha 	/* create or get the parent child database */
1659bdf4a3c6SKishore Padmanabha 	pc_idx = ulp_flow_db_pc_db_idx_alloc(parms->ulp_ctx, parms->tun_idx);
1660bdf4a3c6SKishore Padmanabha 	if (pc_idx < 0) {
1661dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Error in getting parent child db %x\n",
1662bdf4a3c6SKishore Padmanabha 			     parms->tun_idx);
1663bdf4a3c6SKishore Padmanabha 		return -1;
1664bdf4a3c6SKishore Padmanabha 	}
1665be8acb27SKishore Padmanabha 
1666be8acb27SKishore Padmanabha 	/* create the parent flow entry in parent flow table */
1667bdf4a3c6SKishore Padmanabha 	rc = ulp_flow_db_pc_db_child_flow_set(parms->ulp_ctx, pc_idx,
1668dd0191d5SShuanglin Wang 					      parms->flow_id, 1);
1669be8acb27SKishore Padmanabha 	if (rc) {
1670dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Error in setting child fid %x\n",
1671dd0191d5SShuanglin Wang 			     parms->flow_id);
1672640bfd23SKishore Padmanabha 		return rc;
1673be8acb27SKishore Padmanabha 	}
1674be8acb27SKishore Padmanabha 
1675be8acb27SKishore Padmanabha 	/* Add the parent details in the resource list of the flow */
1676be8acb27SKishore Padmanabha 	memset(&fid_parms, 0, sizeof(fid_parms));
1677be8acb27SKishore Padmanabha 	fid_parms.resource_func	= BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW;
1678bdf4a3c6SKishore Padmanabha 	fid_parms.resource_hndl	= pc_idx;
1679be8acb27SKishore Padmanabha 	fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1680640bfd23SKishore Padmanabha 	rc  = ulp_flow_db_resource_add(parms->ulp_ctx,
1681640bfd23SKishore Padmanabha 				       BNXT_ULP_FDB_TYPE_REGULAR,
1682dd0191d5SShuanglin Wang 				       parms->flow_id, &fid_parms);
1683640bfd23SKishore Padmanabha 	if (rc) {
1684dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Error in adding flow res for flow id %x\n",
1685dd0191d5SShuanglin Wang 			     parms->flow_id);
1686640bfd23SKishore Padmanabha 		return rc;
1687640bfd23SKishore Padmanabha 	}
1688640bfd23SKishore Padmanabha 
1689640bfd23SKishore Padmanabha 	/* check if internal count action included for this flow.*/
1690640bfd23SKishore Padmanabha 	res_fun = BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE;
1691640bfd23SKishore Padmanabha 	rc = ulp_flow_db_resource_params_get(parms->ulp_ctx,
1692640bfd23SKishore Padmanabha 					     BNXT_ULP_FDB_TYPE_REGULAR,
1693dd0191d5SShuanglin Wang 					     parms->flow_id,
1694640bfd23SKishore Padmanabha 					     res_fun,
1695640bfd23SKishore Padmanabha 					     sub_type,
1696640bfd23SKishore Padmanabha 					     &res_p);
1697640bfd23SKishore Padmanabha 	if (!rc) {
1698640bfd23SKishore Padmanabha 		/* update the counter manager to include parent fid */
1699640bfd23SKishore Padmanabha 		if (ulp_fc_mgr_cntr_parent_flow_set(parms->ulp_ctx,
1700640bfd23SKishore Padmanabha 						    res_p.direction,
1701640bfd23SKishore Padmanabha 						    res_p.resource_hndl,
1702bdf4a3c6SKishore Padmanabha 						    pc_idx)) {
1703dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Error in setting child %x\n",
1704dd0191d5SShuanglin Wang 				     parms->flow_id);
1705be8acb27SKishore Padmanabha 			return -1;
1706be8acb27SKishore Padmanabha 		}
1707640bfd23SKishore Padmanabha 	}
1708bdf4a3c6SKishore Padmanabha 
1709640bfd23SKishore Padmanabha 	/* return success */
1710be8acb27SKishore Padmanabha 	return 0;
1711be8acb27SKishore Padmanabha }
1712640bfd23SKishore Padmanabha 
1713640bfd23SKishore Padmanabha /*
1714640bfd23SKishore Padmanabha  * Update the parent counters
1715640bfd23SKishore Padmanabha  *
1716640bfd23SKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp_context
1717bdf4a3c6SKishore Padmanabha  * pc_idx [in] The parent flow entry idx
1718640bfd23SKishore Padmanabha  * packet_count [in] - packet count
1719640bfd23SKishore Padmanabha  * byte_count [in] - byte count
1720640bfd23SKishore Padmanabha  *
1721640bfd23SKishore Padmanabha  * returns 0 on success
1722640bfd23SKishore Padmanabha  */
1723640bfd23SKishore Padmanabha int32_t
1724640bfd23SKishore Padmanabha ulp_flow_db_parent_flow_count_update(struct bnxt_ulp_context *ulp_ctxt,
1725bdf4a3c6SKishore Padmanabha 				     uint32_t pc_idx,
1726640bfd23SKishore Padmanabha 				     uint64_t packet_count,
1727640bfd23SKishore Padmanabha 				     uint64_t byte_count)
1728640bfd23SKishore Padmanabha {
1729bdf4a3c6SKishore Padmanabha 	struct ulp_fdb_parent_info *pc_entry;
1730640bfd23SKishore Padmanabha 
1731bdf4a3c6SKishore Padmanabha 	/* validate the arguments and get parent child entry */
1732bdf4a3c6SKishore Padmanabha 	pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx);
1733bdf4a3c6SKishore Padmanabha 	if (!pc_entry) {
1734dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "failed to get the parent child entry\n");
1735640bfd23SKishore Padmanabha 		return -EINVAL;
1736640bfd23SKishore Padmanabha 	}
1737640bfd23SKishore Padmanabha 
1738bdf4a3c6SKishore Padmanabha 	if (pc_entry->counter_acc) {
1739bdf4a3c6SKishore Padmanabha 		pc_entry->pkt_count += packet_count;
1740bdf4a3c6SKishore Padmanabha 		pc_entry->byte_count += byte_count;
1741640bfd23SKishore Padmanabha 	}
1742640bfd23SKishore Padmanabha 	return 0;
1743640bfd23SKishore Padmanabha }
1744640bfd23SKishore Padmanabha 
1745640bfd23SKishore Padmanabha /*
1746640bfd23SKishore Padmanabha  * Get the parent accumulation counters
1747640bfd23SKishore Padmanabha  *
1748640bfd23SKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp_context
1749bdf4a3c6SKishore Padmanabha  * pc_idx [in] The parent flow entry idx
1750640bfd23SKishore Padmanabha  * packet_count [out] - packet count
1751640bfd23SKishore Padmanabha  * byte_count [out] - byte count
1752640bfd23SKishore Padmanabha  *
1753640bfd23SKishore Padmanabha  * returns 0 on success
1754640bfd23SKishore Padmanabha  */
1755640bfd23SKishore Padmanabha int32_t
1756640bfd23SKishore Padmanabha ulp_flow_db_parent_flow_count_get(struct bnxt_ulp_context *ulp_ctxt,
17578782e4deSKishore Padmanabha 				  uint32_t flow_id,
1758bdf4a3c6SKishore Padmanabha 				  uint32_t pc_idx, uint64_t *packet_count,
1759ddaf0afaSKishore Padmanabha 				  uint64_t *byte_count, uint8_t count_reset)
1760640bfd23SKishore Padmanabha {
1761bdf4a3c6SKishore Padmanabha 	struct ulp_fdb_parent_info *pc_entry;
1762640bfd23SKishore Padmanabha 
1763bdf4a3c6SKishore Padmanabha 	/* validate the arguments and get parent child entry */
1764bdf4a3c6SKishore Padmanabha 	pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx);
1765bdf4a3c6SKishore Padmanabha 	if (!pc_entry) {
1766dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "failed to get the parent child entry\n");
1767640bfd23SKishore Padmanabha 		return -EINVAL;
1768640bfd23SKishore Padmanabha 	}
1769640bfd23SKishore Padmanabha 
17708782e4deSKishore Padmanabha 	/* stale parent fid */
17718782e4deSKishore Padmanabha 	if (flow_id != pc_entry->parent_fid) {
17728782e4deSKishore Padmanabha 		*packet_count = 0;
17738782e4deSKishore Padmanabha 		*byte_count = 0;
17748782e4deSKishore Padmanabha 		return 0;
17758782e4deSKishore Padmanabha 	}
17768782e4deSKishore Padmanabha 
1777bdf4a3c6SKishore Padmanabha 	if (pc_entry->counter_acc) {
1778bdf4a3c6SKishore Padmanabha 		*packet_count = pc_entry->pkt_count;
1779bdf4a3c6SKishore Padmanabha 		*byte_count = pc_entry->byte_count;
1780ddaf0afaSKishore Padmanabha 		if (count_reset) {
1781bdf4a3c6SKishore Padmanabha 			pc_entry->pkt_count = 0;
1782bdf4a3c6SKishore Padmanabha 			pc_entry->byte_count = 0;
1783ddaf0afaSKishore Padmanabha 		}
1784640bfd23SKishore Padmanabha 	}
1785640bfd23SKishore Padmanabha 	return 0;
1786640bfd23SKishore Padmanabha }
1787640bfd23SKishore Padmanabha 
1788640bfd23SKishore Padmanabha /*
1789640bfd23SKishore Padmanabha  * reset the parent accumulation counters
1790640bfd23SKishore Padmanabha  *
1791640bfd23SKishore Padmanabha  * ulp_ctxt [in] Ptr to ulp_context
1792640bfd23SKishore Padmanabha  *
1793640bfd23SKishore Padmanabha  * returns none
1794640bfd23SKishore Padmanabha  */
1795640bfd23SKishore Padmanabha void
1796640bfd23SKishore Padmanabha ulp_flow_db_parent_flow_count_reset(struct bnxt_ulp_context *ulp_ctxt)
1797640bfd23SKishore Padmanabha {
1798640bfd23SKishore Padmanabha 	struct bnxt_ulp_flow_db *flow_db;
1799640bfd23SKishore Padmanabha 	struct ulp_fdb_parent_child_db *p_pdb;
1800640bfd23SKishore Padmanabha 	uint32_t idx;
1801640bfd23SKishore Padmanabha 
1802640bfd23SKishore Padmanabha 	/* validate the arguments */
1803bdf4a3c6SKishore Padmanabha 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1804640bfd23SKishore Padmanabha 	if (!flow_db) {
1805dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "parent child db validation failed\n");
1806640bfd23SKishore Padmanabha 		return;
1807640bfd23SKishore Padmanabha 	}
1808640bfd23SKishore Padmanabha 
1809640bfd23SKishore Padmanabha 	p_pdb = &flow_db->parent_child_db;
1810640bfd23SKishore Padmanabha 	for (idx = 0; idx < p_pdb->entries_count; idx++) {
1811bdf4a3c6SKishore Padmanabha 		if (p_pdb->parent_flow_tbl[idx].valid &&
1812640bfd23SKishore Padmanabha 		    p_pdb->parent_flow_tbl[idx].counter_acc) {
1813640bfd23SKishore Padmanabha 			p_pdb->parent_flow_tbl[idx].pkt_count = 0;
1814640bfd23SKishore Padmanabha 			p_pdb->parent_flow_tbl[idx].byte_count = 0;
1815640bfd23SKishore Padmanabha 		}
1816640bfd23SKishore Padmanabha 	}
1817640bfd23SKishore Padmanabha }
181819994cc7SKishore Padmanabha 
181919994cc7SKishore Padmanabha /*
182019994cc7SKishore Padmanabha  * Set the shared bit for the flow db entry
182119994cc7SKishore Padmanabha  *
182219994cc7SKishore Padmanabha  * res [in] Ptr to fdb entry
182319994cc7SKishore Padmanabha  * shared [in] shared flag
182419994cc7SKishore Padmanabha  *
182519994cc7SKishore Padmanabha  * returns none
182619994cc7SKishore Padmanabha  */
182719994cc7SKishore Padmanabha void ulp_flow_db_shared_session_set(struct ulp_flow_db_res_params *res,
1828d9e70b1dSRandy Schacher 				    enum bnxt_ulp_session_type s_type)
182919994cc7SKishore Padmanabha {
1830d9e70b1dSRandy Schacher 	if (res && (s_type & BNXT_ULP_SESSION_TYPE_SHARED))
183119994cc7SKishore Padmanabha 		res->fdb_flags |= ULP_FDB_FLAG_SHARED_SESSION;
1832d9e70b1dSRandy Schacher 	else if (res && (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC))
1833d9e70b1dSRandy Schacher 		res->fdb_flags |= ULP_FDB_FLAG_SHARED_WC_SESSION;
1834d9e70b1dSRandy Schacher }
1835d9e70b1dSRandy Schacher 
1836d9e70b1dSRandy Schacher /*
1837dd0191d5SShuanglin Wang  * get the shared bit for the flow db entry
1838d9e70b1dSRandy Schacher  *
1839dd0191d5SShuanglin Wang  * res [in] Ptr to fdb entry
1840dd0191d5SShuanglin Wang  *
1841dd0191d5SShuanglin Wang  * returns session type
1842d9e70b1dSRandy Schacher  */
1843d9e70b1dSRandy Schacher enum bnxt_ulp_session_type
1844d9e70b1dSRandy Schacher ulp_flow_db_shared_session_get(struct ulp_flow_db_res_params *res)
1845d9e70b1dSRandy Schacher {
1846d9e70b1dSRandy Schacher 	enum bnxt_ulp_session_type stype = BNXT_ULP_SESSION_TYPE_DEFAULT;
1847d9e70b1dSRandy Schacher 
1848d9e70b1dSRandy Schacher 	if (res && (res->fdb_flags & ULP_FDB_FLAG_SHARED_SESSION))
1849d9e70b1dSRandy Schacher 		stype = BNXT_ULP_SESSION_TYPE_SHARED;
1850d9e70b1dSRandy Schacher 	else if (res && (res->fdb_flags & ULP_FDB_FLAG_SHARED_WC_SESSION))
1851d9e70b1dSRandy Schacher 		stype = BNXT_ULP_SESSION_TYPE_SHARED_WC;
1852d9e70b1dSRandy Schacher 
1853d9e70b1dSRandy Schacher 	return stype;
185419994cc7SKishore Padmanabha }
1855