xref: /dpdk/drivers/net/bnxt/tf_core/tf_tbl.c (revision 3cc6ecfdfe85d2577fef30e1791bb7534e3d60b3)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2020 Broadcom
3  * All rights reserved.
4  */
5 
6 /* Truflow Table APIs and supporting code */
7 
8 #include <rte_common.h>
9 
10 #include "tf_tbl.h"
11 #include "tf_common.h"
12 #include "tf_rm.h"
13 #include "tf_util.h"
14 #include "tf_msg.h"
15 #include "tfp.h"
16 #include "tf_shadow_tbl.h"
17 #include "tf_session.h"
18 #include "tf_device.h"
19 
20 
21 struct tf;
22 
23 /**
24  * Table DBs.
25  */
26 static void *tbl_db[TF_DIR_MAX];
27 
28 /**
29  * Table Shadow DBs
30  */
31 static void *shadow_tbl_db[TF_DIR_MAX];
32 
33 /**
34  * Init flag, set on bind and cleared on unbind
35  */
36 static uint8_t init;
37 
38 /**
39  * Shadow init flag, set on bind and cleared on unbind
40  */
41 static uint8_t shadow_init;
42 
43 int
44 tf_tbl_bind(struct tf *tfp,
45 	    struct tf_tbl_cfg_parms *parms)
46 {
47 	int rc, d, i;
48 	struct tf_rm_alloc_info info;
49 	struct tf_rm_free_db_parms fparms;
50 	struct tf_shadow_tbl_free_db_parms fshadow;
51 	struct tf_rm_get_alloc_info_parms ainfo;
52 	struct tf_shadow_tbl_cfg_parms shadow_cfg;
53 	struct tf_shadow_tbl_create_db_parms shadow_cdb;
54 	struct tf_rm_create_db_parms db_cfg = { 0 };
55 
56 	TF_CHECK_PARMS2(tfp, parms);
57 
58 	if (init) {
59 		TFP_DRV_LOG(ERR,
60 			    "Table DB already initialized\n");
61 		return -EINVAL;
62 	}
63 
64 	db_cfg.num_elements = parms->num_elements;
65 	db_cfg.type = TF_DEVICE_MODULE_TYPE_TABLE;
66 	db_cfg.num_elements = parms->num_elements;
67 	db_cfg.cfg = parms->cfg;
68 
69 	for (d = 0; d < TF_DIR_MAX; d++) {
70 		db_cfg.dir = d;
71 		db_cfg.alloc_cnt = parms->resources->tbl_cnt[d].cnt;
72 		db_cfg.rm_db = &tbl_db[d];
73 		rc = tf_rm_create_db(tfp, &db_cfg);
74 		if (rc) {
75 			TFP_DRV_LOG(ERR,
76 				    "%s: Table DB creation failed\n",
77 				    tf_dir_2_str(d));
78 
79 			return rc;
80 		}
81 	}
82 
83 	/* Initialize the Shadow Table. */
84 	if (parms->shadow_copy) {
85 		for (d = 0; d < TF_DIR_MAX; d++) {
86 			memset(&shadow_cfg, 0, sizeof(shadow_cfg));
87 			memset(&shadow_cdb, 0, sizeof(shadow_cdb));
88 			/* Get the base addresses of the tables */
89 			for (i = 0; i < TF_TBL_TYPE_MAX; i++) {
90 				memset(&info, 0, sizeof(info));
91 
92 				if (!parms->resources->tbl_cnt[d].cnt[i])
93 					continue;
94 				ainfo.rm_db = tbl_db[d];
95 				ainfo.db_index = i;
96 				ainfo.info = &info;
97 				rc = tf_rm_get_info(&ainfo);
98 				if (rc)
99 					goto error;
100 
101 				shadow_cfg.base_addr[i] = info.entry.start;
102 			}
103 
104 			/* Create the shadow db */
105 			shadow_cfg.alloc_cnt =
106 				parms->resources->tbl_cnt[d].cnt;
107 			shadow_cfg.num_entries = parms->num_elements;
108 
109 			shadow_cdb.shadow_db = &shadow_tbl_db[d];
110 			shadow_cdb.cfg = &shadow_cfg;
111 			rc = tf_shadow_tbl_create_db(&shadow_cdb);
112 			if (rc) {
113 				TFP_DRV_LOG(ERR,
114 					    "Shadow TBL DB creation failed "
115 					    "rc=%d\n", rc);
116 				goto error;
117 			}
118 		}
119 		shadow_init = 1;
120 	}
121 
122 	init = 1;
123 
124 	TFP_DRV_LOG(INFO,
125 		    "Table Type - initialized\n");
126 
127 	return 0;
128 error:
129 	for (d = 0; d < TF_DIR_MAX; d++) {
130 		memset(&fparms, 0, sizeof(fparms));
131 		fparms.dir = d;
132 		fparms.rm_db = tbl_db[d];
133 		/* Ignoring return here since we are in the error case */
134 		(void)tf_rm_free_db(tfp, &fparms);
135 
136 		if (parms->shadow_copy) {
137 			fshadow.shadow_db = shadow_tbl_db[d];
138 			tf_shadow_tbl_free_db(&fshadow);
139 			shadow_tbl_db[d] = NULL;
140 		}
141 
142 		tbl_db[d] = NULL;
143 	}
144 
145 	shadow_init = 0;
146 	init = 0;
147 
148 	return rc;
149 }
150 
151 int
152 tf_tbl_unbind(struct tf *tfp)
153 {
154 	int rc;
155 	int i;
156 	struct tf_rm_free_db_parms fparms = { 0 };
157 	struct tf_shadow_tbl_free_db_parms fshadow;
158 
159 	TF_CHECK_PARMS1(tfp);
160 
161 	/* Bail if nothing has been initialized */
162 	if (!init) {
163 		TFP_DRV_LOG(INFO,
164 			    "No Table DBs created\n");
165 		return 0;
166 	}
167 
168 	for (i = 0; i < TF_DIR_MAX; i++) {
169 		fparms.dir = i;
170 		fparms.rm_db = tbl_db[i];
171 		rc = tf_rm_free_db(tfp, &fparms);
172 		if (rc)
173 			return rc;
174 
175 		tbl_db[i] = NULL;
176 
177 		if (shadow_init) {
178 			memset(&fshadow, 0, sizeof(fshadow));
179 			fshadow.shadow_db = shadow_tbl_db[i];
180 			tf_shadow_tbl_free_db(&fshadow);
181 			shadow_tbl_db[i] = NULL;
182 		}
183 	}
184 
185 	init = 0;
186 	shadow_init = 0;
187 
188 	return 0;
189 }
190 
191 int
192 tf_tbl_alloc(struct tf *tfp __rte_unused,
193 	     struct tf_tbl_alloc_parms *parms)
194 {
195 	int rc;
196 	uint32_t idx;
197 	struct tf_rm_allocate_parms aparms = { 0 };
198 
199 	TF_CHECK_PARMS2(tfp, parms);
200 
201 	if (!init) {
202 		TFP_DRV_LOG(ERR,
203 			    "%s: No Table DBs created\n",
204 			    tf_dir_2_str(parms->dir));
205 		return -EINVAL;
206 	}
207 
208 	/* Allocate requested element */
209 	aparms.rm_db = tbl_db[parms->dir];
210 	aparms.db_index = parms->type;
211 	aparms.index = &idx;
212 	rc = tf_rm_allocate(&aparms);
213 	if (rc) {
214 		TFP_DRV_LOG(ERR,
215 			    "%s: Failed allocate, type:%d\n",
216 			    tf_dir_2_str(parms->dir),
217 			    parms->type);
218 		return rc;
219 	}
220 
221 	*parms->idx = idx;
222 
223 	return 0;
224 }
225 
226 int
227 tf_tbl_free(struct tf *tfp __rte_unused,
228 	    struct tf_tbl_free_parms *parms)
229 {
230 	int rc;
231 	struct tf_rm_is_allocated_parms aparms = { 0 };
232 	struct tf_rm_free_parms fparms = { 0 };
233 	struct tf_shadow_tbl_remove_parms shparms;
234 	int allocated = 0;
235 
236 	TF_CHECK_PARMS2(tfp, parms);
237 
238 	if (!init) {
239 		TFP_DRV_LOG(ERR,
240 			    "%s: No Table DBs created\n",
241 			    tf_dir_2_str(parms->dir));
242 		return -EINVAL;
243 	}
244 
245 	/* Check if element is in use */
246 	aparms.rm_db = tbl_db[parms->dir];
247 	aparms.db_index = parms->type;
248 	aparms.index = parms->idx;
249 	aparms.allocated = &allocated;
250 	rc = tf_rm_is_allocated(&aparms);
251 	if (rc)
252 		return rc;
253 
254 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
255 		TFP_DRV_LOG(ERR,
256 			    "%s: Entry already free, type:%d, index:%d\n",
257 			    tf_dir_2_str(parms->dir),
258 			    parms->type,
259 			    parms->idx);
260 		return -EINVAL;
261 	}
262 
263 	/*
264 	 * The Shadow mgmt, if enabled, determines if the entry needs
265 	 * to be deleted.
266 	 */
267 	if (shadow_init) {
268 		memset(&shparms, 0, sizeof(shparms));
269 		shparms.shadow_db = shadow_tbl_db[parms->dir];
270 		shparms.fparms = parms;
271 		rc = tf_shadow_tbl_remove(&shparms);
272 		if (rc) {
273 			/*
274 			 * Should not get here, log it and let the entry be
275 			 * deleted.
276 			 */
277 			TFP_DRV_LOG(ERR, "%s: Shadow free fail, "
278 				    "type:%d index:%d deleting the entry.\n",
279 				    tf_dir_2_str(parms->dir),
280 				    parms->type,
281 				    parms->idx);
282 		} else {
283 			/*
284 			 * If the entry still has references, just return the
285 			 * ref count to the caller.  No need to remove entry
286 			 * from rm.
287 			 */
288 			if (parms->ref_cnt >= 1)
289 				return rc;
290 		}
291 	}
292 
293 	/* Free requested element */
294 	fparms.rm_db = tbl_db[parms->dir];
295 	fparms.db_index = parms->type;
296 	fparms.index = parms->idx;
297 	rc = tf_rm_free(&fparms);
298 	if (rc) {
299 		TFP_DRV_LOG(ERR,
300 			    "%s: Free failed, type:%d, index:%d\n",
301 			    tf_dir_2_str(parms->dir),
302 			    parms->type,
303 			    parms->idx);
304 		return rc;
305 	}
306 
307 	return 0;
308 }
309 
310 int
311 tf_tbl_alloc_search(struct tf *tfp,
312 		    struct tf_tbl_alloc_search_parms *parms)
313 {
314 	int rc, frc;
315 	uint32_t idx;
316 	struct tf_session *tfs;
317 	struct tf_dev_info *dev;
318 	struct tf_tbl_alloc_parms aparms;
319 	struct tf_shadow_tbl_search_parms sparms;
320 	struct tf_shadow_tbl_bind_index_parms bparms;
321 	struct tf_tbl_free_parms fparms;
322 
323 	TF_CHECK_PARMS2(tfp, parms);
324 
325 	if (!shadow_init || !shadow_tbl_db[parms->dir]) {
326 		TFP_DRV_LOG(ERR, "%s: Shadow TBL not initialized.\n",
327 			    tf_dir_2_str(parms->dir));
328 		return -EINVAL;
329 	}
330 
331 	memset(&sparms, 0, sizeof(sparms));
332 	sparms.sparms = parms;
333 	sparms.shadow_db = shadow_tbl_db[parms->dir];
334 	rc = tf_shadow_tbl_search(&sparms);
335 	if (rc)
336 		return rc;
337 
338 	/*
339 	 * The app didn't request us to alloc the entry, so return now.
340 	 * The hit should have been updated in the original search parm.
341 	 */
342 	if (!parms->alloc || parms->search_status != MISS)
343 		return rc;
344 
345 	/* Retrieve the session information */
346 	rc = tf_session_get_session(tfp, &tfs);
347 	if (rc) {
348 		TFP_DRV_LOG(ERR,
349 			    "%s: Failed to lookup session, rc:%s\n",
350 			    tf_dir_2_str(parms->dir),
351 			    strerror(-rc));
352 		return rc;
353 	}
354 
355 	/* Retrieve the device information */
356 	rc = tf_session_get_device(tfs, &dev);
357 	if (rc) {
358 		TFP_DRV_LOG(ERR,
359 			    "%s: Failed to lookup device, rc:%s\n",
360 			    tf_dir_2_str(parms->dir),
361 			    strerror(-rc));
362 		return rc;
363 	}
364 
365 	/* Allocate the index */
366 	if (dev->ops->tf_dev_alloc_tbl == NULL) {
367 		rc = -EOPNOTSUPP;
368 		TFP_DRV_LOG(ERR,
369 			    "%s: Operation not supported, rc:%s\n",
370 			    tf_dir_2_str(parms->dir),
371 			    strerror(-rc));
372 		return -EOPNOTSUPP;
373 	}
374 
375 	memset(&aparms, 0, sizeof(aparms));
376 	aparms.dir = parms->dir;
377 	aparms.type = parms->type;
378 	aparms.tbl_scope_id = parms->tbl_scope_id;
379 	aparms.idx = &idx;
380 	rc = dev->ops->tf_dev_alloc_tbl(tfp, &aparms);
381 	if (rc) {
382 		TFP_DRV_LOG(ERR,
383 			    "%s: Table allocation failed, rc:%s\n",
384 			    tf_dir_2_str(parms->dir),
385 			    strerror(-rc));
386 		return rc;
387 	}
388 
389 	/* Bind the allocated index to the data */
390 	memset(&bparms, 0, sizeof(bparms));
391 	bparms.shadow_db = shadow_tbl_db[parms->dir];
392 	bparms.dir = parms->dir;
393 	bparms.type = parms->type;
394 	bparms.idx = idx;
395 	bparms.data = parms->result;
396 	bparms.data_sz_in_bytes = parms->result_sz_in_bytes;
397 	bparms.hb_handle = sparms.hb_handle;
398 	rc = tf_shadow_tbl_bind_index(&bparms);
399 	if (rc) {
400 		/* Error binding entry, need to free the allocated idx */
401 		if (dev->ops->tf_dev_free_tbl == NULL) {
402 			rc = -EOPNOTSUPP;
403 			TFP_DRV_LOG(ERR,
404 				    "%s: Operation not supported, rc:%s\n",
405 				    tf_dir_2_str(parms->dir),
406 				    strerror(-rc));
407 			return rc;
408 		}
409 
410 		memset(&fparms, 0, sizeof(fparms));
411 		fparms.dir = parms->dir;
412 		fparms.type = parms->type;
413 		fparms.idx = idx;
414 		frc = dev->ops->tf_dev_free_tbl(tfp, &fparms);
415 		if (frc) {
416 			TFP_DRV_LOG(ERR,
417 				    "%s: Failed free index allocated during "
418 				    "search. rc=%s\n",
419 				    tf_dir_2_str(parms->dir),
420 				    strerror(-frc));
421 			/* return the original failure. */
422 			return rc;
423 		}
424 	}
425 
426 	parms->idx = idx;
427 
428 	return rc;
429 }
430 
431 int
432 tf_tbl_set(struct tf *tfp,
433 	   struct tf_tbl_set_parms *parms)
434 {
435 	int rc;
436 	int allocated = 0;
437 	uint16_t hcapi_type;
438 	struct tf_rm_is_allocated_parms aparms = { 0 };
439 	struct tf_rm_get_hcapi_parms hparms = { 0 };
440 
441 	TF_CHECK_PARMS3(tfp, parms, parms->data);
442 
443 	if (!init) {
444 		TFP_DRV_LOG(ERR,
445 			    "%s: No Table DBs created\n",
446 			    tf_dir_2_str(parms->dir));
447 		return -EINVAL;
448 	}
449 
450 	/* Verify that the entry has been previously allocated */
451 	aparms.rm_db = tbl_db[parms->dir];
452 	aparms.db_index = parms->type;
453 	aparms.index = parms->idx;
454 	aparms.allocated = &allocated;
455 	rc = tf_rm_is_allocated(&aparms);
456 	if (rc)
457 		return rc;
458 
459 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
460 		TFP_DRV_LOG(ERR,
461 		   "%s, Invalid or not allocated index, type:%d, idx:%d\n",
462 		   tf_dir_2_str(parms->dir),
463 		   parms->type,
464 		   parms->idx);
465 		return -EINVAL;
466 	}
467 
468 	/* Set the entry */
469 	hparms.rm_db = tbl_db[parms->dir];
470 	hparms.db_index = parms->type;
471 	hparms.hcapi_type = &hcapi_type;
472 	rc = tf_rm_get_hcapi_type(&hparms);
473 	if (rc) {
474 		TFP_DRV_LOG(ERR,
475 			    "%s, Failed type lookup, type:%d, rc:%s\n",
476 			    tf_dir_2_str(parms->dir),
477 			    parms->type,
478 			    strerror(-rc));
479 		return rc;
480 	}
481 
482 	rc = tf_msg_set_tbl_entry(tfp,
483 				  parms->dir,
484 				  hcapi_type,
485 				  parms->data_sz_in_bytes,
486 				  parms->data,
487 				  parms->idx);
488 	if (rc) {
489 		TFP_DRV_LOG(ERR,
490 			    "%s, Set failed, type:%d, rc:%s\n",
491 			    tf_dir_2_str(parms->dir),
492 			    parms->type,
493 			    strerror(-rc));
494 		return rc;
495 	}
496 
497 	return 0;
498 }
499 
500 int
501 tf_tbl_get(struct tf *tfp,
502 	   struct tf_tbl_get_parms *parms)
503 {
504 	int rc;
505 	uint16_t hcapi_type;
506 	int allocated = 0;
507 	struct tf_rm_is_allocated_parms aparms = { 0 };
508 	struct tf_rm_get_hcapi_parms hparms = { 0 };
509 
510 	TF_CHECK_PARMS3(tfp, parms, parms->data);
511 
512 	if (!init) {
513 		TFP_DRV_LOG(ERR,
514 			    "%s: No Table DBs created\n",
515 			    tf_dir_2_str(parms->dir));
516 		return -EINVAL;
517 	}
518 
519 	/* Verify that the entry has been previously allocated */
520 	aparms.rm_db = tbl_db[parms->dir];
521 	aparms.db_index = parms->type;
522 	aparms.index = parms->idx;
523 	aparms.allocated = &allocated;
524 	rc = tf_rm_is_allocated(&aparms);
525 	if (rc)
526 		return rc;
527 
528 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
529 		TFP_DRV_LOG(ERR,
530 		   "%s, Invalid or not allocated index, type:%d, idx:%d\n",
531 		   tf_dir_2_str(parms->dir),
532 		   parms->type,
533 		   parms->idx);
534 		return -EINVAL;
535 	}
536 
537 	/* Set the entry */
538 	hparms.rm_db = tbl_db[parms->dir];
539 	hparms.db_index = parms->type;
540 	hparms.hcapi_type = &hcapi_type;
541 	rc = tf_rm_get_hcapi_type(&hparms);
542 	if (rc) {
543 		TFP_DRV_LOG(ERR,
544 			    "%s, Failed type lookup, type:%d, rc:%s\n",
545 			    tf_dir_2_str(parms->dir),
546 			    parms->type,
547 			    strerror(-rc));
548 		return rc;
549 	}
550 
551 	/* Get the entry */
552 	rc = tf_msg_get_tbl_entry(tfp,
553 				  parms->dir,
554 				  hcapi_type,
555 				  parms->data_sz_in_bytes,
556 				  parms->data,
557 				  parms->idx);
558 	if (rc) {
559 		TFP_DRV_LOG(ERR,
560 			    "%s, Get failed, type:%d, rc:%s\n",
561 			    tf_dir_2_str(parms->dir),
562 			    parms->type,
563 			    strerror(-rc));
564 		return rc;
565 	}
566 
567 	return 0;
568 }
569 
570 int
571 tf_tbl_bulk_get(struct tf *tfp,
572 		struct tf_tbl_get_bulk_parms *parms)
573 {
574 	int rc;
575 	uint16_t hcapi_type;
576 	struct tf_rm_get_hcapi_parms hparms = { 0 };
577 	struct tf_rm_check_indexes_in_range_parms cparms = { 0 };
578 
579 	TF_CHECK_PARMS2(tfp, parms);
580 
581 	if (!init) {
582 		TFP_DRV_LOG(ERR,
583 			    "%s: No Table DBs created\n",
584 			    tf_dir_2_str(parms->dir));
585 
586 		return -EINVAL;
587 	}
588 
589 	/* Verify that the entries are in the range of reserved resources. */
590 	cparms.rm_db = tbl_db[parms->dir];
591 	cparms.db_index = parms->type;
592 	cparms.starting_index = parms->starting_idx;
593 	cparms.num_entries = parms->num_entries;
594 
595 	rc = tf_rm_check_indexes_in_range(&cparms);
596 	if (rc) {
597 		TFP_DRV_LOG(ERR,
598 			    "%s, Invalid or %d index starting from %d"
599 			    " not in range, type:%d",
600 			    tf_dir_2_str(parms->dir),
601 			    parms->starting_idx,
602 			    parms->num_entries,
603 			    parms->type);
604 		return rc;
605 	}
606 
607 	hparms.rm_db = tbl_db[parms->dir];
608 	hparms.db_index = parms->type;
609 	hparms.hcapi_type = &hcapi_type;
610 	rc = tf_rm_get_hcapi_type(&hparms);
611 	if (rc) {
612 		TFP_DRV_LOG(ERR,
613 			    "%s, Failed type lookup, type:%d, rc:%s\n",
614 			    tf_dir_2_str(parms->dir),
615 			    parms->type,
616 			    strerror(-rc));
617 		return rc;
618 	}
619 
620 	/* Get the entries */
621 	rc = tf_msg_bulk_get_tbl_entry(tfp,
622 				       parms->dir,
623 				       hcapi_type,
624 				       parms->starting_idx,
625 				       parms->num_entries,
626 				       parms->entry_sz_in_bytes,
627 				       parms->physical_mem_addr);
628 	if (rc) {
629 		TFP_DRV_LOG(ERR,
630 			    "%s, Bulk get failed, type:%d, rc:%s\n",
631 			    tf_dir_2_str(parms->dir),
632 			    parms->type,
633 			    strerror(-rc));
634 	}
635 
636 	return rc;
637 }
638