xref: /dpdk/drivers/net/bnxt/tf_core/tf_tcam_shared.c (revision 37ff91c1)
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_shared.h"
10 #include "tf_tcam.h"
11 #include "tf_common.h"
12 #include "tf_util.h"
13 #include "tf_rm.h"
14 #include "tf_device.h"
15 #include "tfp.h"
16 #include "tf_session.h"
17 #include "tf_msg.h"
18 #include "bitalloc.h"
19 #include "tf_core.h"
20 
21 /** Shared WC TCAM pool identifiers
22  */
23 enum tf_tcam_shared_wc_pool_id {
24 	TF_TCAM_SHARED_WC_POOL_HI  = 0,
25 	TF_TCAM_SHARED_WC_POOL_LO  = 1,
26 	TF_TCAM_SHARED_WC_POOL_MAX = 2
27 };
28 
29 /** Get string representation of a WC TCAM shared pool id
30  */
31 static const char *
tf_pool_2_str(enum tf_tcam_shared_wc_pool_id id)32 tf_pool_2_str(enum tf_tcam_shared_wc_pool_id id)
33 {
34 	switch (id) {
35 	case TF_TCAM_SHARED_WC_POOL_HI:
36 		return "TCAM_SHARED_WC_POOL_HI";
37 	case TF_TCAM_SHARED_WC_POOL_LO:
38 		return "TCAM_SHARED_WC_POOL_LO";
39 	default:
40 		return "Invalid TCAM_SHARED_WC_POOL";
41 	}
42 }
43 
44 /** The WC TCAM shared pool datastructure
45  */
46 struct tf_tcam_shared_wc_pool {
47 	/** Start and stride data */
48 	struct tf_resource_info info;
49 	/** bitalloc pool */
50 	struct bitalloc *pool;
51 };
52 
53 struct tf_tcam_shared_wc_pools {
54 	struct tf_tcam_shared_wc_pool db[TF_DIR_MAX][TF_TCAM_SHARED_WC_POOL_MAX];
55 };
56 
57 /** The WC TCAM shared pool declarations
58  */
59 /* struct tf_tcam_shared_wc_pool tcam_shared_wc[TF_DIR_MAX][TF_TCAM_SHARED_WC_POOL_MAX]; */
60 
61 static int
tf_tcam_shared_create_db(struct tf_tcam_shared_wc_pools ** db)62 tf_tcam_shared_create_db(struct tf_tcam_shared_wc_pools **db)
63 {
64 	struct tfp_calloc_parms cparms;
65 	int rc = 0;
66 
67 	cparms.nitems = 1;
68 	cparms.alignment = 0;
69 	cparms.size = sizeof(struct tf_tcam_shared_wc_pools);
70 	rc = tfp_calloc(&cparms);
71 	if (rc) {
72 		TFP_DRV_LOG(ERR,
73 			    "TCAM shared db allocation failed (%s)\n",
74 			    strerror(-rc));
75 		return rc;
76 	}
77 	*db = cparms.mem_va;
78 
79 	return rc;
80 }
81 
82 /** Create a WC TCAM shared pool
83  */
84 static int
tf_tcam_shared_create_wc_pool(int dir,enum tf_tcam_shared_wc_pool_id id,int start,int stride,struct tf_tcam_shared_wc_pools * tcam_shared_wc)85 tf_tcam_shared_create_wc_pool(int dir,
86 			      enum tf_tcam_shared_wc_pool_id id,
87 			      int start,
88 			      int stride,
89 			      struct tf_tcam_shared_wc_pools *tcam_shared_wc)
90 {
91 	int rc = 0;
92 	bool free = true;
93 	struct tfp_calloc_parms cparms;
94 	uint32_t pool_size;
95 
96 	/* Create pool */
97 	pool_size = (BITALLOC_SIZEOF(stride) / sizeof(struct bitalloc));
98 	cparms.nitems = pool_size;
99 	cparms.alignment = 0;
100 	cparms.size = sizeof(struct bitalloc);
101 	rc = tfp_calloc(&cparms);
102 	if (rc) {
103 		TFP_DRV_LOG(ERR,
104 			    "%s: pool memory alloc failed %s:%s\n",
105 			    tf_dir_2_str(dir), tf_pool_2_str(id),
106 			    strerror(-rc));
107 		return rc;
108 	}
109 	tcam_shared_wc->db[dir][id].pool = (struct bitalloc *)cparms.mem_va;
110 
111 	rc = ba_init(tcam_shared_wc->db[dir][id].pool,
112 		     stride,
113 		     free);
114 
115 	if (rc) {
116 		TFP_DRV_LOG(ERR,
117 			    "%s: pool bitalloc failed %s\n",
118 			    tf_dir_2_str(dir), tf_pool_2_str(id));
119 		return rc;
120 	}
121 
122 	tcam_shared_wc->db[dir][id].info.start = start;
123 	tcam_shared_wc->db[dir][id].info.stride = stride;
124 
125 	return rc;
126 }
127 /** Free a WC TCAM shared pool
128  */
129 static int
tf_tcam_shared_free_wc_pool(int dir,enum tf_tcam_shared_wc_pool_id id,struct tf_tcam_shared_wc_pools * tcam_shared_wc)130 tf_tcam_shared_free_wc_pool(int dir,
131 			    enum tf_tcam_shared_wc_pool_id id,
132 			    struct tf_tcam_shared_wc_pools *tcam_shared_wc)
133 {
134 	int rc = 0;
135 	TF_CHECK_PARMS1(tcam_shared_wc);
136 
137 	tcam_shared_wc->db[dir][id].info.start = 0;
138 	tcam_shared_wc->db[dir][id].info.stride = 0;
139 
140 	if (tcam_shared_wc->db[dir][id].pool)
141 		tfp_free((void *)tcam_shared_wc->db[dir][id].pool);
142 	return rc;
143 }
144 
145 /** Get the number of WC TCAM slices allocated during 1 allocation/free
146  */
147 static int
tf_tcam_shared_get_slices(struct tf * tfp,struct tf_dev_info * dev,uint16_t * num_slices)148 tf_tcam_shared_get_slices(struct tf *tfp,
149 			  struct tf_dev_info *dev,
150 			  uint16_t *num_slices)
151 {
152 	int rc;
153 
154 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
155 		rc = -EOPNOTSUPP;
156 		TFP_DRV_LOG(ERR,
157 			    "Operation not supported, rc:%s\n", strerror(-rc));
158 		return rc;
159 	}
160 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
161 						  TF_TCAM_TBL_TYPE_WC_TCAM,
162 						  0,
163 						  num_slices);
164 	return rc;
165 }
166 
167 static bool
tf_tcam_db_valid(struct tf * tfp,enum tf_dir dir)168 tf_tcam_db_valid(struct tf *tfp,
169 			enum tf_dir dir)
170 {
171 	struct tcam_rm_db *tcam_db;
172 	void *tcam_db_ptr = NULL;
173 	int rc;
174 
175 	TF_CHECK_PARMS1(tfp);
176 
177 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
178 	if (rc)
179 		return false;
180 
181 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
182 
183 	if (tcam_db->tcam_db[dir])
184 		return true;
185 
186 	return false;
187 }
188 
189 static int
tf_tcam_shared_get_rm_info(struct tf * tfp,enum tf_dir dir,uint16_t * hcapi_type,struct tf_rm_alloc_info * info)190 tf_tcam_shared_get_rm_info(struct tf *tfp,
191 			   enum tf_dir dir,
192 			   uint16_t *hcapi_type,
193 			   struct tf_rm_alloc_info *info)
194 {
195 	int rc;
196 	struct tcam_rm_db *tcam_db;
197 	void *tcam_db_ptr = NULL;
198 	struct tf_rm_get_alloc_info_parms ainfo;
199 	struct tf_rm_get_hcapi_parms hparms;
200 
201 	TF_CHECK_PARMS3(tfp, hcapi_type, info);
202 
203 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
204 	if (rc) {
205 		TFP_DRV_LOG(INFO,
206 			    "Tcam_db is not initialized, rc:%s\n",
207 			    strerror(-rc));
208 		return 0;
209 	}
210 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
211 
212 	/* Convert TF type to HCAPI RM type */
213 	memset(&hparms, 0, sizeof(hparms));
214 	hparms.rm_db = tcam_db->tcam_db[dir];
215 	hparms.subtype = TF_TCAM_TBL_TYPE_WC_TCAM;
216 	hparms.hcapi_type = hcapi_type;
217 
218 	rc = tf_rm_get_hcapi_type(&hparms);
219 	if (rc) {
220 		TFP_DRV_LOG(ERR,
221 			    "%s: Get RM hcapi type failed %s\n",
222 			    tf_dir_2_str(dir),
223 			    strerror(-rc));
224 		return rc;
225 	}
226 
227 	memset(info, 0, sizeof(struct tf_rm_alloc_info));
228 	ainfo.rm_db = tcam_db->tcam_db[dir];
229 	ainfo.subtype = TF_TCAM_TBL_TYPE_WC_TCAM;
230 	ainfo.info = info;
231 
232 	rc = tf_rm_get_info(&ainfo);
233 	if (rc) {
234 		TFP_DRV_LOG(ERR,
235 			    "%s: TCAM rm info get failed %s\n",
236 			    tf_dir_2_str(dir),
237 			    strerror(-rc));
238 		return rc;
239 	}
240 	return rc;
241 }
242 
243 /**
244  * tf_tcam_shared_bind
245  */
246 int
tf_tcam_shared_bind(struct tf * tfp,struct tf_tcam_cfg_parms * parms)247 tf_tcam_shared_bind(struct tf *tfp,
248 		    struct tf_tcam_cfg_parms *parms)
249 {
250 	int rc, dir;
251 	struct tf_session *tfs;
252 	struct tf_dev_info *dev;
253 	struct tf_rm_alloc_info info;
254 	uint16_t start, stride;
255 	uint16_t num_slices;
256 	uint16_t hcapi_type;
257 	struct tf_tcam_shared_wc_pools *tcam_shared_wc = NULL;
258 
259 	TF_CHECK_PARMS2(tfp, parms);
260 
261 	/* Perform normal bind
262 	 */
263 	rc = tf_tcam_bind(tfp, parms);
264 	if (rc)
265 		return rc;
266 
267 	/* After the normal TCAM bind, if this is a shared session
268 	 * create all required databases for the WC_HI and WC_LO pools
269 	 */
270 	rc = tf_session_get_session_internal(tfp, &tfs);
271 	if (rc) {
272 		TFP_DRV_LOG(ERR,
273 			    "Session access failure: %s\n", strerror(-rc));
274 		return rc;
275 	}
276 	if (tf_session_is_shared_session(tfs)) {
277 		/* Retrieve the device information */
278 		rc = tf_session_get_device(tfs, &dev);
279 		if (rc)
280 			return rc;
281 
282 		tf_tcam_shared_create_db(&tcam_shared_wc);
283 
284 
285 		/* If there are WC TCAM entries, create 2 pools each with 1/2
286 		 * the total number of entries
287 		 */
288 		for (dir = 0; dir < TF_DIR_MAX; dir++) {
289 			if (!tf_tcam_db_valid(tfp, dir))
290 				continue;
291 
292 			rc = tf_tcam_shared_get_rm_info(tfp,
293 							dir,
294 							&hcapi_type,
295 							&info);
296 			if (rc) {
297 				TFP_DRV_LOG(ERR,
298 					    "%s: TCAM rm info get failed\n",
299 					    tf_dir_2_str(dir));
300 				goto done;
301 			}
302 
303 			start = info.entry.start;
304 			stride = info.entry.stride / 2;
305 
306 			tf_tcam_shared_create_wc_pool(dir,
307 						      TF_TCAM_SHARED_WC_POOL_HI,
308 						      start,
309 						      stride,
310 						      tcam_shared_wc);
311 
312 			start += stride;
313 			tf_tcam_shared_create_wc_pool(dir,
314 						      TF_TCAM_SHARED_WC_POOL_LO,
315 						      start,
316 						      stride,
317 						      tcam_shared_wc);
318 
319 			tf_session_set_tcam_shared_db(tfp, (void *)tcam_shared_wc);
320 		}
321 
322 		rc = tf_tcam_shared_get_slices(tfp,
323 					       dev,
324 					       &num_slices);
325 		if (rc)
326 			return rc;
327 
328 		if (num_slices > 1) {
329 			TFP_DRV_LOG(ERR,
330 				    "Only single slice supported\n");
331 			return -EOPNOTSUPP;
332 		}
333 	}
334 done:
335 	return rc;
336 }
337 /**
338  * tf_tcam_shared_unbind
339  */
340 int
tf_tcam_shared_unbind(struct tf * tfp)341 tf_tcam_shared_unbind(struct tf *tfp)
342 {
343 	int rc, dir;
344 	struct tf_dev_info *dev;
345 	struct tf_session *tfs;
346 	void *tcam_shared_db_ptr = NULL;
347 	struct tf_tcam_shared_wc_pools *tcam_shared_wc;
348 	enum tf_tcam_shared_wc_pool_id pool_id;
349 	struct tf_tcam_free_parms parms;
350 	struct bitalloc *pool;
351 	uint16_t start;
352 	int log_idx, phy_idx;
353 	uint16_t hcapi_type;
354 	struct tf_rm_alloc_info info;
355 	int i, pool_cnt;
356 
357 	TF_CHECK_PARMS1(tfp);
358 
359 	/* Retrieve the session information */
360 	rc = tf_session_get_session_internal(tfp, &tfs);
361 	if (rc)
362 		return rc;
363 
364 	/* If not the shared session, call the normal
365 	 * tcam unbind and exit
366 	 */
367 	if (!tf_session_is_shared_session(tfs)) {
368 		rc = tf_tcam_unbind(tfp);
369 		return rc;
370 	}
371 
372 	/* We must be a shared session, get the database
373 	 */
374 	rc = tf_session_get_tcam_shared_db(tfp,
375 					   (void *)&tcam_shared_db_ptr);
376 	if (rc) {
377 		TFP_DRV_LOG(ERR,
378 			    "Failed to get tcam_shared_db, rc:%s\n",
379 			    strerror(-rc));
380 		return rc;
381 	}
382 
383 	tcam_shared_wc =
384 		(struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
385 
386 
387 	/* Get the device
388 	 */
389 	rc = tf_session_get_device(tfs, &dev);
390 	if (rc)
391 		return rc;
392 
393 
394 	/* If there are WC TCAM entries allocated, free them
395 	 */
396 	for (dir = 0; dir < TF_DIR_MAX; dir++) {
397 		/* If the database is invalid, skip
398 		 */
399 		if (!tf_tcam_db_valid(tfp, dir))
400 			continue;
401 
402 		rc = tf_tcam_shared_get_rm_info(tfp,
403 						dir,
404 						&hcapi_type,
405 						&info);
406 		if (rc) {
407 			TFP_DRV_LOG(ERR,
408 				    "%s: TCAM shared rm info get failed\n",
409 				    tf_dir_2_str(dir));
410 			return rc;
411 		}
412 
413 		for (pool_id = TF_TCAM_SHARED_WC_POOL_HI;
414 		     pool_id < TF_TCAM_SHARED_WC_POOL_MAX;
415 		     pool_id++) {
416 			pool = tcam_shared_wc->db[dir][pool_id].pool;
417 			start = tcam_shared_wc->db[dir][pool_id].info.start;
418 			pool_cnt = ba_inuse_count(pool);
419 
420 			if (pool_cnt) {
421 				TFP_DRV_LOG(INFO,
422 					    "%s: %s: %d residuals found, freeing\n",
423 					    tf_dir_2_str(dir),
424 					    tf_pool_2_str(pool_id),
425 					    pool_cnt);
426 			}
427 
428 			log_idx = 0;
429 
430 			for (i = 0; i < pool_cnt; i++) {
431 				log_idx = ba_find_next_inuse(pool, log_idx);
432 
433 				if (log_idx < 0) {
434 					TFP_DRV_LOG(ERR,
435 						    "Expected a found %s entry %d\n",
436 						    tf_pool_2_str(pool_id),
437 						    i);
438 					/* attempt normal unbind
439 					 */
440 					goto done;
441 				}
442 				phy_idx = start + log_idx;
443 
444 				parms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
445 				parms.hcapi_type = hcapi_type;
446 				parms.idx = phy_idx;
447 				parms.dir = dir;
448 				rc = tf_msg_tcam_entry_free(tfp, dev, &parms);
449 				if (rc) {
450 					/* Log error */
451 					TFP_DRV_LOG(ERR,
452 						    "%s: %s: %d free failed, rc:%s\n",
453 						    tf_dir_2_str(parms.dir),
454 						    tf_tcam_tbl_2_str(parms.type),
455 						    phy_idx,
456 						    strerror(-rc));
457 					return rc;
458 				}
459 			}
460 			/* Free the pool once all the entries
461 			 * have been cleared
462 			 */
463 			tf_tcam_shared_free_wc_pool(dir,
464 						    pool_id,
465 						    tcam_shared_wc);
466 		}
467 	}
468 done:
469 	rc = tf_tcam_unbind(tfp);
470 	return rc;
471 }
472 
473 /**
474  * tf_tcam_shared_alloc
475  */
476 int
tf_tcam_shared_alloc(struct tf * tfp,struct tf_tcam_alloc_parms * parms)477 tf_tcam_shared_alloc(struct tf *tfp,
478 		     struct tf_tcam_alloc_parms *parms)
479 {
480 	int rc;
481 	struct tf_session *tfs;
482 	struct tf_dev_info *dev;
483 	int log_idx;
484 	struct bitalloc *pool;
485 	enum tf_tcam_shared_wc_pool_id id;
486 	struct tf_tcam_shared_wc_pools *tcam_shared_wc;
487 	void *tcam_shared_db_ptr = NULL;
488 
489 	TF_CHECK_PARMS2(tfp, parms);
490 
491 	/* Retrieve the session information */
492 	rc = tf_session_get_session_internal(tfp, &tfs);
493 	if (rc)
494 		return rc;
495 
496 	/* If we aren't the shared session or the type is
497 	 * not one of the special WC TCAM types, call the normal
498 	 * allocation.
499 	 */
500 	if (!tf_session_is_shared_session(tfs) ||
501 	    (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
502 	     parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
503 		/* Perform normal alloc
504 		 */
505 		rc = tf_tcam_alloc(tfp, parms);
506 		return rc;
507 	}
508 
509 	if (!tf_tcam_db_valid(tfp, parms->dir)) {
510 		TFP_DRV_LOG(ERR,
511 			    "%s: tcam shared pool doesn't exist\n",
512 			    tf_dir_2_str(parms->dir));
513 		return -ENOMEM;
514 	}
515 
516 	rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
517 	if (rc) {
518 		TFP_DRV_LOG(ERR,
519 			    "Failed to get tcam_shared_db from session, rc:%s\n",
520 			    strerror(-rc));
521 		return rc;
522 	}
523 	tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
524 
525 	if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
526 		id = TF_TCAM_SHARED_WC_POOL_HI;
527 	else
528 		id = TF_TCAM_SHARED_WC_POOL_LO;
529 
530 	/* Retrieve the device information */
531 	rc = tf_session_get_device(tfs, &dev);
532 	if (rc)
533 		return rc;
534 
535 	pool = tcam_shared_wc->db[parms->dir][id].pool;
536 
537 	/*
538 	 * priority  0: allocate from top of the tcam i.e. high
539 	 * priority !0: allocate index from bottom i.e lowest
540 	 */
541 	if (parms->priority)
542 		log_idx = ba_alloc_reverse(pool);
543 	else
544 		log_idx = ba_alloc(pool);
545 	if (log_idx == BA_FAIL) {
546 		TFP_DRV_LOG(ERR,
547 			    "%s: Allocation failed, rc:%s\n",
548 			    tf_dir_2_str(parms->dir),
549 			    strerror(ENOMEM));
550 		return -ENOMEM;
551 	}
552 	parms->idx = log_idx;
553 	return 0;
554 }
555 
556 int
tf_tcam_shared_free(struct tf * tfp,struct tf_tcam_free_parms * parms)557 tf_tcam_shared_free(struct tf *tfp,
558 		    struct tf_tcam_free_parms *parms)
559 {
560 	int rc;
561 	struct tf_session *tfs;
562 	struct tf_dev_info *dev;
563 	int allocated = 0;
564 	uint16_t start;
565 	int phy_idx;
566 	struct bitalloc *pool;
567 	enum tf_tcam_shared_wc_pool_id id;
568 	struct tf_tcam_free_parms nparms;
569 	uint16_t hcapi_type;
570 	struct tf_rm_alloc_info info;
571 	void *tcam_shared_db_ptr = NULL;
572 	struct tf_tcam_shared_wc_pools *tcam_shared_wc;
573 
574 	TF_CHECK_PARMS2(tfp, parms);
575 
576 	/* Retrieve the session information */
577 	rc = tf_session_get_session_internal(tfp, &tfs);
578 	if (rc)
579 		return rc;
580 
581 	/* If we aren't the shared session or the type is
582 	 * not one of the special WC TCAM types, call the normal
583 	 * allocation.
584 	 */
585 	if (!tf_session_is_shared_session(tfs) ||
586 	    (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
587 	     parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
588 		/* Perform normal free
589 		 */
590 		rc = tf_tcam_free(tfp, parms);
591 		return rc;
592 	}
593 
594 	if (!tf_tcam_db_valid(tfp, parms->dir)) {
595 		TFP_DRV_LOG(ERR,
596 			    "%s: tcam shared pool doesn't exist\n",
597 			    tf_dir_2_str(parms->dir));
598 		return -ENOMEM;
599 	}
600 
601 	rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
602 	if (rc) {
603 		TFP_DRV_LOG(ERR,
604 			    "Failed to get tcam_shared_db from session, rc:%s\n",
605 			    strerror(-rc));
606 		return rc;
607 	}
608 	tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
609 
610 
611 	if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
612 		id = TF_TCAM_SHARED_WC_POOL_HI;
613 	else
614 		id = TF_TCAM_SHARED_WC_POOL_LO;
615 
616 	/* Retrieve the device information */
617 	rc = tf_session_get_device(tfs, &dev);
618 	if (rc)
619 		return rc;
620 
621 	rc = tf_tcam_shared_get_rm_info(tfp,
622 					parms->dir,
623 					&hcapi_type,
624 					&info);
625 	if (rc) {
626 		TFP_DRV_LOG(ERR,
627 			    "%s: TCAM rm info get failed\n",
628 			    tf_dir_2_str(parms->dir));
629 		return rc;
630 	}
631 
632 	pool = tcam_shared_wc->db[parms->dir][id].pool;
633 	start = tcam_shared_wc->db[parms->dir][id].info.start;
634 
635 	phy_idx = parms->idx + start;
636 	allocated = ba_inuse(pool, parms->idx);
637 
638 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
639 		TFP_DRV_LOG(ERR,
640 			    "%s: Entry already free, type:%d, idx:%d\n",
641 			    tf_dir_2_str(parms->dir), parms->type, parms->idx);
642 		return -EINVAL;
643 	}
644 
645 	rc = ba_free(pool, parms->idx);
646 	if (rc) {
647 		TFP_DRV_LOG(ERR,
648 			    "%s: Free failed, type:%s, idx:%d\n",
649 			    tf_dir_2_str(parms->dir),
650 			    tf_tcam_tbl_2_str(parms->type),
651 			    parms->idx);
652 		return rc;
653 	}
654 
655 	/* Override HI/LO type with parent WC TCAM type */
656 	nparms = *parms;
657 	nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
658 	nparms.hcapi_type = hcapi_type;
659 	nparms.idx = phy_idx;
660 
661 	rc = tf_msg_tcam_entry_free(tfp, dev, &nparms);
662 	if (rc) {
663 		/* Log error */
664 		TFP_DRV_LOG(ERR,
665 			    "%s: %s: log%d free failed, rc:%s\n",
666 			    tf_dir_2_str(nparms.dir),
667 			    tf_tcam_tbl_2_str(nparms.type),
668 			    phy_idx,
669 			    strerror(-rc));
670 		return rc;
671 	}
672 	return 0;
673 }
674 
675 int
tf_tcam_shared_set(struct tf * tfp __rte_unused,struct tf_tcam_set_parms * parms __rte_unused)676 tf_tcam_shared_set(struct tf *tfp __rte_unused,
677 		   struct tf_tcam_set_parms *parms __rte_unused)
678 {
679 	int rc;
680 	struct tf_session *tfs;
681 	struct tf_dev_info *dev;
682 	int allocated = 0;
683 	int phy_idx, log_idx;
684 	struct tf_tcam_set_parms nparms;
685 	struct bitalloc *pool;
686 	uint16_t start;
687 	enum tf_tcam_shared_wc_pool_id id;
688 	uint16_t hcapi_type;
689 	struct tf_rm_alloc_info info;
690 	struct tf_tcam_shared_wc_pools *tcam_shared_wc;
691 	void *tcam_shared_db_ptr = NULL;
692 
693 
694 	TF_CHECK_PARMS2(tfp, parms);
695 
696 	/* Retrieve the session information */
697 	rc = tf_session_get_session_internal(tfp, &tfs);
698 	if (rc)
699 		return rc;
700 
701 	/* If we aren't the shared session or one of our
702 	 * special types
703 	 */
704 	if (!tf_session_is_shared_session(tfs) ||
705 	    (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
706 	     parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
707 		/* Perform normal set and exit
708 		 */
709 		rc = tf_tcam_set(tfp, parms);
710 		return rc;
711 	}
712 
713 	if (!tf_tcam_db_valid(tfp, parms->dir)) {
714 		TFP_DRV_LOG(ERR,
715 			    "%s: tcam shared pool doesn't exist\n",
716 			    tf_dir_2_str(parms->dir));
717 		return -ENOMEM;
718 	}
719 
720 	/* Retrieve the device information */
721 	rc = tf_session_get_device(tfs, &dev);
722 	if (rc)
723 		return rc;
724 
725 	if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
726 		id = TF_TCAM_SHARED_WC_POOL_HI;
727 	else
728 		id = TF_TCAM_SHARED_WC_POOL_LO;
729 
730 	rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
731 	if (rc) {
732 		TFP_DRV_LOG(ERR,
733 			    "Failed to get tcam_shared_db from session, rc:%s\n",
734 			    strerror(-rc));
735 		return rc;
736 	}
737 	tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
738 
739 	pool = tcam_shared_wc->db[parms->dir][id].pool;
740 	start = tcam_shared_wc->db[parms->dir][id].info.start;
741 
742 	log_idx = parms->idx;
743 	phy_idx = parms->idx + start;
744 	allocated = ba_inuse(pool, parms->idx);
745 
746 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
747 		TFP_DRV_LOG(ERR,
748 			    "%s: Entry is not allocated, type:%d, logid:%d\n",
749 			    tf_dir_2_str(parms->dir), parms->type, log_idx);
750 		return -EINVAL;
751 	}
752 
753 	rc = tf_tcam_shared_get_rm_info(tfp,
754 					parms->dir,
755 					&hcapi_type,
756 					&info);
757 	if (rc)
758 		return rc;
759 
760 	/* Override HI/LO type with parent WC TCAM type */
761 	nparms.hcapi_type = hcapi_type;
762 	nparms.dir = parms->dir;
763 	nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
764 	nparms.idx = phy_idx;
765 	nparms.key = parms->key;
766 	nparms.mask = parms->mask;
767 	nparms.key_size = parms->key_size;
768 	nparms.result = parms->result;
769 	nparms.result_size = parms->result_size;
770 
771 	rc = tf_msg_tcam_entry_set(tfp, dev, &nparms);
772 	if (rc) {
773 		/* Log error */
774 		TFP_DRV_LOG(ERR,
775 			    "%s: %s: phy entry %d set failed, rc:%s",
776 			    tf_dir_2_str(parms->dir),
777 			    tf_tcam_tbl_2_str(nparms.type),
778 			    phy_idx,
779 			    strerror(-rc));
780 		return rc;
781 	}
782 	return 0;
783 }
784 
785 int
tf_tcam_shared_get(struct tf * tfp __rte_unused,struct tf_tcam_get_parms * parms)786 tf_tcam_shared_get(struct tf *tfp __rte_unused,
787 		   struct tf_tcam_get_parms *parms)
788 {
789 	int rc;
790 	struct tf_session *tfs;
791 	struct tf_dev_info *dev;
792 	int allocated = 0;
793 	int phy_idx, log_idx;
794 	struct tf_tcam_get_parms nparms;
795 	struct bitalloc *pool;
796 	uint16_t start;
797 	enum tf_tcam_shared_wc_pool_id id;
798 	uint16_t hcapi_type;
799 	struct tf_rm_alloc_info info;
800 	struct tf_tcam_shared_wc_pools *tcam_shared_wc;
801 	void *tcam_shared_db_ptr = NULL;
802 
803 	TF_CHECK_PARMS2(tfp, parms);
804 
805 	/* Retrieve the session information */
806 	rc = tf_session_get_session_internal(tfp, &tfs);
807 	if (rc)
808 		return rc;
809 
810 	/* If we aren't the shared session or one of our
811 	 * special types
812 	 */
813 	if (!tf_session_is_shared_session(tfs) ||
814 	    (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
815 	     parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
816 		/* Perform normal get and exit
817 		 */
818 		rc = tf_tcam_get(tfp, parms);
819 		return rc;
820 	}
821 
822 	if (!tf_tcam_db_valid(tfp, parms->dir)) {
823 		TFP_DRV_LOG(ERR,
824 			    "%s: tcam shared pool doesn't exist\n",
825 			    tf_dir_2_str(parms->dir));
826 		return -ENOMEM;
827 	}
828 
829 	/* Retrieve the device information */
830 	rc = tf_session_get_device(tfs, &dev);
831 	if (rc)
832 		return rc;
833 	if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
834 		id = TF_TCAM_SHARED_WC_POOL_HI;
835 	else
836 		id = TF_TCAM_SHARED_WC_POOL_LO;
837 
838 
839 	rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
840 	if (rc) {
841 		TFP_DRV_LOG(ERR,
842 			    "Failed to get tcam_shared_db from session, rc:%s\n",
843 			    strerror(-rc));
844 		return rc;
845 	}
846 	tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
847 
848 	pool = tcam_shared_wc->db[parms->dir][id].pool;
849 	start = tcam_shared_wc->db[parms->dir][id].info.start;
850 
851 	log_idx = parms->idx;
852 	phy_idx = parms->idx + start;
853 	allocated = ba_inuse(pool, parms->idx);
854 
855 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
856 		TFP_DRV_LOG(ERR,
857 			    "%s: Entry is not allocated, type:%d, logid:%d\n",
858 			    tf_dir_2_str(parms->dir), parms->type, log_idx);
859 		return -EINVAL;
860 	}
861 
862 	rc = tf_tcam_shared_get_rm_info(tfp,
863 					parms->dir,
864 					&hcapi_type,
865 					&info);
866 	if (rc)
867 		return rc;
868 
869 	/* Override HI/LO type with parent WC TCAM type */
870 	nparms = *parms;
871 	nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
872 	nparms.hcapi_type = hcapi_type;
873 	nparms.idx = phy_idx;
874 
875 	rc = tf_msg_tcam_entry_get(tfp, dev, &nparms);
876 	if (rc) {
877 		/* Log error */
878 		TFP_DRV_LOG(ERR,
879 			    "%s: %s: Entry %d set failed, rc:%s",
880 			    tf_dir_2_str(nparms.dir),
881 			    tf_tcam_tbl_2_str(nparms.type),
882 			    nparms.idx,
883 			    strerror(-rc));
884 		return rc;
885 	}
886 	return 0;
887 }
888 
889 /* Normally, device specific code wouldn't reside here, it belongs
890  * in a separate device specific function in tf_device_pxx.c.
891  * But this code is placed here as it is not a long term solution
892  * and we would like to have this code centrally located for easy
893  * removal
894  */
895 #define TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P4 12
896 #define TF_TCAM_SHARED_REMAP_SZ_BYTES_P4 4
897 #define TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58 24
898 #define TF_TCAM_SHARED_REMAP_SZ_BYTES_P58 8
899 
900 /* Temporary builder defines pulled in here and adjusted
901  * for max WC TCAM values
902  */
903 union tf_tmp_field_obj {
904 	uint32_t words[(TF_TCAM_SHARED_REMAP_SZ_BYTES_P58 + 3) / 4];
905 	uint8_t bytes[TF_TCAM_SHARED_REMAP_SZ_BYTES_P58];
906 };
907 
908 union tf_tmp_key {
909 	uint32_t words[(TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58 + 3) / 4];
910 	uint8_t bytes[TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58];
911 };
912 
913 /** p58 has an enable bit, p4 does not
914  */
915 #define TF_TCAM_SHARED_ENTRY_ENABLE 0x8
916 
917 /** Move a WC TCAM entry from the high offset to the same low offset
918  */
919 static int
tf_tcam_shared_move_entry(struct tf * tfp,struct tf_dev_info * dev,uint16_t hcapi_type,enum tf_dir dir,int sphy_idx,int dphy_idx,int key_sz_bytes,int remap_sz_bytes,bool set_enable_bit)920 tf_tcam_shared_move_entry(struct tf *tfp,
921 			  struct tf_dev_info *dev,
922 			  uint16_t hcapi_type,
923 			  enum tf_dir dir,
924 			  int sphy_idx,
925 			  int dphy_idx,
926 			  int key_sz_bytes,
927 			  int remap_sz_bytes,
928 			  bool set_enable_bit)
929 {
930 	int rc = 0;
931 	struct tf_tcam_get_parms gparms;
932 	struct tf_tcam_set_parms sparms;
933 	struct tf_tcam_free_parms fparms;
934 	union tf_tmp_key tcam_key_obj;
935 	union tf_tmp_key tcam_key_msk_obj;
936 	union tf_tmp_field_obj tcam_remap_obj;
937 
938 	memset(&tcam_key_obj, 0, sizeof(tcam_key_obj));
939 	memset(&tcam_key_msk_obj, 0, sizeof(tcam_key_msk_obj));
940 	memset(&tcam_remap_obj, 0, sizeof(tcam_remap_obj));
941 	memset(&gparms, 0, sizeof(gparms));
942 
943 	gparms.hcapi_type = hcapi_type;
944 	gparms.dir = dir;
945 	gparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
946 	gparms.idx = sphy_idx;
947 	gparms.key = (uint8_t *)&tcam_key_obj;
948 	gparms.key_size = key_sz_bytes;
949 	gparms.mask = (uint8_t *)&tcam_key_msk_obj;
950 	gparms.result = (uint8_t *)&tcam_remap_obj;
951 	gparms.result_size = remap_sz_bytes;
952 
953 	rc = tf_msg_tcam_entry_get(tfp, dev, &gparms);
954 	if (rc) {
955 		/* Log error */
956 		TFP_DRV_LOG(ERR,
957 			    "%s: %s: phyid(%d) get failed, rc:%s\n",
958 			    tf_tcam_tbl_2_str(gparms.type),
959 			    tf_dir_2_str(dir),
960 			    gparms.idx,
961 			    strerror(-rc));
962 		return rc;
963 	}
964 
965 	if (set_enable_bit)
966 		tcam_key_obj.bytes[0] |= TF_TCAM_SHARED_ENTRY_ENABLE;
967 
968 	/* Override HI/LO type with parent WC TCAM type */
969 	sparms.hcapi_type = hcapi_type;
970 	sparms.dir = dir;
971 	sparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
972 	sparms.idx = dphy_idx;
973 	sparms.key = gparms.key;
974 	sparms.mask = gparms.mask;
975 	sparms.key_size = key_sz_bytes;
976 	sparms.result = gparms.result;
977 	sparms.result_size = remap_sz_bytes;
978 
979 	rc = tf_msg_tcam_entry_set(tfp, dev, &sparms);
980 	if (rc) {
981 		/* Log error */
982 		TFP_DRV_LOG(ERR,
983 			    "%s: %s phyid(%d/0x%x) set failed, rc:%s\n",
984 			    tf_tcam_tbl_2_str(sparms.type),
985 			    tf_dir_2_str(dir),
986 			    sparms.idx,
987 			    sparms.idx,
988 			    strerror(-rc));
989 		return rc;
990 	}
991 
992 	/* Override HI/LO type with parent WC TCAM type */
993 	fparms.dir = dir;
994 	fparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
995 	fparms.hcapi_type = hcapi_type;
996 	fparms.idx = sphy_idx;
997 
998 	rc = tf_msg_tcam_entry_free(tfp, dev, &fparms);
999 	if (rc) {
1000 		/* Log error */
1001 		TFP_DRV_LOG(ERR,
1002 			    "%s: %s: phyid(%d/0x%x) free failed, rc:%s\n",
1003 			    tf_dir_2_str(dir),
1004 			    tf_tcam_tbl_2_str(fparms.type),
1005 			    sphy_idx,
1006 			    sphy_idx,
1007 			    strerror(-rc));
1008 		return rc;
1009 	}
1010 	return rc;
1011 }
1012 
1013 /** Move all shared WC TCAM entries from the high pool into the low pool
1014  *  and clear out the high pool entries.
1015  */
1016 static
tf_tcam_shared_move(struct tf * tfp,struct tf_move_tcam_shared_entries_parms * parms,int key_sz_bytes,int remap_sz_bytes,bool set_enable_bit)1017 int tf_tcam_shared_move(struct tf *tfp,
1018 			struct tf_move_tcam_shared_entries_parms *parms,
1019 			int key_sz_bytes,
1020 			int remap_sz_bytes,
1021 			bool set_enable_bit)
1022 {
1023 	int rc;
1024 	struct tf_session *tfs;
1025 	struct tf_dev_info *dev;
1026 	int log_idx;
1027 	struct bitalloc *hi_pool, *lo_pool;
1028 	uint16_t hi_start, lo_start;
1029 	enum tf_tcam_shared_wc_pool_id hi_id, lo_id;
1030 	uint16_t hcapi_type;
1031 	struct tf_rm_alloc_info info;
1032 	int hi_cnt, i;
1033 	struct tf_tcam_shared_wc_pools *tcam_shared_wc;
1034 	void *tcam_shared_db_ptr = NULL;
1035 
1036 	TF_CHECK_PARMS2(tfp, parms);
1037 
1038 	/* Retrieve the session information */
1039 	rc = tf_session_get_session_internal(tfp, &tfs);
1040 	if (rc)
1041 		return rc;
1042 
1043 	/* If we aren't the shared session or one of our
1044 	 * special types
1045 	 */
1046 	if (!tf_session_is_shared_session(tfs) ||
1047 	    (parms->tcam_tbl_type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
1048 	     parms->tcam_tbl_type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
1049 		TFP_DRV_LOG(ERR,
1050 			    "%s: Session must be shared with HI/LO type\n",
1051 			    tf_dir_2_str(parms->dir));
1052 		return -EOPNOTSUPP;
1053 	}
1054 
1055 	if (!tf_tcam_db_valid(tfp, parms->dir)) {
1056 		TFP_DRV_LOG(ERR,
1057 			    "%s: tcam shared pool doesn't exist\n",
1058 			    tf_dir_2_str(parms->dir));
1059 		return -ENOMEM;
1060 	}
1061 
1062 	/* Retrieve the device information */
1063 	rc = tf_session_get_device(tfs, &dev);
1064 	if (rc) {
1065 		/* TODO print amazing error */
1066 		return rc;
1067 	}
1068 
1069 	rc = tf_tcam_shared_get_rm_info(tfp,
1070 					parms->dir,
1071 					&hcapi_type,
1072 					&info);
1073 	if (rc) {
1074 		TFP_DRV_LOG(ERR,
1075 			    "%s: TCAM rm info get failed\n",
1076 			    tf_dir_2_str(parms->dir));
1077 		return rc;
1078 	}
1079 
1080 	rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
1081 	if (rc) {
1082 		TFP_DRV_LOG(ERR,
1083 			    "Failed to get tcam_shared_db from session, rc:%s\n",
1084 			    strerror(-rc));
1085 		return rc;
1086 	}
1087 	tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
1088 
1089 	hi_id = TF_TCAM_SHARED_WC_POOL_HI;
1090 	hi_pool = tcam_shared_wc->db[parms->dir][hi_id].pool;
1091 	hi_start = tcam_shared_wc->db[parms->dir][hi_id].info.start;
1092 
1093 	lo_id = TF_TCAM_SHARED_WC_POOL_LO;
1094 	lo_pool = tcam_shared_wc->db[parms->dir][lo_id].pool;
1095 	lo_start = tcam_shared_wc->db[parms->dir][lo_id].info.start;
1096 
1097 	if (hi_pool == NULL || lo_pool == NULL)
1098 		return -ENOMEM;
1099 
1100 	/* Get the total count of in use entries in the high pool
1101 	 */
1102 	hi_cnt = ba_inuse_count(hi_pool);
1103 
1104 	/* Copy each valid entry to the same low pool logical offset
1105 	 */
1106 	log_idx = 0;
1107 
1108 	for (i = 0; i < hi_cnt; i++) {
1109 		/* Find next free index starting from where we left off
1110 		 */
1111 		log_idx = ba_find_next_inuse(hi_pool, log_idx);
1112 		if (log_idx < 0) {
1113 			TFP_DRV_LOG(ERR,
1114 				    "Expected a found %s entry %d\n",
1115 				    tf_pool_2_str(hi_id),
1116 				    i);
1117 			goto done;
1118 		}
1119 		/* The user should have never allocated from the low
1120 		 * pool because the move only happens when switching
1121 		 * from the high to the low pool
1122 		 */
1123 		if (ba_alloc_index(lo_pool, log_idx) < 0) {
1124 			TFP_DRV_LOG(ERR,
1125 				    "Warning %s index %d already allocated\n",
1126 				    tf_pool_2_str(lo_id),
1127 				    i);
1128 
1129 			/* Since already allocated, continue with move
1130 			 */
1131 		}
1132 
1133 		rc = tf_tcam_shared_move_entry(tfp, dev,
1134 					       hcapi_type,
1135 					       parms->dir,
1136 					       hi_start + log_idx,
1137 					       lo_start + log_idx,
1138 					       key_sz_bytes,
1139 					       remap_sz_bytes,
1140 					       set_enable_bit);
1141 		if (rc) {
1142 			TFP_DRV_LOG(ERR,
1143 				    "%s: Move error %s to %s index %d\n",
1144 				    tf_dir_2_str(parms->dir),
1145 				    tf_pool_2_str(hi_id),
1146 				    tf_pool_2_str(lo_id),
1147 				    i);
1148 			goto done;
1149 		}
1150 		ba_free(hi_pool, log_idx);
1151 	}
1152 done:
1153 	return rc;
1154 }
1155 
1156 int
tf_tcam_shared_move_p4(struct tf * tfp,struct tf_move_tcam_shared_entries_parms * parms)1157 tf_tcam_shared_move_p4(struct tf *tfp,
1158 		       struct tf_move_tcam_shared_entries_parms *parms)
1159 {
1160 	int rc = 0;
1161 	rc = tf_tcam_shared_move(tfp,
1162 				 parms,
1163 				 TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P4,
1164 				 TF_TCAM_SHARED_REMAP_SZ_BYTES_P4,
1165 				 false); /* no enable bit */
1166 	return rc;
1167 }
1168 
1169 
1170 int
tf_tcam_shared_move_p58(struct tf * tfp,struct tf_move_tcam_shared_entries_parms * parms)1171 tf_tcam_shared_move_p58(struct tf *tfp,
1172 			struct tf_move_tcam_shared_entries_parms *parms)
1173 {
1174 	int rc = 0;
1175 	rc = tf_tcam_shared_move(tfp,
1176 				 parms,
1177 				 TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58,
1178 				 TF_TCAM_SHARED_REMAP_SZ_BYTES_P58,
1179 				 true); /* set enable bit */
1180 	return rc;
1181 }
1182 
1183 int
tf_tcam_shared_clear(struct tf * tfp,struct tf_clear_tcam_shared_entries_parms * parms)1184 tf_tcam_shared_clear(struct tf *tfp,
1185 		     struct tf_clear_tcam_shared_entries_parms *parms)
1186 {
1187 	int rc = 0;
1188 	struct tf_session *tfs;
1189 	struct tf_dev_info *dev;
1190 	uint16_t start;
1191 	int phy_idx;
1192 	enum tf_tcam_shared_wc_pool_id id;
1193 	struct tf_tcam_free_parms nparms;
1194 	uint16_t hcapi_type;
1195 	struct tf_rm_alloc_info info;
1196 	void *tcam_shared_db_ptr = NULL;
1197 	struct tf_tcam_shared_wc_pools *tcam_shared_wc;
1198 	int i, cnt;
1199 
1200 	TF_CHECK_PARMS2(tfp, parms);
1201 
1202 	/* Retrieve the session information */
1203 	rc = tf_session_get_session_internal(tfp, &tfs);
1204 	if (rc)
1205 		return rc;
1206 
1207 	if (!tf_session_is_shared_session(tfs) ||
1208 	    (parms->tcam_tbl_type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
1209 	     parms->tcam_tbl_type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW))
1210 		return -EOPNOTSUPP;
1211 
1212 	if (!tf_tcam_db_valid(tfp, parms->dir)) {
1213 		TFP_DRV_LOG(ERR,
1214 			    "%s: tcam shared pool doesn't exist\n",
1215 			    tf_dir_2_str(parms->dir));
1216 		return -ENOMEM;
1217 	}
1218 
1219 	rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
1220 	if (rc) {
1221 		TFP_DRV_LOG(ERR,
1222 			    "Failed to get tcam_shared_db from session, rc:%s\n",
1223 			    strerror(-rc));
1224 		return rc;
1225 	}
1226 	tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
1227 
1228 
1229 	if (parms->tcam_tbl_type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
1230 		id = TF_TCAM_SHARED_WC_POOL_HI;
1231 	else
1232 		id = TF_TCAM_SHARED_WC_POOL_LO;
1233 
1234 
1235 	/* Retrieve the device information */
1236 	rc = tf_session_get_device(tfs, &dev);
1237 	if (rc)
1238 		return rc;
1239 
1240 	rc = tf_tcam_shared_get_rm_info(tfp,
1241 					parms->dir,
1242 					&hcapi_type,
1243 					&info);
1244 	if (rc) {
1245 		TFP_DRV_LOG(ERR,
1246 			    "%s: TCAM rm info get failed\n",
1247 			    tf_dir_2_str(parms->dir));
1248 		return rc;
1249 	}
1250 
1251 	start = tcam_shared_wc->db[parms->dir][id].info.start;
1252 	cnt = tcam_shared_wc->db[parms->dir][id].info.stride;
1253 
1254 	/* Override HI/LO type with parent WC TCAM type */
1255 	nparms.dir = parms->dir;
1256 	nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
1257 	nparms.hcapi_type = hcapi_type;
1258 
1259 	for (i = 0; i < cnt; i++) {
1260 		phy_idx = start + i;
1261 		nparms.idx = phy_idx;
1262 
1263 		/* Clear entry */
1264 		rc = tf_msg_tcam_entry_free(tfp, dev, &nparms);
1265 		if (rc) {
1266 			/* Log error */
1267 			TFP_DRV_LOG(ERR,
1268 				    "%s: %s: log%d free failed, rc:%s\n",
1269 				    tf_dir_2_str(nparms.dir),
1270 				    tf_tcam_tbl_2_str(nparms.type),
1271 				    phy_idx,
1272 				    strerror(-rc));
1273 			return rc;
1274 		}
1275 	}
1276 
1277 	TFP_DRV_LOG(DEBUG,
1278 		    "%s: TCAM shared clear pool(%s)\n",
1279 		    tf_dir_2_str(nparms.dir),
1280 		    tf_pool_2_str(id));
1281 	return 0;
1282 }
1283