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