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