b1092cd9da052cab2d19f05b1bb242ec8da310b8
[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         printf("TCAM - initialized\n");
85
86         return 0;
87 }
88
89 int
90 tf_tcam_unbind(struct tf *tfp)
91 {
92         int rc;
93         int i;
94         struct tf_rm_free_db_parms fparms = { 0 };
95
96         TF_CHECK_PARMS1(tfp);
97
98         /* Bail if nothing has been initialized */
99         if (!init) {
100                 TFP_DRV_LOG(INFO,
101                             "No TCAM DBs created\n");
102                 return 0;
103         }
104
105         for (i = 0; i < TF_DIR_MAX; i++) {
106                 fparms.dir = i;
107                 fparms.rm_db = tcam_db[i];
108                 rc = tf_rm_free_db(tfp, &fparms);
109                 if (rc)
110                         return rc;
111
112                 tcam_db[i] = NULL;
113         }
114
115         init = 0;
116
117         return 0;
118 }
119
120 int
121 tf_tcam_alloc(struct tf *tfp,
122               struct tf_tcam_alloc_parms *parms)
123 {
124         int rc;
125         struct tf_session *tfs;
126         struct tf_dev_info *dev;
127         struct tf_rm_allocate_parms aparms = { 0 };
128         uint16_t num_slice_per_row = 1;
129
130         TF_CHECK_PARMS2(tfp, parms);
131
132         if (!init) {
133                 TFP_DRV_LOG(ERR,
134                             "%s: No TCAM DBs created\n",
135                             tf_dir_2_str(parms->dir));
136                 return -EINVAL;
137         }
138
139         /* Retrieve the session information */
140         rc = tf_session_get_session(tfp, &tfs);
141         if (rc)
142                 return rc;
143
144         /* Retrieve the device information */
145         rc = tf_session_get_device(tfs, &dev);
146         if (rc)
147                 return rc;
148
149         if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
150                 rc = -EOPNOTSUPP;
151                 TFP_DRV_LOG(ERR,
152                             "%s: Operation not supported, rc:%s\n",
153                             tf_dir_2_str(parms->dir),
154                             strerror(-rc));
155                 return rc;
156         }
157
158         /* Need to retrieve row size etc */
159         rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
160                                                   parms->type,
161                                                   parms->key_size,
162                                                   &num_slice_per_row);
163         if (rc)
164                 return rc;
165
166         /* Allocate requested element */
167         aparms.rm_db = tcam_db[parms->dir];
168         aparms.db_index = parms->type;
169         aparms.priority = parms->priority;
170         aparms.index = (uint32_t *)&parms->idx;
171         rc = tf_rm_allocate(&aparms);
172         if (rc) {
173                 TFP_DRV_LOG(ERR,
174                             "%s: Failed tcam, type:%d\n",
175                             tf_dir_2_str(parms->dir),
176                             parms->type);
177                 return rc;
178         }
179
180         if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM &&
181             (parms->idx % 2) != 0) {
182                 rc = tf_rm_allocate(&aparms);
183                 if (rc) {
184                         TFP_DRV_LOG(ERR,
185                                     "%s: Failed tcam, type:%d\n",
186                                     tf_dir_2_str(parms->dir),
187                                     parms->type);
188                         return rc;
189                 }
190         }
191
192         parms->idx *= num_slice_per_row;
193
194         return 0;
195 }
196
197 int
198 tf_tcam_free(struct tf *tfp,
199              struct tf_tcam_free_parms *parms)
200 {
201         int rc;
202         struct tf_session *tfs;
203         struct tf_dev_info *dev;
204         struct tf_rm_is_allocated_parms aparms = { 0 };
205         struct tf_rm_free_parms fparms = { 0 };
206         struct tf_rm_get_hcapi_parms hparms = { 0 };
207         uint16_t num_slice_per_row = 1;
208         int allocated = 0;
209
210         TF_CHECK_PARMS2(tfp, parms);
211
212         if (!init) {
213                 TFP_DRV_LOG(ERR,
214                             "%s: No TCAM DBs created\n",
215                             tf_dir_2_str(parms->dir));
216                 return -EINVAL;
217         }
218
219         /* Retrieve the session information */
220         rc = tf_session_get_session(tfp, &tfs);
221         if (rc)
222                 return rc;
223
224         /* Retrieve the device information */
225         rc = tf_session_get_device(tfs, &dev);
226         if (rc)
227                 return rc;
228
229         if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
230                 rc = -EOPNOTSUPP;
231                 TFP_DRV_LOG(ERR,
232                             "%s: Operation not supported, rc:%s\n",
233                             tf_dir_2_str(parms->dir),
234                             strerror(-rc));
235                 return rc;
236         }
237
238         /* Need to retrieve row size etc */
239         rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
240                                                   parms->type,
241                                                   0,
242                                                   &num_slice_per_row);
243         if (rc)
244                 return rc;
245
246         /* Check if element is in use */
247         aparms.rm_db = tcam_db[parms->dir];
248         aparms.db_index = parms->type;
249         aparms.index = parms->idx / num_slice_per_row;
250         aparms.allocated = &allocated;
251         rc = tf_rm_is_allocated(&aparms);
252         if (rc)
253                 return rc;
254
255         if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
256                 TFP_DRV_LOG(ERR,
257                             "%s: Entry already free, type:%d, index:%d\n",
258                             tf_dir_2_str(parms->dir),
259                             parms->type,
260                             parms->idx);
261                 return -EINVAL;
262         }
263
264         /* Free requested element */
265         fparms.rm_db = tcam_db[parms->dir];
266         fparms.db_index = parms->type;
267         fparms.index = parms->idx / num_slice_per_row;
268         rc = tf_rm_free(&fparms);
269         if (rc) {
270                 TFP_DRV_LOG(ERR,
271                             "%s: Free failed, type:%d, index:%d\n",
272                             tf_dir_2_str(parms->dir),
273                             parms->type,
274                             parms->idx);
275                 return rc;
276         }
277
278         /* Convert TF type to HCAPI RM type */
279         hparms.rm_db = tcam_db[parms->dir];
280         hparms.db_index = parms->type;
281         hparms.hcapi_type = &parms->hcapi_type;
282
283         rc = tf_rm_get_hcapi_type(&hparms);
284         if (rc)
285                 return rc;
286
287         rc = tf_msg_tcam_entry_free(tfp, parms);
288         if (rc) {
289                 /* Log error */
290                 TFP_DRV_LOG(ERR,
291                             "%s: %s: Entry %d free failed, rc:%s\n",
292                             tf_dir_2_str(parms->dir),
293                             tf_tcam_tbl_2_str(parms->type),
294                             parms->idx,
295                             strerror(-rc));
296         }
297
298         return 0;
299 }
300
301 int
302 tf_tcam_alloc_search(struct tf *tfp __rte_unused,
303                      struct tf_tcam_alloc_search_parms *parms __rte_unused)
304 {
305         return 0;
306 }
307
308 int
309 tf_tcam_set(struct tf *tfp __rte_unused,
310             struct tf_tcam_set_parms *parms __rte_unused)
311 {
312         int rc;
313         struct tf_session *tfs;
314         struct tf_dev_info *dev;
315         struct tf_rm_is_allocated_parms aparms = { 0 };
316         struct tf_rm_get_hcapi_parms hparms = { 0 };
317         uint16_t num_slice_per_row = 1;
318         int allocated = 0;
319
320         TF_CHECK_PARMS2(tfp, parms);
321
322         if (!init) {
323                 TFP_DRV_LOG(ERR,
324                             "%s: No TCAM DBs created\n",
325                             tf_dir_2_str(parms->dir));
326                 return -EINVAL;
327         }
328
329         /* Retrieve the session information */
330         rc = tf_session_get_session(tfp, &tfs);
331         if (rc)
332                 return rc;
333
334         /* Retrieve the device information */
335         rc = tf_session_get_device(tfs, &dev);
336         if (rc)
337                 return rc;
338
339         if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
340                 rc = -EOPNOTSUPP;
341                 TFP_DRV_LOG(ERR,
342                             "%s: Operation not supported, rc:%s\n",
343                             tf_dir_2_str(parms->dir),
344                             strerror(-rc));
345                 return rc;
346         }
347
348         /* Need to retrieve row size etc */
349         rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
350                                                   parms->type,
351                                                   parms->key_size,
352                                                   &num_slice_per_row);
353         if (rc)
354                 return rc;
355
356         /* Check if element is in use */
357         aparms.rm_db = tcam_db[parms->dir];
358         aparms.db_index = parms->type;
359         aparms.index = parms->idx / num_slice_per_row;
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 is not allocated, type:%d, index:%d\n",
368                             tf_dir_2_str(parms->dir),
369                             parms->type,
370                             parms->idx);
371                 return -EINVAL;
372         }
373
374         /* Convert TF type to HCAPI RM type */
375         hparms.rm_db = tcam_db[parms->dir];
376         hparms.db_index = parms->type;
377         hparms.hcapi_type = &parms->hcapi_type;
378
379         rc = tf_rm_get_hcapi_type(&hparms);
380         if (rc)
381                 return rc;
382
383         rc = tf_msg_tcam_entry_set(tfp, parms);
384         if (rc) {
385                 /* Log error */
386                 TFP_DRV_LOG(ERR,
387                             "%s: %s: Entry %d set failed, rc:%s",
388                             tf_dir_2_str(parms->dir),
389                             tf_tcam_tbl_2_str(parms->type),
390                             parms->idx,
391                             strerror(-rc));
392         }
393
394         return 0;
395 }
396
397 int
398 tf_tcam_get(struct tf *tfp __rte_unused,
399             struct tf_tcam_get_parms *parms __rte_unused)
400 {
401         return 0;
402 }