xref: /dpdk/drivers/net/bnxt/tf_ulp/bnxt_ulp.c (revision e9fd1ebf981f361844aea9ec94e17f4bda5e1479)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2023 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 #include <rte_spinlock.h>
12 
13 #include "bnxt.h"
14 #include "bnxt_ulp.h"
15 #include "bnxt_tf_common.h"
16 #include "hsi_struct_def_dpdk.h"
17 #include "tf_core.h"
18 #include "tf_ext_flow_handle.h"
19 
20 #include "ulp_template_db_enum.h"
21 #include "ulp_template_struct.h"
22 #include "ulp_mark_mgr.h"
23 #include "ulp_fc_mgr.h"
24 #include "ulp_flow_db.h"
25 #include "ulp_mapper.h"
26 #include "ulp_port_db.h"
27 #include "ulp_tun.h"
28 #include "ulp_ha_mgr.h"
29 #include "bnxt_tf_pmd_shim.h"
30 #include "ulp_template_db_tbl.h"
31 
32 /* Linked list of all TF sessions. */
33 STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
34 			STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
35 
36 /* Mutex to synchronize bnxt_ulp_session_list operations. */
37 static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
38 
39 /* Spin lock to protect context global list */
40 uint32_t bnxt_ulp_ctxt_lock_created;
41 rte_spinlock_t bnxt_ulp_ctxt_lock;
42 TAILQ_HEAD(cntx_list_entry_list, ulp_context_list_entry);
43 static struct cntx_list_entry_list ulp_cntx_list =
44 	TAILQ_HEAD_INITIALIZER(ulp_cntx_list);
45 
46 /* Static function declarations */
47 static int32_t bnxt_ulp_cntxt_list_init(void);
48 static int32_t bnxt_ulp_cntxt_list_add(struct bnxt_ulp_context *ulp_ctx);
49 static void bnxt_ulp_cntxt_list_del(struct bnxt_ulp_context *ulp_ctx);
50 
51 /*
52  * Allow the deletion of context only for the bnxt device that
53  * created the session.
54  */
55 bool
56 ulp_ctx_deinit_allowed(struct bnxt_ulp_context *ulp_ctx)
57 {
58 	if (!ulp_ctx || !ulp_ctx->cfg_data)
59 		return false;
60 
61 	if (!ulp_ctx->cfg_data->ref_cnt) {
62 		BNXT_TF_DBG(DEBUG, "ulp ctx shall initiate deinit\n");
63 		return true;
64 	}
65 
66 	return false;
67 }
68 
69 static int32_t
70 bnxt_ulp_devid_get(struct bnxt *bp,
71 		   enum bnxt_ulp_device_id  *ulp_dev_id)
72 {
73 	if (BNXT_CHIP_P5(bp)) {
74 		*ulp_dev_id = BNXT_ULP_DEVICE_ID_THOR;
75 		return 0;
76 	}
77 
78 	if (BNXT_STINGRAY(bp))
79 		*ulp_dev_id = BNXT_ULP_DEVICE_ID_STINGRAY;
80 	else
81 		/* Assuming P4 */
82 		*ulp_dev_id = BNXT_ULP_DEVICE_ID_WH_PLUS;
83 
84 	return 0;
85 }
86 
87 struct bnxt_ulp_app_capabilities_info *
88 bnxt_ulp_app_cap_list_get(uint32_t *num_entries)
89 {
90 	if (!num_entries)
91 		return NULL;
92 	*num_entries = BNXT_ULP_APP_CAP_TBL_MAX_SZ;
93 	return ulp_app_cap_info_list;
94 }
95 
96 struct bnxt_ulp_shared_act_info *
97 bnxt_ulp_shared_act_info_get(uint32_t *num_entries)
98 {
99 	if (!num_entries)
100 		return NULL;
101 
102 	*num_entries = BNXT_ULP_GEN_TBL_MAX_SZ;
103 
104 	return ulp_shared_act_info;
105 }
106 
107 static struct bnxt_ulp_resource_resv_info *
108 bnxt_ulp_app_resource_resv_list_get(uint32_t *num_entries)
109 {
110 	if (num_entries == NULL)
111 		return NULL;
112 	*num_entries = BNXT_ULP_APP_RESOURCE_RESV_LIST_MAX_SZ;
113 	return ulp_app_resource_resv_list;
114 }
115 
116 struct bnxt_ulp_resource_resv_info *
117 bnxt_ulp_resource_resv_list_get(uint32_t *num_entries)
118 {
119 	if (!num_entries)
120 		return NULL;
121 	*num_entries = BNXT_ULP_RESOURCE_RESV_LIST_MAX_SZ;
122 	return ulp_resource_resv_list;
123 }
124 
125 struct bnxt_ulp_glb_resource_info *
126 bnxt_ulp_app_glb_resource_info_list_get(uint32_t *num_entries)
127 {
128 	if (!num_entries)
129 		return NULL;
130 	*num_entries = BNXT_ULP_APP_GLB_RESOURCE_TBL_MAX_SZ;
131 	return ulp_app_glb_resource_tbl;
132 }
133 
134 static int32_t
135 bnxt_ulp_named_resources_calc(struct bnxt_ulp_context *ulp_ctx,
136 			      struct bnxt_ulp_glb_resource_info *info,
137 			      uint32_t num,
138 			      enum bnxt_ulp_session_type stype,
139 			      struct tf_session_resources *res)
140 {
141 	uint32_t dev_id = BNXT_ULP_DEVICE_ID_LAST, res_type, i;
142 	enum tf_dir dir;
143 	uint8_t app_id;
144 	int32_t rc = 0;
145 
146 	if (ulp_ctx == NULL || info == NULL || res == NULL || num == 0) {
147 		BNXT_TF_DBG(ERR, "Invalid parms to named resources calc.\n");
148 		return -EINVAL;
149 	}
150 
151 	rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
152 	if (rc) {
153 		BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
154 		return -EINVAL;
155 	}
156 
157 	rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
158 	if (rc) {
159 		BNXT_TF_DBG(ERR, "Unable to get the dev id from ulp.\n");
160 		return -EINVAL;
161 	}
162 
163 	for (i = 0; i < num; i++) {
164 		if (dev_id != info[i].device_id || app_id != info[i].app_id)
165 			continue;
166 		/* check to see if the session type matches only then include */
167 		if ((stype || info[i].session_type) &&
168 		    !(info[i].session_type & stype))
169 			continue;
170 
171 		dir = info[i].direction;
172 		res_type = info[i].resource_type;
173 
174 		switch (info[i].resource_func) {
175 		case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
176 			res->ident_cnt[dir].cnt[res_type]++;
177 			break;
178 		case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
179 			res->tbl_cnt[dir].cnt[res_type]++;
180 			break;
181 		case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
182 			res->tcam_cnt[dir].cnt[res_type]++;
183 			break;
184 		case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
185 			res->em_cnt[dir].cnt[res_type]++;
186 			break;
187 		default:
188 			BNXT_TF_DBG(ERR, "Unknown resource func (0x%x)\n,",
189 				    info[i].resource_func);
190 			continue;
191 		}
192 	}
193 
194 	return 0;
195 }
196 
197 static int32_t
198 bnxt_ulp_unnamed_resources_calc(struct bnxt_ulp_context *ulp_ctx,
199 				struct bnxt_ulp_resource_resv_info *info,
200 				uint32_t num,
201 				enum bnxt_ulp_session_type stype,
202 				struct tf_session_resources *res)
203 {
204 	uint32_t dev_id, res_type, i;
205 	enum tf_dir dir;
206 	uint8_t app_id;
207 	int32_t rc = 0;
208 
209 	if (ulp_ctx == NULL || res == NULL || info == NULL || num == 0) {
210 		BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n");
211 		return -EINVAL;
212 	}
213 
214 	rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
215 	if (rc) {
216 		BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
217 		return -EINVAL;
218 	}
219 
220 	rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
221 	if (rc) {
222 		BNXT_TF_DBG(ERR, "Unable to get the dev id from ulp.\n");
223 		return -EINVAL;
224 	}
225 
226 	for (i = 0; i < num; i++) {
227 		if (app_id != info[i].app_id || dev_id != info[i].device_id)
228 			continue;
229 
230 		/* check to see if the session type matches only then include */
231 		if ((stype || info[i].session_type) &&
232 		    !(info[i].session_type & stype))
233 			continue;
234 
235 		dir = info[i].direction;
236 		res_type = info[i].resource_type;
237 
238 		switch (info[i].resource_func) {
239 		case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
240 			res->ident_cnt[dir].cnt[res_type] = info[i].count;
241 			break;
242 		case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
243 			res->tbl_cnt[dir].cnt[res_type] = info[i].count;
244 			break;
245 		case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
246 			res->tcam_cnt[dir].cnt[res_type] = info[i].count;
247 			break;
248 		case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
249 			res->em_cnt[dir].cnt[res_type] = info[i].count;
250 			break;
251 		default:
252 			break;
253 		}
254 	}
255 	return 0;
256 }
257 
258 static int32_t
259 bnxt_ulp_tf_resources_get(struct bnxt_ulp_context *ulp_ctx,
260 			  enum bnxt_ulp_session_type stype,
261 			  struct tf_session_resources *res)
262 {
263 	struct bnxt_ulp_resource_resv_info *unnamed = NULL;
264 	uint32_t unum;
265 	int32_t rc = 0;
266 
267 	if (ulp_ctx == NULL || res == NULL) {
268 		BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n");
269 		return -EINVAL;
270 	}
271 
272 	/* use DEFAULT_NON_HA instead of DEFAULT resources if HA is disabled */
273 	if (ULP_APP_HA_IS_DYNAMIC(ulp_ctx))
274 		stype = ulp_ctx->cfg_data->def_session_type;
275 
276 	unnamed = bnxt_ulp_resource_resv_list_get(&unum);
277 	if (unnamed == NULL) {
278 		BNXT_TF_DBG(ERR, "Unable to get resource resv list.\n");
279 		return -EINVAL;
280 	}
281 
282 	rc = bnxt_ulp_unnamed_resources_calc(ulp_ctx, unnamed, unum, stype,
283 					     res);
284 	if (rc)
285 		BNXT_TF_DBG(ERR, "Unable to calc resources for session.\n");
286 
287 	return rc;
288 }
289 
290 static int32_t
291 bnxt_ulp_tf_shared_session_resources_get(struct bnxt_ulp_context *ulp_ctx,
292 					 enum bnxt_ulp_session_type stype,
293 					 struct tf_session_resources *res)
294 {
295 	struct bnxt_ulp_resource_resv_info *unnamed;
296 	struct bnxt_ulp_glb_resource_info *named;
297 	uint32_t unum, nnum;
298 	int32_t rc;
299 
300 	if (ulp_ctx == NULL || res == NULL) {
301 		BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n");
302 		return -EINVAL;
303 	}
304 
305 	/* Make sure the resources are zero before accumulating. */
306 	memset(res, 0, sizeof(struct tf_session_resources));
307 
308 	if (bnxt_ulp_cntxt_ha_enabled(ulp_ctx) &&
309 	    stype == BNXT_ULP_SESSION_TYPE_SHARED)
310 		stype = ulp_ctx->cfg_data->hu_session_type;
311 
312 	/*
313 	 * Shared resources are comprised of both named and unnamed resources.
314 	 * First get the unnamed counts, and then add the named to the result.
315 	 */
316 	/* Get the baseline counts */
317 	unnamed = bnxt_ulp_app_resource_resv_list_get(&unum);
318 	if (unnamed == NULL) {
319 		BNXT_TF_DBG(ERR, "Unable to get shared resource resv list.\n");
320 		return -EINVAL;
321 	}
322 	rc = bnxt_ulp_unnamed_resources_calc(ulp_ctx, unnamed, unum, stype,
323 					     res);
324 	if (rc) {
325 		BNXT_TF_DBG(ERR,
326 			    "Unable to calc resources for shared session.\n");
327 		return -EINVAL;
328 	}
329 
330 	/* Get the named list and add the totals */
331 	named = bnxt_ulp_app_glb_resource_info_list_get(&nnum);
332 	if (named == NULL) {
333 		BNXT_TF_DBG(ERR, "Unable to get app global resource list\n");
334 		return -EINVAL;
335 	}
336 	rc = bnxt_ulp_named_resources_calc(ulp_ctx, named, nnum, stype, res);
337 	if (rc)
338 		BNXT_TF_DBG(ERR, "Unable to calc named resources\n");
339 
340 	return rc;
341 }
342 
343 /* Function to set the hot upgrade support into the context */
344 static int
345 bnxt_ulp_multi_shared_session_support_set(struct bnxt *bp,
346 					  enum bnxt_ulp_device_id devid,
347 					  uint32_t fw_hu_update)
348 {
349 	struct bnxt_ulp_context *ulp_ctx = bp->ulp_ctx;
350 	struct tf_get_version_parms v_params = { 0 };
351 	struct tf *tfp;
352 	int32_t rc = 0;
353 	int32_t new_fw = 0;
354 
355 	v_params.device_type = bnxt_ulp_cntxt_convert_dev_id(devid);
356 	v_params.bp = bp;
357 
358 	tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT);
359 	rc = tf_get_version(tfp, &v_params);
360 	if (rc) {
361 		BNXT_TF_DBG(ERR, "Unable to get tf version.\n");
362 		return rc;
363 	}
364 
365 	if (v_params.major == 1 && v_params.minor == 0 &&
366 	    v_params.update == 1) {
367 		new_fw = 1;
368 	}
369 	/* if the version update is greater than 0 then set support for
370 	 * multiple version
371 	 */
372 	if (new_fw) {
373 		ulp_ctx->cfg_data->ulp_flags |= BNXT_ULP_MULTI_SHARED_SUPPORT;
374 		ulp_ctx->cfg_data->hu_session_type =
375 			BNXT_ULP_SESSION_TYPE_SHARED;
376 	}
377 	if (!new_fw && fw_hu_update) {
378 		ulp_ctx->cfg_data->ulp_flags &= ~BNXT_ULP_HIGH_AVAIL_ENABLED;
379 		ulp_ctx->cfg_data->hu_session_type =
380 			BNXT_ULP_SESSION_TYPE_SHARED |
381 			BNXT_ULP_SESSION_TYPE_SHARED_OWC;
382 	}
383 
384 	if (!new_fw && !fw_hu_update) {
385 		ulp_ctx->cfg_data->hu_session_type =
386 			BNXT_ULP_SESSION_TYPE_SHARED |
387 			BNXT_ULP_SESSION_TYPE_SHARED_OWC;
388 	}
389 
390 	return rc;
391 }
392 
393 int32_t
394 bnxt_ulp_cntxt_app_caps_init(struct bnxt *bp,
395 			     uint8_t app_id, uint32_t dev_id)
396 {
397 	struct bnxt_ulp_app_capabilities_info *info;
398 	uint32_t num = 0, fw = 0;
399 	uint16_t i;
400 	bool found = false;
401 	struct bnxt_ulp_context *ulp_ctx = bp->ulp_ctx;
402 
403 	if (ULP_APP_DEV_UNSUPPORTED_ENABLED(ulp_ctx->cfg_data->ulp_flags)) {
404 		BNXT_TF_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n",
405 			    app_id, dev_id);
406 		return -EINVAL;
407 	}
408 
409 	info = bnxt_ulp_app_cap_list_get(&num);
410 	if (!info || !num) {
411 		BNXT_TF_DBG(ERR, "Failed to get app capabilities.\n");
412 		return -EINVAL;
413 	}
414 
415 	for (i = 0; i < num; i++) {
416 		if (info[i].app_id != app_id || info[i].device_id != dev_id)
417 			continue;
418 		found = true;
419 		if (info[i].flags & BNXT_ULP_APP_CAP_SHARED_EN)
420 			ulp_ctx->cfg_data->ulp_flags |=
421 				BNXT_ULP_SHARED_SESSION_ENABLED;
422 		if (info[i].flags & BNXT_ULP_APP_CAP_HOT_UPGRADE_EN)
423 			ulp_ctx->cfg_data->ulp_flags |=
424 				BNXT_ULP_HIGH_AVAIL_ENABLED;
425 		if (info[i].flags & BNXT_ULP_APP_CAP_UNICAST_ONLY)
426 			ulp_ctx->cfg_data->ulp_flags |=
427 				BNXT_ULP_APP_UNICAST_ONLY;
428 		if (info[i].flags & BNXT_ULP_APP_CAP_IP_TOS_PROTO_SUPPORT)
429 			ulp_ctx->cfg_data->ulp_flags |=
430 				BNXT_ULP_APP_TOS_PROTO_SUPPORT;
431 		if (info[i].flags & BNXT_ULP_APP_CAP_BC_MC_SUPPORT)
432 			ulp_ctx->cfg_data->ulp_flags |=
433 				BNXT_ULP_APP_BC_MC_SUPPORT;
434 		if (info[i].flags & BNXT_ULP_APP_CAP_SOCKET_DIRECT) {
435 			/* Enable socket direction only if MR is enabled in fw*/
436 			if (BNXT_MULTIROOT_EN(bp)) {
437 				ulp_ctx->cfg_data->ulp_flags |=
438 					BNXT_ULP_APP_SOCKET_DIRECT;
439 				BNXT_TF_DBG(INFO,
440 					    "Socket Direct feature is enabled\n");
441 			}
442 		}
443 		if (info[i].flags & BNXT_ULP_APP_CAP_HA_DYNAMIC) {
444 			/* Read the environment variable to determine hot up */
445 			if (!bnxt_pmd_get_hot_upgrade_env()) {
446 				ulp_ctx->cfg_data->ulp_flags |=
447 					BNXT_ULP_APP_HA_DYNAMIC;
448 				/* reset Hot upgrade, dynamically disabled */
449 				ulp_ctx->cfg_data->ulp_flags &=
450 					~BNXT_ULP_HIGH_AVAIL_ENABLED;
451 				ulp_ctx->cfg_data->def_session_type =
452 					BNXT_ULP_SESSION_TYPE_DEFAULT_NON_HA;
453 				BNXT_TF_DBG(INFO, "Hot upgrade disabled.\n");
454 			}
455 		}
456 
457 		bnxt_ulp_vxlan_ip_port_set(ulp_ctx, info[i].vxlan_ip_port);
458 		bnxt_ulp_vxlan_port_set(ulp_ctx, info[i].vxlan_port);
459 		bnxt_ulp_ecpri_udp_port_set(ulp_ctx, info[i].ecpri_udp_port);
460 
461 		/* set the shared session support from firmware */
462 		fw = info[i].upgrade_fw_update;
463 		if (ULP_HIGH_AVAIL_IS_ENABLED(ulp_ctx->cfg_data->ulp_flags) &&
464 		    bnxt_ulp_multi_shared_session_support_set(bp, dev_id, fw)) {
465 			BNXT_TF_DBG(ERR,
466 				    "Unable to get shared session support\n");
467 			return -EINVAL;
468 		}
469 		bnxt_ulp_ha_reg_set(ulp_ctx, info[i].ha_reg_state,
470 				    info[i].ha_reg_cnt);
471 		ulp_ctx->cfg_data->ha_pool_id = info[i].ha_pool_id;
472 	}
473 	if (!found) {
474 		BNXT_TF_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n",
475 			    app_id, dev_id);
476 		ulp_ctx->cfg_data->ulp_flags |= BNXT_ULP_APP_DEV_UNSUPPORTED;
477 		return -EINVAL;
478 	}
479 
480 	return 0;
481 }
482 
483 /* Function to retrieve the vxlan_ip (ecpri) port from the context. */
484 int
485 bnxt_ulp_ecpri_udp_port_set(struct bnxt_ulp_context *ulp_ctx,
486 			   uint32_t ecpri_udp_port)
487 {
488 	if (!ulp_ctx || !ulp_ctx->cfg_data)
489 		return -EINVAL;
490 
491 	ulp_ctx->cfg_data->ecpri_udp_port = ecpri_udp_port;
492 
493 	return 0;
494 }
495 
496 /* Function to retrieve the vxlan_ip (ecpri) port from the context. */
497 unsigned int
498 bnxt_ulp_ecpri_udp_port_get(struct bnxt_ulp_context *ulp_ctx)
499 {
500 	if (!ulp_ctx || !ulp_ctx->cfg_data)
501 		return 0;
502 
503 	return (unsigned int)ulp_ctx->cfg_data->ecpri_udp_port;
504 }
505 
506 /* Function to set the number for vxlan_ip (custom vxlan) port into the context */
507 int
508 bnxt_ulp_vxlan_ip_port_set(struct bnxt_ulp_context *ulp_ctx,
509 			   uint32_t vxlan_ip_port)
510 {
511 	if (!ulp_ctx || !ulp_ctx->cfg_data)
512 		return -EINVAL;
513 
514 	ulp_ctx->cfg_data->vxlan_ip_port = vxlan_ip_port;
515 
516 	return 0;
517 }
518 
519 /* Function to retrieve the vxlan_ip (custom vxlan) port from the context. */
520 unsigned int
521 bnxt_ulp_vxlan_ip_port_get(struct bnxt_ulp_context *ulp_ctx)
522 {
523 	if (!ulp_ctx || !ulp_ctx->cfg_data)
524 		return 0;
525 
526 	return (unsigned int)ulp_ctx->cfg_data->vxlan_ip_port;
527 }
528 
529 /* Function to set the number for vxlan port into the context */
530 int
531 bnxt_ulp_vxlan_port_set(struct bnxt_ulp_context *ulp_ctx,
532 			uint32_t vxlan_port)
533 {
534 	if (!ulp_ctx || !ulp_ctx->cfg_data)
535 		return -EINVAL;
536 
537 	ulp_ctx->cfg_data->vxlan_port = vxlan_port;
538 
539 	return 0;
540 }
541 
542 /* Function to retrieve the vxlan port from the context. */
543 unsigned int
544 bnxt_ulp_vxlan_port_get(struct bnxt_ulp_context *ulp_ctx)
545 {
546 	if (!ulp_ctx || !ulp_ctx->cfg_data)
547 		return 0;
548 
549 	return (unsigned int)ulp_ctx->cfg_data->vxlan_port;
550 }
551 
552 static inline uint32_t
553 bnxt_ulp_session_idx_get(enum bnxt_ulp_session_type session_type) {
554 	if (session_type & BNXT_ULP_SESSION_TYPE_SHARED)
555 		return 1;
556 	else if (session_type & BNXT_ULP_SESSION_TYPE_SHARED_WC)
557 		return 2;
558 	return 0;
559 }
560 
561 /* Function to set the tfp session details in session */
562 static int32_t
563 bnxt_ulp_session_tfp_set(struct bnxt_ulp_session_state *session,
564 			 enum bnxt_ulp_session_type session_type,
565 			 struct tf *tfp)
566 {
567 	uint32_t idx = bnxt_ulp_session_idx_get(session_type);
568 	int32_t rc = 0;
569 
570 	if (!session->session_opened[idx]) {
571 		session->g_tfp[idx] = rte_zmalloc("bnxt_ulp_session_tfp",
572 						  sizeof(struct tf), 0);
573 		if (!session->g_tfp[idx]) {
574 			BNXT_TF_DBG(DEBUG, "Failed to alloc session tfp\n");
575 			return -ENOMEM;
576 		}
577 		session->g_tfp[idx]->session  = tfp->session;
578 		session->session_opened[idx] = 1;
579 	}
580 	return rc;
581 }
582 
583 /* Function to get the tfp session details in session */
584 static struct tf_session_info *
585 bnxt_ulp_session_tfp_get(struct bnxt_ulp_session_state *session,
586 			 enum bnxt_ulp_session_type session_type)
587 {
588 	uint32_t idx = bnxt_ulp_session_idx_get(session_type);
589 
590 	if (session->session_opened[idx])
591 		return session->g_tfp[idx]->session;
592 	return NULL;
593 }
594 
595 static uint32_t
596 bnxt_ulp_session_is_open(struct bnxt_ulp_session_state *session,
597 			 enum bnxt_ulp_session_type session_type)
598 {
599 	uint32_t idx = bnxt_ulp_session_idx_get(session_type);
600 
601 	return session->session_opened[idx];
602 }
603 
604 /* Function to reset the tfp session details in session */
605 static void
606 bnxt_ulp_session_tfp_reset(struct bnxt_ulp_session_state *session,
607 			   enum bnxt_ulp_session_type session_type)
608 {
609 	uint32_t idx = bnxt_ulp_session_idx_get(session_type);
610 
611 	if (session->session_opened[idx]) {
612 		session->session_opened[idx] = 0;
613 		rte_free(session->g_tfp[idx]);
614 		session->g_tfp[idx] = NULL;
615 	}
616 }
617 
618 static void
619 ulp_ctx_shared_session_close(struct bnxt *bp,
620 			     enum bnxt_ulp_session_type session_type,
621 			     struct bnxt_ulp_session_state *session)
622 {
623 	struct tf *tfp;
624 	int32_t rc;
625 
626 	tfp = bnxt_ulp_cntxt_tfp_get(bp->ulp_ctx, session_type);
627 	if (!tfp) {
628 		/*
629 		 * Log it under debug since this is likely a case of the
630 		 * shared session not being created.  For example, a failed
631 		 * initialization.
632 		 */
633 		BNXT_TF_DBG(DEBUG, "Failed to get shared tfp on close.\n");
634 		return;
635 	}
636 	rc = tf_close_session(tfp);
637 	if (rc)
638 		BNXT_TF_DBG(ERR, "Failed to close the shared session rc=%d.\n",
639 			    rc);
640 	(void)bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, session_type, NULL);
641 	bnxt_ulp_session_tfp_reset(session, session_type);
642 }
643 
644 static int32_t
645 ulp_ctx_mh_get_session_name(struct bnxt *bp,
646 			    struct tf_open_session_parms *parms)
647 {
648 	int32_t	rc = 0;
649 	unsigned int domain = 0, bus = 0, slot = 0, device = 0;
650 	rc = sscanf(parms->ctrl_chan_name,
651 		    "%x:%x:%x.%u",
652 		    &domain,
653 		    &bus,
654 		    &slot,
655 		    &device);
656 	if (rc != 4) {
657 		/* PCI Domain not provided (optional in DPDK), thus we
658 		 * force domain to 0 and recheck.
659 		 */
660 		domain = 0;
661 		/* Check parsing of bus/slot/device */
662 		rc = sscanf(parms->ctrl_chan_name,
663 			    "%x:%x.%u",
664 			    &bus,
665 			    &slot,
666 			    &device);
667 		if (rc != 3) {
668 			BNXT_TF_DBG(DEBUG,
669 				    "Failed to scan device ctrl_chan_name\n");
670 			return -EINVAL;
671 		}
672 	}
673 
674 	/* change domain name for multi-host system */
675 	domain = domain + (0xf & bp->multi_host_pf_pci_id);
676 	sprintf(parms->ctrl_chan_name,
677 		"%x:%x:%x.%u",
678 		domain,
679 		bus,
680 		slot,
681 		device);
682 	BNXT_TF_DBG(DEBUG,
683 		    "Session name for Multi-Host: ctrl_chan_name:%s\n", parms->ctrl_chan_name);
684 	return 0;
685 }
686 
687 static int32_t
688 ulp_ctx_shared_session_open(struct bnxt *bp,
689 			    enum bnxt_ulp_session_type session_type,
690 			    struct bnxt_ulp_session_state *session)
691 {
692 	struct rte_eth_dev *ethdev = bp->eth_dev;
693 	struct tf_session_resources *resources;
694 	struct tf_open_session_parms parms;
695 	size_t nb;
696 	uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST;
697 	int32_t	rc = 0;
698 	uint8_t app_id;
699 	struct tf *tfp;
700 	uint8_t pool_id;
701 
702 	memset(&parms, 0, sizeof(parms));
703 	rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id,
704 					  parms.ctrl_chan_name);
705 	if (rc) {
706 		BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n",
707 			    ethdev->data->port_id, rc);
708 		return rc;
709 	}
710 
711 	/* On multi-host system, adjust ctrl_chan_name to avoid confliction */
712 	if (BNXT_MH(bp)) {
713 		rc = ulp_ctx_mh_get_session_name(bp, &parms);
714 		if (rc)
715 			return rc;
716 	}
717 
718 	resources = &parms.resources;
719 
720 	/*
721 	 * Need to account for size of ctrl_chan_name and 1 extra for Null
722 	 * terminator
723 	 */
724 	nb = sizeof(parms.ctrl_chan_name) - strlen(parms.ctrl_chan_name) - 1;
725 
726 	/*
727 	 * Build the ctrl_chan_name with shared token.
728 	 * When HA is enabled, the WC TCAM needs extra management by the core,
729 	 * so add the wc_tcam string to the control channel.
730 	 */
731 	pool_id = bp->ulp_ctx->cfg_data->ha_pool_id;
732 	if (!bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) {
733 		if (bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx))
734 			strncat(parms.ctrl_chan_name, "-tf_shared-wc_tcam", nb);
735 		else
736 			strncat(parms.ctrl_chan_name, "-tf_shared", nb);
737 	} else if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) {
738 		if (session_type == BNXT_ULP_SESSION_TYPE_SHARED) {
739 			strncat(parms.ctrl_chan_name, "-tf_shared", nb);
740 		} else if (session_type == BNXT_ULP_SESSION_TYPE_SHARED_WC) {
741 			char session_pool_name[64];
742 
743 			sprintf(session_pool_name, "-tf_shared-pool%d",
744 				pool_id);
745 
746 			if (nb >= strlen(session_pool_name)) {
747 				strncat(parms.ctrl_chan_name, session_pool_name, nb);
748 			} else {
749 				BNXT_TF_DBG(ERR, "No space left for session_name\n");
750 				return -EINVAL;
751 			}
752 		}
753 	}
754 
755 	rc = bnxt_ulp_tf_shared_session_resources_get(bp->ulp_ctx, session_type,
756 						      resources);
757 	if (rc)
758 		return rc;
759 
760 	rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id);
761 	if (rc) {
762 		BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
763 		return -EINVAL;
764 	}
765 
766 	rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id);
767 	if (rc) {
768 		BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n");
769 		return rc;
770 	}
771 
772 	tfp = bnxt_ulp_bp_tfp_get(bp, session_type);
773 	parms.device_type = bnxt_ulp_cntxt_convert_dev_id(ulp_dev_id);
774 	parms.bp = bp;
775 
776 	/*
777 	 * Open the session here, but the collect the resources during the
778 	 * mapper initialization.
779 	 */
780 	rc = tf_open_session(tfp, &parms);
781 	if (rc)
782 		return rc;
783 
784 	if (parms.shared_session_creator)
785 		BNXT_TF_DBG(DEBUG, "Shared session creator.\n");
786 	else
787 		BNXT_TF_DBG(DEBUG, "Shared session attached.\n");
788 
789 	/* Save the shared session in global data */
790 	rc = bnxt_ulp_session_tfp_set(session, session_type, tfp);
791 	if (rc) {
792 		BNXT_TF_DBG(ERR, "Failed to add shared tfp to session\n");
793 		return rc;
794 	}
795 
796 	rc = bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, session_type, tfp);
797 	if (rc) {
798 		BNXT_TF_DBG(ERR, "Failed to add shared tfp to ulp (%d)\n", rc);
799 		return rc;
800 	}
801 
802 	return rc;
803 }
804 
805 static int32_t
806 ulp_ctx_shared_session_attach(struct bnxt *bp,
807 			      struct bnxt_ulp_session_state *ses)
808 {
809 	enum bnxt_ulp_session_type type;
810 	struct tf *tfp;
811 	int32_t rc = 0;
812 
813 	/* Simply return success if shared session not enabled */
814 	if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) {
815 		type = BNXT_ULP_SESSION_TYPE_SHARED;
816 		tfp = bnxt_ulp_bp_tfp_get(bp, type);
817 		tfp->session = bnxt_ulp_session_tfp_get(ses, type);
818 		rc = ulp_ctx_shared_session_open(bp, type, ses);
819 	}
820 
821 	if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) {
822 		type = BNXT_ULP_SESSION_TYPE_SHARED_WC;
823 		tfp = bnxt_ulp_bp_tfp_get(bp, type);
824 		tfp->session = bnxt_ulp_session_tfp_get(ses, type);
825 		rc = ulp_ctx_shared_session_open(bp, type, ses);
826 	}
827 
828 	if (!rc)
829 		bnxt_ulp_cntxt_num_shared_clients_set(bp->ulp_ctx, true);
830 
831 	return rc;
832 }
833 
834 static void
835 ulp_ctx_shared_session_detach(struct bnxt *bp)
836 {
837 	struct tf *tfp;
838 
839 	if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) {
840 		tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_SHARED);
841 		if (tfp->session) {
842 			tf_close_session(tfp);
843 			tfp->session = NULL;
844 		}
845 	}
846 	if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) {
847 		tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_SHARED_WC);
848 		if (tfp->session) {
849 			tf_close_session(tfp);
850 			tfp->session = NULL;
851 		}
852 	}
853 	bnxt_ulp_cntxt_num_shared_clients_set(bp->ulp_ctx, false);
854 }
855 
856 /*
857  * Initialize an ULP session.
858  * An ULP session will contain all the resources needed to support rte flow
859  * offloads. A session is initialized as part of rte_eth_device start.
860  * A single vswitch instance can have multiple uplinks which means
861  * rte_eth_device start will be called for each of these devices.
862  * ULP session manager will make sure that a single ULP session is only
863  * initialized once. Apart from this, it also initializes MARK database,
864  * EEM table & flow database. ULP session manager also manages a list of
865  * all opened ULP sessions.
866  */
867 static int32_t
868 ulp_ctx_session_open(struct bnxt *bp,
869 		     struct bnxt_ulp_session_state *session)
870 {
871 	struct rte_eth_dev		*ethdev = bp->eth_dev;
872 	int32_t				rc = 0;
873 	struct tf_open_session_parms	params;
874 	struct tf_session_resources	*resources;
875 	uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST;
876 	uint8_t app_id;
877 	struct tf *tfp;
878 
879 	memset(&params, 0, sizeof(params));
880 
881 	rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id,
882 					  params.ctrl_chan_name);
883 	if (rc) {
884 		BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n",
885 			    ethdev->data->port_id, rc);
886 		return rc;
887 	}
888 
889 	/* On multi-host system, adjust ctrl_chan_name to avoid confliction */
890 	if (BNXT_MH(bp)) {
891 		rc = ulp_ctx_mh_get_session_name(bp, &params);
892 		if (rc)
893 			return rc;
894 	}
895 
896 	rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id);
897 	if (rc) {
898 		BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
899 		return -EINVAL;
900 	}
901 
902 	rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id);
903 	if (rc) {
904 		BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n");
905 		return rc;
906 	}
907 
908 	params.device_type = bnxt_ulp_cntxt_convert_dev_id(ulp_dev_id);
909 	resources = &params.resources;
910 	rc = bnxt_ulp_tf_resources_get(bp->ulp_ctx,
911 				       BNXT_ULP_SESSION_TYPE_DEFAULT,
912 				       resources);
913 	if (rc)
914 		return rc;
915 
916 	params.bp = bp;
917 
918 	tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT);
919 	rc = tf_open_session(tfp, &params);
920 	if (rc) {
921 		BNXT_TF_DBG(ERR, "Failed to open TF session - %s, rc = %d\n",
922 			    params.ctrl_chan_name, rc);
923 		return -EINVAL;
924 	}
925 	rc = bnxt_ulp_session_tfp_set(session,
926 				      BNXT_ULP_SESSION_TYPE_DEFAULT, tfp);
927 	if (rc) {
928 		BNXT_TF_DBG(ERR, "Failed to set TF session - %s, rc = %d\n",
929 			    params.ctrl_chan_name, rc);
930 		return -EINVAL;
931 	}
932 	return rc;
933 }
934 
935 /*
936  * Close the ULP session.
937  * It takes the ulp context pointer.
938  */
939 static void
940 ulp_ctx_session_close(struct bnxt *bp,
941 		      struct bnxt_ulp_session_state *session)
942 {
943 	struct tf *tfp;
944 
945 	/* close the session in the hardware */
946 	if (bnxt_ulp_session_is_open(session, BNXT_ULP_SESSION_TYPE_DEFAULT)) {
947 		tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT);
948 		tf_close_session(tfp);
949 	}
950 	bnxt_ulp_session_tfp_reset(session, BNXT_ULP_SESSION_TYPE_DEFAULT);
951 }
952 
953 static void
954 bnxt_init_tbl_scope_parms(struct bnxt *bp,
955 			  struct tf_alloc_tbl_scope_parms *params)
956 {
957 	struct bnxt_ulp_device_params	*dparms;
958 	uint32_t dev_id;
959 	int rc;
960 
961 	rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id);
962 	if (rc)
963 		/* TBD: For now, just use default. */
964 		dparms = 0;
965 	else
966 		dparms = bnxt_ulp_device_params_get(dev_id);
967 
968 	/*
969 	 * Set the flush timer for EEM entries. The value is in 100ms intervals,
970 	 * so 100 is 10s.
971 	 */
972 	params->hw_flow_cache_flush_timer = 100;
973 
974 	if (!dparms) {
975 		params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY;
976 		params->rx_max_action_entry_sz_in_bits =
977 			BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY;
978 		params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM;
979 		params->rx_num_flows_in_k = BNXT_ULP_RX_NUM_FLOWS;
980 
981 		params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY;
982 		params->tx_max_action_entry_sz_in_bits =
983 			BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY;
984 		params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM;
985 		params->tx_num_flows_in_k = BNXT_ULP_TX_NUM_FLOWS;
986 	} else {
987 		params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY;
988 		params->rx_max_action_entry_sz_in_bits =
989 			BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY;
990 		params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM;
991 		params->rx_num_flows_in_k =
992 			dparms->ext_flow_db_num_entries / 1024;
993 
994 		params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY;
995 		params->tx_max_action_entry_sz_in_bits =
996 			BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY;
997 		params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM;
998 		params->tx_num_flows_in_k =
999 			dparms->ext_flow_db_num_entries / 1024;
1000 	}
1001 	BNXT_TF_DBG(INFO, "Table Scope initialized with %uK flows.\n",
1002 		    params->rx_num_flows_in_k);
1003 }
1004 
1005 /* Initialize Extended Exact Match host memory. */
1006 static int32_t
1007 ulp_eem_tbl_scope_init(struct bnxt *bp)
1008 {
1009 	struct tf_alloc_tbl_scope_parms params = {0};
1010 	struct bnxt_ulp_device_params *dparms;
1011 	enum bnxt_ulp_flow_mem_type mtype;
1012 	uint32_t dev_id;
1013 	struct tf *tfp;
1014 	int rc;
1015 
1016 	/* Get the dev specific number of flows that needed to be supported. */
1017 	if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) {
1018 		BNXT_TF_DBG(ERR, "Invalid device id\n");
1019 		return -EINVAL;
1020 	}
1021 
1022 	dparms = bnxt_ulp_device_params_get(dev_id);
1023 	if (!dparms) {
1024 		BNXT_TF_DBG(ERR, "could not fetch the device params\n");
1025 		return -ENODEV;
1026 	}
1027 
1028 	if (bnxt_ulp_cntxt_mem_type_get(bp->ulp_ctx, &mtype))
1029 		return -EINVAL;
1030 	if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) {
1031 		BNXT_TF_DBG(INFO, "Table Scope alloc is not required\n");
1032 		return 0;
1033 	}
1034 
1035 	bnxt_init_tbl_scope_parms(bp, &params);
1036 	tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT);
1037 	rc = tf_alloc_tbl_scope(tfp, &params);
1038 	if (rc) {
1039 		BNXT_TF_DBG(ERR, "Unable to allocate eem table scope rc = %d\n",
1040 			    rc);
1041 		return rc;
1042 	}
1043 
1044 	rc = bnxt_ulp_cntxt_tbl_scope_id_set(bp->ulp_ctx, params.tbl_scope_id);
1045 	if (rc) {
1046 		BNXT_TF_DBG(ERR, "Unable to set table scope id\n");
1047 		return rc;
1048 	}
1049 
1050 	return 0;
1051 }
1052 
1053 /* Free Extended Exact Match host memory */
1054 static int32_t
1055 ulp_eem_tbl_scope_deinit(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx)
1056 {
1057 	struct tf_free_tbl_scope_parms	params = {0};
1058 	struct tf			*tfp;
1059 	int32_t				rc = 0;
1060 	struct bnxt_ulp_device_params *dparms;
1061 	enum bnxt_ulp_flow_mem_type mtype;
1062 	uint32_t dev_id;
1063 
1064 	if (!ulp_ctx || !ulp_ctx->cfg_data)
1065 		return -EINVAL;
1066 
1067 	tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SESSION_TYPE_DEFAULT);
1068 	if (!tfp) {
1069 		BNXT_TF_DBG(ERR, "Failed to get the truflow pointer\n");
1070 		return -EINVAL;
1071 	}
1072 
1073 	/* Get the dev specific number of flows that needed to be supported. */
1074 	if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) {
1075 		BNXT_TF_DBG(ERR, "Invalid device id\n");
1076 		return -EINVAL;
1077 	}
1078 
1079 	dparms = bnxt_ulp_device_params_get(dev_id);
1080 	if (!dparms) {
1081 		BNXT_TF_DBG(ERR, "could not fetch the device params\n");
1082 		return -ENODEV;
1083 	}
1084 
1085 	if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype))
1086 		return -EINVAL;
1087 	if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) {
1088 		BNXT_TF_DBG(INFO, "Table Scope free is not required\n");
1089 		return 0;
1090 	}
1091 
1092 	rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &params.tbl_scope_id);
1093 	if (rc) {
1094 		BNXT_TF_DBG(ERR, "Failed to get the table scope id\n");
1095 		return -EINVAL;
1096 	}
1097 
1098 	rc = tf_free_tbl_scope(tfp, &params);
1099 	if (rc) {
1100 		BNXT_TF_DBG(ERR, "Unable to free table scope\n");
1101 		return -EINVAL;
1102 	}
1103 	return rc;
1104 }
1105 
1106 /* The function to free and deinit the ulp context data. */
1107 static int32_t
1108 ulp_ctx_deinit(struct bnxt *bp,
1109 	       struct bnxt_ulp_session_state *session)
1110 {
1111 	/* close the tf session */
1112 	ulp_ctx_session_close(bp, session);
1113 
1114 	/* The shared session must be closed last. */
1115 	if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx))
1116 		ulp_ctx_shared_session_close(bp, BNXT_ULP_SESSION_TYPE_SHARED,
1117 					     session);
1118 
1119 	if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx))
1120 		ulp_ctx_shared_session_close(bp,
1121 					     BNXT_ULP_SESSION_TYPE_SHARED_WC,
1122 					     session);
1123 
1124 	bnxt_ulp_cntxt_num_shared_clients_set(bp->ulp_ctx, false);
1125 
1126 	/* Free the contents */
1127 	if (session->cfg_data) {
1128 		rte_free(session->cfg_data);
1129 		bp->ulp_ctx->cfg_data = NULL;
1130 		session->cfg_data = NULL;
1131 	}
1132 	return 0;
1133 }
1134 
1135 /* The function to allocate and initialize the ulp context data. */
1136 static int32_t
1137 ulp_ctx_init(struct bnxt *bp,
1138 	     struct bnxt_ulp_session_state *session)
1139 {
1140 	struct bnxt_ulp_data	*ulp_data;
1141 	int32_t			rc = 0;
1142 	enum bnxt_ulp_device_id devid;
1143 	enum bnxt_ulp_session_type stype;
1144 	struct tf *tfp;
1145 
1146 	/* Initialize the context entries list */
1147 	bnxt_ulp_cntxt_list_init();
1148 
1149 	/* Add the context to the context entries list */
1150 	rc = bnxt_ulp_cntxt_list_add(bp->ulp_ctx);
1151 	if (rc) {
1152 		BNXT_TF_DBG(ERR, "Failed to add the context list entry\n");
1153 		return -ENOMEM;
1154 	}
1155 
1156 	/* Allocate memory to hold ulp context data. */
1157 	ulp_data = rte_zmalloc("bnxt_ulp_data",
1158 			       sizeof(struct bnxt_ulp_data), 0);
1159 	if (!ulp_data) {
1160 		BNXT_TF_DBG(ERR, "Failed to allocate memory for ulp data\n");
1161 		return -ENOMEM;
1162 	}
1163 
1164 	/* Increment the ulp context data reference count usage. */
1165 	bp->ulp_ctx->cfg_data = ulp_data;
1166 	session->cfg_data = ulp_data;
1167 	ulp_data->ref_cnt++;
1168 	ulp_data->ulp_flags |= BNXT_ULP_VF_REP_ENABLED;
1169 
1170 	rc = bnxt_ulp_devid_get(bp, &devid);
1171 	if (rc) {
1172 		BNXT_TF_DBG(ERR, "Unable to determine device for ULP init.\n");
1173 		goto error_deinit;
1174 	}
1175 
1176 	rc = bnxt_ulp_cntxt_dev_id_set(bp->ulp_ctx, devid);
1177 	if (rc) {
1178 		BNXT_TF_DBG(ERR, "Unable to set device for ULP init.\n");
1179 		goto error_deinit;
1180 	}
1181 
1182 	rc = bnxt_ulp_cntxt_app_id_set(bp->ulp_ctx, bp->app_id);
1183 	if (rc) {
1184 		BNXT_TF_DBG(ERR, "Unable to set app_id for ULP init.\n");
1185 		goto error_deinit;
1186 	}
1187 	BNXT_TF_DBG(DEBUG, "Ulp initialized with app id %d\n", bp->app_id);
1188 
1189 	rc = bnxt_ulp_cntxt_app_caps_init(bp, bp->app_id, devid);
1190 	if (rc) {
1191 		BNXT_TF_DBG(ERR, "Unable to set caps for app(%x)/dev(%x)\n",
1192 			    bp->app_id, devid);
1193 		goto error_deinit;
1194 	}
1195 
1196 	if (BNXT_TESTPMD_EN(bp)) {
1197 		ulp_data->ulp_flags &= ~BNXT_ULP_VF_REP_ENABLED;
1198 		BNXT_TF_DBG(ERR, "Enabled Testpmd forward mode\n");
1199 	}
1200 
1201 	/*
1202 	 * Shared session must be created before first regular session but after
1203 	 * the ulp_ctx is valid.
1204 	 */
1205 	if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) {
1206 		rc = ulp_ctx_shared_session_open(bp,
1207 						 BNXT_ULP_SESSION_TYPE_SHARED,
1208 						 session);
1209 		if (rc) {
1210 			BNXT_TF_DBG(ERR, "Unable to open shared session (%d)\n",
1211 				    rc);
1212 			goto error_deinit;
1213 		}
1214 	}
1215 
1216 	/* Multiple session support */
1217 	if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) {
1218 		stype = BNXT_ULP_SESSION_TYPE_SHARED_WC;
1219 		rc = ulp_ctx_shared_session_open(bp, stype, session);
1220 		if (rc) {
1221 			BNXT_TF_DBG(ERR,
1222 				    "Unable to open shared wc session (%d)\n",
1223 				    rc);
1224 			goto error_deinit;
1225 		}
1226 	}
1227 	bnxt_ulp_cntxt_num_shared_clients_set(bp->ulp_ctx, true);
1228 
1229 	/* Open the ulp session. */
1230 	rc = ulp_ctx_session_open(bp, session);
1231 	if (rc)
1232 		goto error_deinit;
1233 
1234 	tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT);
1235 	bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, BNXT_ULP_SESSION_TYPE_DEFAULT, tfp);
1236 	return rc;
1237 
1238 error_deinit:
1239 	session->session_opened[BNXT_ULP_SESSION_TYPE_DEFAULT] = 1;
1240 	(void)ulp_ctx_deinit(bp, session);
1241 	return rc;
1242 }
1243 
1244 /* The function to initialize ulp dparms with devargs */
1245 static int32_t
1246 ulp_dparms_init(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx)
1247 {
1248 	struct bnxt_ulp_device_params *dparms;
1249 	uint32_t dev_id = BNXT_ULP_DEVICE_ID_LAST;
1250 
1251 	if (!bp->max_num_kflows) {
1252 		/* Defaults to Internal */
1253 		bnxt_ulp_cntxt_mem_type_set(ulp_ctx,
1254 					    BNXT_ULP_FLOW_MEM_TYPE_INT);
1255 		return 0;
1256 	}
1257 
1258 	/* The max_num_kflows were set, so move to external */
1259 	if (bnxt_ulp_cntxt_mem_type_set(ulp_ctx, BNXT_ULP_FLOW_MEM_TYPE_EXT))
1260 		return -EINVAL;
1261 
1262 	if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
1263 		BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
1264 		return -EINVAL;
1265 	}
1266 
1267 	dparms = bnxt_ulp_device_params_get(dev_id);
1268 	if (!dparms) {
1269 		BNXT_TF_DBG(DEBUG, "Failed to get device parms\n");
1270 		return -EINVAL;
1271 	}
1272 
1273 	/* num_flows = max_num_kflows * 1024 */
1274 	dparms->ext_flow_db_num_entries = bp->max_num_kflows * 1024;
1275 	/* GFID =  2 * num_flows */
1276 	dparms->mark_db_gfid_entries = dparms->ext_flow_db_num_entries * 2;
1277 	BNXT_TF_DBG(DEBUG, "Set the number of flows = %" PRIu64 "\n",
1278 		    dparms->ext_flow_db_num_entries);
1279 
1280 	return 0;
1281 }
1282 
1283 /* The function to initialize bp flags with truflow features */
1284 static int32_t
1285 ulp_dparms_dev_port_intf_update(struct bnxt *bp,
1286 				struct bnxt_ulp_context *ulp_ctx)
1287 {
1288 	enum bnxt_ulp_flow_mem_type mtype;
1289 
1290 	if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype))
1291 		return -EINVAL;
1292 	/* Update the bp flag with gfid flag */
1293 	if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT)
1294 		bp->flags |= BNXT_FLAG_GFID_ENABLE;
1295 
1296 	return 0;
1297 }
1298 
1299 static int32_t
1300 ulp_ctx_attach(struct bnxt *bp,
1301 	       struct bnxt_ulp_session_state *session)
1302 {
1303 	int32_t rc = 0;
1304 	uint32_t flags, dev_id = BNXT_ULP_DEVICE_ID_LAST;
1305 	struct tf *tfp;
1306 	uint8_t app_id;
1307 
1308 	/* Increment the ulp context data reference count usage. */
1309 	bp->ulp_ctx->cfg_data = session->cfg_data;
1310 	bp->ulp_ctx->cfg_data->ref_cnt++;
1311 
1312 	/* update the session details in bnxt tfp */
1313 	tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT);
1314 	tfp->session = bnxt_ulp_session_tfp_get(session,
1315 						BNXT_ULP_SESSION_TYPE_DEFAULT);
1316 
1317 	/* Add the context to the context entries list */
1318 	rc = bnxt_ulp_cntxt_list_add(bp->ulp_ctx);
1319 	if (rc) {
1320 		BNXT_TF_DBG(ERR, "Failed to add the context list entry\n");
1321 		return -EINVAL;
1322 	}
1323 
1324 	/*
1325 	 * The supported flag will be set during the init. Use it now to
1326 	 * know if we should go through the attach.
1327 	 */
1328 	rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id);
1329 	if (rc) {
1330 		BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
1331 		return -EINVAL;
1332 	}
1333 
1334 	rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id);
1335 	if (rc) {
1336 		BNXT_TF_DBG(ERR, "Unable do get the dev_id.\n");
1337 		return -EINVAL;
1338 	}
1339 
1340 	flags = bp->ulp_ctx->cfg_data->ulp_flags;
1341 	if (ULP_APP_DEV_UNSUPPORTED_ENABLED(flags)) {
1342 		BNXT_TF_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n",
1343 			    app_id, dev_id);
1344 		return -EINVAL;
1345 	}
1346 
1347 	/* Create a TF Client */
1348 	rc = ulp_ctx_session_open(bp, session);
1349 	if (rc) {
1350 		PMD_DRV_LOG(ERR, "Failed to open ctxt session, rc:%d\n", rc);
1351 		tfp->session = NULL;
1352 		return rc;
1353 	}
1354 	tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT);
1355 	bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, BNXT_ULP_SESSION_TYPE_DEFAULT, tfp);
1356 	return rc;
1357 }
1358 
1359 static void
1360 ulp_ctx_detach(struct bnxt *bp)
1361 {
1362 	struct tf *tfp;
1363 
1364 	tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT);
1365 	if (tfp->session) {
1366 		tf_close_session(tfp);
1367 		tfp->session = NULL;
1368 	}
1369 }
1370 
1371 /*
1372  * Initialize the state of an ULP session.
1373  * If the state of an ULP session is not initialized, set it's state to
1374  * initialized. If the state is already initialized, do nothing.
1375  */
1376 static void
1377 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
1378 {
1379 	pthread_mutex_lock(&session->bnxt_ulp_mutex);
1380 
1381 	if (!session->bnxt_ulp_init) {
1382 		session->bnxt_ulp_init = true;
1383 		*init = false;
1384 	} else {
1385 		*init = true;
1386 	}
1387 
1388 	pthread_mutex_unlock(&session->bnxt_ulp_mutex);
1389 }
1390 
1391 /*
1392  * Check if an ULP session is already allocated for a specific PCI
1393  * domain & bus. If it is already allocated simply return the session
1394  * pointer, otherwise allocate a new session.
1395  */
1396 static struct bnxt_ulp_session_state *
1397 ulp_get_session(struct bnxt *bp, struct rte_pci_addr *pci_addr)
1398 {
1399 	struct bnxt_ulp_session_state *session;
1400 
1401 	/* if multi root capability is enabled, then ignore the pci bus id */
1402 	STAILQ_FOREACH(session, &bnxt_ulp_session_list, next) {
1403 		if (BNXT_MULTIROOT_EN(bp)) {
1404 			if (!memcmp(bp->dsn, session->dsn,
1405 				    sizeof(session->dsn))) {
1406 				return session;
1407 			}
1408 		} else if (session->pci_info.domain == pci_addr->domain &&
1409 			   session->pci_info.bus == pci_addr->bus) {
1410 			return session;
1411 		}
1412 	}
1413 	return NULL;
1414 }
1415 
1416 /*
1417  * Allocate and Initialize an ULP session and set it's state to INITIALIZED.
1418  * If it's already initialized simply return the already existing session.
1419  */
1420 static struct bnxt_ulp_session_state *
1421 ulp_session_init(struct bnxt *bp,
1422 		 bool *init)
1423 {
1424 	struct rte_pci_device		*pci_dev;
1425 	struct rte_pci_addr		*pci_addr;
1426 	struct bnxt_ulp_session_state	*session;
1427 	int rc = 0;
1428 
1429 	if (!bp)
1430 		return NULL;
1431 
1432 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
1433 	pci_addr = &pci_dev->addr;
1434 
1435 	pthread_mutex_lock(&bnxt_ulp_global_mutex);
1436 
1437 	session = ulp_get_session(bp, pci_addr);
1438 	if (!session) {
1439 		/* Not Found the session  Allocate a new one */
1440 		session = rte_zmalloc("bnxt_ulp_session",
1441 				      sizeof(struct bnxt_ulp_session_state),
1442 				      0);
1443 		if (!session) {
1444 			BNXT_TF_DBG(ERR,
1445 				    "Allocation failed for bnxt_ulp_session\n");
1446 			pthread_mutex_unlock(&bnxt_ulp_global_mutex);
1447 			return NULL;
1448 
1449 		} else {
1450 			/* Add it to the queue */
1451 			session->pci_info.domain = pci_addr->domain;
1452 			session->pci_info.bus = pci_addr->bus;
1453 			memcpy(session->dsn, bp->dsn, sizeof(session->dsn));
1454 			rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
1455 			if (rc) {
1456 				BNXT_TF_DBG(ERR, "mutex create failed\n");
1457 				pthread_mutex_unlock(&bnxt_ulp_global_mutex);
1458 				return NULL;
1459 			}
1460 			STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
1461 					   session, next);
1462 		}
1463 	}
1464 	ulp_context_initialized(session, init);
1465 	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
1466 	return session;
1467 }
1468 
1469 /*
1470  * When a device is closed, remove it's associated session from the global
1471  * session list.
1472  */
1473 static void
1474 ulp_session_deinit(struct bnxt_ulp_session_state *session)
1475 {
1476 	if (!session)
1477 		return;
1478 
1479 	if (!session->cfg_data) {
1480 		pthread_mutex_lock(&bnxt_ulp_global_mutex);
1481 		STAILQ_REMOVE(&bnxt_ulp_session_list, session,
1482 			      bnxt_ulp_session_state, next);
1483 		pthread_mutex_destroy(&session->bnxt_ulp_mutex);
1484 		rte_free(session);
1485 		pthread_mutex_unlock(&bnxt_ulp_global_mutex);
1486 	}
1487 }
1488 
1489 /*
1490  * Internal api to enable NAT feature.
1491  * Set set_flag to 1 to set the value or zero to reset the value.
1492  * returns 0 on success.
1493  */
1494 static int32_t
1495 bnxt_ulp_global_cfg_update(struct bnxt *bp,
1496 			   enum tf_dir dir,
1497 			   enum tf_global_config_type type,
1498 			   uint32_t offset,
1499 			   uint32_t value,
1500 			   uint32_t set_flag)
1501 {
1502 	uint32_t global_cfg = 0;
1503 	int rc;
1504 	struct tf_global_cfg_parms parms = { 0 };
1505 	struct tf *tfp;
1506 
1507 	/* Initialize the params */
1508 	parms.dir = dir,
1509 	parms.type = type,
1510 	parms.offset = offset,
1511 	parms.config = (uint8_t *)&global_cfg,
1512 	parms.config_sz_in_bytes = sizeof(global_cfg);
1513 
1514 	tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT);
1515 	rc = tf_get_global_cfg(tfp, &parms);
1516 	if (rc) {
1517 		BNXT_TF_DBG(ERR, "Failed to get global cfg 0x%x rc:%d\n",
1518 			    type, rc);
1519 		return rc;
1520 	}
1521 
1522 	if (set_flag)
1523 		global_cfg |= value;
1524 	else
1525 		global_cfg &= ~value;
1526 
1527 	/* SET the register RE_CFA_REG_ACT_TECT */
1528 	rc = tf_set_global_cfg(tfp, &parms);
1529 	if (rc) {
1530 		BNXT_TF_DBG(ERR, "Failed to set global cfg 0x%x rc:%d\n",
1531 			    type, rc);
1532 		return rc;
1533 	}
1534 	return rc;
1535 }
1536 
1537 /* Internal function to delete all the flows belonging to the given port */
1538 static void
1539 bnxt_ulp_flush_port_flows(struct bnxt *bp)
1540 {
1541 	uint16_t func_id;
1542 
1543 	/* it is assumed that port is either TVF or PF */
1544 	if (ulp_port_db_port_func_id_get(bp->ulp_ctx,
1545 					 bp->eth_dev->data->port_id,
1546 					 &func_id)) {
1547 		BNXT_TF_DBG(ERR, "Invalid argument\n");
1548 		return;
1549 	}
1550 	(void)ulp_flow_db_function_flow_flush(bp->ulp_ctx, func_id);
1551 }
1552 
1553 /* Internal function to delete the VFR default flows */
1554 static void
1555 bnxt_ulp_destroy_vfr_default_rules(struct bnxt *bp, bool global)
1556 {
1557 	struct bnxt_ulp_vfr_rule_info *info;
1558 	uint16_t port_id;
1559 	struct rte_eth_dev *vfr_eth_dev;
1560 	struct bnxt_representor *vfr_bp;
1561 
1562 	if (!BNXT_TRUFLOW_EN(bp) || rte_eth_dev_is_repr(bp->eth_dev))
1563 		return;
1564 
1565 	if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data)
1566 		return;
1567 
1568 	/* Delete default rules for all ports */
1569 	for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
1570 		info = &bp->ulp_ctx->cfg_data->vfr_rule_info[port_id];
1571 		if (!info->valid)
1572 			continue;
1573 
1574 		if (!global && info->parent_port_id !=
1575 		    bp->eth_dev->data->port_id)
1576 			continue;
1577 
1578 		/* Destroy the flows */
1579 		ulp_default_flow_destroy(bp->eth_dev, info->vfr_flow_id);
1580 		/* Clean up the tx action pointer */
1581 		vfr_eth_dev = &rte_eth_devices[port_id];
1582 		if (vfr_eth_dev) {
1583 			vfr_bp = vfr_eth_dev->data->dev_private;
1584 			vfr_bp->vfr_tx_cfa_action = 0;
1585 		}
1586 		memset(info, 0, sizeof(struct bnxt_ulp_vfr_rule_info));
1587 	}
1588 }
1589 
1590 /*
1591  * When a port is deinit'ed by dpdk. This function is called
1592  * and this function clears the ULP context and rest of the
1593  * infrastructure associated with it.
1594  */
1595 static void
1596 bnxt_ulp_deinit(struct bnxt *bp,
1597 		struct bnxt_ulp_session_state *session)
1598 {
1599 	bool ha_enabled;
1600 
1601 	if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data)
1602 		return;
1603 
1604 	ha_enabled = bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx);
1605 	if (ha_enabled &&
1606 	    bnxt_ulp_session_is_open(session, BNXT_ULP_SESSION_TYPE_DEFAULT)) {
1607 		int32_t rc = ulp_ha_mgr_close(bp->ulp_ctx);
1608 		if (rc)
1609 			BNXT_TF_DBG(ERR, "Failed to close HA (%d)\n", rc);
1610 	}
1611 
1612 	/* clean up default flows */
1613 	bnxt_ulp_destroy_df_rules(bp, true);
1614 
1615 	/* clean up default VFR flows */
1616 	bnxt_ulp_destroy_vfr_default_rules(bp, true);
1617 
1618 	/* clean up regular flows */
1619 	ulp_flow_db_flush_flows(bp->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR);
1620 
1621 	/* cleanup the eem table scope */
1622 	ulp_eem_tbl_scope_deinit(bp, bp->ulp_ctx);
1623 
1624 	/* cleanup the flow database */
1625 	ulp_flow_db_deinit(bp->ulp_ctx);
1626 
1627 	/* Delete the Mark database */
1628 	ulp_mark_db_deinit(bp->ulp_ctx);
1629 
1630 	/* cleanup the ulp mapper */
1631 	ulp_mapper_deinit(bp->ulp_ctx);
1632 
1633 	/* Delete the Flow Counter Manager */
1634 	ulp_fc_mgr_deinit(bp->ulp_ctx);
1635 
1636 	/* Delete the Port database */
1637 	ulp_port_db_deinit(bp->ulp_ctx);
1638 
1639 	/* Disable NAT feature */
1640 	(void)bnxt_ulp_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP,
1641 					 TF_TUNNEL_ENCAP_NAT,
1642 					 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
1643 
1644 	(void)bnxt_ulp_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP,
1645 					 TF_TUNNEL_ENCAP_NAT,
1646 					 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
1647 
1648 	/* free the flow db lock */
1649 	pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
1650 
1651 	if (ha_enabled)
1652 		ulp_ha_mgr_deinit(bp->ulp_ctx);
1653 
1654 	/* Delete the ulp context and tf session and free the ulp context */
1655 	ulp_ctx_deinit(bp, session);
1656 	BNXT_TF_DBG(DEBUG, "ulp ctx has been deinitialized\n");
1657 }
1658 
1659 /*
1660  * When a port is initialized by dpdk. This functions is called
1661  * and this function initializes the ULP context and rest of the
1662  * infrastructure associated with it.
1663  */
1664 static int32_t
1665 bnxt_ulp_init(struct bnxt *bp,
1666 	      struct bnxt_ulp_session_state *session)
1667 {
1668 	int rc;
1669 	uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST;
1670 
1671 	/* Allocate and Initialize the ulp context. */
1672 	rc = ulp_ctx_init(bp, session);
1673 	if (rc) {
1674 		BNXT_TF_DBG(ERR, "Failed to create the ulp context\n");
1675 		goto jump_to_error;
1676 	}
1677 
1678 	rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL);
1679 	if (rc) {
1680 		BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n");
1681 		goto jump_to_error;
1682 	}
1683 
1684 	/* Initialize ulp dparms with values devargs passed */
1685 	rc = ulp_dparms_init(bp, bp->ulp_ctx);
1686 	if (rc) {
1687 		BNXT_TF_DBG(ERR, "Failed to initialize the dparms\n");
1688 		goto jump_to_error;
1689 	}
1690 
1691 	/* create the port database */
1692 	rc = ulp_port_db_init(bp->ulp_ctx, bp->port_cnt);
1693 	if (rc) {
1694 		BNXT_TF_DBG(ERR, "Failed to create the port database\n");
1695 		goto jump_to_error;
1696 	}
1697 
1698 	/* Create the Mark database. */
1699 	rc = ulp_mark_db_init(bp->ulp_ctx);
1700 	if (rc) {
1701 		BNXT_TF_DBG(ERR, "Failed to create the mark database\n");
1702 		goto jump_to_error;
1703 	}
1704 
1705 	/* Create the flow database. */
1706 	rc = ulp_flow_db_init(bp->ulp_ctx);
1707 	if (rc) {
1708 		BNXT_TF_DBG(ERR, "Failed to create the flow database\n");
1709 		goto jump_to_error;
1710 	}
1711 
1712 	/* Create the eem table scope. */
1713 	rc = ulp_eem_tbl_scope_init(bp);
1714 	if (rc) {
1715 		BNXT_TF_DBG(ERR, "Failed to create the eem scope table\n");
1716 		goto jump_to_error;
1717 	}
1718 
1719 	rc = ulp_mapper_init(bp->ulp_ctx);
1720 	if (rc) {
1721 		BNXT_TF_DBG(ERR, "Failed to initialize ulp mapper\n");
1722 		goto jump_to_error;
1723 	}
1724 
1725 	rc = ulp_fc_mgr_init(bp->ulp_ctx);
1726 	if (rc) {
1727 		BNXT_TF_DBG(ERR, "Failed to initialize ulp flow counter mgr\n");
1728 		goto jump_to_error;
1729 	}
1730 
1731 	/*
1732 	 * Enable NAT feature. Set the global configuration register
1733 	 * Tunnel encap to enable NAT with the reuse of existing inner
1734 	 * L2 header smac and dmac
1735 	 */
1736 	rc = bnxt_ulp_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP,
1737 					TF_TUNNEL_ENCAP_NAT,
1738 					BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1);
1739 	if (rc) {
1740 		BNXT_TF_DBG(ERR, "Failed to set rx global configuration\n");
1741 		goto jump_to_error;
1742 	}
1743 
1744 	rc = bnxt_ulp_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP,
1745 					TF_TUNNEL_ENCAP_NAT,
1746 					BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1);
1747 	if (rc) {
1748 		BNXT_TF_DBG(ERR, "Failed to set tx global configuration\n");
1749 		goto jump_to_error;
1750 	}
1751 
1752 	if (bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx)) {
1753 		rc = ulp_ha_mgr_init(bp->ulp_ctx);
1754 		if (rc) {
1755 			BNXT_TF_DBG(ERR, "Failed to initialize HA %d\n", rc);
1756 			goto jump_to_error;
1757 		}
1758 		rc = ulp_ha_mgr_open(bp->ulp_ctx);
1759 		if (rc) {
1760 			BNXT_TF_DBG(ERR, "Failed to Process HA Open %d\n", rc);
1761 			goto jump_to_error;
1762 		}
1763 	}
1764 
1765 	rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id);
1766 	if (rc) {
1767 		BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n");
1768 		return rc;
1769 	}
1770 
1771 	if (ulp_dev_id == BNXT_ULP_DEVICE_ID_THOR) {
1772 		rc = bnxt_flow_meter_init(bp);
1773 		if (rc) {
1774 			BNXT_TF_DBG(ERR, "Failed to config meter\n");
1775 			goto jump_to_error;
1776 		}
1777 	}
1778 
1779 	BNXT_TF_DBG(DEBUG, "ulp ctx has been initialized\n");
1780 	return rc;
1781 
1782 jump_to_error:
1783 	bnxt_ulp_deinit(bp, session);
1784 	return rc;
1785 }
1786 
1787 static int
1788 ulp_cust_vxlan_alloc(struct bnxt *bp)
1789 {
1790 	int rc = 0;
1791 
1792 	if (ULP_APP_CUST_VXLAN_SUPPORT(bp->ulp_ctx)) {
1793 		rc = bnxt_tunnel_dst_port_alloc(bp,
1794 						bp->ulp_ctx->cfg_data->vxlan_port,
1795 					HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN);
1796 		if (rc)
1797 			BNXT_TF_DBG(ERR, "Failed to set global vxlan port\n");
1798 	}
1799 
1800 	if (ULP_APP_CUST_VXLAN_IP_SUPPORT(bp->ulp_ctx)) {
1801 		rc = bnxt_tunnel_dst_port_alloc(bp,
1802 						bp->ulp_ctx->cfg_data->vxlan_ip_port,
1803 					HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN_V4);
1804 		if (rc)
1805 			BNXT_TF_DBG(ERR, "Failed to set global custom vxlan_ip port\n");
1806 	}
1807 
1808 	return rc;
1809 }
1810 
1811 /*
1812  * When a port is initialized by dpdk. This functions sets up
1813  * the port specific details.
1814  */
1815 int32_t
1816 bnxt_ulp_port_init(struct bnxt *bp)
1817 {
1818 	struct bnxt_ulp_session_state *session;
1819 	bool initialized;
1820 	enum bnxt_ulp_device_id devid = BNXT_ULP_DEVICE_ID_LAST;
1821 	uint32_t ulp_flags;
1822 	int32_t rc = 0;
1823 
1824 	if (!BNXT_TRUFLOW_EN(bp)) {
1825 		BNXT_TF_DBG(DEBUG,
1826 			    "Skip ulp init for port: %d, TF is not enabled\n",
1827 			    bp->eth_dev->data->port_id);
1828 		return rc;
1829 	}
1830 
1831 	if (!BNXT_PF(bp) && !BNXT_VF_IS_TRUSTED(bp)) {
1832 		BNXT_TF_DBG(DEBUG,
1833 			    "Skip ulp init for port: %d, not a TVF or PF\n",
1834 			    bp->eth_dev->data->port_id);
1835 		return rc;
1836 	}
1837 
1838 	if (bp->ulp_ctx) {
1839 		BNXT_TF_DBG(DEBUG, "ulp ctx already allocated\n");
1840 		return rc;
1841 	}
1842 
1843 	bp->ulp_ctx = rte_zmalloc("bnxt_ulp_ctx",
1844 				  sizeof(struct bnxt_ulp_context), 0);
1845 	if (!bp->ulp_ctx) {
1846 		BNXT_TF_DBG(ERR, "Failed to allocate ulp ctx\n");
1847 		return -ENOMEM;
1848 	}
1849 
1850 	/*
1851 	 * Multiple uplink ports can be associated with a single vswitch.
1852 	 * Make sure only the port that is started first will initialize
1853 	 * the TF session.
1854 	 */
1855 	session = ulp_session_init(bp, &initialized);
1856 	if (!session) {
1857 		BNXT_TF_DBG(ERR, "Failed to initialize the tf session\n");
1858 		rc = -EIO;
1859 		goto jump_to_error;
1860 	}
1861 
1862 	if (initialized) {
1863 		/*
1864 		 * If ULP is already initialized for a specific domain then
1865 		 * simply assign the ulp context to this rte_eth_dev.
1866 		 */
1867 		rc = ulp_ctx_attach(bp, session);
1868 		if (rc) {
1869 			BNXT_TF_DBG(ERR, "Failed to attach the ulp context\n");
1870 			goto jump_to_error;
1871 		}
1872 
1873 		/*
1874 		 * Attach to the shared session, must be called after the
1875 		 * ulp_ctx_attach in order to ensure that ulp data is available
1876 		 * for attaching.
1877 		 */
1878 		rc = ulp_ctx_shared_session_attach(bp, session);
1879 		if (rc) {
1880 			BNXT_TF_DBG(ERR,
1881 				    "Failed attach to shared session (%d)", rc);
1882 			goto jump_to_error;
1883 		}
1884 	} else {
1885 		rc = bnxt_ulp_init(bp, session);
1886 		if (rc) {
1887 			BNXT_TF_DBG(ERR, "Failed to initialize the ulp init\n");
1888 			goto jump_to_error;
1889 		}
1890 	}
1891 
1892 	/* Update bnxt driver flags */
1893 	rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx);
1894 	if (rc) {
1895 		BNXT_TF_DBG(ERR, "Failed to update driver flags\n");
1896 		goto jump_to_error;
1897 	}
1898 
1899 	/* update the port database for the given interface */
1900 	rc = ulp_port_db_port_update(bp->ulp_ctx, bp->eth_dev);
1901 	if (rc) {
1902 		BNXT_TF_DBG(ERR, "Failed to update port database\n");
1903 		goto jump_to_error;
1904 	}
1905 
1906 	/* create the default rules */
1907 	rc = bnxt_ulp_create_df_rules(bp);
1908 	if (rc) {
1909 		BNXT_TF_DBG(ERR, "Failed to create default flow\n");
1910 		goto jump_to_error;
1911 	}
1912 
1913 	rc = bnxt_ulp_devid_get(bp, &devid);
1914 	if (rc) {
1915 		BNXT_TF_DBG(ERR, "Unable to determine device for ULP port init.\n");
1916 		goto jump_to_error;
1917 	}
1918 
1919 	/* set the unicast mode */
1920 	if (bnxt_ulp_cntxt_ptr2_ulp_flags_get(bp->ulp_ctx, &ulp_flags)) {
1921 		BNXT_TF_DBG(ERR, "Error in getting ULP context flags\n");
1922 		goto jump_to_error;
1923 	}
1924 	if (ulp_flags & BNXT_ULP_APP_UNICAST_ONLY) {
1925 		if (bnxt_pmd_set_unicast_rxmask(bp->eth_dev)) {
1926 			BNXT_TF_DBG(ERR, "Error in setting unicast rxmode\n");
1927 			goto jump_to_error;
1928 		}
1929 	}
1930 
1931 	rc = ulp_cust_vxlan_alloc(bp);
1932 	if (rc)
1933 		goto jump_to_error;
1934 
1935 	return rc;
1936 
1937 jump_to_error:
1938 	bnxt_ulp_port_deinit(bp);
1939 	return rc;
1940 }
1941 
1942 static void
1943 ulp_cust_vxlan_free(struct bnxt *bp)
1944 {
1945 	int rc;
1946 
1947 	if (ULP_APP_CUST_VXLAN_SUPPORT(bp->ulp_ctx)) {
1948 		rc = bnxt_tunnel_dst_port_free(bp,
1949 					       bp->ulp_ctx->cfg_data->vxlan_port,
1950 				     HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN);
1951 		if (rc)
1952 			BNXT_TF_DBG(ERR, "Failed to clear global vxlan port\n");
1953 	}
1954 
1955 	if (ULP_APP_CUST_VXLAN_IP_SUPPORT(bp->ulp_ctx)) {
1956 		rc = bnxt_tunnel_dst_port_free(bp,
1957 					       bp->ulp_ctx->cfg_data->vxlan_ip_port,
1958 				     HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN_V4);
1959 		if (rc)
1960 			BNXT_TF_DBG(ERR, "Failed to clear global custom vxlan port\n");
1961 	}
1962 }
1963 
1964 /*
1965  * When a port is de-initialized by dpdk. This functions clears up
1966  * the port specific details.
1967  */
1968 void
1969 bnxt_ulp_port_deinit(struct bnxt *bp)
1970 {
1971 	struct bnxt_ulp_session_state *session;
1972 	struct rte_pci_device *pci_dev;
1973 	struct rte_pci_addr *pci_addr;
1974 
1975 	if (!BNXT_TRUFLOW_EN(bp)) {
1976 		BNXT_TF_DBG(DEBUG,
1977 			    "Skip ULP deinit for port:%d, TF is not enabled\n",
1978 			    bp->eth_dev->data->port_id);
1979 		return;
1980 	}
1981 
1982 	if (!BNXT_PF(bp) && !BNXT_VF_IS_TRUSTED(bp)) {
1983 		BNXT_TF_DBG(DEBUG,
1984 			    "Skip ULP deinit port:%d, not a TVF or PF\n",
1985 			    bp->eth_dev->data->port_id);
1986 		return;
1987 	}
1988 
1989 	if (!bp->ulp_ctx) {
1990 		BNXT_TF_DBG(DEBUG, "ulp ctx already de-allocated\n");
1991 		return;
1992 	}
1993 
1994 	BNXT_TF_DBG(DEBUG, "BNXT Port:%d ULP port deinit\n",
1995 		    bp->eth_dev->data->port_id);
1996 
1997 	/* Get the session details  */
1998 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
1999 	pci_addr = &pci_dev->addr;
2000 	pthread_mutex_lock(&bnxt_ulp_global_mutex);
2001 	session = ulp_get_session(bp, pci_addr);
2002 	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
2003 
2004 	/* session not found then just exit */
2005 	if (!session) {
2006 		/* Free the ulp context */
2007 		rte_free(bp->ulp_ctx);
2008 		bp->ulp_ctx = NULL;
2009 		return;
2010 	}
2011 
2012 	/* Check the reference count to deinit or deattach*/
2013 	if (bp->ulp_ctx->cfg_data && bp->ulp_ctx->cfg_data->ref_cnt) {
2014 		bp->ulp_ctx->cfg_data->ref_cnt--;
2015 		if (bp->ulp_ctx->cfg_data->ref_cnt) {
2016 			/* Free tunnel configurations */
2017 			ulp_cust_vxlan_free(bp);
2018 
2019 			/* free the port details */
2020 			/* Free the default flow rule associated to this port */
2021 			bnxt_ulp_destroy_df_rules(bp, false);
2022 			bnxt_ulp_destroy_vfr_default_rules(bp, false);
2023 
2024 			/* free flows associated with this port */
2025 			bnxt_ulp_flush_port_flows(bp);
2026 
2027 			/* close the session associated with this port */
2028 			ulp_ctx_detach(bp);
2029 
2030 			/* always detach/close shared after the session. */
2031 			ulp_ctx_shared_session_detach(bp);
2032 		} else {
2033 			/* Perform ulp ctx deinit */
2034 			bnxt_ulp_deinit(bp, session);
2035 		}
2036 	}
2037 
2038 	/* Free the ulp context in the context entry list */
2039 	bnxt_ulp_cntxt_list_del(bp->ulp_ctx);
2040 
2041 	/* clean up the session */
2042 	ulp_session_deinit(session);
2043 
2044 	/* Free the ulp context */
2045 	rte_free(bp->ulp_ctx);
2046 	bp->ulp_ctx = NULL;
2047 }
2048 
2049 /* Below are the access functions to access internal data of ulp context. */
2050 /* Function to set the Mark DB into the context */
2051 int32_t
2052 bnxt_ulp_cntxt_ptr2_mark_db_set(struct bnxt_ulp_context *ulp_ctx,
2053 				struct bnxt_ulp_mark_tbl *mark_tbl)
2054 {
2055 	if (!ulp_ctx || !ulp_ctx->cfg_data) {
2056 		BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
2057 		return -EINVAL;
2058 	}
2059 
2060 	ulp_ctx->cfg_data->mark_tbl = mark_tbl;
2061 
2062 	return 0;
2063 }
2064 
2065 /* Function to retrieve the Mark DB from the context. */
2066 struct bnxt_ulp_mark_tbl *
2067 bnxt_ulp_cntxt_ptr2_mark_db_get(struct bnxt_ulp_context *ulp_ctx)
2068 {
2069 	if (!ulp_ctx || !ulp_ctx->cfg_data)
2070 		return NULL;
2071 
2072 	return ulp_ctx->cfg_data->mark_tbl;
2073 }
2074 
2075 bool
2076 bnxt_ulp_cntxt_shared_session_enabled(struct bnxt_ulp_context *ulp_ctx)
2077 {
2078 	return ULP_SHARED_SESSION_IS_ENABLED(ulp_ctx->cfg_data->ulp_flags);
2079 }
2080 
2081 bool
2082 bnxt_ulp_cntxt_multi_shared_session_enabled(struct bnxt_ulp_context *ulp_ctx)
2083 {
2084 	return ULP_MULTI_SHARED_IS_SUPPORTED(ulp_ctx);
2085 }
2086 
2087 int32_t
2088 bnxt_ulp_cntxt_app_id_set(struct bnxt_ulp_context *ulp_ctx, uint8_t app_id)
2089 {
2090 	if (!ulp_ctx)
2091 		return -EINVAL;
2092 	ulp_ctx->cfg_data->app_id = app_id;
2093 	return 0;
2094 }
2095 
2096 int32_t
2097 bnxt_ulp_cntxt_app_id_get(struct bnxt_ulp_context *ulp_ctx, uint8_t *app_id)
2098 {
2099 	/* Default APP id is zero */
2100 	if (!ulp_ctx || !app_id)
2101 		return -EINVAL;
2102 	*app_id = ulp_ctx->cfg_data->app_id;
2103 	return 0;
2104 }
2105 
2106 /* Function to set the device id of the hardware. */
2107 int32_t
2108 bnxt_ulp_cntxt_dev_id_set(struct bnxt_ulp_context *ulp_ctx,
2109 			  uint32_t dev_id)
2110 {
2111 	if (ulp_ctx && ulp_ctx->cfg_data) {
2112 		ulp_ctx->cfg_data->dev_id = dev_id;
2113 		return 0;
2114 	}
2115 
2116 	return -EINVAL;
2117 }
2118 
2119 /* Function to get the device id of the hardware. */
2120 int32_t
2121 bnxt_ulp_cntxt_dev_id_get(struct bnxt_ulp_context *ulp_ctx,
2122 			  uint32_t *dev_id)
2123 {
2124 	if (ulp_ctx && ulp_ctx->cfg_data) {
2125 		*dev_id = ulp_ctx->cfg_data->dev_id;
2126 		return 0;
2127 	}
2128 	*dev_id = BNXT_ULP_DEVICE_ID_LAST;
2129 	BNXT_TF_DBG(ERR, "Failed to read dev_id from ulp ctxt\n");
2130 	return -EINVAL;
2131 }
2132 
2133 int32_t
2134 bnxt_ulp_cntxt_mem_type_set(struct bnxt_ulp_context *ulp_ctx,
2135 			    enum bnxt_ulp_flow_mem_type mem_type)
2136 {
2137 	if (ulp_ctx && ulp_ctx->cfg_data) {
2138 		ulp_ctx->cfg_data->mem_type = mem_type;
2139 		return 0;
2140 	}
2141 	BNXT_TF_DBG(ERR, "Failed to write mem_type in ulp ctxt\n");
2142 	return -EINVAL;
2143 }
2144 
2145 int32_t
2146 bnxt_ulp_cntxt_mem_type_get(struct bnxt_ulp_context *ulp_ctx,
2147 			    enum bnxt_ulp_flow_mem_type *mem_type)
2148 {
2149 	if (ulp_ctx && ulp_ctx->cfg_data) {
2150 		*mem_type = ulp_ctx->cfg_data->mem_type;
2151 		return 0;
2152 	}
2153 	*mem_type = BNXT_ULP_FLOW_MEM_TYPE_LAST;
2154 	BNXT_TF_DBG(ERR, "Failed to read mem_type in ulp ctxt\n");
2155 	return -EINVAL;
2156 }
2157 
2158 /* Function to get the table scope id of the EEM table. */
2159 int32_t
2160 bnxt_ulp_cntxt_tbl_scope_id_get(struct bnxt_ulp_context *ulp_ctx,
2161 				uint32_t *tbl_scope_id)
2162 {
2163 	if (ulp_ctx && ulp_ctx->cfg_data) {
2164 		*tbl_scope_id = ulp_ctx->cfg_data->tbl_scope_id;
2165 		return 0;
2166 	}
2167 
2168 	return -EINVAL;
2169 }
2170 
2171 /* Function to set the table scope id of the EEM table. */
2172 int32_t
2173 bnxt_ulp_cntxt_tbl_scope_id_set(struct bnxt_ulp_context *ulp_ctx,
2174 				uint32_t tbl_scope_id)
2175 {
2176 	if (ulp_ctx && ulp_ctx->cfg_data) {
2177 		ulp_ctx->cfg_data->tbl_scope_id = tbl_scope_id;
2178 		return 0;
2179 	}
2180 
2181 	return -EINVAL;
2182 }
2183 
2184 /* Function to get the number of shared clients attached */
2185 uint8_t
2186 bnxt_ulp_cntxt_num_shared_clients_get(struct bnxt_ulp_context *ulp)
2187 {
2188 	if (ulp == NULL || ulp->cfg_data == NULL) {
2189 		BNXT_TF_DBG(ERR, "Invalid arguments\n");
2190 		return 0;
2191 	}
2192 	return ulp->cfg_data->num_shared_clients;
2193 }
2194 
2195 /* Function to set the number of shared clients */
2196 int
2197 bnxt_ulp_cntxt_num_shared_clients_set(struct bnxt_ulp_context *ulp, bool incr)
2198 {
2199 	if (ulp == NULL || ulp->cfg_data == NULL) {
2200 		BNXT_TF_DBG(ERR, "Invalid arguments\n");
2201 		return 0;
2202 	}
2203 	if (incr)
2204 		ulp->cfg_data->num_shared_clients++;
2205 	else if (ulp->cfg_data->num_shared_clients)
2206 		ulp->cfg_data->num_shared_clients--;
2207 
2208 	BNXT_TF_DBG(DEBUG, "%d:clients(%d)\n", incr,
2209 		    ulp->cfg_data->num_shared_clients);
2210 
2211 	return 0;
2212 }
2213 
2214 /* Function to set the tfp session details from the ulp context. */
2215 int32_t
2216 bnxt_ulp_cntxt_tfp_set(struct bnxt_ulp_context *ulp,
2217 		       enum bnxt_ulp_session_type s_type,
2218 		       struct tf *tfp)
2219 {
2220 	uint32_t idx = 0;
2221 
2222 	if (!ulp) {
2223 		BNXT_TF_DBG(ERR, "Invalid arguments\n");
2224 		return -EINVAL;
2225 	}
2226 	if (ULP_MULTI_SHARED_IS_SUPPORTED(ulp)) {
2227 		if (s_type & BNXT_ULP_SESSION_TYPE_SHARED)
2228 			idx = 1;
2229 		else if (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC)
2230 			idx = 2;
2231 
2232 	} else {
2233 		if ((s_type & BNXT_ULP_SESSION_TYPE_SHARED) ||
2234 		    (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC))
2235 			idx = 1;
2236 	}
2237 
2238 	ulp->g_tfp[idx] = tfp;
2239 	return 0;
2240 }
2241 
2242 /* Function to get the tfp session details from the ulp context. */
2243 struct tf *
2244 bnxt_ulp_cntxt_tfp_get(struct bnxt_ulp_context *ulp,
2245 		       enum bnxt_ulp_session_type s_type)
2246 {
2247 	uint32_t idx = 0;
2248 
2249 	if (!ulp) {
2250 		BNXT_TF_DBG(ERR, "Invalid arguments\n");
2251 		return NULL;
2252 	}
2253 	if (ULP_MULTI_SHARED_IS_SUPPORTED(ulp)) {
2254 		if (s_type & BNXT_ULP_SESSION_TYPE_SHARED)
2255 			idx = 1;
2256 		else if (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC)
2257 			idx = 2;
2258 	} else {
2259 		if ((s_type & BNXT_ULP_SESSION_TYPE_SHARED) ||
2260 		    (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC))
2261 			idx = 1;
2262 	}
2263 	return ulp->g_tfp[idx];
2264 }
2265 
2266 /*
2267  * Get the device table entry based on the device id.
2268  *
2269  * dev_id [in] The device id of the hardware
2270  *
2271  * Returns the pointer to the device parameters.
2272  */
2273 struct bnxt_ulp_device_params *
2274 bnxt_ulp_device_params_get(uint32_t dev_id)
2275 {
2276 	if (dev_id < BNXT_ULP_MAX_NUM_DEVICES)
2277 		return &ulp_device_params[dev_id];
2278 	return NULL;
2279 }
2280 
2281 /* Function to set the flow database to the ulp context. */
2282 int32_t
2283 bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context	*ulp_ctx,
2284 				struct bnxt_ulp_flow_db	*flow_db)
2285 {
2286 	if (!ulp_ctx || !ulp_ctx->cfg_data)
2287 		return -EINVAL;
2288 
2289 	ulp_ctx->cfg_data->flow_db = flow_db;
2290 	return 0;
2291 }
2292 
2293 /* Function to get the flow database from the ulp context. */
2294 struct bnxt_ulp_flow_db	*
2295 bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context	*ulp_ctx)
2296 {
2297 	if (!ulp_ctx || !ulp_ctx->cfg_data)
2298 		return NULL;
2299 
2300 	return ulp_ctx->cfg_data->flow_db;
2301 }
2302 
2303 /* Function to get the tunnel cache table info from the ulp context. */
2304 struct bnxt_tun_cache_entry *
2305 bnxt_ulp_cntxt_ptr2_tun_tbl_get(struct bnxt_ulp_context *ulp_ctx)
2306 {
2307 	if (!ulp_ctx || !ulp_ctx->cfg_data)
2308 		return NULL;
2309 
2310 	return ulp_ctx->cfg_data->tun_tbl;
2311 }
2312 
2313 /* Function to get the ulp context from eth device. */
2314 struct bnxt_ulp_context	*
2315 bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev	*dev)
2316 {
2317 	struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
2318 
2319 	if (rte_eth_dev_is_repr(dev)) {
2320 		struct bnxt_representor *vfr = dev->data->dev_private;
2321 
2322 		bp = vfr->parent_dev->data->dev_private;
2323 	}
2324 
2325 	if (!bp) {
2326 		BNXT_TF_DBG(ERR, "Bnxt private data is not initialized\n");
2327 		return NULL;
2328 	}
2329 	return bp->ulp_ctx;
2330 }
2331 
2332 int32_t
2333 bnxt_ulp_cntxt_ptr2_mapper_data_set(struct bnxt_ulp_context *ulp_ctx,
2334 				    void *mapper_data)
2335 {
2336 	if (!ulp_ctx || !ulp_ctx->cfg_data) {
2337 		BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
2338 		return -EINVAL;
2339 	}
2340 
2341 	ulp_ctx->cfg_data->mapper_data = mapper_data;
2342 	return 0;
2343 }
2344 
2345 void *
2346 bnxt_ulp_cntxt_ptr2_mapper_data_get(struct bnxt_ulp_context *ulp_ctx)
2347 {
2348 	if (!ulp_ctx || !ulp_ctx->cfg_data) {
2349 		BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
2350 		return NULL;
2351 	}
2352 
2353 	return ulp_ctx->cfg_data->mapper_data;
2354 }
2355 
2356 /* Function to set the port database to the ulp context. */
2357 int32_t
2358 bnxt_ulp_cntxt_ptr2_port_db_set(struct bnxt_ulp_context	*ulp_ctx,
2359 				struct bnxt_ulp_port_db	*port_db)
2360 {
2361 	if (!ulp_ctx || !ulp_ctx->cfg_data)
2362 		return -EINVAL;
2363 
2364 	ulp_ctx->cfg_data->port_db = port_db;
2365 	return 0;
2366 }
2367 
2368 /* Function to get the port database from the ulp context. */
2369 struct bnxt_ulp_port_db *
2370 bnxt_ulp_cntxt_ptr2_port_db_get(struct bnxt_ulp_context	*ulp_ctx)
2371 {
2372 	if (!ulp_ctx || !ulp_ctx->cfg_data)
2373 		return NULL;
2374 
2375 	return ulp_ctx->cfg_data->port_db;
2376 }
2377 
2378 /* Function to set the flow counter info into the context */
2379 int32_t
2380 bnxt_ulp_cntxt_ptr2_fc_info_set(struct bnxt_ulp_context *ulp_ctx,
2381 				struct bnxt_ulp_fc_info *ulp_fc_info)
2382 {
2383 	if (!ulp_ctx || !ulp_ctx->cfg_data) {
2384 		BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
2385 		return -EINVAL;
2386 	}
2387 
2388 	ulp_ctx->cfg_data->fc_info = ulp_fc_info;
2389 
2390 	return 0;
2391 }
2392 
2393 /* Function to retrieve the flow counter info from the context. */
2394 struct bnxt_ulp_fc_info *
2395 bnxt_ulp_cntxt_ptr2_fc_info_get(struct bnxt_ulp_context *ulp_ctx)
2396 {
2397 	if (!ulp_ctx || !ulp_ctx->cfg_data)
2398 		return NULL;
2399 
2400 	return ulp_ctx->cfg_data->fc_info;
2401 }
2402 
2403 /* Function to get the ulp flags from the ulp context. */
2404 int32_t
2405 bnxt_ulp_cntxt_ptr2_ulp_flags_get(struct bnxt_ulp_context *ulp_ctx,
2406 				  uint32_t *flags)
2407 {
2408 	if (!ulp_ctx || !ulp_ctx->cfg_data)
2409 		return -1;
2410 
2411 	*flags =  ulp_ctx->cfg_data->ulp_flags;
2412 	return 0;
2413 }
2414 
2415 /* Function to get the ulp vfr info from the ulp context. */
2416 struct bnxt_ulp_vfr_rule_info*
2417 bnxt_ulp_cntxt_ptr2_ulp_vfr_info_get(struct bnxt_ulp_context *ulp_ctx,
2418 				     uint32_t port_id)
2419 {
2420 	if (!ulp_ctx || !ulp_ctx->cfg_data || port_id >= RTE_MAX_ETHPORTS)
2421 		return NULL;
2422 
2423 	return &ulp_ctx->cfg_data->vfr_rule_info[port_id];
2424 }
2425 
2426 /* Function to acquire the flow database lock from the ulp context. */
2427 int32_t
2428 bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
2429 {
2430 	if (!ulp_ctx || !ulp_ctx->cfg_data)
2431 		return -1;
2432 
2433 	if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
2434 		BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n");
2435 		return -1;
2436 	}
2437 	return 0;
2438 }
2439 
2440 /* Function to release the flow database lock from the ulp context. */
2441 void
2442 bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
2443 {
2444 	if (!ulp_ctx || !ulp_ctx->cfg_data)
2445 		return;
2446 
2447 	pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
2448 }
2449 
2450 /* Function to extract the action type from the shared action handle. */
2451 int32_t
2452 bnxt_get_action_handle_type(const struct rte_flow_action_handle *handle,
2453 			    uint32_t *action_handle_type)
2454 {
2455 	if (!action_handle_type)
2456 		return -EINVAL;
2457 
2458 	*action_handle_type = (uint32_t)(((uint64_t)handle >> 32) & 0xffffffff);
2459 	if (*action_handle_type >= BNXT_ULP_GEN_TBL_MAX_SZ)
2460 		return -EINVAL;
2461 
2462 	return 0;
2463 }
2464 
2465 /* Function to extract the direction from the shared action handle. */
2466 int32_t
2467 bnxt_get_action_handle_direction(const struct rte_flow_action_handle *handle,
2468 				 uint32_t *dir)
2469 {
2470 	uint32_t shared_type;
2471 	int32_t ret = 0;
2472 
2473 	ret = bnxt_get_action_handle_type(handle, &shared_type);
2474 	if (ret)
2475 		return ret;
2476 
2477 	*dir = shared_type & 0x1 ? BNXT_ULP_DIR_EGRESS : BNXT_ULP_DIR_INGRESS;
2478 
2479 	return ret;
2480 }
2481 
2482 /* Function to extract the action index from the shared action handle. */
2483 uint32_t
2484 bnxt_get_action_handle_index(const struct rte_flow_action_handle *handle)
2485 {
2486 	return (uint32_t)((uint64_t)handle & 0xffffffff);
2487 }
2488 
2489 /* Function to set the ha info into the context */
2490 int32_t
2491 bnxt_ulp_cntxt_ptr2_ha_info_set(struct bnxt_ulp_context *ulp_ctx,
2492 				struct bnxt_ulp_ha_mgr_info *ulp_ha_info)
2493 {
2494 	if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) {
2495 		BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
2496 		return -EINVAL;
2497 	}
2498 	ulp_ctx->cfg_data->ha_info = ulp_ha_info;
2499 	return 0;
2500 }
2501 
2502 /* Function to retrieve the ha info from the context. */
2503 struct bnxt_ulp_ha_mgr_info *
2504 bnxt_ulp_cntxt_ptr2_ha_info_get(struct bnxt_ulp_context *ulp_ctx)
2505 {
2506 	if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL)
2507 		return NULL;
2508 	return ulp_ctx->cfg_data->ha_info;
2509 }
2510 
2511 bool
2512 bnxt_ulp_cntxt_ha_enabled(struct bnxt_ulp_context *ulp_ctx)
2513 {
2514 	if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL)
2515 		return false;
2516 	return !!ULP_HIGH_AVAIL_IS_ENABLED(ulp_ctx->cfg_data->ulp_flags);
2517 }
2518 
2519 static int32_t
2520 bnxt_ulp_cntxt_list_init(void)
2521 {
2522 	/* Create the cntxt spin lock only once*/
2523 	if (!bnxt_ulp_ctxt_lock_created)
2524 		rte_spinlock_init(&bnxt_ulp_ctxt_lock);
2525 	bnxt_ulp_ctxt_lock_created = 1;
2526 	return 0;
2527 }
2528 
2529 static int32_t
2530 bnxt_ulp_cntxt_list_add(struct bnxt_ulp_context *ulp_ctx)
2531 {
2532 	struct ulp_context_list_entry	*entry;
2533 
2534 	entry = rte_zmalloc(NULL, sizeof(struct ulp_context_list_entry), 0);
2535 	if (entry == NULL) {
2536 		BNXT_TF_DBG(ERR, "unable to allocate memory\n");
2537 		return -ENOMEM;
2538 	}
2539 
2540 	rte_spinlock_lock(&bnxt_ulp_ctxt_lock);
2541 	entry->ulp_ctx = ulp_ctx;
2542 	TAILQ_INSERT_TAIL(&ulp_cntx_list, entry, next);
2543 	rte_spinlock_unlock(&bnxt_ulp_ctxt_lock);
2544 	return 0;
2545 }
2546 
2547 static void
2548 bnxt_ulp_cntxt_list_del(struct bnxt_ulp_context *ulp_ctx)
2549 {
2550 	struct ulp_context_list_entry	*entry, *temp;
2551 
2552 	rte_spinlock_lock(&bnxt_ulp_ctxt_lock);
2553 	RTE_TAILQ_FOREACH_SAFE(entry, &ulp_cntx_list, next, temp) {
2554 		if (entry->ulp_ctx == ulp_ctx) {
2555 			TAILQ_REMOVE(&ulp_cntx_list, entry, next);
2556 			rte_free(entry);
2557 			break;
2558 		}
2559 	}
2560 	rte_spinlock_unlock(&bnxt_ulp_ctxt_lock);
2561 }
2562 
2563 struct bnxt_ulp_context *
2564 bnxt_ulp_cntxt_entry_acquire(void *arg)
2565 {
2566 	struct ulp_context_list_entry	*entry;
2567 
2568 	/* take a lock and get the first ulp context available */
2569 	if (rte_spinlock_trylock(&bnxt_ulp_ctxt_lock)) {
2570 		TAILQ_FOREACH(entry, &ulp_cntx_list, next)
2571 			if (entry->ulp_ctx->cfg_data == arg)
2572 				return entry->ulp_ctx;
2573 		rte_spinlock_unlock(&bnxt_ulp_ctxt_lock);
2574 	}
2575 	return NULL;
2576 }
2577 
2578 void
2579 bnxt_ulp_cntxt_entry_release(void)
2580 {
2581 	rte_spinlock_unlock(&bnxt_ulp_ctxt_lock);
2582 }
2583 
2584 /* Function to get the app tunnel details from the ulp context. */
2585 struct bnxt_flow_app_tun_ent *
2586 bnxt_ulp_cntxt_ptr2_app_tun_list_get(struct bnxt_ulp_context *ulp)
2587 {
2588 	if (!ulp || !ulp->cfg_data)
2589 		return NULL;
2590 
2591 	return ulp->cfg_data->app_tun;
2592 }
2593 
2594 /* Function to get the truflow app id. This defined in the build file */
2595 uint32_t
2596 bnxt_ulp_default_app_id_get(void)
2597 {
2598 	return BNXT_TF_APP_ID;
2599 }
2600 
2601 /* Function to convert ulp dev id to regular dev id. */
2602 uint32_t
2603 bnxt_ulp_cntxt_convert_dev_id(uint32_t ulp_dev_id)
2604 {
2605 	enum tf_device_type type = 0;
2606 
2607 	switch (ulp_dev_id) {
2608 	case BNXT_ULP_DEVICE_ID_WH_PLUS:
2609 		type = TF_DEVICE_TYPE_P4;
2610 		break;
2611 	case BNXT_ULP_DEVICE_ID_STINGRAY:
2612 		type = TF_DEVICE_TYPE_SR;
2613 		break;
2614 	case BNXT_ULP_DEVICE_ID_THOR:
2615 		type = TF_DEVICE_TYPE_P5;
2616 		break;
2617 	default:
2618 		BNXT_TF_DBG(ERR, "Invalid device id\n");
2619 		break;
2620 	}
2621 	return type;
2622 }
2623 
2624 /* This function sets the IF table index for the
2625  * Application to poll to get the hot upgrade state and count details from
2626  * the firmware.
2627  */
2628 int32_t
2629 bnxt_ulp_ha_reg_set(struct bnxt_ulp_context *ulp_ctx,
2630 		    uint8_t state, uint8_t cnt)
2631 {
2632 	if (!ulp_ctx || !ulp_ctx->cfg_data)
2633 		return -EINVAL;
2634 
2635 	if (ULP_MULTI_SHARED_IS_SUPPORTED(ulp_ctx)) {
2636 		ulp_ctx->cfg_data->hu_reg_state = state;
2637 		ulp_ctx->cfg_data->hu_reg_cnt = cnt;
2638 	} else {
2639 		ulp_ctx->cfg_data->hu_reg_state = ULP_HA_IF_TBL_IDX;
2640 		ulp_ctx->cfg_data->hu_reg_cnt = ULP_HA_CLIENT_CNT_IF_TBL_IDX;
2641 	}
2642 	return 0;
2643 }
2644 
2645 /* This function gets the IF table index for the
2646  * application to poll to get the application hot upgrade state from
2647  * the firmware.
2648  */
2649 uint32_t
2650 bnxt_ulp_ha_reg_state_get(struct bnxt_ulp_context *ulp_ctx)
2651 {
2652 	if (!ulp_ctx || !ulp_ctx->cfg_data)
2653 		return 0;
2654 
2655 	return (uint32_t)ulp_ctx->cfg_data->hu_reg_state;
2656 }
2657 
2658 /* This function gets the IF table index for the
2659  * Application to poll to get the application count from
2660  * the firmware.
2661  */
2662 uint32_t
2663 bnxt_ulp_ha_reg_cnt_get(struct bnxt_ulp_context *ulp_ctx)
2664 {
2665 	if (!ulp_ctx || !ulp_ctx->cfg_data)
2666 		return 0;
2667 
2668 	return (uint32_t)ulp_ctx->cfg_data->hu_reg_cnt;
2669 }
2670 
2671 struct tf*
2672 bnxt_ulp_bp_tfp_get(struct bnxt *bp, enum bnxt_ulp_session_type type)
2673 {
2674 	enum bnxt_session_type btype;
2675 
2676 	if (type & BNXT_ULP_SESSION_TYPE_SHARED)
2677 		btype = BNXT_SESSION_TYPE_SHARED_COMMON;
2678 	else if (type & BNXT_ULP_SESSION_TYPE_SHARED_WC)
2679 		btype = BNXT_SESSION_TYPE_SHARED_WC;
2680 	else
2681 		btype = BNXT_SESSION_TYPE_REGULAR;
2682 
2683 	return bnxt_get_tfp_session(bp, btype);
2684 }
2685