net/bnxt: add ULP flow counter manager
[dpdk.git] / drivers / net / bnxt / tf_ulp / bnxt_ulp.c
index c67da6d..c058611 100644 (file)
 #include "tf_core.h"
 #include "tf_ext_flow_handle.h"
 
-#include "ulp_template_db.h"
+#include "ulp_template_db_enum.h"
 #include "ulp_template_struct.h"
 #include "ulp_mark_mgr.h"
+#include "ulp_fc_mgr.h"
 #include "ulp_flow_db.h"
+#include "ulp_mapper.h"
+#include "ulp_port_db.h"
 
 /* Linked list of all TF sessions. */
 STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
@@ -42,7 +45,7 @@ ulp_ctx_deinit_allowed(void *ptr)
        if (!bp)
                return 0;
 
-       if (&bp->tfp == bp->ulp_ctx.g_tfp)
+       if (&bp->tfp == bp->ulp_ctx->g_tfp)
                return 1;
 
        return 0;
@@ -66,6 +69,7 @@ ulp_ctx_session_open(struct bnxt *bp,
        struct rte_eth_dev              *ethdev = bp->eth_dev;
        int32_t                         rc = 0;
        struct tf_open_session_parms    params;
+       struct tf_session_resources     *resources;
 
        memset(&params, 0, sizeof(params));
 
@@ -77,6 +81,55 @@ ulp_ctx_session_open(struct bnxt *bp,
                return rc;
        }
 
+       params.shadow_copy = false;
+       params.device_type = TF_DEVICE_TYPE_WH;
+       resources = &params.resources;
+       /** RX **/
+       /* Identifiers */
+       resources->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT] = 16;
+       resources->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_WC_PROF] = 8;
+       resources->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 8;
+       resources->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_EM_PROF] = 8;
+
+       /* Table Types */
+       resources->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 720;
+       resources->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 720;
+
+       /* TCAMs */
+       resources->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM] = 16;
+       resources->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 8;
+       resources->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 416;
+
+       /* EM */
+       resources->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 2048;
+
+       /** TX **/
+       /* Identifiers */
+       resources->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT] = 8;
+       resources->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_WC_PROF] = 8;
+       resources->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 8;
+       resources->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_EM_PROF] = 8;
+
+       /* Table Types */
+       resources->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 16;
+       resources->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 16;
+
+       /* ENCAP */
+       resources->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_64B] = 16;
+       resources->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_16B] = 16;
+
+       /* TCAMs */
+       resources->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM] = 8;
+       resources->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 8;
+       resources->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 8;
+
+       /* EM */
+       resources->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 8;
+
+       /* EEM */
+       resources->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1;
+       resources->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1;
+
        rc = tf_open_session(&bp->tfp, &params);
        if (rc) {
                BNXT_TF_DBG(ERR, "Failed to open TF session - %s, rc = %d\n",
@@ -101,7 +154,7 @@ ulp_ctx_session_close(struct bnxt *bp,
                tf_close_session(&bp->tfp);
        session->session_opened = 0;
        session->g_tfp = NULL;
-       bp->ulp_ctx.g_tfp = NULL;
+       bp->ulp_ctx->g_tfp = NULL;
 }
 
 static void
@@ -112,13 +165,19 @@ bnxt_init_tbl_scope_parms(struct bnxt *bp,
        uint32_t dev_id;
        int rc;
 
-       rc = bnxt_ulp_cntxt_dev_id_get(&bp->ulp_ctx, &dev_id);
+       rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id);
        if (rc)
                /* TBD: For now, just use default. */
                dparms = 0;
        else
                dparms = bnxt_ulp_device_params_get(dev_id);
 
+       /*
+        * Set the flush timer for EEM entries. The value is in 100ms intervals,
+        * so 100 is 10s.
+        */
+       params->hw_flow_cache_flush_timer = 100;
+
        if (!dparms) {
                params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY;
                params->rx_max_action_entry_sz_in_bits =
@@ -138,14 +197,14 @@ bnxt_init_tbl_scope_parms(struct bnxt *bp,
                params->rx_max_action_entry_sz_in_bits =
                        BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY;
                params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM;
-               params->rx_num_flows_in_k = dparms->num_flows / (1024);
+               params->rx_num_flows_in_k = dparms->flow_db_num_entries / 1024;
                params->rx_tbl_if_id = BNXT_ULP_RX_TBL_IF_ID;
 
                params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY;
                params->tx_max_action_entry_sz_in_bits =
                        BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY;
                params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM;
-               params->tx_num_flows_in_k = dparms->num_flows / (1024);
+               params->tx_num_flows_in_k = dparms->flow_db_num_entries / 1024;
                params->tx_tbl_if_id = BNXT_ULP_TX_TBL_IF_ID;
        }
 }
@@ -155,8 +214,27 @@ static int32_t
 ulp_eem_tbl_scope_init(struct bnxt *bp)
 {
        struct tf_alloc_tbl_scope_parms params = {0};
+       uint32_t dev_id;
+       struct bnxt_ulp_device_params *dparms;
        int rc;
 
+       /* Get the dev specific number of flows that needed to be supported. */
+       if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) {
+               BNXT_TF_DBG(ERR, "Invalid device id\n");
+               return -EINVAL;
+       }
+
+       dparms = bnxt_ulp_device_params_get(dev_id);
+       if (!dparms) {
+               BNXT_TF_DBG(ERR, "could not fetch the device params\n");
+               return -ENODEV;
+       }
+
+       if (dparms->flow_mem_type != BNXT_ULP_FLOW_MEM_TYPE_EXT) {
+               BNXT_TF_DBG(INFO, "Table Scope alloc is not required\n");
+               return 0;
+       }
+
        bnxt_init_tbl_scope_parms(bp, &params);
 
        rc = tf_alloc_tbl_scope(&bp->tfp, &params);
@@ -166,7 +244,7 @@ ulp_eem_tbl_scope_init(struct bnxt *bp)
                return rc;
        }
 
-       rc = bnxt_ulp_cntxt_tbl_scope_id_set(&bp->ulp_ctx, params.tbl_scope_id);
+       rc = bnxt_ulp_cntxt_tbl_scope_id_set(bp->ulp_ctx, params.tbl_scope_id);
        if (rc) {
                BNXT_TF_DBG(ERR, "Unable to set table scope id\n");
                return rc;
@@ -182,6 +260,8 @@ ulp_eem_tbl_scope_deinit(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx)
        struct tf_free_tbl_scope_parms  params = {0};
        struct tf                       *tfp;
        int32_t                         rc = 0;
+       struct bnxt_ulp_device_params *dparms;
+       uint32_t dev_id;
 
        if (!ulp_ctx || !ulp_ctx->cfg_data)
                return -EINVAL;
@@ -196,6 +276,23 @@ ulp_eem_tbl_scope_deinit(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx)
                return -EINVAL;
        }
 
+       /* Get the dev specific number of flows that needed to be supported. */
+       if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) {
+               BNXT_TF_DBG(ERR, "Invalid device id\n");
+               return -EINVAL;
+       }
+
+       dparms = bnxt_ulp_device_params_get(dev_id);
+       if (!dparms) {
+               BNXT_TF_DBG(ERR, "could not fetch the device params\n");
+               return -ENODEV;
+       }
+
+       if (dparms->flow_mem_type != BNXT_ULP_FLOW_MEM_TYPE_EXT) {
+               BNXT_TF_DBG(INFO, "Table Scope free is not required\n");
+               return 0;
+       }
+
        rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &params.tbl_scope_id);
        if (rc) {
                BNXT_TF_DBG(ERR, "Failed to get the table scope id\n");
@@ -226,7 +323,7 @@ ulp_ctx_deinit(struct bnxt *bp,
        /* Free the contents */
        if (session->cfg_data) {
                rte_free(session->cfg_data);
-               bp->ulp_ctx.cfg_data = NULL;
+               bp->ulp_ctx->cfg_data = NULL;
                session->cfg_data = NULL;
        }
        return 0;
@@ -254,7 +351,7 @@ ulp_ctx_init(struct bnxt *bp,
        }
 
        /* Increment the ulp context data reference count usage. */
-       bp->ulp_ctx.cfg_data = ulp_data;
+       bp->ulp_ctx->cfg_data = ulp_data;
        session->cfg_data = ulp_data;
        ulp_data->ref_cnt++;
 
@@ -264,10 +361,68 @@ ulp_ctx_init(struct bnxt *bp,
                (void)ulp_ctx_deinit(bp, session);
                return rc;
        }
-       bnxt_ulp_cntxt_tfp_set(&bp->ulp_ctx, session->g_tfp);
+       bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, session->g_tfp);
        return rc;
 }
 
