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