xref: /dpdk/drivers/net/bnxt/tf_core/tf_em_internal.c (revision fb97e509)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2021 Broadcom
3  * All rights reserved.
4  */
5 
6 #include <string.h>
7 #include <rte_common.h>
8 #include <rte_errno.h>
9 #include <rte_log.h>
10 
11 #include "tf_core.h"
12 #include "tf_util.h"
13 #include "tf_common.h"
14 #include "tf_em.h"
15 #include "tf_msg.h"
16 #include "tfp.h"
17 #include "tf_ext_flow_handle.h"
18 #include "bnxt.h"
19 
20 #define TF_EM_DB_EM_REC 0
21 
22 /**
23  * EM Pool
24  */
25 #include "dpool.h"
26 
27 /**
28  * Insert EM internal entry API
29  *
30  *  returns:
31  *     0 - Success
32  */
33 int
tf_em_insert_int_entry(struct tf * tfp,struct tf_insert_em_entry_parms * parms)34 tf_em_insert_int_entry(struct tf *tfp,
35 		       struct tf_insert_em_entry_parms *parms)
36 {
37 	int rc;
38 	uint32_t gfid;
39 	uint16_t rptr_index = 0;
40 	uint8_t rptr_entry = 0;
41 	uint8_t num_of_entries = 0;
42 	struct tf_session *tfs;
43 	struct dpool *pool;
44 	uint32_t index;
45 
46 	/* Retrieve the session information */
47 	rc = tf_session_get_session(tfp, &tfs);
48 	if (rc) {
49 		TFP_DRV_LOG(ERR,
50 			    "%s: Failed to lookup session, rc:%s\n",
51 			    tf_dir_2_str(parms->dir),
52 			    strerror(-rc));
53 		return rc;
54 	}
55 
56 	pool = (struct dpool *)tfs->em_pool[parms->dir];
57 	index = dpool_alloc(pool, TF_SESSION_EM_ENTRY_SIZE, 0);
58 	if (index == DP_INVALID_INDEX) {
59 		PMD_DRV_LOG(ERR,
60 			    "%s, EM entry index allocation failed\n",
61 			    tf_dir_2_str(parms->dir));
62 		return -1;
63 	}
64 
65 
66 	rptr_index = index;
67 	rc = tf_msg_insert_em_internal_entry(tfp,
68 					     parms,
69 					     &rptr_index,
70 					     &rptr_entry,
71 					     &num_of_entries);
72 	if (rc) {
73 		/* Free the allocated index before returning */
74 		dpool_free(pool, index);
75 		return -1;
76 	}
77 	TF_SET_GFID(gfid,
78 		    ((rptr_index << TF_EM_INTERNAL_INDEX_SHIFT) |
79 		     rptr_entry),
80 		    0); /* N/A for internal table */
81 
82 	TF_SET_FLOW_ID(parms->flow_id,
83 		       gfid,
84 		       TF_GFID_TABLE_INTERNAL,
85 		       parms->dir);
86 
87 	TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
88 				     (uint32_t)num_of_entries,
89 				     0,
90 				     TF_FLAGS_FLOW_HANDLE_INTERNAL,
91 				     rptr_index,
92 				     rptr_entry,
93 				     0);
94 	return 0;
95 }
96 
97 
98 /** Delete EM internal entry API
99  *
100  * returns:
101  * 0
102  * -EINVAL
103  */
104 int
tf_em_delete_int_entry(struct tf * tfp,struct tf_delete_em_entry_parms * parms)105 tf_em_delete_int_entry(struct tf *tfp,
106 		       struct tf_delete_em_entry_parms *parms)
107 {
108 	int rc = 0;
109 	struct tf_session *tfs;
110 	struct dpool *pool;
111 	/* Retrieve the session information */
112 	rc = tf_session_get_session(tfp, &tfs);
113 	if (rc) {
114 		TFP_DRV_LOG(ERR,
115 			    "%s: Failed to lookup session, rc:%s\n",
116 			    tf_dir_2_str(parms->dir),
117 			    strerror(-rc));
118 		return rc;
119 	}
120 
121 	rc = tf_msg_delete_em_entry(tfp, parms);
122 
123 	/* Return resource to pool */
124 	if (rc == 0) {
125 		pool = (struct dpool *)tfs->em_pool[parms->dir];
126 		dpool_free(pool, parms->index);
127 	}
128 
129 	return rc;
130 }
131 
132 static int
tf_em_move_callback(void * user_data,uint64_t entry_data,uint32_t new_index)133 tf_em_move_callback(void *user_data,
134 		    uint64_t entry_data,
135 		    uint32_t new_index)
136 {
137 	int rc;
138 	struct tf *tfp = (struct tf *)user_data;
139 	struct tf_move_em_entry_parms parms;
140 	struct tf_dev_info     *dev;
141 	struct tf_session      *tfs;
142 
143 	memset(&parms, 0, sizeof(parms));
144 
145 	parms.tbl_scope_id = 0;
146 	parms.flow_handle  = entry_data;
147 	parms.new_index    = new_index;
148 	TF_GET_DIR_FROM_FLOW_ID(entry_data, parms.dir);
149 	parms.mem          = TF_MEM_INTERNAL;
150 
151 	/* Retrieve the session information */
152 	rc = tf_session_get_session(tfp, &tfs);
153 	if (rc) {
154 		TFP_DRV_LOG(ERR,
155 			    "%s: Failed to lookup session, rc:%s\n",
156 			    tf_dir_2_str(parms.dir),
157 			    strerror(-rc));
158 		return rc;
159 	}
160 
161 	/* Retrieve the device information */
162 	rc = tf_session_get_device(tfs, &dev);
163 	if (rc) {
164 		TFP_DRV_LOG(ERR,
165 			    "%s: Failed to lookup device, rc:%s\n",
166 			    tf_dir_2_str(parms.dir),
167 			    strerror(-rc));
168 		return rc;
169 	}
170 
171 	if (dev->ops->tf_dev_move_int_em_entry != NULL)
172 		rc = dev->ops->tf_dev_move_int_em_entry(tfp, &parms);
173 	else
174 		rc = -EOPNOTSUPP;
175 
176 	return rc;
177 }
178 
179 int
tf_em_int_bind(struct tf * tfp,struct tf_em_cfg_parms * parms)180 tf_em_int_bind(struct tf *tfp,
181 	       struct tf_em_cfg_parms *parms)
182 {
183 	int rc;
184 	int db_rc[TF_DIR_MAX] = { 0 };
185 	int i;
186 	struct tf_rm_create_db_parms db_cfg = { 0 };
187 	struct tf_rm_get_alloc_info_parms iparms;
188 	struct tf_rm_alloc_info info;
189 	struct em_rm_db *em_db;
190 	struct tfp_calloc_parms cparms;
191 	struct tf_session *tfs;
192 
193 	TF_CHECK_PARMS2(tfp, parms);
194 
195 	/* Retrieve the session information */
196 	rc = tf_session_get_session_internal(tfp, &tfs);
197 	if (rc)
198 		return rc;
199 
200 	memset(&db_cfg, 0, sizeof(db_cfg));
201 	cparms.nitems = 1;
202 	cparms.size = sizeof(struct em_rm_db);
203 	cparms.alignment = 0;
204 	if (tfp_calloc(&cparms) != 0) {
205 		TFP_DRV_LOG(ERR, "em_rm_db alloc error %s\n",
206 			    strerror(ENOMEM));
207 		return -ENOMEM;
208 	}
209 
210 	em_db = cparms.mem_va;
211 	for (i = 0; i < TF_DIR_MAX; i++)
212 		em_db->em_db[i] = NULL;
213 	tf_session_set_db(tfp, TF_MODULE_TYPE_EM, em_db);
214 
215 	db_cfg.module = TF_MODULE_TYPE_EM;
216 	db_cfg.num_elements = parms->num_elements;
217 	db_cfg.cfg = parms->cfg;
218 
219 	for (i = 0; i < TF_DIR_MAX; i++) {
220 		db_cfg.dir = i;
221 		db_cfg.alloc_cnt = parms->resources->em_cnt[i].cnt;
222 
223 		/* Check if we got any request to support EEM, if so
224 		 * we build an EM Int DB holding Table Scopes.
225 		 */
226 		if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_EM_RECORD] == 0)
227 			continue;
228 
229 		if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_EM_RECORD] %
230 		    TF_SESSION_EM_ENTRY_SIZE != 0) {
231 			rc = -ENOMEM;
232 			TFP_DRV_LOG(ERR,
233 				    "%s, EM Allocation must be in blocks of %d, failure %s\n",
234 				    tf_dir_2_str(i),
235 				    TF_SESSION_EM_ENTRY_SIZE,
236 				    strerror(-rc));
237 
238 			return rc;
239 		}
240 
241 		db_cfg.rm_db = (void *)&em_db->em_db[i];
242 		if (tf_session_is_shared_session(tfs) &&
243 			(!tf_session_is_shared_session_creator(tfs)))
244 			db_rc[i] = tf_rm_create_db_no_reservation(tfp, &db_cfg);
245 		else
246 			db_rc[i] = tf_rm_create_db(tfp, &db_cfg);
247 	}
248 
249 	/* No db created */
250 	if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) {
251 		TFP_DRV_LOG(ERR, "EM Int DB creation failed\n");
252 		return db_rc[TF_DIR_RX];
253 	}
254 
255 
256 	if (!tf_session_is_shared_session(tfs)) {
257 		for (i = 0; i < TF_DIR_MAX; i++) {
258 			iparms.rm_db = em_db->em_db[i];
259 			iparms.subtype = TF_EM_DB_EM_REC;
260 			iparms.info = &info;
261 
262 			rc = tf_rm_get_info(&iparms);
263 			if (rc) {
264 				TFP_DRV_LOG(ERR,
265 					    "%s: EM DB get info failed\n",
266 					    tf_dir_2_str(i));
267 				return rc;
268 			}
269 
270 			/*
271 			 * Allocate stack pool
272 			 */
273 			cparms.nitems = 1;
274 			cparms.size = sizeof(struct dpool);
275 			cparms.alignment = 0;
276 
277 			rc = tfp_calloc(&cparms);
278 
279 			if (rc) {
280 				TFP_DRV_LOG(ERR,
281 					 "%s, EM stack allocation failure %s\n",
282 					 tf_dir_2_str(i),
283 					 strerror(-rc));
284 				return rc;
285 			}
286 
287 			tfs->em_pool[i] = (struct dpool *)cparms.mem_va;
288 
289 			rc = dpool_init(tfs->em_pool[i],
290 					iparms.info->entry.start,
291 					iparms.info->entry.stride,
292 					7,
293 					(void *)tfp,
294 					tf_em_move_callback);
295 			/* Logging handled in tf_create_em_pool */
296 			if (rc)
297 				return rc;
298 		}
299 
300 		if (rc) {
301 			TFP_DRV_LOG(ERR,
302 				    "%s: EM pool init failed\n",
303 				    tf_dir_2_str(i));
304 			return rc;
305 		}
306 	}
307 
308 	return 0;
309 }
310 
311 int
tf_em_int_unbind(struct tf * tfp)312 tf_em_int_unbind(struct tf *tfp)
313 {
314 	int rc;
315 	int i;
316 	struct tf_rm_free_db_parms fparms = { 0 };
317 	struct em_rm_db *em_db;
318 	void *em_db_ptr = NULL;
319 	struct tf_session *tfs;
320 
321 	TF_CHECK_PARMS1(tfp);
322 
323 	/* Retrieve the session information */
324 	rc = tf_session_get_session_internal(tfp, &tfs);
325 	if (rc)
326 		return rc;
327 
328 	if (!tf_session_is_shared_session(tfs)) {
329 		for (i = 0; i < TF_DIR_MAX; i++) {
330 			if (tfs->em_pool[i] == NULL)
331 				continue;
332 			dpool_free_all(tfs->em_pool[i]);
333 		}
334 	}
335 
336 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr);
337 	if (rc) {
338 		return 0;
339 	}
340 	em_db = (struct em_rm_db *)em_db_ptr;
341 
342 	for (i = 0; i < TF_DIR_MAX; i++) {
343 		if (em_db->em_db[i] == NULL)
344 			continue;
345 		fparms.dir = i;
346 		fparms.rm_db = em_db->em_db[i];
347 		rc = tf_rm_free_db(tfp, &fparms);
348 		if (rc)
349 			return rc;
350 
351 		em_db->em_db[i] = NULL;
352 	}
353 
354 	return 0;
355 }
356 
357 int
tf_em_get_resc_info(struct tf * tfp,struct tf_em_resource_info * em)358 tf_em_get_resc_info(struct tf *tfp,
359 		    struct tf_em_resource_info *em)
360 {
361 	int rc;
362 	int d;
363 	struct tf_resource_info *dinfo;
364 	struct tf_rm_get_alloc_info_parms ainfo;
365 	void *em_db_ptr = NULL;
366 	struct em_rm_db *em_db;
367 
368 	TF_CHECK_PARMS2(tfp, em);
369 
370 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr);
371 	if (rc == -ENOMEM)
372 		return 0;  /* db does not exist */
373 	else if (rc)
374 		return rc; /* db error */
375 
376 	em_db = (struct em_rm_db *)em_db_ptr;
377 
378 	/* check if reserved resource for EM is multiple of num_slices */
379 	for (d = 0; d < TF_DIR_MAX; d++) {
380 		ainfo.rm_db = em_db->em_db[d];
381 		dinfo = em[d].info;
382 
383 		if (!ainfo.rm_db)
384 			continue;
385 
386 		ainfo.info = (struct tf_rm_alloc_info *)dinfo;
387 		ainfo.subtype = 0;
388 		rc = tf_rm_get_all_info(&ainfo, TF_EM_TBL_TYPE_MAX);
389 		if (rc && rc != -ENOTSUP)
390 			return rc;
391 	}
392 
393 	return 0;
394 }
395