+static int32_t
+bnxt_ulp_devid_get(struct bnxt *bp,
+ enum bnxt_ulp_device_id *ulp_dev_id)
+{
+ if (BNXT_CHIP_P5(bp)) {
+ *ulp_dev_id = BNXT_ULP_DEVICE_ID_THOR;
+ return 0;
+ }
+
+ if (BNXT_STINGRAY(bp))
+ *ulp_dev_id = BNXT_ULP_DEVICE_ID_STINGRAY;
+ else
+ /* Assuming Whitney */
+ *ulp_dev_id = BNXT_ULP_DEVICE_ID_WH_PLUS;
+
+ return 0;
+}
+
+struct bnxt_ulp_app_capabilities_info *
+bnxt_ulp_app_cap_list_get(uint32_t *num_entries)
+{
+ if (!num_entries)
+ return NULL;
+ *num_entries = BNXT_ULP_APP_CAP_TBL_MAX_SZ;
+ return ulp_app_cap_info_list;
+}
+
+static struct bnxt_ulp_resource_resv_info *
+bnxt_ulp_app_resource_resv_list_get(uint32_t *num_entries)
+{
+ if (num_entries == NULL)
+ return NULL;
+ *num_entries = BNXT_ULP_APP_RESOURCE_RESV_LIST_MAX_SZ;
+ return ulp_app_resource_resv_list;
+}
+
+struct bnxt_ulp_resource_resv_info *
+bnxt_ulp_resource_resv_list_get(uint32_t *num_entries)
+{
+ if (!num_entries)
+ return NULL;
+ *num_entries = BNXT_ULP_RESOURCE_RESV_LIST_MAX_SZ;
+ return ulp_resource_resv_list;
+}
+
+struct bnxt_ulp_glb_resource_info *
+bnxt_ulp_app_glb_resource_info_list_get(uint32_t *num_entries)
+{
+ if (!num_entries)
+ return NULL;
+ *num_entries = BNXT_ULP_APP_GLB_RESOURCE_TBL_MAX_SZ;
+ return ulp_app_glb_resource_tbl;
+}
+
+static int32_t
+bnxt_ulp_named_resources_calc(struct bnxt_ulp_context *ulp_ctx,
+ struct bnxt_ulp_glb_resource_info *info,
+ uint32_t num,
+ struct tf_session_resources *res)
+{
+ uint32_t dev_id = BNXT_ULP_DEVICE_ID_LAST, res_type, i;
+ enum tf_dir dir;
+ uint8_t app_id;
+ int32_t rc = 0;
+
+ if (ulp_ctx == NULL || info == NULL || res == NULL || num == 0) {
+ BNXT_TF_DBG(ERR, "Invalid parms to named resources calc.\n");
+ return -EINVAL;
+ }
+
+ rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
+ return -EINVAL;
+ }
+
+ rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Unable to get the dev id from ulp.\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num; i++) {
+ if (dev_id != info[i].device_id || app_id != info[i].app_id)
+ continue;
+ dir = info[i].direction;
+ res_type = info[i].resource_type;
+
+ switch (info[i].resource_func) {
+ case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
+ res->ident_cnt[dir].cnt[res_type]++;
+ break;
+ case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
+ res->tbl_cnt[dir].cnt[res_type]++;
+ break;
+ case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
+ res->tcam_cnt[dir].cnt[res_type]++;
+ break;
+ case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
+ res->em_cnt[dir].cnt[res_type]++;
+ break;
+ default:
+ BNXT_TF_DBG(ERR, "Unknown resource func (0x%x)\n,",
+ info[i].resource_func);
+ continue;
+ }
+ }
+
+ return 0;
+}
+
+static int32_t
+bnxt_ulp_unnamed_resources_calc(struct bnxt_ulp_context *ulp_ctx,
+ struct bnxt_ulp_resource_resv_info *info,
+ uint32_t num,
+ struct tf_session_resources *res)
+{
+ uint32_t dev_id, res_type, i;
+ enum tf_dir dir;
+ uint8_t app_id;
+ int32_t rc = 0;
+
+ if (ulp_ctx == NULL || res == NULL || info == NULL || num == 0) {
+ BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n");
+ return -EINVAL;
+ }
+
+ rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
+ return -EINVAL;
+ }
+
+ rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Unable to get the dev id from ulp.\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num; i++) {
+ if (app_id != info[i].app_id || dev_id != info[i].device_id)
+ continue;
+ dir = info[i].direction;
+ res_type = info[i].resource_type;
+
+ switch (info[i].resource_func) {
+ case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
+ res->ident_cnt[dir].cnt[res_type] = info[i].count;
+ break;
+ case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
+ res->tbl_cnt[dir].cnt[res_type] = info[i].count;
+ break;
+ case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
+ res->tcam_cnt[dir].cnt[res_type] = info[i].count;
+ break;
+ case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
+ res->em_cnt[dir].cnt[res_type] = info[i].count;
+ break;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+static int32_t
+bnxt_ulp_tf_resources_get(struct bnxt_ulp_context *ulp_ctx,
+ struct tf_session_resources *res)
+{
+ struct bnxt_ulp_resource_resv_info *unnamed = NULL;
+ uint32_t unum;
+ int32_t rc = 0;
+
+ if (ulp_ctx == NULL || res == NULL) {
+ BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n");
+ return -EINVAL;
+ }
+
+ unnamed = bnxt_ulp_resource_resv_list_get(&unum);
+ if (unnamed == NULL) {
+ BNXT_TF_DBG(ERR, "Unable to get resource resv list.\n");
+ return -EINVAL;
+ }
+
+ rc = bnxt_ulp_unnamed_resources_calc(ulp_ctx, unnamed, unum, res);
+ if (rc)
+ BNXT_TF_DBG(ERR, "Unable to calc resources for session.\n");
+
+ return rc;
+}
+
+static int32_t
+bnxt_ulp_tf_shared_session_resources_get(struct bnxt_ulp_context *ulp_ctx,
+ struct tf_session_resources *res)
+{
+ struct bnxt_ulp_resource_resv_info *unnamed;
+ struct bnxt_ulp_glb_resource_info *named;
+ uint32_t unum, nnum;
+ int32_t rc;
+
+ if (ulp_ctx == NULL || res == NULL) {
+ BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n");
+ return -EINVAL;
+ }
+
+ /* Make sure the resources are zero before accumulating. */
+ memset(res, 0, sizeof(struct tf_session_resources));
+
+ /*
+ * Shared resources are comprised of both named and unnamed resources.
+ * First get the unnamed counts, and then add the named to the result.
+ */
+ /* Get the baseline counts */
+ unnamed = bnxt_ulp_app_resource_resv_list_get(&unum);
+ if (unnamed == NULL) {
+ BNXT_TF_DBG(ERR, "Unable to get shared resource resv list.\n");
+ return -EINVAL;
+ }
+ rc = bnxt_ulp_unnamed_resources_calc(ulp_ctx, unnamed, unum, res);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Unable to calc resources for shared session.\n");
+ return -EINVAL;
+ }
+
+ /* Get the named list and add the totals */
+ named = bnxt_ulp_app_glb_resource_info_list_get(&nnum);
+ if (named == NULL) {
+ BNXT_TF_DBG(ERR, "Unable to get app global resource list\n");
+ return -EINVAL;
+ }
+ rc = bnxt_ulp_named_resources_calc(ulp_ctx, named, nnum, res);
+ if (rc)
+ BNXT_TF_DBG(ERR, "Unable to calc named resources\n");
+
+ return rc;
+}
+
+int32_t
+bnxt_ulp_cntxt_app_caps_init(struct bnxt_ulp_context *ulp_ctx,
+ uint8_t app_id, uint32_t dev_id)
+{
+ struct bnxt_ulp_app_capabilities_info *info;
+ uint32_t num = 0;
+ uint16_t i;
+ bool found = false;
+
+ if (ULP_APP_DEV_UNSUPPORTED_ENABLED(ulp_ctx->cfg_data->ulp_flags)) {
+ BNXT_TF_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n",
+ app_id, dev_id);
+ return -EINVAL;
+ }
+
+ info = bnxt_ulp_app_cap_list_get(&num);
+ if (!info || !num) {
+ BNXT_TF_DBG(ERR, "Failed to get app capabilities.\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num; i++) {
+ if (info[i].app_id != app_id || info[i].device_id != dev_id)
+ continue;
+ found = true;
+ if (info[i].flags & BNXT_ULP_APP_CAP_SHARED_EN)
+ ulp_ctx->cfg_data->ulp_flags |=
+ BNXT_ULP_SHARED_SESSION_ENABLED;
+ if (info[i].flags & BNXT_ULP_APP_CAP_HOT_UPGRADE_EN)
+ ulp_ctx->cfg_data->ulp_flags |=
+ BNXT_ULP_HIGH_AVAIL_ENABLED;
+ if (info[i].flags & BNXT_ULP_APP_CAP_UNICAST_ONLY)
+ ulp_ctx->cfg_data->ulp_flags |=
+ BNXT_ULP_APP_UNICAST_ONLY;
+ }
+ if (!found) {
+ BNXT_TF_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n",
+ app_id, dev_id);
+ ulp_ctx->cfg_data->ulp_flags |= BNXT_ULP_APP_DEV_UNSUPPORTED;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void
+ulp_ctx_shared_session_close(struct bnxt *bp,
+ struct bnxt_ulp_session_state *session)
+{
+ struct tf *tfp;
+ int32_t rc;
+
+ if (!bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx))
+ return;
+
+ tfp = bnxt_ulp_cntxt_shared_tfp_get(bp->ulp_ctx);
+ if (!tfp) {
+ /*
+ * Log it under debug since this is likely a case of the
+ * shared session not being created. For example, a failed
+ * initialization.
+ */
+ BNXT_TF_DBG(DEBUG, "Failed to get shared tfp on close.\n");
+ return;
+ }
+ rc = tf_close_session(tfp);
+ if (rc)
+ BNXT_TF_DBG(ERR, "Failed to close the shared session rc=%d.\n",
+ rc);
+ (void)bnxt_ulp_cntxt_shared_tfp_set(bp->ulp_ctx, NULL);
+
+ session->g_shared_tfp.session = NULL;
+}
+
+static int32_t
+ulp_ctx_shared_session_open(struct bnxt *bp,
+ struct bnxt_ulp_session_state *session)
+{
+ struct rte_eth_dev *ethdev = bp->eth_dev;
+ struct tf_session_resources *resources;
+ struct tf_open_session_parms parms;
+ size_t copy_nbytes;
+ uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST;
+ int32_t rc = 0;
+ uint8_t app_id;
+
+ /* only perform this if shared session is enabled. */
+ if (!bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx))
+ return 0;
+
+ memset(&parms, 0, sizeof(parms));
+
+ rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id,
+ parms.ctrl_chan_name);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n",
+ ethdev->data->port_id, rc);
+ return rc;
+ }
+ resources = &parms.resources;
+
+ /*
+ * Need to account for size of ctrl_chan_name and 1 extra for Null
+ * terminator
+ */
+ copy_nbytes = sizeof(parms.ctrl_chan_name) -
+ strlen(parms.ctrl_chan_name) - 1;
+
+ /*
+ * Build the ctrl_chan_name with shared token.
+ * When HA is enabled, the WC TCAM needs extra management by the core,
+ * so add the wc_tcam string to the control channel.
+ */
+ if (bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx))
+ strncat(parms.ctrl_chan_name, "-tf_shared-wc_tcam",
+ copy_nbytes);
+ else
+ strncat(parms.ctrl_chan_name, "-tf_shared", copy_nbytes);
+
+ rc = bnxt_ulp_tf_shared_session_resources_get(bp->ulp_ctx, resources);
+ if (rc)
+ return rc;
+
+ rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
+ return -EINVAL;
+ }
+
+ rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n");
+ return rc;
+ }
+
+ switch (ulp_dev_id) {
+ case BNXT_ULP_DEVICE_ID_WH_PLUS:
+ parms.device_type = TF_DEVICE_TYPE_WH;
+ break;
+ case BNXT_ULP_DEVICE_ID_STINGRAY:
+ parms.device_type = TF_DEVICE_TYPE_SR;
+ break;
+ case BNXT_ULP_DEVICE_ID_THOR:
+ parms.device_type = TF_DEVICE_TYPE_THOR;
+ break;
+ default:
+ BNXT_TF_DBG(ERR, "Unable to determine dev for opening session.\n");
+ return rc;
+ }
+
+ parms.shadow_copy = true;
+ parms.bp = bp;
+ if (app_id == 0 || app_id == 3)
+ parms.wc_num_slices = TF_WC_TCAM_2_SLICE_PER_ROW;
+ else
+ parms.wc_num_slices = TF_WC_TCAM_1_SLICE_PER_ROW;
+
+ /*
+ * Open the session here, but the collect the resources during the
+ * mapper initialization.
+ */
+ rc = tf_open_session(&bp->tfp_shared, &parms);
+ if (rc)
+ return rc;
+
+ if (parms.shared_session_creator)
+ BNXT_TF_DBG(DEBUG, "Shared session creator.\n");
+ else
+ BNXT_TF_DBG(DEBUG, "Shared session attached.\n");
+
+ /* Save the shared session in global data */
+ if (!session->g_shared_tfp.session)
+ session->g_shared_tfp.session = bp->tfp_shared.session;
+
+ rc = bnxt_ulp_cntxt_shared_tfp_set(bp->ulp_ctx, &bp->tfp_shared);
+ if (rc)
+ BNXT_TF_DBG(ERR, "Failed to add shared tfp to ulp (%d)\n", rc);
+
+ return rc;
+}
+
+static int32_t
+ulp_ctx_shared_session_attach(struct bnxt *bp,
+ struct bnxt_ulp_session_state *session)
+{
+ int32_t rc = 0;
+
+ /* Simply return success if shared session not enabled */
+ if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) {
+ bp->tfp_shared.session = session->g_shared_tfp.session;
+ rc = ulp_ctx_shared_session_open(bp, session);
+ }
+
+ return rc;
+}
+
+static void
+ulp_ctx_shared_session_detach(struct bnxt *bp)
+{
+ if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) {
+ if (bp->tfp_shared.session) {
+ tf_close_session(&bp->tfp_shared);
+ bp->tfp_shared.session = NULL;
+ }
+ }
+}
+