1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2020 Broadcom
3  * All rights reserved.
4  */
5 
6 #include <rte_common.h>
7 
8 #include "tf_shadow_identifier.h"
9 #include "tf_common.h"
10 #include "tf_util.h"
11 #include "tfp.h"
12 
13 /**
14  * Shadow identifier DB element
15  */
16 struct tf_shadow_ident_element {
17 	/**
18 	 * Identifier
19 	 */
20 	uint32_t *id;
21 
22 	/**
23 	 * Reference count, array of number of identifier type entries
24 	 */
25 	uint32_t *ref_count;
26 };
27 
28 /**
29  * Shadow identifier DB definition
30  */
31 struct tf_shadow_ident_db {
32 	/**
33 	 * Number of elements in the DB
34 	 */
35 	uint16_t num_entries;
36 
37 	/**
38 	 * The DB consists of an array of elements
39 	 */
40 	struct tf_shadow_ident_element *db;
41 };
42 
43 int
tf_shadow_ident_create_db(struct tf_shadow_ident_create_db_parms * parms)44 tf_shadow_ident_create_db(struct tf_shadow_ident_create_db_parms *parms)
45 {
46 	int rc;
47 	int i;
48 	struct tfp_calloc_parms cparms;
49 	struct tf_shadow_ident_db *shadow_db;
50 	struct tf_shadow_ident_element *db;
51 
52 	TF_CHECK_PARMS1(parms);
53 
54 	/* Build the shadow DB per the request */
55 	cparms.nitems = 1;
56 	cparms.size = sizeof(struct tf_shadow_ident_db);
57 	cparms.alignment = 0;
58 	rc = tfp_calloc(&cparms);
59 	if (rc)
60 		return rc;
61 	shadow_db = (void *)cparms.mem_va;
62 
63 	/* Build the DB within shadow DB */
64 	cparms.nitems = parms->num_elements;
65 	cparms.size = sizeof(struct tf_shadow_ident_element);
66 	rc = tfp_calloc(&cparms);
67 	if (rc)
68 		return rc;
69 	shadow_db->db = (struct tf_shadow_ident_element *)cparms.mem_va;
70 	shadow_db->num_entries = parms->num_elements;
71 
72 	db = shadow_db->db;
73 	for (i = 0; i < parms->num_elements; i++) {
74 		/* If the element didn't request an allocation no need
75 		 * to create a pool nor verify if we got a reservation.
76 		 */
77 		if (parms->cfg->alloc_cnt[i] == 0)
78 			continue;
79 
80 		/* Create array */
81 		cparms.nitems = parms->cfg->alloc_cnt[i];
82 		cparms.size = sizeof(uint32_t);
83 		rc = tfp_calloc(&cparms);
84 		if (rc) {
85 			TFP_DRV_LOG(ERR,
86 				    "%s: Array alloc failed, type:%d\n",
87 				    tf_dir_2_str(parms->dir),
88 				    i);
89 			goto fail;
90 		}
91 		db[i].ref_count = (uint32_t *)cparms.mem_va;
92 	}
93 
94 	*parms->tf_shadow_ident_db = (void *)shadow_db;
95 
96 	return 0;
97 fail:
98 	tfp_free((void *)db->ref_count);
99 	tfp_free((void *)db);
100 	tfp_free((void *)shadow_db);
101 	parms->tf_shadow_ident_db = NULL;
102 
103 	return -EINVAL;
104 }
105 
106 int
tf_shadow_ident_free_db(struct tf_shadow_ident_free_db_parms * parms)107 tf_shadow_ident_free_db(struct tf_shadow_ident_free_db_parms *parms)
108 {
109 	int i;
110 	struct tf_shadow_ident_db *shadow_db;
111 
112 	TF_CHECK_PARMS1(parms);
113 
114 	shadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db;
115 	for (i = 0; i < shadow_db->num_entries; i++)
116 		tfp_free((void *)shadow_db->db[i].ref_count);
117 
118 	tfp_free((void *)shadow_db->db);
119 	tfp_free((void *)parms->tf_shadow_ident_db);
120 
121 	return 0;
122 }
123 
124 int
tf_shadow_ident_search(struct tf_shadow_ident_search_parms * parms)125 tf_shadow_ident_search(struct tf_shadow_ident_search_parms *parms)
126 {
127 	struct tf_shadow_ident_db *shadow_db;
128 	uint32_t ref_cnt = 0;
129 
130 	TF_CHECK_PARMS1(parms);
131 
132 	shadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db;
133 	ref_cnt = shadow_db->db[parms->type].ref_count[parms->search_id];
134 	if (ref_cnt > 0) {
135 		*parms->hit = 1;
136 		*parms->ref_cnt = ++ref_cnt;
137 		shadow_db->db[parms->type].ref_count[parms->search_id] =
138 								ref_cnt;
139 	} else {
140 		*parms->hit = 0;
141 		*parms->ref_cnt = 0;
142 	}
143 
144 
145 	return 0;
146 }
147 
148 #define ID_REF_CNT_MAX 0xffffffff
149 int
tf_shadow_ident_insert(struct tf_shadow_ident_insert_parms * parms)150 tf_shadow_ident_insert(struct tf_shadow_ident_insert_parms *parms)
151 {
152 	struct tf_shadow_ident_db *shadow_db;
153 
154 	TF_CHECK_PARMS1(parms);
155 
156 	shadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db;
157 
158 	/* In case of overflow, ref count keeps the max value */
159 	if (shadow_db->db[parms->type].ref_count[parms->id] < ID_REF_CNT_MAX)
160 		shadow_db->db[parms->type].ref_count[parms->id]++;
161 	else
162 		TFP_DRV_LOG(ERR,
163 			    "Identifier %d in type %d reaches the max ref_cnt\n",
164 			    parms->type,
165 			    parms->id);
166 
167 	parms->ref_cnt = shadow_db->db[parms->type].ref_count[parms->id];
168 
169 	return 0;
170 }
171 
172 int
tf_shadow_ident_remove(struct tf_shadow_ident_remove_parms * parms)173 tf_shadow_ident_remove(struct tf_shadow_ident_remove_parms *parms)
174 {
175 	struct tf_shadow_ident_db *shadow_db;
176 	uint32_t ref_cnt = 0;
177 
178 	TF_CHECK_PARMS1(parms);
179 
180 	shadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db;
181 	ref_cnt = shadow_db->db[parms->type].ref_count[parms->id];
182 	if (ref_cnt > 0)
183 		shadow_db->db[parms->type].ref_count[parms->id]--;
184 	else
185 		return -EINVAL;
186 
187 	*parms->ref_cnt = shadow_db->db[parms->type].ref_count[parms->id];
188 
189 	return 0;
190 }
191