-
-/**
- * Free External Tbl entry to the session pool.
- *
- * [in] tfp
- * Pointer to Truflow Handle
- * [in] parms
- * Allocation parameters
- *
- * Return:
- * 0 - Success, entry freed
- *
- * - Failure, entry not successfully freed for these reasons
- * -ENOMEM
- * -EOPNOTSUPP
- * -EINVAL
- */
-static int
-tf_free_tbl_entry_pool_external(struct tf *tfp,
- struct tf_free_tbl_entry_parms *parms)
-{
- int rc = 0;
- struct tf_session *tfs;
- uint32_t index;
- struct tf_tbl_scope_cb *tbl_scope_cb;
- struct stack *pool;
-
- /* Check parameters */
- if (tfp == NULL || parms == NULL) {
- PMD_DRV_LOG(ERR, "Invalid parameters\n");
- return -EINVAL;
- }
-
- if (tfp->session == NULL || tfp->session->core_data == NULL) {
- PMD_DRV_LOG(ERR,
- "dir:%d, Session info invalid\n",
- parms->dir);
- return -EINVAL;
- }
-
- tfs = (struct tf_session *)(tfp->session->core_data);
-
- /* Get the pool info from the table scope
- */
- tbl_scope_cb = tbl_scope_cb_find(tfs, parms->tbl_scope_id);
-
- if (tbl_scope_cb == NULL) {
- PMD_DRV_LOG(ERR,
- "dir:%d, Session info invalid\n",
- parms->dir);
- return -EINVAL;
- }
- pool = &tbl_scope_cb->ext_act_pool[parms->dir];
-
- index = parms->idx;
-
- rc = stack_push(pool, index);
-
- if (rc != 0) {
- PMD_DRV_LOG(ERR,
- "dir:%d, consistency error, stack full, type:%d, idx:%d\n",
- parms->dir,
- parms->type,
- index);
- }
- return rc;
-}
-
-/**
- * Free Internal Tbl entry from the Session Pool.
- *
- * [in] tfp
- * Pointer to Truflow Handle
- * [in] parms
- * Allocation parameters
- *
- * Return:
- * 0 - Success, entry found and ref count decremented
- * -ENOMEM - Failure, entry not allocated, out of resources
- */
-static int
-tf_free_tbl_entry_pool_internal(struct tf *tfp,
- struct tf_free_tbl_entry_parms *parms)
-{
- int rc = 0;
- int id;
- struct bitalloc *session_pool;
- struct tf_session *tfs;
- uint32_t index;
-
- /* Check parameters */
- if (tfp == NULL || parms == NULL) {
- PMD_DRV_LOG(ERR, "Invalid parameters\n");
- return -EINVAL;
- }
-
- if (tfp->session == NULL || tfp->session->core_data == NULL) {
- PMD_DRV_LOG(ERR,
- "dir:%d, Session info invalid\n",
- parms->dir);
- return -EINVAL;
- }
-
- tfs = (struct tf_session *)(tfp->session->core_data);
-
- if (parms->type != TF_TBL_TYPE_FULL_ACT_RECORD &&
- parms->type != TF_TBL_TYPE_ACT_SP_SMAC &&
- parms->type != TF_TBL_TYPE_ACT_SP_SMAC_IPV4 &&
- parms->type != TF_TBL_TYPE_ACT_ENCAP_8B &&
- parms->type != TF_TBL_TYPE_ACT_ENCAP_16B &&
- parms->type != TF_TBL_TYPE_ACT_ENCAP_64B &&
- parms->type != TF_TBL_TYPE_ACT_STATS_64) {
- PMD_DRV_LOG(ERR,
- "dir:%d, Type not supported, type:%d\n",
- parms->dir,
- parms->type);
- return -EOPNOTSUPP;
- }
-
- /* Lookup the pool using the table type of the element */
- rc = tf_rm_lookup_tbl_type_pool(tfs,
- parms->dir,
- parms->type,
- &session_pool);
- /* Error logging handled by tf_rm_lookup_tbl_type_pool */
- if (rc)
- return rc;
-
- index = parms->idx;
-
- /* Adjust the returned index/offset as there is no guarantee
- * that the start is 0 at time of RM allocation
- */
- tf_rm_convert_index(tfs,
- parms->dir,
- parms->type,
- TF_RM_CONVERT_RM_BASE,
- parms->idx,
- &index);
-
- /* Check if element was indeed allocated */
- id = ba_inuse_free(session_pool, index);
- if (id == -1) {
- PMD_DRV_LOG(ERR,
- "dir:%d, Element not previously alloc'ed, type:%d, idx:%d\n",
- parms->dir,
- parms->type,
- index);
- return -ENOMEM;
- }
-
- return rc;
-}
-
-/* API defined in tf_em.h */
-struct tf_tbl_scope_cb *
-tbl_scope_cb_find(struct tf_session *session,
- uint32_t tbl_scope_id)
-{
- int i;
-
- /* Check that id is valid */
- i = ba_inuse(session->tbl_scope_pool_rx, tbl_scope_id);
- if (i < 0)
- return NULL;
-
- for (i = 0; i < TF_NUM_TBL_SCOPE; i++) {
- if (session->tbl_scopes[i].tbl_scope_id == tbl_scope_id)
- return &session->tbl_scopes[i];
- }
-
- return NULL;
-}
-
-/* API defined in tf_core.h */
-int
-tf_free_eem_tbl_scope_cb(struct tf *tfp,
- struct tf_free_tbl_scope_parms *parms)
-{
- int rc = 0;
- enum tf_dir dir;
- struct tf_tbl_scope_cb *tbl_scope_cb;
- struct tf_session *session;
-
- session = (struct tf_session *)(tfp->session->core_data);
-
- tbl_scope_cb = tbl_scope_cb_find(session,
- parms->tbl_scope_id);
-
- if (tbl_scope_cb == NULL)
- return -EINVAL;
-
- /* Free Table control block */
- ba_free(session->tbl_scope_pool_rx, tbl_scope_cb->index);
-
- /* free table scope locks */
- for (dir = 0; dir < TF_DIR_MAX; dir++) {
- /* Free associated external pools
- */
- tf_destroy_tbl_pool_external(dir,
- tbl_scope_cb);
- tf_msg_em_op(tfp,
- dir,
- HWRM_TF_EXT_EM_OP_INPUT_OP_EXT_EM_DISABLE);
-
- /* free table scope and all associated resources */
- tf_em_ctx_unreg(tfp, tbl_scope_cb, dir);
- }
-
- return rc;
-}
-
-/* API defined in tf_em.h */
-int
-tf_alloc_eem_tbl_scope(struct tf *tfp,
- struct tf_alloc_tbl_scope_parms *parms)
-{
- int rc;
- enum tf_dir dir;
- struct tf_tbl_scope_cb *tbl_scope_cb;
- struct tf_em_table *em_tables;
- int index;
- struct tf_session *session;
- struct tf_free_tbl_scope_parms free_parms;
-
- /* check parameters */
- if (parms == NULL || tfp->session == NULL) {
- PMD_DRV_LOG(ERR, "TBL: Invalid parameters\n");
- return -EINVAL;
- }
-
- session = (struct tf_session *)tfp->session->core_data;
-
- /* Get Table Scope control block from the session pool */
- index = ba_alloc(session->tbl_scope_pool_rx);
- if (index == -1) {
- PMD_DRV_LOG(ERR, "EEM: Unable to allocate table scope "
- "Control Block\n");
- return -ENOMEM;
- }
-
- tbl_scope_cb = &session->tbl_scopes[index];
- tbl_scope_cb->index = index;
- tbl_scope_cb->tbl_scope_id = index;
- parms->tbl_scope_id = index;
-
- for (dir = 0; dir < TF_DIR_MAX; dir++) {
- rc = tf_msg_em_qcaps(tfp,
- dir,
- &tbl_scope_cb->em_caps[dir]);
- if (rc) {
- PMD_DRV_LOG(ERR,
- "EEM: Unable to query for EEM capability\n");
- goto cleanup;
- }
- }
-
- /*
- * Validate and setup table sizes
- */
- if (tf_em_validate_num_entries(tbl_scope_cb, parms))
- goto cleanup;
-
- for (dir = 0; dir < TF_DIR_MAX; dir++) {
- /*
- * Allocate tables and signal configuration to FW
- */
- rc = tf_em_ctx_reg(tfp, tbl_scope_cb, dir);
- if (rc) {
- PMD_DRV_LOG(ERR,
- "EEM: Unable to register for EEM ctx\n");
- goto cleanup;
- }
-
- em_tables = tbl_scope_cb->em_ctx_info[dir].em_tables;
- rc = tf_msg_em_cfg(tfp,
- em_tables[KEY0_TABLE].num_entries,
- em_tables[KEY0_TABLE].ctx_id,
- em_tables[KEY1_TABLE].ctx_id,
- em_tables[RECORD_TABLE].ctx_id,
- em_tables[EFC_TABLE].ctx_id,
- parms->hw_flow_cache_flush_timer,
- dir);
- if (rc) {
- PMD_DRV_LOG(ERR,
- "TBL: Unable to configure EEM in firmware\n");
- goto cleanup_full;
- }
-
- rc = tf_msg_em_op(tfp,
- dir,
- HWRM_TF_EXT_EM_OP_INPUT_OP_EXT_EM_ENABLE);
-
- if (rc) {
- PMD_DRV_LOG(ERR,
- "EEM: Unable to enable EEM in firmware\n");
- goto cleanup_full;
- }
-
- /* Allocate the pool of offsets of the external memory.
- * Initially, this is a single fixed size pool for all external
- * actions related to a single table scope.
- */
- rc = tf_create_tbl_pool_external(dir,
- tbl_scope_cb,
- em_tables[RECORD_TABLE].num_entries,
- em_tables[RECORD_TABLE].entry_size);
- if (rc) {
- PMD_DRV_LOG(ERR,
- "%d TBL: Unable to allocate idx pools %s\n",
- dir,
- strerror(-rc));
- goto cleanup_full;
- }
- }
-
- return 0;
-
-cleanup_full:
- free_parms.tbl_scope_id = index;
- tf_free_eem_tbl_scope_cb(tfp, &free_parms);
- return -EINVAL;
-
-cleanup:
- /* Free Table control block */
- ba_free(session->tbl_scope_pool_rx, tbl_scope_cb->index);
- return -EINVAL;
-}
-
-/* API defined in tf_core.h */
-int
-tf_set_tbl_entry(struct tf *tfp,
- struct tf_set_tbl_entry_parms *parms)
-{
- int rc = 0;
- struct tf_tbl_scope_cb *tbl_scope_cb;
- struct tf_session *session;
-
- if (tfp == NULL || parms == NULL || parms->data == NULL)
- return -EINVAL;
-
- if (tfp->session == NULL || tfp->session->core_data == NULL) {
- PMD_DRV_LOG(ERR,
- "dir:%d, Session info invalid\n",
- parms->dir);
- return -EINVAL;
- }
-
- if (parms->type == TF_TBL_TYPE_EXT) {
- void *base_addr;
- uint32_t offset = parms->idx;
- uint32_t tbl_scope_id;
-
- session = (struct tf_session *)(tfp->session->core_data);
-
- tbl_scope_id = parms->tbl_scope_id;
-
- if (tbl_scope_id == TF_TBL_SCOPE_INVALID) {
- PMD_DRV_LOG(ERR,
- "dir:%d, Table scope not allocated\n",
- parms->dir);
- return -EINVAL;
- }
-
- /* Get the table scope control block associated with the
- * external pool
- */
- tbl_scope_cb = tbl_scope_cb_find(session, tbl_scope_id);
-
- if (tbl_scope_cb == NULL)
- return -EINVAL;
-
- /* External table, implicitly the Action table */
- base_addr = tf_em_get_table_page(tbl_scope_cb,
- parms->dir,
- offset,
- RECORD_TABLE);
- if (base_addr == NULL) {
- PMD_DRV_LOG(ERR,
- "dir:%d, Base address lookup failed\n",
- parms->dir);
- return -EINVAL;
- }
-
- offset %= TF_EM_PAGE_SIZE;
- rte_memcpy((char *)base_addr + offset,
- parms->data,
- parms->data_sz_in_bytes);
- } else {
- /* Internal table type processing */
- rc = tf_set_tbl_entry_internal(tfp, parms);
- if (rc) {
- PMD_DRV_LOG(ERR,
- "dir:%d, Set failed, type:%d, rc:%d\n",
- parms->dir,
- parms->type,
- rc);
- }
- }
-
- return rc;
-}
-
-/* API defined in tf_core.h */
-int
-tf_get_tbl_entry(struct tf *tfp,
- struct tf_get_tbl_entry_parms *parms)
-{
- int rc = 0;
-
- if (tfp == NULL || parms == NULL)
- return -EINVAL;
-
- if (tfp->session == NULL || tfp->session->core_data == NULL) {
- PMD_DRV_LOG(ERR,
- "dir:%d, Session info invalid\n",
- parms->dir);
- return -EINVAL;
- }
-
- if (parms->type == TF_TBL_TYPE_EXT) {
- PMD_DRV_LOG(ERR,
- "dir:%d, External table type not supported\n",
- parms->dir);
-
- rc = -EOPNOTSUPP;
- } else {
- /* Internal table type processing */
- rc = tf_get_tbl_entry_internal(tfp, parms);
- if (rc)
- PMD_DRV_LOG(ERR,
- "dir:%d, Get failed, type:%d, rc:%d\n",
- parms->dir,
- parms->type,
- rc);
- }
-
- return rc;
-}
-
-/* API defined in tf_core.h */
-int
-tf_alloc_tbl_scope(struct tf *tfp,
- struct tf_alloc_tbl_scope_parms *parms)
-{
- int rc;
-
- /* check parameters */
- if (parms == NULL || tfp == NULL) {
- PMD_DRV_LOG(ERR, "TBL: Invalid parameters\n");
- return -EINVAL;
- }
-
- rc = tf_alloc_eem_tbl_scope(tfp, parms);
-
- return rc;
-}
-
-/* API defined in tf_core.h */
-int
-tf_free_tbl_scope(struct tf *tfp,
- struct tf_free_tbl_scope_parms *parms)
-{
- int rc;
-
- /* check parameters */
- if (parms == NULL || tfp == NULL) {
- PMD_DRV_LOG(ERR, "TBL: Invalid parameters\n");
- return -EINVAL;
- }
-
- /* free table scope and all associated resources */
- rc = tf_free_eem_tbl_scope_cb(tfp, parms);
-
- return rc;
-}
-
-/* API defined in tf_core.h */
-int
-tf_alloc_tbl_entry(struct tf *tfp,
- struct tf_alloc_tbl_entry_parms *parms)
-{
- int rc;
-#if (TF_SHADOW == 1)
- struct tf_session *tfs;
-#endif /* TF_SHADOW */
-
- /* Check parameters */
- if (parms == NULL || tfp == NULL) {
- PMD_DRV_LOG(ERR, "TBL: Invalid parameters\n");
- return -EINVAL;
- }
- /*
- * No shadow copy support for external tables, allocate and return
- */
- if (parms->type == TF_TBL_TYPE_EXT) {
- rc = tf_alloc_tbl_entry_pool_external(tfp, parms);
- return rc;
- }
-
-#if (TF_SHADOW == 1)
- if (tfp->session == NULL || tfp->session->core_data == NULL) {
- PMD_DRV_LOG(ERR,
- "dir:%d, Session info invalid\n",
- parms->dir);
- return -EINVAL;
- }
-
- tfs = (struct tf_session *)(tfp->session->core_data);
-
- /* Search the Shadow DB for requested element. If not found go
- * allocate one from the Session Pool
- */
- if (parms->search_enable && tfs->shadow_copy) {
- rc = tf_alloc_tbl_entry_shadow(tfs, parms);
- /* Entry found and parms populated with return data */
- if (rc == 0)
- return rc;
- }
-#endif /* TF_SHADOW */
-
- rc = tf_alloc_tbl_entry_pool_internal(tfp, parms);
- if (rc)
- PMD_DRV_LOG(ERR, "dir%d, Alloc failed, rc:%d\n",
- parms->dir,
- rc);
-
- return rc;
-}
-
-/* API defined in tf_core.h */
-int
-tf_free_tbl_entry(struct tf *tfp,
- struct tf_free_tbl_entry_parms *parms)
-{
- int rc;
-#if (TF_SHADOW == 1)
- struct tf_session *tfs;
-#endif /* TF_SHADOW */
-
- /* Check parameters */
- if (parms == NULL || tfp == NULL) {
- PMD_DRV_LOG(ERR, "TBL: Invalid parameters\n");
- return -EINVAL;
- }
- /*
- * No shadow of external tables so just free the entry
- */
- if (parms->type == TF_TBL_TYPE_EXT) {
- rc = tf_free_tbl_entry_pool_external(tfp, parms);
- return rc;
- }
-
-#if (TF_SHADOW == 1)
- if (tfp->session == NULL || tfp->session->core_data == NULL) {
- PMD_DRV_LOG(ERR,
- "dir:%d, Session info invalid\n",
- parms->dir);
- return -EINVAL;
- }
-
- tfs = (struct tf_session *)(tfp->session->core_data);
-
- /* Search the Shadow DB for requested element. If not found go
- * allocate one from the Session Pool
- */
- if (parms->search_enable && tfs->shadow_copy) {
- rc = tf_free_tbl_entry_shadow(tfs, parms);
- /* Entry free'ed and parms populated with return data */
- if (rc == 0)
- return rc;
- }
-#endif /* TF_SHADOW */
-
- rc = tf_free_tbl_entry_pool_internal(tfp, parms);
-
- if (rc)
- PMD_DRV_LOG(ERR, "dir:%d, Alloc failed, rc:%d\n",
- parms->dir,
- rc);
- return rc;
-}
-
-
-static void
-tf_dump_link_page_table(struct tf_em_page_tbl *tp,
- struct tf_em_page_tbl *tp_next)
-{
- uint64_t *pg_va;
- uint32_t i;
- uint32_t j;
- uint32_t k = 0;
-
- printf("pg_count:%d pg_size:0x%x\n",
- tp->pg_count,
- tp->pg_size);
- for (i = 0; i < tp->pg_count; i++) {
- pg_va = tp->pg_va_tbl[i];
- printf("\t%p\n", (void *)pg_va);
- for (j = 0; j < MAX_PAGE_PTRS(tp->pg_size); j++) {
- printf("\t\t%p\n", (void *)(uintptr_t)pg_va[j]);
- if (((pg_va[j] & 0x7) ==
- tfp_cpu_to_le_64(PTU_PTE_LAST |
- PTU_PTE_VALID)))
- return;
-
- if (!(pg_va[j] & tfp_cpu_to_le_64(PTU_PTE_VALID))) {
- printf("** Invalid entry **\n");
- return;
- }
-
- if (++k >= tp_next->pg_count) {
- printf("** Shouldn't get here **\n");
- return;
- }
- }
- }
-}
-
-void tf_dump_dma(struct tf *tfp, uint32_t tbl_scope_id);
-
-void tf_dump_dma(struct tf *tfp, uint32_t tbl_scope_id)
-{
- struct tf_session *session;
- struct tf_tbl_scope_cb *tbl_scope_cb;
- struct tf_em_page_tbl *tp;
- struct tf_em_page_tbl *tp_next;
- struct tf_em_table *tbl;
- int i;
- int j;
- int dir;
-
- printf("called %s\n", __func__);
-
- /* find session struct */
- session = (struct tf_session *)tfp->session->core_data;
-
- /* find control block for table scope */
- tbl_scope_cb = tbl_scope_cb_find(session,
- tbl_scope_id);
- if (tbl_scope_cb == NULL)
- PMD_DRV_LOG(ERR, "No table scope\n");
-
- for (dir = 0; dir < TF_DIR_MAX; dir++) {
- printf("Direction %s:\n", (dir == TF_DIR_RX ? "Rx" : "Tx"));
-
- for (j = KEY0_TABLE; j < MAX_TABLE; j++) {
- tbl = &tbl_scope_cb->em_ctx_info[dir].em_tables[j];
- printf
- ("Table: j:%d type:%d num_entries:%d entry_size:0x%x num_lvl:%d ",
- j,
- tbl->type,
- tbl->num_entries,
- tbl->entry_size,
- tbl->num_lvl);
- if (tbl->pg_tbl[0].pg_va_tbl &&
- tbl->pg_tbl[0].pg_pa_tbl)
- printf("%p %p\n",
- tbl->pg_tbl[0].pg_va_tbl[0],
- (void *)(uintptr_t)tbl->pg_tbl[0].pg_pa_tbl[0]);
- for (i = 0; i < tbl->num_lvl - 1; i++) {
- printf("Level:%d\n", i);
- tp = &tbl->pg_tbl[i];
- tp_next = &tbl->pg_tbl[i + 1];
- tf_dump_link_page_table(tp, tp_next);
- }
- printf("\n");
- }
- }
-}