net/bnxt: support bulk table get and mirror
authorShahaji Bhosle <sbhosle@broadcom.com>
Thu, 2 Jul 2020 23:27:59 +0000 (16:27 -0700)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 7 Jul 2020 21:38:26 +0000 (23:38 +0200)
- 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>
drivers/net/bnxt/tf_core/hwrm_tf.h
drivers/net/bnxt/tf_core/tf_common.h [new file with mode: 0644]
drivers/net/bnxt/tf_core/tf_core.c
drivers/net/bnxt/tf_core/tf_core.h
drivers/net/bnxt/tf_core/tf_msg.c
drivers/net/bnxt/tf_core/tf_msg.h
drivers/net/bnxt/tf_core/tf_resources.h
drivers/net/bnxt/tf_core/tf_tbl.c

index d69bed8..96fb1fd 100644 (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_ */
diff --git a/drivers/net/bnxt/tf_core/tf_common.h b/drivers/net/bnxt/tf_core/tf_common.h
new file mode 100644 (file)
index 0000000..2aa4b86
--- /dev/null
@@ -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_ */
index 6e15a4c..a8236ae 100644 (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)
 {
index becc50c..96a1a79 100644 (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
  *
index c8f6b88..c755c85 100644 (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);
 
index 89f7370..8d050c4 100644 (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_ */
index 05e131f..9b7f5a0 100644 (file)
 #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
 
index 17399a5..26313ed 100644 (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,