net/bnxt: support TruFlow core TCAM

- Add TruFlow TCAM public API functions
- Add TCAM support functions as well as public APIs.

Signed-off-by: Shahaji Bhosle <sbhosle@broadcom.com>
Signed-off-by: Jay Ding <jay.ding@broadcom.com>
Reviewed-by: Randy Schacher <stuart.schacher@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
This commit is contained in:
Shahaji Bhosle 2020-04-15 13:48:47 +05:30 committed by Ferruh Yigit
parent 6cf2f95d4d
commit 82fa189de8
4 changed files with 579 additions and 0 deletions

View File

@ -440,3 +440,166 @@ int tf_free_identifier(struct tf *tfp,
return 0;
}
int
tf_alloc_tcam_entry(struct tf *tfp,
struct tf_alloc_tcam_entry_parms *parms)
{
int rc;
int index;
struct tf_session *tfs;
struct bitalloc *session_pool;
if (parms == NULL || tfp == NULL)
return -EINVAL;
if (tfp->session == NULL || tfp->session->core_data == NULL) {
PMD_DRV_LOG(ERR, "%s: session error\n",
tf_dir_2_str(parms->dir));
return -EINVAL;
}
tfs = (struct tf_session *)(tfp->session->core_data);
rc = tf_rm_lookup_tcam_type_pool(tfs,
parms->dir,
parms->tcam_tbl_type,
&session_pool);
/* Error logging handled by tf_rm_lookup_tcam_type_pool */
if (rc)
return rc;
index = ba_alloc(session_pool);
if (index == BA_FAIL) {
PMD_DRV_LOG(ERR, "%s: %s: No resource available\n",
tf_dir_2_str(parms->dir),
tf_tcam_tbl_2_str(parms->tcam_tbl_type));
return -ENOMEM;
}
parms->idx = index;
return 0;
}
int
tf_set_tcam_entry(struct tf *tfp,
struct tf_set_tcam_entry_parms *parms)
{
int rc;
int id;
struct tf_session *tfs;
struct bitalloc *session_pool;
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,
"%s, Session info invalid\n",
tf_dir_2_str(parms->dir));
return -EINVAL;
}
tfs = (struct tf_session *)(tfp->session->core_data);
/*
* Each tcam send msg function should check for key sizes range
*/
rc = tf_rm_lookup_tcam_type_pool(tfs,
parms->dir,
parms->tcam_tbl_type,
&session_pool);
/* Error logging handled by tf_rm_lookup_tcam_type_pool */
if (rc)
return rc;
/* Verify that the entry has been previously allocated */
id = ba_inuse(session_pool, parms->idx);
if (id != 1) {
PMD_DRV_LOG(ERR,
"%s: %s: Invalid or not allocated index, idx:%d\n",
tf_dir_2_str(parms->dir),
tf_tcam_tbl_2_str(parms->tcam_tbl_type),
parms->idx);
return -EINVAL;
}
rc = tf_msg_tcam_entry_set(tfp, parms);
return rc;
}
int
tf_get_tcam_entry(struct tf *tfp __rte_unused,
struct tf_get_tcam_entry_parms *parms __rte_unused)
{
int rc = -EOPNOTSUPP;
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,
"%s, Session info invalid\n",
tf_dir_2_str(parms->dir));
return -EINVAL;
}
return rc;
}
int
tf_free_tcam_entry(struct tf *tfp,
struct tf_free_tcam_entry_parms *parms)
{
int rc;
struct tf_session *tfs;
struct bitalloc *session_pool;
if (parms == NULL || tfp == NULL)
return -EINVAL;
if (tfp->session == NULL || tfp->session->core_data == NULL) {
PMD_DRV_LOG(ERR, "%s: Session error\n",
tf_dir_2_str(parms->dir));
return -EINVAL;
}
tfs = (struct tf_session *)(tfp->session->core_data);
rc = tf_rm_lookup_tcam_type_pool(tfs,
parms->dir,
parms->tcam_tbl_type,
&session_pool);
/* Error logging handled by tf_rm_lookup_tcam_type_pool */
if (rc)
return rc;
rc = ba_inuse(session_pool, (int)parms->idx);
if (rc == BA_FAIL || rc == BA_ENTRY_FREE) {
PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
tf_dir_2_str(parms->dir),
tf_tcam_tbl_2_str(parms->tcam_tbl_type),
parms->idx);
return -EINVAL;
}
ba_free(session_pool, (int)parms->idx);
rc = tf_msg_tcam_entry_free(tfp, parms);
if (rc) {
/* Log error */
PMD_DRV_LOG(ERR, "%s: %s: Entry %d free failed",
tf_dir_2_str(parms->dir),
tf_tcam_tbl_2_str(parms->tcam_tbl_type),
parms->idx);
}
return rc;
}

