xref: /dpdk/drivers/net/bnxt/tf_core/tf_tcam.c (revision aa49b38fa7c350da251b70f455224ae8e3f79d0b)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2023 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_tcam_mgr_msg.h"
18 
19 struct tf;
20 
21 int
22 tf_tcam_bind(struct tf *tfp,
23 	     struct tf_tcam_cfg_parms *parms)
24 {
25 	int rc;
26 	int db_rc[TF_DIR_MAX] = { 0 };
27 	int d, t;
28 	struct tf_rm_alloc_info info;
29 	struct tf_rm_free_db_parms fparms;
30 	struct tf_rm_create_db_parms db_cfg;
31 	struct tf_tcam_resources local_tcam_cnt[TF_DIR_MAX];
32 	struct tf_tcam_resources *tcam_cnt;
33 	struct tf_rm_get_alloc_info_parms ainfo;
34 	uint16_t num_slices = 1;
35 	struct tf_session *tfs;
36 	struct tf_dev_info *dev;
37 	struct tcam_rm_db *tcam_db;
38 	struct tfp_calloc_parms cparms;
39 	struct tf_resource_info resv_res[TF_DIR_MAX][TF_TCAM_TBL_TYPE_MAX];
40 	uint32_t rx_supported;
41 	uint32_t tx_supported;
42 	bool no_req = true;
43 
44 	TF_CHECK_PARMS2(tfp, parms);
45 
46 	/* Retrieve the session information */
47 	rc = tf_session_get_session_internal(tfp, &tfs);
48 	if (rc)
49 		return rc;
50 
51 	/* Retrieve the device information */
52 	rc = tf_session_get_device(tfs, &dev);
53 	if (rc)
54 		return rc;
55 
56 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
57 		rc = -EOPNOTSUPP;
58 		TFP_DRV_LOG(ERR,
59 			    "Operation not supported, rc:%s\n",
60 			    strerror(-rc));
61 		return rc;
62 	}
63 
64 	tcam_cnt = parms->resources->tcam_cnt;
65 
66 	for (d = 0; d < TF_DIR_MAX; d++) {
67 		for (t = 0; t < TF_TCAM_TBL_TYPE_MAX; t++) {
68 			rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, t, 0,
69 								  &num_slices);
70 	if (rc)
71 		return rc;
72 
73 			if (num_slices == 1)
74 				continue;
75 
76 			if (tcam_cnt[d].cnt[t] % num_slices) {
77 				TFP_DRV_LOG(ERR,
78 					    "%s: Requested num of %s entries "
79 					    "has to be multiple of %d\n",
80 					    tf_dir_2_str(d),
81 					    tf_tcam_tbl_2_str(t),
82 					    num_slices);
83 				return -EINVAL;
84 			}
85 		}
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 (d = 0; d < TF_DIR_MAX; d++)
100 		tcam_db->tcam_db[d] = 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 = 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 	/* No db created */
118 	if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) {
119 		TFP_DRV_LOG(ERR, "No TCAM DB created\n");
120 		return db_rc[TF_DIR_RX];
121 	}
122 
123 	/* Collect info on which entries were reserved. */
124 	for (d = 0; d < TF_DIR_MAX; d++) {
125 		for (t = 0; t < TF_TCAM_TBL_TYPE_MAX; t++) {
126 			memset(&info, 0, sizeof(info));
127 			if (tcam_cnt[d].cnt[t] == 0) {
128 				resv_res[d][t].start  = 0;
129 				resv_res[d][t].stride = 0;
130 				continue;
131 			}
132 			ainfo.rm_db = tcam_db->tcam_db[d];
133 			ainfo.subtype = t;
134 			ainfo.info = &info;
135 			rc = tf_rm_get_info(&ainfo);
136 			if (rc)
137 				goto error;
138 
139 			rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, t, 0,
140 								  &num_slices);
141 			if (rc)
142 				return rc;
143 
144 			if (num_slices > 1) {
145 				/* check if reserved resource for is multiple of
146 				 * num_slices
147 				 */
148 				if (info.entry.start % num_slices != 0 ||
149 				    info.entry.stride % num_slices != 0) {
150 					TFP_DRV_LOG(ERR,
151 						    "%s: %s reserved resource"
152 						    " is not multiple of %d\n",
153 						    tf_dir_2_str(d),
154 						    tf_tcam_tbl_2_str(t),
155 						    num_slices);
156 					rc = -EINVAL;
157 					goto error;
158 				}
159 			}
160 
161 			resv_res[d][t].start  = info.entry.start;
162 			resv_res[d][t].stride = info.entry.stride;
163 		}
164 	}
165 
166 	rc = tf_tcam_mgr_bind_msg(tfp, dev, parms, resv_res);
167 	if (rc)
168 		return rc;
169 
170 	rc = tf_tcam_mgr_qcaps_msg(tfp, dev,
171 				   &rx_supported, &tx_supported);
172 	if (rc)
173 		return rc;
174 
175 	for (t = 0; t < TF_TCAM_TBL_TYPE_MAX; t++) {
176 		if (rx_supported & 1 << t)
177 			tfs->tcam_mgr_control[TF_DIR_RX][t] = 1;
178 		if (tx_supported & 1 << t)
179 			tfs->tcam_mgr_control[TF_DIR_TX][t] = 1;
180 	}
181 
182 	/*
183 	 * Make a local copy of tcam_cnt with only resources not managed by TCAM
184 	 * Manager requested.
185 	 */
186 	memcpy(&local_tcam_cnt, tcam_cnt, sizeof(local_tcam_cnt));
187 	tcam_cnt = local_tcam_cnt;
188 	for (d = 0; d < TF_DIR_MAX; d++) {
189 		for (t = 0; t < TF_TCAM_TBL_TYPE_MAX; t++) {
190 			/* If controlled by TCAM Manager */
191 			if (tfs->tcam_mgr_control[d][t])
192 				tcam_cnt[d].cnt[t] = 0;
193 			else if (tcam_cnt[d].cnt[t] > 0)
194 				no_req = false;
195 		}
196 	}
197 
198 	/* If no resources left to request */
199 	if (no_req)
200 		goto finished;
201 
202 finished:
203 	TFP_DRV_LOG(INFO,
204 		    "TCAM - initialized\n");
205 
206 	return 0;
207 error:
208 	for (d = 0; d < TF_DIR_MAX; d++) {
209 		if (tcam_db->tcam_db[d] != NULL) {
210 			memset(&fparms, 0, sizeof(fparms));
211 			fparms.dir = d;
212 			fparms.rm_db = tcam_db->tcam_db[d];
213 			/*
214 			 * Ignoring return here since we are in the error case
215 			 */
216 			(void)tf_rm_free_db(tfp, &fparms);
217 
218 			tcam_db->tcam_db[d] = NULL;
219 		}
220 		tcam_db->tcam_db[d] = NULL;
221 		tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, NULL);
222 	}
223 	return rc;
224 }
225 
226 int
227 tf_tcam_unbind(struct tf *tfp)
228 {
229 	int rc;
230 	int i;
231 	struct tf_rm_free_db_parms fparms;
232 	struct tcam_rm_db *tcam_db;
233 	void *tcam_db_ptr = NULL;
234 	struct tf_session *tfs;
235 	struct tf_dev_info *dev;
236 	TF_CHECK_PARMS1(tfp);
237 
238 	/* Retrieve the session information */
239 	rc = tf_session_get_session_internal(tfp, &tfs);
240 	if (rc)
241 		return rc;
242 
243 	/* Retrieve the device information */
244 	rc = tf_session_get_device(tfs, &dev);
245 	if (rc)
246 		return rc;
247 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
248 	if (rc)
249 		return 0;
250 
251 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
252 
253 	for (i = 0; i < TF_DIR_MAX; i++) {
254 		if (tcam_db->tcam_db[i] != NULL) {
255 			memset(&fparms, 0, sizeof(fparms));
256 			fparms.dir = i;
257 			fparms.rm_db = tcam_db->tcam_db[i];
258 			rc = tf_rm_free_db(tfp, &fparms);
259 			if (rc)
260 				return rc;
261 
262 			tcam_db->tcam_db[i] = NULL;
263 		}
264 	}
265 
266 	rc = tf_tcam_mgr_unbind_msg(tfp, dev);
267 	if (rc)
268 		return rc;
269 
270 	return 0;
271 }
272 
273 int
274 tf_tcam_alloc(struct tf *tfp,
275 	      struct tf_tcam_alloc_parms *parms)
276 {
277 	int rc, i;
278 	struct tf_session *tfs;
279 	struct tf_dev_info *dev;
280 	struct tf_rm_allocate_parms aparms;
281 	uint16_t num_slices = 1;
282 	uint32_t index;
283 	struct tcam_rm_db *tcam_db;
284 	void *tcam_db_ptr = NULL;
285 
286 	TF_CHECK_PARMS2(tfp, parms);
287 
288 	/* Retrieve the session information */
289 	rc = tf_session_get_session_internal(tfp, &tfs);
290 	if (rc)
291 		return rc;
292 
293 	/* Retrieve the device information */
294 	rc = tf_session_get_device(tfs, &dev);
295 	if (rc)
296 		return rc;
297 
298 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
299 		rc = -EOPNOTSUPP;
300 		TFP_DRV_LOG(ERR,
301 			    "%s: Operation not supported, rc:%s\n",
302 			    tf_dir_2_str(parms->dir),
303 			    strerror(-rc));
304 		return rc;
305 	}
306 
307 	/* Need to retrieve number of slices based on the key_size */
308 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
309 						  parms->type,
310 						  parms->key_size,
311 						  &num_slices);
312 	if (rc)
313 		return rc;
314 
315 	/* If TCAM controlled by TCAM Manager */
316 	if (tfs->tcam_mgr_control[parms->dir][parms->type])
317 		return tf_tcam_mgr_alloc_msg(tfp, dev, parms);
318 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
319 	if (rc) {
320 		TFP_DRV_LOG(ERR,
321 			    "Failed to get tcam_db from session, rc:%s\n",
322 			    strerror(-rc));
323 		return rc;
324 	}
325 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
326 
327 	/*
328 	 * For WC TCAM, number of slices could be 4, 2, 1 based on
329 	 * the key_size. For other TCAM, it is always 1
330 	 */
331 	for (i = 0; i < num_slices; i++) {
332 		memset(&aparms, 0, sizeof(aparms));
333 		aparms.rm_db = tcam_db->tcam_db[parms->dir];
334 		aparms.subtype = parms->type;
335 		aparms.priority = parms->priority;
336 		aparms.index = &index;
337 		rc = tf_rm_allocate(&aparms);
338 		if (rc) {
339 			TFP_DRV_LOG(ERR,
340 				    "%s: Failed tcam, type:%d\n",
341 				    tf_dir_2_str(parms->dir),
342 				    parms->type);
343 			return rc;
344 		}
345 
346 		/* return the start index of each row */
347 			if (i == 0)
348 				parms->idx = index;
349 	}
350 
351 	return 0;
352 }
353 
354 int
355 tf_tcam_free(struct tf *tfp,
356 	     struct tf_tcam_free_parms *parms)
357 {
358 	int rc;
359 	struct tf_session *tfs;
360 	struct tf_dev_info *dev;
361 	struct tf_rm_is_allocated_parms aparms;
362 	struct tf_rm_free_parms fparms;
363 	struct tf_rm_get_hcapi_parms hparms;
364 	uint16_t num_slices = 1;
365 	int allocated = 0;
366 	int i;
367 	struct tcam_rm_db *tcam_db;
368 	void *tcam_db_ptr = NULL;
369 
370 	TF_CHECK_PARMS2(tfp, parms);
371 
372 	/* Retrieve the session information */
373 	rc = tf_session_get_session_internal(tfp, &tfs);
374 	if (rc)
375 		return rc;
376 
377 	/* Retrieve the device information */
378 	rc = tf_session_get_device(tfs, &dev);
379 	if (rc)
380 		return rc;
381 
382 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
383 		rc = -EOPNOTSUPP;
384 		TFP_DRV_LOG(ERR,
385 			    "%s: Operation not supported, rc:%s\n",
386 			    tf_dir_2_str(parms->dir),
387 			    strerror(-rc));
388 		return rc;
389 	}
390 
391 	/* Need to retrieve row size etc */
392 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
393 						  parms->type,
394 						  0,
395 						  &num_slices);
396 	if (rc)
397 		return rc;
398 
399 	/* If TCAM controlled by TCAM Manager */
400 	if (tfs->tcam_mgr_control[parms->dir][parms->type])
401 		/*
402 		 * If a session can have multiple references to an entry, check
403 		 * the reference count here before actually freeing the entry.
404 		 */
405 		return tf_tcam_mgr_free_msg(tfp, dev, parms);
406 
407 	if (parms->idx % num_slices) {
408 		TFP_DRV_LOG(ERR,
409 			    "%s: TCAM reserved resource is not multiple of %d\n",
410 			    tf_dir_2_str(parms->dir),
411 			    num_slices);
412 		return -EINVAL;
413 	}
414 
415 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
416 	if (rc) {
417 		TFP_DRV_LOG(ERR,
418 			    "Failed to get em_ext_db from session, rc:%s\n",
419 			    strerror(-rc));
420 		return rc;
421 	}
422 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
423 
424 	/* Check if element is in use */
425 	memset(&aparms, 0, sizeof(aparms));
426 	aparms.rm_db = tcam_db->tcam_db[parms->dir];
427 	aparms.subtype = parms->type;
428 	aparms.index = parms->idx;
429 	aparms.allocated = &allocated;
430 	rc = tf_rm_is_allocated(&aparms);
431 	if (rc)
432 		return rc;
433 
434 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
435 		TFP_DRV_LOG(ERR,
436 			    "%s: Entry already free, type:%d, index:%d\n",
437 			    tf_dir_2_str(parms->dir),
438 			    parms->type,
439 			    parms->idx);
440 		return -EINVAL;
441 	}
442 
443 	for (i = 0; i < num_slices; i++) {
444 		/* Free requested element */
445 		memset(&fparms, 0, sizeof(fparms));
446 		fparms.rm_db = tcam_db->tcam_db[parms->dir];
447 		fparms.subtype = parms->type;
448 		fparms.index = parms->idx + i;
449 		rc = tf_rm_free(&fparms);
450 		if (rc) {
451 			TFP_DRV_LOG(ERR,
452 				    "%s: Free failed, type:%d, index:%d\n",
453 				    tf_dir_2_str(parms->dir),
454 				    parms->type,
455 				    parms->idx);
456 			return rc;
457 		}
458 	}
459 
460 	/* Convert TF type to HCAPI RM type */
461 	memset(&hparms, 0, sizeof(hparms));
462 
463 	hparms.rm_db = tcam_db->tcam_db[parms->dir];
464 	hparms.subtype = parms->type;
465 	hparms.hcapi_type = &parms->hcapi_type;
466 
467 	rc = tf_rm_get_hcapi_type(&hparms);
468 	if (rc)
469 		return rc;
470 
471 	rc = tf_msg_tcam_entry_free(tfp, dev, parms);
472 	if (rc) {
473 		/* Log error */
474 		TFP_DRV_LOG(ERR,
475 			    "%s: %s: Entry %d free failed, rc:%s\n",
476 			    tf_dir_2_str(parms->dir),
477 			    tf_tcam_tbl_2_str(parms->type),
478 			    parms->idx,
479 			    strerror(-rc));
480 		return rc;
481 	}
482 
483 	return 0;
484 }
485 
486 int
487 tf_tcam_set(struct tf *tfp __rte_unused,
488 	    struct tf_tcam_set_parms *parms __rte_unused)
489 {
490 	int rc;
491 	struct tf_session *tfs;
492 	struct tf_dev_info *dev;
493 	struct tf_rm_is_allocated_parms aparms;
494 	struct tf_rm_get_hcapi_parms hparms;
495 	uint16_t num_slice_per_row = 1;
496 	int allocated = 0;
497 	struct tcam_rm_db *tcam_db;
498 	void *tcam_db_ptr = NULL;
499 
500 	TF_CHECK_PARMS2(tfp, parms);
501 
502 	/* Retrieve the session information */
503 	rc = tf_session_get_session_internal(tfp, &tfs);
504 	if (rc)
505 		return rc;
506 
507 	/* Retrieve the device information */
508 	rc = tf_session_get_device(tfs, &dev);
509 	if (rc)
510 		return rc;
511 
512 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
513 		rc = -EOPNOTSUPP;
514 		TFP_DRV_LOG(ERR,
515 			    "%s: Operation not supported, rc:%s\n",
516 			    tf_dir_2_str(parms->dir),
517 			    strerror(-rc));
518 		return rc;
519 	}
520 
521 	/* Need to retrieve row size etc */
522 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
523 						  parms->type,
524 						  parms->key_size,
525 						  &num_slice_per_row);
526 	if (rc)
527 		return rc;
528 
529 	/* If TCAM controlled by TCAM Manager */
530 	if (tfs->tcam_mgr_control[parms->dir][parms->type])
531 		return tf_tcam_mgr_set_msg(tfp, dev, parms);
532 
533 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
534 	if (rc) {
535 		TFP_DRV_LOG(ERR,
536 			    "Failed to get em_ext_db from session, rc:%s\n",
537 			    strerror(-rc));
538 		return rc;
539 	}
540 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
541 
542 	/* Check if element is in use */
543 	memset(&aparms, 0, sizeof(aparms));
544 
545 	aparms.rm_db = tcam_db->tcam_db[parms->dir];
546 	aparms.subtype = parms->type;
547 	aparms.index = parms->idx;
548 	aparms.allocated = &allocated;
549 	rc = tf_rm_is_allocated(&aparms);
550 	if (rc)
551 		return rc;
552 
553 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
554 		TFP_DRV_LOG(ERR,
555 			    "%s: Entry is not allocated, type:%d, index:%d\n",
556 			    tf_dir_2_str(parms->dir),
557 			    parms->type,
558 			    parms->idx);
559 		return -EINVAL;
560 	}
561 
562 	/* Convert TF type to HCAPI RM type */
563 	memset(&hparms, 0, sizeof(hparms));
564 
565 	hparms.rm_db = tcam_db->tcam_db[parms->dir];
566 	hparms.subtype = parms->type;
567 	hparms.hcapi_type = &parms->hcapi_type;
568 
569 	rc = tf_rm_get_hcapi_type(&hparms);
570 	if (rc)
571 		return rc;
572 
573 	rc = tf_msg_tcam_entry_set(tfp, dev, parms);
574 	if (rc) {
575 		/* Log error */
576 		TFP_DRV_LOG(ERR,
577 			    "%s: %s: Entry %d set failed, rc:%s",
578 			    tf_dir_2_str(parms->dir),
579 			    tf_tcam_tbl_2_str(parms->type),
580 			    parms->idx,
581 			    strerror(-rc));
582 		return rc;
583 	}
584 	return 0;
585 }
586 
587 int
588 tf_tcam_get(struct tf *tfp __rte_unused,
589 	    struct tf_tcam_get_parms *parms)
590 {
591 	int rc;
592 	struct tf_session *tfs;
593 	struct tf_dev_info *dev;
594 	struct tf_rm_is_allocated_parms aparms;
595 	struct tf_rm_get_hcapi_parms hparms;
596 	int allocated = 0;
597 	struct tcam_rm_db *tcam_db;
598 	void *tcam_db_ptr = NULL;
599 
600 	TF_CHECK_PARMS2(tfp, parms);
601 
602 	/* Retrieve the session information */
603 	rc = tf_session_get_session_internal(tfp, &tfs);
604 	if (rc)
605 		return rc;
606 
607 	/* Retrieve the device information */
608 	rc = tf_session_get_device(tfs, &dev);
609 	if (rc)
610 		return rc;
611 
612 	/* If TCAM controlled by TCAM Manager */
613 	if (tfs->tcam_mgr_control[parms->dir][parms->type])
614 		return tf_tcam_mgr_get_msg(tfp, dev, parms);
615 
616 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
617 	if (rc) {
618 		TFP_DRV_LOG(ERR,
619 			    "Failed to get em_ext_db from session, rc:%s\n",
620 			    strerror(-rc));
621 		return rc;
622 	}
623 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
624 
625 	/* Check if element is in use */
626 	memset(&aparms, 0, sizeof(aparms));
627 
628 	aparms.rm_db = tcam_db->tcam_db[parms->dir];
629 	aparms.subtype = parms->type;
630 	aparms.index = parms->idx;
631 	aparms.allocated = &allocated;
632 	rc = tf_rm_is_allocated(&aparms);
633 	if (rc)
634 		return rc;
635 
636 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
637 		TFP_DRV_LOG(ERR,
638 			    "%s: Entry is not allocated, type:%d, index:%d\n",
639 			    tf_dir_2_str(parms->dir),
640 			    parms->type,
641 			    parms->idx);
642 		return -EINVAL;
643 	}
644 
645 	/* Convert TF type to HCAPI RM type */
646 	memset(&hparms, 0, sizeof(hparms));
647 
648 	hparms.rm_db = tcam_db->tcam_db[parms->dir];
649 	hparms.subtype = parms->type;
650 	hparms.hcapi_type = &parms->hcapi_type;
651 
652 	rc = tf_rm_get_hcapi_type(&hparms);
653 	if (rc)
654 		return rc;
655 
656 	rc = tf_msg_tcam_entry_get(tfp, dev, parms);
657 	if (rc) {
658 		/* Log error */
659 		TFP_DRV_LOG(ERR,
660 			    "%s: %s: Entry %d set failed, rc:%s",
661 			    tf_dir_2_str(parms->dir),
662 			    tf_tcam_tbl_2_str(parms->type),
663 			    parms->idx,
664 			    strerror(-rc));
665 		return rc;
666 	}
667 
668 	return 0;
669 }
670 
671 int
672 tf_tcam_get_resc_info(struct tf *tfp,
673 		      struct tf_tcam_resource_info *tcam)
674 {
675 	int rc;
676 	int d;
677 	struct tf_resource_info *dinfo;
678 	struct tf_rm_get_alloc_info_parms ainfo;
679 	void *tcam_db_ptr = NULL;
680 	struct tcam_rm_db *tcam_db;
681 
682 	TF_CHECK_PARMS2(tfp, tcam);
683 
684 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
685 	if (rc == -ENOMEM)
686 		return 0;  /* db doesn't exist */
687 	else if (rc)
688 		return rc; /* error getting db */
689 
690 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
691 
692 	/* check if reserved resource for WC is multiple of num_slices */
693 	for (d = 0; d < TF_DIR_MAX; d++) {
694 		ainfo.rm_db = tcam_db->tcam_db[d];
695 
696 		if (!ainfo.rm_db)
697 			continue;
698 
699 		dinfo = tcam[d].info;
700 
701 		ainfo.info = (struct tf_rm_alloc_info *)dinfo;
702 		ainfo.subtype = 0;
703 		rc = tf_rm_get_all_info(&ainfo, TF_TCAM_TBL_TYPE_MAX);
704 		if (rc && rc != -ENOTSUP)
705 			return rc;
706 	}
707 
708 	return 0;
709 }
710