xref: /dpdk/drivers/net/bnxt/tf_core/tf_tcam.c (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2021 Broadcom
3  * All rights reserved.
4  */
5 
6 #include <string.h>
7 #include <rte_common.h>
8 
9 #include "tf_tcam.h"
10 #include "tf_common.h"
11 #include "tf_util.h"
12 #include "tf_rm.h"
13 #include "tf_device.h"
14 #include "tfp.h"
15 #include "tf_session.h"
16 #include "tf_msg.h"
17 #include "tf_shadow_tcam.h"
18 
19 struct tf;
20 
21 /**
22  * TCAM Shadow DBs
23  */
24 static void *shadow_tcam_db[TF_DIR_MAX];
25 
26 /**
27  * Shadow init flag, set on bind and cleared on unbind
28  */
29 static uint8_t shadow_init;
30 
31 int
32 tf_tcam_bind(struct tf *tfp,
33 	     struct tf_tcam_cfg_parms *parms)
34 {
35 	int rc;
36 	int db_rc[TF_DIR_MAX] = { 0 };
37 	int i, d;
38 	struct tf_rm_alloc_info info;
39 	struct tf_rm_free_db_parms fparms;
40 	struct tf_rm_create_db_parms db_cfg;
41 	struct tf_tcam_resources *tcam_cnt;
42 	struct tf_rm_get_alloc_info_parms ainfo;
43 	struct tf_shadow_tcam_free_db_parms fshadow;
44 	struct tf_shadow_tcam_cfg_parms shadow_cfg;
45 	struct tf_shadow_tcam_create_db_parms shadow_cdb;
46 	uint16_t num_slices = parms->wc_num_slices;
47 	struct tf_session *tfs;
48 	struct tf_dev_info *dev;
49 	struct tcam_rm_db *tcam_db;
50 	struct tfp_calloc_parms cparms;
51 
52 	TF_CHECK_PARMS2(tfp, parms);
53 
54 	/* Retrieve the session information */
55 	rc = tf_session_get_session_internal(tfp, &tfs);
56 	if (rc)
57 		return rc;
58 
59 	/* Retrieve the device information */
60 	rc = tf_session_get_device(tfs, &dev);
61 	if (rc)
62 		return rc;
63 
64 	if (dev->ops->tf_dev_set_tcam_slice_info == NULL) {
65 		rc = -EOPNOTSUPP;
66 		TFP_DRV_LOG(ERR,
67 			    "Operation not supported, rc:%s\n",
68 			    strerror(-rc));
69 		return rc;
70 	}
71 
72 	rc = dev->ops->tf_dev_set_tcam_slice_info(tfp,
73 						  num_slices);
74 	if (rc)
75 		return rc;
76 
77 	tcam_cnt = parms->resources->tcam_cnt;
78 	if ((tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % num_slices) ||
79 	    (tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % num_slices)) {
80 		TFP_DRV_LOG(ERR,
81 			    "Requested num of WC TCAM entries has to be multiple %d\n",
82 			    num_slices);
83 		return -EINVAL;
84 	}
85 
86 	memset(&db_cfg, 0, sizeof(db_cfg));
87 	cparms.nitems = 1;
88 	cparms.size = sizeof(struct tcam_rm_db);
89 	cparms.alignment = 0;
90 	if (tfp_calloc(&cparms) != 0) {
91 		TFP_DRV_LOG(ERR, "tcam_rm_db alloc error %s\n",
92 			    strerror(ENOMEM));
93 		return -ENOMEM;
94 	}
95 
96 	tcam_db = cparms.mem_va;
97 	for (i = 0; i < TF_DIR_MAX; i++)
98 		tcam_db->tcam_db[i] = NULL;
99 	tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, tcam_db);
100 
101 	db_cfg.module = TF_MODULE_TYPE_TCAM;
102 	db_cfg.num_elements = parms->num_elements;
103 	db_cfg.cfg = parms->cfg;
104 
105 	for (d = 0; d < TF_DIR_MAX; d++) {
106 		db_cfg.dir = d;
107 		db_cfg.alloc_cnt = parms->resources->tcam_cnt[d].cnt;
108 		db_cfg.rm_db = (void *)&tcam_db->tcam_db[d];
109 		if (tf_session_is_shared_session(tfs) &&
110 			(!tf_session_is_shared_session_creator(tfs)))
111 			db_rc[d] = tf_rm_create_db_no_reservation(tfp, &db_cfg);
112 		else
113 			db_rc[d] = tf_rm_create_db(tfp, &db_cfg);
114 	}
115 
116 	/* No db created */
117 	if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) {
118 		TFP_DRV_LOG(ERR, "No TCAM DB created\n");
119 		return db_rc[TF_DIR_RX];
120 	}
121 
122 	/* check if reserved resource for WC is multiple of num_slices */
123 	for (d = 0; d < TF_DIR_MAX; d++) {
124 		if (!tcam_db->tcam_db[d])
125 			continue;
126 
127 		memset(&info, 0, sizeof(info));
128 		ainfo.rm_db = tcam_db->tcam_db[d];
129 		ainfo.subtype = TF_TCAM_TBL_TYPE_WC_TCAM;
130 		ainfo.info = &info;
131 		rc = tf_rm_get_info(&ainfo);
132 		if (rc)
133 			goto error;
134 
135 		if (info.entry.start % num_slices != 0 ||
136 		    info.entry.stride % num_slices != 0) {
137 			TFP_DRV_LOG(ERR,
138 				    "%s: TCAM reserved resource is not multiple of %d\n",
139 				    tf_dir_2_str(d),
140 				    num_slices);
141 			rc = -EINVAL;
142 			goto error;
143 		}
144 	}
145 
146 	/* Initialize the TCAM manager. */
147 	if (parms->shadow_copy) {
148 		for (d = 0; d < TF_DIR_MAX; d++) {
149 			memset(&shadow_cfg, 0, sizeof(shadow_cfg));
150 			memset(&shadow_cdb, 0, sizeof(shadow_cdb));
151 			/* Get the base addresses of the tcams for tcam mgr */
152 			for (i = 0; i < TF_TCAM_TBL_TYPE_MAX; i++) {
153 				memset(&info, 0, sizeof(info));
154 
155 				if (!parms->resources->tcam_cnt[d].cnt[i])
156 					continue;
157 				ainfo.rm_db = tcam_db->tcam_db[d];
158 				ainfo.subtype = i;
159 				ainfo.info = &info;
160 				rc = tf_rm_get_info(&ainfo);
161 				if (rc)
162 					goto error;
163 
164 				shadow_cfg.base_addr[i] = info.entry.start;
165 			}
166 
167 			/* Create the shadow db */
168 			shadow_cfg.alloc_cnt =
169 				parms->resources->tcam_cnt[d].cnt;
170 			shadow_cfg.num_entries = parms->num_elements;
171 
172 			shadow_cdb.shadow_db = &shadow_tcam_db[d];
173 			shadow_cdb.cfg = &shadow_cfg;
174 			rc = tf_shadow_tcam_create_db(&shadow_cdb);
175 			if (rc) {
176 				TFP_DRV_LOG(ERR,
177 					    "TCAM MGR DB creation failed "
178 					    "rc=%d\n", rc);
179 				goto error;
180 			}
181 		}
182 		shadow_init = 1;
183 	}
184 
185 	TFP_DRV_LOG(INFO,
186 		    "TCAM - initialized\n");
187 
188 	return 0;
189 error:
190 	for (i = 0; i < TF_DIR_MAX; i++) {
191 		memset(&fparms, 0, sizeof(fparms));
192 		fparms.dir = i;
193 		fparms.rm_db = tcam_db->tcam_db[i];
194 		/* Ignoring return here since we are in the error case */
195 		(void)tf_rm_free_db(tfp, &fparms);
196 
197 		if (parms->shadow_copy) {
198 			fshadow.shadow_db = shadow_tcam_db[i];
199 			tf_shadow_tcam_free_db(&fshadow);
200 			shadow_tcam_db[i] = NULL;
201 		}
202 
203 		tcam_db->tcam_db[i] = NULL;
204 		tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, NULL);
205 	}
206 
207 	shadow_init = 0;
208 
209 	return rc;
210 }
211 
212 int
213 tf_tcam_unbind(struct tf *tfp)
214 {
215 	int rc;
216 	int i;
217 	struct tf_rm_free_db_parms fparms;
218 	struct tcam_rm_db *tcam_db;
219 	void *tcam_db_ptr = NULL;
220 	struct tf_shadow_tcam_free_db_parms fshadow;
221 	TF_CHECK_PARMS1(tfp);
222 
223 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
224 	if (rc) {
225 		return 0;
226 	}
227 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
228 
229 	for (i = 0; i < TF_DIR_MAX; i++) {
230 		if (tcam_db->tcam_db[i] == NULL)
231 			continue;
232 		memset(&fparms, 0, sizeof(fparms));
233 		fparms.dir = i;
234 		fparms.rm_db = tcam_db->tcam_db[i];
235 		rc = tf_rm_free_db(tfp, &fparms);
236 		if (rc)
237 			return rc;
238 
239 		tcam_db->tcam_db[i] = NULL;
240 
241 		if (shadow_init) {
242 			memset(&fshadow, 0, sizeof(fshadow));
243 
244 			fshadow.shadow_db = shadow_tcam_db[i];
245 			tf_shadow_tcam_free_db(&fshadow);
246 			shadow_tcam_db[i] = NULL;
247 		}
248 	}
249 
250 	shadow_init = 0;
251 
252 	return 0;
253 }
254 
255 int
256 tf_tcam_alloc(struct tf *tfp,
257 	      struct tf_tcam_alloc_parms *parms)
258 {
259 	int rc, i;
260 	struct tf_session *tfs;
261 	struct tf_dev_info *dev;
262 	struct tf_rm_allocate_parms aparms;
263 	uint16_t num_slices = 1;
264 	uint32_t index;
265 	struct tcam_rm_db *tcam_db;
266 	void *tcam_db_ptr = NULL;
267 
268 	TF_CHECK_PARMS2(tfp, parms);
269 
270 	/* Retrieve the session information */
271 	rc = tf_session_get_session_internal(tfp, &tfs);
272 	if (rc)
273 		return rc;
274 
275 	/* Retrieve the device information */
276 	rc = tf_session_get_device(tfs, &dev);
277 	if (rc)
278 		return rc;
279 
280 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
281 		rc = -EOPNOTSUPP;
282 		TFP_DRV_LOG(ERR,
283 			    "%s: Operation not supported, rc:%s\n",
284 			    tf_dir_2_str(parms->dir),
285 			    strerror(-rc));
286 		return rc;
287 	}
288 
289 	/* Need to retrieve number of slices based on the key_size */
290 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
291 						  parms->type,
292 						  parms->key_size,
293 						  &num_slices);
294 	if (rc)
295 		return rc;
296 
297 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
298 	if (rc) {
299 		TFP_DRV_LOG(ERR,
300 			    "Failed to get tcam_db from session, rc:%s\n",
301 			    strerror(-rc));
302 		return rc;
303 	}
304 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
305 
306 	/*
307 	 * For WC TCAM, number of slices could be 4, 2, 1 based on
308 	 * the key_size. For other TCAM, it is always 1
309 	 */
310 	for (i = 0; i < num_slices; i++) {
311 		memset(&aparms, 0, sizeof(aparms));
312 		aparms.rm_db = tcam_db->tcam_db[parms->dir];
313 		aparms.subtype = parms->type;
314 		aparms.priority = parms->priority;
315 		aparms.index = &index;
316 		rc = tf_rm_allocate(&aparms);
317 		if (rc) {
318 			TFP_DRV_LOG(ERR,
319 				    "%s: Failed tcam, type:%d\n",
320 				    tf_dir_2_str(parms->dir),
321 				    parms->type);
322 			return rc;
323 		}
324 
325 		/* return the start index of each row */
326 		if (parms->priority == 0) {
327 			if (i == 0)
328 				parms->idx = index;
329 		} else {
330 			parms->idx = index;
331 		}
332 	}
333 
334 	return 0;
335 }
336 
337 int
338 tf_tcam_free(struct tf *tfp,
339 	     struct tf_tcam_free_parms *parms)
340 {
341 	int rc;
342 	struct tf_session *tfs;
343 	struct tf_dev_info *dev;
344 	struct tf_rm_is_allocated_parms aparms;
345 	struct tf_rm_free_parms fparms;
346 	struct tf_rm_get_hcapi_parms hparms;
347 	uint16_t num_slices = 1;
348 	int allocated = 0;
349 	struct tf_shadow_tcam_remove_parms shparms;
350 	int i;
351 	struct tcam_rm_db *tcam_db;
352 	void *tcam_db_ptr = NULL;
353 
354 	TF_CHECK_PARMS2(tfp, parms);
355 
356 	/* Retrieve the session information */
357 	rc = tf_session_get_session_internal(tfp, &tfs);
358 	if (rc)
359 		return rc;
360 
361 	/* Retrieve the device information */
362 	rc = tf_session_get_device(tfs, &dev);
363 	if (rc)
364 		return rc;
365 
366 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
367 		rc = -EOPNOTSUPP;
368 		TFP_DRV_LOG(ERR,
369 			    "%s: Operation not supported, rc:%s\n",
370 			    tf_dir_2_str(parms->dir),
371 			    strerror(-rc));
372 		return rc;
373 	}
374 
375 	/* Need to retrieve row size etc */
376 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
377 						  parms->type,
378 						  0,
379 						  &num_slices);
380 	if (rc)
381 		return rc;
382 
383 	if (parms->idx % num_slices) {
384 		TFP_DRV_LOG(ERR,
385 			    "%s: TCAM reserved resource is not multiple of %d\n",
386 			    tf_dir_2_str(parms->dir),
387 			    num_slices);
388 		return -EINVAL;
389 	}
390 
391 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
392 	if (rc) {
393 		TFP_DRV_LOG(ERR,
394 			    "Failed to get em_ext_db from session, rc:%s\n",
395 			    strerror(-rc));
396 		return rc;
397 	}
398 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
399 
400 	/* Check if element is in use */
401 	memset(&aparms, 0, sizeof(aparms));
402 	aparms.rm_db = tcam_db->tcam_db[parms->dir];
403 	aparms.subtype = parms->type;
404 	aparms.index = parms->idx;
405 	aparms.allocated = &allocated;
406 	rc = tf_rm_is_allocated(&aparms);
407 	if (rc)
408 		return rc;
409 
410 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
411 		TFP_DRV_LOG(ERR,
412 			    "%s: Entry already free, type:%d, index:%d\n",
413 			    tf_dir_2_str(parms->dir),
414 			    parms->type,
415 			    parms->idx);
416 		return -EINVAL;
417 	}
418 
419 	/*
420 	 * The Shadow mgmt, if enabled, determines if the entry needs
421 	 * to be deleted.
422 	 */
423 	if (shadow_init) {
424 		shparms.shadow_db = shadow_tcam_db[parms->dir];
425 		shparms.fparms = parms;
426 		rc = tf_shadow_tcam_remove(&shparms);
427 		if (rc) {
428 			/*
429 			 * Should not get here, log it and let the entry be
430 			 * deleted.
431 			 */
432 			TFP_DRV_LOG(ERR, "%s: Shadow free fail, "
433 				    "type:%d index:%d deleting the entry.\n",
434 				    tf_dir_2_str(parms->dir),
435 				    parms->type,
436 				    parms->idx);
437 		} else {
438 			/*
439 			 * If the entry still has references, just return the
440 			 * ref count to the caller.  No need to remove entry
441 			 * from rm or hw
442 			 */
443 			if (parms->ref_cnt >= 1)
444 				return rc;
445 		}
446 	}
447 
448 	for (i = 0; i < num_slices; i++) {
449 		/* Free requested element */
450 		memset(&fparms, 0, sizeof(fparms));
451 		fparms.rm_db = tcam_db->tcam_db[parms->dir];
452 		fparms.subtype = parms->type;
453 		fparms.index = parms->idx + i;
454 		rc = tf_rm_free(&fparms);
455 		if (rc) {
456 			TFP_DRV_LOG(ERR,
457 				    "%s: Free failed, type:%d, index:%d\n",
458 				    tf_dir_2_str(parms->dir),
459 				    parms->type,
460 				    parms->idx);
461 			return rc;
462 		}
463 	}
464 
465 	/* Convert TF type to HCAPI RM type */
466 	memset(&hparms, 0, sizeof(hparms));
467 
468 	hparms.rm_db = tcam_db->tcam_db[parms->dir];
469 	hparms.subtype = parms->type;
470 	hparms.hcapi_type = &parms->hcapi_type;
471 
472 	rc = tf_rm_get_hcapi_type(&hparms);
473 	if (rc)
474 		return rc;
475 
476 	rc = tf_msg_tcam_entry_free(tfp, dev, parms);
477 	if (rc) {
478 		/* Log error */
479 		TFP_DRV_LOG(ERR,
480 			    "%s: %s: Entry %d free failed, rc:%s\n",
481 			    tf_dir_2_str(parms->dir),
482 			    tf_tcam_tbl_2_str(parms->type),
483 			    parms->idx,
484 			    strerror(-rc));
485 		return rc;
486 	}
487 
488 	return 0;
489 }
490 
491 int
492 tf_tcam_alloc_search(struct tf *tfp,
493 		     struct tf_tcam_alloc_search_parms *parms)
494 {
495 	struct tf_shadow_tcam_search_parms sparms;
496 	struct tf_shadow_tcam_bind_index_parms bparms;
497 	struct tf_tcam_free_parms fparms;
498 	struct tf_tcam_alloc_parms aparms;
499 	uint16_t num_slice_per_row = 1;
500 	struct tf_session *tfs;
501 	struct tf_dev_info *dev;
502 	int rc;
503 
504 	TF_CHECK_PARMS2(tfp, parms);
505 
506 	if (!shadow_init || !shadow_tcam_db[parms->dir]) {
507 		TFP_DRV_LOG(ERR, "%s: TCAM Shadow not initialized for %s\n",
508 			    tf_dir_2_str(parms->dir),
509 			    tf_tcam_tbl_2_str(parms->type));
510 		return -EINVAL;
511 	}
512 
513 	/* Retrieve the session information */
514 	rc = tf_session_get_session_internal(tfp, &tfs);
515 	if (rc)
516 		return rc;
517 
518 	/* Retrieve the device information */
519 	rc = tf_session_get_device(tfs, &dev);
520 	if (rc)
521 		return rc;
522 
523 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
524 		rc = -EOPNOTSUPP;
525 		TFP_DRV_LOG(ERR,
526 			    "%s: Operation not supported, rc:%s\n",
527 			    tf_dir_2_str(parms->dir),
528 			    strerror(-rc));
529 		return rc;
530 	}
531 
532 	/* Need to retrieve row size etc */
533 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
534 						  parms->type,
535 						  parms->key_size,
536 						  &num_slice_per_row);
537 	if (rc)
538 		return rc;
539 
540 	/*
541 	 * Prep the shadow search, reusing the parms from original search
542 	 * instead of copying them.  Shadow will update output in there.
543 	 */
544 	memset(&sparms, 0, sizeof(sparms));
545 	sparms.sparms = parms;
546 	sparms.shadow_db = shadow_tcam_db[parms->dir];
547 
548 	rc = tf_shadow_tcam_search(&sparms);
549 	if (rc)
550 		return rc;
551 
552 	/*
553 	 * The app didn't request us to alloc the entry, so return now.
554 	 * The hit should have been updated in the original search parm.
555 	 */
556 	if (!parms->alloc || parms->search_status != MISS)
557 		return rc;
558 
559 	/* Caller desires an allocate on miss */
560 	if (dev->ops->tf_dev_alloc_tcam == NULL) {
561 		rc = -EOPNOTSUPP;
562 		TFP_DRV_LOG(ERR,
563 			    "%s: Operation not supported, rc:%s\n",
564 			    tf_dir_2_str(parms->dir),
565 			    strerror(-rc));
566 		return rc;
567 	}
568 	memset(&aparms, 0, sizeof(aparms));
569 	aparms.dir = parms->dir;
570 	aparms.type = parms->type;
571 	aparms.key_size = parms->key_size;
572 	aparms.priority = parms->priority;
573 	rc = dev->ops->tf_dev_alloc_tcam(tfp, &aparms);
574 	if (rc)
575 		return rc;
576 
577 	/* Successful allocation, attempt to add it to the shadow */
578 	memset(&bparms, 0, sizeof(bparms));
579 	bparms.dir = parms->dir;
580 	bparms.shadow_db = shadow_tcam_db[parms->dir];
581 	bparms.type = parms->type;
582 	bparms.key = parms->key;
583 	bparms.mask = parms->mask;
584 	bparms.key_size = parms->key_size;
585 	bparms.idx = aparms.idx;
586 	bparms.hb_handle = sparms.hb_handle;
587 	rc = tf_shadow_tcam_bind_index(&bparms);
588 	if (rc) {
589 		/* Error binding entry, need to free the allocated idx */
590 		if (dev->ops->tf_dev_free_tcam == NULL) {
591 			rc = -EOPNOTSUPP;
592 			TFP_DRV_LOG(ERR,
593 				    "%s: Operation not supported, rc:%s\n",
594 				    tf_dir_2_str(parms->dir),
595 				    strerror(-rc));
596 			return rc;
597 		}
598 
599 		fparms.dir = parms->dir;
600 		fparms.type = parms->type;
601 		fparms.idx = aparms.idx;
602 		rc = dev->ops->tf_dev_free_tcam(tfp, &fparms);
603 		if (rc)
604 			return rc;
605 	}
606 
607 	/* Add the allocated index to output and done */
608 	parms->idx = aparms.idx;
609 
610 	return 0;
611 }
612 
613 int
614 tf_tcam_set(struct tf *tfp __rte_unused,
615 	    struct tf_tcam_set_parms *parms __rte_unused)
616 {
617 	int rc;
618 	struct tf_session *tfs;
619 	struct tf_dev_info *dev;
620 	struct tf_rm_is_allocated_parms aparms;
621 	struct tf_rm_get_hcapi_parms hparms;
622 	struct tf_shadow_tcam_insert_parms iparms;
623 	uint16_t num_slice_per_row = 1;
624 	int allocated = 0;
625 	struct tcam_rm_db *tcam_db;
626 	void *tcam_db_ptr = NULL;
627 
628 	TF_CHECK_PARMS2(tfp, parms);
629 
630 	/* Retrieve the session information */
631 	rc = tf_session_get_session_internal(tfp, &tfs);
632 	if (rc)
633 		return rc;
634 
635 	/* Retrieve the device information */
636 	rc = tf_session_get_device(tfs, &dev);
637 	if (rc)
638 		return rc;
639 
640 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
641 		rc = -EOPNOTSUPP;
642 		TFP_DRV_LOG(ERR,
643 			    "%s: Operation not supported, rc:%s\n",
644 			    tf_dir_2_str(parms->dir),
645 			    strerror(-rc));
646 		return rc;
647 	}
648 
649 	/* Need to retrieve row size etc */
650 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
651 						  parms->type,
652 						  parms->key_size,
653 						  &num_slice_per_row);
654 	if (rc)
655 		return rc;
656 
657 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
658 	if (rc) {
659 		TFP_DRV_LOG(ERR,
660 			    "Failed to get em_ext_db from session, rc:%s\n",
661 			    strerror(-rc));
662 		return rc;
663 	}
664 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
665 
666 	/* Check if element is in use */
667 	memset(&aparms, 0, sizeof(aparms));
668 
669 	aparms.rm_db = tcam_db->tcam_db[parms->dir];
670 	aparms.subtype = parms->type;
671 	aparms.index = parms->idx;
672 	aparms.allocated = &allocated;
673 	rc = tf_rm_is_allocated(&aparms);
674 	if (rc)
675 		return rc;
676 
677 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
678 		TFP_DRV_LOG(ERR,
679 			    "%s: Entry is not allocated, type:%d, index:%d\n",
680 			    tf_dir_2_str(parms->dir),
681 			    parms->type,
682 			    parms->idx);
683 		return -EINVAL;
684 	}
685 
686 	/* Convert TF type to HCAPI RM type */
687 	memset(&hparms, 0, sizeof(hparms));
688 
689 	hparms.rm_db = tcam_db->tcam_db[parms->dir];
690 	hparms.subtype = parms->type;
691 	hparms.hcapi_type = &parms->hcapi_type;
692 
693 	rc = tf_rm_get_hcapi_type(&hparms);
694 	if (rc)
695 		return rc;
696 
697 	rc = tf_msg_tcam_entry_set(tfp, dev, parms);
698 	if (rc) {
699 		/* Log error */
700 		TFP_DRV_LOG(ERR,
701 			    "%s: %s: Entry %d set failed, rc:%s",
702 			    tf_dir_2_str(parms->dir),
703 			    tf_tcam_tbl_2_str(parms->type),
704 			    parms->idx,
705 			    strerror(-rc));
706 		return rc;
707 	}
708 
709 	/* Successfully added to hw, now for shadow if enabled. */
710 	if (!shadow_init || !shadow_tcam_db[parms->dir])
711 		return 0;
712 
713 	iparms.shadow_db = shadow_tcam_db[parms->dir];
714 	iparms.sparms = parms;
715 	rc = tf_shadow_tcam_insert(&iparms);
716 	if (rc) {
717 		TFP_DRV_LOG(ERR,
718 			    "%s: %s: Entry %d set failed, rc:%s",
719 			    tf_dir_2_str(parms->dir),
720 			    tf_tcam_tbl_2_str(parms->type),
721 			    parms->idx,
722 			    strerror(-rc));
723 		return rc;
724 	}
725 
726 	return 0;
727 }
728 
729 int
730 tf_tcam_get(struct tf *tfp __rte_unused,
731 	    struct tf_tcam_get_parms *parms)
732 {
733 	int rc;
734 	struct tf_session *tfs;
735 	struct tf_dev_info *dev;
736 	struct tf_rm_is_allocated_parms aparms;
737 	struct tf_rm_get_hcapi_parms hparms;
738 	int allocated = 0;
739 	struct tcam_rm_db *tcam_db;
740 	void *tcam_db_ptr = NULL;
741 
742 	TF_CHECK_PARMS2(tfp, parms);
743 
744 	/* Retrieve the session information */
745 	rc = tf_session_get_session_internal(tfp, &tfs);
746 	if (rc)
747 		return rc;
748 
749 	/* Retrieve the device information */
750 	rc = tf_session_get_device(tfs, &dev);
751 	if (rc)
752 		return rc;
753 
754 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
755 	if (rc) {
756 		TFP_DRV_LOG(ERR,
757 			    "Failed to get em_ext_db from session, rc:%s\n",
758 			    strerror(-rc));
759 		return rc;
760 	}
761 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
762 
763 	/* Check if element is in use */
764 	memset(&aparms, 0, sizeof(aparms));
765 
766 	aparms.rm_db = tcam_db->tcam_db[parms->dir];
767 	aparms.subtype = parms->type;
768 	aparms.index = parms->idx;
769 	aparms.allocated = &allocated;
770 	rc = tf_rm_is_allocated(&aparms);
771 	if (rc)
772 		return rc;
773 
774 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
775 		TFP_DRV_LOG(ERR,
776 			    "%s: Entry is not allocated, type:%d, index:%d\n",
777 			    tf_dir_2_str(parms->dir),
778 			    parms->type,
779 			    parms->idx);
780 		return -EINVAL;
781 	}
782 
783 	/* Convert TF type to HCAPI RM type */
784 	memset(&hparms, 0, sizeof(hparms));
785 
786 	hparms.rm_db = tcam_db->tcam_db[parms->dir];
787 	hparms.subtype = parms->type;
788 	hparms.hcapi_type = &parms->hcapi_type;
789 
790 	rc = tf_rm_get_hcapi_type(&hparms);
791 	if (rc)
792 		return rc;
793 
794 	rc = tf_msg_tcam_entry_get(tfp, dev, parms);
795 	if (rc) {
796 		/* Log error */
797 		TFP_DRV_LOG(ERR,
798 			    "%s: %s: Entry %d set failed, rc:%s",
799 			    tf_dir_2_str(parms->dir),
800 			    tf_tcam_tbl_2_str(parms->type),
801 			    parms->idx,
802 			    strerror(-rc));
803 		return rc;
804 	}
805 
806 	return 0;
807 }
808 
809 int
810 tf_tcam_get_resc_info(struct tf *tfp,
811 		      struct tf_tcam_resource_info *tcam)
812 {
813 	int rc;
814 	int d;
815 	struct tf_resource_info *dinfo;
816 	struct tf_rm_get_alloc_info_parms ainfo;
817 	void *tcam_db_ptr = NULL;
818 	struct tcam_rm_db *tcam_db;
819 
820 	TF_CHECK_PARMS2(tfp, tcam);
821 
822 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
823 	if (rc == -ENOMEM)
824 		return 0;  /* db doesn't exist */
825 	else if (rc)
826 		return rc; /* error getting db */
827 
828 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
829 
830 	/* check if reserved resource for WC is multiple of num_slices */
831 	for (d = 0; d < TF_DIR_MAX; d++) {
832 		ainfo.rm_db = tcam_db->tcam_db[d];
833 
834 		if (!ainfo.rm_db)
835 			continue;
836 
837 		dinfo = tcam[d].info;
838 
839 		ainfo.info = (struct tf_rm_alloc_info *)dinfo;
840 		ainfo.subtype = 0;
841 		rc = tf_rm_get_all_info(&ainfo, TF_TCAM_TBL_TYPE_MAX);
842 		if (rc && rc != -ENOTSUP)
843 			return rc;
844 	}
845 
846 	return 0;
847 }
848