net/bnxt: align CFA resources with RM
[dpdk.git] / drivers / net / bnxt / tf_core / tf_tcam.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
9 #include "tf_tcam.h"
10 #include "tf_common.h"
11 #include "tf_util.h"
12 #include "tf_rm.h"
13 #include "tf_device.h"
14 #include "tfp.h"
15 #include "tf_session.h"
16 #include "tf_msg.h"
17
18 struct tf;
19
20 /**
21  * TCAM DBs.
22  */
23 static void *tcam_db[TF_DIR_MAX];
24
25 /**
26  * TCAM Shadow DBs
27  */
28 /* static void *shadow_tcam_db[TF_DIR_MAX]; */
29
30 /**
31  * Init flag, set on bind and cleared on unbind
32  */
33 static uint8_t init;
34
35 /**
36  * Shadow init flag, set on bind and cleared on unbind
37  */
38 /* static uint8_t shadow_init; */
39
40 int
41 tf_tcam_bind(struct tf *tfp,
42              struct tf_tcam_cfg_parms *parms)
43 {
44         int rc;
45         int i;
46         struct tf_tcam_resources *tcam_cnt;
47         struct tf_rm_create_db_parms db_cfg = { 0 };
48
49         TF_CHECK_PARMS2(tfp, parms);
50
51         if (init) {
52                 TFP_DRV_LOG(ERR,
53                             "TCAM DB already initialized\n");
54                 return -EINVAL;
55         }
56
57         tcam_cnt = parms->resources->tcam_cnt;
58         if ((tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % 2) ||
59             (tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % 2)) {
60                 TFP_DRV_LOG(ERR,
61                             "Number of WC TCAM entries cannot be odd num\n");
62                 return -EINVAL;
63         }
64
65         db_cfg.type = TF_DEVICE_MODULE_TYPE_TCAM;
66         db_cfg.num_elements = parms->num_elements;
67         db_cfg.cfg = parms->cfg;
68
69         for (i = 0; i < TF_DIR_MAX; i++) {
70                 db_cfg.dir = i;
71                 db_cfg.alloc_cnt = parms->resources->tcam_cnt[i].cnt;
72                 db_cfg.rm_db = &tcam_db[i];
73                 rc = tf_rm_create_db(tfp, &db_cfg);
74                 if (rc) {
75                         TFP_DRV_LOG(ERR,
76                                     "%s: TCAM DB creation failed\n",
77                                     tf_dir_2_str(i));
78                         return rc;
79                 }
80         }
81
82         init = 1;
83
84         TFP_DRV_LOG(INFO,
85                     "TCAM - initialized\n");
86
87         return 0;
88 }
89
90 int
91 tf_tcam_unbind(struct tf *tfp)
92 {
93         int rc;
94         int i;
95         struct tf_rm_free_db_parms fparms = { 0 };
96
97         TF_CHECK_PARMS1(tfp);
98
99         /* Bail if nothing has been initialized */
100         if (!init) {
101                 TFP_DRV_LOG(INFO,
102                             "No TCAM DBs created\n");
103                 return 0;
104         }
105
106         for (i = 0; i < TF_DIR_MAX; i++) {
107                 fparms.dir = i;
108                 fparms.rm_db = tcam_db[i];
109                 rc = tf_rm_free_db(tfp, &fparms);
110                 if (rc)
111                         return rc;
112
113                 tcam_db[i] = NULL;
114         }
115
116         init = 0;
117
118         return 0;
119 }
120
121 int
122 tf_tcam_alloc(struct tf *tfp,
123               struct tf_tcam_alloc_parms *parms)
124 {
125         int rc;
126         struct tf_session *tfs;
127         struct tf_dev_info *dev;
128         struct tf_rm_allocate_parms aparms = { 0 };
129         uint16_t num_slice_per_row = 1;
130
131         TF_CHECK_PARMS2(tfp, parms);
132
133         if (!init) {
134                 TFP_DRV_LOG(ERR,
135                             "%s: No TCAM DBs created\n",
136                             tf_dir_2_str(parms->dir));
137                 return -EINVAL;
138         }
139
140         /* Retrieve the session information */
141         rc = tf_session_get_session(tfp, &tfs);
142         if (rc)
143                 return rc;
144
145         /* Retrieve the device information */
146         rc = tf_session_get_device(tfs, &dev);
147         if (rc)
148                 return rc;
149
150         if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
151                 rc = -EOPNOTSUPP;
152                 TFP_DRV_LOG(ERR,
153                             "%s: Operation not supported, rc:%s\n",
154                             tf_dir_2_str(parms->dir),
155                             strerror(-rc));
156                 return rc;
157         }
158
159         /* Need to retrieve row size etc */
160         rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
161                                                   parms->type,
162                                                   parms->key_size,
163                                                   &num_slice_per_row);
164         if (rc)
165                 return rc;
166
167         /* Allocate requested element */
168         aparms.rm_db = tcam_db[parms->dir];
169         aparms.db_index = parms->type;
170         aparms.priority = parms->priority;
171         aparms.index = (uint32_t *)&parms->idx;
172         rc = tf_rm_allocate(&aparms);
173         if (rc) {
174                 TFP_DRV_LOG(ERR,
175                             "%s: Failed tcam, type:%d\n",
176                             tf_dir_2_str(parms->dir),
177                             parms->type);
178                 return rc;
179         }
180
181         if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM &&
182             (parms->idx % 2) != 0) {
183                 rc = tf_rm_allocate(&aparms);
184                 if (rc) {
185                         TFP_DRV_LOG(ERR,
186                                     "%s: Failed tcam, type:%d\n",
187                                     tf_dir_2_str(parms->dir),
188                                     parms->type);
189                         return rc;
190                 }
191         }
192
193         parms->idx *= num_slice_per_row;
194
195         return 0;
196 }
197
198 int
199 tf_tcam_free(struct tf *tfp,
200              struct tf_tcam_free_parms *parms)
201 {
202         int rc;
203         struct tf_session *tfs;
204         struct tf_dev_info *dev;
205         struct tf_rm_is_allocated_parms aparms = { 0 };
206         struct tf_rm_free_parms fparms = { 0 };
207         struct tf_rm_get_hcapi_parms hparms = { 0 };
208         uint16_t num_slice_per_row = 1;
209         int allocated = 0;
210
211         TF_CHECK_PARMS2(tfp, parms);
212
213         if (!init) {
214                 TFP_DRV_LOG(ERR,
215                             "%s: No TCAM DBs created\n",
216                             tf_dir_2_str(parms->dir));
217                 return -EINVAL;
218         }
219
220         /* Retrieve the session information */
221         rc = tf_session_get_session(tfp, &tfs);
222         if (rc)
223                 return rc;
224
225         /* Retrieve the device information */
226         rc = tf_session_get_device(tfs, &dev);
227         if (rc)
228                 return rc;
229
230         if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
231                 rc = -EOPNOTSUPP;
232                 TFP_DRV_LOG(ERR,
233                             "%s: Operation not supported, rc:%s\n",
234                             tf_dir_2_str(parms->dir),
235                             strerror(-rc));
236                 return rc;
237         }
238
239         /* Need to retrieve row size etc */
240         rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
241                                                   parms->type,
242                                                   0,
243                                                   &num_slice_per_row);
244         if (rc)
245                 return rc;
246
247         /* Check if element is in use */
248         aparms.rm_db = tcam_db[parms->dir];
249         aparms.db_index = parms->type;
250         aparms.index = parms->idx / num_slice_per_row;
251         aparms.allocated = &allocated;
252         rc = tf_rm_is_allocated(&aparms);
253         if (rc)
254                 return rc;
255
256         if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
257                 TFP_DRV_LOG(ERR,
258                             "%s: Entry already free, type:%d, index:%d\n",
259                             tf_dir_2_str(parms->dir),
260                             parms->type,
261                             parms->idx);
262                 return -EINVAL;
263         }
264
265         /* Free requested element */
266         fparms.rm_db = tcam_db[parms->dir];
267         fparms.db_index = parms->type;
268         fparms.index = parms->idx / num_slice_per_row;
269         rc = tf_rm_free(&fparms);
270         if (rc) {
271                 TFP_DRV_LOG(ERR,
272                             "%s: Free failed, type:%d, index:%d\n",
273                             tf_dir_2_str(parms->dir),
274                             parms->type,
275                             parms->idx);
276                 return rc;
277         }
278
279         if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM) {
280                 int i;
281
282                 for (i = -1; i < 3; i += 3) {
283                         aparms.index += i;
284                         rc = tf_rm_is_allocated(&aparms);
285                         if (rc)
286                                 return rc;
287
288                         if (allocated == TF_RM_ALLOCATED_ENTRY_IN_USE) {
289                                 /* Free requested element */
290                                 fparms.index = aparms.index;
291                                 rc = tf_rm_free(&fparms);
292                                 if (rc) {
293                                         TFP_DRV_LOG(ERR,
294                                                     "%s: Free failed, type:%d, index:%d\n",
295                                                     tf_dir_2_str(parms->dir),
296                                                     parms->type,
297                                                     fparms.index);
298                                         return rc;
299                                 }
300                         }
301                 }
302         }
303
304         /* Convert TF type to HCAPI RM type */
305         hparms.rm_db = tcam_db[parms->dir];
306         hparms.db_index = parms->type;
307         hparms.hcapi_type = &parms->hcapi_type;
308
309         rc = tf_rm_get_hcapi_type(&hparms);
310         if (rc)
311                 return rc;
312
313         rc = tf_msg_tcam_entry_free(tfp, parms);
314         if (rc) {
315                 /* Log error */
316                 TFP_DRV_LOG(ERR,
317                             "%s: %s: Entry %d free failed, rc:%s\n",
318                             tf_dir_2_str(parms->dir),
319                             tf_tcam_tbl_2_str(parms->type),
320                             parms->idx,
321                             strerror(-rc));
322         }
323
324         return 0;
325 }
326
327 int
328 tf_tcam_alloc_search(struct tf *tfp __rte_unused,
329                      struct tf_tcam_alloc_search_parms *parms __rte_unused)
330 {
331         return 0;
332 }
333
334 int
335 tf_tcam_set(struct tf *tfp __rte_unused,
336             struct tf_tcam_set_parms *parms __rte_unused)
337 {
338         int rc;
339         struct tf_session *tfs;
340         struct tf_dev_info *dev;
341         struct tf_rm_is_allocated_parms aparms = { 0 };
342         struct tf_rm_get_hcapi_parms hparms = { 0 };
343         uint16_t num_slice_per_row = 1;
344         int allocated = 0;
345
346         TF_CHECK_PARMS2(tfp, parms);
347
348         if (!init) {
349                 TFP_DRV_LOG(ERR,
350                             "%s: No TCAM DBs created\n",
351                             tf_dir_2_str(parms->dir));
352                 return -EINVAL;
353         }
354
355         /* Retrieve the session information */
356         rc = tf_session_get_session(tfp, &tfs);
357         if (rc)
358                 return rc;
359
360         /* Retrieve the device information */
361         rc = tf_session_get_device(tfs, &dev);
362         if (rc)
363                 return rc;
364
365         if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
366                 rc = -EOPNOTSUPP;
367                 TFP_DRV_LOG(ERR,
368                             "%s: Operation not supported, rc:%s\n",
369                             tf_dir_2_str(parms->dir),
370                             strerror(-rc));
371                 return rc;
372         }
373
374         /* Need to retrieve row size etc */
375         rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
376                                                   parms->type,
377                                                   parms->key_size,
378                                                   &num_slice_per_row);
379         if (rc)
380                 return rc;
381
382         /* Check if element is in use */
383         aparms.rm_db = tcam_db[parms->dir];
384         aparms.db_index = parms->type;
385         aparms.index = parms->idx / num_slice_per_row;
386         aparms.allocated = &allocated;
387         rc = tf_rm_is_allocated(&aparms);
388         if (rc)
389                 return rc;
390
391         if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
392                 TFP_DRV_LOG(ERR,
393                             "%s: Entry is not allocated, type:%d, index:%d\n",
394                             tf_dir_2_str(parms->dir),
395                             parms->type,
396                             parms->idx);
397                 return -EINVAL;
398         }
399
400         /* Convert TF type to HCAPI RM type */
401         hparms.rm_db = tcam_db[parms->dir];
402         hparms.db_index = parms->type;
403         hparms.hcapi_type = &parms->hcapi_type;
404
405         rc = tf_rm_get_hcapi_type(&hparms);
406         if (rc)
407                 return rc;
408
409         rc = tf_msg_tcam_entry_set(tfp, parms);
410         if (rc) {
411                 /* Log error */
412                 TFP_DRV_LOG(ERR,
413                             "%s: %s: Entry %d set failed, rc:%s",
414                             tf_dir_2_str(parms->dir),
415                             tf_tcam_tbl_2_str(parms->type),
416                             parms->idx,
417                             strerror(-rc));
418         }
419
420         return 0;
421 }
422
423 int
424 tf_tcam_get(struct tf *tfp __rte_unused,
425             struct tf_tcam_get_parms *parms __rte_unused)
426 {
427         return 0;
428 }