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