xref: /dpdk/drivers/net/bnxt/tf_core/tf_device.c (revision b53d106d34b5c638f5a2cbdfee0da5bd42d4383f)
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
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
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
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
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
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