+/* The function to initialize ulp dparms with devargs */
+static int32_t
+ulp_dparms_init(struct bnxt *bp,
+               struct bnxt_ulp_context *ulp_ctx)
+{
+       struct bnxt_ulp_device_params *dparms;
+       uint32_t dev_id;
+
+       if (!bp->max_num_kflows)
+               return -EINVAL;
+
+       if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
+               BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
+               return -EINVAL;
+       }
+
+       dparms = bnxt_ulp_device_params_get(dev_id);
+       if (!dparms) {
+               BNXT_TF_DBG(DEBUG, "Failed to get device parms\n");
+               return -EINVAL;
+       }
+
+       /* num_flows = max_num_kflows * 1024 */
+       dparms->flow_db_num_entries = bp->max_num_kflows * 1024;
+       /* GFID =  2 * num_flows */
+       dparms->mark_db_gfid_entries = dparms->flow_db_num_entries * 2;
+       BNXT_TF_DBG(DEBUG, "Set the number of flows = %"PRIu64"\n",
+                   dparms->flow_db_num_entries);
+
+       return 0;
+}
+
+/* The function to initialize bp flags with truflow features */
+static int32_t
+ulp_dparms_dev_port_intf_update(struct bnxt *bp,
+                               struct bnxt_ulp_context *ulp_ctx)
+{
+       struct bnxt_ulp_device_params *dparms;
+       uint32_t dev_id;
+
+       if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
+               BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
+               return -EINVAL;
+       }
+
+       dparms = bnxt_ulp_device_params_get(dev_id);
+       if (!dparms) {
+               BNXT_TF_DBG(DEBUG, "Failed to get device parms\n");
+               return -EINVAL;
+       }
+
+       /* Update the bp flag with gfid flag */
+       if (dparms->flow_mem_type == BNXT_ULP_FLOW_MEM_TYPE_EXT)
+               bp->flags |= BNXT_FLAG_GFID_ENABLE;
+
+       return 0;
+}
+
 static int32_t
 ulp_ctx_attach(struct bnxt_ulp_context *ulp_ctx,
               struct bnxt_ulp_session_state *session)
