net/bnxt: support bulk table get and mirror

- Add new bulk table type get using FW
  to DMA the data back to host.
- Add flag to allow records to be cleared if possible
- Set mirror using tf_alloc_tbl_entry

Signed-off-by: Shahaji Bhosle <sbhosle@broadcom.com>
Signed-off-by: Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
This commit is contained in:
Shahaji Bhosle 2020-07-02 16:27:59 -07:00 committed by Ferruh Yigit
parent 8187694b15
commit 8c37258d78
8 changed files with 319 additions and 22 deletions

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2019 Broadcom
* Copyright(c) 2019-2020 Broadcom
* All rights reserved.
*/
#ifndef _HWRM_TF_H_
@ -27,7 +27,8 @@ typedef enum tf_subtype {
HWRM_TFT_REG_SET = 822,
HWRM_TFT_TBL_TYPE_SET = 823,
HWRM_TFT_TBL_TYPE_GET = 824,
TF_SUBTYPE_LAST = HWRM_TFT_TBL_TYPE_GET,
HWRM_TFT_TBL_TYPE_GET_BULK = 825,
TF_SUBTYPE_LAST = HWRM_TFT_TBL_TYPE_GET_BULK,
} tf_subtype_t;
/* Request and Response compile time checking */
@ -81,6 +82,8 @@ struct tf_session_sram_resc_flush_input;
struct tf_tbl_type_set_input;
struct tf_tbl_type_get_input;
struct tf_tbl_type_get_output;
struct tf_tbl_type_get_bulk_input;
struct tf_tbl_type_get_bulk_output;
/* Input params for session attach */
typedef struct tf_session_attach_input {
/* Firmware session id returned when HWRM_TF_SESSION_OPEN is sent */
@ -902,6 +905,8 @@ typedef struct tf_tbl_type_get_input {
#define TF_TBL_TYPE_GET_INPUT_FLAGS_DIR_RX (0x0)
/* When set to 1, indicates the get apply to TX */
#define TF_TBL_TYPE_GET_INPUT_FLAGS_DIR_TX (0x1)
/* When set to 1, indicates the clear entry on read */
#define TF_TBL_TYPE_GET_INPUT_FLAGS_CLEAR_ON_READ (0x2)
/* Type of the object to set */
uint32_t type;
/* Index to get */
@ -916,4 +921,32 @@ typedef struct tf_tbl_type_get_output {
uint8_t data[TF_BULK_RECV];
} tf_tbl_type_get_output_t, *ptf_tbl_type_get_output_t;
/* Input params for table type get */
typedef struct tf_tbl_type_get_bulk_input {
/* Session Id */
uint32_t fw_session_id;
/* flags */
uint16_t flags;
/* When set to 0, indicates the get apply to RX */
#define TF_TBL_TYPE_GET_BULK_INPUT_FLAGS_DIR_RX (0x0)
/* When set to 1, indicates the get apply to TX */
#define TF_TBL_TYPE_GET_BULK_INPUT_FLAGS_DIR_TX (0x1)
/* When set to 1, indicates the clear entry on read */
#define TF_TBL_TYPE_GET_BULK_INPUT_FLAGS_CLEAR_ON_READ (0x2)
/* Type of the object to set */
uint32_t type;
/* Starting index to get from */
uint32_t start_index;
/* Number of entries to get */
uint32_t num_entries;
/* Host memory where data will be stored */
uint64_t host_addr;
} tf_tbl_type_get_bulk_input_t, *ptf_tbl_type_get_bulk_input_t;
/* Output params for table type get */
typedef struct tf_tbl_type_get_bulk_output {
/* Size of the total data read in bytes */
uint16_t size;
} tf_tbl_type_get_bulk_output_t, *ptf_tbl_type_get_bulk_output_t;
#endif /* _HWRM_TF_H_ */

View File

@ -0,0 +1,54 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2020 Broadcom
* All rights reserved.
*/
#ifndef _TF_COMMON_H_
#define _TF_COMMON_H_
/* Helper to check the parms */
#define TF_CHECK_PARMS_SESSION(tfp, parms) do { \
if ((parms) == NULL || (tfp) == NULL) { \
TFP_DRV_LOG(ERR, "Invalid Argument(s)\n"); \
return -EINVAL; \
} \
if ((tfp)->session == NULL || \
(tfp)->session->core_data == NULL) { \
TFP_DRV_LOG(ERR, "%s: session error\n", \
tf_dir_2_str((parms)->dir)); \
return -EINVAL; \
} \
} while (0)
#define TF_CHECK_PARMS_SESSION_NO_DIR(tfp, parms) do { \
if ((parms) == NULL || (tfp) == NULL) { \
TFP_DRV_LOG(ERR, "Invalid Argument(s)\n"); \
return -EINVAL; \
} \
if ((tfp)->session == NULL || \
(tfp)->session->core_data == NULL) { \
TFP_DRV_LOG(ERR, "Session error\n"); \
return -EINVAL; \
} \
} while (0)
#define TF_CHECK_PARMS(tfp, parms) do { \
if ((parms) == NULL || (tfp) == NULL) { \
TFP_DRV_LOG(ERR, "Invalid Argument(s)\n"); \
return -EINVAL; \
} \
} while (0)
#define TF_CHECK_TFP_SESSION(tfp) do { \
if ((tfp) == NULL) { \
TFP_DRV_LOG(ERR, "Invalid Argument(s)\n"); \
return -EINVAL; \
} \
if ((tfp)->session == NULL || \
(tfp)->session->core_data == NULL) { \
TFP_DRV_LOG(ERR, "Session error\n"); \
return -EINVAL; \
} \
} while (0)
#endif /* _TF_COMMON_H_ */

