net/bnxt: support L2 context TCAM operations
authorJay Ding <jay.ding@broadcom.com>
Sun, 30 May 2021 08:58:38 +0000 (14:28 +0530)
committerAjit Khaparde <ajit.khaparde@broadcom.com>
Wed, 9 Jun 2021 19:38:22 +0000 (21:38 +0200)
- Implement TCAM get in host
- Add Thor support for TCAM set/free

Signed-off-by: Jay Ding <jay.ding@broadcom.com>
Signed-off-by: Randy Schacher <stuart.schacher@broadcom.com>
Signed-off-by: Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>
Reviewed-by: Peter Spreadborough <peter.spreadborough@broadcom.com>
Reviewed-by: Farah Smith <farah.smith@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
drivers/net/bnxt/tf_core/hwrm_tf.h
drivers/net/bnxt/tf_core/tf_core.c
drivers/net/bnxt/tf_core/tf_device.h
drivers/net/bnxt/tf_core/tf_device_p4.c
drivers/net/bnxt/tf_core/tf_device_p58.c
drivers/net/bnxt/tf_core/tf_msg.c
drivers/net/bnxt/tf_core/tf_msg.h
drivers/net/bnxt/tf_core/tf_tcam.c
drivers/net/bnxt/tf_core/tf_tcam.h

