xref: /dpdk/drivers/net/bnxt/tf_core/tf_tcam.c (revision 5873bd31dc8393b17fb7b45bd1f714c227dad3f5)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2024 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 #include "tf_tcam_mgr_msg.h"
18 
19 struct tf;
20 
21 int
22 tf_tcam_bind(struct tf *tfp,
23 	     struct tf_tcam_cfg_parms *parms)
24 {
25 	int rc;
26 	int db_rc[TF_DIR_MAX] = { 0 };
27 	int d, t;
28 	struct tf_rm_alloc_info info;
29 	struct tf_rm_free_db_parms fparms;
30 	struct tf_rm_create_db_parms db_cfg = { 0 };
31 	struct tf_tcam_resources local_tcam_cnt[TF_DIR_MAX];
32 	struct tf_tcam_resources *tcam_cnt;
33 	struct tf_rm_get_alloc_info_parms ainfo;
34 	uint16_t num_slices = 1;
35 	struct tf_session *tfs;
36 	struct tf_dev_info *dev;
37 	struct tcam_rm_db *tcam_db;
38 	struct tfp_calloc_parms cparms;
39 	struct tf_resource_info resv_res[TF_DIR_MAX][TF_TCAM_TBL_TYPE_MAX];
40 
41 	TF_CHECK_PARMS2(tfp, parms);
42 
43 	/* Retrieve the session information */
44 	rc = tf_session_get_session_internal(tfp, &tfs);
45 	if (rc)
46 		return rc;
47 
48 	/* Retrieve the device information */
49 	rc = tf_session_get_device(tfs, &dev);
50 	if (rc)
51 		return rc;
52 
53 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
54 		rc = -EOPNOTSUPP;
55 		TFP_DRV_LOG(ERR,
56 			    "Operation not supported, rc:%s\n",
57 			    strerror(-rc));
58 		return rc;
59 	}
60 
61 	tcam_cnt = parms->resources->tcam_cnt;
62 
63 	for (d = 0; d < TF_DIR_MAX; d++) {
64 		for (t = 0; t < TF_TCAM_TBL_TYPE_MAX; t++) {
65 			rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, t, 0,
66 								  &num_slices);
67 	if (rc)
68 		return rc;
69 
70 			if (num_slices == 1)
71 				continue;
72 
73 			if (tcam_cnt[d].cnt[t] % num_slices) {
74 				TFP_DRV_LOG(ERR,
75 					    "%s: Requested num of %s entries "
76 					    "has to be multiple of %d\n",
77 					    tf_dir_2_str(d),
78 					    tf_tcam_tbl_2_str(t),
79 					    num_slices);
80 				return -EINVAL;
81 			}
82 		}
83 	}
84 
85 	memset(&db_cfg, 0, sizeof(db_cfg));
86 	cparms.nitems = 1;
87 	cparms.size = sizeof(struct tcam_rm_db);
88 	cparms.alignment = 0;
89 	if (tfp_calloc(&cparms) != 0) {
90 		TFP_DRV_LOG(ERR, "tcam_rm_db alloc error %s\n",
91 			    strerror(ENOMEM));
92 		return -ENOMEM;
93 	}
94 
95 	tcam_db = cparms.mem_va;
96 	for (d = 0; d < TF_DIR_MAX; d++)
97 		tcam_db->tcam_db[d] = NULL;
98 	tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, tcam_db);
99 
100 	db_cfg.module = TF_MODULE_TYPE_TCAM;
101 	db_cfg.num_elements = parms->num_elements;
102 	db_cfg.cfg = parms->cfg;
103 
104 	for (d = 0; d < TF_DIR_MAX; d++) {
105 		db_cfg.dir = d;
106 		db_cfg.alloc_cnt = tcam_cnt[d].cnt;
107 		db_cfg.rm_db = (void *)&tcam_db->tcam_db[d];
108 		if (tf_session_is_shared_session(tfs) &&
109 			(!tf_session_is_shared_session_creator(tfs)))
110 			db_rc[d] = tf_rm_create_db_no_reservation(tfp, &db_cfg);
111 		else
112 			db_rc[d] = tf_rm_create_db(tfp, &db_cfg);
113 	}
114 	/* No db created */
115 	if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) {
116 		TFP_DRV_LOG(ERR, "No TCAM DB created\n");
117 		return db_rc[TF_DIR_RX];
118 	}
119 
120 	/* Collect info on which entries were reserved. */
121 	for (d = 0; d < TF_DIR_MAX; d++) {
122 		for (t = 0; t < TF_TCAM_TBL_TYPE_MAX; t++) {
123 			memset(&info, 0, sizeof(info));
124 			if (tcam_cnt[d].cnt[t] == 0) {
125 				resv_res[d][t].start  = 0;
126 				resv_res[d][t].stride = 0;
127 				continue;
128 			}
129 			ainfo.rm_db = tcam_db->tcam_db[d];
130 			ainfo.subtype = t;
131 			ainfo.info = &info;
132 			rc = tf_rm_get_info(&ainfo);
133 			if (rc)
134 				goto error;
135 
136 			rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, t, 0,
137 								  &num_slices);
138 			if (rc)
139 				return rc;
140 
141 			if (num_slices > 1) {
142 				/* check if reserved resource for is multiple of
143 				 * num_slices
144 				 */
145 				if (info.entry.start % num_slices != 0 ||
146 				    info.entry.stride % num_slices != 0) {
147 					TFP_DRV_LOG(ERR,
148 						    "%s: %s reserved resource"
149 						    " is not multiple of %d\n",
150 						    tf_dir_2_str(d),
151 						    tf_tcam_tbl_2_str(t),
152 						    num_slices);
153 					rc = -EINVAL;
154 					goto error;
155 				}
156 			}
157 
158 			resv_res[d][t].start  = info.entry.start;
159 			resv_res[d][t].stride = info.entry.stride;
160 		}
161 	}
162 
163 	rc = tf_tcam_mgr_bind_msg(tfp, dev, parms, resv_res);
164 	if (rc)
165 		return rc;
166 
167 	/*
168 	 * Make a local copy of tcam_cnt with only resources not managed by TCAM
169 	 * Manager requested.
170 	 */
171 	memcpy(&local_tcam_cnt, tcam_cnt, sizeof(local_tcam_cnt));
172 	tcam_cnt = local_tcam_cnt;
173 	for (d = 0; d < TF_DIR_MAX; d++)
174 		for (t = 0; t < TF_TCAM_TBL_TYPE_MAX; t++)
175 			tcam_cnt[d].cnt[t] = 0;
176 
177 	TFP_DRV_LOG(INFO,
178 		    "TCAM - initialized\n");
179 
180 	return 0;
181 error:
182 	for (d = 0; d < TF_DIR_MAX; d++) {
183 		if (tcam_db->tcam_db[d] != NULL) {
184 			memset(&fparms, 0, sizeof(fparms));
185 			fparms.dir = d;
186 			fparms.rm_db = tcam_db->tcam_db[d];
187 			/*
188 			 * Ignoring return here since we are in the error case
189 			 */
190 			(void)tf_rm_free_db(tfp, &fparms);
191 
192 			tcam_db->tcam_db[d] = NULL;
193 		}
194 		tcam_db->tcam_db[d] = NULL;
195 		tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, NULL);
196 	}
197 	return rc;
198 }
199 
200 int
201 tf_tcam_unbind(struct tf *tfp)
202 {
203 	int rc;
204 	int i;
205 	struct tf_rm_free_db_parms fparms;
206 	struct tcam_rm_db *tcam_db;
207 	void *tcam_db_ptr = NULL;
208 	struct tf_session *tfs;
209 	struct tf_dev_info *dev;
210 	TF_CHECK_PARMS1(tfp);
211 
212 	/* Retrieve the session information */
213 	rc = tf_session_get_session_internal(tfp, &tfs);
214 	if (rc)
215 		return rc;
216 
217 	/* Retrieve the device information */
218 	rc = tf_session_get_device(tfs, &dev);
219 	if (rc)
220 		return rc;
221 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
222 	if (rc)
223 		return 0;
224 
225 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
226 
227 	for (i = 0; i < TF_DIR_MAX; i++) {
228 		if (tcam_db->tcam_db[i] != NULL) {
229 			memset(&fparms, 0, sizeof(fparms));
230 			fparms.dir = i;
231 			fparms.rm_db = tcam_db->tcam_db[i];
232 			rc = tf_rm_free_db(tfp, &fparms);
233 			if (rc)
234 				return rc;
235 
236 			tcam_db->tcam_db[i] = NULL;
237 		}
238 	}
239 
240 	rc = tf_tcam_mgr_unbind_msg(tfp, dev);
241 	if (rc)
242 		return rc;
243 
244 	return 0;
245 }
246 
247 int
248 tf_tcam_alloc(struct tf *tfp,
249 	      struct tf_tcam_alloc_parms *parms)
250 {
251 	int rc;
252 	struct tf_session *tfs;
253 	struct tf_dev_info *dev;
254 	uint16_t num_slices = 1;
255 
256 	TF_CHECK_PARMS2(tfp, parms);
257 
258 	/* Retrieve the session information */
259 	rc = tf_session_get_session_internal(tfp, &tfs);
260 	if (rc)
261 		return rc;
262 
263 	/* Retrieve the device information */
264 	rc = tf_session_get_device(tfs, &dev);
265 	if (rc)
266 		return rc;
267 
268 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
269 		rc = -EOPNOTSUPP;
270 		TFP_DRV_LOG(ERR,
271 			    "%s: Operation not supported, rc:%s\n",
272 			    tf_dir_2_str(parms->dir),
273 			    strerror(-rc));
274 		return rc;
275 	}
276 
277 	/* Need to retrieve number of slices based on the key_size */
278 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
279 						  parms->type,
280 						  parms->key_size,
281 						  &num_slices);
282 	if (rc)
283 		return rc;
284 
285 	return tf_tcam_mgr_alloc_msg(tfp, dev, parms);
286 }
287 
288 int
289 tf_tcam_free(struct tf *tfp,
290 	     struct tf_tcam_free_parms *parms)
291 {
292 	int rc;
293 	struct tf_session *tfs;
294 	struct tf_dev_info *dev;
295 	uint16_t num_slices = 1;
296 
297 	TF_CHECK_PARMS2(tfp, parms);
298 
299 	/* Retrieve the session information */
300 	rc = tf_session_get_session_internal(tfp, &tfs);
301 	if (rc)
302 		return rc;
303 
304 	/* Retrieve the device information */
305 	rc = tf_session_get_device(tfs, &dev);
306 	if (rc)
307 		return rc;
308 
309 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
310 		rc = -EOPNOTSUPP;
311 		TFP_DRV_LOG(ERR,
312 			    "%s: Operation not supported, rc:%s\n",
313 			    tf_dir_2_str(parms->dir),
314 			    strerror(-rc));
315 		return rc;
316 	}
317 
318 	/* Need to retrieve row size etc */
319 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
320 						  parms->type,
321 						  0,
322 						  &num_slices);
323 	if (rc)
324 		return rc;
325 
326 	return tf_tcam_mgr_free_msg(tfp, dev, parms);
327 }
328 
329 int
330 tf_tcam_set(struct tf *tfp __rte_unused,
331 	    struct tf_tcam_set_parms *parms __rte_unused)
332 {
333 	int rc;
334 	struct tf_session *tfs;
335 	struct tf_dev_info *dev;
336 	uint16_t num_slice_per_row = 1;
337 
338 	TF_CHECK_PARMS2(tfp, parms);
339 
340 	/* Retrieve the session information */
341 	rc = tf_session_get_session_internal(tfp, &tfs);
342 	if (rc)
343 		return rc;
344 
345 	/* Retrieve the device information */
346 	rc = tf_session_get_device(tfs, &dev);
347 	if (rc)
348 		return rc;
349 
350 	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
351 		rc = -EOPNOTSUPP;
352 		TFP_DRV_LOG(ERR,
353 			    "%s: Operation not supported, rc:%s\n",
354 			    tf_dir_2_str(parms->dir),
355 			    strerror(-rc));
356 		return rc;
357 	}
358 
359 	/* Need to retrieve row size etc */
360 	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
361 						  parms->type,
362 						  parms->key_size,
363 						  &num_slice_per_row);
364 	if (rc)
365 		return rc;
366 
367 	return tf_tcam_mgr_set_msg(tfp, dev, parms);
368 }
369 
370 int
371 tf_tcam_get(struct tf *tfp __rte_unused,
372 	    struct tf_tcam_get_parms *parms)
373 {
374 	int rc;
375 	struct tf_session *tfs;
376 	struct tf_dev_info *dev;
377 
378 	TF_CHECK_PARMS2(tfp, parms);
379 
380 	/* Retrieve the session information */
381 	rc = tf_session_get_session_internal(tfp, &tfs);
382 	if (rc)
383 		return rc;
384 
385 	/* Retrieve the device information */
386 	rc = tf_session_get_device(tfs, &dev);
387 	if (rc)
388 		return rc;
389 
390 	return tf_tcam_mgr_get_msg(tfp, dev, parms);
391 }
392 
393 int
394 tf_tcam_get_resc_info(struct tf *tfp,
395 		      struct tf_tcam_resource_info *tcam)
396 {
397 	int rc;
398 	int d;
399 	struct tf_resource_info *dinfo;
400 	struct tf_rm_get_alloc_info_parms ainfo;
401 	void *tcam_db_ptr = NULL;
402 	struct tcam_rm_db *tcam_db;
403 
404 	TF_CHECK_PARMS2(tfp, tcam);
405 
406 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
407 	if (rc == -ENOMEM)
408 		return 0;  /* db doesn't exist */
409 	else if (rc)
410 		return rc; /* error getting db */
411 
412 	tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
413 
414 	/* check if reserved resource for WC is multiple of num_slices */
415 	for (d = 0; d < TF_DIR_MAX; d++) {
416 		ainfo.rm_db = tcam_db->tcam_db[d];
417 
418 		if (!ainfo.rm_db)
419 			continue;
420 
421 		dinfo = tcam[d].info;
422 
423 		ainfo.info = (struct tf_rm_alloc_info *)dinfo;
424 		ainfo.subtype = 0;
425 		rc = tf_rm_get_all_info(&ainfo, TF_TCAM_TBL_TYPE_MAX);
426 		if (rc && rc != -ENOTSUP)
427 			return rc;
428 	}
429 
430 	return 0;
431 }
432