From 8c37258d780858814dfc62a9c8438bf354330dc0 Mon Sep 17 00:00:00 2001 From: Shahaji Bhosle Date: Thu, 2 Jul 2020 16:27:59 -0700 Subject: [PATCH] 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 Signed-off-by: Venkat Duvvuru Reviewed-by: Ajit Khaparde --- drivers/net/bnxt/tf_core/hwrm_tf.h | 37 ++++++++- drivers/net/bnxt/tf_core/tf_common.h | 54 +++++++++++++ drivers/net/bnxt/tf_core/tf_core.c | 2 + drivers/net/bnxt/tf_core/tf_core.h | 55 ++++++++++++- drivers/net/bnxt/tf_core/tf_msg.c | 70 ++++++++++++---- drivers/net/bnxt/tf_core/tf_msg.h | 15 ++++ drivers/net/bnxt/tf_core/tf_resources.h | 5 +- drivers/net/bnxt/tf_core/tf_tbl.c | 103 ++++++++++++++++++++++++ 8 files changed, 319 insertions(+), 22 deletions(-) create mode 100644 drivers/net/bnxt/tf_core/tf_common.h diff --git a/drivers/net/bnxt/tf_core/hwrm_tf.h b/drivers/net/bnxt/tf_core/hwrm_tf.h index d69bed863b..96fb1fdde1 100644 --- a/drivers/net/bnxt/tf_core/hwrm_tf.h +++ b/drivers/net/bnxt/tf_core/hwrm_tf.h @@ -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_ */ diff --git a/drivers/net/bnxt/tf_core/tf_common.h b/drivers/net/bnxt/tf_core/tf_common.h new file mode 100644 index 0000000000..2aa4b86407 --- /dev/null +++ b/drivers/net/bnxt/tf_core/tf_common.h @@ -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_ */ diff --git a/drivers/net/bnxt/tf_core/tf_core.c b/drivers/net/bnxt/tf_core/tf_core.c index 6e15a4c5ca..a8236aec9e 100644 --- a/drivers/net/bnxt/tf_core/tf_core.c +++ b/drivers/net/bnxt/tf_core/tf_core.c @@ -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) { diff --git a/drivers/net/bnxt/tf_core/tf_core.h b/drivers/net/bnxt/tf_core/tf_core.h index becc50c7f0..96a1a794f0 100644 --- a/drivers/net/bnxt/tf_core/tf_core.h +++ b/drivers/net/bnxt/tf_core/tf_core.h @@ -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 * diff --git a/drivers/net/bnxt/tf_core/tf_msg.c b/drivers/net/bnxt/tf_core/tf_msg.c index c8f6b88d3b..c755c8555b 100644 --- a/drivers/net/bnxt/tf_core/tf_msg.c +++ b/drivers/net/bnxt/tf_core/tf_msg.c @@ -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); diff --git a/drivers/net/bnxt/tf_core/tf_msg.h b/drivers/net/bnxt/tf_core/tf_msg.h index 89f7370ccb..8d050c4026 100644 --- a/drivers/net/bnxt/tf_core/tf_msg.h +++ b/drivers/net/bnxt/tf_core/tf_msg.h @@ -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_ */ diff --git a/drivers/net/bnxt/tf_core/tf_resources.h b/drivers/net/bnxt/tf_core/tf_resources.h index 05e131f8b0..9b7f5a069e 100644 --- a/drivers/net/bnxt/tf_core/tf_resources.h +++ b/drivers/net/bnxt/tf_core/tf_resources.h @@ -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 diff --git a/drivers/net/bnxt/tf_core/tf_tbl.c b/drivers/net/bnxt/tf_core/tf_tbl.c index 17399a5b24..26313ed3c2 100644 --- a/drivers/net/bnxt/tf_core/tf_tbl.c +++ b/drivers/net/bnxt/tf_core/tf_tbl.c @@ -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, -- 2.20.1