xref: /dpdk/drivers/net/bnxt/tf_core/tf_device.c (revision aa49b38fa7c350da251b70f455224ae8e3f79d0b)
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 	 * EM
158 	 */
159 	rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX,
160 					   tf_em_int_p4,
161 					   (uint16_t *)resources->em_cnt);
162 	if (rsv_cnt) {
163 		em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
164 		em_cfg.cfg = tf_em_int_p4;
165 		em_cfg.resources = resources;
166 		em_cfg.mem_type = 0; /* Not used by EM */
167 
168 		rc = tf_em_int_bind(tfp, &em_cfg);
169 		if (rc) {
170 			TFP_DRV_LOG(ERR,
171 				    "EM initialization failure\n");
172 			goto fail;
173 		}
174 		no_rsv_flag = false;
175 	}
176 
177 	/*
178 	 * There is no rm reserved for any tables
179 	 *
180 	 */
181 	if (no_rsv_flag) {
182 		TFP_DRV_LOG(ERR,
183 			    "No rm reserved for any tables\n");
184 		return -ENOMEM;
185 	}
186 
187 	/*
188 	 * IF_TBL
189 	 */
190 	if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX;
191 	if_tbl_cfg.cfg = tf_if_tbl_p4;
192 	rc = tf_if_tbl_bind(tfp, &if_tbl_cfg);
193 	if (rc) {
194 		TFP_DRV_LOG(ERR,
195 			    "IF Table initialization failure\n");
196 		goto fail;
197 	}
198 
199 	if (!tf_session_is_shared_session(tfs)) {
200 		/*
201 		 * GLOBAL_CFG
202 		 */
203 		global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX;
204 		global_cfg.cfg = tf_global_cfg_p4;
205 		rc = tf_global_cfg_bind(tfp, &global_cfg);
206 		if (rc) {
207 			TFP_DRV_LOG(ERR,
208 				    "Global Cfg initialization failure\n");
209 			goto fail;
210 		}
211 	}
212 	/* Final function initialization */
213 	dev_handle->ops = &tf_dev_ops_p4;
214 
215 	return 0;
216 
217  fail:
218 	/* Cleanup of already created modules */
219 	frc = tf_dev_unbind_p4(tfp);
220 	if (frc)
221 		return frc;
222 
223 	return rc;
224 }
225 
226 /**
227  * Device specific unbind function, WH+
228  *
229  * [in] tfp
230  *   Pointer to TF handle
231  *
232  * Returns
233  *   - (0) if successful.
234  *   - (-EINVAL) on failure.
235  */
236 static int
237 tf_dev_unbind_p4(struct tf *tfp)
238 {
239 	int rc = 0;
240 	bool fail = false;
241 	struct tf_session *tfs;
242 
243 	/* Retrieve the session information */
244 	rc = tf_session_get_session_internal(tfp, &tfs);
245 	if (rc)
246 		return rc;
247 
248 	/* Unbind all the support modules. As this is only done on
249 	 * close we only report errors as everything has to be cleaned
250 	 * up regardless.
251 	 *
252 	 * In case of residuals TCAMs are cleaned up first as to
253 	 * invalidate the pipeline in a clean manner.
254 	 */
255 	rc = tf_tcam_shared_unbind(tfp);
256 	if (rc) {
257 		TFP_DRV_LOG(INFO,
258 			    "Device unbind failed, TCAM\n");
259 		fail = true;
260 	}
261 
262 	rc = tf_ident_unbind(tfp);
263 	if (rc) {
264 		TFP_DRV_LOG(INFO,
265 			    "Device unbind failed, Identifier\n");
266 		fail = true;
267 	}
268 
269 	rc = tf_tbl_unbind(tfp);
270 	if (rc) {
271 		TFP_DRV_LOG(INFO,
272 			    "Device unbind failed, Table Type\n");
273 		fail = true;
274 	}
275 	rc = tf_em_int_unbind(tfp);
276 	if (rc) {
277 		TFP_DRV_LOG(INFO,
278 			    "Device unbind failed, EM\n");
279 		fail = true;
280 	}
281 
282 	if (!tf_session_is_shared_session(tfs)) {
283 		rc = tf_if_tbl_unbind(tfp);
284 		if (rc) {
285 			TFP_DRV_LOG(INFO,
286 				    "Device unbind failed, IF Table Type\n");
287 			fail = true;
288 		}
289 
290 		rc = tf_global_cfg_unbind(tfp);
291 		if (rc) {
292 			TFP_DRV_LOG(INFO,
293 				    "Device unbind failed, Global Cfg Type\n");
294 			fail = true;
295 		}
296 	}
297 
298 	if (fail)
299 		return -1;
300 
301 	return rc;
302 }
303 
304 /**
305  * Device specific bind function, P5
306  *
307  * [in] tfp
308  *   Pointer to TF handle
309  *
310  * [in] resources
311  *   Pointer to resource allocation information
312  *
313  * [out] dev_handle
314  *   Device handle
315  *
316  * Returns
317  *   - (0) if successful.
318  *   - (-EINVAL) on parameter or internal failure.
319  */
320 static int
321 tf_dev_bind_p58(struct tf *tfp,
322 		struct tf_session_resources *resources,
323 		struct tf_dev_info *dev_handle,
324 		enum tf_wc_num_slice wc_num_slices)
325 {
326 	int rc;
327 	int frc;
328 	int rsv_cnt;
329 	bool no_rsv_flag = true;
330 	struct tf_ident_cfg_parms ident_cfg;
331 	struct tf_tbl_cfg_parms tbl_cfg;
332 	struct tf_tcam_cfg_parms tcam_cfg;
333 	struct tf_em_cfg_parms em_cfg;
334 	struct tf_if_tbl_cfg_parms if_tbl_cfg;
335 	struct tf_global_cfg_cfg_parms global_cfg;
336 	struct tf_session *tfs;
337 
338 	/* Initial function initialization */
339 	dev_handle->ops = &tf_dev_ops_p58_init;
340 
341 	/* Retrieve the session information */
342 	rc = tf_session_get_session_internal(tfp, &tfs);
343 	if (rc)
344 		return rc;
345 
346 	rsv_cnt = tf_dev_reservation_check(TF_IDENT_TYPE_MAX,
347 					   tf_ident_p58,
348 					   (uint16_t *)resources->ident_cnt);
349 	if (rsv_cnt) {
350 		ident_cfg.num_elements = TF_IDENT_TYPE_MAX;
351 		ident_cfg.cfg = tf_ident_p58;
352 		ident_cfg.resources = resources;
353 		rc = tf_ident_bind(tfp, &ident_cfg);
354 		if (rc) {
355 			TFP_DRV_LOG(ERR,
356 				    "Identifier initialization failure\n");
357 			goto fail;
358 		}
359 		no_rsv_flag = false;
360 	}
361 
362 	rsv_cnt = tf_dev_reservation_check(TF_TBL_TYPE_MAX,
363 					   tf_tbl_p58[TF_DIR_RX],
364 					   (uint16_t *)resources->tbl_cnt);
365 	rsv_cnt += tf_dev_reservation_check(TF_TBL_TYPE_MAX,
366 					   tf_tbl_p58[TF_DIR_TX],
367 					   (uint16_t *)resources->tbl_cnt);
368 	if (rsv_cnt) {
369 		tbl_cfg.num_elements = TF_TBL_TYPE_MAX;
370 		tbl_cfg.cfg = tf_tbl_p58[TF_DIR_RX];
371 		tbl_cfg.resources = resources;
372 		rc = tf_tbl_bind(tfp, &tbl_cfg);
373 		if (rc) {
374 			TFP_DRV_LOG(ERR,
375 				    "Table initialization failure\n");
376 			goto fail;
377 		}
378 		no_rsv_flag = false;
379 
380 		rc = tf_tbl_sram_bind(tfp);
381 		if (rc) {
382 			TFP_DRV_LOG(ERR,
383 				    "SRAM table initialization failure\n");
384 			goto fail;
385 		}
386 	}
387 
388 	rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX,
389 					   tf_tcam_p58,
390 					   (uint16_t *)resources->tcam_cnt);
391 	if (rsv_cnt) {
392 		tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX;
393 		tcam_cfg.cfg = tf_tcam_p58;
394 		tcam_cfg.resources = resources;
395 		tcam_cfg.wc_num_slices = wc_num_slices;
396 		rc = tf_tcam_shared_bind(tfp, &tcam_cfg);
397 		if (rc) {
398 			TFP_DRV_LOG(ERR,
399 				    "TCAM initialization failure\n");
400 			goto fail;
401 		}
402 		no_rsv_flag = false;
403 	}
404 
405 	/*
406 	 * EM
407 	 */
408 	rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX,
409 					   tf_em_int_p58,
410 					   (uint16_t *)resources->em_cnt);
411 	if (rsv_cnt) {
412 		em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
413 		em_cfg.cfg = tf_em_int_p58;
414 		em_cfg.resources = resources;
415 		em_cfg.mem_type = 0; /* Not used by EM */
416 
417 		rc = tf_em_int_bind(tfp, &em_cfg);
418 		if (rc) {
419 			TFP_DRV_LOG(ERR,
420 				    "EM initialization failure\n");
421 			goto fail;
422 		}
423 		no_rsv_flag = false;
424 	}
425 
426 	/*
427 	 * There is no rm reserved for any tables
428 	 *
429 	 */
430 	if (no_rsv_flag) {
431 		TFP_DRV_LOG(ERR,
432 			    "No rm reserved for any tables\n");
433 		return -ENOMEM;
434 	}
435 
436 	/*
437 	 * IF_TBL
438 	 */
439 	if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX;
440 	if_tbl_cfg.cfg = tf_if_tbl_p58;
441 	rc = tf_if_tbl_bind(tfp, &if_tbl_cfg);
442 	if (rc) {
443 		TFP_DRV_LOG(ERR,
444 			    "IF Table initialization failure\n");
445 		goto fail;
446 	}
447 
448 	if (!tf_session_is_shared_session(tfs)) {
449 		/*
450 		 * GLOBAL_CFG
451 		 */
452 		global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX;
453 		global_cfg.cfg = tf_global_cfg_p58;
454 		rc = tf_global_cfg_bind(tfp, &global_cfg);
455 		if (rc) {
456 			TFP_DRV_LOG(ERR,
457 				    "Global Cfg initialization failure\n");
458 			goto fail;
459 		}
460 	}
461 
462 	/* Final function initialization */
463 	dev_handle->ops = &tf_dev_ops_p58;
464 
465 	return 0;
466 
467  fail:
468 	/* Cleanup of already created modules */
469 	frc = tf_dev_unbind_p58(tfp);
470 	if (frc)
471 		return frc;
472 
473 	return rc;
474 }
475 
476 /**
477  * Device specific unbind function, P5
478  *
479  * [in] tfp
480  *   Pointer to TF handle
481  *
482  * Returns
483  *   - (0) if successful.
484  *   - (-EINVAL) on failure.
485  */
486 static int
487 tf_dev_unbind_p58(struct tf *tfp)
488 {
489 	int rc = 0;
490 	bool fail = false;
491 	struct tf_session *tfs;
492 
493 	/* Retrieve the session information */
494 	rc = tf_session_get_session_internal(tfp, &tfs);
495 	if (rc)
496 		return rc;
497 
498 	/* Unbind all the support modules. As this is only done on
499 	 * close we only report errors as everything has to be cleaned
500 	 * up regardless.
501 	 *
502 	 * In case of residuals TCAMs are cleaned up first as to
503 	 * invalidate the pipeline in a clean manner.
504 	 */
505 	rc = tf_tcam_shared_unbind(tfp);
506 	if (rc) {
507 		TFP_DRV_LOG(INFO,
508 			    "Device unbind failed, TCAM\n");
509 		fail = true;
510 	}
511 
512 	rc = tf_ident_unbind(tfp);
513 	if (rc) {
514 		TFP_DRV_LOG(INFO,
515 			    "Device unbind failed, Identifier\n");
516 		fail = true;
517 	}
518 
519 	/* Unbind the SRAM table prior to table as the table manager
520 	 * owns and frees the table DB while the SRAM table manager owns
521 	 * and manages it's internal data structures.  SRAM table manager
522 	 * relies on the table rm_db to exist.
523 	 */
524 	rc = tf_tbl_sram_unbind(tfp);
525 	if (rc) {
526 		TFP_DRV_LOG(ERR,
527 			    "Device unbind failed, SRAM table\n");
528 		fail = true;
529 	}
530 
531 	rc = tf_tbl_unbind(tfp);
532 	if (rc) {
533 		TFP_DRV_LOG(INFO,
534 			    "Device unbind failed, Table Type\n");
535 		fail = true;
536 	}
537 
538 	rc = tf_em_int_unbind(tfp);
539 	if (rc) {
540 		TFP_DRV_LOG(INFO,
541 			    "Device unbind failed, EM\n");
542 		fail = true;
543 	}
544 
545 	rc = tf_if_tbl_unbind(tfp);
546 	if (rc) {
547 		TFP_DRV_LOG(ERR,
548 			    "Device unbind failed, IF Table Type\n");
549 		fail = true;
550 	}
551 
552 	if (!tf_session_is_shared_session(tfs)) {
553 		rc = tf_global_cfg_unbind(tfp);
554 		if (rc) {
555 			TFP_DRV_LOG(ERR,
556 				    "Device unbind failed, Global Cfg Type\n");
557 			fail = true;
558 		}
559 	}
560 
561 	if (fail)
562 		return -1;
563 
564 	return rc;
565 }
566 
567 int
568 tf_dev_bind(struct tf *tfp __rte_unused,
569 	    enum tf_device_type type,
570 	    struct tf_session_resources *resources,
571 	    uint16_t wc_num_slices,
572 	    struct tf_dev_info *dev_handle)
573 {
574 	switch (type) {
575 	case TF_DEVICE_TYPE_P4:
576 	case TF_DEVICE_TYPE_SR:
577 		dev_handle->type = type;
578 		return tf_dev_bind_p4(tfp,
579 				      resources,
580 				      dev_handle,
581 				      wc_num_slices);
582 	case TF_DEVICE_TYPE_P5:
583 		dev_handle->type = type;
584 		return tf_dev_bind_p58(tfp,
585 				       resources,
586 				       dev_handle,
587 				       wc_num_slices);
588 	default:
589 		TFP_DRV_LOG(ERR,
590 			    "No such device\n");
591 		return -ENODEV;
592 	}
593 }
594 
595 int
596 tf_dev_bind_ops(enum tf_device_type type,
597 		struct tf_dev_info *dev_handle)
598 {
599 	switch (type) {
600 	case TF_DEVICE_TYPE_P4:
601 	case TF_DEVICE_TYPE_SR:
602 		dev_handle->ops = &tf_dev_ops_p4_init;
603 		break;
604 	case TF_DEVICE_TYPE_P5:
605 		dev_handle->ops = &tf_dev_ops_p58_init;
606 		break;
607 	default:
608 		TFP_DRV_LOG(ERR,
609 			    "No such device\n");
610 		return -ENODEV;
611 	}
612 
613 	return 0;
614 }
615 
616 int
617 tf_dev_unbind(struct tf *tfp,
618 	      struct tf_dev_info *dev_handle)
619 {
620 	switch (dev_handle->type) {
621 	case TF_DEVICE_TYPE_P4:
622 	case TF_DEVICE_TYPE_SR:
623 		return tf_dev_unbind_p4(tfp);
624 	case TF_DEVICE_TYPE_P5:
625 		return tf_dev_unbind_p58(tfp);
626 	default:
627 		TFP_DRV_LOG(ERR,
628 			    "No such device\n");
629 		return -ENODEV;
630 	}
631 }
632