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_identifier.h"
9 #include "tf_shadow_identifier.h"
10 #include "tf_common.h"
11 #include "tf_rm.h"
12 #include "tf_util.h"
13 #include "tfp.h"
14
15 struct tf;
16
17 /**
18 * Identifier DBs.
19 */
20 static void *ident_db[TF_DIR_MAX];
21
22 /**
23 * Init flag, set on bind and cleared on unbind
24 */
25 static uint8_t init;
26
27 /**
28 * Identifier shadow DBs.
29 */
30 static void *ident_shadow_db[TF_DIR_MAX];
31
32 /**
33 * Shadow DB Init flag, set on bind and cleared on unbind
34 */
35 static uint8_t shadow_init;
36
37 int
tf_ident_bind(struct tf * tfp,struct tf_ident_cfg_parms * parms)38 tf_ident_bind(struct tf *tfp,
39 struct tf_ident_cfg_parms *parms)
40 {
41 int rc;
42 int i;
43 struct tf_rm_create_db_parms db_cfg = { 0 };
44 struct tf_shadow_ident_cfg_parms shadow_cfg = { 0 };
45 struct tf_shadow_ident_create_db_parms shadow_cdb = { 0 };
46
47 TF_CHECK_PARMS2(tfp, parms);
48
49 if (init) {
50 TFP_DRV_LOG(ERR,
51 "Identifier DB already initialized\n");
52 return -EINVAL;
53 }
54
55 db_cfg.type = TF_DEVICE_MODULE_TYPE_IDENTIFIER;
56 db_cfg.num_elements = parms->num_elements;
57 db_cfg.cfg = parms->cfg;
58
59 for (i = 0; i < TF_DIR_MAX; i++) {
60 db_cfg.dir = i;
61 db_cfg.alloc_cnt = parms->resources->ident_cnt[i].cnt;
62 db_cfg.rm_db = &ident_db[i];
63 rc = tf_rm_create_db(tfp, &db_cfg);
64 if (rc) {
65 TFP_DRV_LOG(ERR,
66 "%s: Identifier DB creation failed\n",
67 tf_dir_2_str(i));
68
69 return rc;
70 }
71
72 if (parms->shadow_copy) {
73 shadow_cfg.alloc_cnt =
74 parms->resources->ident_cnt[i].cnt;
75 shadow_cdb.num_elements = parms->num_elements;
76 shadow_cdb.tf_shadow_ident_db = &ident_shadow_db[i];
77 shadow_cdb.cfg = &shadow_cfg;
78 rc = tf_shadow_ident_create_db(&shadow_cdb);
79 if (rc) {
80 TFP_DRV_LOG(ERR,
81 "%s: Ident shadow DB creation failed\n",
82 tf_dir_2_str(i));
83
84 return rc;
85 }
86 shadow_init = 1;
87 }
88 }
89
90 init = 1;
91
92 TFP_DRV_LOG(INFO,
93 "Identifier - initialized\n");
94
95 return 0;
96 }
97
98 int
tf_ident_unbind(struct tf * tfp)99 tf_ident_unbind(struct tf *tfp)
100 {
101 int rc = 0;
102 int i;
103 struct tf_rm_free_db_parms fparms = { 0 };
104 struct tf_shadow_ident_free_db_parms sparms = { 0 };
105
106 TF_CHECK_PARMS1(tfp);
107
108 /* Bail if nothing has been initialized */
109 if (!init) {
110 TFP_DRV_LOG(INFO,
111 "No Identifier DBs created\n");
112 return 0;
113 }
114
115 for (i = 0; i < TF_DIR_MAX; i++) {
116 fparms.dir = i;
117 fparms.rm_db = ident_db[i];
118 rc = tf_rm_free_db(tfp, &fparms);
119 if (rc) {
120 TFP_DRV_LOG(ERR,
121 "rm free failed on unbind\n");
122 }
123 if (shadow_init) {
124 sparms.tf_shadow_ident_db = ident_shadow_db[i];
125 rc = tf_shadow_ident_free_db(&sparms);
126 if (rc) {
127 /* TODO: If there are failures on unbind we
128 * really just have to try until all DBs are
129 * attempted to be cleared.
130 */
131 }
132 ident_shadow_db[i] = NULL;
133 }
134 ident_db[i] = NULL;
135 }
136
137 init = 0;
138 shadow_init = 0;
139
140 return 0;
141 }
142
143 int
tf_ident_alloc(struct tf * tfp __rte_unused,struct tf_ident_alloc_parms * parms)144 tf_ident_alloc(struct tf *tfp __rte_unused,
145 struct tf_ident_alloc_parms *parms)
146 {
147 int rc;
148 uint32_t id;
149 uint32_t base_id;
150 struct tf_rm_allocate_parms aparms = { 0 };
151 struct tf_shadow_ident_insert_parms iparms = { 0 };
152
153 TF_CHECK_PARMS2(tfp, parms);
154
155 if (!init) {
156 TFP_DRV_LOG(ERR,
157 "%s: No Identifier DBs created\n",
158 tf_dir_2_str(parms->dir));
159 return -EINVAL;
160 }
161
162 /* Allocate requested element */
163 aparms.rm_db = ident_db[parms->dir];
164 aparms.db_index = parms->type;
165 aparms.index = &id;
166 aparms.base_index = &base_id;
167 rc = tf_rm_allocate(&aparms);
168 if (rc) {
169 TFP_DRV_LOG(ERR,
170 "%s: Failed allocate, type:%d\n",
171 tf_dir_2_str(parms->dir),
172 parms->type);
173 return rc;
174 }
175
176 if (shadow_init) {
177 iparms.tf_shadow_ident_db = ident_shadow_db[parms->dir];
178 iparms.type = parms->type;
179 iparms.id = base_id;
180
181 rc = tf_shadow_ident_insert(&iparms);
182 if (rc) {
183 TFP_DRV_LOG(ERR,
184 "%s: Failed insert shadow DB, type:%d\n",
185 tf_dir_2_str(parms->dir),
186 parms->type);
187 return rc;
188 }
189 }
190
191 *parms->id = id;
192
193 return 0;
194 }
195
196 int
tf_ident_free(struct tf * tfp __rte_unused,struct tf_ident_free_parms * parms)197 tf_ident_free(struct tf *tfp __rte_unused,
198 struct tf_ident_free_parms *parms)
199 {
200 int rc;
201 struct tf_rm_is_allocated_parms aparms = { 0 };
202 struct tf_rm_free_parms fparms = { 0 };
203 struct tf_shadow_ident_remove_parms rparms = { 0 };
204 int allocated = 0;
205 uint32_t base_id;
206
207 TF_CHECK_PARMS2(tfp, parms);
208
209 if (!init) {
210 TFP_DRV_LOG(ERR,
211 "%s: No Identifier DBs created\n",
212 tf_dir_2_str(parms->dir));
213 return -EINVAL;
214 }
215
216 /* Check if element is in use */
217 aparms.rm_db = ident_db[parms->dir];
218 aparms.db_index = parms->type;
219 aparms.index = parms->id;
220 aparms.base_index = &base_id;
221 aparms.allocated = &allocated;
222 rc = tf_rm_is_allocated(&aparms);
223 if (rc)
224 return rc;
225
226 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
227 TFP_DRV_LOG(ERR,
228 "%s: Entry already free, type:%d, index:%d\n",
229 tf_dir_2_str(parms->dir),
230 parms->type,
231 parms->id);
232 return -EINVAL;
233 }
234
235 if (shadow_init) {
236 rparms.tf_shadow_ident_db = ident_shadow_db[parms->dir];
237 rparms.type = parms->type;
238 rparms.id = base_id;
239 rparms.ref_cnt = parms->ref_cnt;
240
241 rc = tf_shadow_ident_remove(&rparms);
242 if (rc) {
243 TFP_DRV_LOG(ERR,
244 "%s: ref_cnt was 0 in shadow DB,"
245 " type:%d, index:%d\n",
246 tf_dir_2_str(parms->dir),
247 parms->type,
248 parms->id);
249 return rc;
250 }
251
252 if (*rparms.ref_cnt > 0)
253 return 0;
254 }
255
256 /* Free requested element */
257 fparms.rm_db = ident_db[parms->dir];
258 fparms.db_index = parms->type;
259 fparms.index = parms->id;
260 rc = tf_rm_free(&fparms);
261 if (rc) {
262 TFP_DRV_LOG(ERR,
263 "%s: Free failed, type:%d, index:%d\n",
264 tf_dir_2_str(parms->dir),
265 parms->type,
266 parms->id);
267 return rc;
268 }
269
270 return 0;
271 }
272
273 int
tf_ident_search(struct tf * tfp __rte_unused,struct tf_ident_search_parms * parms)274 tf_ident_search(struct tf *tfp __rte_unused,
275 struct tf_ident_search_parms *parms)
276 {
277 int rc;
278 struct tf_rm_is_allocated_parms aparms = { 0 };
279 struct tf_shadow_ident_search_parms sparms = { 0 };
280 int allocated = 0;
281 uint32_t base_id;
282
283 TF_CHECK_PARMS2(tfp, parms);
284
285 if (!init) {
286 TFP_DRV_LOG(ERR,
287 "%s: No Identifier DBs created\n",
288 tf_dir_2_str(parms->dir));
289 return -EINVAL;
290 }
291
292 if (!shadow_init) {
293 TFP_DRV_LOG(ERR,
294 "%s: Identifier Shadow copy is not enabled\n",
295 tf_dir_2_str(parms->dir));
296 return -EINVAL;
297 }
298
299 /* Check if element is in use */
300 aparms.rm_db = ident_db[parms->dir];
301 aparms.db_index = parms->type;
302 aparms.index = parms->search_id;
303 aparms.base_index = &base_id;
304 aparms.allocated = &allocated;
305 rc = tf_rm_is_allocated(&aparms);
306 if (rc)
307 return rc;
308
309 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
310 TFP_DRV_LOG(ERR,
311 "%s: Entry not allocated, type:%d, index:%d\n",
312 tf_dir_2_str(parms->dir),
313 parms->type,
314 parms->search_id);
315 return -EINVAL;
316 }
317
318 sparms.tf_shadow_ident_db = ident_shadow_db[parms->dir];
319 sparms.type = parms->type;
320 sparms.search_id = base_id;
321 sparms.hit = parms->hit;
322 sparms.ref_cnt = parms->ref_cnt;
323
324 rc = tf_shadow_ident_search(&sparms);
325 if (rc) {
326 TFP_DRV_LOG(ERR,
327 "%s: Failed search shadow DB, type:%d\n",
328 tf_dir_2_str(parms->dir),
329 parms->type);
330 return rc;
331 }
332
333 return 0;
334 }
335