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