net/bnxt: refactor host session failure cleanup
[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  * 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
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
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
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
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
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
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 }