xref: /dpdk/drivers/net/bnxt/tf_core/tf_tcam.c (revision d0d22f1f062d6d08839601397e74d2aeb6b5a72c)
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 }
429