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"
26 #define PTU_PTE_VALID 0x1UL
27 #define PTU_PTE_LAST 0x2UL
28 #define PTU_PTE_NEXT_TO_LAST 0x4UL
30 /* Number of pointers per page_size */
31 #define MAX_PAGE_PTRS(page_size) ((page_size) / sizeof(void *))
33 #define TF_EM_PG_SZ_4K (1 << 12)
34 #define TF_EM_PG_SZ_8K (1 << 13)
35 #define TF_EM_PG_SZ_64K (1 << 16)
36 #define TF_EM_PG_SZ_256K (1 << 18)
37 #define TF_EM_PG_SZ_1M (1 << 20)
38 #define TF_EM_PG_SZ_2M (1 << 21)
39 #define TF_EM_PG_SZ_4M (1 << 22)
40 #define TF_EM_PG_SZ_1G (1 << 30)
42 #define TF_EM_CTX_ID_INVALID 0xFFFF
44 #define TF_EM_MIN_ENTRIES (1 << 15) /* 32K */
45 #define TF_EM_MAX_ENTRIES (1 << 27) /* 128M */
50 extern void *eem_db[TF_DIR_MAX];
51 #define TF_EEM_DB_TBL_SCOPE 1
53 extern struct tf_tbl_scope_cb tbl_scopes[TF_NUM_TBL_SCOPE];
56 * Function to free a page table
59 * Pointer to the page table to free
62 tf_em_free_pg_tbl(struct hcapi_cfa_em_page_tbl *tp)
66 for (i = 0; i < tp->pg_count; i++) {
67 if (!tp->pg_va_tbl[i]) {
69 "No mapping for page: %d table: %016" PRIu64 "\n",
71 (uint64_t)(uintptr_t)tp);
75 tfp_free(tp->pg_va_tbl[i]);
76 tp->pg_va_tbl[i] = NULL;
80 tfp_free(tp->pg_va_tbl);
82 tfp_free(tp->pg_pa_tbl);
87 * Function to free an EM table
90 * Pointer to the EM table to free
93 tf_em_free_page_table(struct hcapi_cfa_em_table *tbl)
95 struct hcapi_cfa_em_page_tbl *tp;
98 for (i = 0; i < tbl->num_lvl; i++) {
101 "EEM: Freeing page table: size %u lvl %d cnt %u\n",
106 tf_em_free_pg_tbl(tp);
110 tbl->l0_dma_addr = 0;
112 tbl->num_data_pages = 0;
116 * Allocation of page tables
119 * Pointer to a TruFlow handle
122 * Page count to allocate
129 * -ENOMEM - Out of memory
132 tf_em_alloc_pg_tbl(struct hcapi_cfa_em_page_tbl *tp,
137 struct tfp_calloc_parms parms;
139 parms.nitems = pg_count;
140 parms.size = sizeof(void *);
143 if (tfp_calloc(&parms) != 0)
146 tp->pg_va_tbl = parms.mem_va;
148 if (tfp_calloc(&parms) != 0) {
149 tfp_free(tp->pg_va_tbl);
153 tp->pg_pa_tbl = parms.mem_va;
156 tp->pg_size = pg_size;
158 for (i = 0; i < pg_count; i++) {
160 parms.size = pg_size;
161 parms.alignment = TF_EM_PAGE_ALIGNMENT;
163 if (tfp_calloc(&parms) != 0)
166 tp->pg_pa_tbl[i] = (uintptr_t)parms.mem_pa;
167 tp->pg_va_tbl[i] = parms.mem_va;
169 memset(tp->pg_va_tbl[i], 0, pg_size);
176 tf_em_free_pg_tbl(tp);
181 * Allocates EM page tables
184 * Table to allocate pages for
188 * -ENOMEM - Out of memory
191 tf_em_alloc_page_table(struct hcapi_cfa_em_table *tbl)
193 struct hcapi_cfa_em_page_tbl *tp;
198 for (i = 0; i < tbl->num_lvl; i++) {
199 tp = &tbl->pg_tbl[i];
201 rc = tf_em_alloc_pg_tbl(tp,
206 "Failed to allocate page table: lvl: %d, rc:%s\n",
212 for (j = 0; j < tp->pg_count; j++) {
214 "EEM: Allocated page table: size %u lvl %d cnt"
219 (void *)(uintptr_t)tp->pg_va_tbl[j],
220 (void *)(uintptr_t)tp->pg_pa_tbl[j]);
226 tf_em_free_page_table(tbl);
231 * Links EM page tables
234 * Pointer to page table
237 * Pointer to the next page table
240 * Flag controlling if the page table is last
243 tf_em_link_page_table(struct hcapi_cfa_em_page_tbl *tp,
244 struct hcapi_cfa_em_page_tbl *tp_next,
247 uint64_t *pg_pa = tp_next->pg_pa_tbl;
254 for (i = 0; i < tp->pg_count; i++) {
255 pg_va = tp->pg_va_tbl[i];
257 for (j = 0; j < MAX_PAGE_PTRS(tp->pg_size); j++) {
258 if (k == tp_next->pg_count - 2 && set_pte_last)
259 valid = PTU_PTE_NEXT_TO_LAST | PTU_PTE_VALID;
260 else if (k == tp_next->pg_count - 1 && set_pte_last)
261 valid = PTU_PTE_LAST | PTU_PTE_VALID;
263 valid = PTU_PTE_VALID;
265 pg_va[j] = tfp_cpu_to_le_64(pg_pa[k] | valid);
266 if (++k >= tp_next->pg_count)
273 * Setup a EM page table
276 * Pointer to EM page table
279 tf_em_setup_page_table(struct hcapi_cfa_em_table *tbl)
281 struct hcapi_cfa_em_page_tbl *tp_next;
282 struct hcapi_cfa_em_page_tbl *tp;
283 bool set_pte_last = 0;
286 for (i = 0; i < tbl->num_lvl - 1; i++) {
287 tp = &tbl->pg_tbl[i];
288 tp_next = &tbl->pg_tbl[i + 1];
289 if (i == tbl->num_lvl - 2)
291 tf_em_link_page_table(tp, tp_next, set_pte_last);
294 tbl->l0_addr = tbl->pg_tbl[TF_PT_LVL_0].pg_va_tbl[0];
295 tbl->l0_dma_addr = tbl->pg_tbl[TF_PT_LVL_0].pg_pa_tbl[0];
299 * Given the page size, size of each data item (entry size),
300 * and the total number of entries needed, determine the number
301 * of page table levels and the number of data pages required.
310 * Number of entries needed
312 * [out] num_data_pages
313 * Number of pages required
316 * Success - Number of EM page levels required
317 * -ENOMEM - Out of memory
320 tf_em_size_page_tbl_lvl(uint32_t page_size,
322 uint32_t num_entries,
323 uint64_t *num_data_pages)
325 uint64_t lvl_data_size = page_size;
326 int lvl = TF_PT_LVL_0;
330 data_size = (uint64_t)num_entries * entry_size;
332 while (lvl_data_size < data_size) {
335 if (lvl == TF_PT_LVL_1)
336 lvl_data_size = (uint64_t)MAX_PAGE_PTRS(page_size) *
338 else if (lvl == TF_PT_LVL_2)
339 lvl_data_size = (uint64_t)MAX_PAGE_PTRS(page_size) *
340 MAX_PAGE_PTRS(page_size) * page_size;
345 *num_data_pages = roundup(data_size, page_size) / page_size;
351 * Return the number of page table pages needed to
352 * reference the given number of next level pages.
358 * Size of each EM page
361 * Number of EM page table pages
364 tf_em_page_tbl_pgcnt(uint32_t num_pages,
367 return roundup(num_pages, MAX_PAGE_PTRS(page_size)) /
368 MAX_PAGE_PTRS(page_size);
373 * Given the number of data pages, page_size and the maximum
374 * number of page table levels (already determined), size
375 * the number of page table pages required at each level.
378 * Max number of levels
380 * [in] num_data_pages
381 * Number of EM data pages
390 tf_em_size_page_tbls(int max_lvl,
391 uint64_t num_data_pages,
395 if (max_lvl == TF_PT_LVL_0) {
396 page_cnt[TF_PT_LVL_0] = num_data_pages;
397 } else if (max_lvl == TF_PT_LVL_1) {
398 page_cnt[TF_PT_LVL_1] = num_data_pages;
399 page_cnt[TF_PT_LVL_0] =
400 tf_em_page_tbl_pgcnt(page_cnt[TF_PT_LVL_1], page_size);
401 } else if (max_lvl == TF_PT_LVL_2) {
402 page_cnt[TF_PT_LVL_2] = num_data_pages;
403 page_cnt[TF_PT_LVL_1] =
404 tf_em_page_tbl_pgcnt(page_cnt[TF_PT_LVL_2], page_size);
405 page_cnt[TF_PT_LVL_0] =
406 tf_em_page_tbl_pgcnt(page_cnt[TF_PT_LVL_1], page_size);
413 * Size the EM table based on capabilities
420 * - EINVAL - Parameter error
421 * - ENOMEM - Out of memory
424 tf_em_size_table(struct hcapi_cfa_em_table *tbl)
426 uint64_t num_data_pages;
429 uint32_t num_entries;
430 uint32_t cnt = TF_EM_MIN_ENTRIES;
432 /* Ignore entry if both size and number are zero */
433 if (!tbl->entry_size && !tbl->num_entries)
436 /* If only one is set then error */
437 if (!tbl->entry_size || !tbl->num_entries)
440 /* Determine number of page table levels and the number
441 * of data pages needed to process the given eem table.
443 if (tbl->type == TF_RECORD_TABLE) {
445 * For action records just a memory size is provided. Work
446 * backwards to resolve to number of entries
448 num_entries = tbl->num_entries / tbl->entry_size;
449 if (num_entries < TF_EM_MIN_ENTRIES) {
450 num_entries = TF_EM_MIN_ENTRIES;
452 while (num_entries > cnt && cnt <= TF_EM_MAX_ENTRIES)
457 num_entries = tbl->num_entries;
460 max_lvl = tf_em_size_page_tbl_lvl(TF_EM_PAGE_SIZE,
465 TFP_DRV_LOG(WARNING, "EEM: Failed to size page table levels\n");
467 "table: %d data-sz: %016" PRIu64 " page-sz: %u\n",
468 tbl->type, (uint64_t)num_entries * tbl->entry_size,
473 tbl->num_lvl = max_lvl + 1;
474 tbl->num_data_pages = num_data_pages;
476 /* Determine the number of pages needed at each level */
477 page_cnt = tbl->page_cnt;
478 memset(page_cnt, 0, sizeof(tbl->page_cnt));
479 tf_em_size_page_tbls(max_lvl, num_data_pages, TF_EM_PAGE_SIZE,
482 TFP_DRV_LOG(INFO, "EEM: Sized page table: %d\n", tbl->type);
484 "EEM: lvls: %d sz: %016" PRIu64 " pgs: %016" PRIu64 " l0: %u l1: %u l2: %u\n",
486 (uint64_t)num_data_pages * TF_EM_PAGE_SIZE,
488 page_cnt[TF_PT_LVL_0],
489 page_cnt[TF_PT_LVL_1],
490 page_cnt[TF_PT_LVL_2]);
496 * Unregisters EM Ctx in Firmware
499 * Pointer to a TruFlow handle
502 * Pointer to a table scope control block
505 * Receive or transmit direction
508 tf_em_ctx_unreg(struct tf *tfp,
509 struct tf_tbl_scope_cb *tbl_scope_cb,
512 struct hcapi_cfa_em_ctx_mem_info *ctxp = &tbl_scope_cb->em_ctx_info[dir];
513 struct hcapi_cfa_em_table *tbl;
516 for (i = TF_KEY0_TABLE; i < TF_MAX_TABLE; i++) {
517 tbl = &ctxp->em_tables[i];
519 if (tbl->num_entries != 0 && tbl->entry_size != 0) {
520 tf_msg_em_mem_unrgtr(tfp, &tbl->ctx_id);
521 tf_em_free_page_table(tbl);
527 * Registers EM Ctx in Firmware
530 * Pointer to a TruFlow handle
533 * Pointer to a table scope control block
536 * Receive or transmit direction
540 * -ENOMEM - Out of Memory
543 tf_em_ctx_reg(struct tf *tfp,
544 struct tf_tbl_scope_cb *tbl_scope_cb,
547 struct hcapi_cfa_em_ctx_mem_info *ctxp = &tbl_scope_cb->em_ctx_info[dir];
548 struct hcapi_cfa_em_table *tbl;
552 for (i = TF_KEY0_TABLE; i < TF_MAX_TABLE; i++) {
553 tbl = &ctxp->em_tables[i];
555 if (tbl->num_entries && tbl->entry_size) {
556 rc = tf_em_size_table(tbl);
561 rc = tf_em_alloc_page_table(tbl);
565 tf_em_setup_page_table(tbl);
566 rc = tf_msg_em_mem_rgtr(tfp,
568 TF_EM_PAGE_SIZE_ENUM,
578 tf_em_ctx_unreg(tfp, tbl_scope_cb, dir);
584 * Validates EM number of entries requested
587 * Pointer to table scope control block to be populated
590 * Pointer to input parameters
594 * -EINVAL - Parameter error
597 tf_em_validate_num_entries(struct tf_tbl_scope_cb *tbl_scope_cb,
598 struct tf_alloc_tbl_scope_parms *parms)
602 if (parms->rx_mem_size_in_mb != 0) {
603 uint32_t key_b = 2 * ((parms->rx_max_key_sz_in_bits / 8) + 1);
604 uint32_t action_b = ((parms->rx_max_action_entry_sz_in_bits / 8)
606 uint32_t num_entries = (parms->rx_mem_size_in_mb *
607 TF_MEGABYTE) / (key_b + action_b);
609 if (num_entries < TF_EM_MIN_ENTRIES) {
610 TFP_DRV_LOG(ERR, "EEM: Insufficient memory requested:"
612 parms->rx_mem_size_in_mb);
616 cnt = TF_EM_MIN_ENTRIES;
617 while (num_entries > cnt &&
618 cnt <= TF_EM_MAX_ENTRIES)
621 if (cnt > TF_EM_MAX_ENTRIES) {
622 TFP_DRV_LOG(ERR, "EEM: Invalid number of Tx requested: "
624 (parms->tx_num_flows_in_k * TF_KILOBYTE));
628 parms->rx_num_flows_in_k = cnt / TF_KILOBYTE;
630 if ((parms->rx_num_flows_in_k * TF_KILOBYTE) <
632 (parms->rx_num_flows_in_k * TF_KILOBYTE) >
633 tbl_scope_cb->em_caps[TF_DIR_RX].max_entries_supported) {
635 "EEM: Invalid number of Rx flows "
636 "requested:%u max:%u\n",
637 parms->rx_num_flows_in_k * TF_KILOBYTE,
638 tbl_scope_cb->em_caps[TF_DIR_RX].max_entries_supported);
642 /* must be a power-of-2 supported value
643 * in the range 32K - 128M
645 cnt = TF_EM_MIN_ENTRIES;
646 while ((parms->rx_num_flows_in_k * TF_KILOBYTE) != cnt &&
647 cnt <= TF_EM_MAX_ENTRIES)
650 if (cnt > TF_EM_MAX_ENTRIES) {
652 "EEM: Invalid number of Rx requested: %u\n",
653 (parms->rx_num_flows_in_k * TF_KILOBYTE));
658 if (parms->tx_mem_size_in_mb != 0) {
659 uint32_t key_b = 2 * (parms->tx_max_key_sz_in_bits / 8 + 1);
660 uint32_t action_b = ((parms->tx_max_action_entry_sz_in_bits / 8)
662 uint32_t num_entries = (parms->tx_mem_size_in_mb *
663 (TF_KILOBYTE * TF_KILOBYTE)) /
666 if (num_entries < TF_EM_MIN_ENTRIES) {
668 "EEM: Insufficient memory requested:%uMB\n",
669 parms->rx_mem_size_in_mb);
673 cnt = TF_EM_MIN_ENTRIES;
674 while (num_entries > cnt &&
675 cnt <= TF_EM_MAX_ENTRIES)
678 if (cnt > TF_EM_MAX_ENTRIES) {
680 "EEM: Invalid number of Tx requested: %u\n",
681 (parms->tx_num_flows_in_k * TF_KILOBYTE));
685 parms->tx_num_flows_in_k = cnt / TF_KILOBYTE;
687 if ((parms->tx_num_flows_in_k * TF_KILOBYTE) <
689 (parms->tx_num_flows_in_k * TF_KILOBYTE) >
690 tbl_scope_cb->em_caps[TF_DIR_TX].max_entries_supported) {
692 "EEM: Invalid number of Tx flows "
693 "requested:%u max:%u\n",
694 (parms->tx_num_flows_in_k * TF_KILOBYTE),
695 tbl_scope_cb->em_caps[TF_DIR_TX].max_entries_supported);
699 cnt = TF_EM_MIN_ENTRIES;
700 while ((parms->tx_num_flows_in_k * TF_KILOBYTE) != cnt &&
701 cnt <= TF_EM_MAX_ENTRIES)
704 if (cnt > TF_EM_MAX_ENTRIES) {
706 "EEM: Invalid number of Tx requested: %u\n",
707 (parms->tx_num_flows_in_k * TF_KILOBYTE));
712 if (parms->rx_num_flows_in_k != 0 &&
713 (parms->rx_max_key_sz_in_bits / 8 == 0)) {
715 "EEM: Rx key size required: %u\n",
716 (parms->rx_max_key_sz_in_bits));
720 if (parms->tx_num_flows_in_k != 0 &&
721 (parms->tx_max_key_sz_in_bits / 8 == 0)) {
723 "EEM: Tx key size required: %u\n",
724 (parms->tx_max_key_sz_in_bits));
728 tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY0_TABLE].num_entries =
729 parms->rx_num_flows_in_k * TF_KILOBYTE;
730 tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY0_TABLE].entry_size =
731 parms->rx_max_key_sz_in_bits / 8;
733 tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY1_TABLE].num_entries =
734 parms->rx_num_flows_in_k * TF_KILOBYTE;
735 tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY1_TABLE].entry_size =
736 parms->rx_max_key_sz_in_bits / 8;
738 tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_RECORD_TABLE].num_entries =
739 parms->rx_num_flows_in_k * TF_KILOBYTE;
740 tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_RECORD_TABLE].entry_size =
741 parms->rx_max_action_entry_sz_in_bits / 8;
743 tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_EFC_TABLE].num_entries = 0;
746 tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY0_TABLE].num_entries =
747 parms->tx_num_flows_in_k * TF_KILOBYTE;
748 tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY0_TABLE].entry_size =
749 parms->tx_max_key_sz_in_bits / 8;
751 tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY1_TABLE].num_entries =
752 parms->tx_num_flows_in_k * TF_KILOBYTE;
753 tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY1_TABLE].entry_size =
754 parms->tx_max_key_sz_in_bits / 8;
756 tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_RECORD_TABLE].num_entries =
757 parms->tx_num_flows_in_k * TF_KILOBYTE;
758 tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_RECORD_TABLE].entry_size =
759 parms->tx_max_action_entry_sz_in_bits / 8;
761 tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_EFC_TABLE].num_entries = 0;
766 /** insert EEM entry API
770 * TF_ERR - unable to get lock
772 * insert callback returns:
774 * TF_ERR_EM_DUP - key is already in table
777 tf_insert_eem_entry(struct tf_tbl_scope_cb *tbl_scope_cb,
778 struct tf_insert_em_entry_parms *parms)
785 struct cfa_p4_eem_64b_entry key_entry;
787 enum hcapi_cfa_em_table_type table_type;
789 struct hcapi_cfa_hwop op;
790 struct hcapi_cfa_key_tbl key_tbl;
791 struct hcapi_cfa_key_data key_obj;
792 struct hcapi_cfa_key_loc key_loc;
796 /* Get mask to use on hash */
797 mask = tf_em_get_key_mask(tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY0_TABLE].num_entries);
803 dump_raw((uint8_t *)parms->key, TF_HW_EM_KEY_MAX_SIZE + 4, "In Key");
806 big_hash = hcapi_cfa_key_hash((uint64_t *)parms->key,
807 (TF_HW_EM_KEY_MAX_SIZE + 4) * 8);
808 key0_hash = (uint32_t)(big_hash >> 32);
809 key1_hash = (uint32_t)(big_hash & 0xFFFFFFFF);
811 key0_index = key0_hash & mask;
812 key1_index = key1_hash & mask;
815 TFP_DRV_LOG(DEBUG, "Key0 hash:0x%08x\n", key0_hash);
816 TFP_DRV_LOG(DEBUG, "Key1 hash:0x%08x\n", key1_hash);
819 * Use the "result" arg to populate all of the key entry then
820 * store the byte swapped "raw" entry in a local copy ready
821 * for insertion in to the table.
823 tf_em_create_key_entry((struct cfa_p4_eem_entry_hdr *)parms->em_record,
824 ((uint8_t *)parms->key),
828 * Try to add to Key0 table, if that does not work then
829 * try the key1 table.
832 op.opcode = HCAPI_CFA_HWOPS_ADD;
833 key_tbl.base0 = (uint8_t *)
834 &tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY0_TABLE];
835 key_obj.offset = (index * TF_EM_KEY_RECORD_SIZE) % TF_EM_PAGE_SIZE;
836 key_obj.data = (uint8_t *)&key_entry;
837 key_obj.size = TF_EM_KEY_RECORD_SIZE;
839 rc = hcapi_cfa_key_hw_op(&op,
845 table_type = TF_KEY0_TABLE;
849 key_tbl.base0 = (uint8_t *)
850 &tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY1_TABLE];
852 (index * TF_EM_KEY_RECORD_SIZE) % TF_EM_PAGE_SIZE;
854 rc = hcapi_cfa_key_hw_op(&op,
861 table_type = TF_KEY1_TABLE;
867 TF_SET_FLOW_ID(parms->flow_id,
869 TF_GFID_TABLE_EXTERNAL,
871 TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
882 /** delete EEM hash entry API
886 * -EINVAL - parameter error
887 * TF_NO_SESSION - bad session ID
888 * TF_ERR_TBL_SCOPE - invalid table scope
889 * TF_ERR_TBL_IF - invalid table interface
891 * insert callback returns
893 * TF_NO_EM_MATCH - entry not found
896 tf_delete_eem_entry(struct tf_tbl_scope_cb *tbl_scope_cb,
897 struct tf_delete_em_entry_parms *parms)
899 enum hcapi_cfa_em_table_type hash_type;
901 struct hcapi_cfa_hwop op;
902 struct hcapi_cfa_key_tbl key_tbl;
903 struct hcapi_cfa_key_data key_obj;
904 struct hcapi_cfa_key_loc key_loc;
907 if (parms->flow_handle == 0)
910 TF_GET_HASH_TYPE_FROM_FLOW_HANDLE(parms->flow_handle, hash_type);
911 TF_GET_INDEX_FROM_FLOW_HANDLE(parms->flow_handle, index);
913 op.opcode = HCAPI_CFA_HWOPS_DEL;
914 key_tbl.base0 = (uint8_t *)
915 &tbl_scope_cb->em_ctx_info[parms->dir].em_tables[(hash_type == 0 ?
918 key_obj.offset = (index * TF_EM_KEY_RECORD_SIZE) % TF_EM_PAGE_SIZE;
920 key_obj.size = TF_EM_KEY_RECORD_SIZE;
922 rc = hcapi_cfa_key_hw_op(&op,
933 /** insert EM hash entry API
940 tf_em_insert_ext_entry(struct tf *tfp __rte_unused,
941 struct tf_insert_em_entry_parms *parms)
943 struct tf_tbl_scope_cb *tbl_scope_cb;
945 tbl_scope_cb = tbl_scope_cb_find(parms->tbl_scope_id);
946 if (tbl_scope_cb == NULL) {
947 TFP_DRV_LOG(ERR, "Invalid tbl_scope_cb\n");
951 return tf_insert_eem_entry(tbl_scope_cb, parms);
954 /** Delete EM hash entry API
961 tf_em_delete_ext_entry(struct tf *tfp __rte_unused,
962 struct tf_delete_em_entry_parms *parms)
964 struct tf_tbl_scope_cb *tbl_scope_cb;
966 tbl_scope_cb = tbl_scope_cb_find(parms->tbl_scope_id);
967 if (tbl_scope_cb == NULL) {
968 TFP_DRV_LOG(ERR, "Invalid tbl_scope_cb\n");
972 return tf_delete_eem_entry(tbl_scope_cb, parms);
976 tf_em_ext_host_alloc(struct tf *tfp,
977 struct tf_alloc_tbl_scope_parms *parms)
981 struct tf_tbl_scope_cb *tbl_scope_cb;
982 struct hcapi_cfa_em_table *em_tables;
983 struct tf_free_tbl_scope_parms free_parms;
984 struct tf_rm_allocate_parms aparms = { 0 };
985 struct tf_rm_free_parms fparms = { 0 };
987 /* Get Table Scope control block from the session pool */
988 aparms.rm_db = eem_db[TF_DIR_RX];
989 aparms.db_index = TF_EEM_DB_TBL_SCOPE;
990 aparms.index = (uint32_t *)&parms->tbl_scope_id;
991 rc = tf_rm_allocate(&aparms);
994 "Failed to allocate table scope\n");
998 tbl_scope_cb = &tbl_scopes[parms->tbl_scope_id];
999 tbl_scope_cb->index = parms->tbl_scope_id;
1000 tbl_scope_cb->tbl_scope_id = parms->tbl_scope_id;
1002 for (dir = 0; dir < TF_DIR_MAX; dir++) {
1003 rc = tf_msg_em_qcaps(tfp,
1005 &tbl_scope_cb->em_caps[dir]);
1008 "EEM: Unable to query for EEM capability,"
1016 * Validate and setup table sizes
1018 if (tf_em_validate_num_entries(tbl_scope_cb, parms))
1021 for (dir = 0; dir < TF_DIR_MAX; dir++) {
1023 * Allocate tables and signal configuration to FW
1025 rc = tf_em_ctx_reg(tfp, tbl_scope_cb, dir);
1028 "EEM: Unable to register for EEM ctx,"
1034 em_tables = tbl_scope_cb->em_ctx_info[dir].em_tables;
1035 rc = tf_msg_em_cfg(tfp,
1036 em_tables[TF_KEY0_TABLE].num_entries,
1037 em_tables[TF_KEY0_TABLE].ctx_id,
1038 em_tables[TF_KEY1_TABLE].ctx_id,
1039 em_tables[TF_RECORD_TABLE].ctx_id,
1040 em_tables[TF_EFC_TABLE].ctx_id,
1041 parms->hw_flow_cache_flush_timer,
1045 "TBL: Unable to configure EEM in firmware"
1051 rc = tf_msg_em_op(tfp,
1053 HWRM_TF_EXT_EM_OP_INPUT_OP_EXT_EM_ENABLE);
1057 "EEM: Unable to enable EEM in firmware"
1063 /* Allocate the pool of offsets of the external memory.
1064 * Initially, this is a single fixed size pool for all external
1065 * actions related to a single table scope.
1067 rc = tf_create_tbl_pool_external(dir,
1069 em_tables[TF_RECORD_TABLE].num_entries,
1070 em_tables[TF_RECORD_TABLE].entry_size);
1073 "%s TBL: Unable to allocate idx pools %s\n",
1083 free_parms.tbl_scope_id = parms->tbl_scope_id;
1084 tf_em_ext_host_free(tfp, &free_parms);
1088 /* Free Table control block */
1089 fparms.rm_db = eem_db[TF_DIR_RX];
1090 fparms.db_index = TF_EEM_DB_TBL_SCOPE;
1091 fparms.index = parms->tbl_scope_id;
1092 tf_rm_free(&fparms);
1097 tf_em_ext_host_free(struct tf *tfp,
1098 struct tf_free_tbl_scope_parms *parms)
1102 struct tf_tbl_scope_cb *tbl_scope_cb;
1103 struct tf_rm_free_parms aparms = { 0 };
1105 tbl_scope_cb = tbl_scope_cb_find(parms->tbl_scope_id);
1107 if (tbl_scope_cb == NULL) {
1108 TFP_DRV_LOG(ERR, "Table scope error\n");
1112 /* Free Table control block */
1113 aparms.rm_db = eem_db[TF_DIR_RX];
1114 aparms.db_index = TF_EEM_DB_TBL_SCOPE;
1115 aparms.index = parms->tbl_scope_id;
1116 rc = tf_rm_free(&aparms);
1119 "Failed to free table scope\n");
1122 /* free table scope locks */
1123 for (dir = 0; dir < TF_DIR_MAX; dir++) {
1124 /* Free associated external pools
1126 tf_destroy_tbl_pool_external(dir,
1130 HWRM_TF_EXT_EM_OP_INPUT_OP_EXT_EM_DISABLE);
1132 /* free table scope and all associated resources */
1133 tf_em_ctx_unreg(tfp, tbl_scope_cb, dir);
1136 tbl_scopes[parms->tbl_scope_id].tbl_scope_id = -1;