1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2021 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 #include "tf_session.h"
15
16 struct tf;
17
18 /**
19 * Identifier shadow DBs.
20 */
21 static void *ident_shadow_db[TF_DIR_MAX];
22
23 /**
24 * Shadow DB Init flag, set on bind and cleared on unbind
25 */
26 static uint8_t shadow_init;
27
28 int
tf_ident_bind(struct tf * tfp,struct tf_ident_cfg_parms * parms)29 tf_ident_bind(struct tf *tfp,
30 struct tf_ident_cfg_parms *parms)
31 {
32 int rc;
33 int db_rc[TF_DIR_MAX] = { 0 };
34 int i;
35 struct tf_rm_create_db_parms db_cfg = { 0 };
36 struct tf_shadow_ident_cfg_parms shadow_cfg = { 0 };
37 struct tf_shadow_ident_create_db_parms shadow_cdb = { 0 };
38 struct ident_rm_db *ident_db;
39 struct tfp_calloc_parms cparms;
40 struct tf_session *tfs;
41
42 TF_CHECK_PARMS2(tfp, parms);
43
44 /* Retrieve the session information */
45 rc = tf_session_get_session_internal(tfp, &tfs);
46 if (rc)
47 return rc;
48
49 memset(&db_cfg, 0, sizeof(db_cfg));
50 cparms.nitems = 1;
51 cparms.size = sizeof(struct ident_rm_db);
52 cparms.alignment = 0;
53 if (tfp_calloc(&cparms) != 0) {
54 TFP_DRV_LOG(ERR, "ident_rm_db alloc error %s\n",
55 strerror(ENOMEM));
56 return -ENOMEM;
57 }
58
59 ident_db = cparms.mem_va;
60 for (i = 0; i < TF_DIR_MAX; i++)
61 ident_db->ident_db[i] = NULL;
62 tf_session_set_db(tfp, TF_MODULE_TYPE_IDENTIFIER, ident_db);
63
64 db_cfg.module = TF_MODULE_TYPE_IDENTIFIER;
65 db_cfg.num_elements = parms->num_elements;
66 db_cfg.cfg = parms->cfg;
67
68 for (i = 0; i < TF_DIR_MAX; i++) {
69 db_cfg.rm_db = (void *)&ident_db->ident_db[i];
70 db_cfg.dir = i;
71 db_cfg.alloc_cnt = parms->resources->ident_cnt[i].cnt;
72 if (tf_session_is_shared_session(tfs) &&
73 (!tf_session_is_shared_session_creator(tfs)))
74 db_rc[i] = tf_rm_create_db_no_reservation(tfp, &db_cfg);
75 else
76 db_rc[i] = tf_rm_create_db(tfp, &db_cfg);
77
78 if (parms->shadow_copy) {
79 shadow_cfg.alloc_cnt =
80 parms->resources->ident_cnt[i].cnt;
81 shadow_cdb.num_elements = parms->num_elements;
82 shadow_cdb.tf_shadow_ident_db = &ident_shadow_db[i];
83 shadow_cdb.cfg = &shadow_cfg;
84 rc = tf_shadow_ident_create_db(&shadow_cdb);
85 if (rc) {
86 TFP_DRV_LOG(ERR,
87 "%s: Ident shadow DB creation failed\n",
88 tf_dir_2_str(i));
89
90 return rc;
91 }
92 shadow_init = 1;
93 }
94 }
95
96 /* No db created */
97 if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) {
98 TFP_DRV_LOG(ERR, "No Identifier DB created\n");
99 return db_rc[TF_DIR_RX];
100 }
101
102 TFP_DRV_LOG(INFO,
103 "Identifier - initialized\n");
104
105 return 0;
106 }
107
108 int
tf_ident_unbind(struct tf * tfp)109 tf_ident_unbind(struct tf *tfp)
110 {
111 int rc = 0;
112 int i;
113 struct tf_rm_free_db_parms fparms = { 0 };
114 struct tf_shadow_ident_free_db_parms sparms = { 0 };
115 struct ident_rm_db *ident_db;
116 void *ident_db_ptr = NULL;
117
118 TF_CHECK_PARMS1(tfp);
119
120 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_IDENTIFIER, &ident_db_ptr);
121 if (rc)
122 return 0;
123 ident_db = (struct ident_rm_db *)ident_db_ptr;
124
125 for (i = 0; i < TF_DIR_MAX; i++) {
126 if (ident_db->ident_db[i] == NULL)
127 continue;
128 fparms.rm_db = ident_db->ident_db[i];
129 fparms.dir = i;
130 rc = tf_rm_free_db(tfp, &fparms);
131 if (rc) {
132 TFP_DRV_LOG(ERR,
133 "rm free failed on unbind\n");
134 }
135 if (shadow_init) {
136 sparms.tf_shadow_ident_db = ident_shadow_db[i];
137 rc = tf_shadow_ident_free_db(&sparms);
138 if (rc) {
139 /* TODO: If there are failures on unbind we
140 * really just have to try until all DBs are
141 * attempted to be cleared.
142 */
143 }
144 ident_shadow_db[i] = NULL;
145 }
146 ident_db->ident_db[i] = NULL;
147 }
148
149 shadow_init = 0;
150
151 return 0;
152 }
153
154 int
tf_ident_alloc(struct tf * tfp __rte_unused,struct tf_ident_alloc_parms * parms)155 tf_ident_alloc(struct tf *tfp __rte_unused,
156 struct tf_ident_alloc_parms *parms)
157 {
158 int rc;
159 uint32_t id;
160 uint32_t base_id;
161 struct tf_rm_allocate_parms aparms = { 0 };
162 struct tf_shadow_ident_insert_parms iparms = { 0 };
163 struct ident_rm_db *ident_db;
164 void *ident_db_ptr = NULL;
165
166 TF_CHECK_PARMS2(tfp, parms);
167
168 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_IDENTIFIER, &ident_db_ptr);
169 if (rc) {
170 TFP_DRV_LOG(ERR,
171 "Failed to get ident_db from session, rc:%s\n",
172 strerror(-rc));
173 return rc;
174 }
175 ident_db = (struct ident_rm_db *)ident_db_ptr;
176
177 aparms.rm_db = ident_db->ident_db[parms->dir];
178 aparms.subtype = parms->type;
179 aparms.index = &id;
180 aparms.base_index = &base_id;
181 rc = tf_rm_allocate(&aparms);
182 if (rc) {
183 TFP_DRV_LOG(ERR,
184 "%s: Failed allocate, type:%d\n",
185 tf_dir_2_str(parms->dir),
186 parms->type);
187 return rc;
188 }
189
190 if (shadow_init) {
191 iparms.tf_shadow_ident_db = ident_shadow_db[parms->dir];
192 iparms.type = parms->type;
193 iparms.id = base_id;
194
195 rc = tf_shadow_ident_insert(&iparms);
196 if (rc) {
197 TFP_DRV_LOG(ERR,
198 "%s: Failed insert shadow DB, type:%d\n",
199 tf_dir_2_str(parms->dir),
200 parms->type);
201 return rc;
202 }
203 }
204
205 *parms->id = id;
206
207 return 0;
208 }
209
210 int
tf_ident_free(struct tf * tfp __rte_unused,struct tf_ident_free_parms * parms)211 tf_ident_free(struct tf *tfp __rte_unused,
212 struct tf_ident_free_parms *parms)
213 {
214 int rc;
215 struct tf_rm_is_allocated_parms aparms = { 0 };
216 struct tf_rm_free_parms fparms = { 0 };
217 struct tf_shadow_ident_remove_parms rparms = { 0 };
218 int allocated = 0;
219 uint32_t base_id;
220 struct ident_rm_db *ident_db;
221 void *ident_db_ptr = NULL;
222
223 TF_CHECK_PARMS2(tfp, parms);
224
225 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_IDENTIFIER, &ident_db_ptr);
226 if (rc) {
227 TFP_DRV_LOG(ERR,
228 "Failed to get ident_db from session, rc:%s\n",
229 strerror(-rc));
230 return rc;
231 }
232 ident_db = (struct ident_rm_db *)ident_db_ptr;
233
234 /* Check if element is in use */
235 aparms.rm_db = ident_db->ident_db[parms->dir];
236 aparms.subtype = parms->type;
237 aparms.index = parms->id;
238 aparms.base_index = &base_id;
239 aparms.allocated = &allocated;
240 rc = tf_rm_is_allocated(&aparms);
241 if (rc)
242 return rc;
243
244 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
245 TFP_DRV_LOG(ERR,
246 "%s: Entry already free, type:%d, index:%d\n",
247 tf_dir_2_str(parms->dir),
248 parms->type,
249 parms->id);
250 return -EINVAL;
251 }
252
253 if (shadow_init) {
254 rparms.tf_shadow_ident_db = ident_shadow_db[parms->dir];
255 rparms.type = parms->type;
256 rparms.id = base_id;
257 rparms.ref_cnt = parms->ref_cnt;
258
259 rc = tf_shadow_ident_remove(&rparms);
260 if (rc) {
261 TFP_DRV_LOG(ERR,
262 "%s: ref_cnt was 0 in shadow DB,"
263 " type:%d, index:%d\n",
264 tf_dir_2_str(parms->dir),
265 parms->type,
266 parms->id);
267 return rc;
268 }
269
270 if (*rparms.ref_cnt > 0)
271 return 0;
272 }
273
274 /* Free requested element */
275 fparms.rm_db = ident_db->ident_db[parms->dir];
276 fparms.subtype = parms->type;
277 fparms.index = parms->id;
278 rc = tf_rm_free(&fparms);
279 if (rc) {
280 TFP_DRV_LOG(ERR,
281 "%s: Free failed, type:%d, index:%d\n",
282 tf_dir_2_str(parms->dir),
283 parms->type,
284 parms->id);
285 return rc;
286 }
287
288 return 0;
289 }
290
291 int
tf_ident_search(struct tf * tfp __rte_unused,struct tf_ident_search_parms * parms)292 tf_ident_search(struct tf *tfp __rte_unused,
293 struct tf_ident_search_parms *parms)
294 {
295 int rc;
296 struct tf_rm_is_allocated_parms aparms = { 0 };
297 struct tf_shadow_ident_search_parms sparms = { 0 };
298 int allocated = 0;
299 uint32_t base_id;
300 struct ident_rm_db *ident_db;
301 void *ident_db_ptr = NULL;
302
303 TF_CHECK_PARMS2(tfp, parms);
304
305 if (!shadow_init) {
306 TFP_DRV_LOG(ERR,
307 "%s: Identifier Shadow copy is not enabled\n",
308 tf_dir_2_str(parms->dir));
309 return -EINVAL;
310 }
311
312 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_IDENTIFIER, &ident_db_ptr);
313 if (rc) {
314 TFP_DRV_LOG(ERR,
315 "Failed to get ident_db from session, rc:%s\n",
316 strerror(-rc));
317 return rc;
318 }
319 ident_db = (struct ident_rm_db *)ident_db_ptr;
320
321 /* Check if element is in use */
322 aparms.rm_db = ident_db->ident_db[parms->dir];
323 aparms.subtype = parms->type;
324 aparms.index = parms->search_id;
325 aparms.base_index = &base_id;
326 aparms.allocated = &allocated;
327 rc = tf_rm_is_allocated(&aparms);
328 if (rc)
329 return rc;
330
331 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
332 TFP_DRV_LOG(ERR,
333 "%s: Entry not allocated, type:%d, index:%d\n",
334 tf_dir_2_str(parms->dir),
335 parms->type,
336 parms->search_id);
337 return -EINVAL;
338 }
339
340 sparms.tf_shadow_ident_db = ident_shadow_db[parms->dir];
341 sparms.type = parms->type;
342 sparms.search_id = base_id;
343 sparms.hit = parms->hit;
344 sparms.ref_cnt = parms->ref_cnt;
345
346 rc = tf_shadow_ident_search(&sparms);
347 if (rc) {
348 TFP_DRV_LOG(ERR,
349 "%s: Failed search shadow DB, type:%d\n",
350 tf_dir_2_str(parms->dir),
351 parms->type);
352 return rc;
353 }
354
355 return 0;
356 }
357
358 int
tf_ident_get_resc_info(struct tf * tfp,struct tf_identifier_resource_info * ident)359 tf_ident_get_resc_info(struct tf *tfp,
360 struct tf_identifier_resource_info *ident)
361 {
362 int rc;
363 int d;
364 struct tf_resource_info *dinfo;
365 struct tf_rm_get_alloc_info_parms ainfo;
366 void *ident_db_ptr = NULL;
367 struct ident_rm_db *ident_db;
368
369 TF_CHECK_PARMS2(tfp, ident);
370
371 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_IDENTIFIER, &ident_db_ptr);
372 if (rc == -ENOMEM)
373 return 0; /* db doesn't exist */
374 else if (rc)
375 return rc; /* error getting db */
376
377 ident_db = (struct ident_rm_db *)ident_db_ptr;
378
379 /* check if reserved resource for WC is multiple of num_slices */
380 for (d = 0; d < TF_DIR_MAX; d++) {
381 ainfo.rm_db = ident_db->ident_db[d];
382
383 if (!ainfo.rm_db)
384 continue;
385
386 dinfo = ident[d].info;
387
388 ainfo.info = (struct tf_rm_alloc_info *)dinfo;
389 ainfo.subtype = 0;
390 rc = tf_rm_get_all_info(&ainfo, TF_IDENT_TYPE_MAX);
391 if (rc)
392 return rc;
393 }
394
395 return 0;
396 }
397