@@ -296,7 +451,7 @@ ulp_ctx_detach(struct bnxt *bp,
                BNXT_TF_DBG(ERR, "Invalid Arguments\n");
                return -EINVAL;
        }
-       ulp_ctx = &bp->ulp_ctx;
+       ulp_ctx = bp->ulp_ctx;
 
        if (!ulp_ctx->cfg_data)
                return 0;
@@ -433,6 +588,11 @@ bnxt_ulp_init(struct bnxt *bp)
        bool init;
        int rc;
 
+       if (bp->ulp_ctx) {
+               BNXT_TF_DBG(ERR, "ulp ctx already allocated\n");
+               return -EINVAL;
+       }
+
        /*
         * Multiple uplink ports can be associated with a single vswitch.
         * Make sure only the port that is started first will initialize
@@ -444,15 +604,46 @@ bnxt_ulp_init(struct bnxt *bp)
                return -EINVAL;
        }
 
+       bp->ulp_ctx = rte_zmalloc("bnxt_ulp_ctx",
+                                 sizeof(struct bnxt_ulp_context), 0);
+       if (!bp->ulp_ctx) {
+               BNXT_TF_DBG(ERR, "Failed to allocate ulp ctx\n");
+               ulp_session_deinit(session);
+               return -ENOMEM;
+       }
+
        /*
         * If ULP is already initialized for a specific domain then simply
         * assign the ulp context to this rte_eth_dev.
         */
        if (init) {
-               rc = ulp_ctx_attach(&bp->ulp_ctx, session);
+               rc = ulp_ctx_attach(bp->ulp_ctx, session);
                if (rc) {
                        BNXT_TF_DBG(ERR,
                                    "Failed to attach the ulp context\n");
+                       ulp_session_deinit(session);
+                       rte_free(bp->ulp_ctx);
+                       return rc;
+               }
+
+               /* Update bnxt driver flags */
+               rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx);
+               if (rc) {
+                       BNXT_TF_DBG(ERR, "Failed to update driver flags\n");
+                       ulp_ctx_detach(bp, session);
+                       ulp_session_deinit(session);
+                       rte_free(bp->ulp_ctx);
+                       return rc;
+               }
+
+               /* update the port database */
+               rc = ulp_port_db_dev_port_intf_update(bp->ulp_ctx, bp->eth_dev);
+               if (rc) {
+                       BNXT_TF_DBG(ERR,
+                                   "Failed to update port database\n");
+                       ulp_ctx_detach(bp, session);
+                       ulp_session_deinit(session);
+                       rte_free(bp->ulp_ctx);
                }
                return rc;
        }
