net/bnxt: fix out of bound access in bit handling
[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 #define TF_EM_DB_EM_REC 0
27
28 /**
29  * Init flag, set on bind and cleared on unbind
30  */
31 static uint8_t init;
32
33
34 /**
35  * EM Pool
36  */
37 static struct stack em_pool[TF_DIR_MAX];
38
39 /**
40  * Create EM Tbl pool of memory indexes.
41  *
42  * [in] dir
43  *   direction
44  * [in] num_entries
45  *   number of entries to write
46  * [in] start
47  *   starting offset
48  *
49  * Return:
50  *  0       - Success, entry allocated - no search support
51  *  -ENOMEM -EINVAL -EOPNOTSUPP
52  *          - Failure, entry not allocated, out of resources
53  */
54 static int
55 tf_create_em_pool(enum tf_dir dir,
56                   uint32_t num_entries,
57                   uint32_t start)
58 {
59         struct tfp_calloc_parms parms;
60         uint32_t i, j;
61         int rc = 0;
62         struct stack *pool = &em_pool[dir];
63
64         /* Assumes that num_entries has been checked before we get here */
65         parms.nitems = num_entries / TF_SESSION_EM_ENTRY_SIZE;
66         parms.size = sizeof(uint32_t);
67         parms.alignment = 0;
68
69         rc = tfp_calloc(&parms);
70
71         if (rc) {
72                 TFP_DRV_LOG(ERR,
73                             "%s, EM pool allocation failure %s\n",
74                             tf_dir_2_str(dir),
75                             strerror(-rc));
76                 return rc;
77         }
78
79         /* Create empty stack
80          */
81         rc = stack_init(num_entries / TF_SESSION_EM_ENTRY_SIZE,
82                         (uint32_t *)parms.mem_va,
83                         pool);
84
85         if (rc) {
86                 TFP_DRV_LOG(ERR,
87                             "%s, EM pool stack init failure %s\n",
88                             tf_dir_2_str(dir),
89                             strerror(-rc));
90                 goto cleanup;
91         }
92
93         /* Fill pool with indexes
94          */
95         j = start + num_entries - TF_SESSION_EM_ENTRY_SIZE;
96
97         for (i = 0; i < (num_entries / TF_SESSION_EM_ENTRY_SIZE); i++) {
98                 rc = stack_push(pool, j);
99                 if (rc) {
100                         TFP_DRV_LOG(ERR,
101                                     "%s, EM pool stack push failure %s\n",
102                                     tf_dir_2_str(dir),
103                                     strerror(-rc));
104                         goto cleanup;
105                 }
106
107                 j -= TF_SESSION_EM_ENTRY_SIZE;
108         }
109
110         if (!stack_is_full(pool)) {
111                 rc = -EINVAL;
112                 TFP_DRV_LOG(ERR,
113                             "%s, EM pool stack failure %s\n",
114                             tf_dir_2_str(dir),
115                             strerror(-rc));
116                 goto cleanup;
117         }
118
119         return 0;
120 cleanup:
121         tfp_free((void *)parms.mem_va);
122         return rc;
123 }
124
125 /**
126  * Create EM Tbl pool of memory indexes.
127  *
128  * [in] dir
129  *   direction
130  *
131  * Return:
132  */
133 static void
134 tf_free_em_pool(enum tf_dir dir)
135 {
136         struct stack *pool = &em_pool[dir];
137         uint32_t *ptr;
138
139         ptr = stack_items(pool);
140
141         if (ptr != NULL)
142                 tfp_free(ptr);
143 }
144
145 /**
146  * Insert EM internal entry API
147  *
148  *  returns:
149  *     0 - Success
150  */
151 int
152 tf_em_insert_int_entry(struct tf *tfp,
153                        struct tf_insert_em_entry_parms *parms)
154 {
155         int rc;
156         uint32_t gfid;
157         uint16_t rptr_index = 0;
158         uint8_t rptr_entry = 0;
159         uint8_t num_of_entries = 0;
160         struct stack *pool = &em_pool[parms->dir];
161         uint32_t index;
162
163         rc = stack_pop(pool, &index);
164
165         if (rc) {
166                 PMD_DRV_LOG(ERR,
167                             "%s, EM entry index allocation failed\n",
168                             tf_dir_2_str(parms->dir));
169                 return rc;
170         }
171
172         rptr_index = index;
173         rc = tf_msg_insert_em_internal_entry(tfp,
174                                              parms,
175                                              &rptr_index,
176                                              &rptr_entry,
177                                              &num_of_entries);
178         if (rc) {
179                 /* Free the allocated index before returning */
180                 stack_push(pool, index);
181                 return -1;
182         }
183
184         PMD_DRV_LOG
185                   (DEBUG,
186                    "%s, Internal entry @ Index:%d rptr_index:0x%x rptr_entry:0x%x num_of_entries:%d\n",
187                    tf_dir_2_str(parms->dir),
188                    index,
189                    rptr_index,
190                    rptr_entry,
191                    num_of_entries);
192
193         TF_SET_GFID(gfid,
194                     ((rptr_index << TF_EM_INTERNAL_INDEX_SHIFT) |
195                      rptr_entry),
196                     0); /* N/A for internal table */
197
198         TF_SET_FLOW_ID(parms->flow_id,
199                        gfid,
200                        TF_GFID_TABLE_INTERNAL,
201                        parms->dir);
202
203         TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
204                                      (uint32_t)num_of_entries,
205                                      0,
206                                      0,
207                                      rptr_index,
208                                      rptr_entry,
209                                      0);
210         return 0;
211 }
212
213
214 /** Delete EM internal entry API
215  *
216  * returns:
217  * 0
218  * -EINVAL
219  */
220 int
221 tf_em_delete_int_entry(struct tf *tfp,
222                        struct tf_delete_em_entry_parms *parms)
223 {
224         int rc = 0;
225         struct stack *pool = &em_pool[parms->dir];
226
227         rc = tf_msg_delete_em_entry(tfp, parms);
228
229         /* Return resource to pool */
230         if (rc == 0)
231                 stack_push(pool, parms->index);
232
233         return rc;
234 }
235
236 int
237 tf_em_int_bind(struct tf *tfp,
238                struct tf_em_cfg_parms *parms)
239 {
240         int rc;
241         int i;
242         struct tf_rm_create_db_parms db_cfg = { 0 };
243         uint8_t db_exists = 0;
244         struct tf_rm_get_alloc_info_parms iparms;
245         struct tf_rm_alloc_info info;
246
247         TF_CHECK_PARMS2(tfp, parms);
248
249         if (init) {
250                 TFP_DRV_LOG(ERR,
251                             "EM Int DB already initialized\n");
252                 return -EINVAL;
253         }
254
255         db_cfg.type = TF_DEVICE_MODULE_TYPE_EM;
256         db_cfg.num_elements = parms->num_elements;
257         db_cfg.cfg = parms->cfg;
258
259         for (i = 0; i < TF_DIR_MAX; i++) {
260                 db_cfg.dir = i;
261                 db_cfg.alloc_cnt = parms->resources->em_cnt[i].cnt;
262
263                 /* Check if we got any request to support EEM, if so
264                  * we build an EM Int DB holding Table Scopes.
265                  */
266                 if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_EM_RECORD] == 0)
267                         continue;
268
269                 if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_EM_RECORD] %
270                     TF_SESSION_EM_ENTRY_SIZE != 0) {
271                         rc = -ENOMEM;
272                         TFP_DRV_LOG(ERR,
273                                     "%s, EM Allocation must be in blocks of %d, failure %s\n",
274                                     tf_dir_2_str(i),
275                                     TF_SESSION_EM_ENTRY_SIZE,
276                                     strerror(-rc));
277
278                         return rc;
279                 }
280
281                 db_cfg.rm_db = &em_db[i];
282                 rc = tf_rm_create_db(tfp, &db_cfg);
283                 if (rc) {
284                         TFP_DRV_LOG(ERR,
285                                     "%s: EM Int DB creation failed\n",
286                                     tf_dir_2_str(i));
287
288                         return rc;
289                 }
290                 db_exists = 1;
291         }
292
293         if (db_exists)
294                 init = 1;
295
296         for (i = 0; i < TF_DIR_MAX; i++) {
297                 iparms.rm_db = em_db[i];
298                 iparms.db_index = TF_EM_DB_EM_REC;
299                 iparms.info = &info;
300
301                 rc = tf_rm_get_info(&iparms);
302                 if (rc) {
303                         TFP_DRV_LOG(ERR,
304                                     "%s: EM DB get info failed\n",
305                                     tf_dir_2_str(i));
306                         return rc;
307                 }
308
309                 rc = tf_create_em_pool(i,
310                                        iparms.info->entry.stride,
311                                        iparms.info->entry.start);
312                 /* Logging handled in tf_create_em_pool */
313                 if (rc)
314                         return rc;
315         }
316
317
318         return 0;
319 }
320
321 int
322 tf_em_int_unbind(struct tf *tfp)
323 {
324         int rc;
325         int i;
326         struct tf_rm_free_db_parms fparms = { 0 };
327
328         TF_CHECK_PARMS1(tfp);
329
330         /* Bail if nothing has been initialized */
331         if (!init) {
332                 TFP_DRV_LOG(INFO,
333                             "No EM Int DBs created\n");
334                 return 0;
335         }
336
337         for (i = 0; i < TF_DIR_MAX; i++)
338                 tf_free_em_pool(i);
339
340         for (i = 0; i < TF_DIR_MAX; i++) {
341                 fparms.dir = i;
342                 fparms.rm_db = em_db[i];
343                 if (em_db[i] != NULL) {
344                         rc = tf_rm_free_db(tfp, &fparms);
345                         if (rc)
346                                 return rc;
347                 }
348
349                 em_db[i] = NULL;
350         }
351
352         init = 0;
353
354         return 0;
355 }