net/bnxt: modify table processing
[dpdk.git] / drivers / net / bnxt / tf_core / tf_em_internal.c
index c95515b..0720bb9 100644 (file)
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2019-2020 Broadcom
+ * Copyright(c) 2019-2021 Broadcom
  * All rights reserved.
  */
 
 #include "tf_msg.h"
 #include "tfp.h"
 #include "tf_ext_flow_handle.h"
-
 #include "bnxt.h"
 
-/**
- * EM DBs.
- */
-static void *em_db[TF_DIR_MAX];
-
 #define TF_EM_DB_EM_REC 0
 
-/**
- * Init flag, set on bind and cleared on unbind
- */
-static uint8_t init;
-
-
 /**
  * EM Pool
  */
-static struct stack em_pool[TF_DIR_MAX];
+#if (TF_EM_ALLOC == 1)
+#include "dpool.h"
+#else
 
 /**
  * Create EM Tbl pool of memory indexes.
@@ -52,14 +42,35 @@ static struct stack em_pool[TF_DIR_MAX];
  *          - Failure, entry not allocated, out of resources
  */
 static int
-tf_create_em_pool(enum tf_dir dir,
+tf_create_em_pool(struct tf_session *tfs,
+                 enum tf_dir dir,
                  uint32_t num_entries,
                  uint32_t start)
 {
        struct tfp_calloc_parms parms;
        uint32_t i, j;
        int rc = 0;
-       struct stack *pool = &em_pool[dir];
+       struct stack *pool;
+
+       /*
+        * Allocate stack pool
+        */
+       parms.nitems = 1;
+       parms.size = sizeof(struct stack);
+       parms.alignment = 0;
+
+       rc = tfp_calloc(&parms);
+
+       if (rc) {
+               TFP_DRV_LOG(ERR,
+                           "%s, EM stack allocation failure %s\n",
+                           tf_dir_2_str(dir),
+                           strerror(-rc));
+               return rc;
+       }
+
+       pool = (struct stack *)parms.mem_va;
+       tfs->em_pool[dir] = (void *)pool;
 
        /* Assumes that num_entries has been checked before we get here */
        parms.nitems = num_entries / TF_SESSION_EM_ENTRY_SIZE;
@@ -119,6 +130,8 @@ tf_create_em_pool(enum tf_dir dir,
        return 0;
 cleanup:
        tfp_free((void *)parms.mem_va);
+       tfp_free((void *)tfs->em_pool[dir]);
+       tfs->em_pool[dir] = NULL;
        return rc;
 }
 
@@ -131,16 +144,23 @@ cleanup:
  * Return:
  */
 static void
-tf_free_em_pool(enum tf_dir dir)
+tf_free_em_pool(struct tf_session *tfs,
+               enum tf_dir dir)
 {
-       struct stack *pool = &em_pool[dir];
+       struct stack *pool = (struct stack *)tfs->em_pool[dir];
        uint32_t *ptr;
 
-       ptr = stack_items(pool);
+       if (pool != NULL) {
+               ptr = stack_items(pool);
+
+               if (ptr != NULL)
+                       tfp_free(ptr);
 
-       if (ptr != NULL)
-               tfp_free(ptr);
+               tfp_free(pool);
+               tfs->em_pool[dir] = NULL;
+       }
 }
+#endif /* TF_EM_ALLOC != 1 */
 
 /**
  * Insert EM internal entry API
@@ -157,17 +177,44 @@ tf_em_insert_int_entry(struct tf *tfp,
        uint16_t rptr_index = 0;
        uint8_t rptr_entry = 0;
        uint8_t num_of_entries = 0;
-       struct stack *pool = &em_pool[parms->dir];
+       struct tf_session *tfs;
+#if (TF_EM_ALLOC == 1)
+       struct dpool *pool;
+#else
+       struct stack *pool;
+#endif
        uint32_t index;
 
-       rc = stack_pop(pool, &index);
+       /* Retrieve the session information */
+       rc = tf_session_get_session(tfp, &tfs);
+       if (rc) {
+               TFP_DRV_LOG(ERR,
+                           "%s: Failed to lookup session, rc:%s\n",
+                           tf_dir_2_str(parms->dir),
+                           strerror(-rc));
+               return rc;
+       }
 
+#if (TF_EM_ALLOC == 1)
+       pool = (struct dpool *)tfs->em_pool[parms->dir];
+       index = dpool_alloc(pool, TF_SESSION_EM_ENTRY_SIZE, 0);
+       if (index == DP_INVALID_INDEX) {
+               PMD_DRV_LOG(ERR,
+                           "%s, EM entry index allocation failed\n",
+                           tf_dir_2_str(parms->dir));
+               return -1;
+       }
+#else
+       pool = (struct stack *)tfs->em_pool[parms->dir];
+       rc = stack_pop(pool, &index);
        if (rc) {
                PMD_DRV_LOG(ERR,
                            "%s, EM entry index allocation failed\n",
                            tf_dir_2_str(parms->dir));
                return rc;
        }
+#endif
+
 
        rptr_index = index;
        rc = tf_msg_insert_em_internal_entry(tfp,
@@ -177,19 +224,13 @@ tf_em_insert_int_entry(struct tf *tfp,
                                             &num_of_entries);
        if (rc) {
                /* Free the allocated index before returning */
+#if (TF_EM_ALLOC == 1)
+               dpool_free(pool, index);
+#else
                stack_push(pool, index);
+#endif
                return -1;
        }
-
-       PMD_DRV_LOG
-                 (DEBUG,
-                  "%s, Internal entry @ Index:%d rptr_index:0x%x rptr_entry:0x%x num_of_entries:%d\n",
-                  tf_dir_2_str(parms->dir),
-                  index,
-                  rptr_index,
-                  rptr_entry,
-                  num_of_entries);
-
        TF_SET_GFID(gfid,
                    ((rptr_index << TF_EM_INTERNAL_INDEX_SHIFT) |
                     rptr_entry),
@@ -203,7 +244,7 @@ tf_em_insert_int_entry(struct tf *tfp,
        TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
                                     (uint32_t)num_of_entries,
                                     0,
-                                    0,
+                                    TF_FLAGS_FLOW_HANDLE_INTERNAL,
                                     rptr_index,
                                     rptr_entry,
                                     0);
@@ -222,37 +263,124 @@ tf_em_delete_int_entry(struct tf *tfp,
                       struct tf_delete_em_entry_parms *parms)
 {
        int rc = 0;
-       struct stack *pool = &em_pool[parms->dir];
+       struct tf_session *tfs;
+#if (TF_EM_ALLOC == 1)
+       struct dpool *pool;
+#else
+       struct stack *pool;
+#endif
+       /* Retrieve the session information */
+       rc = tf_session_get_session(tfp, &tfs);
+       if (rc) {
+               TFP_DRV_LOG(ERR,
+                           "%s: Failed to lookup session, rc:%s\n",
+                           tf_dir_2_str(parms->dir),
+                           strerror(-rc));
+               return rc;
+       }
 
        rc = tf_msg_delete_em_entry(tfp, parms);
 
        /* Return resource to pool */
-       if (rc == 0)
+       if (rc == 0) {
+#if (TF_EM_ALLOC == 1)
+               pool = (struct dpool *)tfs->em_pool[parms->dir];
+               dpool_free(pool, parms->index);
+#else
+               pool = (struct stack *)tfs->em_pool[parms->dir];
                stack_push(pool, parms->index);
+#endif
+       }
 
        return rc;
 }
 
+#if (TF_EM_ALLOC == 1)
+static int
+tf_em_move_callback(void *user_data,
+                   uint64_t entry_data,
+                   uint32_t new_index)
+{
+       int rc;
+       struct tf *tfp = (struct tf *)user_data;
+       struct tf_move_em_entry_parms parms;
+       struct tf_dev_info     *dev;
+       struct tf_session      *tfs;
+
+       memset(&parms, 0, sizeof(parms));
+
+       parms.tbl_scope_id = 0;
+       parms.flow_handle  = entry_data;
+       parms.new_index    = new_index;
+       TF_GET_DIR_FROM_FLOW_ID(entry_data, parms.dir);
+       parms.mem          = TF_MEM_INTERNAL;
+
+       /* Retrieve the session information */
+       rc = tf_session_get_session(tfp, &tfs);
+       if (rc) {
+               TFP_DRV_LOG(ERR,
+                           "%s: Failed to lookup session, rc:%s\n",
+                           tf_dir_2_str(parms.dir),
+                           strerror(-rc));
+               return rc;
+       }
+
+       /* Retrieve the device information */
+       rc = tf_session_get_device(tfs, &dev);
+       if (rc) {
+               TFP_DRV_LOG(ERR,
+                           "%s: Failed to lookup device, rc:%s\n",
+                           tf_dir_2_str(parms.dir),
+                           strerror(-rc));
+               return rc;
+       }
+
+       if (dev->ops->tf_dev_move_int_em_entry != NULL)
+               rc = dev->ops->tf_dev_move_int_em_entry(tfp, &parms);
+       else
+               rc = -EOPNOTSUPP;
+
+       return rc;
+}
+#endif
+
 int
 tf_em_int_bind(struct tf *tfp,
               struct tf_em_cfg_parms *parms)
 {
        int rc;
+       int db_rc[TF_DIR_MAX] = { 0 };
        int i;
        struct tf_rm_create_db_parms db_cfg = { 0 };
-       uint8_t db_exists = 0;
        struct tf_rm_get_alloc_info_parms iparms;
        struct tf_rm_alloc_info info;
+       struct em_rm_db *em_db;
+       struct tfp_calloc_parms cparms;
+       struct tf_session *tfs;
 
        TF_CHECK_PARMS2(tfp, parms);
 
-       if (init) {
-               TFP_DRV_LOG(ERR,
-                           "EM Int DB already initialized\n");
-               return -EINVAL;
+       /* Retrieve the session information */
+       rc = tf_session_get_session_internal(tfp, &tfs);
+       if (rc)
+               return rc;
+
+       memset(&db_cfg, 0, sizeof(db_cfg));
+       cparms.nitems = 1;
+       cparms.size = sizeof(struct em_rm_db);
+       cparms.alignment = 0;
+       if (tfp_calloc(&cparms) != 0) {
+               TFP_DRV_LOG(ERR, "em_rm_db alloc error %s\n",
+                           strerror(ENOMEM));
+               return -ENOMEM;
        }
 
-       db_cfg.type = TF_DEVICE_MODULE_TYPE_EM;
+       em_db = cparms.mem_va;
+       for (i = 0; i < TF_DIR_MAX; i++)
+               em_db->em_db[i] = NULL;
+       tf_session_set_db(tfp, TF_MODULE_TYPE_EM, em_db);
+
+       db_cfg.module = TF_MODULE_TYPE_EM;
        db_cfg.num_elements = parms->num_elements;
        db_cfg.cfg = parms->cfg;
 
@@ -278,43 +406,79 @@ tf_em_int_bind(struct tf *tfp,
                        return rc;
                }
 
-               db_cfg.rm_db = &em_db[i];
-               rc = tf_rm_create_db(tfp, &db_cfg);
-               if (rc) {
-                       TFP_DRV_LOG(ERR,
-                                   "%s: EM Int DB creation failed\n",
-                                   tf_dir_2_str(i));
+               db_cfg.rm_db = (void *)&em_db->em_db[i];
+               if (tf_session_is_shared_session(tfs) &&
+                       (!tf_session_is_shared_session_creator(tfs)))
+                       db_rc[i] = tf_rm_create_db_no_reservation(tfp, &db_cfg);
+               else
+                       db_rc[i] = tf_rm_create_db(tfp, &db_cfg);
+       }
 
-                       return rc;
-               }
-               db_exists = 1;
+       /* No db created */
+       if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) {
+               TFP_DRV_LOG(ERR, "EM Int DB creation failed\n");
+               return db_rc[TF_DIR_RX];
        }
 
-       if (db_exists)
-               init = 1;
 
-       for (i = 0; i < TF_DIR_MAX; i++) {
-               iparms.rm_db = em_db[i];
-               iparms.db_index = TF_EM_DB_EM_REC;
-               iparms.info = &info;
+       if (!tf_session_is_shared_session(tfs)) {
+               for (i = 0; i < TF_DIR_MAX; i++) {
+                       iparms.rm_db = em_db->em_db[i];
+                       iparms.subtype = TF_EM_DB_EM_REC;
+                       iparms.info = &info;
+
+                       rc = tf_rm_get_info(&iparms);
+                       if (rc) {
+                               TFP_DRV_LOG(ERR,
+                                           "%s: EM DB get info failed\n",
+                                           tf_dir_2_str(i));
+                               return rc;
+                       }
+#if (TF_EM_ALLOC == 1)
+                       /*
+                        * Allocate stack pool
+                        */
+                       cparms.nitems = 1;
+                       cparms.size = sizeof(struct dpool);
+                       cparms.alignment = 0;
+
+                       rc = tfp_calloc(&cparms);
+
+                       if (rc) {
+                               TFP_DRV_LOG(ERR,
+                                        "%s, EM stack allocation failure %s\n",
+                                        tf_dir_2_str(i),
+                                        strerror(-rc));
+                               return rc;
+                       }
+
+                       tfs->em_pool[i] = (struct dpool *)cparms.mem_va;
+
+                       rc = dpool_init(tfs->em_pool[i],
+                                       iparms.info->entry.start,
+                                       iparms.info->entry.stride,
+                                       7,
+                                       (void *)tfp,
+                                       tf_em_move_callback);
+#else
+                       rc = tf_create_em_pool(tfs,
+                                      i,
+                                      iparms.info->entry.stride,
+                                      iparms.info->entry.start);
+#endif
+                       /* Logging handled in tf_create_em_pool */
+                       if (rc)
+                               return rc;
+               }
 
-               rc = tf_rm_get_info(&iparms);
                if (rc) {
                        TFP_DRV_LOG(ERR,
-                                   "%s: EM DB get info failed\n",
+                                   "%s: EM pool init failed\n",
                                    tf_dir_2_str(i));
                        return rc;
                }
-
-               rc = tf_create_em_pool(i,
-                                      iparms.info->entry.stride,
-                                      iparms.info->entry.start);
-               /* Logging handled in tf_create_em_pool */
-               if (rc)
-                       return rc;
        }
 
-
        return 0;
 }
 
@@ -324,32 +488,82 @@ tf_em_int_unbind(struct tf *tfp)
        int rc;
        int i;
        struct tf_rm_free_db_parms fparms = { 0 };
+       struct em_rm_db *em_db;
+       void *em_db_ptr = NULL;
+       struct tf_session *tfs;
 
        TF_CHECK_PARMS1(tfp);
 
-       /* Bail if nothing has been initialized */
-       if (!init) {
-               TFP_DRV_LOG(INFO,
-                           "No EM Int DBs created\n");
-               return 0;
+       /* Retrieve the session information */
+       rc = tf_session_get_session_internal(tfp, &tfs);
+       if (rc)
+               return rc;
+
+       if (!tf_session_is_shared_session(tfs)) {
+               for (i = 0; i < TF_DIR_MAX; i++)
+#if (TF_EM_ALLOC == 1)
+                       dpool_free_all(tfs->em_pool[i]);
+#else
+               tf_free_em_pool(tfs, i);
+#endif
        }
 
-       for (i = 0; i < TF_DIR_MAX; i++)
-               tf_free_em_pool(i);
+       rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr);
+       if (rc) {
+               return 0;
+       }
+       em_db = (struct em_rm_db *)em_db_ptr;
 
        for (i = 0; i < TF_DIR_MAX; i++) {
+               if (em_db->em_db[i] == NULL)
+                       continue;
                fparms.dir = i;
-               fparms.rm_db = em_db[i];
-               if (em_db[i] != NULL) {
-                       rc = tf_rm_free_db(tfp, &fparms);
-                       if (rc)
-                               return rc;
-               }
+               fparms.rm_db = em_db->em_db[i];
+               rc = tf_rm_free_db(tfp, &fparms);
+               if (rc)
+                       return rc;
 
-               em_db[i] = NULL;
+               em_db->em_db[i] = NULL;
        }
 
-       init = 0;
+       return 0;
+}
+
+int
+tf_em_get_resc_info(struct tf *tfp,
+                   struct tf_em_resource_info *em)
+{
+       int rc;
+       int d;
+       struct tf_resource_info *dinfo;
+       struct tf_rm_get_alloc_info_parms ainfo;
+       void *em_db_ptr = NULL;
+       struct em_rm_db *em_db;
+
+       TF_CHECK_PARMS2(tfp, em);
+
+       rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr);
+       if (rc == -ENOMEM)
+               return 0;  /* db does not exist */
+       else if (rc)
+               return rc; /* db error */
+
+       em_db = (struct em_rm_db *)em_db_ptr;
+
+       /* check if reserved resource for EM is multiple of num_slices */
+       for (d = 0; d < TF_DIR_MAX; d++) {
+               ainfo.rm_db = em_db->em_db[d];
+               dinfo = em[d].info;
+
+               if (!ainfo.rm_db)
+                       continue;
+
+               ainfo.info = (struct tf_rm_alloc_info *)dinfo;
+               ainfo.subtype = 0;
+               rc = tf_rm_get_all_info(&ainfo, TF_EM_TBL_TYPE_MAX);
+               if (rc && rc != -ENOTSUP)
+                       return rc;
+       }
 
        return 0;
 }