net/bnxt: support EM and TCAM lookup with table scope
[dpdk.git] / drivers / net / bnxt / tf_core / tf_em_internal.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2020 Broadcom
3  * All rights reserved.
4  */
5
6 #include <string.h>
7 #include <rte_common.h>
8 #include <rte_errno.h>
9 #include <rte_log.h>
10
11 #include "tf_core.h"
12 #include "tf_util.h"
13 #include "tf_common.h"
14 #include "tf_em.h"
15 #include "tf_msg.h"
16 #include "tfp.h"
17 #include "tf_ext_flow_handle.h"
18
19 #include "bnxt.h"
20
21 /**
22  * EM DBs.
23  */
24 static void *em_db[TF_DIR_MAX];
25
26 /**
27  * Init flag, set on bind and cleared on unbind
28  */
29 static uint8_t init;
30
31 /**
32  * Create EM Tbl pool of memory indexes.
33  *
34  * [in] session
35  *   Pointer to session
36  * [in] dir
37  *   direction
38  * [in] num_entries
39  *   number of entries to write
40  *
41  * Return:
42  *  0       - Success, entry allocated - no search support
43  *  -ENOMEM -EINVAL -EOPNOTSUPP
44  *          - Failure, entry not allocated, out of resources
45  */
46 static int
47 tf_create_em_pool(struct tf_session *session,
48                   enum tf_dir dir,
49                   uint32_t num_entries)
50 {
51         struct tfp_calloc_parms parms;
52         uint32_t i, j;
53         int rc = 0;
54         struct stack *pool = &session->em_pool[dir];
55
56         parms.nitems = num_entries;
57         parms.size = sizeof(uint32_t);
58         parms.alignment = 0;
59
60         rc = tfp_calloc(&parms);
61
62         if (rc) {
63                 TFP_DRV_LOG(ERR, "EM pool allocation failure %s\n",
64                             strerror(-rc));
65                 return rc;
66         }
67
68         /* Create empty stack
69          */
70         rc = stack_init(num_entries, (uint32_t *)parms.mem_va, pool);
71
72         if (rc) {
73                 TFP_DRV_LOG(ERR, "EM pool stack init failure %s\n",
74                             strerror(-rc));
75                 goto cleanup;
76         }
77
78         /* Fill pool with indexes
79          */
80         j = num_entries - 1;
81
82         for (i = 0; i < num_entries; i++) {
83                 rc = stack_push(pool, j);
84                 if (rc) {
85                         TFP_DRV_LOG(ERR, "EM pool stack push failure %s\n",
86                                     strerror(-rc));
87                         goto cleanup;
88                 }
89                 j--;
90         }
91
92         if (!stack_is_full(pool)) {
93                 rc = -EINVAL;
94                 TFP_DRV_LOG(ERR, "EM pool stack failure %s\n",
95                             strerror(-rc));
96                 goto cleanup;
97         }
98
99         return 0;
100 cleanup:
101         tfp_free((void *)parms.mem_va);
102         return rc;
103 }
104
105 /**
106  * Create EM Tbl pool of memory indexes.
107  *
108  * [in] session
109  *   Pointer to session
110  * [in] dir
111  *   direction
112  *
113  * Return:
114  */
115 static void
116 tf_free_em_pool(struct tf_session *session,
117                 enum tf_dir dir)
118 {
119         struct stack *pool = &session->em_pool[dir];
120         uint32_t *ptr;
121
122         ptr = stack_items(pool);
123
124         if (ptr != NULL)
125                 tfp_free(ptr);
126 }
127
128 /**
129  * Insert EM internal entry API
130  *
131  *  returns:
132  *     0 - Success
133  */
134 int
135 tf_em_insert_int_entry(struct tf *tfp,
136                        struct tf_insert_em_entry_parms *parms)
137 {
138         int rc;
139         uint32_t gfid;
140         uint16_t rptr_index = 0;
141         uint8_t rptr_entry = 0;
142         uint8_t num_of_entries = 0;
143         struct tf_session *session =
144                 (struct tf_session *)(tfp->session->core_data);
145         struct stack *pool = &session->em_pool[parms->dir];
146         uint32_t index;
147
148         rc = stack_pop(pool, &index);
149
150         if (rc) {
151                 PMD_DRV_LOG
152                   (ERR,
153                    "dir:%d, EM entry index allocation failed\n",
154                    parms->dir);
155                 return rc;
156         }
157
158         rptr_index = index * TF_SESSION_EM_ENTRY_SIZE;
159         rc = tf_msg_insert_em_internal_entry(tfp,
160                                              parms,
161                                              &rptr_index,
162                                              &rptr_entry,
163                                              &num_of_entries);
164         if (rc)
165                 return -1;
166
167         PMD_DRV_LOG
168                   (ERR,
169                    "Internal entry @ Index:%d rptr_index:0x%x rptr_entry:0x%x num_of_entries:%d\n",
170                    index * TF_SESSION_EM_ENTRY_SIZE,
171                    rptr_index,
172                    rptr_entry,
173                    num_of_entries);
174
175         TF_SET_GFID(gfid,
176                     ((rptr_index << TF_EM_INTERNAL_INDEX_SHIFT) |
177                      rptr_entry),
178                     0); /* N/A for internal table */
179
180         TF_SET_FLOW_ID(parms->flow_id,
181                        gfid,
182                        TF_GFID_TABLE_INTERNAL,
183                        parms->dir);
184
185         TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
186                                      (uint32_t)num_of_entries,
187                                      0,
188                                      0,
189                                      rptr_index,
190                                      rptr_entry,
191                                      0);
192         return 0;
193 }
194
195
196 /** Delete EM internal entry API
197  *
198  * returns:
199  * 0
200  * -EINVAL
201  */
202 int
203 tf_em_delete_int_entry(struct tf *tfp,
204                        struct tf_delete_em_entry_parms *parms)
205 {
206         int rc = 0;
207         struct tf_session *session =
208                 (struct tf_session *)(tfp->session->core_data);
209         struct stack *pool = &session->em_pool[parms->dir];
210
211         rc = tf_msg_delete_em_entry(tfp, parms);
212
213         /* Return resource to pool */
214         if (rc == 0)
215                 stack_push(pool, parms->index / TF_SESSION_EM_ENTRY_SIZE);
216
217         return rc;
218 }
219
220 int
221 tf_em_int_bind(struct tf *tfp,
222                struct tf_em_cfg_parms *parms)
223 {
224         int rc;
225         int i;
226         struct tf_rm_create_db_parms db_cfg = { 0 };
227         struct tf_session *session;
228
229         TF_CHECK_PARMS2(tfp, parms);
230
231         if (init) {
232                 TFP_DRV_LOG(ERR,
233                             "Identifier already initialized\n");
234                 return -EINVAL;
235         }
236
237         session = (struct tf_session *)tfp->session->core_data;
238
239         for (i = 0; i < TF_DIR_MAX; i++) {
240                 tf_create_em_pool(session,
241                                   i,
242                                   TF_SESSION_EM_POOL_SIZE);
243         }
244
245         /*
246          * I'm not sure that this code is needed.
247          * leaving for now until resolved
248          */
249         if (parms->num_elements) {
250                 db_cfg.type = TF_DEVICE_MODULE_TYPE_EM;
251                 db_cfg.num_elements = parms->num_elements;
252                 db_cfg.cfg = parms->cfg;
253
254                 for (i = 0; i < TF_DIR_MAX; i++) {
255                         db_cfg.dir = i;
256                         db_cfg.alloc_cnt = parms->resources->em_cnt[i].cnt;
257                         db_cfg.rm_db = &em_db[i];
258                         rc = tf_rm_create_db(tfp, &db_cfg);
259                         if (rc) {
260                                 TFP_DRV_LOG(ERR,
261                                             "%s: EM DB creation failed\n",
262                                             tf_dir_2_str(i));
263
264                                 return rc;
265                         }
266                 }
267         }
268
269         init = 1;
270         return 0;
271 }
272
273 int
274 tf_em_int_unbind(struct tf *tfp)
275 {
276         int rc;
277         int i;
278         struct tf_rm_free_db_parms fparms = { 0 };
279         struct tf_session *session;
280
281         TF_CHECK_PARMS1(tfp);
282
283         /* Bail if nothing has been initialized done silent as to
284          * allow for creation cleanup.
285          */
286         if (!init) {
287                 TFP_DRV_LOG(ERR,
288                             "No EM DBs created\n");
289                 return -EINVAL;
290         }
291
292         session = (struct tf_session *)tfp->session->core_data;
293
294         for (i = 0; i < TF_DIR_MAX; i++)
295                 tf_free_em_pool(session, i);
296
297         for (i = 0; i < TF_DIR_MAX; i++) {
298                 fparms.dir = i;
299                 fparms.rm_db = em_db[i];
300                 if (em_db[i] != NULL) {
301                         rc = tf_rm_free_db(tfp, &fparms);
302                         if (rc)
303                                 return rc;
304                 }
305
306                 em_db[i] = NULL;
307         }
308
309         init = 0;
310
311         return 0;
312 }