@@ -464,15 +655,39 @@ bnxt_ulp_init(struct bnxt *bp)
                goto jump_to_error;
        }
 
+       /* Initialize ulp dparms with values devargs passed */
+       rc = ulp_dparms_init(bp, bp->ulp_ctx);
+
+       /* create the port database */
+       rc = ulp_port_db_init(bp->ulp_ctx, bp->port_cnt);
+       if (rc) {
+               BNXT_TF_DBG(ERR, "Failed to create the port database\n");
+               goto jump_to_error;
+       }
+
+       /* Update bnxt driver flags */
+       rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx);
+       if (rc) {
+               BNXT_TF_DBG(ERR, "Failed to update driver flags\n");
+               goto jump_to_error;
+       }
+
+       /* update the port database */
+       rc = ulp_port_db_dev_port_intf_update(bp->ulp_ctx, bp->eth_dev);
+       if (rc) {
+               BNXT_TF_DBG(ERR, "Failed to update port database\n");
+               goto jump_to_error;
+       }
+
        /* Create the Mark database. */
-       rc = ulp_mark_db_init(&bp->ulp_ctx);
+       rc = ulp_mark_db_init(bp->ulp_ctx);
        if (rc) {
                BNXT_TF_DBG(ERR, "Failed to create the mark database\n");
                goto jump_to_error;
        }
 
        /* Create the flow database. */
-       rc = ulp_flow_db_init(&bp->ulp_ctx);
+       rc = ulp_flow_db_init(bp->ulp_ctx);
        if (rc) {
                BNXT_TF_DBG(ERR, "Failed to create the flow database\n");
                goto jump_to_error;
@@ -485,6 +700,18 @@ bnxt_ulp_init(struct bnxt *bp)
                goto jump_to_error;
        }
 
+       rc = ulp_mapper_init(bp->ulp_ctx);
+       if (rc) {
+               BNXT_TF_DBG(ERR, "Failed to initialize ulp mapper\n");
+               goto jump_to_error;
+       }
+
+       rc = ulp_fc_mgr_init(bp->ulp_ctx);
+       if (rc) {
+               BNXT_TF_DBG(ERR, "Failed to initialize ulp flow counter mgr\n");
+               goto jump_to_error;
+       }
+
        return rc;
 
 jump_to_error:
@@ -518,22 +745,33 @@ bnxt_ulp_deinit(struct bnxt *bp)
                return;
 
        /* clean up regular flows */
-       ulp_flow_db_flush_flows(&bp->ulp_ctx, BNXT_ULP_REGULAR_FLOW_TABLE);
+       ulp_flow_db_flush_flows(bp->ulp_ctx, BNXT_ULP_REGULAR_FLOW_TABLE);
 
        /* cleanup the eem table scope */
