/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2019-2020 Broadcom
+ * Copyright(c) 2019-2021 Broadcom
* All rights reserved.
*/
#include "tf_device.h"
#include "tf_device_p4.h"
+#include "tf_device_p58.h"
#include "tfp.h"
#include "tf_em.h"
+#include "tf_rm.h"
+#ifdef TF_TCAM_SHARED
+#include "tf_tcam_shared.h"
+#include "tf_tbl_sram.h"
+#endif /* TF_TCAM_SHARED */
struct tf;
+/* Number of slices per row for WC TCAM */
+uint16_t g_wc_num_slices_per_row = TF_WC_TCAM_1_SLICE_PER_ROW;
+
/* Forward declarations */
static int tf_dev_unbind_p4(struct tf *tfp);
+static int tf_dev_unbind_p58(struct tf *tfp);
+
+/**
+ * Resource Reservation Check function
+ *
+ * [in] count
+ * Number of module subtypes
+ *
+ * [in] cfg
+ * Pointer to rm element config
+ *
+ * [in] reservations
+ * Pointer to resource reservation array
+ *
+ * Returns
+ * - (n) number of tables in module that have non-zero reservation count.
+ */
+static int
+tf_dev_reservation_check(uint16_t count,
+ struct tf_rm_element_cfg *cfg,
+ uint16_t *reservations)
+{
+ uint16_t cnt = 0;
+ uint16_t *rm_num;
+ int i, j;
+
+ for (i = 0; i < TF_DIR_MAX; i++) {
+ rm_num = (uint16_t *)reservations + i * count;
+ for (j = 0; j < count; j++) {
+ if ((cfg[j].cfg_type == TF_RM_ELEM_CFG_HCAPI ||
+ cfg[j].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA ||
+ cfg[j].cfg_type ==
+ TF_RM_ELEM_CFG_HCAPI_BA_PARENT ||
+ cfg[j].cfg_type ==
+ TF_RM_ELEM_CFG_HCAPI_BA_CHILD) &&
+ rm_num[j] > 0)
+ cnt++;
+ }
+ }
+
+ return cnt;
+}
/**
* Device specific bind function, WH+
tf_dev_bind_p4(struct tf *tfp,
bool shadow_copy,
struct tf_session_resources *resources,
- struct tf_dev_info *dev_handle)
+ struct tf_dev_info *dev_handle,
+ enum tf_wc_num_slice wc_num_slices)
{
int rc;
int frc;
+ int rsv_cnt;
+ bool no_rsv_flag = true;
struct tf_ident_cfg_parms ident_cfg;
struct tf_tbl_cfg_parms tbl_cfg;
struct tf_tcam_cfg_parms tcam_cfg;
struct tf_em_cfg_parms em_cfg;
+ struct tf_if_tbl_cfg_parms if_tbl_cfg;
+ struct tf_global_cfg_cfg_parms global_cfg;
+ struct tf_session *tfs;
+
+ /* Retrieve the session information */
+ rc = tf_session_get_session_internal(tfp, &tfs);
+ if (rc)
+ return rc;
- dev_handle->type = TF_DEVICE_TYPE_WH;
/* Initial function initialization */
dev_handle->ops = &tf_dev_ops_p4_init;
/* Initialize the modules */
- ident_cfg.num_elements = TF_IDENT_TYPE_MAX;
- ident_cfg.cfg = tf_ident_p4;
- ident_cfg.shadow_copy = shadow_copy;
- ident_cfg.resources = resources;
- rc = tf_ident_bind(tfp, &ident_cfg);
- if (rc) {
- TFP_DRV_LOG(ERR,
- "Identifier initialization failure\n");
- goto fail;
+ rsv_cnt = tf_dev_reservation_check(TF_IDENT_TYPE_MAX,
+ tf_ident_p4,
+ (uint16_t *)resources->ident_cnt);
+ if (rsv_cnt) {
+ ident_cfg.num_elements = TF_IDENT_TYPE_MAX;
+ ident_cfg.cfg = tf_ident_p4;
+ ident_cfg.shadow_copy = shadow_copy;
+ ident_cfg.resources = resources;
+ rc = tf_ident_bind(tfp, &ident_cfg);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Identifier initialization failure\n");
+ goto fail;
+ }
+
+ no_rsv_flag = false;
}
- tbl_cfg.num_elements = TF_TBL_TYPE_MAX;
- tbl_cfg.cfg = tf_tbl_p4;
- tbl_cfg.shadow_copy = shadow_copy;
- tbl_cfg.resources = resources;
- rc = tf_tbl_bind(tfp, &tbl_cfg);
- if (rc) {
- TFP_DRV_LOG(ERR,
- "Table initialization failure\n");
- goto fail;
+ rsv_cnt = tf_dev_reservation_check(TF_TBL_TYPE_MAX,
+ tf_tbl_p4,
+ (uint16_t *)resources->tbl_cnt);
+ if (rsv_cnt) {
+ tbl_cfg.num_elements = TF_TBL_TYPE_MAX;
+ tbl_cfg.cfg = tf_tbl_p4;
+ tbl_cfg.resources = resources;
+ rc = tf_tbl_bind(tfp, &tbl_cfg);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Table initialization failure\n");
+ goto fail;
+ }
+
+ no_rsv_flag = false;
}
- tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX;
- tcam_cfg.cfg = tf_tcam_p4;
- tcam_cfg.shadow_copy = shadow_copy;
- tcam_cfg.resources = resources;
- rc = tf_tcam_bind(tfp, &tcam_cfg);
- if (rc) {
- TFP_DRV_LOG(ERR,
- "TCAM initialization failure\n");
- goto fail;
+ rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX,
+ tf_tcam_p4,
+ (uint16_t *)resources->tcam_cnt);
+ if (rsv_cnt) {
+ tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX;
+ tcam_cfg.cfg = tf_tcam_p4;
+ tcam_cfg.shadow_copy = shadow_copy;
+ tcam_cfg.resources = resources;
+ tcam_cfg.wc_num_slices = wc_num_slices;
+#ifdef TF_TCAM_SHARED
+ rc = tf_tcam_shared_bind(tfp, &tcam_cfg);
+#else /* !TF_TCAM_SHARED */
+ rc = tf_tcam_bind(tfp, &tcam_cfg);
+#endif
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "TCAM initialization failure\n");
+ goto fail;
+ }
+ no_rsv_flag = false;
}
/*
* EEM
*/
- em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
- em_cfg.cfg = tf_em_ext_p4;
- em_cfg.resources = resources;
- em_cfg.mem_type = TF_EEM_MEM_TYPE_HOST;
- rc = tf_em_ext_common_bind(tfp, &em_cfg);
- if (rc) {
- TFP_DRV_LOG(ERR,
- "EEM initialization failure\n");
- goto fail;
+ em_cfg.cfg = tf_em_ext_p4;
+ rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX,
+ em_cfg.cfg,
+ (uint16_t *)resources->em_cnt);
+ if (rsv_cnt) {
+ em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
+ em_cfg.resources = resources;
+ em_cfg.mem_type = TF_EEM_MEM_TYPE_HOST;
+ rc = tf_em_ext_common_bind(tfp, &em_cfg);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "EEM initialization failure\n");
+ goto fail;
+ }
+ no_rsv_flag = false;
}
/*
* EM
*/
- em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
- em_cfg.cfg = tf_em_int_p4;
- em_cfg.resources = resources;
- em_cfg.mem_type = 0; /* Not used by EM */
+ rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX,
+ tf_em_int_p4,
+ (uint16_t *)resources->em_cnt);
+ if (rsv_cnt) {
+ em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
+ em_cfg.cfg = tf_em_int_p4;
+ em_cfg.resources = resources;
+ em_cfg.mem_type = 0; /* Not used by EM */
- rc = tf_em_int_bind(tfp, &em_cfg);
+ rc = tf_em_int_bind(tfp, &em_cfg);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "EM initialization failure\n");
+ goto fail;
+ }
+ no_rsv_flag = false;
+ }
+
+ /*
+ * There is no rm reserved for any tables
+ *
+ */
+ if (no_rsv_flag) {
+ TFP_DRV_LOG(ERR,
+ "No rm reserved for any tables\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * IF_TBL
+ */
+ if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX;
+ if_tbl_cfg.cfg = tf_if_tbl_p4;
+ if_tbl_cfg.shadow_copy = shadow_copy;
+ rc = tf_if_tbl_bind(tfp, &if_tbl_cfg);
if (rc) {
TFP_DRV_LOG(ERR,
- "EM initialization failure\n");
+ "IF Table initialization failure\n");
goto fail;
}
+ if (!tf_session_is_shared_session(tfs)) {
+ /*
+ * GLOBAL_CFG
+ */
+ global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX;
+ global_cfg.cfg = tf_global_cfg_p4;
+ rc = tf_global_cfg_bind(tfp, &global_cfg);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Global Cfg initialization failure\n");
+ goto fail;
+ }
+ }
/* Final function initialization */
dev_handle->ops = &tf_dev_ops_p4;
{
int rc = 0;
bool fail = false;
+ struct tf_session *tfs;
+
+ /* Retrieve the session information */
+ rc = tf_session_get_session_internal(tfp, &tfs);
+ if (rc)
+ return rc;
/* Unbind all the support modules. As this is only done on
* close we only report errors as everything has to be cleaned
* In case of residuals TCAMs are cleaned up first as to
* invalidate the pipeline in a clean manner.
*/
+#ifdef TF_TCAM_SHARED
+ rc = tf_tcam_shared_unbind(tfp);
+#else /* !TF_TCAM_SHARED */
rc = tf_tcam_unbind(tfp);
+#endif /* TF_TCAM_SHARED */
if (rc) {
- TFP_DRV_LOG(ERR,
+ TFP_DRV_LOG(INFO,
"Device unbind failed, TCAM\n");
fail = true;
}
rc = tf_ident_unbind(tfp);
if (rc) {
- TFP_DRV_LOG(ERR,
+ TFP_DRV_LOG(INFO,
"Device unbind failed, Identifier\n");
fail = true;
}
rc = tf_tbl_unbind(tfp);
if (rc) {
- TFP_DRV_LOG(ERR,
+ TFP_DRV_LOG(INFO,
"Device unbind failed, Table Type\n");
fail = true;
}
rc = tf_em_ext_common_unbind(tfp);
if (rc) {
- TFP_DRV_LOG(ERR,
+ TFP_DRV_LOG(INFO,
"Device unbind failed, EEM\n");
fail = true;
}
rc = tf_em_int_unbind(tfp);
+ if (rc) {
+ TFP_DRV_LOG(INFO,
+ "Device unbind failed, EM\n");
+ fail = true;
+ }
+
+ if (!tf_session_is_shared_session(tfs)) {
+ rc = tf_if_tbl_unbind(tfp);
+ if (rc) {
+ TFP_DRV_LOG(INFO,
+ "Device unbind failed, IF Table Type\n");
+ fail = true;
+ }
+
+ rc = tf_global_cfg_unbind(tfp);
+ if (rc) {
+ TFP_DRV_LOG(INFO,
+ "Device unbind failed, Global Cfg Type\n");
+ fail = true;
+ }
+ }
+
+ if (fail)
+ return -1;
+
+ return rc;
+}
+
+/**
+ * Device specific bind function, THOR
+ *
+ * [in] tfp
+ * Pointer to TF handle
+ *
+ * [in] shadow_copy
+ * Flag controlling shadow copy DB creation
+ *
+ * [in] resources
+ * Pointer to resource allocation information
+ *
+ * [out] dev_handle
+ * Device handle
+ *
+ * Returns
+ * - (0) if successful.
+ * - (-EINVAL) on parameter or internal failure.
+ */
+static int
+tf_dev_bind_p58(struct tf *tfp,
+ bool shadow_copy,
+ struct tf_session_resources *resources,
+ struct tf_dev_info *dev_handle,
+ enum tf_wc_num_slice wc_num_slices)
+{
+ int rc;
+ int frc;
+ int rsv_cnt;
+ bool no_rsv_flag = true;
+ struct tf_ident_cfg_parms ident_cfg;
+ struct tf_tbl_cfg_parms tbl_cfg;
+ struct tf_tcam_cfg_parms tcam_cfg;
+ struct tf_em_cfg_parms em_cfg;
+ struct tf_if_tbl_cfg_parms if_tbl_cfg;
+ struct tf_global_cfg_cfg_parms global_cfg;
+ struct tf_session *tfs;
+
+ /* Initial function initialization */
+ dev_handle->ops = &tf_dev_ops_p58_init;
+
+ /* Retrieve the session information */
+ rc = tf_session_get_session_internal(tfp, &tfs);
+ if (rc)
+ return rc;
+
+ rsv_cnt = tf_dev_reservation_check(TF_IDENT_TYPE_MAX,
+ tf_ident_p58,
+ (uint16_t *)resources->ident_cnt);
+ if (rsv_cnt) {
+ ident_cfg.num_elements = TF_IDENT_TYPE_MAX;
+ ident_cfg.cfg = tf_ident_p58;
+ ident_cfg.shadow_copy = shadow_copy;
+ ident_cfg.resources = resources;
+ rc = tf_ident_bind(tfp, &ident_cfg);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Identifier initialization failure\n");
+ goto fail;
+ }
+ no_rsv_flag = false;
+ }
+
+ rsv_cnt = tf_dev_reservation_check(TF_TBL_TYPE_MAX,
+ tf_tbl_p58,
+ (uint16_t *)resources->tbl_cnt);
+ if (rsv_cnt) {
+ tbl_cfg.num_elements = TF_TBL_TYPE_MAX;
+ tbl_cfg.cfg = tf_tbl_p58;
+ tbl_cfg.resources = resources;
+ rc = tf_tbl_bind(tfp, &tbl_cfg);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Table initialization failure\n");
+ goto fail;
+ }
+ no_rsv_flag = false;
+
+ rc = tf_tbl_sram_bind(tfp);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "SRAM table initialization failure\n");
+ goto fail;
+ }
+ }
+
+ rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX,
+ tf_tcam_p58,
+ (uint16_t *)resources->tcam_cnt);
+ if (rsv_cnt) {
+ tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX;
+ tcam_cfg.cfg = tf_tcam_p58;
+ tcam_cfg.shadow_copy = shadow_copy;
+ tcam_cfg.resources = resources;
+ tcam_cfg.wc_num_slices = wc_num_slices;
+#ifdef TF_TCAM_SHARED
+ rc = tf_tcam_shared_bind(tfp, &tcam_cfg);
+#else /* !TF_TCAM_SHARED */
+ rc = tf_tcam_bind(tfp, &tcam_cfg);
+#endif
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "TCAM initialization failure\n");
+ goto fail;
+ }
+ no_rsv_flag = false;
+ }
+
+ /*
+ * EM
+ */
+ rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX,
+ tf_em_int_p58,
+ (uint16_t *)resources->em_cnt);
+ if (rsv_cnt) {
+ em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
+ em_cfg.cfg = tf_em_int_p58;
+ em_cfg.resources = resources;
+ em_cfg.mem_type = 0; /* Not used by EM */
+
+ rc = tf_em_int_bind(tfp, &em_cfg);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "EM initialization failure\n");
+ goto fail;
+ }
+ no_rsv_flag = false;
+ }
+
+ /*
+ * There is no rm reserved for any tables
+ *
+ */
+ if (no_rsv_flag) {
+ TFP_DRV_LOG(ERR,
+ "No rm reserved for any tables\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * IF_TBL
+ */
+ if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX;
+ if_tbl_cfg.cfg = tf_if_tbl_p58;
+ if_tbl_cfg.shadow_copy = shadow_copy;
+ rc = tf_if_tbl_bind(tfp, &if_tbl_cfg);
if (rc) {
TFP_DRV_LOG(ERR,
+ "IF Table initialization failure\n");
+ goto fail;
+ }
+
+ if (!tf_session_is_shared_session(tfs)) {
+ /*
+ * GLOBAL_CFG
+ */
+ global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX;
+ global_cfg.cfg = tf_global_cfg_p58;
+ rc = tf_global_cfg_bind(tfp, &global_cfg);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Global Cfg initialization failure\n");
+ goto fail;
+ }
+ }
+
+ /* Final function initialization */
+ dev_handle->ops = &tf_dev_ops_p58;
+
+ return 0;
+
+ fail:
+ /* Cleanup of already created modules */
+ frc = tf_dev_unbind_p58(tfp);
+ if (frc)
+ return frc;
+
+ return rc;
+}
+
+/**
+ * Device specific unbind function, THOR
+ *
+ * [in] tfp
+ * Pointer to TF handle
+ *
+ * Returns
+ * - (0) if successful.
+ * - (-EINVAL) on failure.
+ */
+static int
+tf_dev_unbind_p58(struct tf *tfp)
+{
+ int rc = 0;
+ bool fail = false;
+ struct tf_session *tfs;
+
+ /* Retrieve the session information */
+ rc = tf_session_get_session_internal(tfp, &tfs);
+ if (rc)
+ return rc;
+
+ /* Unbind all the support modules. As this is only done on
+ * close we only report errors as everything has to be cleaned
+ * up regardless.
+ *
+ * In case of residuals TCAMs are cleaned up first as to
+ * invalidate the pipeline in a clean manner.
+ */
+#ifdef TF_TCAM_SHARED
+ rc = tf_tcam_shared_unbind(tfp);
+#else /* !TF_TCAM_SHARED */
+ rc = tf_tcam_unbind(tfp);
+#endif /* TF_TCAM_SHARED */
+ if (rc) {
+ TFP_DRV_LOG(INFO,
+ "Device unbind failed, TCAM\n");
+ fail = true;
+ }
+
+ rc = tf_ident_unbind(tfp);
+ if (rc) {
+ TFP_DRV_LOG(INFO,
+ "Device unbind failed, Identifier\n");
+ fail = true;
+ }
+
+ /* Unbind the SRAM table prior to table as the table manager
+ * owns and frees the table DB while the SRAM table manager owns
+ * and manages it's internal data structures. SRAM table manager
+ * relies on the table rm_db to exist.
+ */
+ rc = tf_tbl_sram_unbind(tfp);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Device unbind failed, SRAM table\n");
+ fail = true;
+ }
+
+ rc = tf_tbl_unbind(tfp);
+ if (rc) {
+ TFP_DRV_LOG(INFO,
+ "Device unbind failed, Table Type\n");
+ fail = true;
+ }
+
+ rc = tf_em_int_unbind(tfp);
+ if (rc) {
+ TFP_DRV_LOG(INFO,
"Device unbind failed, EM\n");
fail = true;
}
+ rc = tf_if_tbl_unbind(tfp);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Device unbind failed, IF Table Type\n");
+ fail = true;
+ }
+
+ if (!tf_session_is_shared_session(tfs)) {
+ rc = tf_global_cfg_unbind(tfp);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Device unbind failed, Global Cfg Type\n");
+ fail = true;
+ }
+ }
+
if (fail)
return -1;
enum tf_device_type type,
bool shadow_copy,
struct tf_session_resources *resources,
+ uint16_t wc_num_slices,
struct tf_dev_info *dev_handle)
{
switch (type) {
case TF_DEVICE_TYPE_WH:
+ case TF_DEVICE_TYPE_SR:
+ dev_handle->type = type;
return tf_dev_bind_p4(tfp,
shadow_copy,
resources,
- dev_handle);
+ dev_handle,
+ wc_num_slices);
+ case TF_DEVICE_TYPE_THOR:
+ dev_handle->type = type;
+ return tf_dev_bind_p58(tfp,
+ shadow_copy,
+ resources,
+ dev_handle,
+ wc_num_slices);
+ default:
+ TFP_DRV_LOG(ERR,
+ "No such device\n");
+ return -ENODEV;
+ }
+}
+
+int
+tf_dev_bind_ops(enum tf_device_type type,
+ struct tf_dev_info *dev_handle)
+{
+ switch (type) {
+ case TF_DEVICE_TYPE_WH:
+ case TF_DEVICE_TYPE_SR:
+ dev_handle->ops = &tf_dev_ops_p4_init;
+ break;
+ case TF_DEVICE_TYPE_THOR:
+ dev_handle->ops = &tf_dev_ops_p58_init;
+ break;
default:
TFP_DRV_LOG(ERR,
"No such device\n");
return -ENODEV;
}
+
+ return 0;
}
int
{
switch (dev_handle->type) {
case TF_DEVICE_TYPE_WH:
+ case TF_DEVICE_TYPE_SR:
return tf_dev_unbind_p4(tfp);
+ case TF_DEVICE_TYPE_THOR:
+ return tf_dev_unbind_p58(tfp);
default:
TFP_DRV_LOG(ERR,
"No such device\n");