1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2020 Broadcom
9 #include <rte_common.h>
10 #include <rte_errno.h>
15 #include "tf_common.h"
17 #include "tf_em_common.h"
21 #include "tf_ext_flow_handle.h"
25 #define PTU_PTE_VALID 0x1UL
26 #define PTU_PTE_LAST 0x2UL
27 #define PTU_PTE_NEXT_TO_LAST 0x4UL
29 /* Number of pointers per page_size */
30 #define MAX_PAGE_PTRS(page_size) ((page_size) / sizeof(void *))
35 extern void *eem_db[TF_DIR_MAX];
37 extern struct tf_tbl_scope_cb tbl_scopes[TF_NUM_TBL_SCOPE];
40 * Function to free a page table
43 * Pointer to the page table to free
46 tf_em_free_pg_tbl(struct hcapi_cfa_em_page_tbl *tp)
50 for (i = 0; i < tp->pg_count; i++) {
51 if (!tp->pg_va_tbl[i]) {
53 "No mapping for page: %d table: %016" PRIu64 "\n",
55 (uint64_t)(uintptr_t)tp);
59 tfp_free(tp->pg_va_tbl[i]);
60 tp->pg_va_tbl[i] = NULL;
64 tfp_free(tp->pg_va_tbl);
66 tfp_free(tp->pg_pa_tbl);
71 * Function to free an EM table
74 * Pointer to the EM table to free
77 tf_em_free_page_table(struct hcapi_cfa_em_table *tbl)
79 struct hcapi_cfa_em_page_tbl *tp;
82 for (i = 0; i < tbl->num_lvl; i++) {
85 "EEM: Freeing page table: size %u lvl %d cnt %u\n",
90 tf_em_free_pg_tbl(tp);
96 tbl->num_data_pages = 0;
100 * Allocation of page tables
103 * Pointer to a TruFlow handle
106 * Page count to allocate
113 * -ENOMEM - Out of memory
116 tf_em_alloc_pg_tbl(struct hcapi_cfa_em_page_tbl *tp,
121 struct tfp_calloc_parms parms;
123 parms.nitems = pg_count;
124 parms.size = sizeof(void *);
127 if (tfp_calloc(&parms) != 0)
130 tp->pg_va_tbl = parms.mem_va;
132 if (tfp_calloc(&parms) != 0) {
133 tfp_free(tp->pg_va_tbl);
137 tp->pg_pa_tbl = parms.mem_va;
140 tp->pg_size = pg_size;
142 for (i = 0; i < pg_count; i++) {
144 parms.size = pg_size;
145 parms.alignment = TF_EM_PAGE_ALIGNMENT;
147 if (tfp_calloc(&parms) != 0)
150 tp->pg_pa_tbl[i] = (uintptr_t)parms.mem_pa;
151 tp->pg_va_tbl[i] = parms.mem_va;
153 memset(tp->pg_va_tbl[i], 0, pg_size);
160 tf_em_free_pg_tbl(tp);
165 * Allocates EM page tables
168 * Table to allocate pages for
172 * -ENOMEM - Out of memory
175 tf_em_alloc_page_table(struct hcapi_cfa_em_table *tbl)
177 struct hcapi_cfa_em_page_tbl *tp;
182 for (i = 0; i < tbl->num_lvl; i++) {
183 tp = &tbl->pg_tbl[i];
185 rc = tf_em_alloc_pg_tbl(tp,
190 "Failed to allocate page table: lvl: %d, rc:%s\n",
196 for (j = 0; j < tp->pg_count; j++) {
198 "EEM: Allocated page table: size %u lvl %d cnt"
203 (void *)(uintptr_t)tp->pg_va_tbl[j],
204 (void *)(uintptr_t)tp->pg_pa_tbl[j]);
210 tf_em_free_page_table(tbl);
215 * Links EM page tables
218 * Pointer to page table
221 * Pointer to the next page table
224 * Flag controlling if the page table is last
227 tf_em_link_page_table(struct hcapi_cfa_em_page_tbl *tp,
228 struct hcapi_cfa_em_page_tbl *tp_next,
231 uint64_t *pg_pa = tp_next->pg_pa_tbl;
238 for (i = 0; i < tp->pg_count; i++) {
239 pg_va = tp->pg_va_tbl[i];
241 for (j = 0; j < MAX_PAGE_PTRS(tp->pg_size); j++) {
242 if (k == tp_next->pg_count - 2 && set_pte_last)
243 valid = PTU_PTE_NEXT_TO_LAST | PTU_PTE_VALID;
244 else if (k == tp_next->pg_count - 1 && set_pte_last)
245 valid = PTU_PTE_LAST | PTU_PTE_VALID;
247 valid = PTU_PTE_VALID;
249 pg_va[j] = tfp_cpu_to_le_64(pg_pa[k] | valid);
250 if (++k >= tp_next->pg_count)
257 * Setup a EM page table
260 * Pointer to EM page table
263 tf_em_setup_page_table(struct hcapi_cfa_em_table *tbl)
265 struct hcapi_cfa_em_page_tbl *tp_next;
266 struct hcapi_cfa_em_page_tbl *tp;
267 bool set_pte_last = 0;
270 for (i = 0; i < tbl->num_lvl - 1; i++) {
271 tp = &tbl->pg_tbl[i];
272 tp_next = &tbl->pg_tbl[i + 1];
273 if (i == tbl->num_lvl - 2)
275 tf_em_link_page_table(tp, tp_next, set_pte_last);
278 tbl->l0_addr = tbl->pg_tbl[TF_PT_LVL_0].pg_va_tbl[0];
279 tbl->l0_dma_addr = tbl->pg_tbl[TF_PT_LVL_0].pg_pa_tbl[0];
283 * Unregisters EM Ctx in Firmware
286 * Pointer to a TruFlow handle
289 * Pointer to a table scope control block
292 * Receive or transmit direction
295 tf_em_ctx_unreg(struct tf *tfp,
296 struct tf_tbl_scope_cb *tbl_scope_cb,
299 struct hcapi_cfa_em_ctx_mem_info *ctxp = &tbl_scope_cb->em_ctx_info[dir];
300 struct hcapi_cfa_em_table *tbl;
303 for (i = TF_KEY0_TABLE; i < TF_MAX_TABLE; i++) {
304 tbl = &ctxp->em_tables[i];
306 if (tbl->num_entries != 0 && tbl->entry_size != 0) {
307 tf_msg_em_mem_unrgtr(tfp, &tbl->ctx_id);
308 tf_em_free_page_table(tbl);
314 * Registers EM Ctx in Firmware
317 * Pointer to a TruFlow handle
320 * Pointer to a table scope control block
323 * Receive or transmit direction
327 * -ENOMEM - Out of Memory
330 tf_em_ctx_reg(struct tf *tfp,
331 struct tf_tbl_scope_cb *tbl_scope_cb,
334 struct hcapi_cfa_em_ctx_mem_info *ctxp = &tbl_scope_cb->em_ctx_info[dir];
335 struct hcapi_cfa_em_table *tbl;
339 for (i = TF_KEY0_TABLE; i < TF_MAX_TABLE; i++) {
340 tbl = &ctxp->em_tables[i];
342 if (tbl->num_entries && tbl->entry_size) {
343 rc = tf_em_size_table(tbl, TF_EM_PAGE_SIZE);
348 rc = tf_em_alloc_page_table(tbl);
352 tf_em_setup_page_table(tbl);
353 rc = tf_msg_em_mem_rgtr(tfp,
355 TF_EM_PAGE_SIZE_ENUM,
365 tf_em_ctx_unreg(tfp, tbl_scope_cb, dir);
370 tf_em_ext_alloc(struct tf *tfp, struct tf_alloc_tbl_scope_parms *parms)
374 struct tf_tbl_scope_cb *tbl_scope_cb;
375 struct hcapi_cfa_em_table *em_tables;
376 struct tf_free_tbl_scope_parms free_parms;
377 struct tf_rm_allocate_parms aparms = { 0 };
378 struct tf_rm_free_parms fparms = { 0 };
380 /* Get Table Scope control block from the session pool */
381 aparms.rm_db = eem_db[TF_DIR_RX];
382 aparms.db_index = TF_EM_TBL_TYPE_TBL_SCOPE;
383 aparms.index = (uint32_t *)&parms->tbl_scope_id;
384 rc = tf_rm_allocate(&aparms);
387 "Failed to allocate table scope\n");
391 tbl_scope_cb = &tbl_scopes[parms->tbl_scope_id];
392 tbl_scope_cb->index = parms->tbl_scope_id;
393 tbl_scope_cb->tbl_scope_id = parms->tbl_scope_id;
395 for (dir = 0; dir < TF_DIR_MAX; dir++) {
396 rc = tf_msg_em_qcaps(tfp,
398 &tbl_scope_cb->em_caps[dir]);
401 "EEM: Unable to query for EEM capability,"
409 * Validate and setup table sizes
411 if (tf_em_validate_num_entries(tbl_scope_cb, parms))
414 for (dir = 0; dir < TF_DIR_MAX; dir++) {
416 * Allocate tables and signal configuration to FW
418 rc = tf_em_ctx_reg(tfp, tbl_scope_cb, dir);
421 "EEM: Unable to register for EEM ctx,"
427 em_tables = tbl_scope_cb->em_ctx_info[dir].em_tables;
428 rc = tf_msg_em_cfg(tfp,
429 em_tables[TF_KEY0_TABLE].num_entries,
430 em_tables[TF_KEY0_TABLE].ctx_id,
431 em_tables[TF_KEY1_TABLE].ctx_id,
432 em_tables[TF_RECORD_TABLE].ctx_id,
433 em_tables[TF_EFC_TABLE].ctx_id,
434 parms->hw_flow_cache_flush_timer,
438 "TBL: Unable to configure EEM in firmware"
444 rc = tf_msg_em_op(tfp,
446 HWRM_TF_EXT_EM_OP_INPUT_OP_EXT_EM_ENABLE);
450 "EEM: Unable to enable EEM in firmware"
456 /* Allocate the pool of offsets of the external memory.
457 * Initially, this is a single fixed size pool for all external
458 * actions related to a single table scope.
460 rc = tf_create_tbl_pool_external(dir,
462 em_tables[TF_RECORD_TABLE].num_entries,
463 em_tables[TF_RECORD_TABLE].entry_size);
466 "%s TBL: Unable to allocate idx pools %s\n",
476 free_parms.tbl_scope_id = parms->tbl_scope_id;
477 tf_em_ext_free(tfp, &free_parms);
481 /* Free Table control block */
482 fparms.rm_db = eem_db[TF_DIR_RX];
483 fparms.db_index = TF_EM_TBL_TYPE_TBL_SCOPE;
484 fparms.index = parms->tbl_scope_id;
490 tf_em_ext_free(struct tf *tfp,
491 struct tf_free_tbl_scope_parms *parms)
495 struct tf_tbl_scope_cb *tbl_scope_cb;
496 struct tf_rm_free_parms aparms = { 0 };
498 tbl_scope_cb = tbl_scope_cb_find(parms->tbl_scope_id);
500 if (tbl_scope_cb == NULL) {
501 TFP_DRV_LOG(ERR, "Table scope error\n");
505 /* Free Table control block */
506 aparms.rm_db = eem_db[TF_DIR_RX];
507 aparms.db_index = TF_EM_TBL_TYPE_TBL_SCOPE;
508 aparms.index = parms->tbl_scope_id;
509 rc = tf_rm_free(&aparms);
512 "Failed to free table scope\n");
515 /* free table scope locks */
516 for (dir = 0; dir < TF_DIR_MAX; dir++) {
517 /* Free associated external pools
519 tf_destroy_tbl_pool_external(dir,
523 HWRM_TF_EXT_EM_OP_INPUT_OP_EXT_EM_DISABLE);
525 /* free table scope and all associated resources */
526 tf_em_ctx_unreg(tfp, tbl_scope_cb, dir);
529 tbl_scopes[parms->tbl_scope_id].tbl_scope_id = TF_TBL_SCOPE_INVALID;