-       ulp_eem_tbl_scope_deinit(bp, &bp->ulp_ctx);
+       ulp_eem_tbl_scope_deinit(bp, bp->ulp_ctx);
 
        /* cleanup the flow database */
-       ulp_flow_db_deinit(&bp->ulp_ctx);
+       ulp_flow_db_deinit(bp->ulp_ctx);
 
        /* Delete the Mark database */
-       ulp_mark_db_deinit(&bp->ulp_ctx);
+       ulp_mark_db_deinit(bp->ulp_ctx);
+
+       /* cleanup the ulp mapper */
+       ulp_mapper_deinit(bp->ulp_ctx);
+
+       /* Delete the Flow Counter Manager */
+       ulp_fc_mgr_deinit(bp->ulp_ctx);
+
+       /* Delete the Port database */
+       ulp_port_db_deinit(bp->ulp_ctx);
 
        /* Delete the ulp context and tf session */
        ulp_ctx_detach(bp, session);
 
        /* Finally delete the bnxt session*/
        ulp_session_deinit(session);
+
+       rte_free(bp->ulp_ctx);
 }
 
 /* Function to set the Mark DB into the context */
@@ -687,5 +925,76 @@ bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev *dev)
                BNXT_TF_DBG(ERR, "Bnxt private data is not initialized\n");
                return NULL;
        }
-       return &bp->ulp_ctx;
+       return bp->ulp_ctx;
+}
+
+int32_t
+bnxt_ulp_cntxt_ptr2_mapper_data_set(struct bnxt_ulp_context *ulp_ctx,
+                                   void *mapper_data)
+{
+       if (!ulp_ctx || !ulp_ctx->cfg_data) {
+               BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
+               return -EINVAL;
+       }
+
+       ulp_ctx->cfg_data->mapper_data = mapper_data;
+       return 0;
+}
+
+void *
+bnxt_ulp_cntxt_ptr2_mapper_data_get(struct bnxt_ulp_context *ulp_ctx)
+{
+       if (!ulp_ctx || !ulp_ctx->cfg_data) {
+               BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
+               return NULL;
+       }
+
+       return ulp_ctx->cfg_data->mapper_data;
+}
+
+/* Function to set the port database to the ulp context. */
+int32_t
+bnxt_ulp_cntxt_ptr2_port_db_set(struct bnxt_ulp_context        *ulp_ctx,
+                               struct bnxt_ulp_port_db *port_db)
+{
+       if (!ulp_ctx || !ulp_ctx->cfg_data)
+               return -EINVAL;
+
+       ulp_ctx->cfg_data->port_db = port_db;
+       return 0;
+}
+
+/* Function to get the port database from the ulp context. */
+struct bnxt_ulp_port_db *
+bnxt_ulp_cntxt_ptr2_port_db_get(struct bnxt_ulp_context        *ulp_ctx)
+{
+       if (!ulp_ctx || !ulp_ctx->cfg_data)
+               return NULL;
+
+       return ulp_ctx->cfg_data->port_db;
+}
+
+/* Function to set the flow counter info into the context */
+int32_t
+bnxt_ulp_cntxt_ptr2_fc_info_set(struct bnxt_ulp_context *ulp_ctx,
+                               struct bnxt_ulp_fc_info *ulp_fc_info)
+{
+       if (!ulp_ctx || !ulp_ctx->cfg_data) {
+               BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
+               return -EINVAL;
+       }
+
+       ulp_ctx->cfg_data->fc_info = ulp_fc_info;
+
+       return 0;
+}
+
+/* Function to retrieve the flow counter info from the context. */
+struct bnxt_ulp_fc_info *
+bnxt_ulp_cntxt_ptr2_fc_info_get(struct bnxt_ulp_context *ulp_ctx)
+{
+       if (!ulp_ctx || !ulp_ctx->cfg_data)
+               return NULL;
+
+       return ulp_ctx->cfg_data->fc_info;
 }