index a707cd2..9cc9a14 100644 (file)
@@ -65,6 +65,7 @@ typedef enum tf_subtype {
 
 #define TF_BITS2BYTES(x) (((x) + 7) >> 3)
 #define TF_BITS2BYTES_WORD_ALIGN(x) ((((x) + 31) >> 5) * 4)
+#define TF_BITS2BYTES_64B_WORD_ALIGN(x) ((((x) + 63) >> 6) * 8)
 
 struct tf_set_global_cfg_input;
 struct tf_get_global_cfg_input;
index ebe0fc3..a3b6afb 100644 (file)
@@ -764,7 +764,8 @@ tf_set_tcam_entry(struct tf *tfp,
                return rc;
        }
 
-       if (dev->ops->tf_dev_set_tcam == NULL) {
+       if (dev->ops->tf_dev_set_tcam == NULL ||
+           dev->ops->tf_dev_word_align == NULL) {
                rc = -EOPNOTSUPP;
                TFP_DRV_LOG(ERR,
                            "%s: Operation not supported, rc:%s\n",
@@ -778,7 +779,7 @@ tf_set_tcam_entry(struct tf *tfp,
        sparms.idx = parms->idx;
        sparms.key = parms->key;
        sparms.mask = parms->mask;
-       sparms.key_size = TF_BITS2BYTES_WORD_ALIGN(parms->key_sz_in_bits);
+       sparms.key_size = dev->ops->tf_dev_word_align(parms->key_sz_in_bits);
        sparms.result = parms->result;
        sparms.result_size = TF_BITS2BYTES_WORD_ALIGN(parms->result_sz_in_bits);
 
@@ -796,10 +797,66 @@ tf_set_tcam_entry(struct tf *tfp,
 
 int
 tf_get_tcam_entry(struct tf *tfp __rte_unused,
-                 struct tf_get_tcam_entry_parms *parms __rte_unused)
+                 struct tf_get_tcam_entry_parms *parms)
 {
+       int rc;
+       struct tf_session *tfs;
+       struct tf_dev_info *dev;
+       struct tf_tcam_get_parms gparms;
+
        TF_CHECK_PARMS2(tfp, parms);
-       return -EOPNOTSUPP;
+
+       memset(&gparms, 0, sizeof(struct tf_tcam_get_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_get_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;
+       }
+
+       gparms.dir = parms->dir;
+       gparms.type = parms->tcam_tbl_type;
+       gparms.idx = parms->idx;
+       gparms.key = parms->key;
+       gparms.mask = parms->mask;
+       gparms.result = parms->result;
+
+       rc = dev->ops->tf_dev_get_tcam(tfp, &gparms);
+       if (rc) {
+               TFP_DRV_LOG(ERR,
+                           "%s: TCAM get failed, rc:%s\n",
+                           tf_dir_2_str(parms->dir),
+                           strerror(-rc));
+               return rc;
+       }
+       parms->key_sz_in_bits = gparms.key_size * 8;
+       parms->result_sz_in_bits = gparms.result_size * 8;
+
+       return 0;
 }
 
 int
index cbacc09..4f4120c 100644 (file)
@@ -736,6 +736,18 @@ struct tf_dev_ops {
         *      mailbox
         */
        int (*tf_dev_get_mailbox)(void);
+
+       /**
+        * Convert length in bit to length in byte and align to word.
+        * The word length depends on device type.
+        *
+        * [in] size
+        *   Size in bit
+        *
+        * Returns
+        *   Size in byte
+        */
+       int (*tf_dev_word_align)(uint16_t size);
 };
 
 /**
index f6c8f5e..fbe92b7 100644 (file)
@@ -212,6 +212,10 @@ static int tf_dev_p4_get_mailbox(void)
        return TF_KONG_MB;
 }
 
+static int tf_dev_p4_word_align(uint16_t size)
+{
+       return ((((size) + 31) >> 5) * 4);
+}
 
 /**
  * Truflow P4 device specific functions
@@ -250,6 +254,7 @@ const struct tf_dev_ops tf_dev_ops_p4_init = {
        .tf_dev_set_global_cfg = NULL,
        .tf_dev_get_global_cfg = NULL,
        .tf_dev_get_mailbox = tf_dev_p4_get_mailbox,
+       .tf_dev_word_align = NULL,
 };
 
 /**
@@ -289,4 +294,5 @@ const struct tf_dev_ops tf_dev_ops_p4 = {
        .tf_dev_set_global_cfg = tf_global_cfg_set,
        .tf_dev_get_global_cfg = tf_global_cfg_get,
        .tf_dev_get_mailbox = tf_dev_p4_get_mailbox,
+       .tf_dev_word_align = tf_dev_p4_word_align,
 };
index 6cef1d5..688d987 100644 (file)
@@ -193,6 +193,11 @@ static int tf_dev_p58_get_mailbox(void)
        return TF_CHIMP_MB;
 }
 
+static int tf_dev_p58_word_align(uint16_t size)
+{
+       return ((((size) + 63) >> 6) * 8);
+}
+
 /**
  * Truflow P58 device specific functions
  */
@@ -230,6 +235,7 @@ const struct tf_dev_ops tf_dev_ops_p58_init = {
        .tf_dev_set_global_cfg = NULL,
        .tf_dev_get_global_cfg = NULL,
        .tf_dev_get_mailbox = tf_dev_p58_get_mailbox,
+       .tf_dev_word_align = NULL,
 };
 
 /**
@@ -255,7 +261,7 @@ const struct tf_dev_ops tf_dev_ops_p58 = {
        .tf_dev_free_tcam = tf_tcam_free,
        .tf_dev_alloc_search_tcam = tf_tcam_alloc_search,
        .tf_dev_set_tcam = tf_tcam_set,
-       .tf_dev_get_tcam = NULL,
+       .tf_dev_get_tcam = tf_tcam_get,
        .tf_dev_insert_int_em_entry = tf_em_hash_insert_int_entry,
        .tf_dev_delete_int_em_entry = tf_em_hash_delete_int_entry,
        .tf_dev_insert_ext_em_entry = NULL,
@@ -269,4 +275,5 @@ const struct tf_dev_ops tf_dev_ops_p58 = {
        .tf_dev_set_global_cfg = tf_global_cfg_set,
        .tf_dev_get_global_cfg = tf_global_cfg_get,
        .tf_dev_get_mailbox = tf_dev_p58_get_mailbox,
+       .tf_dev_word_align = tf_dev_p58_word_align,
 };
index 39d7e3e..1af5c6d 100644 (file)
@@ -1212,6 +1212,58 @@ cleanup:
        return rc;
 }
 
+int
+tf_msg_tcam_entry_get(struct tf *tfp,
+                     struct tf_dev_info *dev,
+                     struct tf_tcam_get_parms *parms)
+{
+       int rc;
+       struct tfp_send_msg_parms mparms = { 0 };
+       struct hwrm_tf_tcam_get_input req = { 0 };
+       struct hwrm_tf_tcam_get_output resp = { 0 };
+       uint8_t fw_session_id;
+
+       rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
+       if (rc) {
+               TFP_DRV_LOG(ERR,
+                           "%s: Unable to lookup FW id, rc:%s\n",
+                           tf_dir_2_str(parms->dir),
+                           strerror(-rc));
+               return rc;
+       }
+
+       /* Populate the request */
+       req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
+       req.type = parms->hcapi_type;
+       req.idx = tfp_cpu_to_le_16(parms->idx);
+       if (parms->dir == TF_DIR_TX)
+               req.flags |= HWRM_TF_TCAM_GET_INPUT_FLAGS_DIR_TX;
+
+       mparms.tf_type = HWRM_TF_TCAM_GET;
+       mparms.req_data = (uint32_t *)&req;
+       mparms.req_size = sizeof(req);
+       mparms.resp_data = (uint32_t *)&resp;
+       mparms.resp_size = sizeof(resp);
+       mparms.mailbox = dev->ops->tf_dev_get_mailbox();
+
+       rc = tfp_send_msg_direct(tfp,
+                                &mparms);
+
+       if (rc != 0)
+               return rc;
+
+       if (mparms.tf_resp_code != 0)
+               return tfp_le_to_cpu_32(mparms.tf_resp_code);
+
+       parms->key_size = resp.key_size;
+       parms->result_size = resp.result_size;
+       tfp_memcpy(parms->key, resp.dev_data, resp.key_size);
+       tfp_memcpy(parms->mask, &resp.dev_data[resp.key_size], resp.key_size);
+       tfp_memcpy(parms->result, &resp.dev_data[resp.result_offset], resp.result_size);
+
+       return tfp_le_to_cpu_32(mparms.tf_resp_code);
+}
+
 int
 tf_msg_tcam_entry_free(struct tf *tfp,
                       struct tf_dev_info *dev,
index 1d82ce5..a14bcd3 100644 (file)
@@ -412,6 +412,22 @@ int tf_msg_tcam_entry_set(struct tf *tfp,
                          struct tf_dev_info *dev,
                          struct tf_tcam_set_parms *parms);
 
+/**
+ * Sends tcam entry 'get' to the Firmware.
+ *
+ * [in] tfp
+ *   Pointer to session handle
+ *
+ * [in] parms
+ *   Pointer to get parameters
+ *
+ * Returns:
+ *  0 on Success else internal Truflow error
+ */
+int tf_msg_tcam_entry_get(struct tf *tfp,
+                         struct tf_dev_info *dev,
+                         struct tf_tcam_get_parms *parms);
+
 /**
  * Sends tcam entry 'free' to the Firmware.
  *
index 038aa40..a18d0e1 100644 (file)
@@ -686,7 +686,94 @@ tf_tcam_set(struct tf *tfp __rte_unused,
 
 int
 tf_tcam_get(struct tf *tfp __rte_unused,
-           struct tf_tcam_get_parms *parms __rte_unused)
+           struct tf_tcam_get_parms *parms)
 {
+       int rc;
+       struct tf_session *tfs;
+       struct tf_dev_info *dev;
+       struct tf_rm_is_allocated_parms aparms;
+       struct tf_rm_get_hcapi_parms hparms;
+       uint16_t num_slice_per_row = 1;
+       int allocated = 0;
+
+       TF_CHECK_PARMS2(tfp, parms);
+
+       if (!init) {
+               TFP_DRV_LOG(ERR,
+                           "%s: No TCAM DBs created\n",
+                           tf_dir_2_str(parms->dir));
+               return -EINVAL;
+       }
+
+       /* Retrieve the session information */
+       rc = tf_session_get_session_internal(tfp, &tfs);
+       if (rc)
+               return rc;
+
+       /* Retrieve the device information */
+       rc = tf_session_get_device(tfs, &dev);
+       if (rc)
+               return rc;
+
+       if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
+               rc = -EOPNOTSUPP;
+               TFP_DRV_LOG(ERR,
+                           "%s: Operation not supported, rc:%s\n",
+                           tf_dir_2_str(parms->dir),
+                           strerror(-rc));
+               return rc;
+       }
+
+       /* Need to retrieve row size etc */
+       rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
+                                                 parms->type,
+                                                 parms->key_size,
+                                                 &num_slice_per_row);
+       if (rc)
+               return rc;
+
+       /* Check if element is in use */
+       memset(&aparms, 0, sizeof(aparms));
+
+       aparms.rm_db = tcam_db[parms->dir];
+       aparms.db_index = parms->type;
+       aparms.index = parms->idx / num_slice_per_row;
+       aparms.allocated = &allocated;
+       rc = tf_rm_is_allocated(&aparms);
+       if (rc)
+               return rc;
+
+       if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
+               TFP_DRV_LOG(ERR,
+                           "%s: Entry is not allocated, type:%d, index:%d\n",
+                           tf_dir_2_str(parms->dir),
+                           parms->type,
+                           parms->idx);
+               return -EINVAL;
+       }
+
+       /* Convert TF type to HCAPI RM type */
+       memset(&hparms, 0, sizeof(hparms));
+
+       hparms.rm_db = tcam_db[parms->dir];
+       hparms.db_index = parms->type;
+       hparms.hcapi_type = &parms->hcapi_type;
+
+       rc = tf_rm_get_hcapi_type(&hparms);
+       if (rc)
+               return rc;
+
+       rc = tf_msg_tcam_entry_get(tfp, dev, parms);
+       if (rc) {
+               /* Log error */
+               TFP_DRV_LOG(ERR,
+                           "%s: %s: Entry %d set failed, rc:%s",
+                           tf_dir_2_str(parms->dir),
+                           tf_tcam_tbl_2_str(parms->type),
+                           parms->idx,
+                           strerror(-rc));
+               return rc;
+       }
+
        return 0;
 }
index 40d010b..b550fa4 100644 (file)
@@ -207,6 +207,10 @@ struct tf_tcam_get_parms {
         * [in] Type of object to get
         */
        enum tf_tcam_tbl_type type;
+       /**
+        * [in] Type of HCAPI
+        */
+       uint16_t hcapi_type;
        /**
         * [in] Entry index to read
         */