xref: /dpdk/drivers/net/bnxt/tf_core/tf_tcam.c (revision 7917b0d38e92e8b9ec5a870415b791420e10f11a)
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 
267 	rc = tf_tcam_mgr_unbind_msg(tfp, dev);
268 	if (rc)
269 		return rc;
270 
271 	return 0;
272 }
273 
274 int
275 tf_tcam_alloc(struct tf *tfp,
276 	      struct tf_tcam_alloc_parms *parms)
277 {
278 	int rc, i;
279 	struct tf_session *tfs;
280 	struct tf_dev_info *dev;
281 	struct tf_rm_allocate_parms aparms;
282 	uint16_t num_slices = 1;
283 	uint32_t index;
284 	struct tcam_rm_db *tcam_db;
285 	void *tcam_db_ptr = NULL;
286 
287 	TF_CHECK_PARMS2(tfp, parms);
288 
289 	/* Retrieve the session information */
290 	rc = tf_session_get_session_internal(tfp, &tfs);
291 	if (rc)
292 		return rc;
293 
294 	/* Retrieve the device information */
295 	rc = tf_session_get_device(tfs, &dev);
296 	if (rc)
297 		return rc;
298 
299 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
300 		rc = -EOPNOTSUPP;
301 		TFP_DRV_LOG(ERR,
302 			    "%s: Operation not supported, rc:%s\n",
303 			    tf_dir_2_str(parms->dir),
304 			    strerror(-rc));
305 		return rc;
306 	}
307 
308 	/* Need to retrieve number of slices based on the key_size */
309 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
310 						  parms->type,
311 						  parms->key_size,
312 						  &num_slices);
313 	if (rc)
314 		return rc;
315 
316 	/* If TCAM controlled by TCAM Manager */
317 	if (tfs->tcam_mgr_control[parms->dir][parms->type])
318 		return tf_tcam_mgr_alloc_msg(tfp, dev, parms);
319 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
320 	if (rc) {
321 		TFP_DRV_LOG(ERR,
322 			    "Failed to get tcam_db from session, rc:%s\n",
323 			    strerror(-rc));
324 		return rc;
325 	}
326 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
327 
328 	/*
329 	 * For WC TCAM, number of slices could be 4, 2, 1 based on
330 	 * the key_size. For other TCAM, it is always 1
331 	 */
332 	for (i = 0; i < num_slices; i++) {
333 		memset(&aparms, 0, sizeof(aparms));
334 		aparms.rm_db = tcam_db->tcam_db[parms->dir];
335 		aparms.subtype = parms->type;
336 		aparms.priority = parms->priority;
337 		aparms.index = &index;
338 		rc = tf_rm_allocate(&aparms);
339 		if (rc) {
340 			TFP_DRV_LOG(ERR,
341 				    "%s: Failed tcam, type:%d\n",
342 				    tf_dir_2_str(parms->dir),
343 				    parms->type);
344 			return rc;
345 		}
346 
347 		/* return the start index of each row */
348 			if (i == 0)
349 				parms->idx = index;
350 	}
351 
352 	return 0;
353 }
354 
355 int
356 tf_tcam_free(struct tf *tfp,
357 	     struct tf_tcam_free_parms *parms)
358 {
359 	int rc;
360 	struct tf_session *tfs;
361 	struct tf_dev_info *dev;
362 	struct tf_rm_is_allocated_parms aparms;
363 	struct tf_rm_free_parms fparms;
364 	struct tf_rm_get_hcapi_parms hparms;
365 	uint16_t num_slices = 1;
366 	int allocated = 0;
367 	int i;
368 	struct tcam_rm_db *tcam_db;
369 	void *tcam_db_ptr = NULL;
370 
371 	TF_CHECK_PARMS2(tfp, parms);
372 
373 	/* Retrieve the session information */
374 	rc = tf_session_get_session_internal(tfp, &tfs);
375 	if (rc)
376 		return rc;
377 
378 	/* Retrieve the device information */
379 	rc = tf_session_get_device(tfs, &dev);
380 	if (rc)
381 		return rc;
382 
383 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
384 		rc = -EOPNOTSUPP;
385 		TFP_DRV_LOG(ERR,
386 			    "%s: Operation not supported, rc:%s\n",
387 			    tf_dir_2_str(parms->dir),
388 			    strerror(-rc));
389 		return rc;
390 	}
391 
392 	/* Need to retrieve row size etc */
393 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
394 						  parms->type,
395 						  0,
396 						  &num_slices);
397 	if (rc)
398 		return rc;
399 
400 	/* If TCAM controlled by TCAM Manager */
401 	if (tfs->tcam_mgr_control[parms->dir][parms->type])
402 		/*
403 		 * If a session can have multiple references to an entry, check
404 		 * the reference count here before actually freeing the entry.
405 		 */
406 		return tf_tcam_mgr_free_msg(tfp, dev, parms);
407 
408 	if (parms->idx % num_slices) {
409 		TFP_DRV_LOG(ERR,
410 			    "%s: TCAM reserved resource is not multiple of %d\n",
411 			    tf_dir_2_str(parms->dir),
412 			    num_slices);
413 		return -EINVAL;
414 	}
415 
416 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
417 	if (rc) {
418 		TFP_DRV_LOG(ERR,
419 			    "Failed to get em_ext_db from session, rc:%s\n",
420 			    strerror(-rc));
421 		return rc;
422 	}
423 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
424 
425 	/* Check if element is in use */
426 	memset(&aparms, 0, sizeof(aparms));
427 	aparms.rm_db = tcam_db->tcam_db[parms->dir];
428 	aparms.subtype = parms->type;
429 	aparms.index = parms->idx;
430 	aparms.allocated = &allocated;
431 	rc = tf_rm_is_allocated(&aparms);
432 	if (rc)
433 		return rc;
434 
435 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
436 		TFP_DRV_LOG(ERR,
437 			    "%s: Entry already free, type:%d, index:%d\n",
438 			    tf_dir_2_str(parms->dir),
439 			    parms->type,
440 			    parms->idx);
441 		return -EINVAL;
442 	}
443 
444 	for (i = 0; i < num_slices; i++) {
445 		/* Free requested element */
446 		memset(&fparms, 0, sizeof(fparms));
447 		fparms.rm_db = tcam_db->tcam_db[parms->dir];
448 		fparms.subtype = parms->type;
449 		fparms.index = parms->idx + i;
450 		rc = tf_rm_free(&fparms);
451 		if (rc) {
452 			TFP_DRV_LOG(ERR,
453 				    "%s: Free failed, type:%d, index:%d\n",
454 				    tf_dir_2_str(parms->dir),
455 				    parms->type,
456 				    parms->idx);
457 			return rc;
458 		}
459 	}
460 
461 	/* Convert TF type to HCAPI RM type */
462 	memset(&hparms, 0, sizeof(hparms));
463 
464 	hparms.rm_db = tcam_db->tcam_db[parms->dir];
465 	hparms.subtype = parms->type;
466 	hparms.hcapi_type = &parms->hcapi_type;
467 
468 	rc = tf_rm_get_hcapi_type(&hparms);
469 	if (rc)
470 		return rc;
471 
472 	rc = tf_msg_tcam_entry_free(tfp, dev, parms);
473 	if (rc) {
474 		/* Log error */
475 		TFP_DRV_LOG(ERR,
476 			    "%s: %s: Entry %d free failed, rc:%s\n",
477 			    tf_dir_2_str(parms->dir),
478 			    tf_tcam_tbl_2_str(parms->type),
479 			    parms->idx,
480 			    strerror(-rc));
481 		return rc;
482 	}
483 
484 	return 0;
485 }
486 
487 int
488 tf_tcam_set(struct tf *tfp __rte_unused,
489 	    struct tf_tcam_set_parms *parms __rte_unused)
490 {
491 	int rc;
492 	struct tf_session *tfs;
493 	struct tf_dev_info *dev;
494 	struct tf_rm_is_allocated_parms aparms;
495 	struct tf_rm_get_hcapi_parms hparms;
496 	uint16_t num_slice_per_row = 1;
497 	int allocated = 0;
498 	struct tcam_rm_db *tcam_db;
499 	void *tcam_db_ptr = NULL;
500 
501 	TF_CHECK_PARMS2(tfp, parms);
502 
503 	/* Retrieve the session information */
504 	rc = tf_session_get_session_internal(tfp, &tfs);
505 	if (rc)
506 		return rc;
507 
508 	/* Retrieve the device information */
509 	rc = tf_session_get_device(tfs, &dev);
510 	if (rc)
511 		return rc;
512 
513 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
514 		rc = -EOPNOTSUPP;
515 		TFP_DRV_LOG(ERR,
516 			    "%s: Operation not supported, rc:%s\n",
517 			    tf_dir_2_str(parms->dir),
518 			    strerror(-rc));
519 		return rc;
520 	}
521 
522 	/* Need to retrieve row size etc */
523 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
524 						  parms->type,
525 						  parms->key_size,
526 						  &num_slice_per_row);
527 	if (rc)
528 		return rc;
529 
530 	/* If TCAM controlled by TCAM Manager */
531 	if (tfs->tcam_mgr_control[parms->dir][parms->type])
532 		return tf_tcam_mgr_set_msg(tfp, dev, parms);
533 
534 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
535 	if (rc) {
536 		TFP_DRV_LOG(ERR,
537 			    "Failed to get em_ext_db from session, rc:%s\n",
538 			    strerror(-rc));
539 		return rc;
540 	}
541 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
542 
543 	/* Check if element is in use */
544 	memset(&aparms, 0, sizeof(aparms));
545 
546 	aparms.rm_db = tcam_db->tcam_db[parms->dir];
547 	aparms.subtype = parms->type;
548 	aparms.index = parms->idx;
549 	aparms.allocated = &allocated;
550 	rc = tf_rm_is_allocated(&aparms);
551 	if (rc)
552 		return rc;
553 
554 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
555 		TFP_DRV_LOG(ERR,
556 			    "%s: Entry is not allocated, type:%d, index:%d\n",
557 			    tf_dir_2_str(parms->dir),
558 			    parms->type,
559 			    parms->idx);
560 		return -EINVAL;
561 	}
562 
563 	/* Convert TF type to HCAPI RM type */
564 	memset(&hparms, 0, sizeof(hparms));
565 
566 	hparms.rm_db = tcam_db->tcam_db[parms->dir];
567 	hparms.subtype = parms->type;
568 	hparms.hcapi_type = &parms->hcapi_type;
569 
570 	rc = tf_rm_get_hcapi_type(&hparms);
571 	if (rc)
572 		return rc;
573 
574 	rc = tf_msg_tcam_entry_set(tfp, dev, parms);
575 	if (rc) {
576 		/* Log error */
577 		TFP_DRV_LOG(ERR,
578 			    "%s: %s: Entry %d set failed, rc:%s",
579 			    tf_dir_2_str(parms->dir),
580 			    tf_tcam_tbl_2_str(parms->type),
581 			    parms->idx,
582 			    strerror(-rc));
583 		return rc;
584 	}
585 	return 0;
586 }
587 
588 int
589 tf_tcam_get(struct tf *tfp __rte_unused,
590 	    struct tf_tcam_get_parms *parms)
591 {
592 	int rc;
593 	struct tf_session *tfs;
594 	struct tf_dev_info *dev;
595 	struct tf_rm_is_allocated_parms aparms;
596 	struct tf_rm_get_hcapi_parms hparms;
597 	int allocated = 0;
598 	struct tcam_rm_db *tcam_db;
599 	void *tcam_db_ptr = NULL;
600 
601 	TF_CHECK_PARMS2(tfp, parms);
602 
603 	/* Retrieve the session information */
604 	rc = tf_session_get_session_internal(tfp, &tfs);
605 	if (rc)
606 		return rc;
607 
608 	/* Retrieve the device information */
609 	rc = tf_session_get_device(tfs, &dev);
610 	if (rc)
611 		return rc;
612 
613 	/* If TCAM controlled by TCAM Manager */
614 	if (tfs->tcam_mgr_control[parms->dir][parms->type])
615 		return tf_tcam_mgr_get_msg(tfp, dev, parms);
616 
617 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
618 	if (rc) {
619 		TFP_DRV_LOG(ERR,
620 			    "Failed to get em_ext_db from session, rc:%s\n",
621 			    strerror(-rc));
622 		return rc;
623 	}
624 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
625 
626 	/* Check if element is in use */
627 	memset(&aparms, 0, sizeof(aparms));
628 
629 	aparms.rm_db = tcam_db->tcam_db[parms->dir];
630 	aparms.subtype = parms->type;
631 	aparms.index = parms->idx;
632 	aparms.allocated = &allocated;
633 	rc = tf_rm_is_allocated(&aparms);
634 	if (rc)
635 		return rc;
636 
637 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
638 		TFP_DRV_LOG(ERR,
639 			    "%s: Entry is not allocated, type:%d, index:%d\n",
640 			    tf_dir_2_str(parms->dir),
641 			    parms->type,
642 			    parms->idx);
643 		return -EINVAL;
644 	}
645 
646 	/* Convert TF type to HCAPI RM type */
647 	memset(&hparms, 0, sizeof(hparms));
648 
649 	hparms.rm_db = tcam_db->tcam_db[parms->dir];
650 	hparms.subtype = parms->type;
651 	hparms.hcapi_type = &parms->hcapi_type;
652 
653 	rc = tf_rm_get_hcapi_type(&hparms);
654 	if (rc)
655 		return rc;
656 
657 	rc = tf_msg_tcam_entry_get(tfp, dev, parms);
658 	if (rc) {
659 		/* Log error */
660 		TFP_DRV_LOG(ERR,
661 			    "%s: %s: Entry %d set failed, rc:%s",
662 			    tf_dir_2_str(parms->dir),
663 			    tf_tcam_tbl_2_str(parms->type),
664 			    parms->idx,
665 			    strerror(-rc));
666 		return rc;
667 	}
668 
669 	return 0;
670 }
671 
672 int
673 tf_tcam_get_resc_info(struct tf *tfp,
674 		      struct tf_tcam_resource_info *tcam)
675 {
676 	int rc;
677 	int d;
678 	struct tf_resource_info *dinfo;
679 	struct tf_rm_get_alloc_info_parms ainfo;
680 	void *tcam_db_ptr = NULL;
681 	struct tcam_rm_db *tcam_db;
682 
683 	TF_CHECK_PARMS2(tfp, tcam);
684 
685 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
686 	if (rc == -ENOMEM)
687 		return 0;  /* db doesn't exist */
688 	else if (rc)
689 		return rc; /* error getting db */
690 
691 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
692 
693 	/* check if reserved resource for WC is multiple of num_slices */
694 	for (d = 0; d < TF_DIR_MAX; d++) {
695 		ainfo.rm_db = tcam_db->tcam_db[d];
696 
697 		if (!ainfo.rm_db)
698 			continue;
699 
700 		dinfo = tcam[d].info;
701 
702 		ainfo.info = (struct tf_rm_alloc_info *)dinfo;
703 		ainfo.subtype = 0;
704 		rc = tf_rm_get_all_info(&ainfo, TF_TCAM_TBL_TYPE_MAX);
705 		if (rc && rc != -ENOTSUP)
706 			return rc;
707 	}
708 
709 	return 0;
710 }
711