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