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