View File

@ -16,6 +16,8 @@
#include "bitalloc.h"
#include "bnxt.h"
#include "rand.h"
#include "tf_common.h"
#include "hwrm_tf.h"
static inline uint32_t SWAP_WORDS32(uint32_t val32)
{

View File

@ -1165,7 +1165,7 @@ struct tf_get_tbl_entry_parms {
*/
uint8_t *data;
/**
* [out] Entry size
* [in] Entry size
*/
uint16_t data_sz_in_bytes;
/**
@ -1188,6 +1188,59 @@ struct tf_get_tbl_entry_parms {
int tf_get_tbl_entry(struct tf *tfp,
struct tf_get_tbl_entry_parms *parms);
/**
* tf_get_bulk_tbl_entry parameter definition
*/
struct tf_get_bulk_tbl_entry_parms {
/**
* [in] Receive or transmit direction
*/
enum tf_dir dir;
/**
* [in] Type of object to get
*/
enum tf_tbl_type type;
/**
* [in] Clear hardware entries on reads only
* supported for TF_TBL_TYPE_ACT_STATS_64
*/
bool clear_on_read;
/**
* [in] Starting index to read from
*/
uint32_t starting_idx;
/**
* [in] Number of sequential entries
*/
uint16_t num_entries;
/**
* [in] Size of the single entry
*/
uint16_t entry_sz_in_bytes;
/**
* [out] Host physical address, where the data
* will be copied to by the firmware.
* Use tfp_calloc() API and mem_pa
* variable of the tfp_calloc_parms
* structure for the physical address.
*/
uint64_t physical_mem_addr;
};
/**
* Bulk get index table entry
*
* Used to retrieve a previous set index table entry.
*
* Reads and compares with the shadow table copy (if enabled) (only
* for internal objects).
*
* Returns success or failure code. Failure will be returned if the
* provided data buffer is too small for the data type requested.
*/
int tf_get_bulk_tbl_entry(struct tf *tfp,
struct tf_get_bulk_tbl_entry_parms *parms);
/**
* @page exact_match Exact Match Table
*

View File

@ -1216,12 +1216,8 @@ tf_msg_get_tbl_entry(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)
tf_msg_alloc_dma_buf(struct tf_msg_dma_buf *buf, int size)
{
struct tfp_calloc_parms alloc_parms;
int rc;
@ -1229,15 +1225,10 @@ tf_msg_get_dma_buf(struct tf_msg_dma_buf *buf, int size)
/* Allocate session */
alloc_parms.nitems = 1;
alloc_parms.size = size;
alloc_parms.alignment = 0;
alloc_parms.alignment = 4096;
rc = tfp_calloc(&alloc_parms);
if (rc) {
/* Log error */
PMD_DRV_LOG(ERR,
"Failed to allocate tcam dma entry, rc:%d\n",
rc);
if (rc)
return -ENOMEM;
}
buf->pa_addr = (uintptr_t)alloc_parms.mem_pa;
buf->va_addr = alloc_parms.mem_va;
@ -1245,6 +1236,52 @@ tf_msg_get_dma_buf(struct tf_msg_dma_buf *buf, int size)
return 0;
}
int
tf_msg_get_bulk_tbl_entry(struct tf *tfp,
struct tf_get_bulk_tbl_entry_parms *params)
{
int rc;
struct tfp_send_msg_parms parms = { 0 };
struct tf_tbl_type_get_bulk_input req = { 0 };
struct tf_tbl_type_get_bulk_output resp = { 0 };
struct tf_session *tfs = (struct tf_session *)(tfp->session->core_data);
int data_size = 0;
/* Populate the request */
req.fw_session_id =
tfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);
req.flags = tfp_cpu_to_le_16((params->dir) |
((params->clear_on_read) ?
TF_TBL_TYPE_GET_BULK_INPUT_FLAGS_CLEAR_ON_READ : 0x0));
req.type = tfp_cpu_to_le_32(params->type);
req.start_index = tfp_cpu_to_le_32(params->starting_idx);
req.num_entries = tfp_cpu_to_le_32(params->num_entries);
data_size = (params->num_entries * params->entry_sz_in_bytes);
req.host_addr = tfp_cpu_to_le_64(params->physical_mem_addr);
MSG_PREP(parms,
TF_KONG_MB,
HWRM_TF,
HWRM_TFT_TBL_TYPE_GET_BULK,
req,
resp);
rc = tfp_send_msg_tunneled(tfp, &parms);
if (rc)
return rc;
/* Verify that we got enough buffer to return the requested data */
if (resp.size < data_size)
return -EINVAL;
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))
int
tf_msg_tcam_entry_set(struct tf *tfp,
struct tf_set_tcam_entry_parms *parms)
@ -1282,9 +1319,9 @@ tf_msg_tcam_entry_set(struct tf *tfp,
} 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;
rc = tf_msg_alloc_dma_buf(&buf, data_size);
if (rc)
goto cleanup;
data = buf.va_addr;
memcpy(&req.dev_data[0], &buf.pa_addr, sizeof(buf.pa_addr));
}
@ -1303,8 +1340,9 @@ tf_msg_tcam_entry_set(struct tf *tfp,
rc = tfp_send_msg_direct(tfp,
&mparms);
if (rc)
return rc;
goto cleanup;
cleanup:
if (buf.va_addr != NULL)
tfp_free(buf.va_addr);

View File

@ -267,4 +267,19 @@ int tf_msg_get_tbl_entry(struct tf *tfp,
uint8_t *data,
uint32_t index);
/**
* Sends bulk get message of a Table Type element to the firmware.
*
* [in] tfp
* Pointer to session handle
*
* [in] parms
* Pointer to table get bulk parameters
*
* Returns:
* 0 on Success else internal Truflow error
*/
int tf_msg_get_bulk_tbl_entry(struct tf *tfp,
struct tf_get_bulk_tbl_entry_parms *parms);
#endif /* _TF_MSG_H_ */

View File

@ -149,11 +149,10 @@
#define TF_RSVD_METER_INST_END_IDX_TX 0
/* Mirror */
/* Not yet supported fully in the infra */
#define TF_RSVD_MIRROR_RX 0
#define TF_RSVD_MIRROR_RX 1
#define TF_RSVD_MIRROR_BEGIN_IDX_RX 0
#define TF_RSVD_MIRROR_END_IDX_RX 0
#define TF_RSVD_MIRROR_TX 0
#define TF_RSVD_MIRROR_TX 1
#define TF_RSVD_MIRROR_BEGIN_IDX_TX 0
#define TF_RSVD_MIRROR_END_IDX_TX 0

View File

@ -23,6 +23,7 @@
#include "bnxt.h"
#include "tf_resources.h"
#include "tf_rm.h"
#include "tf_common.h"
#define PTU_PTE_VALID 0x1UL
#define PTU_PTE_LAST 0x2UL
@ -794,6 +795,7 @@ tf_set_tbl_entry_internal(struct tf *tfp,
if (parms->type != TF_TBL_TYPE_FULL_ACT_RECORD &&
parms->type != TF_TBL_TYPE_ACT_SP_SMAC_IPV4 &&
parms->type != TF_TBL_TYPE_MIRROR_CONFIG &&
parms->type != TF_TBL_TYPE_ACT_STATS_64) {
PMD_DRV_LOG(ERR,
"dir:%d, Type not supported, type:%d\n",
@ -915,6 +917,76 @@ tf_get_tbl_entry_internal(struct tf *tfp,
return rc;
}
/**
* Internal function to get a Table Entry. Supports all Table Types
* except the TF_TBL_TYPE_EXT as that is handled as a table scope.
*
* [in] tfp
* Pointer to TruFlow handle
*
* [in] parms
* Pointer to input parameters
*
* Returns:
* 0 - Success
* -EINVAL - Parameter error
*/
static int
tf_get_bulk_tbl_entry_internal(struct tf *tfp,
struct tf_get_bulk_tbl_entry_parms *parms)
{
int rc;
int id;
uint32_t index;
struct bitalloc *session_pool;
struct tf_session *tfs = (struct tf_session *)(tfp->session->core_data);
/* 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->starting_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->starting_idx,
&index);
/* Verify that the entry has been previously allocated */
id = ba_inuse(session_pool, index);
if (id != 1) {
TFP_DRV_LOG(ERR,
"%s, Invalid or not allocated index, type:%d, starting_idx:%d\n",
tf_dir_2_str(parms->dir),
parms->type,
index);
return -EINVAL;
}
/* Get the entry */
rc = tf_msg_get_bulk_tbl_entry(tfp, parms);
if (rc) {
TFP_DRV_LOG(ERR,
"%s, Bulk get failed, type:%d, rc:%s\n",
tf_dir_2_str(parms->dir),
parms->type,
strerror(-rc));
}
return rc;
}
#if (TF_SHADOW == 1)
/**
* Allocate Tbl entry from the Shadow DB. Shadow DB is searched for
@ -1182,6 +1254,7 @@ tf_alloc_tbl_entry_pool_internal(struct tf *tfp,
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_MIRROR_CONFIG &&
parms->type != TF_TBL_TYPE_ACT_STATS_64) {
PMD_DRV_LOG(ERR,
"dir:%d, Type not supported, type:%d\n",
@ -1663,6 +1736,36 @@ tf_get_tbl_entry(struct tf *tfp,
return rc;
}
/* API defined in tf_core.h */
int
tf_get_bulk_tbl_entry(struct tf *tfp,
struct tf_get_bulk_tbl_entry_parms *parms)
{
int rc = 0;
TF_CHECK_PARMS_SESSION(tfp, parms);
if (parms->type == TF_TBL_TYPE_EXT) {
/* Not supported, yet */
TFP_DRV_LOG(ERR,
"%s, External table type not supported\n",
tf_dir_2_str(parms->dir));
rc = -EOPNOTSUPP;
} else {
/* Internal table type processing */
rc = tf_get_bulk_tbl_entry_internal(tfp, parms);
if (rc)
TFP_DRV_LOG(ERR,
"%s, Bulk get failed, type:%d, rc:%s\n",
tf_dir_2_str(parms->dir),
parms->type,
strerror(-rc));
}
return rc;
}
/* API defined in tf_core.h */
int
tf_alloc_tbl_scope(struct tf *tfp,