xref: /dpdk/drivers/net/bnxt/tf_core/tf_device.c (revision 2490bb897182f57de80fd924dd3ae48dda819b8c)
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[TF_DIR_RX],
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[TF_DIR_RX];
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[TF_DIR_RX],
419 					   (uint16_t *)resources->tbl_cnt);
420 	rsv_cnt += tf_dev_reservation_check(TF_TBL_TYPE_MAX,
421 					   tf_tbl_p58[TF_DIR_TX],
422 					   (uint16_t *)resources->tbl_cnt);
423 	if (rsv_cnt) {
424 		tbl_cfg.num_elements = TF_TBL_TYPE_MAX;
425 		tbl_cfg.cfg = tf_tbl_p58[TF_DIR_RX];
426 		tbl_cfg.resources = resources;
427 		rc = tf_tbl_bind(tfp, &tbl_cfg);
428 		if (rc) {
429 			TFP_DRV_LOG(ERR,
430 				    "Table initialization failure\n");
431 			goto fail;
432 		}
433 		no_rsv_flag = false;
434 
435 		rc = tf_tbl_sram_bind(tfp);
436 		if (rc) {
437 			TFP_DRV_LOG(ERR,
438 				    "SRAM table initialization failure\n");
439 			goto fail;
440 		}
441 	}
442 
443 	rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX,
444 					   tf_tcam_p58,
445 					   (uint16_t *)resources->tcam_cnt);
446 	if (rsv_cnt) {
447 		tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX;
448 		tcam_cfg.cfg = tf_tcam_p58;
449 		tcam_cfg.shadow_copy = shadow_copy;
450 		tcam_cfg.resources = resources;
451 		tcam_cfg.wc_num_slices = wc_num_slices;
452 #ifdef TF_TCAM_SHARED
453 		rc = tf_tcam_shared_bind(tfp, &tcam_cfg);
454 #else /* !TF_TCAM_SHARED */
455 		rc = tf_tcam_bind(tfp, &tcam_cfg);
456 #endif
457 		if (rc) {
458 			TFP_DRV_LOG(ERR,
459 				    "TCAM initialization failure\n");
460 			goto fail;
461 		}
462 		no_rsv_flag = false;
463 	}
464 
465 	/*
466 	 * EM
467 	 */
468 	rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX,
469 					   tf_em_int_p58,
470 					   (uint16_t *)resources->em_cnt);
471 	if (rsv_cnt) {
472 		em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
473 		em_cfg.cfg = tf_em_int_p58;
474 		em_cfg.resources = resources;
475 		em_cfg.mem_type = 0; /* Not used by EM */
476 
477 		rc = tf_em_int_bind(tfp, &em_cfg);
478 		if (rc) {
479 			TFP_DRV_LOG(ERR,
480 				    "EM initialization failure\n");
481 			goto fail;
482 		}
483 		no_rsv_flag = false;
484 	}
485 
486 	/*
487 	 * There is no rm reserved for any tables
488 	 *
489 	 */
490 	if (no_rsv_flag) {
491 		TFP_DRV_LOG(ERR,
492 			    "No rm reserved for any tables\n");
493 		return -ENOMEM;
494 	}
495 
496 	/*
497 	 * IF_TBL
498 	 */
499 	if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX;
500 	if_tbl_cfg.cfg = tf_if_tbl_p58;
501 	if_tbl_cfg.shadow_copy = shadow_copy;
502 	rc = tf_if_tbl_bind(tfp, &if_tbl_cfg);
503 	if (rc) {
504 		TFP_DRV_LOG(ERR,
505 			    "IF Table initialization failure\n");
506 		goto fail;
507 	}
508 
509 	if (!tf_session_is_shared_session(tfs)) {
510 		/*
511 		 * GLOBAL_CFG
512 		 */
513 		global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX;
514 		global_cfg.cfg = tf_global_cfg_p58;
515 		rc = tf_global_cfg_bind(tfp, &global_cfg);
516 		if (rc) {
517 			TFP_DRV_LOG(ERR,
518 				    "Global Cfg initialization failure\n");
519 			goto fail;
520 		}
521 	}
522 
523 	/* Final function initialization */
524 	dev_handle->ops = &tf_dev_ops_p58;
525 
526 	return 0;
527 
528  fail:
529 	/* Cleanup of already created modules */
530 	frc = tf_dev_unbind_p58(tfp);
531 	if (frc)
532 		return frc;
533 
534 	return rc;
535 }
536 
537 /**
538  * Device specific unbind function, THOR
539  *
540  * [in] tfp
541  *   Pointer to TF handle
542  *
543  * Returns
544  *   - (0) if successful.
545  *   - (-EINVAL) on failure.
546  */
547 static int
548 tf_dev_unbind_p58(struct tf *tfp)
549 {
550 	int rc = 0;
551 	bool fail = false;
552 	struct tf_session *tfs;
553 
554 	/* Retrieve the session information */
555 	rc = tf_session_get_session_internal(tfp, &tfs);
556 	if (rc)
557 		return rc;
558 
559 	/* Unbind all the support modules. As this is only done on
560 	 * close we only report errors as everything has to be cleaned
561 	 * up regardless.
562 	 *
563 	 * In case of residuals TCAMs are cleaned up first as to
564 	 * invalidate the pipeline in a clean manner.
565 	 */
566 #ifdef TF_TCAM_SHARED
567 	rc = tf_tcam_shared_unbind(tfp);
568 #else /* !TF_TCAM_SHARED */
569 	rc = tf_tcam_unbind(tfp);
570 #endif /* TF_TCAM_SHARED */
571 	if (rc) {
572 		TFP_DRV_LOG(INFO,
573 			    "Device unbind failed, TCAM\n");
574 		fail = true;
575 	}
576 
577 	rc = tf_ident_unbind(tfp);
578 	if (rc) {
579 		TFP_DRV_LOG(INFO,
580 			    "Device unbind failed, Identifier\n");
581 		fail = true;
582 	}
583 
584 	/* Unbind the SRAM table prior to table as the table manager
585 	 * owns and frees the table DB while the SRAM table manager owns
586 	 * and manages it's internal data structures.  SRAM table manager
587 	 * relies on the table rm_db to exist.
588 	 */
589 	rc = tf_tbl_sram_unbind(tfp);
590 	if (rc) {
591 		TFP_DRV_LOG(ERR,
592 			    "Device unbind failed, SRAM table\n");
593 		fail = true;
594 	}
595 
596 	rc = tf_tbl_unbind(tfp);
597 	if (rc) {
598 		TFP_DRV_LOG(INFO,
599 			    "Device unbind failed, Table Type\n");
600 		fail = true;
601 	}
602 
603 	rc = tf_em_int_unbind(tfp);
604 	if (rc) {
605 		TFP_DRV_LOG(INFO,
606 			    "Device unbind failed, EM\n");
607 		fail = true;
608 	}
609 
610 	rc = tf_if_tbl_unbind(tfp);
611 	if (rc) {
612 		TFP_DRV_LOG(ERR,
613 			    "Device unbind failed, IF Table Type\n");
614 		fail = true;
615 	}
616 
617 	if (!tf_session_is_shared_session(tfs)) {
618 		rc = tf_global_cfg_unbind(tfp);
619 		if (rc) {
620 			TFP_DRV_LOG(ERR,
621 				    "Device unbind failed, Global Cfg Type\n");
622 			fail = true;
623 		}
624 	}
625 
626 	if (fail)
627 		return -1;
628 
629 	return rc;
630 }
631 
632 int
633 tf_dev_bind(struct tf *tfp __rte_unused,
634 	    enum tf_device_type type,
635 	    bool shadow_copy,
636 	    struct tf_session_resources *resources,
637 	    uint16_t wc_num_slices,
638 	    struct tf_dev_info *dev_handle)
639 {
640 	switch (type) {
641 	case TF_DEVICE_TYPE_WH:
642 	case TF_DEVICE_TYPE_SR:
643 		dev_handle->type = type;
644 		return tf_dev_bind_p4(tfp,
645 				      shadow_copy,
646 				      resources,
647 				      dev_handle,
648 				      wc_num_slices);
649 	case TF_DEVICE_TYPE_THOR:
650 		dev_handle->type = type;
651 		return tf_dev_bind_p58(tfp,
652 				       shadow_copy,
653 				       resources,
654 				       dev_handle,
655 				       wc_num_slices);
656 	default:
657 		TFP_DRV_LOG(ERR,
658 			    "No such device\n");
659 		return -ENODEV;
660 	}
661 }
662 
663 int
664 tf_dev_bind_ops(enum tf_device_type type,
665 		struct tf_dev_info *dev_handle)
666 {
667 	switch (type) {
668 	case TF_DEVICE_TYPE_WH:
669 	case TF_DEVICE_TYPE_SR:
670 		dev_handle->ops = &tf_dev_ops_p4_init;
671 		break;
672 	case TF_DEVICE_TYPE_THOR:
673 		dev_handle->ops = &tf_dev_ops_p58_init;
674 		break;
675 	default:
676 		TFP_DRV_LOG(ERR,
677 			    "No such device\n");
678 		return -ENODEV;
679 	}
680 
681 	return 0;
682 }
683 
684 int
685 tf_dev_unbind(struct tf *tfp,
686 	      struct tf_dev_info *dev_handle)
687 {
688 	switch (dev_handle->type) {
689 	case TF_DEVICE_TYPE_WH:
690 	case TF_DEVICE_TYPE_SR:
691 		return tf_dev_unbind_p4(tfp);
692 	case TF_DEVICE_TYPE_THOR:
693 		return tf_dev_unbind_p58(tfp);
694 	default:
695 		TFP_DRV_LOG(ERR,
696 			    "No such device\n");
697 		return -ENODEV;
698 	}
699 }
700