xref: /dpdk/drivers/net/bnxt/tf_core/tf_device.c (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
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 /* Number of slices per row for WC TCAM */
20 uint16_t g_wc_num_slices_per_row = TF_WC_TCAM_1_SLICE_PER_ROW;
21 
22 /* Forward declarations */
23 static int tf_dev_unbind_p4(struct tf *tfp);
24 static int tf_dev_unbind_p58(struct tf *tfp);
25 
26 /**
27  * Resource Reservation Check function
28  *
29  * [in] count
30  *   Number of module subtypes
31  *
32  * [in] cfg
33  *   Pointer to rm element config
34  *
35  * [in] reservations
36  *   Pointer to resource reservation array
37  *
38  * Returns
39  *   - (n) number of tables in module that have non-zero reservation count.
40  */
41 static int
42 tf_dev_reservation_check(uint16_t count,
43 			 struct tf_rm_element_cfg *cfg,
44 			 uint16_t *reservations)
45 {
46 	uint16_t cnt = 0;
47 	uint16_t *rm_num;
48 	int i, j;
49 
50 	for (i = 0; i < TF_DIR_MAX; i++) {
51 		rm_num = (uint16_t *)reservations + i * count;
52 		for (j = 0; j < count; j++) {
53 			if ((cfg[j].cfg_type == TF_RM_ELEM_CFG_HCAPI ||
54 			     cfg[j].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA ||
55 			     cfg[j].cfg_type ==
56 				TF_RM_ELEM_CFG_HCAPI_BA_PARENT ||
57 			     cfg[j].cfg_type ==
58 				TF_RM_ELEM_CFG_HCAPI_BA_CHILD) &&
59 			     rm_num[j] > 0)
60 				cnt++;
61 		}
62 	}
63 
64 	return cnt;
65 }
66 
67 /**
68  * Device specific bind function, WH+
69  *
70  * [in] tfp
71  *   Pointer to TF handle
72  *
73  * [in] shadow_copy
74  *   Flag controlling shadow copy DB creation
75  *
76  * [in] resources
77  *   Pointer to resource allocation information
78  *
79  * [out] dev_handle
80  *   Device handle
81  *
82  * Returns
83  *   - (0) if successful.
84  *   - (-EINVAL) on parameter or internal failure.
85  */
86 static int
87 tf_dev_bind_p4(struct tf *tfp,
88 	       bool shadow_copy,
89 	       struct tf_session_resources *resources,
90 	       struct tf_dev_info *dev_handle,
91 	       enum tf_wc_num_slice wc_num_slices)
92 {
93 	int rc;
94 	int frc;
95 	int rsv_cnt;
96 	bool no_rsv_flag = true;
97 	struct tf_ident_cfg_parms ident_cfg;
98 	struct tf_tbl_cfg_parms tbl_cfg;
99 	struct tf_tcam_cfg_parms tcam_cfg;
100 	struct tf_em_cfg_parms em_cfg;
101 	struct tf_if_tbl_cfg_parms if_tbl_cfg;
102 	struct tf_global_cfg_cfg_parms global_cfg;
103 	struct tf_session *tfs;
104 
105 	/* Retrieve the session information */
106 	rc = tf_session_get_session_internal(tfp, &tfs);
107 	if (rc)
108 		return rc;
109 
110 	/* Initial function initialization */
111 	dev_handle->ops = &tf_dev_ops_p4_init;
112 
113 	/* Initialize the modules */
114 
115 	rsv_cnt = tf_dev_reservation_check(TF_IDENT_TYPE_MAX,
116 					   tf_ident_p4,
117 					   (uint16_t *)resources->ident_cnt);
118 	if (rsv_cnt) {
119 		ident_cfg.num_elements = TF_IDENT_TYPE_MAX;
120 		ident_cfg.cfg = tf_ident_p4;
121 		ident_cfg.shadow_copy = shadow_copy;
122 		ident_cfg.resources = resources;
123 		rc = tf_ident_bind(tfp, &ident_cfg);
124 		if (rc) {
125 			TFP_DRV_LOG(ERR,
126 				    "Identifier initialization failure\n");
127 			goto fail;
128 		}
129 
130 		no_rsv_flag = false;
131 	}
132 
133 	rsv_cnt = tf_dev_reservation_check(TF_TBL_TYPE_MAX,
134 					   tf_tbl_p4,
135 					   (uint16_t *)resources->tbl_cnt);
136 	if (rsv_cnt) {
137 		tbl_cfg.num_elements = TF_TBL_TYPE_MAX;
138 		tbl_cfg.cfg = tf_tbl_p4;
139 		tbl_cfg.resources = resources;
140 		rc = tf_tbl_bind(tfp, &tbl_cfg);
141 		if (rc) {
142 			TFP_DRV_LOG(ERR,
143 				    "Table initialization failure\n");
144 			goto fail;
145 		}
146 
147 		no_rsv_flag = false;
148 	}
149 
150 	rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX,
151 					   tf_tcam_p4,
152 					   (uint16_t *)resources->tcam_cnt);
153 	if (rsv_cnt) {
154 		tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX;
155 		tcam_cfg.cfg = tf_tcam_p4;
156 		tcam_cfg.shadow_copy = shadow_copy;
157 		tcam_cfg.resources = resources;
158 		tcam_cfg.wc_num_slices = wc_num_slices;
159 #ifdef TF_TCAM_SHARED
160 		rc = tf_tcam_shared_bind(tfp, &tcam_cfg);
161 #else /* !TF_TCAM_SHARED */
162 		rc = tf_tcam_bind(tfp, &tcam_cfg);
163 #endif
164 		if (rc) {
165 			TFP_DRV_LOG(ERR,
166 				    "TCAM initialization failure\n");
167 			goto fail;
168 		}
169 		no_rsv_flag = false;
170 	}
171 
172 	/*
173 	 * EEM
174 	 */
175 
176 	em_cfg.cfg = tf_em_ext_p4;
177 	rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX,
178 					   em_cfg.cfg,
179 					   (uint16_t *)resources->em_cnt);
180 	if (rsv_cnt) {
181 		em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
182 		em_cfg.resources = resources;
183 		em_cfg.mem_type = TF_EEM_MEM_TYPE_HOST;
184 		rc = tf_em_ext_common_bind(tfp, &em_cfg);
185 		if (rc) {
186 			TFP_DRV_LOG(ERR,
187 				    "EEM initialization failure\n");
188 			goto fail;
189 		}
190 		no_rsv_flag = false;
191 	}
192 
193 	/*
194 	 * EM
195 	 */
196 	rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX,
197 					   tf_em_int_p4,
198 					   (uint16_t *)resources->em_cnt);
199 	if (rsv_cnt) {
200 		em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
201 		em_cfg.cfg = tf_em_int_p4;
202 		em_cfg.resources = resources;
203 		em_cfg.mem_type = 0; /* Not used by EM */
204 
205 		rc = tf_em_int_bind(tfp, &em_cfg);
206 		if (rc) {
207 			TFP_DRV_LOG(ERR,
208 				    "EM initialization failure\n");
209 			goto fail;
210 		}
211 		no_rsv_flag = false;
212 	}
213 
214 	/*
215 	 * There is no rm reserved for any tables
216 	 *
217 	 */
218 	if (no_rsv_flag) {
219 		TFP_DRV_LOG(ERR,
220 			    "No rm reserved for any tables\n");
221 		return -ENOMEM;
222 	}
223 
224 	/*
225 	 * IF_TBL
226 	 */
227 	if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX;
228 	if_tbl_cfg.cfg = tf_if_tbl_p4;
229 	if_tbl_cfg.shadow_copy = shadow_copy;
230 	rc = tf_if_tbl_bind(tfp, &if_tbl_cfg);
231 	if (rc) {
232 		TFP_DRV_LOG(ERR,
233 			    "IF Table initialization failure\n");
234 		goto fail;
235 	}
236 
237 	if (!tf_session_is_shared_session(tfs)) {
238 		/*
239 		 * GLOBAL_CFG
240 		 */
241 		global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX;
242 		global_cfg.cfg = tf_global_cfg_p4;
243 		rc = tf_global_cfg_bind(tfp, &global_cfg);
244 		if (rc) {
245 			TFP_DRV_LOG(ERR,
246 				    "Global Cfg initialization failure\n");
247 			goto fail;
248 		}
249 	}
250 	/* Final function initialization */
251 	dev_handle->ops = &tf_dev_ops_p4;
252 
253 	return 0;
254 
255  fail:
256 	/* Cleanup of already created modules */
257 	frc = tf_dev_unbind_p4(tfp);
258 	if (frc)
259 		return frc;
260 
261 	return rc;
262 }
263 
264 /**
265  * Device specific unbind function, WH+
266  *
267  * [in] tfp
268  *   Pointer to TF handle
269  *
270  * Returns
271  *   - (0) if successful.
272  *   - (-EINVAL) on failure.
273  */
274 static int
275 tf_dev_unbind_p4(struct tf *tfp)
276 {
277 	int rc = 0;
278 	bool fail = false;
279 	struct tf_session *tfs;
280 
281 	/* Retrieve the session information */
282 	rc = tf_session_get_session_internal(tfp, &tfs);
283 	if (rc)
284 		return rc;
285 
286 	/* Unbind all the support modules. As this is only done on
287 	 * close we only report errors as everything has to be cleaned
288 	 * up regardless.
289 	 *
290 	 * In case of residuals TCAMs are cleaned up first as to
291 	 * invalidate the pipeline in a clean manner.
292 	 */
293 #ifdef TF_TCAM_SHARED
294 	rc = tf_tcam_shared_unbind(tfp);
295 #else /* !TF_TCAM_SHARED */
296 	rc = tf_tcam_unbind(tfp);
297 #endif /* TF_TCAM_SHARED */
298 	if (rc) {
299 		TFP_DRV_LOG(INFO,
300 			    "Device unbind failed, TCAM\n");
301 		fail = true;
302 	}
303 
304 	rc = tf_ident_unbind(tfp);
305 	if (rc) {
306 		TFP_DRV_LOG(INFO,
307 			    "Device unbind failed, Identifier\n");
308 		fail = true;
309 	}
310 
311 	rc = tf_tbl_unbind(tfp);
312 	if (rc) {
313 		TFP_DRV_LOG(INFO,
314 			    "Device unbind failed, Table Type\n");
315 		fail = true;
316 	}
317 
318 	rc = tf_em_ext_common_unbind(tfp);
319 	if (rc) {
320 		TFP_DRV_LOG(INFO,
321 			    "Device unbind failed, EEM\n");
322 		fail = true;
323 	}
324 
325 	rc = tf_em_int_unbind(tfp);
326 	if (rc) {
327 		TFP_DRV_LOG(INFO,
328 			    "Device unbind failed, EM\n");
329 		fail = true;
330 	}
331 
332 	if (!tf_session_is_shared_session(tfs)) {
333 		rc = tf_if_tbl_unbind(tfp);
334 		if (rc) {
335 			TFP_DRV_LOG(INFO,
336 				    "Device unbind failed, IF Table Type\n");
337 			fail = true;
338 		}
339 
340 		rc = tf_global_cfg_unbind(tfp);
341 		if (rc) {
342 			TFP_DRV_LOG(INFO,
343 				    "Device unbind failed, Global Cfg Type\n");
344 			fail = true;
345 		}
346 	}
347 
348 	if (fail)
349 		return -1;
350 
351 	return rc;
352 }
353 
354 /**
355  * Device specific bind function, THOR
356  *
357  * [in] tfp
358  *   Pointer to TF handle
359  *
360  * [in] shadow_copy
361  *   Flag controlling shadow copy DB creation
362  *
363  * [in] resources
364  *   Pointer to resource allocation information
365  *
366  * [out] dev_handle
367  *   Device handle
368  *
369  * Returns
370  *   - (0) if successful.
371  *   - (-EINVAL) on parameter or internal failure.
372  */
373 static int
374 tf_dev_bind_p58(struct tf *tfp,
375 		bool shadow_copy,
376 		struct tf_session_resources *resources,
377 		struct tf_dev_info *dev_handle,
378 		enum tf_wc_num_slice wc_num_slices)
379 {
380 	int rc;
381 	int frc;
382 	int rsv_cnt;
383 	bool no_rsv_flag = true;
384 	struct tf_ident_cfg_parms ident_cfg;
385 	struct tf_tbl_cfg_parms tbl_cfg;
386 	struct tf_tcam_cfg_parms tcam_cfg;
387 	struct tf_em_cfg_parms em_cfg;
388 	struct tf_if_tbl_cfg_parms if_tbl_cfg;
389 	struct tf_global_cfg_cfg_parms global_cfg;
390 	struct tf_session *tfs;
391 
392 	/* Initial function initialization */
393 	dev_handle->ops = &tf_dev_ops_p58_init;
394 
395 	/* Retrieve the session information */
396 	rc = tf_session_get_session_internal(tfp, &tfs);
397 	if (rc)
398 		return rc;
399 
400 	rsv_cnt = tf_dev_reservation_check(TF_IDENT_TYPE_MAX,
401 					   tf_ident_p58,
402 					   (uint16_t *)resources->ident_cnt);
403 	if (rsv_cnt) {
404 		ident_cfg.num_elements = TF_IDENT_TYPE_MAX;
405 		ident_cfg.cfg = tf_ident_p58;
406 		ident_cfg.shadow_copy = shadow_copy;
407 		ident_cfg.resources = resources;
408 		rc = tf_ident_bind(tfp, &ident_cfg);
409 		if (rc) {
410 			TFP_DRV_LOG(ERR,
411 				    "Identifier initialization failure\n");
412 			goto fail;
413 		}
414 		no_rsv_flag = false;
415 	}
416 
417 	rsv_cnt = tf_dev_reservation_check(TF_TBL_TYPE_MAX,
418 					   tf_tbl_p58,
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;
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
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
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
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
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