1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2021 Broadcom
3 * All rights reserved.
4 */
5
6 #include "tf_device.h"
7 #include "tf_device_p4.h"
8 #include "tf_device_p58.h"
9 #include "tfp.h"
10 #include "tf_em.h"
11 #include "tf_rm.h"
12 #ifdef TF_TCAM_SHARED
13 #include "tf_tcam_shared.h"
14 #include "tf_tbl_sram.h"
15 #endif /* TF_TCAM_SHARED */
16
17 struct tf;
18
19 /* Forward declarations */
20 static int tf_dev_unbind_p4(struct tf *tfp);
21 static int tf_dev_unbind_p58(struct tf *tfp);
22
23 /**
24 * Resource Reservation Check function
25 *
26 * [in] count
27 * Number of module subtypes
28 *
29 * [in] cfg
30 * Pointer to rm element config
31 *
32 * [in] reservations
33 * Pointer to resource reservation array
34 *
35 * Returns
36 * - (n) number of tables in module that have non-zero reservation count.
37 */
38 static int
tf_dev_reservation_check(uint16_t count,struct tf_rm_element_cfg * cfg,uint16_t * reservations)39 tf_dev_reservation_check(uint16_t count,
40 struct tf_rm_element_cfg *cfg,
41 uint16_t *reservations)
42 {
43 uint16_t cnt = 0;
44 uint16_t *rm_num;
45 int i, j;
46
47 for (i = 0; i < TF_DIR_MAX; i++) {
48 rm_num = (uint16_t *)reservations + i * count;
49 for (j = 0; j < count; j++) {
50 if ((cfg[j].cfg_type == TF_RM_ELEM_CFG_HCAPI ||
51 cfg[j].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA ||
52 cfg[j].cfg_type ==
53 TF_RM_ELEM_CFG_HCAPI_BA_PARENT ||
54 cfg[j].cfg_type ==
55 TF_RM_ELEM_CFG_HCAPI_BA_CHILD) &&
56 rm_num[j] > 0)
57 cnt++;
58 }
59 }
60
61 return cnt;
62 }
63
64 /**
65 * Device specific bind function, WH+
66 *
67 * [in] tfp
68 * Pointer to TF handle
69 *
70 * [in] shadow_copy
71 * Flag controlling shadow copy DB creation
72 *
73 * [in] resources
74 * Pointer to resource allocation information
75 *
76 * [out] dev_handle
77 * Device handle
78 *
79 * Returns
80 * - (0) if successful.
81 * - (-EINVAL) on parameter or internal failure.
82 */
83 static int
tf_dev_bind_p4(struct tf * tfp,bool shadow_copy,struct tf_session_resources * resources,struct tf_dev_info * dev_handle,enum tf_wc_num_slice wc_num_slices)84 tf_dev_bind_p4(struct tf *tfp,
85 bool shadow_copy,
86 struct tf_session_resources *resources,
87 struct tf_dev_info *dev_handle,
88 enum tf_wc_num_slice wc_num_slices)
89 {
90 int rc;
91 int frc;
92 int rsv_cnt;
93 bool no_rsv_flag = true;
94 struct tf_ident_cfg_parms ident_cfg;
95 struct tf_tbl_cfg_parms tbl_cfg;
96 struct tf_tcam_cfg_parms tcam_cfg;
97 struct tf_em_cfg_parms em_cfg;
98 struct tf_if_tbl_cfg_parms if_tbl_cfg;
99 struct tf_global_cfg_cfg_parms global_cfg;
100 struct tf_session *tfs;
101
102 /* Retrieve the session information */
103 rc = tf_session_get_session_internal(tfp, &tfs);
104 if (rc)
105 return rc;
106
107 /* Initial function initialization */
108 dev_handle->ops = &tf_dev_ops_p4_init;
109
110 /* Initialize the modules */
111
112 rsv_cnt = tf_dev_reservation_check(TF_IDENT_TYPE_MAX,
113 tf_ident_p4,
114 (uint16_t *)resources->ident_cnt);
115 if (rsv_cnt) {
116 ident_cfg.num_elements = TF_IDENT_TYPE_MAX;
117 ident_cfg.cfg = tf_ident_p4;
118 ident_cfg.shadow_copy = shadow_copy;
119 ident_cfg.resources = resources;
120 rc = tf_ident_bind(tfp, &ident_cfg);
121 if (rc) {
122 TFP_DRV_LOG(ERR,
123 "Identifier initialization failure\n");
124 goto fail;
125 }
126
127 no_rsv_flag = false;
128 }
129
130 rsv_cnt = tf_dev_reservation_check(TF_TBL_TYPE_MAX,
131 tf_tbl_p4[TF_DIR_RX],
132 (uint16_t *)resources->tbl_cnt);
133 if (rsv_cnt) {
134 tbl_cfg.num_elements = TF_TBL_TYPE_MAX;
135 tbl_cfg.cfg = tf_tbl_p4[TF_DIR_RX];
136 tbl_cfg.resources = resources;
137 rc = tf_tbl_bind(tfp, &tbl_cfg);
138 if (rc) {
139 TFP_DRV_LOG(ERR,
140 "Table initialization failure\n");
141 goto fail;
142 }
143
144 no_rsv_flag = false;
145 }
146
147 rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX,
148 tf_tcam_p4,
149 (uint16_t *)resources->tcam_cnt);
150 if (rsv_cnt) {
151 tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX;
152 tcam_cfg.cfg = tf_tcam_p4;
153 tcam_cfg.shadow_copy = shadow_copy;
154 tcam_cfg.resources = resources;
155 tcam_cfg.wc_num_slices = wc_num_slices;
156 #ifdef TF_TCAM_SHARED
157 rc = tf_tcam_shared_bind(tfp, &tcam_cfg);
158 #else /* !TF_TCAM_SHARED */
159 rc = tf_tcam_bind(tfp, &tcam_cfg);
160 #endif
161 if (rc) {
162 TFP_DRV_LOG(ERR,
163 "TCAM initialization failure\n");
164 goto fail;
165 }
166 no_rsv_flag = false;
167 }
168
169 /*
170 * EEM
171 */
172
173 em_cfg.cfg = tf_em_ext_p4;
174 rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX,
175 em_cfg.cfg,
176 (uint16_t *)resources->em_cnt);
177 if (rsv_cnt) {
178 em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
179 em_cfg.resources = resources;
180 em_cfg.mem_type = TF_EEM_MEM_TYPE_HOST;
181 rc = tf_em_ext_common_bind(tfp, &em_cfg);
182 if (rc) {
183 TFP_DRV_LOG(ERR,
184 "EEM initialization failure\n");
185 goto fail;
186 }
187 no_rsv_flag = false;
188 }
189
190 /*
191 * EM
192 */
193 rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX,
194 tf_em_int_p4,
195 (uint16_t *)resources->em_cnt);
196 if (rsv_cnt) {
197 em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
198 em_cfg.cfg = tf_em_int_p4;
199 em_cfg.resources = resources;
200 em_cfg.mem_type = 0; /* Not used by EM */
201
202 rc = tf_em_int_bind(tfp, &em_cfg);
203 if (rc) {
204 TFP_DRV_LOG(ERR,
205 "EM initialization failure\n");
206 goto fail;
207 }
208 no_rsv_flag = false;
209 }
210
211 /*
212 * There is no rm reserved for any tables
213 *
214 */
215 if (no_rsv_flag) {
216 TFP_DRV_LOG(ERR,
217 "No rm reserved for any tables\n");
218 return -ENOMEM;
219 }
220
221 /*
222 * IF_TBL
223 */
224 if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX;
225 if_tbl_cfg.cfg = tf_if_tbl_p4;
226 if_tbl_cfg.shadow_copy = shadow_copy;
227 rc = tf_if_tbl_bind(tfp, &if_tbl_cfg);
228 if (rc) {
229 TFP_DRV_LOG(ERR,
230 "IF Table initialization failure\n");
231 goto fail;
232 }
233
234 if (!tf_session_is_shared_session(tfs)) {
235 /*
236 * GLOBAL_CFG
237 */
238 global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX;
239 global_cfg.cfg = tf_global_cfg_p4;
240 rc = tf_global_cfg_bind(tfp, &global_cfg);
241 if (rc) {
242 TFP_DRV_LOG(ERR,
243 "Global Cfg initialization failure\n");
244 goto fail;
245 }
246 }
247 /* Final function initialization */
248 dev_handle->ops = &tf_dev_ops_p4;
249
250 return 0;
251
252 fail:
253 /* Cleanup of already created modules */
254 frc = tf_dev_unbind_p4(tfp);
255 if (frc)
256 return frc;
257
258 return rc;
259 }
260
261 /**
262 * Device specific unbind function, WH+
263 *
264 * [in] tfp
265 * Pointer to TF handle
266 *
267 * Returns
268 * - (0) if successful.
269 * - (-EINVAL) on failure.
270 */
271 static int
tf_dev_unbind_p4(struct tf * tfp)272 tf_dev_unbind_p4(struct tf *tfp)
273 {
274 int rc = 0;
275 bool fail = false;
276 struct tf_session *tfs;
277
278 /* Retrieve the session information */
279 rc = tf_session_get_session_internal(tfp, &tfs);
280 if (rc)
281 return rc;
282
283 /* Unbind all the support modules. As this is only done on
284 * close we only report errors as everything has to be cleaned
285 * up regardless.
286 *
287 * In case of residuals TCAMs are cleaned up first as to
288 * invalidate the pipeline in a clean manner.
289 */
290 #ifdef TF_TCAM_SHARED
291 rc = tf_tcam_shared_unbind(tfp);
292 #else /* !TF_TCAM_SHARED */
293 rc = tf_tcam_unbind(tfp);
294 #endif /* TF_TCAM_SHARED */
295 if (rc) {
296 TFP_DRV_LOG(INFO,
297 "Device unbind failed, TCAM\n");
298 fail = true;
299 }
300
301 rc = tf_ident_unbind(tfp);
302 if (rc) {
303 TFP_DRV_LOG(INFO,
304 "Device unbind failed, Identifier\n");
305 fail = true;
306 }
307
308 rc = tf_tbl_unbind(tfp);
309 if (rc) {
310 TFP_DRV_LOG(INFO,
311 "Device unbind failed, Table Type\n");
312 fail = true;
313 }
314
315 rc = tf_em_ext_common_unbind(tfp);
316 if (rc) {
317 TFP_DRV_LOG(INFO,
318 "Device unbind failed, EEM\n");
319 fail = true;
320 }
321
322 rc = tf_em_int_unbind(tfp);
323 if (rc) {
324 TFP_DRV_LOG(INFO,
325 "Device unbind failed, EM\n");
326 fail = true;
327 }
328
329 if (!tf_session_is_shared_session(tfs)) {
330 rc = tf_if_tbl_unbind(tfp);
331 if (rc) {
332 TFP_DRV_LOG(INFO,
333 "Device unbind failed, IF Table Type\n");
334 fail = true;
335 }
336
337 rc = tf_global_cfg_unbind(tfp);
338 if (rc) {
339 TFP_DRV_LOG(INFO,
340 "Device unbind failed, Global Cfg Type\n");
341 fail = true;
342 }
343 }
344
345 if (fail)
346 return -1;
347
348 return rc;
349 }
350
351 /**
352 * Device specific bind function, THOR
353 *
354 * [in] tfp
355 * Pointer to TF handle
356 *
357 * [in] shadow_copy
358 * Flag controlling shadow copy DB creation
359 *
360 * [in] resources
361 * Pointer to resource allocation information
362 *
363 * [out] dev_handle
364 * Device handle
365 *
366 * Returns
367 * - (0) if successful.
368 * - (-EINVAL) on parameter or internal failure.
369 */
370 static int
tf_dev_bind_p58(struct tf * tfp,bool shadow_copy,struct tf_session_resources * resources,struct tf_dev_info * dev_handle,enum tf_wc_num_slice wc_num_slices)371 tf_dev_bind_p58(struct tf *tfp,
372 bool shadow_copy,
373 struct tf_session_resources *resources,
374 struct tf_dev_info *dev_handle,
375 enum tf_wc_num_slice wc_num_slices)
376 {
377 int rc;
378 int frc;
379 int rsv_cnt;
380 bool no_rsv_flag = true;
381 struct tf_ident_cfg_parms ident_cfg;
382 struct tf_tbl_cfg_parms tbl_cfg;
383 struct tf_tcam_cfg_parms tcam_cfg;
384 struct tf_em_cfg_parms em_cfg;
385 struct tf_if_tbl_cfg_parms if_tbl_cfg;
386 struct tf_global_cfg_cfg_parms global_cfg;
387 struct tf_session *tfs;
388
389 /* Initial function initialization */
390 dev_handle->ops = &tf_dev_ops_p58_init;
391
392 /* Retrieve the session information */
393 rc = tf_session_get_session_internal(tfp, &tfs);
394 if (rc)
395 return rc;
396
397 rsv_cnt = tf_dev_reservation_check(TF_IDENT_TYPE_MAX,
398 tf_ident_p58,
399 (uint16_t *)resources->ident_cnt);
400 if (rsv_cnt) {
401 ident_cfg.num_elements = TF_IDENT_TYPE_MAX;
402 ident_cfg.cfg = tf_ident_p58;
403 ident_cfg.shadow_copy = shadow_copy;
404 ident_cfg.resources = resources;
405 rc = tf_ident_bind(tfp, &ident_cfg);
406 if (rc) {
407 TFP_DRV_LOG(ERR,
408 "Identifier initialization failure\n");
409 goto fail;
410 }
411 no_rsv_flag = false;
412 }
413
414 rsv_cnt = tf_dev_reservation_check(TF_TBL_TYPE_MAX,
415 tf_tbl_p58[TF_DIR_RX],
416 (uint16_t *)resources->tbl_cnt);
417 rsv_cnt += tf_dev_reservation_check(TF_TBL_TYPE_MAX,
418 tf_tbl_p58[TF_DIR_TX],
419 (uint16_t *)resources->tbl_cnt);
420 if (rsv_cnt) {
421 tbl_cfg.num_elements = TF_TBL_TYPE_MAX;
422 tbl_cfg.cfg = tf_tbl_p58[TF_DIR_RX];
423 tbl_cfg.resources = resources;
424 rc = tf_tbl_bind(tfp, &tbl_cfg);
425 if (rc) {
426 TFP_DRV_LOG(ERR,
427 "Table initialization failure\n");
428 goto fail;
429 }
430 no_rsv_flag = false;
431
432 rc = tf_tbl_sram_bind(tfp);
433 if (rc) {
434 TFP_DRV_LOG(ERR,
435 "SRAM table initialization failure\n");
436 goto fail;
437 }
438 }
439
440 rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX,
441 tf_tcam_p58,
442 (uint16_t *)resources->tcam_cnt);
443 if (rsv_cnt) {
444 tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX;
445 tcam_cfg.cfg = tf_tcam_p58;
446 tcam_cfg.shadow_copy = shadow_copy;
447 tcam_cfg.resources = resources;
448 tcam_cfg.wc_num_slices = wc_num_slices;
449 #ifdef TF_TCAM_SHARED
450 rc = tf_tcam_shared_bind(tfp, &tcam_cfg);
451 #else /* !TF_TCAM_SHARED */
452 rc = tf_tcam_bind(tfp, &tcam_cfg);
453 #endif
454 if (rc) {
455 TFP_DRV_LOG(ERR,
456 "TCAM initialization failure\n");
457 goto fail;
458 }
459 no_rsv_flag = false;
460 }
461
462 /*
463 * EM
464 */
465 rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX,
466 tf_em_int_p58,
467 (uint16_t *)resources->em_cnt);
468 if (rsv_cnt) {
469 em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
470 em_cfg.cfg = tf_em_int_p58;
471 em_cfg.resources = resources;
472 em_cfg.mem_type = 0; /* Not used by EM */
473
474 rc = tf_em_int_bind(tfp, &em_cfg);
475 if (rc) {
476 TFP_DRV_LOG(ERR,
477 "EM initialization failure\n");
478 goto fail;
479 }
480 no_rsv_flag = false;
481 }
482
483 /*
484 * There is no rm reserved for any tables
485 *
486 */
487 if (no_rsv_flag) {
488 TFP_DRV_LOG(ERR,
489 "No rm reserved for any tables\n");
490 return -ENOMEM;
491 }
492
493 /*
494 * IF_TBL
495 */
496 if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX;
497 if_tbl_cfg.cfg = tf_if_tbl_p58;
498 if_tbl_cfg.shadow_copy = shadow_copy;
499 rc = tf_if_tbl_bind(tfp, &if_tbl_cfg);
500 if (rc) {
501 TFP_DRV_LOG(ERR,
502 "IF Table initialization failure\n");
503 goto fail;
504 }
505
506 if (!tf_session_is_shared_session(tfs)) {
507 /*
508 * GLOBAL_CFG
509 */
510 global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX;
511 global_cfg.cfg = tf_global_cfg_p58;
512 rc = tf_global_cfg_bind(tfp, &global_cfg);
513 if (rc) {
514 TFP_DRV_LOG(ERR,
515 "Global Cfg initialization failure\n");
516 goto fail;
517 }
518 }
519
520 /* Final function initialization */
521 dev_handle->ops = &tf_dev_ops_p58;
522
523 return 0;
524
525 fail:
526 /* Cleanup of already created modules */
527 frc = tf_dev_unbind_p58(tfp);
528 if (frc)
529 return frc;
530
531 return rc;
532 }
533
534 /**
535 * Device specific unbind function, THOR
536 *
537 * [in] tfp
538 * Pointer to TF handle
539 *
540 * Returns
541 * - (0) if successful.
542 * - (-EINVAL) on failure.
543 */
544 static int
tf_dev_unbind_p58(struct tf * tfp)545 tf_dev_unbind_p58(struct tf *tfp)
546 {
547 int rc = 0;
548 bool fail = false;
549 struct tf_session *tfs;
550
551 /* Retrieve the session information */
552 rc = tf_session_get_session_internal(tfp, &tfs);
553 if (rc)
554 return rc;
555
556 /* Unbind all the support modules. As this is only done on
557 * close we only report errors as everything has to be cleaned
558 * up regardless.
559 *
560 * In case of residuals TCAMs are cleaned up first as to
561 * invalidate the pipeline in a clean manner.
562 */
563 #ifdef TF_TCAM_SHARED
564 rc = tf_tcam_shared_unbind(tfp);
565 #else /* !TF_TCAM_SHARED */
566 rc = tf_tcam_unbind(tfp);
567 #endif /* TF_TCAM_SHARED */
568 if (rc) {
569 TFP_DRV_LOG(INFO,
570 "Device unbind failed, TCAM\n");
571 fail = true;
572 }
573
574 rc = tf_ident_unbind(tfp);
575 if (rc) {
576 TFP_DRV_LOG(INFO,
577 "Device unbind failed, Identifier\n");
578 fail = true;
579 }
580
581 /* Unbind the SRAM table prior to table as the table manager
582 * owns and frees the table DB while the SRAM table manager owns
583 * and manages it's internal data structures. SRAM table manager
584 * relies on the table rm_db to exist.
585 */
586 rc = tf_tbl_sram_unbind(tfp);
587 if (rc) {
588 TFP_DRV_LOG(ERR,
589 "Device unbind failed, SRAM table\n");
590 fail = true;
591 }
592
593 rc = tf_tbl_unbind(tfp);
594 if (rc) {
595 TFP_DRV_LOG(INFO,
596 "Device unbind failed, Table Type\n");
597 fail = true;
598 }
599
600 rc = tf_em_int_unbind(tfp);
601 if (rc) {
602 TFP_DRV_LOG(INFO,
603 "Device unbind failed, EM\n");
604 fail = true;
605 }
606
607 rc = tf_if_tbl_unbind(tfp);
608 if (rc) {
609 TFP_DRV_LOG(ERR,
610 "Device unbind failed, IF Table Type\n");
611 fail = true;
612 }
613
614 if (!tf_session_is_shared_session(tfs)) {
615 rc = tf_global_cfg_unbind(tfp);
616 if (rc) {
617 TFP_DRV_LOG(ERR,
618 "Device unbind failed, Global Cfg Type\n");
619 fail = true;
620 }
621 }
622
623 if (fail)
624 return -1;
625
626 return rc;
627 }
628
629 int
tf_dev_bind(struct tf * tfp __rte_unused,enum tf_device_type type,bool shadow_copy,struct tf_session_resources * resources,uint16_t wc_num_slices,struct tf_dev_info * dev_handle)630 tf_dev_bind(struct tf *tfp __rte_unused,
631 enum tf_device_type type,
632 bool shadow_copy,
633 struct tf_session_resources *resources,
634 uint16_t wc_num_slices,
635 struct tf_dev_info *dev_handle)
636 {
637 switch (type) {
638 case TF_DEVICE_TYPE_WH:
639 case TF_DEVICE_TYPE_SR:
640 dev_handle->type = type;
641 return tf_dev_bind_p4(tfp,
642 shadow_copy,
643 resources,
644 dev_handle,
645 wc_num_slices);
646 case TF_DEVICE_TYPE_THOR:
647 dev_handle->type = type;
648 return tf_dev_bind_p58(tfp,
649 shadow_copy,
650 resources,
651 dev_handle,
652 wc_num_slices);
653 default:
654 TFP_DRV_LOG(ERR,
655 "No such device\n");
656 return -ENODEV;
657 }
658 }
659
660 int
tf_dev_bind_ops(enum tf_device_type type,struct tf_dev_info * dev_handle)661 tf_dev_bind_ops(enum tf_device_type type,
662 struct tf_dev_info *dev_handle)
663 {
664 switch (type) {
665 case TF_DEVICE_TYPE_WH:
666 case TF_DEVICE_TYPE_SR:
667 dev_handle->ops = &tf_dev_ops_p4_init;
668 break;
669 case TF_DEVICE_TYPE_THOR:
670 dev_handle->ops = &tf_dev_ops_p58_init;
671 break;
672 default:
673 TFP_DRV_LOG(ERR,
674 "No such device\n");
675 return -ENODEV;
676 }
677
678 return 0;
679 }
680
681 int
tf_dev_unbind(struct tf * tfp,struct tf_dev_info * dev_handle)682 tf_dev_unbind(struct tf *tfp,
683 struct tf_dev_info *dev_handle)
684 {
685 switch (dev_handle->type) {
686 case TF_DEVICE_TYPE_WH:
687 case TF_DEVICE_TYPE_SR:
688 return tf_dev_unbind_p4(tfp);
689 case TF_DEVICE_TYPE_THOR:
690 return tf_dev_unbind_p58(tfp);
691 default:
692 TFP_DRV_LOG(ERR,
693 "No such device\n");
694 return -ENODEV;
695 }
696 }
697