net/bnxt: support WC TCAM management

- Add new API to move WC TCAM regions from the hi pool
  to the low pool.
- Enable shared TCAM get/set functions on Thor.

Signed-off-by: Farah Smith <farah.smith@broadcom.com>
Signed-off-by: Randy Schacher <stuart.schacher@broadcom.com>
Signed-off-by: Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
This commit is contained in:
Farah Smith 2021-05-30 14:28:51 +05:30 committed by Ajit Khaparde
parent 1678535b30
commit 83680d3715
10 changed files with 673 additions and 37 deletions

View File

@ -917,6 +917,59 @@ tf_free_tcam_entry(struct tf *tfp,
return 0;
}
#ifdef TF_TCAM_SHARED
int
tf_move_tcam_shared_entries(struct tf *tfp,
struct tf_move_tcam_shared_entries_parms *parms)
{
int rc;
struct tf_session *tfs;
struct tf_dev_info *dev;
TF_CHECK_PARMS2(tfp, parms);
/* 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_tcam == NULL) {
rc = -EOPNOTSUPP;
TFP_DRV_LOG(ERR,
"%s: Operation not supported, rc:%s\n",
tf_dir_2_str(parms->dir),
strerror(-rc));
return rc;
}
rc = dev->ops->tf_dev_move_tcam(tfp, parms);
if (rc) {
TFP_DRV_LOG(ERR,
"%s: TCAM shared entries move failed, rc:%s\n",
tf_dir_2_str(parms->dir),
strerror(-rc));
return rc;
}
return 0;
}
#endif /* TF_TCAM_SHARED */
int
tf_alloc_tbl_entry(struct tf *tfp,
struct tf_alloc_tbl_entry_parms *parms)

View File

@ -1242,6 +1242,10 @@ int tf_free_tbl_scope(struct tf *tfp,
* @ref tf_get_tcam_entry
*
* @ref tf_free_tcam_entry
*
#ifdef TF_TCAM_SHARED
* @ref tf_move_tcam_shared_entries
#endif
*/
/**
@ -1543,6 +1547,41 @@ struct tf_free_tcam_entry_parms {
int tf_free_tcam_entry(struct tf *tfp,
struct tf_free_tcam_entry_parms *parms);
#ifdef TF_TCAM_SHARED
/**
* tf_move_tcam_shared_entries parameter definition
*/
struct tf_move_tcam_shared_entries_parms {
/**
* [in] receive or transmit direction
*/
enum tf_dir dir;
/**
* [in] TCAM table type
*/
enum tf_tcam_tbl_type tcam_tbl_type;
};
/**
* Move TCAM entries
*
* This API only affects the following TCAM pools within a shared session:
*
* TF_TCAM_TBL_TYPE_WC_TCAM_HIGH
* TF_TCAM_TBL_TYPE_WC_TCAM_LOW
*
* When called, all allocated entries from the high pool will be moved to
* the low pool. Then the allocated entries in the high pool will be
* cleared and freed.
*
* This API is not supported on a non-shared session.
*
* Returns success or failure code.
*/
int tf_move_tcam_shared_entries(struct tf *tfp,
struct tf_move_tcam_shared_entries_parms *parms);
#endif /* TF_TCAM_SHARED */
/**
* @page table Table Access
*

View File

@ -563,6 +563,24 @@ struct tf_dev_ops {
int (*tf_dev_get_tcam)(struct tf *tfp,
struct tf_tcam_get_parms *parms);
#ifdef TF_TCAM_SHARED
/**
* Move TCAM shared entries
*
* [in] tfp
* Pointer to TF handle
*
* [in] parms
* Pointer to parameters
*
* returns:
* 0 - Success
* -EINVAL - Error
*/
int (*tf_dev_move_tcam)(struct tf *tfp,
struct tf_move_tcam_shared_entries_parms *parms);
#endif /* TF_TCAM_SHARED */
/**
* Retrieves the tcam resource info.
*

View File

@ -272,6 +272,7 @@ const struct tf_dev_ops tf_dev_ops_p4 = {
.tf_dev_free_tcam = tf_tcam_shared_free,
.tf_dev_set_tcam = tf_tcam_shared_set,
.tf_dev_get_tcam = tf_tcam_shared_get,
.tf_dev_move_tcam = tf_tcam_shared_move_p4,
#else /* !TF_TCAM_SHARED */
.tf_dev_alloc_tcam = tf_tcam_alloc,
.tf_dev_free_tcam = tf_tcam_free,

View File

@ -292,8 +292,9 @@ const struct tf_dev_ops tf_dev_ops_p58 = {
#ifdef TF_TCAM_SHARED
.tf_dev_alloc_tcam = tf_tcam_shared_alloc,
.tf_dev_free_tcam = tf_tcam_shared_free,
.tf_dev_set_tcam = tf_tcam_set,
.tf_dev_get_tcam = tf_tcam_get,
.tf_dev_set_tcam = tf_tcam_shared_set,
.tf_dev_get_tcam = tf_tcam_shared_get,
.tf_dev_move_tcam = tf_tcam_shared_move_p58,
#else /* !TF_TCAM_SHARED */
.tf_dev_alloc_tcam = tf_tcam_alloc,
.tf_dev_free_tcam = tf_tcam_free,

View File

@ -945,3 +945,44 @@ tf_session_set_db(struct tf *tfp,
return rc;
}
#ifdef TF_TCAM_SHARED
int
tf_session_get_tcam_shared_db(struct tf *tfp,
void **tcam_shared_db_handle)
{
struct tf_session *tfs = NULL;
int rc = 0;
*tcam_shared_db_handle = NULL;
if (tfp == NULL)
return (-EINVAL);
rc = tf_session_get_session_internal(tfp, &tfs);
if (rc)
return rc;
*tcam_shared_db_handle = tfs->tcam_shared_db_handle;
return rc;
}
int
tf_session_set_tcam_shared_db(struct tf *tfp,
void *tcam_shared_db_handle)
{
struct tf_session *tfs = NULL;
int rc = 0;
if (tfp == NULL)
return (-EINVAL);
rc = tf_session_get_session_internal(tfp, &tfs);
if (rc)
return rc;
tfs->tcam_shared_db_handle = tcam_shared_db_handle;
return rc;
}
#endif /* TF_TCAM_SHARED */

View File

@ -159,6 +159,13 @@ struct tf_session {
* EM allocator for session
*/
void *em_pool[TF_DIR_MAX];
#ifdef TF_TCAM_SHARED
/**
* tcam db reference for the session
*/
void *tcam_shared_db_handle;
#endif /* TF_TCAM_SHARED */
};
/**
@ -255,6 +262,22 @@ struct tf_session_close_session_parms {
* @ref tf_session_get_fw_session_id
*
* @ref tf_session_get_session_id
*
* @ref tf_session_is_shared_session_creator
*
* @ref tf_session_get_db
*
* @ref tf_session_set_db
*
* @ref tf_session_get_bp
*
* @ref tf_session_is_shared_session
*
* #define TF_SHARED
* @ref tf_session_get_tcam_shared_db
*
* @ref tf_session_set_tcam_shared_db
* #endif
*/
/**
@ -566,4 +589,29 @@ tf_session_get_bp(struct tf *tfp)
{
return tfp->bp;
}
/**
* Set the pointer to the tcam shared database
*
* [in] session, pointer to the session
*
* Returns:
* - the pointer to the parent bnxt struct
*/
int
tf_session_set_tcam_shared_db(struct tf *tfp,
void *tcam_shared_db_handle);
/**
* Get the pointer to the tcam shared database
*
* [in] session, pointer to the session
*
* Returns:
* - the pointer to the parent bnxt struct
*/
int
tf_session_get_tcam_shared_db(struct tf *tfp,
void **tcam_shared_db_handle);
#endif /* _TF_SESSION_H_ */

View File

@ -299,7 +299,7 @@ tf_tcam_alloc(struct tf *tfp,
rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
if (rc) {
TFP_DRV_LOG(ERR,
"Failed to get em_ext_db from session, rc:%s\n",
"Failed to get tcam_db from session, rc:%s\n",
strerror(-rc));
return rc;
}

View File

@ -52,10 +52,34 @@ struct tf_tcam_shared_wc_pool {
struct bitalloc *pool;
};
struct tf_tcam_shared_wc_pools {
struct tf_tcam_shared_wc_pool db[TF_DIR_MAX][TF_TCAM_SHARED_WC_POOL_MAX];
};
/** The WC TCAM shared pool declarations
* TODO: add tcam_shared_wc_db
*/
struct tf_tcam_shared_wc_pool tcam_shared_wc[TF_DIR_MAX][TF_TCAM_SHARED_WC_POOL_MAX];
/* struct tf_tcam_shared_wc_pool tcam_shared_wc[TF_DIR_MAX][TF_TCAM_SHARED_WC_POOL_MAX]; */
static int
tf_tcam_shared_create_db(struct tf_tcam_shared_wc_pools **db)
{
struct tfp_calloc_parms cparms;
int rc = 0;
cparms.nitems = 1;
cparms.alignment = 0;
cparms.size = sizeof(struct tf_tcam_shared_wc_pools);
rc = tfp_calloc(&cparms);
if (rc) {
TFP_DRV_LOG(ERR,
"TCAM shared db allocation failed (%s)\n",
strerror(-rc));
return rc;
}
*db = cparms.mem_va;
return rc;
}
/** Create a WC TCAM shared pool
*/
@ -63,7 +87,8 @@ static int
tf_tcam_shared_create_wc_pool(int dir,
enum tf_tcam_shared_wc_pool_id id,
int start,
int stride)
int stride,
struct tf_tcam_shared_wc_pools *tcam_shared_wc)
{
int rc = 0;
bool free = true;
@ -83,9 +108,9 @@ tf_tcam_shared_create_wc_pool(int dir,
strerror(-rc));
return rc;
}
tcam_shared_wc[dir][id].pool = (struct bitalloc *)cparms.mem_va;
tcam_shared_wc->db[dir][id].pool = (struct bitalloc *)cparms.mem_va;
rc = ba_init(tcam_shared_wc[dir][id].pool,
rc = ba_init(tcam_shared_wc->db[dir][id].pool,
stride,
free);
@ -96,21 +121,27 @@ tf_tcam_shared_create_wc_pool(int dir,
return rc;
}
tcam_shared_wc[dir][id].info.start = start;
tcam_shared_wc[dir][id].info.stride = stride;
tcam_shared_wc->db[dir][id].info.start = start;
tcam_shared_wc->db[dir][id].info.stride = stride;
return rc;
}
/** Free a WC TCAM shared pool
*/
static void
static int
tf_tcam_shared_free_wc_pool(int dir,
enum tf_tcam_shared_wc_pool_id id)
enum tf_tcam_shared_wc_pool_id id,
struct tf_tcam_shared_wc_pools *tcam_shared_wc)
{
tcam_shared_wc[dir][id].info.start = 0;
tcam_shared_wc[dir][id].info.stride = 0;
int rc = 0;
TF_CHECK_PARMS1(tcam_shared_wc);
if (tcam_shared_wc[dir][id].pool)
tfp_free((void *)tcam_shared_wc[dir][id].pool);
tcam_shared_wc->db[dir][id].info.start = 0;
tcam_shared_wc->db[dir][id].info.stride = 0;
if (tcam_shared_wc->db[dir][id].pool)
tfp_free((void *)tcam_shared_wc->db[dir][id].pool);
return rc;
}
/** Get the number of WC TCAM slices allocated during 1 allocation/free
@ -136,7 +167,7 @@ tf_tcam_shared_get_slices(struct tf *tfp,
}
static bool
tf_tcam_shared_db_valid(struct tf *tfp,
tf_tcam_db_valid(struct tf *tfp,
enum tf_dir dir)
{
struct tcam_rm_db *tcam_db;
@ -225,6 +256,7 @@ tf_tcam_shared_bind(struct tf *tfp,
uint16_t start, stride;
uint16_t num_slices;
uint16_t hcapi_type;
struct tf_tcam_shared_wc_pools *tcam_shared_wc = NULL;
TF_CHECK_PARMS2(tfp, parms);
@ -255,11 +287,14 @@ tf_tcam_shared_bind(struct tf *tfp,
if (rc)
return rc;
tf_tcam_shared_create_db(&tcam_shared_wc);
/* If there are WC TCAM entries, create 2 pools each with 1/2
* the total number of entries
*/
for (dir = 0; dir < TF_DIR_MAX; dir++) {
if (!tf_tcam_shared_db_valid(tfp, dir))
if (!tf_tcam_db_valid(tfp, dir))
continue;
rc = tf_tcam_shared_get_rm_info(tfp,
@ -277,15 +312,19 @@ tf_tcam_shared_bind(struct tf *tfp,
stride = info.entry.stride / 2;
tf_tcam_shared_create_wc_pool(dir,
TF_TCAM_SHARED_WC_POOL_HI,
start,
stride);
TF_TCAM_SHARED_WC_POOL_HI,
start,
stride,
tcam_shared_wc);
start += stride;
tf_tcam_shared_create_wc_pool(dir,
TF_TCAM_SHARED_WC_POOL_LO,
start,
stride);
TF_TCAM_SHARED_WC_POOL_LO,
start,
stride,
tcam_shared_wc);
tf_session_set_tcam_shared_db(tfp, (void *)tcam_shared_wc);
}
}
done:
@ -299,6 +338,8 @@ tf_tcam_shared_unbind(struct tf *tfp)
{
int rc, dir;
struct tf_session *tfs;
void *tcam_shared_db_ptr = NULL;
struct tf_tcam_shared_wc_pools *tcam_shared_wc;
TF_CHECK_PARMS1(tfp);
@ -314,6 +355,15 @@ tf_tcam_shared_unbind(struct tf *tfp)
if (rc)
return rc;
rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
if (rc) {
TFP_DRV_LOG(ERR,
"Failed to get tcam_shared_db from session, rc:%s\n",
strerror(-rc));
return rc;
}
tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
/* If we are the shared session
*/
if (tf_session_is_shared_session(tfs)) {
@ -321,9 +371,11 @@ tf_tcam_shared_unbind(struct tf *tfp)
*/
for (dir = 0; dir < TF_DIR_MAX; dir++) {
tf_tcam_shared_free_wc_pool(dir,
TF_TCAM_SHARED_WC_POOL_HI);
TF_TCAM_SHARED_WC_POOL_HI,
tcam_shared_wc);
tf_tcam_shared_free_wc_pool(dir,
TF_TCAM_SHARED_WC_POOL_LO);
TF_TCAM_SHARED_WC_POOL_LO,
tcam_shared_wc);
}
}
return 0;
@ -342,6 +394,8 @@ tf_tcam_shared_alloc(struct tf *tfp,
struct bitalloc *pool;
enum tf_tcam_shared_wc_pool_id id;
uint16_t num_slices;
struct tf_tcam_shared_wc_pools *tcam_shared_wc;
void *tcam_shared_db_ptr = NULL;
TF_CHECK_PARMS2(tfp, parms);
@ -363,13 +417,22 @@ tf_tcam_shared_alloc(struct tf *tfp,
return rc;
}
if (!tf_tcam_shared_db_valid(tfp, parms->dir)) {
if (!tf_tcam_db_valid(tfp, parms->dir)) {
TFP_DRV_LOG(ERR,
"%s: tcam shared pool doesn't exist\n",
tf_dir_2_str(parms->dir));
return -ENOMEM;
}
rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
if (rc) {
TFP_DRV_LOG(ERR,
"Failed to get tcam_shared_db from session, rc:%s\n",
strerror(-rc));
return rc;
}
tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
id = TF_TCAM_SHARED_WC_POOL_HI;
else
@ -384,7 +447,7 @@ tf_tcam_shared_alloc(struct tf *tfp,
if (rc)
return rc;
pool = tcam_shared_wc[parms->dir][id].pool;
pool = tcam_shared_wc->db[parms->dir][id].pool;
for (i = 0; i < num_slices; i++) {
/*
@ -426,6 +489,8 @@ tf_tcam_shared_free(struct tf *tfp,
uint16_t num_slices;
uint16_t hcapi_type;
struct tf_rm_alloc_info info;
void *tcam_shared_db_ptr = NULL;
struct tf_tcam_shared_wc_pools *tcam_shared_wc;
TF_CHECK_PARMS2(tfp, parms);
@ -447,13 +512,23 @@ tf_tcam_shared_free(struct tf *tfp,
return rc;
}
if (!tf_tcam_shared_db_valid(tfp, parms->dir)) {
if (!tf_tcam_db_valid(tfp, parms->dir)) {
TFP_DRV_LOG(ERR,
"%s: tcam shared pool doesn't exist\n",
tf_dir_2_str(parms->dir));
return -ENOMEM;
}
rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
if (rc) {
TFP_DRV_LOG(ERR,
"Failed to get tcam_shared_db from session, rc:%s\n",
strerror(-rc));
return rc;
}
tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
id = TF_TCAM_SHARED_WC_POOL_HI;
else
@ -479,8 +554,8 @@ tf_tcam_shared_free(struct tf *tfp,
return rc;
}
pool = tcam_shared_wc[parms->dir][id].pool;
start = tcam_shared_wc[parms->dir][id].info.start;
pool = tcam_shared_wc->db[parms->dir][id].pool;
start = tcam_shared_wc->db[parms->dir][id].info.start;
if (parms->idx % num_slices) {
TFP_DRV_LOG(ERR,
@ -547,6 +622,9 @@ tf_tcam_shared_set(struct tf *tfp __rte_unused,
enum tf_tcam_shared_wc_pool_id id;
uint16_t hcapi_type;
struct tf_rm_alloc_info info;
struct tf_tcam_shared_wc_pools *tcam_shared_wc;
void *tcam_shared_db_ptr = NULL;
TF_CHECK_PARMS2(tfp, parms);
@ -567,7 +645,7 @@ tf_tcam_shared_set(struct tf *tfp __rte_unused,
return rc;
}
if (!tf_tcam_shared_db_valid(tfp, parms->dir)) {
if (!tf_tcam_db_valid(tfp, parms->dir)) {
TFP_DRV_LOG(ERR,
"%s: tcam shared pool doesn't exist\n",
tf_dir_2_str(parms->dir));
@ -584,8 +662,17 @@ tf_tcam_shared_set(struct tf *tfp __rte_unused,
else
id = TF_TCAM_SHARED_WC_POOL_LO;
pool = tcam_shared_wc[parms->dir][id].pool;
start = tcam_shared_wc[parms->dir][id].info.start;
rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
if (rc) {
TFP_DRV_LOG(ERR,
"Failed to get tcam_shared_db from session, rc:%s\n",
strerror(-rc));
return rc;
}
tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
pool = tcam_shared_wc->db[parms->dir][id].pool;
start = tcam_shared_wc->db[parms->dir][id].info.start;
log_idx = parms->idx;
phy_idx = parms->idx + start;
@ -655,6 +742,8 @@ tf_tcam_shared_get(struct tf *tfp __rte_unused,
enum tf_tcam_shared_wc_pool_id id;
uint16_t hcapi_type;
struct tf_rm_alloc_info info;
struct tf_tcam_shared_wc_pools *tcam_shared_wc;
void *tcam_shared_db_ptr = NULL;
TF_CHECK_PARMS2(tfp, parms);
@ -675,7 +764,7 @@ tf_tcam_shared_get(struct tf *tfp __rte_unused,
return rc;
}
if (!tf_tcam_shared_db_valid(tfp, parms->dir)) {
if (!tf_tcam_db_valid(tfp, parms->dir)) {
TFP_DRV_LOG(ERR,
"%s: tcam shared pool doesn't exist\n",
tf_dir_2_str(parms->dir));
@ -691,8 +780,18 @@ tf_tcam_shared_get(struct tf *tfp __rte_unused,
else
id = TF_TCAM_SHARED_WC_POOL_LO;
pool = tcam_shared_wc[parms->dir][id].pool;
start = tcam_shared_wc[parms->dir][id].info.start;
rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
if (rc) {
TFP_DRV_LOG(ERR,
"Failed to get tcam_shared_db from session, rc:%s\n",
strerror(-rc));
return rc;
}
tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
pool = tcam_shared_wc->db[parms->dir][id].pool;
start = tcam_shared_wc->db[parms->dir][id].info.start;
rc = tf_tcam_shared_get_slices(tfp, dev, &num_slices);
if (rc)
@ -741,3 +840,304 @@ tf_tcam_shared_get(struct tf *tfp __rte_unused,
}
return 0;
}
/* Temporary builder defines pulled in here and renamed
*/
#define TF_TMP_MAX_FIELD_BITLEN 512
union tf_tmp_field_obj {
uint8_t bytes[(TF_TMP_MAX_FIELD_BITLEN + 7) / 8];
};
#define TF_TMP_MAX_KEY_BITLEN 768
#define TF_TMP_MAX_KEY_WORDLEN ((TF_TMP_MAX_KEY_BITLEN + 63) / 64)
union tf_tmp_key {
uint32_t words[(TF_TMP_MAX_KEY_BITLEN + 31) / 32];
uint8_t bytes[(TF_TMP_MAX_KEY_BITLEN + 7) / 8];
};
/** Move a WC TCAM entry from the high offset to the same low offset
*/
static int
tf_tcam_shared_move_entry(struct tf *tfp,
struct tf_dev_info *dev,
uint16_t hcapi_type,
enum tf_dir dir,
int sphy_idx,
int dphy_idx,
int key_sz_bytes,
int remap_sz_bytes,
uint16_t num_slices)
{
int rc = 0;
struct tf_tcam_get_parms gparms;
struct tf_tcam_set_parms sparms;
struct tf_tcam_free_parms fparms;
union tf_tmp_key tcam_key_obj;
union tf_tmp_key tcam_key_msk_obj;
union tf_tmp_field_obj tcam_remap_obj;
memset(&tcam_key_obj, 0, sizeof(tcam_key_obj));
memset(&tcam_key_msk_obj, 0, sizeof(tcam_key_msk_obj));
memset(&tcam_remap_obj, 0, sizeof(tcam_remap_obj));
memset(&gparms, 0, sizeof(gparms));
if (num_slices > 1) {
TFP_DRV_LOG(ERR,
"Only single slice supported");
return -EOPNOTSUPP;
}
gparms.hcapi_type = hcapi_type;
gparms.dir = dir;
gparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
gparms.idx = sphy_idx;
gparms.key = (uint8_t *)&tcam_key_obj;
gparms.key_size = key_sz_bytes;
gparms.mask = (uint8_t *)&tcam_key_msk_obj;
gparms.result = (uint8_t *)&tcam_remap_obj;
gparms.result_size = remap_sz_bytes;
rc = tf_msg_tcam_entry_get(tfp, dev, &gparms);
if (rc) {
/* Log error */
TFP_DRV_LOG(ERR,
"%s: WC_TCAM_HIGH: phyid(%d) get failed, rc:%s",
tf_dir_2_str(dir),
gparms.idx,
strerror(-rc));
return rc;
}
/* Override HI/LO type with parent WC TCAM type */
sparms.hcapi_type = hcapi_type;
sparms.dir = dir;
sparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
sparms.idx = dphy_idx;
sparms.key = gparms.key;
sparms.mask = gparms.mask;
sparms.key_size = gparms.key_size;
sparms.result = gparms.result;
sparms.result_size = gparms.result_size;
rc = tf_msg_tcam_entry_set(tfp, dev, &sparms);
if (rc) {
/* Log error */
TFP_DRV_LOG(ERR,
"%s: WC_TCAM_LOW phyid(%d) set failed, rc:%s",
tf_dir_2_str(dir),
sparms.idx,
strerror(-rc));
return rc;
}
/* Override HI/LO type with parent WC TCAM type */
fparms.dir = dir;
fparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
fparms.hcapi_type = hcapi_type;
fparms.idx = sphy_idx;
rc = tf_msg_tcam_entry_free(tfp, dev, &fparms);
if (rc) {
/* Log error */
TFP_DRV_LOG(ERR,
"%s: %s: phyid(%d) free failed, rc:%s\n",
tf_dir_2_str(dir),
tf_tcam_tbl_2_str(fparms.type),
sphy_idx,
strerror(-rc));
return rc;
}
return rc;
}
/** Move all shared WC TCAM entries from the high pool into the low pool
* and clear out the high pool entries.
*/
static
int tf_tcam_shared_move(struct tf *tfp,
struct tf_move_tcam_shared_entries_parms *parms,
int key_sz_bytes,
int remap_sz_bytes)
{
int rc;
struct tf_session *tfs;
struct tf_dev_info *dev;
int log_idx;
uint16_t num_slices;
struct bitalloc *hi_pool, *lo_pool;
uint16_t hi_start, lo_start;
enum tf_tcam_shared_wc_pool_id hi_id, lo_id;
uint16_t hcapi_type;
struct tf_rm_alloc_info info;
int hi_cnt, i, j;
struct tf_tcam_shared_wc_pools *tcam_shared_wc;
void *tcam_shared_db_ptr = NULL;
TF_CHECK_PARMS2(tfp, parms);
/* Retrieve the session information */
rc = tf_session_get_session_internal(tfp, &tfs);
if (rc)
return rc;
/* If we aren't the shared session or one of our
* special types
*/
if (!tf_session_is_shared_session(tfs) ||
(parms->tcam_tbl_type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
parms->tcam_tbl_type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
TFP_DRV_LOG(ERR,
"%s: Session must be shared with HI/LO type\n",
tf_dir_2_str(parms->dir));
return -EOPNOTSUPP;
}
if (!tf_tcam_db_valid(tfp, parms->dir)) {
TFP_DRV_LOG(ERR,
"%s: tcam shared pool doesn't exist\n",
tf_dir_2_str(parms->dir));
return -ENOMEM;
}
/* Retrieve the device information */
rc = tf_session_get_device(tfs, &dev);
if (rc) {
/* TODO print amazing error */
return rc;
}
rc = tf_tcam_shared_get_slices(tfp, dev, &num_slices);
if (rc)
return rc;
rc = tf_tcam_shared_get_rm_info(tfp,
parms->dir,
&hcapi_type,
&info);
if (rc) {
TFP_DRV_LOG(ERR,
"%s: TCAM rm info get failed\n",
tf_dir_2_str(parms->dir));
return rc;
}
rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
if (rc) {
TFP_DRV_LOG(ERR,
"Failed to get tcam_shared_db from session, rc:%s\n",
strerror(-rc));
return rc;
}
tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
hi_id = TF_TCAM_SHARED_WC_POOL_HI;
hi_pool = tcam_shared_wc->db[parms->dir][hi_id].pool;
hi_start = tcam_shared_wc->db[parms->dir][hi_id].info.start;
lo_id = TF_TCAM_SHARED_WC_POOL_LO;
lo_pool = tcam_shared_wc->db[parms->dir][lo_id].pool;
lo_start = tcam_shared_wc->db[parms->dir][lo_id].info.start;
if (hi_pool == NULL || lo_pool == NULL)
return -ENOMEM;
/* Get the total count of in use entries in the high pool
*/
hi_cnt = ba_inuse_count(hi_pool);
/* Copy each valid entry to the same low pool logical offset
*/
for (i = 0; i < hi_cnt; i++) {
/* Go through all the slices
*/
for (j = 0; j < num_slices; j++) {
/* Find next free starting from where we left off
*/
log_idx = ba_find_next_inuse(hi_pool, i);
if (log_idx < 0) {
TFP_DRV_LOG(ERR,
"Expected a found %s entry %d\n",
tf_pool_2_str(hi_id),
i);
goto done;
}
/* The user should have never allocated from the low
* pool because the move only happens when switching
* from the high to the low pool
*/
if (ba_alloc_index(lo_pool, log_idx) < 0) {
TFP_DRV_LOG(ERR,
"Cannot allocate %s index %d\n",
tf_pool_2_str(lo_id),
i);
goto done;
}
if (j == 0) {
rc = tf_tcam_shared_move_entry(tfp, dev,
hcapi_type,
parms->dir,
hi_start + log_idx,
lo_start + log_idx,
key_sz_bytes,
remap_sz_bytes,
num_slices);
if (rc) {
TFP_DRV_LOG(ERR,
"Cannot allocate %s index %d\n",
tf_pool_2_str(hi_id),
i);
goto done;
}
ba_free(hi_pool, log_idx);
TFP_DRV_LOG(DEBUG,
"%s: TCAM shared move pool(%s) phyid(%d)\n",
tf_dir_2_str(parms->dir),
tf_pool_2_str(hi_id),
hi_start + log_idx);
TFP_DRV_LOG(DEBUG,
"to pool(%s) phyid(%d)\n",
tf_pool_2_str(lo_id),
lo_start + log_idx);
}
}
}
done:
return rc;
}
/* Normally, device specific code wouldn't reside here, it belongs
* in a separate device specific function in tf_device_pxx.c.
* But this code is placed here as it is not a long term solution
* and we would like to have this code centrally located for easy
* removal
*/
#define TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P4 12
#define TF_TCAM_SHARED_REMAP_SZ_BYTES_P4 4
int tf_tcam_shared_move_p4(struct tf *tfp,
struct tf_move_tcam_shared_entries_parms *parms)
{
int rc = 0;
rc = tf_tcam_shared_move(tfp,
parms,
TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P4,
TF_TCAM_SHARED_REMAP_SZ_BYTES_P4);
return rc;
}
#define TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58 24
#define TF_TCAM_SHARED_REMAP_SZ_BYTES_P58 8
int tf_tcam_shared_move_p58(struct tf *tfp,
struct tf_move_tcam_shared_entries_parms *parms)
{
int rc = 0;
rc = tf_tcam_shared_move(tfp,
parms,
TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58,
TF_TCAM_SHARED_REMAP_SZ_BYTES_P58);
return rc;
}

View File

@ -124,4 +124,39 @@ int tf_tcam_shared_set(struct tf *tfp,
int tf_tcam_shared_get(struct tf *tfp,
struct tf_tcam_get_parms *parms);
/**
* Moves entries from the WC_TCAM_HI to the WC_TCAM_LO shared pools
* for the P4 device.
*
* [in] tfp
* Pointer to the truflow handle
*
* [in] parms
* Pointer to parameters
*
* Returns
* - (0) if successful.
* - (-EINVAL) on failure.
*/
int tf_tcam_shared_move_p4(struct tf *tfp,
struct tf_move_tcam_shared_entries_parms *parms);
/**
* Moves entries from the WC_TCAM_HI to the WC_TCAM_LO shared pools
* for the P58 device.
*
* [in] tfp
* Pointer to the truflow handle
*
* [in] parms
* Pointer to parameters
*
* Returns
* - (0) if successful.
* - (-EINVAL) on failure.
*/
int tf_tcam_shared_move_p58(struct tf *tfp,
struct tf_move_tcam_shared_entries_parms *parms);
#endif /* _TF_TCAM_SHARED_H */