net/bnxt: support two-level priority for TCAMs
[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.num_elements = parms->num_elements;
57         db_cfg.type = TF_DEVICE_MODULE_TYPE_TCAM;
58         db_cfg.num_elements = parms->num_elements;
59         db_cfg.cfg = parms->cfg;
60
61         for (i = 0; i < TF_DIR_MAX; i++) {
62                 db_cfg.dir = i;
63                 db_cfg.alloc_cnt = parms->resources->tcam_cnt[i].cnt;
64                 db_cfg.rm_db = &tcam_db[i];
65                 rc = tf_rm_create_db(tfp, &db_cfg);
66                 if (rc) {
67                         TFP_DRV_LOG(ERR,
68                                     "%s: TCAM DB creation failed\n",
69                                     tf_dir_2_str(i));
70                         return rc;
71                 }
72         }
73
74         init = 1;
75
76         printf("TCAM - initialized\n");
77
78         return 0;
79 }
80
81 int
82 tf_tcam_unbind(struct tf *tfp)
83 {
84         int rc;
85         int i;
86         struct tf_rm_free_db_parms fparms = { 0 };
87
88         TF_CHECK_PARMS1(tfp);
89
90         /* Bail if nothing has been initialized done silent as to
91          * allow for creation cleanup.
92          */
93         if (!init)
94                 return -EINVAL;
95
96         for (i = 0; i < TF_DIR_MAX; i++) {
97                 fparms.dir = i;
98                 fparms.rm_db = tcam_db[i];
99                 rc = tf_rm_free_db(tfp, &fparms);
100                 if (rc)
101                         return rc;
102
103                 tcam_db[i] = NULL;
104         }
105
106         init = 0;
107
108         return 0;
109 }
110
111 int
112 tf_tcam_alloc(struct tf *tfp,
113               struct tf_tcam_alloc_parms *parms)
114 {
115         int rc;
116         struct tf_session *tfs;
117         struct tf_dev_info *dev;
118         struct tf_rm_allocate_parms aparms = { 0 };
119         uint16_t num_slice_per_row = 1;
120
121         TF_CHECK_PARMS2(tfp, parms);
122
123         if (!init) {
124                 TFP_DRV_LOG(ERR,
125                             "%s: No TCAM DBs created\n",
126                             tf_dir_2_str(parms->dir));
127                 return -EINVAL;
128         }
129
130         /* Retrieve the session information */
131         rc = tf_session_get_session(tfp, &tfs);
132         if (rc)
133                 return rc;
134
135         /* Retrieve the device information */
136         rc = tf_session_get_device(tfs, &dev);
137         if (rc)
138                 return rc;
139
140         if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
141                 rc = -EOPNOTSUPP;
142                 TFP_DRV_LOG(ERR,
143                             "%s: Operation not supported, rc:%s\n",
144                             tf_dir_2_str(parms->dir),
145                             strerror(-rc));
146                 return rc;
147         }
148
149         /* Need to retrieve row size etc */
150         rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
151                                                   parms->type,
152                                                   parms->key_size,
153                                                   &num_slice_per_row);
154         if (rc)
155                 return rc;
156
157         /* Allocate requested element */
158         aparms.rm_db = tcam_db[parms->dir];
159         aparms.db_index = parms->type;
160         aparms.priority = parms->priority;
161         aparms.index = (uint32_t *)&parms->idx;
162         rc = tf_rm_allocate(&aparms);
163         if (rc) {
164                 TFP_DRV_LOG(ERR,
165                             "%s: Failed tcam, type:%d\n",
166                             tf_dir_2_str(parms->dir),
167                             parms->type);
168                 return rc;
169         }
170
171         parms->idx *= num_slice_per_row;
172
173         return 0;
174 }
175
176 int
177 tf_tcam_free(struct tf *tfp __rte_unused,
178              struct tf_tcam_free_parms *parms __rte_unused)
179 {
180         int rc;
181         struct tf_session *tfs;
182         struct tf_dev_info *dev;
183         struct tf_rm_is_allocated_parms aparms = { 0 };
184         struct tf_rm_free_parms fparms = { 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         rc = tf_msg_tcam_entry_free(tfp, parms);
257         if (rc) {
258                 /* Log error */
259                 TFP_DRV_LOG(ERR, "%s: %s: Entry %d free failed with err %s",
260                             tf_dir_2_str(parms->dir),
261                             tf_tcam_tbl_2_str(parms->type),
262                             parms->idx,
263                             strerror(-rc));
264         }
265
266         return 0;
267 }
268
269 int
270 tf_tcam_alloc_search(struct tf *tfp __rte_unused,
271                      struct tf_tcam_alloc_search_parms *parms __rte_unused)
272 {
273         return 0;
274 }
275
276 int
277 tf_tcam_set(struct tf *tfp __rte_unused,
278             struct tf_tcam_set_parms *parms __rte_unused)
279 {
280         int rc;
281         struct tf_session *tfs;
282         struct tf_dev_info *dev;
283         struct tf_rm_is_allocated_parms aparms = { 0 };
284         uint16_t num_slice_per_row = 1;
285         int allocated = 0;
286
287         TF_CHECK_PARMS2(tfp, parms);
288
289         if (!init) {
290                 TFP_DRV_LOG(ERR,
291                             "%s: No TCAM DBs created\n",
292                             tf_dir_2_str(parms->dir));
293                 return -EINVAL;
294         }
295
296         /* Retrieve the session information */
297         rc = tf_session_get_session(tfp, &tfs);
298         if (rc)
299                 return rc;
300
301         /* Retrieve the device information */
302         rc = tf_session_get_device(tfs, &dev);
303         if (rc)
304                 return rc;
305
306         if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
307                 rc = -EOPNOTSUPP;
308                 TFP_DRV_LOG(ERR,
309                             "%s: Operation not supported, rc:%s\n",
310                             tf_dir_2_str(parms->dir),
311                             strerror(-rc));
312                 return rc;
313         }
314
315         /* Need to retrieve row size etc */
316         rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
317                                                   parms->type,
318                                                   parms->key_size,
319                                                   &num_slice_per_row);
320         if (rc)
321                 return rc;
322
323         /* Check if element is in use */
324         aparms.rm_db = tcam_db[parms->dir];
325         aparms.db_index = parms->type;
326         aparms.index = parms->idx / num_slice_per_row;
327         aparms.allocated = &allocated;
328         rc = tf_rm_is_allocated(&aparms);
329         if (rc)
330                 return rc;
331
332         if (!allocated) {
333                 TFP_DRV_LOG(ERR,
334                             "%s: Entry is not allocated, type:%d, index:%d\n",
335                             tf_dir_2_str(parms->dir),
336                             parms->type,
337                             parms->idx);
338                 return rc;
339         }
340
341         rc = tf_msg_tcam_entry_set(tfp, parms);
342         if (rc) {
343                 /* Log error */
344                 TFP_DRV_LOG(ERR, "%s: %s: Entry %d free failed with err %s",
345                             tf_dir_2_str(parms->dir),
346                             tf_tcam_tbl_2_str(parms->type),
347                             parms->idx,
348                             strerror(-rc));
349         }
350
351         return 0;
352 }
353
354 int
355 tf_tcam_get(struct tf *tfp __rte_unused,
356             struct tf_tcam_get_parms *parms __rte_unused)
357 {
358         return 0;
359 }