xref: /dpdk/drivers/net/bnxt/tf_core/tf_tcam.c (revision cb440babbd45a80c059f8bc80e87c48d09086fd7)
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_internal(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_internal(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 		return rc;
323 	}
324 
325 	return 0;
326 }
327 
328 int
329 tf_tcam_alloc_search(struct tf *tfp __rte_unused,
330 		     struct tf_tcam_alloc_search_parms *parms __rte_unused)
331 {
332 	return 0;
333 }
334 
335 int
336 tf_tcam_set(struct tf *tfp __rte_unused,
337 	    struct tf_tcam_set_parms *parms __rte_unused)
338 {
339 	int rc;
340 	struct tf_session *tfs;
341 	struct tf_dev_info *dev;
342 	struct tf_rm_is_allocated_parms aparms = { 0 };
343 	struct tf_rm_get_hcapi_parms hparms = { 0 };
344 	uint16_t num_slice_per_row = 1;
345 	int allocated = 0;
346 
347 	TF_CHECK_PARMS2(tfp, parms);
348 
349 	if (!init) {
350 		TFP_DRV_LOG(ERR,
351 			    "%s: No TCAM DBs created\n",
352 			    tf_dir_2_str(parms->dir));
353 		return -EINVAL;
354 	}
355 
356 	/* Retrieve the session information */
357 	rc = tf_session_get_session_internal(tfp, &tfs);
358 	if (rc)
359 		return rc;
360 
361 	/* Retrieve the device information */
362 	rc = tf_session_get_device(tfs, &dev);
363 	if (rc)
364 		return rc;
365 
366 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
367 		rc = -EOPNOTSUPP;
368 		TFP_DRV_LOG(ERR,
369 			    "%s: Operation not supported, rc:%s\n",
370 			    tf_dir_2_str(parms->dir),
371 			    strerror(-rc));
372 		return rc;
373 	}
374 
375 	/* Need to retrieve row size etc */
376 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
377 						  parms->type,
378 						  parms->key_size,
379 						  &num_slice_per_row);
380 	if (rc)
381 		return rc;
382 
383 	/* Check if element is in use */
384 	aparms.rm_db = tcam_db[parms->dir];
385 	aparms.db_index = parms->type;
386 	aparms.index = parms->idx / num_slice_per_row;
387 	aparms.allocated = &allocated;
388 	rc = tf_rm_is_allocated(&aparms);
389 	if (rc)
390 		return rc;
391 
392 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
393 		TFP_DRV_LOG(ERR,
394 			    "%s: Entry is not allocated, type:%d, index:%d\n",
395 			    tf_dir_2_str(parms->dir),
396 			    parms->type,
397 			    parms->idx);
398 		return -EINVAL;
399 	}
400 
401 	/* Convert TF type to HCAPI RM type */
402 	hparms.rm_db = tcam_db[parms->dir];
403 	hparms.db_index = parms->type;
404 	hparms.hcapi_type = &parms->hcapi_type;
405 
406 	rc = tf_rm_get_hcapi_type(&hparms);
407 	if (rc)
408 		return rc;
409 
410 	rc = tf_msg_tcam_entry_set(tfp, parms);
411 	if (rc) {
412 		/* Log error */
413 		TFP_DRV_LOG(ERR,
414 			    "%s: %s: Entry %d set failed, rc:%s",
415 			    tf_dir_2_str(parms->dir),
416 			    tf_tcam_tbl_2_str(parms->type),
417 			    parms->idx,
418 			    strerror(-rc));
419 		return rc;
420 	}
421 
422 	return 0;
423 }
424 
425 int
426 tf_tcam_get(struct tf *tfp __rte_unused,
427 	    struct tf_tcam_get_parms *parms __rte_unused)
428 {
429 	return 0;
430 }
431