Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2019-2023 Broadcom
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include <string.h>
7 : : #include <math.h>
8 : : #include <sys/param.h>
9 : : #include <rte_common.h>
10 : : #include <rte_errno.h>
11 : : #include <rte_log.h>
12 : : #include "tf_core.h"
13 : : #include "tf_util.h"
14 : : #include "tf_common.h"
15 : : #include "tf_em.h"
16 : : #include "tf_em_common.h"
17 : : #include "tf_msg.h"
18 : : #include "tfp.h"
19 : : #include "tf_device.h"
20 : : #include "tf_ext_flow_handle.h"
21 : : #include "hcapi_cfa.h"
22 : : #include "bnxt.h"
23 : :
24 : : /** Invalid table scope id */
25 : : #define TF_TBL_SCOPE_INVALID 0xffffffff
26 : :
27 : : /* Number of pointers per page_size */
28 : : #define MAX_PAGE_PTRS(page_size) ((page_size) / sizeof(void *))
29 : :
30 : : /**
31 : : * Host or system
32 : : */
33 : : static enum tf_mem_type mem_type;
34 : :
35 : : /* API defined in tf_em.h */
36 : : int
37 : 0 : tf_create_tbl_pool_external(enum tf_dir dir,
38 : : struct tf_tbl_scope_cb *tbl_scope_cb,
39 : : uint32_t num_entries,
40 : : uint32_t entry_sz_bytes)
41 : : {
42 : : struct tfp_calloc_parms parms;
43 : : uint32_t i;
44 : : int32_t j;
45 : : int rc = 0;
46 : 0 : struct stack *pool = &tbl_scope_cb->ext_act_pool[dir];
47 : :
48 : 0 : parms.nitems = num_entries;
49 : 0 : parms.size = sizeof(uint32_t);
50 : 0 : parms.alignment = 0;
51 : :
52 [ # # ]: 0 : if (tfp_calloc(&parms) != 0) {
53 : 0 : TFP_DRV_LOG(ERR, "%s: TBL: external pool failure %s\n",
54 : : tf_dir_2_str(dir), strerror(ENOMEM));
55 : 0 : return -ENOMEM;
56 : : }
57 : :
58 : : /* Create empty stack
59 : : */
60 : 0 : rc = stack_init(num_entries, parms.mem_va, pool);
61 : :
62 [ # # ]: 0 : if (rc != 0) {
63 : 0 : TFP_DRV_LOG(ERR, "%s: TBL: stack init failure %s\n",
64 : : tf_dir_2_str(dir), strerror(-rc));
65 : 0 : goto cleanup;
66 : : }
67 : :
68 : : /* Save the malloced memory address so that it can
69 : : * be freed when the table scope is freed.
70 : : */
71 : 0 : tbl_scope_cb->ext_act_pool_mem[dir] = (uint32_t *)parms.mem_va;
72 : :
73 : : /* Fill pool with indexes in reverse
74 : : */
75 : 0 : j = (num_entries - 1) * entry_sz_bytes;
76 : :
77 [ # # ]: 0 : for (i = 0; i < num_entries; i++) {
78 : 0 : rc = stack_push(pool, j);
79 [ # # ]: 0 : if (rc != 0) {
80 : 0 : TFP_DRV_LOG(ERR, "%s TBL: stack failure %s\n",
81 : : tf_dir_2_str(dir), strerror(-rc));
82 : 0 : goto cleanup;
83 : : }
84 : :
85 [ # # ]: 0 : if (j < 0) {
86 : 0 : TFP_DRV_LOG(ERR, "%d TBL: invalid offset (%d)\n",
87 : : dir, j);
88 : 0 : goto cleanup;
89 : : }
90 : 0 : j -= entry_sz_bytes;
91 : : }
92 : :
93 [ # # ]: 0 : if (!stack_is_full(pool)) {
94 : : rc = -EINVAL;
95 : 0 : TFP_DRV_LOG(ERR, "%s TBL: stack failure %s\n",
96 : : tf_dir_2_str(dir), strerror(-rc));
97 : 0 : goto cleanup;
98 : : }
99 : : return 0;
100 : 0 : cleanup:
101 : 0 : tfp_free((void *)parms.mem_va);
102 : 0 : return rc;
103 : : }
104 : :
105 : : /**
106 : : * Destroy External Tbl pool of memory indexes.
107 : : *
108 : : * [in] dir
109 : : * direction
110 : : * [in] tbl_scope_cb
111 : : * pointer to the table scope
112 : : */
113 : : void
114 : 0 : tf_destroy_tbl_pool_external(enum tf_dir dir,
115 : : struct tf_tbl_scope_cb *tbl_scope_cb)
116 : : {
117 : 0 : uint32_t *ext_act_pool_mem =
118 : : tbl_scope_cb->ext_act_pool_mem[dir];
119 : :
120 : 0 : tfp_free(ext_act_pool_mem);
121 : 0 : }
122 : :
123 : : /**
124 : : * Looks up table scope control block using tbl_scope_id from tf_session.
125 : : *
126 : : * [in] tfp
127 : : * Pointer to Truflow Handle
128 : : * [in] tbl_scope_id
129 : : * table scope id
130 : : *
131 : : * Return:
132 : : * - Pointer to the tf_tbl_scope_cb, if found.
133 : : * - (NULL) on failure, not found.
134 : : */
135 : : struct tf_tbl_scope_cb *
136 : 0 : tf_em_ext_common_tbl_scope_find(struct tf *tfp,
137 : : uint32_t tbl_scope_id)
138 : : {
139 : : int rc;
140 : : struct em_ext_db *ext_db;
141 : 0 : void *ext_ptr = NULL;
142 : : struct tf_tbl_scope_cb *tbl_scope_cb = NULL;
143 : : struct ll_entry *entry;
144 : :
145 : 0 : rc = tf_session_get_em_ext_db(tfp, &ext_ptr);
146 [ # # ]: 0 : if (rc)
147 : : return NULL;
148 : :
149 : 0 : ext_db = (struct em_ext_db *)ext_ptr;
150 : :
151 [ # # ]: 0 : for (entry = ext_db->tbl_scope_ll.head; entry != NULL;
152 : 0 : entry = entry->next) {
153 : : tbl_scope_cb = (struct tf_tbl_scope_cb *)entry;
154 [ # # ]: 0 : if (tbl_scope_cb->tbl_scope_id == tbl_scope_id)
155 : 0 : return tbl_scope_cb;
156 : : }
157 : :
158 : : return NULL;
159 : : }
160 : :
161 : : /**
162 : : * Allocate External Tbl entry from the scope pool.
163 : : *
164 : : * [in] tfp
165 : : * Pointer to Truflow Handle
166 : : * [in] parms
167 : : * Allocation parameters
168 : : *
169 : : * Return:
170 : : * 0 - Success, entry allocated - no search support
171 : : * -ENOMEM -EINVAL -EOPNOTSUPP
172 : : * - Failure, entry not allocated, out of resources
173 : : */
174 : : int
175 : 0 : tf_tbl_ext_alloc(struct tf *tfp,
176 : : struct tf_tbl_alloc_parms *parms)
177 : : {
178 : : int rc;
179 : : uint32_t index;
180 : : struct tf_tbl_scope_cb *tbl_scope_cb;
181 : : struct stack *pool;
182 : :
183 [ # # ]: 0 : TF_CHECK_PARMS2(tfp, parms);
184 : :
185 : 0 : tbl_scope_cb = tf_em_ext_common_tbl_scope_find(tfp, parms->tbl_scope_id);
186 [ # # ]: 0 : if (tbl_scope_cb == NULL) {
187 : 0 : TFP_DRV_LOG(ERR,
188 : : "%s, table scope not allocated\n",
189 : : tf_dir_2_str(parms->dir));
190 : 0 : return -EINVAL;
191 : : }
192 : :
193 : 0 : pool = &tbl_scope_cb->ext_act_pool[parms->dir];
194 : :
195 : : /* Allocate an element
196 : : */
197 : 0 : rc = stack_pop(pool, &index);
198 : :
199 [ # # ]: 0 : if (rc != 0) {
200 : 0 : TFP_DRV_LOG(ERR,
201 : : "%s, Allocation failed, type:%d\n",
202 : : tf_dir_2_str(parms->dir),
203 : : parms->type);
204 : 0 : return rc;
205 : : }
206 : :
207 : 0 : *parms->idx = index;
208 : 0 : return rc;
209 : : }
210 : :
211 : : /**
212 : : * Free External Tbl entry to the scope pool.
213 : : *
214 : : * [in] tfp
215 : : * Pointer to Truflow Handle
216 : : * [in] parms
217 : : * Allocation parameters
218 : : *
219 : : * Return:
220 : : * 0 - Success, entry freed
221 : : *
222 : : * - Failure, entry not successfully freed for these reasons
223 : : * -ENOMEM
224 : : * -EOPNOTSUPP
225 : : * -EINVAL
226 : : */
227 : : int
228 : 0 : tf_tbl_ext_free(struct tf *tfp,
229 : : struct tf_tbl_free_parms *parms)
230 : : {
231 : : int rc = 0;
232 : : uint32_t index;
233 : : struct tf_tbl_scope_cb *tbl_scope_cb;
234 : : struct stack *pool;
235 : :
236 [ # # ]: 0 : TF_CHECK_PARMS2(tfp, parms);
237 : :
238 : 0 : tbl_scope_cb = tf_em_ext_common_tbl_scope_find(tfp, parms->tbl_scope_id);
239 [ # # ]: 0 : if (tbl_scope_cb == NULL) {
240 : 0 : TFP_DRV_LOG(ERR,
241 : : "%s, table scope error\n",
242 : : tf_dir_2_str(parms->dir));
243 : 0 : return -EINVAL;
244 : : }
245 : 0 : pool = &tbl_scope_cb->ext_act_pool[parms->dir];
246 : :
247 : 0 : index = parms->idx;
248 : :
249 : 0 : rc = stack_push(pool, index);
250 : :
251 [ # # ]: 0 : if (rc != 0) {
252 : 0 : TFP_DRV_LOG(ERR,
253 : : "%s, consistency error, stack full, type:%d, idx:%d\n",
254 : : tf_dir_2_str(parms->dir),
255 : : parms->type,
256 : : index);
257 : : }
258 : : return rc;
259 : : }
260 : :
261 : : uint32_t
262 : 0 : tf_em_get_key_mask(int num_entries)
263 : : {
264 : 0 : uint32_t mask = num_entries - 1;
265 : :
266 [ # # ]: 0 : if (num_entries & TF_EM_MAX_MASK)
267 : : return 0;
268 : :
269 [ # # ]: 0 : if (num_entries > TF_EM_MAX_ENTRY)
270 : 0 : return 0;
271 : :
272 : : return mask;
273 : : }
274 : :
275 : : void
276 : 0 : tf_em_create_key_entry(struct cfa_p4_eem_entry_hdr *result,
277 : : uint8_t *in_key,
278 : : struct cfa_p4_eem_64b_entry *key_entry)
279 : : {
280 : 0 : key_entry->hdr.word1 = result->word1;
281 : 0 : key_entry->hdr.pointer = result->pointer;
282 : 0 : memcpy(key_entry->key, in_key, TF_P4_HW_EM_KEY_MAX_SIZE + 4);
283 : 0 : }
284 : :
285 : : /**
286 : : * Return the number of page table pages needed to
287 : : * reference the given number of next level pages.
288 : : *
289 : : * [in] num_pages
290 : : * Number of EM pages
291 : : *
292 : : * [in] page_size
293 : : * Size of each EM page
294 : : *
295 : : * Returns:
296 : : * Number of EM page table pages
297 : : */
298 : : static uint32_t
299 : : tf_em_page_tbl_pgcnt(uint32_t num_pages,
300 : : uint32_t page_size)
301 : : {
302 [ # # # # : 0 : return roundup(num_pages, MAX_PAGE_PTRS(page_size)) /
# # ]
303 : : MAX_PAGE_PTRS(page_size);
304 : : return 0;
305 : : }
306 : :
307 : : /**
308 : : * Given the number of data pages, page_size and the maximum
309 : : * number of page table levels (already determined), size
310 : : * the number of page table pages required at each level.
311 : : *
312 : : * [in] max_lvl
313 : : * Max number of levels
314 : : *
315 : : * [in] num_data_pages
316 : : * Number of EM data pages
317 : : *
318 : : * [in] page_size
319 : : * Size of an EM page
320 : : *
321 : : * [out] *page_cnt
322 : : * EM page count
323 : : */
324 : : static void
325 : 0 : tf_em_size_page_tbls(int max_lvl,
326 : : uint64_t num_data_pages,
327 : : uint32_t page_size,
328 : : uint32_t *page_cnt)
329 : : {
330 [ # # ]: 0 : if (max_lvl == TF_PT_LVL_0) {
331 : 0 : page_cnt[TF_PT_LVL_0] = num_data_pages;
332 [ # # ]: 0 : } else if (max_lvl == TF_PT_LVL_1) {
333 [ # # ]: 0 : page_cnt[TF_PT_LVL_1] = num_data_pages;
334 : 0 : page_cnt[TF_PT_LVL_0] =
335 : : tf_em_page_tbl_pgcnt(page_cnt[TF_PT_LVL_1], page_size);
336 [ # # ]: 0 : } else if (max_lvl == TF_PT_LVL_2) {
337 [ # # ]: 0 : page_cnt[TF_PT_LVL_2] = num_data_pages;
338 [ # # ]: 0 : page_cnt[TF_PT_LVL_1] =
339 : : tf_em_page_tbl_pgcnt(page_cnt[TF_PT_LVL_2], page_size);
340 : 0 : page_cnt[TF_PT_LVL_0] =
341 : : tf_em_page_tbl_pgcnt(page_cnt[TF_PT_LVL_1], page_size);
342 : : } else {
343 : : return;
344 : : }
345 : : }
346 : :
347 : : /**
348 : : * Given the page size, size of each data item (entry size),
349 : : * and the total number of entries needed, determine the number
350 : : * of page table levels and the number of data pages required.
351 : : *
352 : : * [in] page_size
353 : : * Page size
354 : : *
355 : : * [in] entry_size
356 : : * Entry size
357 : : *
358 : : * [in] num_entries
359 : : * Number of entries needed
360 : : *
361 : : * [out] num_data_pages
362 : : * Number of pages required
363 : : *
364 : : * Returns:
365 : : * Success - Number of EM page levels required
366 : : * -ENOMEM - Out of memory
367 : : */
368 : : static int
369 : 0 : tf_em_size_page_tbl_lvl(uint32_t page_size,
370 : : uint32_t entry_size,
371 : : uint32_t num_entries,
372 : : uint64_t *num_data_pages)
373 : : {
374 : 0 : uint64_t lvl_data_size = page_size;
375 : : int lvl = TF_PT_LVL_0;
376 : : uint64_t data_size;
377 : :
378 : 0 : *num_data_pages = 0;
379 : 0 : data_size = (uint64_t)num_entries * entry_size;
380 : :
381 [ # # ]: 0 : while (lvl_data_size < data_size) {
382 : 0 : lvl++;
383 : :
384 [ # # ]: 0 : if (lvl == TF_PT_LVL_1)
385 : 0 : lvl_data_size = (uint64_t)MAX_PAGE_PTRS(page_size) *
386 : : page_size;
387 [ # # ]: 0 : else if (lvl == TF_PT_LVL_2)
388 : 0 : lvl_data_size = (uint64_t)MAX_PAGE_PTRS(page_size) *
389 : : MAX_PAGE_PTRS(page_size) * page_size;
390 : : else
391 : : return -ENOMEM;
392 : : }
393 : :
394 [ # # # # ]: 0 : *num_data_pages = roundup(data_size, page_size) / page_size;
395 : :
396 : 0 : return lvl;
397 : : }
398 : :
399 : : /**
400 : : * Size the EM table based on capabilities
401 : : *
402 : : * [in] tbl
403 : : * EM table to size
404 : : *
405 : : * Returns:
406 : : * 0 - Success
407 : : * - EINVAL - Parameter error
408 : : * - ENOMEM - Out of memory
409 : : */
410 : : int
411 : 0 : tf_em_size_table(struct hcapi_cfa_em_table *tbl,
412 : : uint32_t page_size)
413 : : {
414 : : uint64_t num_data_pages;
415 : : uint32_t *page_cnt;
416 : : int max_lvl;
417 : : uint32_t num_entries;
418 : : uint32_t cnt = TF_EM_MIN_ENTRIES;
419 : :
420 : : /* Ignore entry if both size and number are zero */
421 [ # # # # ]: 0 : if (!tbl->entry_size && !tbl->num_entries)
422 : : return 0;
423 : :
424 : : /* If only one is set then error */
425 [ # # # # ]: 0 : if (!tbl->entry_size || !tbl->num_entries)
426 : : return -EINVAL;
427 : :
428 : : /* Determine number of page table levels and the number
429 : : * of data pages needed to process the given eem table.
430 : : */
431 [ # # ]: 0 : if (tbl->type == TF_RECORD_TABLE) {
432 : : /*
433 : : * For action records just a memory size is provided. Work
434 : : * backwards to resolve to number of entries
435 : : */
436 : 0 : num_entries = tbl->num_entries / tbl->entry_size;
437 [ # # ]: 0 : if (num_entries < TF_EM_MIN_ENTRIES) {
438 : : num_entries = TF_EM_MIN_ENTRIES;
439 : : } else {
440 [ # # ]: 0 : while (num_entries > cnt && cnt <= TF_EM_MAX_ENTRIES)
441 : 0 : cnt *= 2;
442 : : num_entries = cnt;
443 : : }
444 : : } else {
445 : : num_entries = tbl->num_entries;
446 : : }
447 : :
448 : 0 : max_lvl = tf_em_size_page_tbl_lvl(page_size,
449 : : tbl->entry_size,
450 : : tbl->num_entries,
451 : : &num_data_pages);
452 [ # # ]: 0 : if (max_lvl < 0) {
453 : 0 : TFP_DRV_LOG(WARNING, "EEM: Failed to size page table levels\n");
454 : 0 : TFP_DRV_LOG(WARNING,
455 : : "table: %d data-sz: %016" PRIu64 " page-sz: %u\n",
456 : : tbl->type, (uint64_t)num_entries * tbl->entry_size,
457 : : page_size);
458 : 0 : return -ENOMEM;
459 : : }
460 : :
461 : 0 : tbl->num_lvl = max_lvl + 1;
462 : 0 : tbl->num_data_pages = num_data_pages;
463 : :
464 : : /* Determine the number of pages needed at each level */
465 : 0 : page_cnt = tbl->page_cnt;
466 : : memset(page_cnt, 0, sizeof(tbl->page_cnt));
467 : 0 : tf_em_size_page_tbls(max_lvl, num_data_pages, page_size,
468 : : page_cnt);
469 : :
470 : 0 : TFP_DRV_LOG(INFO, "EEM: Sized page table: %d\n", tbl->type);
471 : 0 : TFP_DRV_LOG(INFO,
472 : : "EEM: lvls: %d sz: %016" PRIu64 " pgs: %016" PRIu64 \
473 : : " l0: %u l1: %u l2: %u\n",
474 : : max_lvl + 1,
475 : : (uint64_t)num_data_pages * page_size,
476 : : num_data_pages,
477 : : page_cnt[TF_PT_LVL_0],
478 : : page_cnt[TF_PT_LVL_1],
479 : : page_cnt[TF_PT_LVL_2]);
480 : :
481 : 0 : return 0;
482 : : }
483 : :
484 : : /**
485 : : * Validates EM number of entries requested
486 : : *
487 : : * [in] tbl_scope_cb
488 : : * Pointer to table scope control block to be populated
489 : : *
490 : : * [in] parms
491 : : * Pointer to input parameters
492 : : *
493 : : * Returns:
494 : : * 0 - Success
495 : : * -EINVAL - Parameter error
496 : : */
497 : : int
498 : 0 : tf_em_validate_num_entries(struct tf_tbl_scope_cb *tbl_scope_cb,
499 : : struct tf_alloc_tbl_scope_parms *parms)
500 : : {
501 : : uint32_t cnt;
502 : :
503 [ # # ]: 0 : if (parms->rx_mem_size_in_mb != 0) {
504 : 0 : uint32_t key_b = 2 * ((parms->rx_max_key_sz_in_bits / 8) + 1);
505 : 0 : uint32_t action_b = ((parms->rx_max_action_entry_sz_in_bits / 8)
506 : 0 : + 1);
507 : 0 : uint32_t num_entries = (parms->rx_mem_size_in_mb *
508 : 0 : TF_MEGABYTE) / (key_b + action_b);
509 : :
510 [ # # ]: 0 : if (num_entries < TF_EM_MIN_ENTRIES) {
511 : 0 : TFP_DRV_LOG(ERR, "EEM: Insufficient memory requested:"
512 : : "%uMB\n",
513 : : parms->rx_mem_size_in_mb);
514 : 0 : return -EINVAL;
515 : : }
516 : :
517 : : cnt = TF_EM_MIN_ENTRIES;
518 : 0 : while (num_entries > cnt &&
519 [ # # ]: 0 : cnt <= TF_EM_MAX_ENTRIES)
520 : 0 : cnt *= 2;
521 : :
522 [ # # ]: 0 : if (cnt > TF_EM_MAX_ENTRIES) {
523 : 0 : TFP_DRV_LOG(ERR, "EEM: Invalid number of Tx requested: "
524 : : "%u\n",
525 : : (parms->tx_num_flows_in_k * TF_KILOBYTE));
526 : 0 : return -EINVAL;
527 : : }
528 : :
529 : 0 : parms->rx_num_flows_in_k = cnt / TF_KILOBYTE;
530 : : } else {
531 [ # # ]: 0 : if ((parms->rx_num_flows_in_k * TF_KILOBYTE) <
532 : 0 : TF_EM_MIN_ENTRIES ||
533 : : (parms->rx_num_flows_in_k * TF_KILOBYTE) >
534 [ # # ]: 0 : tbl_scope_cb->em_caps[TF_DIR_RX].max_entries_supported) {
535 : 0 : TFP_DRV_LOG(ERR,
536 : : "EEM: Invalid number of Rx flows "
537 : : "requested:%u max:%u\n",
538 : : parms->rx_num_flows_in_k * TF_KILOBYTE,
539 : : tbl_scope_cb->em_caps[TF_DIR_RX].max_entries_supported);
540 : 0 : return -EINVAL;
541 : : }
542 : :
543 : : /* must be a power-of-2 supported value
544 : : * in the range 32K - 128M
545 : : */
546 : : cnt = TF_EM_MIN_ENTRIES;
547 [ # # # # ]: 0 : while ((parms->rx_num_flows_in_k * TF_KILOBYTE) != cnt &&
548 : : cnt <= TF_EM_MAX_ENTRIES)
549 : 0 : cnt *= 2;
550 : :
551 [ # # ]: 0 : if (cnt > TF_EM_MAX_ENTRIES) {
552 : 0 : TFP_DRV_LOG(ERR,
553 : : "EEM: Invalid number of Rx requested: %u\n",
554 : : (parms->rx_num_flows_in_k * TF_KILOBYTE));
555 : 0 : return -EINVAL;
556 : : }
557 : : }
558 : :
559 [ # # ]: 0 : if (parms->tx_mem_size_in_mb != 0) {
560 : 0 : uint32_t key_b = 2 * (parms->tx_max_key_sz_in_bits / 8 + 1);
561 : 0 : uint32_t action_b = ((parms->tx_max_action_entry_sz_in_bits / 8)
562 : 0 : + 1);
563 : 0 : uint32_t num_entries = (parms->tx_mem_size_in_mb *
564 : : (TF_KILOBYTE * TF_KILOBYTE)) /
565 : 0 : (key_b + action_b);
566 : :
567 [ # # ]: 0 : if (num_entries < TF_EM_MIN_ENTRIES) {
568 : 0 : TFP_DRV_LOG(ERR,
569 : : "EEM: Insufficient memory requested:%uMB\n",
570 : : parms->rx_mem_size_in_mb);
571 : 0 : return -EINVAL;
572 : : }
573 : :
574 : : cnt = TF_EM_MIN_ENTRIES;
575 : 0 : while (num_entries > cnt &&
576 [ # # ]: 0 : cnt <= TF_EM_MAX_ENTRIES)
577 : 0 : cnt *= 2;
578 : :
579 [ # # ]: 0 : if (cnt > TF_EM_MAX_ENTRIES) {
580 : 0 : TFP_DRV_LOG(ERR,
581 : : "EEM: Invalid number of Tx requested: %u\n",
582 : : (parms->tx_num_flows_in_k * TF_KILOBYTE));
583 : 0 : return -EINVAL;
584 : : }
585 : :
586 : 0 : parms->tx_num_flows_in_k = cnt / TF_KILOBYTE;
587 : : } else {
588 [ # # ]: 0 : if ((parms->tx_num_flows_in_k * TF_KILOBYTE) <
589 : 0 : TF_EM_MIN_ENTRIES ||
590 : : (parms->tx_num_flows_in_k * TF_KILOBYTE) >
591 [ # # ]: 0 : tbl_scope_cb->em_caps[TF_DIR_TX].max_entries_supported) {
592 : 0 : TFP_DRV_LOG(ERR,
593 : : "EEM: Invalid number of Tx flows "
594 : : "requested:%u max:%u\n",
595 : : (parms->tx_num_flows_in_k * TF_KILOBYTE),
596 : : tbl_scope_cb->em_caps[TF_DIR_TX].max_entries_supported);
597 : 0 : return -EINVAL;
598 : : }
599 : :
600 : : cnt = TF_EM_MIN_ENTRIES;
601 [ # # # # ]: 0 : while ((parms->tx_num_flows_in_k * TF_KILOBYTE) != cnt &&
602 : : cnt <= TF_EM_MAX_ENTRIES)
603 : 0 : cnt *= 2;
604 : :
605 [ # # ]: 0 : if (cnt > TF_EM_MAX_ENTRIES) {
606 : 0 : TFP_DRV_LOG(ERR,
607 : : "EEM: Invalid number of Tx requested: %u\n",
608 : : (parms->tx_num_flows_in_k * TF_KILOBYTE));
609 : 0 : return -EINVAL;
610 : : }
611 : : }
612 : :
613 [ # # ]: 0 : if (parms->rx_num_flows_in_k != 0 &&
614 [ # # ]: 0 : parms->rx_max_key_sz_in_bits / 8 == 0) {
615 : 0 : TFP_DRV_LOG(ERR,
616 : : "EEM: Rx key size required: %u\n",
617 : : (parms->rx_max_key_sz_in_bits));
618 : 0 : return -EINVAL;
619 : : }
620 : :
621 [ # # ]: 0 : if (parms->tx_num_flows_in_k != 0 &&
622 [ # # ]: 0 : parms->tx_max_key_sz_in_bits / 8 == 0) {
623 : 0 : TFP_DRV_LOG(ERR,
624 : : "EEM: Tx key size required: %u\n",
625 : : (parms->tx_max_key_sz_in_bits));
626 : 0 : return -EINVAL;
627 : : }
628 : : /* Rx */
629 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY0_TABLE].num_entries =
630 : 0 : parms->rx_num_flows_in_k * TF_KILOBYTE;
631 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY0_TABLE].entry_size =
632 : 0 : parms->rx_max_key_sz_in_bits / 8;
633 : :
634 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY1_TABLE].num_entries =
635 : : parms->rx_num_flows_in_k * TF_KILOBYTE;
636 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY1_TABLE].entry_size =
637 : : parms->rx_max_key_sz_in_bits / 8;
638 : :
639 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_RECORD_TABLE].num_entries =
640 : : parms->rx_num_flows_in_k * TF_KILOBYTE;
641 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_RECORD_TABLE].entry_size =
642 : 0 : parms->rx_max_action_entry_sz_in_bits / 8;
643 : :
644 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_EFC_TABLE].num_entries =
645 : : 0;
646 : :
647 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_ACTION_TABLE].num_entries =
648 : : parms->rx_num_flows_in_k * TF_KILOBYTE;
649 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_ACTION_TABLE].entry_size =
650 : : parms->rx_max_action_entry_sz_in_bits / 8;
651 : :
652 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_EM_LKUP_TABLE].num_entries =
653 : : parms->rx_num_flows_in_k * TF_KILOBYTE;
654 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_EM_LKUP_TABLE].entry_size =
655 : : parms->rx_max_key_sz_in_bits / 8;
656 : :
657 : : /* Tx */
658 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY0_TABLE].num_entries =
659 : 0 : parms->tx_num_flows_in_k * TF_KILOBYTE;
660 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY0_TABLE].entry_size =
661 : 0 : parms->tx_max_key_sz_in_bits / 8;
662 : :
663 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY1_TABLE].num_entries =
664 : : parms->tx_num_flows_in_k * TF_KILOBYTE;
665 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY1_TABLE].entry_size =
666 : : parms->tx_max_key_sz_in_bits / 8;
667 : :
668 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_RECORD_TABLE].num_entries =
669 : : parms->tx_num_flows_in_k * TF_KILOBYTE;
670 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_RECORD_TABLE].entry_size =
671 : 0 : parms->tx_max_action_entry_sz_in_bits / 8;
672 : :
673 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_EFC_TABLE].num_entries =
674 : : 0;
675 : :
676 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_ACTION_TABLE].num_entries =
677 : : parms->rx_num_flows_in_k * TF_KILOBYTE;
678 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_ACTION_TABLE].entry_size =
679 : : parms->tx_max_action_entry_sz_in_bits / 8;
680 : :
681 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_EM_LKUP_TABLE].num_entries =
682 : : parms->rx_num_flows_in_k * TF_KILOBYTE;
683 : 0 : tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_EM_LKUP_TABLE].entry_size =
684 : : parms->tx_max_key_sz_in_bits / 8;
685 : :
686 : 0 : return 0;
687 : : }
688 : :
689 : : /** insert EEM entry API
690 : : *
691 : : * returns:
692 : : * 0
693 : : * TF_ERR - unable to get lock
694 : : *
695 : : * insert callback returns:
696 : : * 0
697 : : * TF_ERR_EM_DUP - key is already in table
698 : : */
699 : : static int
700 : 0 : tf_insert_eem_entry(struct tf_dev_info *dev,
701 : : struct tf_tbl_scope_cb *tbl_scope_cb,
702 : : struct tf_insert_em_entry_parms *parms)
703 : : {
704 : : uint32_t mask;
705 : : uint32_t key0_hash;
706 : : uint32_t key1_hash;
707 : : uint32_t key0_index;
708 : : uint32_t key1_index;
709 : : struct cfa_p4_eem_64b_entry key_entry;
710 : : uint32_t index;
711 : : enum hcapi_cfa_em_table_type table_type;
712 : : uint32_t gfid;
713 : : struct hcapi_cfa_hwop op;
714 : : struct hcapi_cfa_key_tbl key_tbl;
715 : : struct hcapi_cfa_key_data key_obj;
716 : : struct hcapi_cfa_key_loc key_loc;
717 : : uint64_t big_hash;
718 : : int rc;
719 : :
720 : : /* Get mask to use on hash */
721 : 0 : mask = tf_em_get_key_mask(tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY0_TABLE].num_entries);
722 : :
723 [ # # ]: 0 : if (!mask)
724 : : return -EINVAL;
725 : :
726 [ # # ]: 0 : if (dev->ops->tf_dev_cfa_key_hash == NULL)
727 : : return -EINVAL;
728 : :
729 : 0 : big_hash = dev->ops->tf_dev_cfa_key_hash((uint64_t *)parms->key,
730 : : (TF_P4_HW_EM_KEY_MAX_SIZE + 4) * 8);
731 : 0 : key0_hash = (uint32_t)(big_hash >> 32);
732 : 0 : key1_hash = (uint32_t)(big_hash & 0xFFFFFFFF);
733 : :
734 : 0 : key0_index = key0_hash & mask;
735 : 0 : key1_index = key1_hash & mask;
736 : :
737 : : /*
738 : : * Use the "result" arg to populate all of the key entry then
739 : : * store the byte swapped "raw" entry in a local copy ready
740 : : * for insertion in to the table.
741 : : */
742 : 0 : tf_em_create_key_entry((struct cfa_p4_eem_entry_hdr *)parms->em_record,
743 : : ((uint8_t *)parms->key),
744 : : &key_entry);
745 : :
746 : : /*
747 : : * Try to add to Key0 table, if that does not work then
748 : : * try the key1 table.
749 : : */
750 : : index = key0_index;
751 : 0 : op.opcode = HCAPI_CFA_HWOPS_ADD;
752 : 0 : key_tbl.base0 =
753 : 0 : (uint8_t *)&tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY0_TABLE];
754 : 0 : key_tbl.page_size = TF_EM_PAGE_SIZE;
755 : 0 : key_obj.offset = index * TF_P4_EM_KEY_RECORD_SIZE;
756 : 0 : key_obj.data = (uint8_t *)&key_entry;
757 : 0 : key_obj.size = TF_P4_EM_KEY_RECORD_SIZE;
758 : :
759 : 0 : rc = cfa_p4_devops.hcapi_cfa_key_hw_op(&op,
760 : : &key_tbl,
761 : : &key_obj,
762 : : &key_loc);
763 : :
764 [ # # ]: 0 : if (rc == 0) {
765 : : table_type = TF_KEY0_TABLE;
766 : : } else {
767 : : index = key1_index;
768 : :
769 : 0 : key_tbl.base0 =
770 : 0 : (uint8_t *)&tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY1_TABLE];
771 : 0 : key_obj.offset = index * TF_P4_EM_KEY_RECORD_SIZE;
772 : :
773 : 0 : rc = cfa_p4_devops.hcapi_cfa_key_hw_op(&op,
774 : : &key_tbl,
775 : : &key_obj,
776 : : &key_loc);
777 [ # # ]: 0 : if (rc != 0)
778 : : return rc;
779 : :
780 : : table_type = TF_KEY1_TABLE;
781 : : }
782 : :
783 : 0 : TF_SET_GFID(gfid,
784 : : index,
785 : : table_type);
786 : 0 : TF_SET_FLOW_ID(parms->flow_id,
787 : : gfid,
788 : : TF_GFID_TABLE_EXTERNAL,
789 : : parms->dir);
790 : 0 : TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
791 : : 0,
792 : : 0,
793 : : 0,
794 : : index,
795 : : 0,
796 : : table_type);
797 : :
798 : 0 : return 0;
799 : : }
800 : :
801 : : /** delete EEM hash entry API
802 : : *
803 : : * returns:
804 : : * 0
805 : : * -EINVAL - parameter error
806 : : * TF_NO_SESSION - bad session ID
807 : : * TF_ERR_TBL_SCOPE - invalid table scope
808 : : * TF_ERR_TBL_IF - invalid table interface
809 : : *
810 : : * insert callback returns
811 : : * 0
812 : : * TF_NO_EM_MATCH - entry not found
813 : : */
814 : : static int
815 : : tf_delete_eem_entry(struct tf_tbl_scope_cb *tbl_scope_cb,
816 : : struct tf_delete_em_entry_parms *parms)
817 : : {
818 : : enum hcapi_cfa_em_table_type hash_type;
819 : : uint32_t index;
820 : : struct hcapi_cfa_hwop op;
821 : : struct hcapi_cfa_key_tbl key_tbl;
822 : : struct hcapi_cfa_key_data key_obj;
823 : : struct hcapi_cfa_key_loc key_loc;
824 : : int rc;
825 : :
826 : 0 : TF_GET_HASH_TYPE_FROM_FLOW_HANDLE(parms->flow_handle, hash_type);
827 : 0 : TF_GET_INDEX_FROM_FLOW_HANDLE(parms->flow_handle, index);
828 : :
829 : 0 : op.opcode = HCAPI_CFA_HWOPS_DEL;
830 : 0 : key_tbl.base0 =
831 : 0 : (uint8_t *)&tbl_scope_cb->em_ctx_info[parms->dir].em_tables
832 : 0 : [(hash_type == 0 ? TF_KEY0_TABLE : TF_KEY1_TABLE)];
833 : 0 : key_tbl.page_size = TF_EM_PAGE_SIZE;
834 : 0 : key_obj.offset = index * TF_P4_EM_KEY_RECORD_SIZE;
835 : 0 : key_obj.data = NULL;
836 : 0 : key_obj.size = TF_P4_EM_KEY_RECORD_SIZE;
837 : :
838 : 0 : rc = cfa_p4_devops.hcapi_cfa_key_hw_op(&op,
839 : : &key_tbl,
840 : : &key_obj,
841 : : &key_loc);
842 : :
843 : : if (!rc)
844 : : return rc;
845 : :
846 : : return 0;
847 : : }
848 : :
849 : : /** insert EM hash entry API
850 : : *
851 : : * returns:
852 : : * 0 - Success
853 : : * -EINVAL - Error
854 : : */
855 : : int
856 : 0 : tf_em_insert_ext_entry(struct tf *tfp,
857 : : struct tf_insert_em_entry_parms *parms)
858 : : {
859 : : int rc;
860 : : struct tf_tbl_scope_cb *tbl_scope_cb;
861 : : struct tf_session *tfs;
862 : : struct tf_dev_info *dev;
863 : :
864 : 0 : tbl_scope_cb = tf_em_ext_common_tbl_scope_find(tfp, parms->tbl_scope_id);
865 [ # # ]: 0 : if (tbl_scope_cb == NULL) {
866 : 0 : TFP_DRV_LOG(ERR, "Invalid tbl_scope_cb\n");
867 : 0 : return -EINVAL;
868 : : }
869 : :
870 : : /* Retrieve the session information */
871 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
872 [ # # ]: 0 : if (rc)
873 : : return rc;
874 : :
875 : : /* Retrieve the device information */
876 : 0 : rc = tf_session_get_device(tfs, &dev);
877 [ # # ]: 0 : if (rc)
878 : : return rc;
879 : :
880 : 0 : return tf_insert_eem_entry
881 : : (dev,
882 : : tbl_scope_cb,
883 : : parms);
884 : : }
885 : :
886 : : /** Delete EM hash entry API
887 : : *
888 : : * returns:
889 : : * 0 - Success
890 : : * -EINVAL - Error
891 : : */
892 : : int
893 : 0 : tf_em_delete_ext_entry(struct tf *tfp,
894 : : struct tf_delete_em_entry_parms *parms)
895 : : {
896 : : struct tf_tbl_scope_cb *tbl_scope_cb;
897 : :
898 : 0 : tbl_scope_cb = tf_em_ext_common_tbl_scope_find(tfp, parms->tbl_scope_id);
899 [ # # ]: 0 : if (tbl_scope_cb == NULL) {
900 : 0 : TFP_DRV_LOG(ERR, "Invalid tbl_scope_cb\n");
901 : 0 : return -EINVAL;
902 : : }
903 : :
904 : 0 : return tf_delete_eem_entry(tbl_scope_cb, parms);
905 : : }
906 : :
907 : : int
908 : 0 : tf_em_ext_common_bind(struct tf *tfp,
909 : : struct tf_em_cfg_parms *parms)
910 : : {
911 : : int rc;
912 : : int i;
913 : 0 : struct tf_rm_create_db_parms db_cfg = { 0 };
914 : : struct em_ext_db *ext_db;
915 : : struct tfp_calloc_parms cparms;
916 : :
917 [ # # ]: 0 : TF_CHECK_PARMS2(tfp, parms);
918 : :
919 : 0 : cparms.nitems = 1;
920 : 0 : cparms.size = sizeof(struct em_ext_db);
921 : 0 : cparms.alignment = 0;
922 [ # # ]: 0 : if (tfp_calloc(&cparms) != 0) {
923 : 0 : TFP_DRV_LOG(ERR, "em_ext_db alloc error %s\n",
924 : : strerror(ENOMEM));
925 : 0 : return -ENOMEM;
926 : : }
927 : :
928 : 0 : ext_db = cparms.mem_va;
929 : 0 : ll_init(&ext_db->tbl_scope_ll);
930 [ # # ]: 0 : for (i = 0; i < TF_DIR_MAX; i++)
931 : 0 : ext_db->eem_db[i] = NULL;
932 : 0 : tf_session_set_em_ext_db(tfp, ext_db);
933 : :
934 : 0 : db_cfg.module = TF_MODULE_TYPE_EM;
935 : 0 : db_cfg.num_elements = parms->num_elements;
936 : 0 : db_cfg.cfg = parms->cfg;
937 : :
938 [ # # ]: 0 : for (i = 0; i < TF_DIR_MAX; i++) {
939 : 0 : db_cfg.dir = i;
940 : 0 : db_cfg.alloc_cnt = parms->resources->em_cnt[i].cnt;
941 : :
942 : : /* Check if we got any request to support EEM, if so
943 : : * we build an EM Ext DB holding Table Scopes.
944 : : */
945 [ # # ]: 0 : if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_TBL_SCOPE] == 0)
946 : 0 : continue;
947 : :
948 : 0 : db_cfg.rm_db = (void *)&ext_db->eem_db[i];
949 : 0 : rc = tf_rm_create_db(tfp, &db_cfg);
950 [ # # ]: 0 : if (rc) {
951 : 0 : TFP_DRV_LOG(ERR,
952 : : "%s: EM Ext DB creation failed\n",
953 : : tf_dir_2_str(i));
954 : :
955 : 0 : return rc;
956 : : }
957 : : }
958 : :
959 : 0 : mem_type = parms->mem_type;
960 : :
961 : 0 : return 0;
962 : : }
963 : :
964 : : int
965 : 0 : tf_em_ext_common_unbind(struct tf *tfp)
966 : : {
967 : : int rc;
968 : : int i;
969 : 0 : struct tf_rm_free_db_parms fparms = { 0 };
970 : : struct em_ext_db *ext_db = NULL;
971 : 0 : struct tf_session *tfs = NULL;
972 : : struct tf_dev_info *dev;
973 : : struct ll_entry *entry;
974 : : struct tf_tbl_scope_cb *tbl_scope_cb = NULL;
975 : 0 : void *ext_ptr = NULL;
976 : 0 : struct tf_free_tbl_scope_parms tparms = { 0 };
977 : :
978 [ # # ]: 0 : TF_CHECK_PARMS1(tfp);
979 : :
980 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
981 [ # # ]: 0 : if (rc) {
982 : 0 : TFP_DRV_LOG(ERR, "Failed to get tf_session, rc:%s\n",
983 : : strerror(-rc));
984 : 0 : return rc;
985 : : }
986 : :
987 : : /* Retrieve the device information */
988 : 0 : rc = tf_session_get_device(tfs, &dev);
989 [ # # ]: 0 : if (rc) {
990 : 0 : TFP_DRV_LOG(ERR,
991 : : "Failed to lookup device, rc:%s\n",
992 : : strerror(-rc));
993 : 0 : return rc;
994 : : }
995 : :
996 : 0 : rc = tf_session_get_em_ext_db(tfp, &ext_ptr);
997 [ # # ]: 0 : if (rc) {
998 : 0 : TFP_DRV_LOG(ERR,
999 : : "Failed to get em_ext_db from session, rc:%s\n",
1000 : : strerror(-rc));
1001 : 0 : return rc;
1002 : : }
1003 : :
1004 : 0 : ext_db = (struct em_ext_db *)ext_ptr;
1005 [ # # ]: 0 : if (ext_db != NULL) {
1006 : 0 : entry = ext_db->tbl_scope_ll.head;
1007 [ # # ]: 0 : while (entry != NULL) {
1008 : : tbl_scope_cb = (struct tf_tbl_scope_cb *)entry;
1009 : 0 : entry = entry->next;
1010 : 0 : tparms.tbl_scope_id =
1011 : 0 : tbl_scope_cb->tbl_scope_id;
1012 : :
1013 [ # # ]: 0 : if (dev->ops->tf_dev_free_tbl_scope) {
1014 : 0 : dev->ops->tf_dev_free_tbl_scope(tfp,
1015 : : &tparms);
1016 : : } else {
1017 : : /* should not reach here */
1018 : 0 : ll_delete(&ext_db->tbl_scope_ll,
1019 : : &tbl_scope_cb->ll_entry);
1020 : 0 : tfp_free(tbl_scope_cb);
1021 : : }
1022 : : }
1023 : :
1024 [ # # ]: 0 : for (i = 0; i < TF_DIR_MAX; i++) {
1025 [ # # ]: 0 : if (ext_db->eem_db[i] == NULL)
1026 : 0 : continue;
1027 : :
1028 : 0 : fparms.dir = i;
1029 : 0 : fparms.rm_db = ext_db->eem_db[i];
1030 : 0 : rc = tf_rm_free_db(tfp, &fparms);
1031 [ # # ]: 0 : if (rc)
1032 : 0 : return rc;
1033 : :
1034 : 0 : ext_db->eem_db[i] = NULL;
1035 : : }
1036 : :
1037 : 0 : tfp_free(ext_db);
1038 : : }
1039 : :
1040 : 0 : tf_session_set_em_ext_db(tfp, NULL);
1041 : :
1042 : 0 : return 0;
1043 : : }
1044 : :
1045 : : /**
1046 : : * Sets the specified external table type element.
1047 : : *
1048 : : * This API sets the specified element data
1049 : : *
1050 : : * [in] tfp
1051 : : * Pointer to TF handle
1052 : : *
1053 : : * [in] parms
1054 : : * Pointer to table set parameters
1055 : : *
1056 : : * Returns
1057 : : * - (0) if successful.
1058 : : * - (-EINVAL) on failure.
1059 : : */
1060 : 0 : int tf_tbl_ext_common_set(struct tf *tfp,
1061 : : struct tf_tbl_set_parms *parms)
1062 : : {
1063 : : int rc = 0;
1064 : : struct tf_tbl_scope_cb *tbl_scope_cb;
1065 : : uint32_t tbl_scope_id;
1066 : : struct hcapi_cfa_hwop op;
1067 : : struct hcapi_cfa_key_tbl key_tbl;
1068 : : struct hcapi_cfa_key_data key_obj;
1069 : : struct hcapi_cfa_key_loc key_loc;
1070 : :
1071 [ # # ]: 0 : TF_CHECK_PARMS2(tfp, parms);
1072 : :
1073 [ # # ]: 0 : if (parms->data == NULL) {
1074 : 0 : TFP_DRV_LOG(ERR,
1075 : : "%s, invalid parms->data\n",
1076 : : tf_dir_2_str(parms->dir));
1077 : 0 : return -EINVAL;
1078 : : }
1079 : :
1080 : 0 : tbl_scope_id = parms->tbl_scope_id;
1081 : :
1082 [ # # ]: 0 : if (tbl_scope_id == TF_TBL_SCOPE_INVALID) {
1083 : 0 : TFP_DRV_LOG(ERR,
1084 : : "%s, Table scope not allocated\n",
1085 : : tf_dir_2_str(parms->dir));
1086 : 0 : return -EINVAL;
1087 : : }
1088 : :
1089 : 0 : tbl_scope_cb = tf_em_ext_common_tbl_scope_find(tfp, tbl_scope_id);
1090 [ # # ]: 0 : if (tbl_scope_cb == NULL) {
1091 : 0 : TFP_DRV_LOG(ERR,
1092 : : "%s, table scope error\n",
1093 : : tf_dir_2_str(parms->dir));
1094 : 0 : return -EINVAL;
1095 : : }
1096 : :
1097 : 0 : op.opcode = HCAPI_CFA_HWOPS_PUT;
1098 : 0 : key_tbl.base0 =
1099 : 0 : (uint8_t *)&tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_RECORD_TABLE];
1100 : 0 : key_tbl.page_size = TF_EM_PAGE_SIZE;
1101 : 0 : key_obj.offset = parms->idx;
1102 : 0 : key_obj.data = parms->data;
1103 : 0 : key_obj.size = parms->data_sz_in_bytes;
1104 : :
1105 : 0 : rc = cfa_p4_devops.hcapi_cfa_key_hw_op(&op,
1106 : : &key_tbl,
1107 : : &key_obj,
1108 : : &key_loc);
1109 : :
1110 : 0 : return rc;
1111 : : }
1112 : :
1113 : : int
1114 : 0 : tf_em_ext_common_alloc(struct tf *tfp,
1115 : : struct tf_alloc_tbl_scope_parms *parms)
1116 : : {
1117 : 0 : return tf_em_ext_alloc(tfp, parms);
1118 : : }
1119 : :
1120 : : int
1121 : 0 : tf_em_ext_common_free(struct tf *tfp,
1122 : : struct tf_free_tbl_scope_parms *parms)
1123 : : {
1124 : 0 : return tf_em_ext_free(tfp, parms);
1125 : : }
1126 : :
1127 : 0 : int tf_em_ext_map_tbl_scope(struct tf *tfp,
1128 : : struct tf_map_tbl_scope_parms *parms)
1129 : : {
1130 : : int rc = 0;
1131 : : struct tf_session *tfs;
1132 : : struct tf_tbl_scope_cb *tbl_scope_cb;
1133 : 0 : struct tf_global_cfg_parms gcfg_parms = { 0 };
1134 : : struct tfp_calloc_parms aparms;
1135 : : uint32_t *data, *mask;
1136 : : uint32_t sz_in_bytes = 8;
1137 : : struct tf_dev_info *dev;
1138 : :
1139 : : /* Retrieve the session information */
1140 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
1141 [ # # ]: 0 : if (rc)
1142 : : return rc;
1143 : :
1144 : : /* Retrieve the device information */
1145 : 0 : rc = tf_session_get_device(tfs, &dev);
1146 [ # # ]: 0 : if (rc)
1147 : : return rc;
1148 : :
1149 : 0 : tbl_scope_cb = tf_em_ext_common_tbl_scope_find(tfp, parms->tbl_scope_id);
1150 [ # # ]: 0 : if (tbl_scope_cb == NULL) {
1151 : 0 : TFP_DRV_LOG(ERR, "Invalid tbl_scope_cb tbl_scope_id(%d)\n",
1152 : : parms->tbl_scope_id);
1153 : 0 : return -EINVAL;
1154 : : }
1155 : :
1156 [ # # ]: 0 : if (dev->ops->tf_dev_map_tbl_scope == NULL) {
1157 : : rc = -EOPNOTSUPP;
1158 : 0 : TFP_DRV_LOG(ERR,
1159 : : "Map table scope operation not supported, rc:%s\n",
1160 : : strerror(-rc));
1161 : 0 : return rc;
1162 : : }
1163 : :
1164 : 0 : aparms.nitems = 2;
1165 : 0 : aparms.size = sizeof(uint32_t);
1166 : 0 : aparms.alignment = 0;
1167 : :
1168 [ # # ]: 0 : if (tfp_calloc(&aparms) != 0) {
1169 : 0 : TFP_DRV_LOG(ERR, "Map tbl scope alloc data error %s\n",
1170 : : strerror(ENOMEM));
1171 : 0 : return -ENOMEM;
1172 : : }
1173 : 0 : data = aparms.mem_va;
1174 : :
1175 [ # # ]: 0 : if (tfp_calloc(&aparms) != 0) {
1176 : 0 : TFP_DRV_LOG(ERR, "Map tbl scope alloc mask error %s\n",
1177 : : strerror(ENOMEM));
1178 : : rc = -ENOMEM;
1179 : 0 : goto clean;
1180 : : }
1181 : 0 : mask = aparms.mem_va;
1182 : :
1183 : 0 : rc = dev->ops->tf_dev_map_parif(tfp, parms->parif_bitmask,
1184 : 0 : tbl_scope_cb->pf,
1185 : : (uint8_t *)data, (uint8_t *)mask,
1186 : : sz_in_bytes);
1187 : :
1188 [ # # ]: 0 : if (rc) {
1189 : 0 : TFP_DRV_LOG(ERR,
1190 : : "Map table scope config failure, rc:%s\n",
1191 : : strerror(-rc));
1192 : 0 : goto cleaner;
1193 : : }
1194 : :
1195 : : /* Note that TF_GLOBAL_CFG_INTERNAL_PARIF_2_PF is same as below enum */
1196 : 0 : gcfg_parms.type = TF_GLOBAL_CFG_TYPE_MAX;
1197 : 0 : gcfg_parms.offset = 0;
1198 : 0 : gcfg_parms.config = (uint8_t *)data;
1199 : 0 : gcfg_parms.config_mask = (uint8_t *)mask;
1200 : 0 : gcfg_parms.config_sz_in_bytes = sizeof(uint64_t);
1201 : :
1202 : 0 : rc = tf_msg_set_global_cfg(tfp, &gcfg_parms);
1203 [ # # ]: 0 : if (rc) {
1204 : 0 : TFP_DRV_LOG(ERR,
1205 : : "Map tbl scope, set failed, rc:%s\n",
1206 : : strerror(-rc));
1207 : : }
1208 : 0 : cleaner:
1209 : 0 : tfp_free(mask);
1210 : 0 : clean:
1211 : 0 : tfp_free(data);
1212 : :
1213 : 0 : return rc;
1214 : : }
|