View File

@ -471,6 +471,233 @@ enum tf_tcam_tbl_type {
};
/**
* @page tcam TCAM Access
*
* @ref tf_alloc_tcam_entry
*
* @ref tf_set_tcam_entry
*
* @ref tf_get_tcam_entry
*
* @ref tf_free_tcam_entry
*/
/** tf_alloc_tcam_entry parameter definition
*/
struct tf_alloc_tcam_entry_parms {
/**
* [in] receive or transmit direction
*/
enum tf_dir dir;
/**
* [in] TCAM table type
*/
enum tf_tcam_tbl_type tcam_tbl_type;
/**
* [in] Enable search for matching entry
*/
uint8_t search_enable;
/**
* [in] Key data to match on (if search)
*/
uint8_t *key;
/**
* [in] key size in bits (if search)
*/
uint16_t key_sz_in_bits;
/**
* [in] Mask data to match on (if search)
*/
uint8_t *mask;
/**
* [in] Priority of entry requested (definition TBD)
*/
uint32_t priority;
/**
* [out] If search, set if matching entry found
*/
uint8_t hit;
/**
* [out] Current refcnt after allocation
*/
uint16_t ref_cnt;
/**
* [out] Idx allocated
*
*/
uint16_t idx;
};
/** allocate TCAM entry
*
* Allocate a TCAM entry - one of these types:
*
* L2 Context
* Profile TCAM
* WC TCAM
* VEB TCAM
*
* This function allocates a TCAM table record. This function
* will attempt to allocate a TCAM table entry from the session
* owned TCAM entries or search a shadow copy of the TCAM table for a
* matching entry if search is enabled. Key, mask and result must match for
* hit to be set. Only TruFlow core data is accessed.
* A hash table to entry mapping is maintained for search purposes. If
* search is not enabled, the first available free entry is returned based
* on priority and alloc_cnt is set to 1. If search is enabled and a matching
* entry to entry_data is found, hit is set to TRUE and alloc_cnt is set to 1.
* RefCnt is also returned.
*
* Also returns success or failure code.
*/
int tf_alloc_tcam_entry(struct tf *tfp,
struct tf_alloc_tcam_entry_parms *parms);
/** tf_set_tcam_entry parameter definition
*/
struct tf_set_tcam_entry_parms {
/**
* [in] receive or transmit direction
*/
enum tf_dir dir;
/**
* [in] TCAM table type
*/
enum tf_tcam_tbl_type tcam_tbl_type;
/**
* [in] base index of the entry to program
*/
uint16_t idx;
/**
* [in] struct containing key
*/
uint8_t *key;
/**
* [in] struct containing mask fields
*/
uint8_t *mask;
/**
* [in] key size in bits (if search)
*/
uint16_t key_sz_in_bits;
/**
* [in] struct containing result
*/
uint8_t *result;
/**
* [in] struct containing result size in bits
*/
uint16_t result_sz_in_bits;
};
/** set TCAM entry
*
* Program a TCAM table entry for a TruFlow session.
*
* If the entry has not been allocated, an error will be returned.
*
* Returns success or failure code.
*/
int tf_set_tcam_entry(struct tf *tfp,
struct tf_set_tcam_entry_parms *parms);
/** tf_get_tcam_entry parameter definition
*/
struct tf_get_tcam_entry_parms {
/**
* [in] receive or transmit direction
*/
enum tf_dir dir;
/**
* [in] TCAM table type
*/
enum tf_tcam_tbl_type tcam_tbl_type;
/**
* [in] index of the entry to get
*/
uint16_t idx;
/**
* [out] struct containing key
*/
uint8_t *key;
/**
* [out] struct containing mask fields
*/
uint8_t *mask;
/**
* [out] key size in bits
*/
uint16_t key_sz_in_bits;
/**
* [out] struct containing result
*/
uint8_t *result;
/**
* [out] struct containing result size in bits
*/
uint16_t result_sz_in_bits;
};
/** get TCAM entry
*
* Program a TCAM table entry for a TruFlow session.
*
* If the entry has not been allocated, an error will be returned.
*
* Returns success or failure code.
*/
int tf_get_tcam_entry(struct tf *tfp,
struct tf_get_tcam_entry_parms *parms);
/** tf_free_tcam_entry parameter definition
*/
struct tf_free_tcam_entry_parms {
/**
* [in] receive or transmit direction
*/
enum tf_dir dir;
/**
* [in] TCAM table type
*/
enum tf_tcam_tbl_type tcam_tbl_type;
/**
* [in] Index to free
*/
uint16_t idx;
/**
* [out] reference count after free
*/
uint16_t ref_cnt;
};
/** free TCAM entry
*
* Free TCAM entry.
*
* Firmware checks to ensure the TCAM entries are owned by the TruFlow
* session. TCAM entry will be invalidated. All-ones mask.
* writes to hw.
*
* WCTCAM profile id of 0 must be used to invalidate an entry.
*
* Returns success or failure code.
*/
int tf_free_tcam_entry(struct tf *tfp,
struct tf_free_tcam_entry_parms *parms);
/**
* @page table Table Access
*
* @ref tf_alloc_tbl_entry
*
* @ref tf_free_tbl_entry
*
* @ref tf_set_tbl_entry
*
* @ref tf_get_tbl_entry
*/
/**
* Enumeration of TruFlow table types. A table type is used to identify a
* resource object.

View File

@ -106,6 +106,39 @@ struct tf_msg_dma_buf {
uint64_t pa_addr;
};
static int
tf_tcam_tbl_2_hwrm(enum tf_tcam_tbl_type tcam_type,
uint32_t *hwrm_type)
{
int rc = 0;
switch (tcam_type) {
case TF_TCAM_TBL_TYPE_L2_CTXT_TCAM:
*hwrm_type = TF_DEV_DATA_TYPE_TF_L2_CTX_ENTRY;
break;
case TF_TCAM_TBL_TYPE_PROF_TCAM:
*hwrm_type = TF_DEV_DATA_TYPE_TF_PROF_TCAM_ENTRY;
break;
case TF_TCAM_TBL_TYPE_WC_TCAM:
*hwrm_type = TF_DEV_DATA_TYPE_TF_WC_ENTRY;
break;
case TF_TCAM_TBL_TYPE_VEB_TCAM:
rc = -EOPNOTSUPP;
break;
case TF_TCAM_TBL_TYPE_SP_TCAM:
rc = -EOPNOTSUPP;
break;
case TF_TCAM_TBL_TYPE_CT_RULE_TCAM:
rc = -EOPNOTSUPP;
break;
default:
rc = -EOPNOTSUPP;
break;
}
return rc;
}
/**
* Sends session open request to TF Firmware
*/
@ -835,3 +868,129 @@ tf_msg_session_sram_resc_flush(struct tf *tfp,
return tfp_le_to_cpu_32(parms.tf_resp_code);
}
#define TF_BYTES_PER_SLICE(tfp) 12
#define NUM_SLICES(tfp, bytes) \
(((bytes) + TF_BYTES_PER_SLICE(tfp) - 1) / TF_BYTES_PER_SLICE(tfp))
static int
tf_msg_get_dma_buf(struct tf_msg_dma_buf *buf, int size)
{
struct tfp_calloc_parms alloc_parms;
int rc;
/* Allocate session */
alloc_parms.nitems = 1;
alloc_parms.size = size;
alloc_parms.alignment = 0;
rc = tfp_calloc(&alloc_parms);
if (rc) {
/* Log error */
PMD_DRV_LOG(ERR,
"Failed to allocate tcam dma entry, rc:%d\n",
rc);
return -ENOMEM;
}
buf->pa_addr = (uintptr_t)alloc_parms.mem_pa;
buf->va_addr = alloc_parms.mem_va;
return 0;
}
int
tf_msg_tcam_entry_set(struct tf *tfp,
struct tf_set_tcam_entry_parms *parms)
{
int rc;
struct tfp_send_msg_parms mparms = { 0 };
struct hwrm_tf_tcam_set_input req = { 0 };
struct hwrm_tf_tcam_set_output resp = { 0 };
uint16_t key_bytes =
TF_BITS2BYTES_WORD_ALIGN(parms->key_sz_in_bits);
uint16_t result_bytes =
TF_BITS2BYTES_WORD_ALIGN(parms->result_sz_in_bits);
struct tf_msg_dma_buf buf = { 0 };
uint8_t *data = NULL;
int data_size = 0;
rc = tf_tcam_tbl_2_hwrm(parms->tcam_tbl_type, &req.type);
if (rc != 0)
return rc;
req.idx = tfp_cpu_to_le_16(parms->idx);
if (parms->dir == TF_DIR_TX)
req.flags |= HWRM_TF_TCAM_SET_INPUT_FLAGS_DIR_TX;
req.key_size = key_bytes;
req.mask_offset = key_bytes;
/* Result follows after key and mask, thus multiply by 2 */
req.result_offset = 2 * key_bytes;
req.result_size = result_bytes;
data_size = 2 * req.key_size + req.result_size;
if (data_size <= TF_PCI_BUF_SIZE_MAX) {
/* use pci buffer */
data = &req.dev_data[0];
} else {
/* use dma buffer */
req.flags |= HWRM_TF_TCAM_SET_INPUT_FLAGS_DMA;
rc = tf_msg_get_dma_buf(&buf, data_size);
if (rc != 0)
return rc;
data = buf.va_addr;
memcpy(&req.dev_data[0], &buf.pa_addr, sizeof(buf.pa_addr));
}
memcpy(&data[0], parms->key, key_bytes);
memcpy(&data[key_bytes], parms->mask, key_bytes);
memcpy(&data[req.result_offset], parms->result, result_bytes);
mparms.tf_type = HWRM_TF_TCAM_SET;
mparms.req_data = (uint32_t *)&req;
mparms.req_size = sizeof(req);
mparms.resp_data = (uint32_t *)&resp;
mparms.resp_size = sizeof(resp);
mparms.mailbox = TF_KONG_MB;
rc = tfp_send_msg_direct(tfp,
&mparms);
if (rc)
return rc;
if (buf.va_addr != NULL)
tfp_free(buf.va_addr);
return rc;
}
int
tf_msg_tcam_entry_free(struct tf *tfp,
struct tf_free_tcam_entry_parms *in_parms)
{
int rc;
struct hwrm_tf_tcam_free_input req = { 0 };
struct hwrm_tf_tcam_free_output resp = { 0 };
struct tfp_send_msg_parms parms = { 0 };
/* Populate the request */
rc = tf_tcam_tbl_2_hwrm(in_parms->tcam_tbl_type, &req.type);
if (rc != 0)
return rc;
req.count = 1;
req.idx_list[0] = tfp_cpu_to_le_16(in_parms->idx);
if (in_parms->dir == TF_DIR_TX)
req.flags |= HWRM_TF_TCAM_FREE_INPUT_FLAGS_DIR_TX;
parms.tf_type = HWRM_TF_TCAM_FREE;
parms.req_data = (uint32_t *)&req;
parms.req_size = sizeof(req);
parms.resp_data = (uint32_t *)&resp;
parms.resp_size = sizeof(resp);
parms.mailbox = TF_KONG_MB;
rc = tfp_send_msg_direct(tfp,
&parms);
return rc;
}

View File

@ -120,4 +120,34 @@ int tf_msg_session_sram_resc_flush(struct tf *tfp,
enum tf_dir dir,
struct tf_rm_entry *sram_entry);
/**
* Sends tcam entry 'set' to the Firmware.
*
* [in] tfp
* Pointer to session handle
*
* [in] parms
* Pointer to set parameters
*
* Returns:
* 0 on Success else internal Truflow error
*/
int tf_msg_tcam_entry_set(struct tf *tfp,
struct tf_set_tcam_entry_parms *parms);
/**
* Sends tcam entry 'free' to the Firmware.
*
* [in] tfp
* Pointer to session handle
*
* [in] parms
* Pointer to free parameters
*
* Returns:
* 0 on Success else internal Truflow error
*/
int tf_msg_tcam_entry_free(struct tf *tfp,
struct tf_free_tcam_entry_parms *parms);
#endif /* _TF_MSG_H_ */