xref: /dpdk/drivers/net/bnxt/tf_ulp/bnxt_ulp.c (revision a2417601)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2021 Broadcom
3  * All rights reserved.
4  */
5 
6 #include <rte_log.h>
7 #include <rte_malloc.h>
8 #include <rte_flow.h>
9 #include <rte_flow_driver.h>
10 #include <rte_tailq.h>
11 
12 #include "bnxt.h"
13 #include "bnxt_ulp.h"
14 #include "bnxt_tf_common.h"
15 #include "tf_core.h"
16 #include "tf_ext_flow_handle.h"
17 
18 #include "ulp_template_db_enum.h"
19 #include "ulp_template_struct.h"
20 #include "ulp_mark_mgr.h"
21 #include "ulp_fc_mgr.h"
22 #include "ulp_flow_db.h"
23 #include "ulp_mapper.h"
24 #include "ulp_port_db.h"
25 
26 /* Linked list of all TF sessions. */
27 STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
28 			STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
29 
30 /* Mutex to synchronize bnxt_ulp_session_list operations. */
31 static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
32 
33 /*
34  * Allow the deletion of context only for the bnxt device that
35  * created the session.
36  */
37 bool
38 ulp_ctx_deinit_allowed(struct bnxt_ulp_context *ulp_ctx)
39 {
40 	if (!ulp_ctx || !ulp_ctx->cfg_data)
41 		return false;
42 
43 	if (!ulp_ctx->cfg_data->ref_cnt) {
44 		BNXT_TF_DBG(DEBUG, "ulp ctx shall initiate deinit\n");
45 		return true;
46 	}
47 
48 	return false;
49 }
50 
51 static int32_t
52 bnxt_ulp_devid_get(struct bnxt *bp,
53 		   enum bnxt_ulp_device_id  *ulp_dev_id)
54 {
55 	if (BNXT_CHIP_P5(bp))
56 		return -EINVAL;
57 
58 	if (BNXT_STINGRAY(bp))
59 		*ulp_dev_id = BNXT_ULP_DEVICE_ID_STINGRAY;
60 	else
61 		/* Assuming Whitney */
62 		*ulp_dev_id = BNXT_ULP_DEVICE_ID_WH_PLUS;
63 
64 	return 0;
65 }
66 
67 static int32_t
68 bnxt_ulp_tf_session_resources_get(struct bnxt *bp,
69 				  struct tf_session_resources *res)
70 {
71 	uint32_t dev_id;
72 	int32_t rc;
73 
74 	rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id);
75 	if (rc) {
76 		BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n");
77 		return -EINVAL;
78 	}
79 
80 	switch (dev_id) {
81 	case BNXT_ULP_DEVICE_ID_WH_PLUS:
82 		/** RX **/
83 		/* Identifiers */
84 		res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT_HIGH] = 422;
85 		res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT_LOW] = 6;
86 		res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_WC_PROF] = 192;
87 		res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 64;
88 		res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_EM_PROF] = 192;
89 
90 		/* Table Types */
91 		res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 8192;
92 		res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 16384;
93 		res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_MODIFY_IPV4] = 1023;
94 
95 		/* ENCAP */
96 		res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_ENCAP_8B] = 511;
97 		res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_ENCAP_16B] = 63;
98 
99 		/* TCAMs */
100 		res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] =
101 			422;
102 		res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] =
103 			6;
104 		res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 960;
105 		res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 88;
106 
107 		/* EM */
108 		res->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 13168;
109 
110 		/* EEM */
111 		res->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1;
112 
113 		/* SP */
114 		res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_SP_SMAC] = 255;
115 
116 		/** TX **/
117 		/* Identifiers */
118 		res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT_HIGH] = 292;
119 		res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT_LOW] = 148;
120 		res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_WC_PROF] = 192;
121 		res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 64;
122 		res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_EM_PROF] = 192;
123 
124 		/* Table Types */
125 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 8192;
126 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 16384;
127 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_MODIFY_IPV4] = 1023;
128 
129 		/* ENCAP */
130 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_64B] = 511;
131 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_16B] = 223;
132 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_8B] = 255;
133 
134 		/* TCAMs */
135 		res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] =
136 			292;
137 		res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] =
138 			144;
139 		res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 960;
140 		res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 928;
141 
142 		/* EM */
143 		res->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 15232;
144 
145 		/* EEM */
146 		res->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1;
147 
148 		/* SP */
149 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV4] = 488;
150 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV6] = 511;
151 		break;
152 	case BNXT_ULP_DEVICE_ID_STINGRAY:
153 		/** RX **/
154 		/* Identifiers */
155 		res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT_HIGH] = 315;
156 		res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT_LOW] = 6;
157 		res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_WC_PROF] = 192;
158 		res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 64;
159 		res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_EM_PROF] = 192;
160 
161 		/* Table Types */
162 		res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 8192;
163 		res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 16384;
164 		res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_MODIFY_IPV4] = 1023;
165 
166 		/* ENCAP */
167 		res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_ENCAP_8B] = 511;
168 		res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_ENCAP_16B] = 63;
169 
170 		/* TCAMs */
171 		res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] =
172 			315;
173 		res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] =
174 			6;
175 		res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 960;
176 		res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 112;
177 
178 		/* EM */
179 		res->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 13200;
180 
181 		/* EEM */
182 		res->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1;
183 
184 		/* SP */
185 		res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_SP_SMAC] = 256;
186 
187 		/** TX **/
188 		/* Identifiers */
189 		res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT_HIGH] = 292;
190 		res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT_LOW] = 127;
191 		res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_WC_PROF] = 192;
192 		res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 64;
193 		res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_EM_PROF] = 192;
194 
195 		/* Table Types */
196 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 8192;
197 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 16384;
198 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_MODIFY_IPV4] = 1023;
199 
200 		/* ENCAP */
201 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_64B] = 367;
202 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_16B] = 223;
203 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_8B] = 255;
204 
205 		/* TCAMs */
206 		res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] =
207 			292;
208 		res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] =
209 			127;
210 		res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 960;
211 		res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 928;
212 
213 		/* EM */
214 		res->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 15232;
215 
216 		/* EEM */
217 		res->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1;
218 
219 		/* SP */
220 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV4] = 488;
221 		res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV6] = 512;
222 		break;
223 	default:
224 		return -EINVAL;
225 	}
226 
227 	return 0;
228 }
229 
230 /*
231  * Initialize an ULP session.
232  * An ULP session will contain all the resources needed to support rte flow
233  * offloads. A session is initialized as part of rte_eth_device start.
234  * A single vswitch instance can have multiple uplinks which means
235  * rte_eth_device start will be called for each of these devices.
236  * ULP session manager will make sure that a single ULP session is only
237  * initialized once. Apart from this, it also initializes MARK database,
238  * EEM table & flow database. ULP session manager also manages a list of
239  * all opened ULP sessions.
240  */
241 static int32_t
242 ulp_ctx_session_open(struct bnxt *bp,
243 		     struct bnxt_ulp_session_state *session)
244 {
245 	struct rte_eth_dev		*ethdev = bp->eth_dev;
246 	int32_t				rc = 0;
247 	struct tf_open_session_parms	params;
248 	struct tf_session_resources	*resources;
249 	uint32_t			ulp_dev_id;
250 
251 	memset(&params, 0, sizeof(params));
252 
253 	rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id,
254 					  params.ctrl_chan_name);
255 	if (rc) {
256 		BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n",
257 			    ethdev->data->port_id, rc);
258 		return rc;
259 	}
260 
261 	params.shadow_copy = true;
262 
263 	rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id);
264 	if (rc) {
265 		BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n");
266 		return rc;
267 	}
268 
269 	switch (ulp_dev_id) {
270 	case BNXT_ULP_DEVICE_ID_WH_PLUS:
271 		params.device_type = TF_DEVICE_TYPE_WH;
272 		break;
273 	case BNXT_ULP_DEVICE_ID_STINGRAY:
274 		params.device_type = TF_DEVICE_TYPE_SR;
275 		break;
276 	default:
277 		BNXT_TF_DBG(ERR, "Unable to determine device for "
278 			    "opening session.\n");
279 		return rc;
280 	}
281 
282 	resources = &params.resources;
283 	rc = bnxt_ulp_tf_session_resources_get(bp, resources);
284 	if (rc) {
285 		BNXT_TF_DBG(ERR, "Unable to determine tf resources for "
286 			    "session open.\n");
287 		return rc;
288 	}
289 
290 	rc = tf_open_session(&bp->tfp, &params);
291 	if (rc) {
292 		BNXT_TF_DBG(ERR, "Failed to open TF session - %s, rc = %d\n",
293 			    params.ctrl_chan_name, rc);
294 		return -EINVAL;
295 	}
296 	if (!session->session_opened) {
297 		session->session_opened = 1;
298 		session->g_tfp = rte_zmalloc("bnxt_ulp_session_tfp",
299 					     sizeof(struct tf), 0);
300 		session->g_tfp->session = bp->tfp.session;
301 	}
302 	return rc;
303 }
304 
305 /*
306  * Close the ULP session.
307  * It takes the ulp context pointer.
308  */
309 static void
310 ulp_ctx_session_close(struct bnxt *bp,
311 		      struct bnxt_ulp_session_state *session)
312 {
313 	/* close the session in the hardware */
314 	if (session->session_opened)
315 		tf_close_session(&bp->tfp);
316 	session->session_opened = 0;
317 	rte_free(session->g_tfp);
318 	session->g_tfp = NULL;
319 }
320 
321 static void
322 bnxt_init_tbl_scope_parms(struct bnxt *bp,
323 			  struct tf_alloc_tbl_scope_parms *params)
324 {
325 	struct bnxt_ulp_device_params	*dparms;
326 	uint32_t dev_id;
327 	int rc;
328 
329 	rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id);
330 	if (rc)
331 		/* TBD: For now, just use default. */
332 		dparms = 0;
333 	else
334 		dparms = bnxt_ulp_device_params_get(dev_id);
335 
336 	/*
337 	 * Set the flush timer for EEM entries. The value is in 100ms intervals,
338 	 * so 100 is 10s.
339 	 */
340 	params->hw_flow_cache_flush_timer = 100;
341 
342 	if (!dparms) {
343 		params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY;
344 		params->rx_max_action_entry_sz_in_bits =
345 			BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY;
346 		params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM;
347 		params->rx_num_flows_in_k = BNXT_ULP_RX_NUM_FLOWS;
348 		params->rx_tbl_if_id = BNXT_ULP_RX_TBL_IF_ID;
349 
350 		params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY;
351 		params->tx_max_action_entry_sz_in_bits =
352 			BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY;
353 		params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM;
354 		params->tx_num_flows_in_k = BNXT_ULP_TX_NUM_FLOWS;
355 		params->tx_tbl_if_id = BNXT_ULP_TX_TBL_IF_ID;
356 	} else {
357 		params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY;
358 		params->rx_max_action_entry_sz_in_bits =
359 			BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY;
360 		params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM;
361 		params->rx_num_flows_in_k =
362 			dparms->ext_flow_db_num_entries / 1024;
363 		params->rx_tbl_if_id = BNXT_ULP_RX_TBL_IF_ID;
364 
365 		params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY;
366 		params->tx_max_action_entry_sz_in_bits =
367 			BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY;
368 		params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM;
369 		params->tx_num_flows_in_k =
370 			dparms->ext_flow_db_num_entries / 1024;
371 		params->tx_tbl_if_id = BNXT_ULP_TX_TBL_IF_ID;
372 	}
373 	BNXT_TF_DBG(INFO, "Table Scope initialized with %uK flows.\n",
374 		    params->rx_num_flows_in_k);
375 }
376 
377 /* Initialize Extended Exact Match host memory. */
378 static int32_t
379 ulp_eem_tbl_scope_init(struct bnxt *bp)
380 {
381 	struct tf_alloc_tbl_scope_parms params = {0};
382 	struct bnxt_ulp_device_params *dparms;
383 	enum bnxt_ulp_flow_mem_type mtype;
384 	uint32_t dev_id;
385 	int rc;
386 
387 	/* Get the dev specific number of flows that needed to be supported. */
388 	if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) {
389 		BNXT_TF_DBG(ERR, "Invalid device id\n");
390 		return -EINVAL;
391 	}
392 
393 	dparms = bnxt_ulp_device_params_get(dev_id);
394 	if (!dparms) {
395 		BNXT_TF_DBG(ERR, "could not fetch the device params\n");
396 		return -ENODEV;
397 	}
398 
399 	if (bnxt_ulp_cntxt_mem_type_get(bp->ulp_ctx, &mtype))
400 		return -EINVAL;
401 	if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) {
402 		BNXT_TF_DBG(INFO, "Table Scope alloc is not required\n");
403 		return 0;
404 	}
405 
406 	bnxt_init_tbl_scope_parms(bp, &params);
407 	rc = tf_alloc_tbl_scope(&bp->tfp, &params);
408 	if (rc) {
409 		BNXT_TF_DBG(ERR, "Unable to allocate eem table scope rc = %d\n",
410 			    rc);
411 		return rc;
412 	}
413 	rc = bnxt_ulp_cntxt_tbl_scope_id_set(bp->ulp_ctx, params.tbl_scope_id);
414 	if (rc) {
415 		BNXT_TF_DBG(ERR, "Unable to set table scope id\n");
416 		return rc;
417 	}
418 
419 	return 0;
420 }
421 
422 /* Free Extended Exact Match host memory */
423 static int32_t
424 ulp_eem_tbl_scope_deinit(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx)
425 {
426 	struct tf_free_tbl_scope_parms	params = {0};
427 	struct tf			*tfp;
428 	int32_t				rc = 0;
429 	struct bnxt_ulp_device_params *dparms;
430 	enum bnxt_ulp_flow_mem_type mtype;
431 	uint32_t dev_id;
432 
433 	if (!ulp_ctx || !ulp_ctx->cfg_data)
434 		return -EINVAL;
435 
436 	tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
437 	if (!tfp) {
438 		BNXT_TF_DBG(ERR, "Failed to get the truflow pointer\n");
439 		return -EINVAL;
440 	}
441 
442 	/* Get the dev specific number of flows that needed to be supported. */
443 	if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) {
444 		BNXT_TF_DBG(ERR, "Invalid device id\n");
445 		return -EINVAL;
446 	}
447 
448 	dparms = bnxt_ulp_device_params_get(dev_id);
449 	if (!dparms) {
450 		BNXT_TF_DBG(ERR, "could not fetch the device params\n");
451 		return -ENODEV;
452 	}
453 
454 	if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype))
455 		return -EINVAL;
456 	if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) {
457 		BNXT_TF_DBG(INFO, "Table Scope free is not required\n");
458 		return 0;
459 	}
460 
461 	rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &params.tbl_scope_id);
462 	if (rc) {
463 		BNXT_TF_DBG(ERR, "Failed to get the table scope id\n");
464 		return -EINVAL;
465 	}
466 
467 	rc = tf_free_tbl_scope(tfp, &params);
468 	if (rc) {
469 		BNXT_TF_DBG(ERR, "Unable to free table scope\n");
470 		return -EINVAL;
471 	}
472 	return rc;
473 }
474 
475 /* The function to free and deinit the ulp context data. */
476 static int32_t
477 ulp_ctx_deinit(struct bnxt *bp,
478 	       struct bnxt_ulp_session_state *session)
479 {
480 	/* close the tf session */
481 	ulp_ctx_session_close(bp, session);
482 
483 	/* Free the contents */
484 	if (session->cfg_data) {
485 		rte_free(session->cfg_data);
486 		bp->ulp_ctx->cfg_data = NULL;
487 		session->cfg_data = NULL;
488 	}
489 	return 0;
490 }
491 
492 /* The function to allocate and initialize the ulp context data. */
493 static int32_t
494 ulp_ctx_init(struct bnxt *bp,
495 	     struct bnxt_ulp_session_state *session)
496 {
497 	struct bnxt_ulp_data	*ulp_data;
498 	int32_t			rc = 0;
499 	enum bnxt_ulp_device_id devid;
500 
501 	/* Allocate memory to hold ulp context data. */
502 	ulp_data = rte_zmalloc("bnxt_ulp_data",
503 			       sizeof(struct bnxt_ulp_data), 0);
504 	if (!ulp_data) {
505 		BNXT_TF_DBG(ERR, "Failed to allocate memory for ulp data\n");
506 		return -ENOMEM;
507 	}
508 
509 	/* Increment the ulp context data reference count usage. */
510 	bp->ulp_ctx->cfg_data = ulp_data;
511 	session->cfg_data = ulp_data;
512 	ulp_data->ref_cnt++;
513 	ulp_data->ulp_flags |= BNXT_ULP_VF_REP_ENABLED;
514 
515 	rc = bnxt_ulp_devid_get(bp, &devid);
516 	if (rc) {
517 		BNXT_TF_DBG(ERR, "Unable to determine device for ULP init.\n");
518 		goto error_deinit;
519 	}
520 
521 	rc = bnxt_ulp_cntxt_dev_id_set(bp->ulp_ctx, devid);
522 	if (rc) {
523 		BNXT_TF_DBG(ERR, "Unable to set device for ULP init.\n");
524 		goto error_deinit;
525 	}
526 
527 	/* Open the ulp session. */
528 	rc = ulp_ctx_session_open(bp, session);
529 	if (rc)
530 		goto error_deinit;
531 
532 	bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, &bp->tfp);
533 	return rc;
534 
535 error_deinit:
536 	session->session_opened = 1;
537 	(void)ulp_ctx_deinit(bp, session);
538 	return rc;
539 }
540 
541 /* The function to initialize ulp dparms with devargs */
542 static int32_t
543 ulp_dparms_init(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx)
544 {
545 	struct bnxt_ulp_device_params *dparms;
546 	uint32_t dev_id;
547 
548 	if (!bp->max_num_kflows) {
549 		/* Defaults to Internal */
550 		bnxt_ulp_cntxt_mem_type_set(ulp_ctx,
551 					    BNXT_ULP_FLOW_MEM_TYPE_INT);
552 		return 0;
553 	}
554 
555 	/* The max_num_kflows were set, so move to external */
556 	if (bnxt_ulp_cntxt_mem_type_set(ulp_ctx, BNXT_ULP_FLOW_MEM_TYPE_EXT))
557 		return -EINVAL;
558 
559 	if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
560 		BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
561 		return -EINVAL;
562 	}
563 
564 	dparms = bnxt_ulp_device_params_get(dev_id);
565 	if (!dparms) {
566 		BNXT_TF_DBG(DEBUG, "Failed to get device parms\n");
567 		return -EINVAL;
568 	}
569 
570 	/* num_flows = max_num_kflows * 1024 */
571 	dparms->ext_flow_db_num_entries = bp->max_num_kflows * 1024;
572 	/* GFID =  2 * num_flows */
573 	dparms->mark_db_gfid_entries = dparms->ext_flow_db_num_entries * 2;
574 	BNXT_TF_DBG(DEBUG, "Set the number of flows = %"PRIu64"\n",
575 		    dparms->ext_flow_db_num_entries);
576 
577 	return 0;
578 }
579 
580 /* The function to initialize bp flags with truflow features */
581 static int32_t
582 ulp_dparms_dev_port_intf_update(struct bnxt *bp,
583 				struct bnxt_ulp_context *ulp_ctx)
584 {
585 	enum bnxt_ulp_flow_mem_type mtype;
586 
587 	if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype))
588 		return -EINVAL;
589 	/* Update the bp flag with gfid flag */
590 	if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT)
591 		bp->flags |= BNXT_FLAG_GFID_ENABLE;
592 
593 	return 0;
594 }
595 
596 static int32_t
597 ulp_ctx_attach(struct bnxt *bp,
598 	       struct bnxt_ulp_session_state *session)
599 {
600 	int32_t rc = 0;
601 
602 	/* Increment the ulp context data reference count usage. */
603 	bp->ulp_ctx->cfg_data = session->cfg_data;
604 	bp->ulp_ctx->cfg_data->ref_cnt++;
605 
606 	/* update the session details in bnxt tfp */
607 	bp->tfp.session = session->g_tfp->session;
608 
609 	/* Create a TF Client */
610 	rc = ulp_ctx_session_open(bp, session);
611 	if (rc) {
612 		PMD_DRV_LOG(ERR, "Failed to open ctxt session, rc:%d\n", rc);
613 		bp->tfp.session = NULL;
614 		return rc;
615 	}
616 
617 	bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, &bp->tfp);
618 	return rc;
619 }
620 
621 static void
622 ulp_ctx_detach(struct bnxt *bp)
623 {
624 	if (bp->tfp.session) {
625 		tf_close_session(&bp->tfp);
626 		bp->tfp.session = NULL;
627 	}
628 }
629 
630 /*
631  * Initialize the state of an ULP session.
632  * If the state of an ULP session is not initialized, set it's state to
633  * initialized. If the state is already initialized, do nothing.
634  */
635 static void
636 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
637 {
638 	pthread_mutex_lock(&session->bnxt_ulp_mutex);
639 
640 	if (!session->bnxt_ulp_init) {
641 		session->bnxt_ulp_init = true;
642 		*init = false;
643 	} else {
644 		*init = true;
645 	}
646 
647 	pthread_mutex_unlock(&session->bnxt_ulp_mutex);
648 }
649 
650 /*
651  * Check if an ULP session is already allocated for a specific PCI
652  * domain & bus. If it is already allocated simply return the session
653  * pointer, otherwise allocate a new session.
654  */
655 static struct bnxt_ulp_session_state *
656 ulp_get_session(struct rte_pci_addr *pci_addr)
657 {
658 	struct bnxt_ulp_session_state *session;
659 
660 	STAILQ_FOREACH(session, &bnxt_ulp_session_list, next) {
661 		if (session->pci_info.domain == pci_addr->domain &&
662 		    session->pci_info.bus == pci_addr->bus) {
663 			return session;
664 		}
665 	}
666 	return NULL;
667 }
668 
669 /*
670  * Allocate and Initialize an ULP session and set it's state to INITIALIZED.
671  * If it's already initialized simply return the already existing session.
672  */
673 static struct bnxt_ulp_session_state *
674 ulp_session_init(struct bnxt *bp,
675 		 bool *init)
676 {
677 	struct rte_pci_device		*pci_dev;
678 	struct rte_pci_addr		*pci_addr;
679 	struct bnxt_ulp_session_state	*session;
680 	int rc = 0;
681 
682 	if (!bp)
683 		return NULL;
684 
685 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
686 	pci_addr = &pci_dev->addr;
687 
688 	pthread_mutex_lock(&bnxt_ulp_global_mutex);
689 
690 	session = ulp_get_session(pci_addr);
691 	if (!session) {
692 		/* Not Found the session  Allocate a new one */
693 		session = rte_zmalloc("bnxt_ulp_session",
694 				      sizeof(struct bnxt_ulp_session_state),
695 				      0);
696 		if (!session) {
697 			BNXT_TF_DBG(ERR,
698 				    "Allocation failed for bnxt_ulp_session\n");
699 			pthread_mutex_unlock(&bnxt_ulp_global_mutex);
700 			return NULL;
701 
702 		} else {
703 			/* Add it to the queue */
704 			session->pci_info.domain = pci_addr->domain;
705 			session->pci_info.bus = pci_addr->bus;
706 			rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
707 			if (rc) {
708 				BNXT_TF_DBG(ERR, "mutex create failed\n");
709 				pthread_mutex_unlock(&bnxt_ulp_global_mutex);
710 				return NULL;
711 			}
712 			STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
713 					   session, next);
714 		}
715 	}
716 	ulp_context_initialized(session, init);
717 	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
718 	return session;
719 }
720 
721 /*
722  * When a device is closed, remove it's associated session from the global
723  * session list.
724  */
725 static void
726 ulp_session_deinit(struct bnxt_ulp_session_state *session)
727 {
728 	if (!session)
729 		return;
730 
731 	if (!session->cfg_data) {
732 		pthread_mutex_lock(&bnxt_ulp_global_mutex);
733 		STAILQ_REMOVE(&bnxt_ulp_session_list, session,
734 			      bnxt_ulp_session_state, next);
735 		pthread_mutex_destroy(&session->bnxt_ulp_mutex);
736 		rte_free(session);
737 		pthread_mutex_unlock(&bnxt_ulp_global_mutex);
738 	}
739 }
740 
741 /*
742  * Internal api to enable NAT feature.
743  * Set set_flag to 1 to set the value or zero to reset the value.
744  * returns 0 on success.
745  */
746 static int32_t
747 bnxt_ulp_global_cfg_update(struct bnxt *bp,
748 			   enum tf_dir dir,
749 			   enum tf_global_config_type type,
750 			   uint32_t offset,
751 			   uint32_t value,
752 			   uint32_t set_flag)
753 {
754 	uint32_t global_cfg = 0;
755 	int rc;
756 	struct tf_global_cfg_parms parms = { 0 };
757 
758 	/* Initialize the params */
759 	parms.dir = dir,
760 	parms.type = type,
761 	parms.offset = offset,
762 	parms.config = (uint8_t *)&global_cfg,
763 	parms.config_sz_in_bytes = sizeof(global_cfg);
764 
765 	rc = tf_get_global_cfg(&bp->tfp, &parms);
766 	if (rc) {
767 		BNXT_TF_DBG(ERR, "Failed to get global cfg 0x%x rc:%d\n",
768 			    type, rc);
769 		return rc;
770 	}
771 
772 	if (set_flag)
773 		global_cfg |= value;
774 	else
775 		global_cfg &= ~value;
776 
777 	/* SET the register RE_CFA_REG_ACT_TECT */
778 	rc = tf_set_global_cfg(&bp->tfp, &parms);
779 	if (rc) {
780 		BNXT_TF_DBG(ERR, "Failed to set global cfg 0x%x rc:%d\n",
781 			    type, rc);
782 		return rc;
783 	}
784 	return rc;
785 }
786 
787 /* Internal function to delete all the flows belonging to the given port */
788 static void
789 bnxt_ulp_flush_port_flows(struct bnxt *bp)
790 {
791 	uint16_t func_id;
792 
793 	/* it is assumed that port is either TVF or PF */
794 	if (ulp_port_db_port_func_id_get(bp->ulp_ctx,
795 					 bp->eth_dev->data->port_id,
796 					 &func_id)) {
797 		BNXT_TF_DBG(ERR, "Invalid argument\n");
798 		return;
799 	}
800 	(void)ulp_flow_db_function_flow_flush(bp->ulp_ctx, func_id);
801 }
802 
803 /* Internal function to delete the VFR default flows */
804 static void
805 bnxt_ulp_destroy_vfr_default_rules(struct bnxt *bp, bool global)
806 {
807 	struct bnxt_ulp_vfr_rule_info *info;
808 	uint16_t port_id;
809 	struct rte_eth_dev *vfr_eth_dev;
810 	struct bnxt_representor *vfr_bp;
811 
812 	if (!BNXT_TRUFLOW_EN(bp) || BNXT_ETH_DEV_IS_REPRESENTOR(bp->eth_dev))
813 		return;
814 
815 	if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data)
816 		return;
817 
818 	/* Delete default rules for all ports */
819 	for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
820 		info = &bp->ulp_ctx->cfg_data->vfr_rule_info[port_id];
821 		if (!info->valid)
822 			continue;
823 
824 		if (!global && info->parent_port_id !=
825 		    bp->eth_dev->data->port_id)
826 			continue;
827 
828 		/* Destroy the flows */
829 		ulp_default_flow_destroy(bp->eth_dev, info->rep2vf_flow_id);
830 		ulp_default_flow_destroy(bp->eth_dev, info->vf2rep_flow_id);
831 		/* Clean up the tx action pointer */
832 		vfr_eth_dev = &rte_eth_devices[port_id];
833 		if (vfr_eth_dev) {
834 			vfr_bp = vfr_eth_dev->data->dev_private;
835 			vfr_bp->vfr_tx_cfa_action = 0;
836 		}
837 		memset(info, 0, sizeof(struct bnxt_ulp_vfr_rule_info));
838 	}
839 }
840 
841 /*
842  * When a port is deinit'ed by dpdk. This function is called
843  * and this function clears the ULP context and rest of the
844  * infrastructure associated with it.
845  */
846 static void
847 bnxt_ulp_deinit(struct bnxt *bp,
848 		struct bnxt_ulp_session_state *session)
849 {
850 	if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data)
851 		return;
852 
853 	/* clean up default flows */
854 	bnxt_ulp_destroy_df_rules(bp, true);
855 
856 	/* clean up default VFR flows */
857 	bnxt_ulp_destroy_vfr_default_rules(bp, true);
858 
859 	/* clean up regular flows */
860 	ulp_flow_db_flush_flows(bp->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR);
861 
862 	/* cleanup the eem table scope */
863 	ulp_eem_tbl_scope_deinit(bp, bp->ulp_ctx);
864 
865 	/* cleanup the flow database */
866 	ulp_flow_db_deinit(bp->ulp_ctx);
867 
868 	/* Delete the Mark database */
869 	ulp_mark_db_deinit(bp->ulp_ctx);
870 
871 	/* cleanup the ulp mapper */
872 	ulp_mapper_deinit(bp->ulp_ctx);
873 
874 	/* Delete the Flow Counter Manager */
875 	ulp_fc_mgr_deinit(bp->ulp_ctx);
876 
877 	/* Delete the Port database */
878 	ulp_port_db_deinit(bp->ulp_ctx);
879 
880 	/* Disable NAT feature */
881 	(void)bnxt_ulp_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP,
882 					 TF_TUNNEL_ENCAP_NAT,
883 					 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
884 
885 	(void)bnxt_ulp_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP,
886 					 TF_TUNNEL_ENCAP_NAT,
887 					 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
888 
889 	/* free the flow db lock */
890 	pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
891 
892 	/* Delete the ulp context and tf session and free the ulp context */
893 	ulp_ctx_deinit(bp, session);
894 	BNXT_TF_DBG(DEBUG, "ulp ctx has been deinitialized\n");
895 }
896 
897 /*
898  * When a port is initialized by dpdk. This functions is called
899  * and this function initializes the ULP context and rest of the
900  * infrastructure associated with it.
901  */
902 static int32_t
903 bnxt_ulp_init(struct bnxt *bp,
904 	      struct bnxt_ulp_session_state *session)
905 {
906 	int rc;
907 
908 	/* Allocate and Initialize the ulp context. */
909 	rc = ulp_ctx_init(bp, session);
910 	if (rc) {
911 		BNXT_TF_DBG(ERR, "Failed to create the ulp context\n");
912 		goto jump_to_error;
913 	}
914 
915 	rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL);
916 	if (rc) {
917 		BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n");
918 		goto jump_to_error;
919 	}
920 
921 	/* Initialize ulp dparms with values devargs passed */
922 	rc = ulp_dparms_init(bp, bp->ulp_ctx);
923 	if (rc) {
924 		BNXT_TF_DBG(ERR, "Failed to initialize the dparms\n");
925 		goto jump_to_error;
926 	}
927 
928 	/* create the port database */
929 	rc = ulp_port_db_init(bp->ulp_ctx, bp->port_cnt);
930 	if (rc) {
931 		BNXT_TF_DBG(ERR, "Failed to create the port database\n");
932 		goto jump_to_error;
933 	}
934 
935 	/* Create the Mark database. */
936 	rc = ulp_mark_db_init(bp->ulp_ctx);
937 	if (rc) {
938 		BNXT_TF_DBG(ERR, "Failed to create the mark database\n");
939 		goto jump_to_error;
940 	}
941 
942 	/* Create the flow database. */
943 	rc = ulp_flow_db_init(bp->ulp_ctx);
944 	if (rc) {
945 		BNXT_TF_DBG(ERR, "Failed to create the flow database\n");
946 		goto jump_to_error;
947 	}
948 
949 	/* Create the eem table scope. */
950 	rc = ulp_eem_tbl_scope_init(bp);
951 	if (rc) {
952 		BNXT_TF_DBG(ERR, "Failed to create the eem scope table\n");
953 		goto jump_to_error;
954 	}
955 
956 	rc = ulp_mapper_init(bp->ulp_ctx);
957 	if (rc) {
958 		BNXT_TF_DBG(ERR, "Failed to initialize ulp mapper\n");
959 		goto jump_to_error;
960 	}
961 
962 	rc = ulp_fc_mgr_init(bp->ulp_ctx);
963 	if (rc) {
964 		BNXT_TF_DBG(ERR, "Failed to initialize ulp flow counter mgr\n");
965 		goto jump_to_error;
966 	}
967 
968 	/*
969 	 * Enable NAT feature. Set the global configuration register
970 	 * Tunnel encap to enable NAT with the reuse of existing inner
971 	 * L2 header smac and dmac
972 	 */
973 	rc = bnxt_ulp_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP,
974 					TF_TUNNEL_ENCAP_NAT,
975 					BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1);
976 	if (rc) {
977 		BNXT_TF_DBG(ERR, "Failed to set rx global configuration\n");
978 		goto jump_to_error;
979 	}
980 
981 	rc = bnxt_ulp_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP,
982 					TF_TUNNEL_ENCAP_NAT,
983 					BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1);
984 	if (rc) {
985 		BNXT_TF_DBG(ERR, "Failed to set tx global configuration\n");
986 		goto jump_to_error;
987 	}
988 	BNXT_TF_DBG(DEBUG, "ulp ctx has been initialized\n");
989 	return rc;
990 
991 jump_to_error:
992 	bnxt_ulp_deinit(bp, session);
993 	return rc;
994 }
995 
996 /*
997  * When a port is initialized by dpdk. This functions sets up
998  * the port specific details.
999  */
1000 int32_t
1001 bnxt_ulp_port_init(struct bnxt *bp)
1002 {
1003 	struct bnxt_ulp_session_state *session;
1004 	bool initialized;
1005 	int32_t rc = 0;
1006 
1007 	if (!bp || !BNXT_TRUFLOW_EN(bp))
1008 		return rc;
1009 
1010 	if (!BNXT_PF(bp) && !BNXT_VF_IS_TRUSTED(bp)) {
1011 		BNXT_TF_DBG(ERR,
1012 			    "Skip ulp init for port: %d, not a TVF or PF\n",
1013 			bp->eth_dev->data->port_id);
1014 		return rc;
1015 	}
1016 
1017 	if (bp->ulp_ctx) {
1018 		BNXT_TF_DBG(DEBUG, "ulp ctx already allocated\n");
1019 		return rc;
1020 	}
1021 
1022 	bp->ulp_ctx = rte_zmalloc("bnxt_ulp_ctx",
1023 				  sizeof(struct bnxt_ulp_context), 0);
1024 	if (!bp->ulp_ctx) {
1025 		BNXT_TF_DBG(ERR, "Failed to allocate ulp ctx\n");
1026 		return -ENOMEM;
1027 	}
1028 
1029 	/*
1030 	 * Multiple uplink ports can be associated with a single vswitch.
1031 	 * Make sure only the port that is started first will initialize
1032 	 * the TF session.
1033 	 */
1034 	session = ulp_session_init(bp, &initialized);
1035 	if (!session) {
1036 		BNXT_TF_DBG(ERR, "Failed to initialize the tf session\n");
1037 		rc = -EIO;
1038 		goto jump_to_error;
1039 	}
1040 
1041 	if (initialized) {
1042 		/*
1043 		 * If ULP is already initialized for a specific domain then
1044 		 * simply assign the ulp context to this rte_eth_dev.
1045 		 */
1046 		rc = ulp_ctx_attach(bp, session);
1047 		if (rc) {
1048 			BNXT_TF_DBG(ERR, "Failed to attach the ulp context\n");
1049 			goto jump_to_error;
1050 		}
1051 	} else {
1052 		rc = bnxt_ulp_init(bp, session);
1053 		if (rc) {
1054 			BNXT_TF_DBG(ERR, "Failed to initialize the ulp init\n");
1055 			goto jump_to_error;
1056 		}
1057 	}
1058 
1059 	/* Update bnxt driver flags */
1060 	rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx);
1061 	if (rc) {
1062 		BNXT_TF_DBG(ERR, "Failed to update driver flags\n");
1063 		goto jump_to_error;
1064 	}
1065 
1066 	/* update the port database for the given interface */
1067 	rc = ulp_port_db_dev_port_intf_update(bp->ulp_ctx, bp->eth_dev);
1068 	if (rc) {
1069 		BNXT_TF_DBG(ERR, "Failed to update port database\n");
1070 		goto jump_to_error;
1071 	}
1072 	/* create the default rules */
1073 	bnxt_ulp_create_df_rules(bp);
1074 	BNXT_TF_DBG(DEBUG, "BNXT Port:%d ULP port init\n",
1075 		    bp->eth_dev->data->port_id);
1076 	return rc;
1077 
1078 jump_to_error:
1079 	bnxt_ulp_port_deinit(bp);
1080 	return rc;
1081 }
1082 
1083 /*
1084  * When a port is de-initialized by dpdk. This functions clears up
1085  * the port specific details.
1086  */
1087 void
1088 bnxt_ulp_port_deinit(struct bnxt *bp)
1089 {
1090 	struct bnxt_ulp_session_state *session;
1091 	struct rte_pci_device *pci_dev;
1092 	struct rte_pci_addr *pci_addr;
1093 
1094 	if (!BNXT_TRUFLOW_EN(bp))
1095 		return;
1096 
1097 	if (!BNXT_PF(bp) && !BNXT_VF_IS_TRUSTED(bp)) {
1098 		BNXT_TF_DBG(ERR,
1099 			    "Skip ULP deinit port:%d, not a TVF or PF\n",
1100 			    bp->eth_dev->data->port_id);
1101 		return;
1102 	}
1103 
1104 	if (!bp->ulp_ctx) {
1105 		BNXT_TF_DBG(DEBUG, "ulp ctx already de-allocated\n");
1106 		return;
1107 	}
1108 
1109 	BNXT_TF_DBG(DEBUG, "BNXT Port:%d ULP port deinit\n",
1110 		    bp->eth_dev->data->port_id);
1111 
1112 	/* Get the session details  */
1113 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
1114 	pci_addr = &pci_dev->addr;
1115 	pthread_mutex_lock(&bnxt_ulp_global_mutex);
1116 	session = ulp_get_session(pci_addr);
1117 	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
1118 
1119 	/* session not found then just exit */
1120 	if (!session) {
1121 		/* Free the ulp context */
1122 		rte_free(bp->ulp_ctx);
1123 		bp->ulp_ctx = NULL;
1124 		return;
1125 	}
1126 
1127 	/* Check the reference count to deinit or deattach*/
1128 	if (bp->ulp_ctx->cfg_data && bp->ulp_ctx->cfg_data->ref_cnt) {
1129 		bp->ulp_ctx->cfg_data->ref_cnt--;
1130 		if (bp->ulp_ctx->cfg_data->ref_cnt) {
1131 			/* free the port details */
1132 			/* Free the default flow rule associated to this port */
1133 			bnxt_ulp_destroy_df_rules(bp, false);
1134 			bnxt_ulp_destroy_vfr_default_rules(bp, false);
1135 
1136 			/* free flows associated with this port */
1137 			bnxt_ulp_flush_port_flows(bp);
1138 
1139 			/* close the session associated with this port */
1140 			ulp_ctx_detach(bp);
1141 		} else {
1142 			/* Perform ulp ctx deinit */
1143 			bnxt_ulp_deinit(bp, session);
1144 		}
1145 	}
1146 
1147 	/* clean up the session */
1148 	ulp_session_deinit(session);
1149 
1150 	/* Free the ulp context */
1151 	rte_free(bp->ulp_ctx);
1152 	bp->ulp_ctx = NULL;
1153 }
1154 
1155 /* Below are the access functions to access internal data of ulp context. */
1156 /* Function to set the Mark DB into the context */
1157 int32_t
1158 bnxt_ulp_cntxt_ptr2_mark_db_set(struct bnxt_ulp_context *ulp_ctx,
1159 				struct bnxt_ulp_mark_tbl *mark_tbl)
1160 {
1161 	if (!ulp_ctx || !ulp_ctx->cfg_data) {
1162 		BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
1163 		return -EINVAL;
1164 	}
1165 
1166 	ulp_ctx->cfg_data->mark_tbl = mark_tbl;
1167 
1168 	return 0;
1169 }
1170 
1171 /* Function to retrieve the Mark DB from the context. */
1172 struct bnxt_ulp_mark_tbl *
1173 bnxt_ulp_cntxt_ptr2_mark_db_get(struct bnxt_ulp_context *ulp_ctx)
1174 {
1175 	if (!ulp_ctx || !ulp_ctx->cfg_data)
1176 		return NULL;
1177 
1178 	return ulp_ctx->cfg_data->mark_tbl;
1179 }
1180 
1181 /* Function to set the device id of the hardware. */
1182 int32_t
1183 bnxt_ulp_cntxt_dev_id_set(struct bnxt_ulp_context *ulp_ctx,
1184 			  uint32_t dev_id)
1185 {
1186 	if (ulp_ctx && ulp_ctx->cfg_data) {
1187 		ulp_ctx->cfg_data->dev_id = dev_id;
1188 		return 0;
1189 	}
1190 
1191 	return -EINVAL;
1192 }
1193 
1194 /* Function to get the device id of the hardware. */
1195 int32_t
1196 bnxt_ulp_cntxt_dev_id_get(struct bnxt_ulp_context *ulp_ctx,
1197 			  uint32_t *dev_id)
1198 {
1199 	if (ulp_ctx && ulp_ctx->cfg_data) {
1200 		*dev_id = ulp_ctx->cfg_data->dev_id;
1201 		return 0;
1202 	}
1203 
1204 	BNXT_TF_DBG(ERR, "Failed to read dev_id from ulp ctxt\n");
1205 	return -EINVAL;
1206 }
1207 
1208 int32_t
1209 bnxt_ulp_cntxt_mem_type_set(struct bnxt_ulp_context *ulp_ctx,
1210 			    enum bnxt_ulp_flow_mem_type mem_type)
1211 {
1212 	if (ulp_ctx && ulp_ctx->cfg_data) {
1213 		ulp_ctx->cfg_data->mem_type = mem_type;
1214 		return 0;
1215 	}
1216 	BNXT_TF_DBG(ERR, "Failed to write mem_type in ulp ctxt\n");
1217 	return -EINVAL;
1218 }
1219 
1220 int32_t
1221 bnxt_ulp_cntxt_mem_type_get(struct bnxt_ulp_context *ulp_ctx,
1222 			    enum bnxt_ulp_flow_mem_type *mem_type)
1223 {
1224 	if (ulp_ctx && ulp_ctx->cfg_data) {
1225 		*mem_type = ulp_ctx->cfg_data->mem_type;
1226 		return 0;
1227 	}
1228 	BNXT_TF_DBG(ERR, "Failed to read mem_type in ulp ctxt\n");
1229 	return -EINVAL;
1230 }
1231 
1232 /* Function to get the table scope id of the EEM table. */
1233 int32_t
1234 bnxt_ulp_cntxt_tbl_scope_id_get(struct bnxt_ulp_context *ulp_ctx,
1235 				uint32_t *tbl_scope_id)
1236 {
1237 	if (ulp_ctx && ulp_ctx->cfg_data) {
1238 		*tbl_scope_id = ulp_ctx->cfg_data->tbl_scope_id;
1239 		return 0;
1240 	}
1241 
1242 	return -EINVAL;
1243 }
1244 
1245 /* Function to set the table scope id of the EEM table. */
1246 int32_t
1247 bnxt_ulp_cntxt_tbl_scope_id_set(struct bnxt_ulp_context *ulp_ctx,
1248 				uint32_t tbl_scope_id)
1249 {
1250 	if (ulp_ctx && ulp_ctx->cfg_data) {
1251 		ulp_ctx->cfg_data->tbl_scope_id = tbl_scope_id;
1252 		return 0;
1253 	}
1254 
1255 	return -EINVAL;
1256 }
1257 
1258 /* Function to set the tfp session details from the ulp context. */
1259 int32_t
1260 bnxt_ulp_cntxt_tfp_set(struct bnxt_ulp_context *ulp, struct tf *tfp)
1261 {
1262 	if (!ulp) {
1263 		BNXT_TF_DBG(ERR, "Invalid arguments\n");
1264 		return -EINVAL;
1265 	}
1266 
1267 	ulp->g_tfp = tfp;
1268 	return 0;
1269 }
1270 
1271 /* Function to get the tfp session details from the ulp context. */
1272 struct tf *
1273 bnxt_ulp_cntxt_tfp_get(struct bnxt_ulp_context *ulp)
1274 {
1275 	if (!ulp) {
1276 		BNXT_TF_DBG(ERR, "Invalid arguments\n");
1277 		return NULL;
1278 	}
1279 	return ulp->g_tfp;
1280 }
1281 
1282 /*
1283  * Get the device table entry based on the device id.
1284  *
1285  * dev_id [in] The device id of the hardware
1286  *
1287  * Returns the pointer to the device parameters.
1288  */
1289 struct bnxt_ulp_device_params *
1290 bnxt_ulp_device_params_get(uint32_t dev_id)
1291 {
1292 	if (dev_id < BNXT_ULP_MAX_NUM_DEVICES)
1293 		return &ulp_device_params[dev_id];
1294 	return NULL;
1295 }
1296 
1297 /* Function to set the flow database to the ulp context. */
1298 int32_t
1299 bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context	*ulp_ctx,
1300 				struct bnxt_ulp_flow_db	*flow_db)
1301 {
1302 	if (!ulp_ctx || !ulp_ctx->cfg_data)
1303 		return -EINVAL;
1304 
1305 	ulp_ctx->cfg_data->flow_db = flow_db;
1306 	return 0;
1307 }
1308 
1309 /* Function to get the flow database from the ulp context. */
1310 struct bnxt_ulp_flow_db	*
1311 bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context	*ulp_ctx)
1312 {
1313 	if (!ulp_ctx || !ulp_ctx->cfg_data)
1314 		return NULL;
1315 
1316 	return ulp_ctx->cfg_data->flow_db;
1317 }
1318 
1319 /* Function to get the tunnel cache table info from the ulp context. */
1320 struct bnxt_tun_cache_entry *
1321 bnxt_ulp_cntxt_ptr2_tun_tbl_get(struct bnxt_ulp_context *ulp_ctx)
1322 {
1323 	if (!ulp_ctx || !ulp_ctx->cfg_data)
1324 		return NULL;
1325 
1326 	return ulp_ctx->cfg_data->tun_tbl;
1327 }
1328 
1329 /* Function to get the ulp context from eth device. */
1330 struct bnxt_ulp_context	*
1331 bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev	*dev)
1332 {
1333 	struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
1334 
1335 	if (BNXT_ETH_DEV_IS_REPRESENTOR(dev)) {
1336 		struct bnxt_representor *vfr = dev->data->dev_private;
1337 
1338 		bp = vfr->parent_dev->data->dev_private;
1339 	}
1340 
1341 	if (!bp) {
1342 		BNXT_TF_DBG(ERR, "Bnxt private data is not initialized\n");
1343 		return NULL;
1344 	}
1345 	return bp->ulp_ctx;
1346 }
1347 
1348 int32_t
1349 bnxt_ulp_cntxt_ptr2_mapper_data_set(struct bnxt_ulp_context *ulp_ctx,
1350 				    void *mapper_data)
1351 {
1352 	if (!ulp_ctx || !ulp_ctx->cfg_data) {
1353 		BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
1354 		return -EINVAL;
1355 	}
1356 
1357 	ulp_ctx->cfg_data->mapper_data = mapper_data;
1358 	return 0;
1359 }
1360 
1361 void *
1362 bnxt_ulp_cntxt_ptr2_mapper_data_get(struct bnxt_ulp_context *ulp_ctx)
1363 {
1364 	if (!ulp_ctx || !ulp_ctx->cfg_data) {
1365 		BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
1366 		return NULL;
1367 	}
1368 
1369 	return ulp_ctx->cfg_data->mapper_data;
1370 }
1371 
1372 /* Function to set the port database to the ulp context. */
1373 int32_t
1374 bnxt_ulp_cntxt_ptr2_port_db_set(struct bnxt_ulp_context	*ulp_ctx,
1375 				struct bnxt_ulp_port_db	*port_db)
1376 {
1377 	if (!ulp_ctx || !ulp_ctx->cfg_data)
1378 		return -EINVAL;
1379 
1380 	ulp_ctx->cfg_data->port_db = port_db;
1381 	return 0;
1382 }
1383 
1384 /* Function to get the port database from the ulp context. */
1385 struct bnxt_ulp_port_db *
1386 bnxt_ulp_cntxt_ptr2_port_db_get(struct bnxt_ulp_context	*ulp_ctx)
1387 {
1388 	if (!ulp_ctx || !ulp_ctx->cfg_data)
1389 		return NULL;
1390 
1391 	return ulp_ctx->cfg_data->port_db;
1392 }
1393 
1394 /* Function to set the flow counter info into the context */
1395 int32_t
1396 bnxt_ulp_cntxt_ptr2_fc_info_set(struct bnxt_ulp_context *ulp_ctx,
1397 				struct bnxt_ulp_fc_info *ulp_fc_info)
1398 {
1399 	if (!ulp_ctx || !ulp_ctx->cfg_data) {
1400 		BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
1401 		return -EINVAL;
1402 	}
1403 
1404 	ulp_ctx->cfg_data->fc_info = ulp_fc_info;
1405 
1406 	return 0;
1407 }
1408 
1409 /* Function to retrieve the flow counter info from the context. */
1410 struct bnxt_ulp_fc_info *
1411 bnxt_ulp_cntxt_ptr2_fc_info_get(struct bnxt_ulp_context *ulp_ctx)
1412 {
1413 	if (!ulp_ctx || !ulp_ctx->cfg_data)
1414 		return NULL;
1415 
1416 	return ulp_ctx->cfg_data->fc_info;
1417 }
1418 
1419 /* Function to get the ulp flags from the ulp context. */
1420 int32_t
1421 bnxt_ulp_cntxt_ptr2_ulp_flags_get(struct bnxt_ulp_context *ulp_ctx,
1422 				  uint32_t *flags)
1423 {
1424 	if (!ulp_ctx || !ulp_ctx->cfg_data)
1425 		return -1;
1426 
1427 	*flags =  ulp_ctx->cfg_data->ulp_flags;
1428 	return 0;
1429 }
1430 
1431 /* Function to get the ulp vfr info from the ulp context. */
1432 struct bnxt_ulp_vfr_rule_info*
1433 bnxt_ulp_cntxt_ptr2_ulp_vfr_info_get(struct bnxt_ulp_context *ulp_ctx,
1434 				     uint32_t port_id)
1435 {
1436 	if (!ulp_ctx || !ulp_ctx->cfg_data || port_id >= RTE_MAX_ETHPORTS)
1437 		return NULL;
1438 
1439 	return &ulp_ctx->cfg_data->vfr_rule_info[port_id];
1440 }
1441 
1442 /* Function to acquire the flow database lock from the ulp context. */
1443 int32_t
1444 bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
1445 {
1446 	if (!ulp_ctx || !ulp_ctx->cfg_data)
1447 		return -1;
1448 
1449 	if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
1450 		BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n");
1451 		return -1;
1452 	}
1453 	return 0;
1454 }
1455 
1456 /* Function to release the flow database lock from the ulp context. */
1457 void
1458 bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
1459 {
1460 	if (!ulp_ctx || !ulp_ctx->cfg_data)
1461 		return;
1462 
1463 	pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
1464 }
1465