From patchwork Wed Apr 19 20:11:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Randy Schacher X-Patchwork-Id: 126274 X-Patchwork-Delegate: ajit.khaparde@broadcom.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 627E24298D; Wed, 19 Apr 2023 22:12:39 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 8A52642D3E; Wed, 19 Apr 2023 22:11:58 +0200 (CEST) Received: from mail-pj1-f100.google.com (mail-pj1-f100.google.com [209.85.216.100]) by mails.dpdk.org (Postfix) with ESMTP id 46A4D42D10 for ; Wed, 19 Apr 2023 22:11:54 +0200 (CEST) Received: by mail-pj1-f100.google.com with SMTP id 98e67ed59e1d1-244a5ccf13eso102578a91.2 for ; Wed, 19 Apr 2023 13:11:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1681935113; x=1684527113; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zw089jKLQGQLxgq+TDDcfV9/ZKwIkMFJY6X1lUjd+hU=; b=Lyo+7UznZamnJj2cR0u4gIbq4Kry6/EJaDUuSK054XfZ2gYIrOrZtfTMBa0r6S7mBb qIRCmXSPVDUiTD6R6tmP/mCItfVl/B+grdyM+c6mYVZr4hrOUq71Ax/2vKZF3CcalvPA KE5Eun8L891SO0eeZR2wGmiG6u2LGvpEaLYPk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681935113; x=1684527113; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zw089jKLQGQLxgq+TDDcfV9/ZKwIkMFJY6X1lUjd+hU=; b=A7NT7+kVDDq+pnT5908oU1xuoETUV7JrqRe4b1Ey1AenozPJcQNHA49e98aeeVgiIa A5nDXapYlr6hYLVMRd3GWqqlDj9pvLEVR0UHKcQmz/X1Jsv6AKMcYqtW89JVM8Jy+Vqm gJIsDgDixOql+1F/kmWUmkb41p1J5mptGp1G4uYIzsi3lKfzhwuzBuTcB6RDojZTdXPz 988/Tz42Kv2ryHKXyaYmn4ATej4yxtwfUo/zMV/QD/HklYyOjGz9+9M23Z77IDAQkGCq KC5J7kc4gBhFSQPqEzA2UfsPodGXdh6c5A6qOyMyuC8aj45LNRBAg6x7JYjXFlfX0UNO hLDg== X-Gm-Message-State: AAQBX9co52/ALLsO/soP9ad40YrzCyPzrvj+ik43K+ELwQ0mSUBL41kl SnTmy+YO/bviZdg5EoPObt6tdNjiQ7OaUzIbMjUA2444V1nTa1Vf2vnMii0Sh5g/7TxIap+/rv4 cUnhgGOF9rHj6FM4KzGnZdi+oQ95c3nxEHLUecQWbWmDG15z/+zblCRjZkZpgvfTSslALXI90nC 2AlqIqhYMh9NbRGOg= X-Google-Smtp-Source: AKy350Y8N6ocL6CG5v8EgkCwp/iPWwjv9V5oiEAKJpyBDp9J4AJj6FPqjPe3T1WjhtbRwi/b30hBMYgo3d3U X-Received: by 2002:a17:90b:94c:b0:247:6eda:a2ae with SMTP id dw12-20020a17090b094c00b002476edaa2aemr3770173pjb.32.1681935112790; Wed, 19 Apr 2023 13:11:52 -0700 (PDT) Received: from r650-k2.dhcp.broadcom.net ([192.19.144.250]) by smtp-relay.gmail.com with ESMTPS id oc14-20020a17090b1c0e00b0024702c1a63bsm487614pjb.16.2023.04.19.13.11.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 13:11:52 -0700 (PDT) X-Relaying-Domain: broadcom.com From: Randy Schacher To: dev@dpdk.org Cc: Farah Smith , Shahaji Bhosle Subject: [PATCH 04/11] net/bnxt: update Truflow core Date: Wed, 19 Apr 2023 20:11:15 +0000 Message-Id: <20230419201122.338133-5-stuart.schacher@broadcom.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230419201122.338133-1-stuart.schacher@broadcom.com> References: <20230419201122.338133-1-stuart.schacher@broadcom.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org - Add shared session managment - Add SRAM session managment - Add dynamic TCAM management - Add shared TCAM session managment - Add Hot Upgrade support - Update copyright Signed-off-by: Farah Smith Reviewed-by: Shahaji Bhosle --- drivers/net/bnxt/bnxt.h | 1 - drivers/net/bnxt/bnxt_irq.h | 1 - drivers/net/bnxt/bnxt_nvm_defs.h | 1 - drivers/net/bnxt/bnxt_ring.h | 1 - drivers/net/bnxt/bnxt_rxr.h | 1 - drivers/net/bnxt/bnxt_txr.h | 1 - drivers/net/bnxt/bnxt_util.h | 1 - drivers/net/bnxt/tf_core/cfa_resource_types.h | 2 - drivers/net/bnxt/tf_core/cfa_tcam_mgr.c | 2116 +++++++++++++++++ drivers/net/bnxt/tf_core/cfa_tcam_mgr.h | 523 ++++ .../net/bnxt/tf_core/cfa_tcam_mgr_device.h | 101 + .../net/bnxt/tf_core/cfa_tcam_mgr_hwop_msg.c | 201 ++ .../net/bnxt/tf_core/cfa_tcam_mgr_hwop_msg.h | 28 + drivers/net/bnxt/tf_core/cfa_tcam_mgr_p4.c | 921 +++++++ drivers/net/bnxt/tf_core/cfa_tcam_mgr_p4.h | 20 + drivers/net/bnxt/tf_core/cfa_tcam_mgr_p58.c | 926 ++++++++ drivers/net/bnxt/tf_core/cfa_tcam_mgr_p58.h | 20 + drivers/net/bnxt/tf_core/cfa_tcam_mgr_sbmp.h | 126 + .../net/bnxt/tf_core/cfa_tcam_mgr_session.c | 377 +++ .../net/bnxt/tf_core/cfa_tcam_mgr_session.h | 54 + drivers/net/bnxt/tf_core/meson.build | 36 +- drivers/net/bnxt/tf_core/tf_core.c | 54 +- drivers/net/bnxt/tf_core/tf_core.h | 97 +- drivers/net/bnxt/tf_core/tf_device.c | 18 +- drivers/net/bnxt/tf_core/tf_device.h | 2 +- drivers/net/bnxt/tf_core/tf_device_p4.c | 14 +- drivers/net/bnxt/tf_core/tf_device_p58.c | 84 +- drivers/net/bnxt/tf_core/tf_em_common.c | 2 +- drivers/net/bnxt/tf_core/tf_em_internal.c | 10 +- drivers/net/bnxt/tf_core/tf_identifier.c | 1 + drivers/net/bnxt/tf_core/tf_if_tbl.c | 59 +- drivers/net/bnxt/tf_core/tf_msg.c | 217 +- drivers/net/bnxt/tf_core/tf_msg.h | 38 +- drivers/net/bnxt/tf_core/tf_rm.c | 117 +- drivers/net/bnxt/tf_core/tf_session.c | 112 +- drivers/net/bnxt/tf_core/tf_session.h | 65 +- drivers/net/bnxt/tf_core/tf_sram_mgr.c | 117 +- drivers/net/bnxt/tf_core/tf_sram_mgr.h | 22 +- drivers/net/bnxt/tf_core/tf_tbl.c | 8 +- drivers/net/bnxt/tf_core/tf_tbl_sram.c | 25 +- drivers/net/bnxt/tf_core/tf_tcam.c | 226 +- drivers/net/bnxt/tf_core/tf_tcam_mgr_msg.c | 286 +++ drivers/net/bnxt/tf_core/tf_tcam_mgr_msg.h | 49 + drivers/net/bnxt/tf_core/tf_tcam_shared.c | 1146 +-------- drivers/net/bnxt/tf_core/tf_tcam_shared.h | 3 +- drivers/net/bnxt/tf_ulp/bnxt_ulp.c | 8 +- 46 files changed, 6686 insertions(+), 1552 deletions(-) create mode 100644 drivers/net/bnxt/tf_core/cfa_tcam_mgr.c create mode 100644 drivers/net/bnxt/tf_core/cfa_tcam_mgr.h create mode 100644 drivers/net/bnxt/tf_core/cfa_tcam_mgr_device.h create mode 100644 drivers/net/bnxt/tf_core/cfa_tcam_mgr_hwop_msg.c create mode 100644 drivers/net/bnxt/tf_core/cfa_tcam_mgr_hwop_msg.h create mode 100644 drivers/net/bnxt/tf_core/cfa_tcam_mgr_p4.c create mode 100644 drivers/net/bnxt/tf_core/cfa_tcam_mgr_p4.h create mode 100644 drivers/net/bnxt/tf_core/cfa_tcam_mgr_p58.c create mode 100644 drivers/net/bnxt/tf_core/cfa_tcam_mgr_p58.h create mode 100644 drivers/net/bnxt/tf_core/cfa_tcam_mgr_sbmp.h create mode 100644 drivers/net/bnxt/tf_core/cfa_tcam_mgr_session.c create mode 100644 drivers/net/bnxt/tf_core/cfa_tcam_mgr_session.h create mode 100644 drivers/net/bnxt/tf_core/tf_tcam_mgr_msg.c create mode 100644 drivers/net/bnxt/tf_core/tf_tcam_mgr_msg.h diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h index 48bd8f2418..2bccdec7e0 100644 --- a/drivers/net/bnxt/bnxt.h +++ b/drivers/net/bnxt/bnxt.h @@ -1044,5 +1044,4 @@ int bnxt_flow_ops_get_op(struct rte_eth_dev *dev, int bnxt_dev_start_op(struct rte_eth_dev *eth_dev); int bnxt_dev_stop_op(struct rte_eth_dev *eth_dev); void bnxt_handle_vf_cfg_change(void *arg); - #endif diff --git a/drivers/net/bnxt/bnxt_irq.h b/drivers/net/bnxt/bnxt_irq.h index e498578968..e2d61bae7a 100644 --- a/drivers/net/bnxt/bnxt_irq.h +++ b/drivers/net/bnxt/bnxt_irq.h @@ -20,5 +20,4 @@ void bnxt_enable_int(struct bnxt *bp); int bnxt_setup_int(struct bnxt *bp); int bnxt_request_int(struct bnxt *bp); void bnxt_int_handler(void *param); - #endif diff --git a/drivers/net/bnxt/bnxt_nvm_defs.h b/drivers/net/bnxt/bnxt_nvm_defs.h index f5ac4e8c84..57ddefa7a1 100644 --- a/drivers/net/bnxt/bnxt_nvm_defs.h +++ b/drivers/net/bnxt/bnxt_nvm_defs.h @@ -66,5 +66,4 @@ enum bnxnvm_pkglog_field_index { BNX_PKG_LOG_FIELD_IDX_INSTALLED_ITEMS = 5, BNX_PKG_LOG_FIELD_IDX_INSTALLED_MASK = 6 }; - #endif /* Don't add anything after this line */ diff --git a/drivers/net/bnxt/bnxt_ring.h b/drivers/net/bnxt/bnxt_ring.h index 3d747aba54..baa60b2627 100644 --- a/drivers/net/bnxt/bnxt_ring.h +++ b/drivers/net/bnxt/bnxt_ring.h @@ -142,5 +142,4 @@ static inline void bnxt_db_cq(struct bnxt_cp_ring_info *cpr) B_CP_DIS_DB(cpr, cp_raw_cons); } } - #endif diff --git a/drivers/net/bnxt/bnxt_rxr.h b/drivers/net/bnxt/bnxt_rxr.h index e132166a18..8e722b7bf0 100644 --- a/drivers/net/bnxt/bnxt_rxr.h +++ b/drivers/net/bnxt/bnxt_rxr.h @@ -386,5 +386,4 @@ bnxt_parse_pkt_type_v2(struct rte_mbuf *mbuf, mbuf->packet_type = pkt_type; } - #endif /* _BNXT_RXR_H_ */ diff --git a/drivers/net/bnxt/bnxt_txr.h b/drivers/net/bnxt/bnxt_txr.h index e11343c082..75456df5bd 100644 --- a/drivers/net/bnxt/bnxt_txr.h +++ b/drivers/net/bnxt/bnxt_txr.h @@ -90,5 +90,4 @@ int bnxt_flush_tx_cmp(struct bnxt_cp_ring_info *cpr); TX_BD_LONG_LFLAGS_IP_CHKSUM) #define TX_BD_FLG_TIP_TCP_UDP_CHKSUM (TX_BD_LONG_LFLAGS_TCP_UDP_CHKSUM | \ TX_BD_LONG_LFLAGS_T_IP_CHKSUM) - #endif diff --git a/drivers/net/bnxt/bnxt_util.h b/drivers/net/bnxt/bnxt_util.h index 3437dc75ae..7f5b4c160e 100644 --- a/drivers/net/bnxt/bnxt_util.h +++ b/drivers/net/bnxt/bnxt_util.h @@ -17,5 +17,4 @@ int bnxt_check_zero_bytes(const uint8_t *bytes, int len); void bnxt_eth_hw_addr_random(uint8_t *mac_addr); - #endif /* _BNXT_UTIL_H_ */ diff --git a/drivers/net/bnxt/tf_core/cfa_resource_types.h b/drivers/net/bnxt/tf_core/cfa_resource_types.h index 874d7b834f..8431c778e4 100644 --- a/drivers/net/bnxt/tf_core/cfa_resource_types.h +++ b/drivers/net/bnxt/tf_core/cfa_resource_types.h @@ -63,7 +63,6 @@ #define CFA_RESOURCE_TYPE_P59_VEB_TCAM 0x18UL #define CFA_RESOURCE_TYPE_P59_LAST CFA_RESOURCE_TYPE_P59_VEB_TCAM - /* Meter */ #define CFA_RESOURCE_TYPE_P58_METER 0x0UL /* SRAM_Bank_0 */ @@ -184,7 +183,6 @@ #define CFA_RESOURCE_TYPE_P45_TBL_SCOPE 0x23UL #define CFA_RESOURCE_TYPE_P45_LAST CFA_RESOURCE_TYPE_P45_TBL_SCOPE - /* Multicast Group */ #define CFA_RESOURCE_TYPE_P4_MCG 0x0UL /* Encap 8 byte record */ diff --git a/drivers/net/bnxt/tf_core/cfa_tcam_mgr.c b/drivers/net/bnxt/tf_core/cfa_tcam_mgr.c new file mode 100644 index 0000000000..f26d93e7a9 --- /dev/null +++ b/drivers/net/bnxt/tf_core/cfa_tcam_mgr.c @@ -0,0 +1,2116 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021-2023 Broadcom + * All rights reserved. + */ + +#include +#include + +#include "hcapi_cfa_defs.h" + +#include "tfp.h" +#include "tf_session.h" +#include "tf_util.h" +#include "cfa_tcam_mgr.h" +#include "cfa_tcam_mgr_hwop_msg.h" +#include "cfa_tcam_mgr_device.h" +#include "cfa_tcam_mgr_session.h" +#include "cfa_tcam_mgr_p58.h" +#include "cfa_tcam_mgr_p4.h" + +#define TF_TCAM_SLICE_INVALID (-1) + +/* + * The following macros are for setting the entry status in a row entry. + * row is (struct cfa_tcam_mgr_table_rows_0 *) + */ +#define ROW_ENTRY_INUSE(row, entry) ((row)->entry_inuse & (1U << (entry))) +#define ROW_ENTRY_SET(row, entry) ((row)->entry_inuse |= (1U << (entry))) +#define ROW_ENTRY_CLEAR(row, entry) ((row)->entry_inuse &= ~(1U << (entry))) +#define ROW_INUSE(row) ((row)->entry_inuse != 0) + +static struct cfa_tcam_mgr_entry_data *entry_data[TF_TCAM_MAX_SESSIONS]; + +static int global_data_initialized[TF_TCAM_MAX_SESSIONS]; +int cfa_tcam_mgr_max_entries[TF_TCAM_MAX_SESSIONS]; + +struct cfa_tcam_mgr_table_data +cfa_tcam_mgr_tables[TF_TCAM_MAX_SESSIONS][TF_DIR_MAX][CFA_TCAM_MGR_TBL_TYPE_MAX]; + +static int physical_table_types[CFA_TCAM_MGR_TBL_TYPE_MAX] = { + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_APPS] = + TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH, + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_APPS] = + TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW, + [CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_APPS] = + TF_TCAM_TBL_TYPE_PROF_TCAM, + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS] = + TF_TCAM_TBL_TYPE_WC_TCAM, + [CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_APPS] = + TF_TCAM_TBL_TYPE_SP_TCAM, + [CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_APPS] = + TF_TCAM_TBL_TYPE_CT_RULE_TCAM, + [CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_APPS] = + TF_TCAM_TBL_TYPE_VEB_TCAM, + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS] = + TF_TCAM_TBL_TYPE_WC_TCAM_HIGH, + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS] = + TF_TCAM_TBL_TYPE_WC_TCAM_LOW, +}; + +int +cfa_tcam_mgr_get_phys_table_type(enum cfa_tcam_mgr_tbl_type type) +{ + if (type >= CFA_TCAM_MGR_TBL_TYPE_MAX) + assert(0); + else + return physical_table_types[type]; +} + +const char * +cfa_tcam_mgr_tbl_2_str(enum cfa_tcam_mgr_tbl_type tcam_type) +{ + switch (tcam_type) { + case CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_AFM: + return "l2_ctxt_tcam_high AFM"; + case CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_APPS: + return "l2_ctxt_tcam_high Apps"; + case CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_AFM: + return "l2_ctxt_tcam_low AFM"; + case CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_APPS: + return "l2_ctxt_tcam_low Apps"; + case CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_AFM: + return "prof_tcam AFM"; + case CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_APPS: + return "prof_tcam Apps"; + case CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_AFM: + return "wc_tcam AFM"; + case CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS: + return "wc_tcam Apps"; + case CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_AFM: + return "veb_tcam AFM"; + case CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_APPS: + return "veb_tcam Apps"; + case CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_AFM: + return "sp_tcam AFM"; + case CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_APPS: + return "sp_tcam Apps"; + case CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_AFM: + return "ct_rule_tcam AFM"; + case CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_APPS: + return "ct_rule_tcam Apps"; + case CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_AFM: + return "wc_tcam_high AFM"; + case CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS: + return "wc_tcam_high Apps"; + case CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_AFM: + return "wc_tcam_low AFM"; + case CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS: + return "wc_tcam_low Apps"; + default: + return "Invalid tcam table type"; + } +} + +/* key_size and slice_width are in bytes */ +static int +cfa_tcam_mgr_get_num_slices(unsigned int key_size, unsigned int slice_width) +{ + int num_slices = 0; + + if (key_size == 0) + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + + num_slices = ((key_size - 1U) / slice_width) + 1U; + /* Round up to next highest power of 2 */ + /* This is necessary since, for example, 3 slices is not a valid entry + * width. + */ + num_slices--; + /* Repeat to maximum number of bits actually used */ + /* This fills in all the bits. */ + num_slices |= num_slices >> 1; + num_slices |= num_slices >> 2; + num_slices |= num_slices >> 4; + /* + * If the maximum number of slices that are supported by the HW + * increases, then additional shifts are needed. + */ + num_slices++; + return num_slices; +} + +static struct cfa_tcam_mgr_entry_data * +cfa_tcam_mgr_entry_get(int sess_idx, uint16_t id) +{ + if (id > cfa_tcam_mgr_max_entries[sess_idx]) + return NULL; + + return &entry_data[sess_idx][id]; +} + +/* Insert an entry into the entry table */ +static int +cfa_tcam_mgr_entry_insert(int sess_idx, uint16_t id, + struct cfa_tcam_mgr_entry_data *entry) +{ + if (id > cfa_tcam_mgr_max_entries[sess_idx]) + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + + memcpy(&entry_data[sess_idx][id], entry, + sizeof(entry_data[sess_idx][id])); + + return 0; +} + +/* Delete an entry from the entry table */ +static int +cfa_tcam_mgr_entry_delete(int sess_idx, uint16_t id) +{ + if (id > cfa_tcam_mgr_max_entries[sess_idx]) + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + + memset(&entry_data[sess_idx][id], 0, sizeof(entry_data[sess_idx][id])); + + return 0; +} + +/* Returns the size of the row structure taking into account how many slices a + * TCAM supports. + */ +static int +cfa_tcam_mgr_row_size_get(int sess_idx, enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type) +{ + return sizeof(struct cfa_tcam_mgr_table_rows_0) + + (cfa_tcam_mgr_tables[sess_idx][dir][type].max_slices * + sizeof(((struct cfa_tcam_mgr_table_rows_0 *)0)->entries[0])); +} + +static void * +cfa_tcam_mgr_row_ptr_get(void *base, int index, int row_size) +{ + return (uint8_t *)base + (index * row_size); +} + +/* + * Searches a table to find the direction and type of an entry. + */ +static int +cfa_tcam_mgr_entry_find_in_table(int sess_idx, int id, enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type) +{ + struct cfa_tcam_mgr_table_data *table_data; + struct cfa_tcam_mgr_table_rows_0 *row; + int max_slices, row_idx, row_size, slice; + + table_data = &cfa_tcam_mgr_tables[sess_idx][dir][type]; + if (table_data->max_entries > 0 && + table_data->hcapi_type > 0) { + max_slices = table_data->max_slices; + row_size = cfa_tcam_mgr_row_size_get(sess_idx, dir, type); + for (row_idx = table_data->start_row; + row_idx <= table_data->end_row; + row_idx++) { + row = cfa_tcam_mgr_row_ptr_get(table_data->tcam_rows, + row_idx, row_size); + if (!ROW_INUSE(row)) + continue; + for (slice = 0; + slice < (max_slices / row->entry_size); + slice++) { + if (!ROW_ENTRY_INUSE(row, slice)) + continue; + if (row->entries[slice] == id) + return 0; + } + } + } + + return -CFA_TCAM_MGR_ERR_CODE(NOENT); +} + +/* + * Searches all the tables to find the direction and type of an entry. + */ +static int +cfa_tcam_mgr_entry_find(int sess_idx, int id, enum tf_dir *tbl_dir, + enum cfa_tcam_mgr_tbl_type *tbl_type) +{ + enum tf_dir dir; + enum cfa_tcam_mgr_tbl_type type; + int rc = -CFA_TCAM_MGR_ERR_CODE(NOENT); + + for (dir = TF_DIR_RX; dir < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx]); dir++) { + for (type = CFA_TCAM_MGR_TBL_TYPE_START; + type < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx][dir]); + type++) { + rc = cfa_tcam_mgr_entry_find_in_table(sess_idx, id, dir, type); + if (rc == 0) { + *tbl_dir = dir; + *tbl_type = type; + return rc; + } + } + } + + return rc; +} + +static int +cfa_tcam_mgr_row_is_entry_free(struct cfa_tcam_mgr_table_rows_0 *row, + int max_slices, + int key_slices) +{ + int j; + + if (ROW_INUSE(row) && + row->entry_size == key_slices) { + for (j = 0; j < (max_slices / row->entry_size); j++) { + if (!ROW_ENTRY_INUSE(row, j)) + return j; + } + } + return -1; +} + +static int +cfa_tcam_mgr_entry_move(int sess_idx, struct cfa_tcam_mgr_context *context, + enum tf_dir dir, enum cfa_tcam_mgr_tbl_type type, + int entry_id, + struct cfa_tcam_mgr_table_data *table_data, + int dest_row_index, int dest_row_slice, + struct cfa_tcam_mgr_table_rows_0 *dest_row, + int source_row_index, + struct cfa_tcam_mgr_table_rows_0 *source_row, + bool free_source_entry) +{ + struct cfa_tcam_mgr_get_parms gparms = { 0 }; + struct cfa_tcam_mgr_set_parms sparms = { 0 }; + struct cfa_tcam_mgr_free_parms fparms = { 0 }; + struct cfa_tcam_mgr_entry_data *entry; + uint8_t key[CFA_TCAM_MGR_MAX_KEY_SIZE]; + uint8_t mask[CFA_TCAM_MGR_MAX_KEY_SIZE]; + uint8_t result[CFA_TCAM_MGR_MAX_KEY_SIZE]; + + int j, rc; + + entry = cfa_tcam_mgr_entry_get(sess_idx, entry_id); + if (entry == NULL) + return -1; + + gparms.dir = dir; + gparms.type = type; + gparms.hcapi_type = table_data->hcapi_type; + gparms.key = key; + gparms.mask = mask; + gparms.result = result; + gparms.id = source_row->entries[entry->slice]; + gparms.key_size = sizeof(key); + gparms.result_size = sizeof(result); + + rc = cfa_tcam_mgr_entry_get_msg(sess_idx, context, &gparms, + source_row_index, + entry->slice * source_row->entry_size, + table_data->max_slices); + if (rc != 0) + return rc; + + sparms.dir = dir; + sparms.type = type; + sparms.hcapi_type = table_data->hcapi_type; + sparms.key = key; + sparms.mask = mask; + sparms.result = result; + sparms.id = gparms.id; + sparms.key_size = gparms.key_size; + sparms.result_size = gparms.result_size; + + /* Slice in destination row not specified. Find first free slice. */ + if (dest_row_slice < 0) + for (j = 0; + j < (table_data->max_slices / dest_row->entry_size); + j++) { + if (!ROW_ENTRY_INUSE(dest_row, j)) { + dest_row_slice = j; + break; + } + } + + /* If no free slice found, return error. */ + if (dest_row_slice < 0) + return -CFA_TCAM_MGR_ERR_CODE(PERM); + + rc = cfa_tcam_mgr_entry_set_msg(sess_idx, context, &sparms, + dest_row_index, + dest_row_slice * dest_row->entry_size, + table_data->max_slices); + if (rc != 0) + return rc; + + if (free_source_entry) { + fparms.dir = dir; + fparms.type = type; + fparms.hcapi_type = table_data->hcapi_type; + rc = cfa_tcam_mgr_entry_free_msg(sess_idx, context, &fparms, + source_row_index, + entry->slice * + dest_row->entry_size, + table_data->row_width / + table_data->max_slices * + source_row->entry_size, + table_data->result_size, + table_data->max_slices); + if (rc != 0) { + CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, + dir, type, + "Failed to free entry ID %d at" + " row %d, slice %d for sess_idx %d. rc: %d.\n", + gparms.id, + source_row_index, + entry->slice, + sess_idx, + -rc); + } + } + + ROW_ENTRY_SET(dest_row, dest_row_slice); + dest_row->entries[dest_row_slice] = entry_id; + ROW_ENTRY_CLEAR(source_row, entry->slice); + entry->row = dest_row_index; + entry->slice = dest_row_slice; + + return 0; +} + +static int +cfa_tcam_mgr_row_move(int sess_idx, struct cfa_tcam_mgr_context *context, + enum tf_dir dir, enum cfa_tcam_mgr_tbl_type type, + struct cfa_tcam_mgr_table_data *table_data, + int dest_row_index, + struct cfa_tcam_mgr_table_rows_0 *dest_row, + int source_row_index, + struct cfa_tcam_mgr_table_rows_0 *source_row) +{ + struct cfa_tcam_mgr_free_parms fparms = { 0 }; + int j, rc; + + dest_row->priority = source_row->priority; + dest_row->entry_size = source_row->entry_size; + dest_row->entry_inuse = 0; + + fparms.dir = dir; + fparms.type = type; + fparms.hcapi_type = table_data->hcapi_type; + + for (j = 0; + j < (table_data->max_slices / source_row->entry_size); + j++) { + if (ROW_ENTRY_INUSE(source_row, j)) { + cfa_tcam_mgr_entry_move(sess_idx, context, dir, type, + source_row->entries[j], + table_data, + dest_row_index, j, dest_row, + source_row_index, source_row, + true); + } else { + /* Slice not in use, write an empty slice. */ + rc = cfa_tcam_mgr_entry_free_msg(sess_idx, context, &fparms, + dest_row_index, + j * + dest_row->entry_size, + table_data->row_width / + table_data->max_slices * + dest_row->entry_size, + table_data->result_size, + table_data->max_slices); + if (rc != 0) + return rc; + } + } + + return 0; +} + +/* Install entry into in-memory tables, not into TCAM (yet). */ +static void +cfa_tcam_mgr_row_entry_install(int sess_idx, + struct cfa_tcam_mgr_table_rows_0 *row, + struct cfa_tcam_mgr_alloc_parms *parms, + struct cfa_tcam_mgr_entry_data *entry, + uint16_t id, + int key_slices, + int row_index, int slice) +{ + if (global_data_initialized[sess_idx] == 0) { + CFA_TCAM_MGR_LOG(INFO, "PANIC: No TCAM data created for sess_idx %d\n", + sess_idx); + return; + } + + if (slice == TF_TCAM_SLICE_INVALID) { + slice = 0; + row->entry_size = key_slices; + row->priority = parms->priority; + } + + ROW_ENTRY_SET(row, slice); + row->entries[slice] = id; + entry->row = row_index; + entry->slice = slice; +} + +/* Finds an empty row that can be used and reserve for entry. If necessary, + * entries will be shuffled in order to make room. + */ +static struct cfa_tcam_mgr_table_rows_0 * +cfa_tcam_mgr_empty_row_alloc(int sess_idx, struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_alloc_parms *parms, + struct cfa_tcam_mgr_entry_data *entry, + uint16_t id, + int key_slices) +{ + struct cfa_tcam_mgr_table_rows_0 *tcam_rows; + struct cfa_tcam_mgr_table_rows_0 *from_row; + struct cfa_tcam_mgr_table_rows_0 *to_row; + struct cfa_tcam_mgr_table_rows_0 *row; + struct cfa_tcam_mgr_table_data *table_data; + int i, max_slices, row_size; + int to_row_idx, from_row_idx, slice, start_row, end_row; + int empty_row = -1; + int target_row = -1; + + table_data = &cfa_tcam_mgr_tables[sess_idx][parms->dir][parms->type]; + + start_row = table_data->start_row; + end_row = table_data->end_row; + max_slices = table_data->max_slices; + tcam_rows = table_data->tcam_rows; + + row_size = cfa_tcam_mgr_row_size_get(sess_idx, parms->dir, parms->type); + + /* + * First check for partially used entries, but only if the key needs + * fewer slices than there are in a row. + */ + if (key_slices < max_slices) { + for (i = start_row; i <= end_row; i++) { + row = cfa_tcam_mgr_row_ptr_get(tcam_rows, i, row_size); + if (!ROW_INUSE(row)) + continue; + if (row->priority < parms->priority) + break; + if (row->priority > parms->priority) + continue; + slice = cfa_tcam_mgr_row_is_entry_free(row, + max_slices, + key_slices); + if (slice >= 0) { + cfa_tcam_mgr_row_entry_install(sess_idx, row, parms, + entry, id, + key_slices, + i, slice); + return row; + } + } + } + + /* No partially used rows available. Find an empty row, if any. */ + + /* + * All max priority entries are placed in the beginning of the TCAM. It + * should not be necessary to shuffle any of these entries. All other + * priorities are placed from the end of the TCAM and may require + * shuffling. + */ + if (parms->priority == TF_TCAM_PRIORITY_MAX) { + /* Handle max priority first. */ + for (i = start_row; i <= end_row; i++) { + row = cfa_tcam_mgr_row_ptr_get(tcam_rows, i, row_size); + if (!ROW_INUSE(row)) { + cfa_tcam_mgr_row_entry_install(sess_idx, + row, parms, + entry, + id, key_slices, + i, + TF_TCAM_SLICE_INVALID); + return row; + } + if (row->priority < parms->priority) { + /* + * No free entries before priority change, table + * is full. + */ + return NULL; + } + } + /* No free entries found, table is full. */ + return NULL; + } + + /* Use the highest available entry */ + for (i = end_row; i >= start_row; i--) { + row = cfa_tcam_mgr_row_ptr_get(tcam_rows, i, row_size); + if (!ROW_INUSE(row)) { + empty_row = i; + break; + } + + if (row->priority > parms->priority && + target_row < 0) + target_row = i; + } + + if (empty_row < 0) { + /* No free entries found, table is full. */ + return NULL; + } + + if (target_row < 0) { + /* + * Did not find a row with higher priority before unused row so + * just install new entry in empty_row. + */ + row = cfa_tcam_mgr_row_ptr_get(tcam_rows, empty_row, row_size); + cfa_tcam_mgr_row_entry_install(sess_idx, row, parms, entry, id, + key_slices, empty_row, + TF_TCAM_SLICE_INVALID); + return row; + } + + to_row_idx = empty_row; + to_row = cfa_tcam_mgr_row_ptr_get(tcam_rows, to_row_idx, row_size); + while (to_row_idx < target_row) { + from_row_idx = to_row_idx + 1; + from_row = cfa_tcam_mgr_row_ptr_get(tcam_rows, from_row_idx, + row_size); + /* + * Find the highest row with the same priority as the initial + * source row (from_row). It's only necessary to copy one row + * of each priority. + */ + for (i = from_row_idx + 1; i <= target_row; i++) { + row = cfa_tcam_mgr_row_ptr_get(tcam_rows, i, row_size); + if (row->priority != from_row->priority) + break; + from_row_idx = i; + from_row = row; + } + cfa_tcam_mgr_row_move(sess_idx, context, parms->dir, parms->type, + table_data, to_row_idx, to_row, + from_row_idx, from_row); + to_row = from_row; + to_row_idx = from_row_idx; + } + to_row = cfa_tcam_mgr_row_ptr_get(tcam_rows, target_row, row_size); + memset(to_row, 0, row_size); + cfa_tcam_mgr_row_entry_install(sess_idx, to_row, parms, entry, id, + key_slices, target_row, + TF_TCAM_SLICE_INVALID); + + return row; +} + +/* + * This function will combine rows when possible to result in the fewest rows + * used necessary for the entries that are installed. + */ +static void +cfa_tcam_mgr_rows_combine(int sess_idx, struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_free_parms *parms, + struct cfa_tcam_mgr_table_data *table_data, + int changed_row_index) +{ + struct cfa_tcam_mgr_table_rows_0 *from_row = NULL; + struct cfa_tcam_mgr_table_rows_0 *to_row; + struct cfa_tcam_mgr_table_rows_0 *tcam_rows; + int i, j, row_size; + int to_row_idx, from_row_idx, start_row, end_row, max_slices; + bool entry_moved = false; + + start_row = table_data->start_row; + end_row = table_data->end_row; + max_slices = table_data->max_slices; + tcam_rows = table_data->tcam_rows; + + row_size = cfa_tcam_mgr_row_size_get(sess_idx, parms->dir, parms->type); + + from_row_idx = changed_row_index; + from_row = cfa_tcam_mgr_row_ptr_get(tcam_rows, from_row_idx, row_size); + + if (ROW_INUSE(from_row)) { + /* + * Row is still in partial use. See if remaining entry(s) can + * be moved to free up a row. + */ + for (i = 0; i < (max_slices / from_row->entry_size); i++) { + if (!ROW_ENTRY_INUSE(from_row, i)) + continue; + for (to_row_idx = end_row; + to_row_idx >= start_row; + to_row_idx--) { + to_row = cfa_tcam_mgr_row_ptr_get(tcam_rows, + to_row_idx, + row_size); + if (!ROW_INUSE(to_row)) + continue; + if (to_row->priority > from_row->priority) + break; + if (to_row->priority != from_row->priority) + continue; + if (to_row->entry_size != from_row->entry_size) + continue; + if (to_row_idx == changed_row_index) + continue; + for (j = 0; + j < (max_slices / to_row->entry_size); + j++) { + if (!ROW_ENTRY_INUSE(to_row, j)) { + cfa_tcam_mgr_entry_move + (sess_idx, + context, + parms->dir, + parms->type, + from_row->entries[i], + table_data, + to_row_idx, + -1, to_row, + from_row_idx, + from_row, + true); + entry_moved = true; + break; + } + } + if (entry_moved) + break; + } + if (ROW_INUSE(from_row)) + entry_moved = false; + else + break; + } + } +} + +/* + * This function will ensure that all rows, except those of the highest + * priority, at the end of the table. When this function is finished, all the + * empty rows should be between the highest priority rows at the beginning of + * the table and the rest of the rows with lower priorities. + */ +/* + * Will need to free the row left newly empty as a result of moving. + * + * Return row to free to caller. If new_row_to_free < 0, then no new row to + * free. + */ +static void +cfa_tcam_mgr_rows_compact(int sess_idx, struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_free_parms *parms, + struct cfa_tcam_mgr_table_data *table_data, + int *new_row_to_free, + int changed_row_index) +{ + struct cfa_tcam_mgr_table_rows_0 *from_row = NULL; + struct cfa_tcam_mgr_table_rows_0 *to_row; + struct cfa_tcam_mgr_table_rows_0 *row; + struct cfa_tcam_mgr_table_rows_0 *tcam_rows; + int i, row_size, priority; + int to_row_idx = 0, from_row_idx = 0, start_row = 0, end_row = 0; + + *new_row_to_free = -1; + + start_row = table_data->start_row; + end_row = table_data->end_row; + tcam_rows = table_data->tcam_rows; + + row_size = cfa_tcam_mgr_row_size_get(sess_idx, parms->dir, parms->type); + + /* + * The row is no longer in use, so see if rows need to be moved in order + * to not leave any gaps. + */ + to_row_idx = changed_row_index; + to_row = cfa_tcam_mgr_row_ptr_get(tcam_rows, to_row_idx, row_size); + + priority = to_row->priority; + if (priority == TF_TCAM_PRIORITY_MAX) { + if (changed_row_index == end_row) + /* + * Nothing to move - the last row in the TCAM is being + * deleted. + */ + return; + for (i = changed_row_index + 1; i <= end_row; i++) { + row = cfa_tcam_mgr_row_ptr_get(tcam_rows, i, row_size); + if (!ROW_INUSE(row)) + break; + + if (row->priority < priority) + break; + + from_row = row; + from_row_idx = i; + } + } else { + if (changed_row_index == start_row) + /* + * Nothing to move - the first row in the TCAM is being + * deleted. + */ + return; + for (i = changed_row_index - 1; i >= start_row; i--) { + row = cfa_tcam_mgr_row_ptr_get(tcam_rows, i, row_size); + if (!ROW_INUSE(row)) + break; + + if (row->priority > priority) { + /* Don't move the highest priority rows. */ + if (row->priority == TF_TCAM_PRIORITY_MAX) + break; + /* + * If from_row is NULL, that means that there + * were no rows of the deleted priority. + * Nothing to move yet. + * + * If from_row is not NULL, then it is the last + * row with the same priority and must be moved + * to fill the newly empty (by free or by move) + * row. + */ + if (from_row != NULL) { + cfa_tcam_mgr_row_move(sess_idx, context, + parms->dir, + parms->type, + table_data, + to_row_idx, to_row, + from_row_idx, + from_row); + *new_row_to_free = from_row_idx; + to_row = from_row; + to_row_idx = from_row_idx; + } + + priority = row->priority; + } + from_row = row; + from_row_idx = i; + } + } + + if (from_row != NULL) { + cfa_tcam_mgr_row_move(sess_idx, context, parms->dir, parms->type, + table_data, + to_row_idx, to_row, + from_row_idx, from_row); + *new_row_to_free = from_row_idx; + } +} + +/* + * This function is to set table limits for the logical TCAM tables. + */ +static int +cfa_tcam_mgr_table_limits_set(int sess_idx, struct cfa_tcam_mgr_init_parms *parms) +{ + struct cfa_tcam_mgr_table_data *table_data; + unsigned int dir, type; + int start, stride; + + if (parms == NULL) + return 0; + + for (dir = 0; dir < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx]); dir++) + for (type = 0; + type < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx][dir]); + type++) { + table_data = &cfa_tcam_mgr_tables[sess_idx][dir][type]; + /* + * If num_rows is zero, then TCAM Manager did not + * allocate any row storage for that table so cannot + * manage it. + */ + if (table_data->num_rows == 0) + continue; + start = parms->resc[dir][type].start; + stride = parms->resc[dir][type].stride; + if (start % table_data->max_slices > 0) { + CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, dir, type, + "Start of resources (%d) for table (%d) " + "does not begin on row boundary.\n", + start, sess_idx); + CFA_TCAM_MGR_LOG_DIR(ERR, dir, + "Start is %d, number of slices " + "is %d.\n", + start, + table_data->max_slices); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + if (stride % table_data->max_slices > 0) { + CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, dir, type, + "Stride of resources (%d) for table (%d)" + " does not end on row boundary.\n", + stride, sess_idx); + CFA_TCAM_MGR_LOG_DIR(ERR, dir, + "Stride is %d, number of " + "slices is %d.\n", + stride, + table_data->max_slices); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + if (stride == 0) { + table_data->start_row = 0; + table_data->end_row = 0; + table_data->max_entries = 0; + } else { + table_data->start_row = start / + table_data->max_slices; + table_data->end_row = table_data->start_row + + (stride / table_data->max_slices) - 1; + table_data->max_entries = + table_data->max_slices * + (table_data->end_row - + table_data->start_row + 1); + } + } + + return 0; +} + +int +cfa_tcam_mgr_init(int sess_idx, enum cfa_tcam_mgr_device_type type, + struct cfa_tcam_mgr_init_parms *parms) +{ + struct cfa_tcam_mgr_table_data *table_data; + unsigned int dir, tbl_type; + int rc; + + switch (type) { + case CFA_TCAM_MGR_DEVICE_TYPE_P4: + case CFA_TCAM_MGR_DEVICE_TYPE_SR: + rc = cfa_tcam_mgr_init_p4(sess_idx, &entry_data[sess_idx]); + break; + case CFA_TCAM_MGR_DEVICE_TYPE_P5: + rc = cfa_tcam_mgr_init_p58(sess_idx, &entry_data[sess_idx]); + break; + default: + CFA_TCAM_MGR_LOG(ERR, "No such device %d for sess_idx %d\n", + type, sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(NODEV); + } + if (rc < 0) + return rc; + + rc = cfa_tcam_mgr_table_limits_set(sess_idx, parms); + if (rc < 0) + return rc; + + /* Now calculate the max entries per table and global max entries based + * on the updated table limits. + */ + for (dir = 0; dir < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx]); dir++) + for (tbl_type = 0; + tbl_type < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx][dir]); + tbl_type++) { + table_data = &cfa_tcam_mgr_tables[sess_idx][dir][tbl_type]; + /* + * If num_rows is zero, then TCAM Manager did not + * allocate any row storage for that table so cannot + * manage it. + */ + if (table_data->num_rows == 0) { + table_data->start_row = 0; + table_data->end_row = 0; + table_data->max_entries = 0; + } else if (table_data->end_row >= + table_data->num_rows) { + CFA_TCAM_MGR_LOG_DIR_TYPE(EMERG, dir, tbl_type, + "End row is out of " + "range (%d >= %d) for sess_idx %d\n", + table_data->end_row, + table_data->num_rows, + sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(FAULT); + } else if (table_data->max_entries == 0 && + table_data->start_row == 0 && + table_data->end_row == 0) { + /* Nothing to do */ + } else { + table_data->max_entries = + table_data->max_slices * + (table_data->end_row - + table_data->start_row + 1); + } + cfa_tcam_mgr_max_entries[sess_idx] += table_data->max_entries; + } + + rc = cfa_tcam_mgr_hwops_init(type); + if (rc < 0) + return rc; + + rc = cfa_tcam_mgr_session_init(sess_idx, type); + if (rc < 0) + return rc; + + global_data_initialized[sess_idx] = 1; + + if (parms != NULL) + parms->max_entries = cfa_tcam_mgr_max_entries[sess_idx]; + + CFA_TCAM_MGR_LOG(INFO, "Global TCAM table initialized for sess_idx %d.\n", + sess_idx); + + return 0; +} + +int +cfa_tcam_mgr_qcaps(struct cfa_tcam_mgr_context *context __rte_unused, + struct cfa_tcam_mgr_qcaps_parms *parms) +{ + unsigned int type; + int rc, sess_idx; + uint32_t session_id; + + CFA_TCAM_MGR_CHECK_PARMS2(context, parms); + + rc = cfa_tcam_mgr_get_session_from_context(context, &session_id); + if (rc < 0) + return rc; + + sess_idx = cfa_tcam_mgr_session_find(session_id); + if (sess_idx < 0) { + CFA_TCAM_MGR_LOG_0(ERR, "Session not found.\n"); + return sess_idx; + } + + if (global_data_initialized[sess_idx] == 0) { + CFA_TCAM_MGR_LOG(ERR, "PANIC: No TCAM data created for sess_idx %d\n", + sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(PERM); + } + + /* + * This code will indicate if TCAM Manager is managing a logical TCAM + * table or not. If not, then the physical TCAM will have to be + * accessed using the traditional methods. + */ + parms->rx_tcam_supported = 0; + parms->tx_tcam_supported = 0; + for (type = 0; type < CFA_TCAM_MGR_TBL_TYPE_MAX; type++) { + if (cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX][type].max_entries > 0 && + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX][type].hcapi_type > 0) + parms->rx_tcam_supported |= 1 << cfa_tcam_mgr_get_phys_table_type(type); + if (cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX][type].max_entries > 0 && + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX][type].hcapi_type > 0) + parms->tx_tcam_supported |= 1 << cfa_tcam_mgr_get_phys_table_type(type); + } + + return 0; +} + +/* + * Manipulate the tables to split the WC TCAM into HIGH and LOW ranges + * and also update the sizes in the tcam count array + */ +static int +cfa_tcam_mgr_shared_wc_bind(uint32_t sess_idx, bool dual_ha_app, + uint16_t tcam_cnt[][CFA_TCAM_MGR_TBL_TYPE_MAX]) +{ + uint16_t start_row, end_row, max_entries, slices; + uint16_t num_pools = dual_ha_app ? 4 : 2; + enum tf_dir dir; + int rc; + + for (dir = 0; dir < TF_DIR_MAX; dir++) { + rc = cfa_tcam_mgr_tables_get(sess_idx, dir, + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS, + &start_row, &end_row, &max_entries, &slices); + if (rc) + return rc; + if (max_entries) { + rc = cfa_tcam_mgr_tables_set(sess_idx, dir, + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS, + start_row, + start_row + + ((max_entries / slices) / num_pools) - 1, + max_entries / num_pools); + if (rc) + return rc; + rc = cfa_tcam_mgr_tables_set(sess_idx, dir, + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS, + start_row + + ((max_entries / slices) / num_pools), + start_row + + (max_entries / slices) - 1, + max_entries / num_pools); + if (rc) + return rc; + rc = cfa_tcam_mgr_tables_set(sess_idx, dir, + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS, + 0, 0, 0); + if (rc) + return rc; + tcam_cnt[dir][CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS] = + max_entries / num_pools; + tcam_cnt[dir][CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS] = + max_entries / num_pools; + tcam_cnt[dir][CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS] = 0; + } + } + + return 0; +} + +int +cfa_tcam_mgr_bind(struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_cfg_parms *parms) +{ + struct cfa_tcam_mgr_table_data *table_data; + struct tf_dev_info *dev; + unsigned int dir; + int rc, sess_idx; + uint32_t session_id; + struct tf_session *tfs; + unsigned int type; + int prev_max_entries; + int start, stride; + enum cfa_tcam_mgr_device_type device_type; + + CFA_TCAM_MGR_CHECK_PARMS2(context, parms); + + /* Retrieve the session information */ + rc = tf_session_get_session_internal(context->tfp, &tfs); + if (rc) + return rc; + + /* Retrieve the device information */ + rc = tf_session_get_device(tfs, &dev); + if (rc) + return rc; + + switch (dev->type) { + case TF_DEVICE_TYPE_P4: + device_type = CFA_TCAM_MGR_DEVICE_TYPE_P4; + break; + case TF_DEVICE_TYPE_SR: + device_type = CFA_TCAM_MGR_DEVICE_TYPE_SR; + break; + case TF_DEVICE_TYPE_P5: + device_type = CFA_TCAM_MGR_DEVICE_TYPE_P5; + break; + default: + CFA_TCAM_MGR_LOG(ERR, "No such device %d\n", dev->type); + return -CFA_TCAM_MGR_ERR_CODE(NODEV); + } + + rc = cfa_tcam_mgr_get_session_from_context(context, &session_id); + if (rc < 0) + return rc; + + sess_idx = cfa_tcam_mgr_session_add(session_id); + if (sess_idx < 0) + return sess_idx; + + if (global_data_initialized[sess_idx] == 0) { + rc = cfa_tcam_mgr_init(sess_idx, device_type, NULL); + if (rc < 0) + return rc; + } + + if (parms->num_elements != ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx][dir])) { + CFA_TCAM_MGR_LOG(ERR, + "Session element count (%d) differs " + "from table count (%zu) for sess_idx %d.\n", + parms->num_elements, + ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx][dir]), + sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + /* + * Only managing one session. resv_res contains the resources allocated + * to this session by the resource manager. Update the limits on TCAMs. + */ + for (dir = 0; dir < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx]); dir++) { + for (type = 0; + type < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx][dir]); + type++) { + table_data = &cfa_tcam_mgr_tables[sess_idx][dir][type]; + prev_max_entries = table_data->max_entries; + /* + * In AFM logical tables, max_entries is initialized to + * zero. These logical tables are not used when TCAM + * Manager is in the core so skip. + */ + if (prev_max_entries == 0) + continue; + start = parms->resv_res[dir][type].start; + stride = parms->resv_res[dir][type].stride; + if (start % table_data->max_slices > 0) { + CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, dir, type, + "Start of resources (%d) for table(%d) " + "does not begin on row boundary.\n", + start, sess_idx); + CFA_TCAM_MGR_LOG_DIR(ERR, dir, + "Start is %d, number of slices " + "is %d.\n", + start, + table_data->max_slices); + (void)cfa_tcam_mgr_session_free(session_id, context); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + if (stride % table_data->max_slices > 0) { + CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, dir, type, + "Stride of resources (%d) for table(%d) " + "does not end on row boundary.\n", + stride, sess_idx); + CFA_TCAM_MGR_LOG_DIR(ERR, dir, + "Stride is %d, number of " + "slices is %d.\n", + stride, + table_data->max_slices); + (void)cfa_tcam_mgr_session_free(session_id, context); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + if (stride == 0) { + table_data->start_row = 0; + table_data->end_row = 0; + table_data->max_entries = 0; + } else { + table_data->start_row = start / + table_data->max_slices; + table_data->end_row = table_data->start_row + + (stride / table_data->max_slices) - 1; + table_data->max_entries = + table_data->max_slices * + (table_data->end_row - + table_data->start_row + 1); + } + cfa_tcam_mgr_max_entries[sess_idx] += (table_data->max_entries - + prev_max_entries); + } + } + + if (tf_session_is_shared_hotup_session(tfs)) { + rc = cfa_tcam_mgr_shared_wc_bind(sess_idx, false, parms->tcam_cnt); + if (rc) { + (void)cfa_tcam_mgr_session_free(session_id, context); + return rc; + } + } + + rc = cfa_tcam_mgr_session_cfg(session_id, parms->tcam_cnt); + if (rc < 0) { + (void)cfa_tcam_mgr_session_free(session_id, context); + return rc; + } + + return 0; +} + +int +cfa_tcam_mgr_unbind(struct cfa_tcam_mgr_context *context) +{ + int rc, sess_idx; + uint32_t session_id; + + CFA_TCAM_MGR_CHECK_PARMS1(context); + + rc = cfa_tcam_mgr_get_session_from_context(context, &session_id); + if (rc < 0) + return rc; + + sess_idx = cfa_tcam_mgr_session_find(session_id); + if (sess_idx < 0) { + CFA_TCAM_MGR_LOG_0(ERR, "Session not found.\n"); + return sess_idx; + } + + if (global_data_initialized[sess_idx] == 0) { + CFA_TCAM_MGR_LOG(INFO, "PANIC: No TCAM data created for sess_idx %d\n", + sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(PERM); + } + + (void)cfa_tcam_mgr_session_free(session_id, context); + + global_data_initialized[sess_idx] = 0; + return 0; +} + +int +cfa_tcam_mgr_alloc(struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_alloc_parms *parms) +{ + struct cfa_tcam_mgr_entry_data entry; + struct cfa_tcam_mgr_table_rows_0 *row; + struct cfa_tcam_mgr_table_data *table_data; + int dir, tbl_type; + int key_slices, rc, sess_idx; + int new_entry_id; + uint32_t session_id; + + CFA_TCAM_MGR_CHECK_PARMS2(context, parms); + + dir = parms->dir; + tbl_type = parms->type; + + if (dir >= TF_DIR_MAX) { + CFA_TCAM_MGR_LOG(ERR, "Invalid direction: %d.\n", dir); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + if (tbl_type >= CFA_TCAM_MGR_TBL_TYPE_MAX) { + CFA_TCAM_MGR_LOG_DIR(ERR, dir, + "Invalid table type: %d.\n", + tbl_type); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + +#if TF_TCAM_PRIORITY_MAX < UINT16_MAX + if (parms->priority > TF_TCAM_PRIORITY_MAX) { + CFA_TCAM_MGR_LOG_DIR(ERR, dir, + "Priority (%u) out of range (%u -%u).\n", + parms->priority, + TF_TCAM_PRIORITY_MIN, + TF_TCAM_PRIORITY_MAX); + } +#endif + + /* Check for session limits */ + rc = cfa_tcam_mgr_get_session_from_context(context, &session_id); + if (rc < 0) + return rc; + + sess_idx = cfa_tcam_mgr_session_find(session_id); + if (sess_idx < 0) { + CFA_TCAM_MGR_LOG(ERR, "Session 0x%08x not found.\n", + session_id); + return -CFA_TCAM_MGR_ERR_CODE(NODEV); + } + + if (global_data_initialized[sess_idx] == 0) { + CFA_TCAM_MGR_LOG(ERR, "PANIC: No TCAM data created for sess_idx %d\n", + sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(PERM); + } + + table_data = &cfa_tcam_mgr_tables[sess_idx][dir][tbl_type]; + + if (parms->key_size == 0 || + parms->key_size > table_data->row_width) { + CFA_TCAM_MGR_LOG_DIR(ERR, dir, + "Invalid key size:%d (range 1-%d) sess_idx %d.\n", + parms->key_size, + table_data->row_width, + sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + /* Check global limits */ + if (table_data->used_entries >= + table_data->max_entries) { + CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, dir, tbl_type, + "Table full sess_idx %d.\n", + sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(NOSPC); + } + + /* There is room, now increment counts and allocate an entry. */ + new_entry_id = cfa_tcam_mgr_session_entry_alloc(session_id, + parms->dir, + parms->type); + if (new_entry_id < 0) + return new_entry_id; + + memset(&entry, 0, sizeof(entry)); + entry.ref_cnt++; + + key_slices = cfa_tcam_mgr_get_num_slices(parms->key_size, + (table_data->row_width / + table_data->max_slices)); + + row = cfa_tcam_mgr_empty_row_alloc(sess_idx, context, parms, &entry, + new_entry_id, key_slices); + if (row == NULL) { + CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, parms->dir, parms->type, + "Table full (HW) sess_idx %d.\n", + sess_idx); + (void)cfa_tcam_mgr_session_entry_free(session_id, new_entry_id, + parms->dir, parms->type); + return -CFA_TCAM_MGR_ERR_CODE(NOSPC); + } + + memcpy(&entry_data[sess_idx][new_entry_id], + &entry, + sizeof(entry_data[sess_idx][new_entry_id])); + table_data->used_entries += 1; + + cfa_tcam_mgr_entry_insert(sess_idx, new_entry_id, &entry); + + parms->id = new_entry_id; + + return 0; +} + +int +cfa_tcam_mgr_free(struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_free_parms *parms) +{ + struct cfa_tcam_mgr_entry_data *entry; + struct cfa_tcam_mgr_table_rows_0 *row; + struct cfa_tcam_mgr_table_data *table_data; + int row_size, rc, sess_idx, new_row_to_free; + uint32_t session_id; + uint16_t id; + + CFA_TCAM_MGR_CHECK_PARMS2(context, parms); + + rc = cfa_tcam_mgr_get_session_from_context(context, &session_id); + if (rc < 0) + return rc; + + sess_idx = cfa_tcam_mgr_session_find(session_id); + if (sess_idx < 0) { + CFA_TCAM_MGR_LOG(ERR, "Session 0x%08x not found.\n", + session_id); + return sess_idx; + } + + if (global_data_initialized[sess_idx] == 0) { + CFA_TCAM_MGR_LOG(INFO, "PANIC: No TCAM data created for sess_idx %d\n", + sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(PERM); + } + + id = parms->id; + entry = cfa_tcam_mgr_entry_get(sess_idx, id); + if (entry == NULL) { + CFA_TCAM_MGR_LOG(INFO, "Entry %d not found for sess_idx %d.\n", + id, sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + if (entry->ref_cnt == 0) { + CFA_TCAM_MGR_LOG(ERR, "Entry %d not in use for sess_idx %d.\n", + id, sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + /* + * If the TCAM type is CFA_TCAM_MGR_TBL_TYPE_MAX, that implies that the + * caller does not know the table or direction of the entry and TCAM + * Manager must search the tables to find out which table has the entry + * installed. + * + * This would be the case if RM has informed TCAM Mgr that an entry must + * be freed. Clients (sessions, AFM) should always know the type and + * direction of the table where an entry is installed. + */ + if (parms->type == CFA_TCAM_MGR_TBL_TYPE_MAX) { + /* Need to search for the entry in the tables */ + rc = cfa_tcam_mgr_entry_find(sess_idx, id, &parms->dir, &parms->type); + if (rc < 0) { + CFA_TCAM_MGR_LOG(ERR, "Entry %d not in tables for sess_idx %d.\n", + id, sess_idx); + return rc; + } + } + + table_data = &cfa_tcam_mgr_tables[sess_idx][parms->dir][parms->type]; + parms->hcapi_type = table_data->hcapi_type; + + row_size = cfa_tcam_mgr_row_size_get(sess_idx, parms->dir, parms->type); + + row = cfa_tcam_mgr_row_ptr_get(table_data->tcam_rows, entry->row, + row_size); + + entry->ref_cnt--; + + (void)cfa_tcam_mgr_session_entry_free(session_id, id, + parms->dir, parms->type); + + if (entry->ref_cnt == 0) { + cfa_tcam_mgr_entry_free_msg(sess_idx, context, parms, + entry->row, + entry->slice * row->entry_size, + table_data->row_width / + table_data->max_slices * + row->entry_size, + table_data->result_size, + table_data->max_slices); + ROW_ENTRY_CLEAR(row, entry->slice); + + new_row_to_free = entry->row; + cfa_tcam_mgr_rows_combine(sess_idx, context, parms, table_data, + new_row_to_free); + + if (!ROW_INUSE(row)) { + cfa_tcam_mgr_rows_compact(sess_idx, context, + parms, table_data, + &new_row_to_free, + new_row_to_free); + if (new_row_to_free >= 0) + cfa_tcam_mgr_entry_free_msg(sess_idx, context, parms, + new_row_to_free, 0, + table_data->row_width, + table_data->result_size, + table_data->max_slices); + } + + cfa_tcam_mgr_entry_delete(sess_idx, id); + table_data->used_entries -= 1; + } + + return 0; +} + +int +cfa_tcam_mgr_set(struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_set_parms *parms) +{ + struct cfa_tcam_mgr_entry_data *entry; + struct cfa_tcam_mgr_table_rows_0 *row; + struct cfa_tcam_mgr_table_data *table_data; + int rc; + int row_size, sess_idx; + int entry_size_in_bytes; + uint32_t session_id; + + CFA_TCAM_MGR_CHECK_PARMS2(context, parms); + + rc = cfa_tcam_mgr_get_session_from_context(context, &session_id); + if (rc < 0) + return rc; + + sess_idx = cfa_tcam_mgr_session_find(session_id); + if (sess_idx < 0) { + CFA_TCAM_MGR_LOG(ERR, "Session 0x%08x not found.\n", + session_id); + return sess_idx; + } + + if (global_data_initialized[sess_idx] == 0) { + CFA_TCAM_MGR_LOG(ERR, "PANIC: No TCAM data created for sess_idx %d\n", + sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(PERM); + } + + entry = cfa_tcam_mgr_entry_get(sess_idx, parms->id); + if (entry == NULL) { + CFA_TCAM_MGR_LOG(ERR, "Entry %d not found for sess_idx %d.\n", + parms->id, sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + table_data = &cfa_tcam_mgr_tables[sess_idx][parms->dir][parms->type]; + parms->hcapi_type = table_data->hcapi_type; + + row_size = cfa_tcam_mgr_row_size_get(sess_idx, parms->dir, parms->type); + row = cfa_tcam_mgr_row_ptr_get(table_data->tcam_rows, entry->row, + row_size); + + entry_size_in_bytes = table_data->row_width / + table_data->max_slices * + row->entry_size; + if (parms->key_size != entry_size_in_bytes) { + CFA_TCAM_MGR_LOG(ERR, + "Key size(%d) is different from entry " + "size(%d).\n", + parms->key_size, + entry_size_in_bytes); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + rc = cfa_tcam_mgr_entry_set_msg(sess_idx, context, parms, + entry->row, + entry->slice * row->entry_size, + table_data->max_slices); + if (rc < 0) { + CFA_TCAM_MGR_LOG_0(ERR, "Failed to set TCAM data.\n"); + return rc; + } + + return 0; +} + +int +cfa_tcam_mgr_get(struct cfa_tcam_mgr_context *context __rte_unused, + struct cfa_tcam_mgr_get_parms *parms) +{ + struct cfa_tcam_mgr_entry_data *entry; + struct cfa_tcam_mgr_table_rows_0 *row; + struct cfa_tcam_mgr_table_data *table_data; + int rc; + int row_size, sess_idx; + uint32_t session_id; + + CFA_TCAM_MGR_CHECK_PARMS2(context, parms); + + rc = cfa_tcam_mgr_get_session_from_context(context, &session_id); + if (rc < 0) + return rc; + + sess_idx = cfa_tcam_mgr_session_find(session_id); + if (sess_idx < 0) { + CFA_TCAM_MGR_LOG(ERR, "Session 0x%08x not found.\n", + session_id); + return sess_idx; + } + + if (global_data_initialized[sess_idx] == 0) { + CFA_TCAM_MGR_LOG(ERR, "PANIC: No TCAM data created for sess_idx %d\n", + sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(PERM); + } + + entry = cfa_tcam_mgr_entry_get(sess_idx, parms->id); + if (entry == NULL) { + CFA_TCAM_MGR_LOG(ERR, "Entry %d not found.\n", parms->id); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + table_data = &cfa_tcam_mgr_tables[sess_idx][parms->dir][parms->type]; + parms->hcapi_type = table_data->hcapi_type; + + row_size = cfa_tcam_mgr_row_size_get(sess_idx, parms->dir, parms->type); + row = cfa_tcam_mgr_row_ptr_get(table_data->tcam_rows, entry->row, + row_size); + + rc = cfa_tcam_mgr_entry_get_msg(sess_idx, context, parms, + entry->row, + entry->slice * row->entry_size, + table_data->max_slices); + if (rc < 0) { + CFA_TCAM_MGR_LOG_0(ERR, "Failed to read from TCAM.\n"); + return rc; + } + + return 0; +} + +int cfa_tcam_mgr_shared_clear(struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_shared_clear_parms *parms) +{ + int rc; + uint16_t row, slice = 0; + int sess_idx; + uint32_t session_id; + struct cfa_tcam_mgr_free_parms fparms; + struct cfa_tcam_mgr_table_data *table_data; + uint16_t start_row, end_row, max_entries, max_slices; + + CFA_TCAM_MGR_CHECK_PARMS2(context, parms); + + rc = cfa_tcam_mgr_get_session_from_context(context, &session_id); + if (rc < 0) + return rc; + + sess_idx = cfa_tcam_mgr_session_find(session_id); + if (sess_idx < 0) { + CFA_TCAM_MGR_LOG(ERR, "Session 0x%08x not found.\n", + session_id); + return sess_idx; + } + + if (global_data_initialized[sess_idx] == 0) { + CFA_TCAM_MGR_LOG(ERR, "PANIC: No TCAM data created for sess_idx %d\n", + sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(PERM); + } + + table_data = &cfa_tcam_mgr_tables[sess_idx][parms->dir][parms->type]; + fparms.dir = parms->dir; + fparms.type = parms->type; + fparms.hcapi_type = table_data->hcapi_type; + fparms.id = 0; + + rc = cfa_tcam_mgr_tables_get(sess_idx, parms->dir, parms->type, + &start_row, &end_row, &max_entries, &max_slices); + if (rc) + return rc; + + for (row = start_row; row <= end_row; row++) { + cfa_tcam_mgr_entry_free_msg(sess_idx, context, &fparms, + row, + slice, + table_data->row_width, + table_data->result_size, + table_data->max_slices); + } + return rc; +} + +static void +cfa_tcam_mgr_mv_used_entries_cnt(int sess_idx, enum tf_dir dir, + struct cfa_tcam_mgr_table_data *dst_table_data, + struct cfa_tcam_mgr_table_data *src_table_data) +{ + dst_table_data->used_entries++; + src_table_data->used_entries--; + + cfa_tcam_mgr_mv_session_used_entries_cnt(sess_idx, dir, + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS, + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS); +} + +/* + * Move HI WC TCAM entries to LOW TCAM region for HA + * This happens when secondary is becoming primary + */ +static int +cfa_tcam_mgr_shared_entry_move(int sess_idx, struct cfa_tcam_mgr_context *context, + enum tf_dir dir, enum cfa_tcam_mgr_tbl_type type, + int entry_id, + struct cfa_tcam_mgr_table_data *dst_table_data, + struct cfa_tcam_mgr_table_data *table_data, + int dst_row_index, int dst_row_slice, + struct cfa_tcam_mgr_table_rows_0 *dst_row, + int src_row_index, + struct cfa_tcam_mgr_table_rows_0 *src_row) +{ + struct cfa_tcam_mgr_get_parms gparms = { 0 }; + struct cfa_tcam_mgr_set_parms sparms = { 0 }; + struct cfa_tcam_mgr_free_parms fparms = { 0 }; + struct cfa_tcam_mgr_entry_data *entry; + uint8_t key[CFA_TCAM_MGR_MAX_KEY_SIZE]; + uint8_t mask[CFA_TCAM_MGR_MAX_KEY_SIZE]; + uint8_t result[CFA_TCAM_MGR_MAX_KEY_SIZE]; + + int rc; + + entry = cfa_tcam_mgr_entry_get(sess_idx, entry_id); + if (entry == NULL) + return -1; + + gparms.dir = dir; + gparms.type = type; + gparms.hcapi_type = table_data->hcapi_type; + gparms.key = key; + gparms.mask = mask; + gparms.result = result; + gparms.id = src_row->entries[entry->slice]; + gparms.key_size = sizeof(key); + gparms.result_size = sizeof(result); + + rc = cfa_tcam_mgr_entry_get_msg(sess_idx, context, &gparms, + src_row_index, + entry->slice * src_row->entry_size, + table_data->max_slices); + if (rc != 0) + return rc; + + sparms.dir = dir; + sparms.type = CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS; + sparms.hcapi_type = table_data->hcapi_type; + sparms.key = key; + sparms.mask = mask; + sparms.result = result; + sparms.id = gparms.id; + sparms.key_size = gparms.key_size; + sparms.result_size = gparms.result_size; + + rc = cfa_tcam_mgr_entry_set_msg(sess_idx, context, &sparms, + dst_row_index, + dst_row_slice * dst_row->entry_size, + table_data->max_slices); + if (rc != 0) + return rc; + + fparms.dir = dir; + fparms.type = type; + fparms.hcapi_type = table_data->hcapi_type; + rc = cfa_tcam_mgr_entry_free_msg(sess_idx, context, &fparms, + src_row_index, + entry->slice * + dst_row->entry_size, + table_data->row_width / + table_data->max_slices * + src_row->entry_size, + table_data->result_size, + table_data->max_slices); + if (rc != 0) { + CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, + dir, type, + "Failed to free entry ID %d at" + " row %d, slice %d for sess_idx %d. rc: %d.\n", + gparms.id, + src_row_index, + entry->slice, + sess_idx, + -rc); + } + +#ifdef CFA_TCAM_MGR_TRACING + CFA_TCAM_MGR_TRACE(INFO, "Moved entry %d from row %d, slice %d to " + "row %d, slice %d.\n", + entry_id, src_row_index, entry->slice, + dst_row_index, dst_row_slice); +#endif + + ROW_ENTRY_SET(dst_row, dst_row_slice); + dst_row->entries[dst_row_slice] = entry_id; + dst_row->entry_size = src_row->entry_size; + dst_row->priority = src_row->priority; + ROW_ENTRY_CLEAR(src_row, entry->slice); + entry->row = dst_row_index; + entry->slice = dst_row_slice; + + cfa_tcam_mgr_mv_used_entries_cnt(sess_idx, dir, dst_table_data, table_data); + +#ifdef CFA_TCAM_MGR_TRACING + cfa_tcam_mgr_rows_dump(sess_idx, dir, type); + cfa_tcam_mgr_rows_dump(sess_idx, dir, CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS); +#endif + + return 0; +} + +int cfa_tcam_mgr_shared_move(struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_shared_move_parms *parms) +{ + int rc; + int sess_idx; + uint32_t session_id; + uint16_t src_row, dst_row, row_size, slice; + struct cfa_tcam_mgr_table_rows_0 *src_table_row; + struct cfa_tcam_mgr_table_rows_0 *dst_table_row; + struct cfa_tcam_mgr_table_data *src_table_data; + struct cfa_tcam_mgr_table_data *dst_table_data; + + CFA_TCAM_MGR_CHECK_PARMS2(context, parms); + + rc = cfa_tcam_mgr_get_session_from_context(context, &session_id); + if (rc < 0) + return rc; + + sess_idx = cfa_tcam_mgr_session_find(session_id); + if (sess_idx < 0) { + CFA_TCAM_MGR_LOG(ERR, "Session 0x%08x not found.\n", + session_id); + return sess_idx; + } + + if (global_data_initialized[sess_idx] == 0) { + CFA_TCAM_MGR_LOG(ERR, "PANIC: No TCAM data created for sess_idx %d\n", + sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(PERM); + } + + src_table_data = + &cfa_tcam_mgr_tables[sess_idx][parms->dir][CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS]; + dst_table_data = + &cfa_tcam_mgr_tables[sess_idx][parms->dir][CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS]; + + row_size = + cfa_tcam_mgr_row_size_get(sess_idx, + parms->dir, + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS); + + for (src_row = src_table_data->start_row, + dst_row = dst_table_data->start_row; + src_row <= src_table_data->end_row; + src_row++, dst_row++) { + src_table_row = cfa_tcam_mgr_row_ptr_get(src_table_data->tcam_rows, + src_row, row_size); + dst_table_row = cfa_tcam_mgr_row_ptr_get(dst_table_data->tcam_rows, + dst_row, row_size); + if (ROW_INUSE(src_table_row)) { + for (slice = 0; + slice < src_table_data->max_slices / src_table_row->entry_size; + slice++) { + if (ROW_ENTRY_INUSE(src_table_row, slice)) { +#ifdef CFA_TCAM_MGR_TRACING + CFA_TCAM_MGR_TRACE(INFO, "Move entry id %d " + "from src_row %d, slice %d " + "to dst_row %d, slice %d.\n", + src_table_row->entries[slice], + src_row, slice, + dst_row, slice); +#endif + rc = cfa_tcam_mgr_shared_entry_move(sess_idx, + context, + parms->dir, + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS, + src_table_row->entries[slice], + dst_table_data, + src_table_data, + dst_row, slice, + dst_table_row, + src_row, + src_table_row); + } + } + } + } + + return rc; +} + +static void +cfa_tcam_mgr_tbl_get(int sess_idx, enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type, + uint16_t *start_row, + uint16_t *end_row, + uint16_t *max_entries, + uint16_t *slices) +{ + struct cfa_tcam_mgr_table_data *table_data = + &cfa_tcam_mgr_tables[sess_idx][dir][type]; + + /* Get start, end and max for tcam type*/ + *start_row = table_data->start_row; + *end_row = table_data->end_row; + *max_entries = table_data->max_entries; + *slices = table_data->max_slices; +} + +int +cfa_tcam_mgr_tables_get(int sess_idx, enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type, + uint16_t *start_row, + uint16_t *end_row, + uint16_t *max_entries, + uint16_t *slices) +{ + CFA_TCAM_MGR_CHECK_PARMS3(start_row, end_row, max_entries); + + if (global_data_initialized[sess_idx] == 0) { + CFA_TCAM_MGR_LOG(ERR, "PANIC: TCAM not initialized for sess_idx %d.\n", + sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + if (dir >= TF_DIR_MAX) { + CFA_TCAM_MGR_LOG(ERR, "Must specify valid dir (0-%d) forsess_idx %d.\n", + TF_DIR_MAX - 1, sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + if (type >= CFA_TCAM_MGR_TBL_TYPE_MAX) { + CFA_TCAM_MGR_LOG(ERR, "Must specify valid tbl type (0-%d) forsess_idx %d.\n", + CFA_TCAM_MGR_TBL_TYPE_MAX - 1, sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + cfa_tcam_mgr_tbl_get(sess_idx, dir, + type, + start_row, + end_row, + max_entries, + slices); + return 0; +} + +static void +cfa_tcam_mgr_tbl_set(int sess_idx, enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type, + uint16_t start_row, + uint16_t end_row, + uint16_t max_entries) +{ + struct cfa_tcam_mgr_table_data *table_data = + &cfa_tcam_mgr_tables[sess_idx][dir][type]; + + /* Update start, end and max for tcam type*/ + table_data->start_row = start_row; + table_data->end_row = end_row; + table_data->max_entries = max_entries; +} + +int +cfa_tcam_mgr_tables_set(int sess_idx, enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type, + uint16_t start_row, + uint16_t end_row, + uint16_t max_entries) +{ + if (global_data_initialized[sess_idx] == 0) { + CFA_TCAM_MGR_LOG(ERR, "PANIC: TCAM not initialized for sess_idx %d.\n", + sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + if (dir >= TF_DIR_MAX) { + CFA_TCAM_MGR_LOG(ERR, "Must specify valid dir (0-%d) forsess_idx %d.\n", + TF_DIR_MAX - 1, sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + if (type >= CFA_TCAM_MGR_TBL_TYPE_MAX) { + CFA_TCAM_MGR_LOG(ERR, "Must specify valid tbl type (0-%d) forsess_idx %d.\n", + CFA_TCAM_MGR_TBL_TYPE_MAX - 1, sess_idx); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + cfa_tcam_mgr_tbl_set(sess_idx, dir, + type, + start_row, + end_row, + max_entries); + return 0; +} + +void +cfa_tcam_mgr_rows_dump(int sess_idx, enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type) +{ + struct cfa_tcam_mgr_table_data *table_data; + struct cfa_tcam_mgr_table_rows_0 *table_row; + int i, row, row_size; + bool row_found = false; + bool empty_row = false; + + if (global_data_initialized[sess_idx] == 0) { + printf("PANIC: TCAM not initialized for sess_idx %d.\n", sess_idx); + return; + } + + if (dir >= TF_DIR_MAX) { + printf("Must specify a valid direction (0-%d).\n", + TF_DIR_MAX - 1); + return; + } + if (type >= CFA_TCAM_MGR_TBL_TYPE_MAX) { + printf("Must specify a valid type (0-%d).\n", + CFA_TCAM_MGR_TBL_TYPE_MAX - 1); + return; + } + + table_data = &cfa_tcam_mgr_tables[sess_idx][dir][type]; + row_size = cfa_tcam_mgr_row_size_get(sess_idx, dir, type); + + printf("\nTCAM Rows:\n"); + printf("Rows for direction %s, Logical table type %s\n", + tf_dir_2_str(dir), cfa_tcam_mgr_tbl_2_str(type)); + printf("Managed rows %d-%d for sess_idx %d:\n", + table_data->start_row, table_data->end_row, sess_idx); + + printf("Index Pri Size Entry IDs\n"); + printf(" Sl 0"); + for (i = 1; i < table_data->max_slices; i++) + printf(" Sl %d", i); + printf("\n"); + for (row = table_data->start_row; row <= table_data->end_row; row++) { + table_row = cfa_tcam_mgr_row_ptr_get(table_data->tcam_rows, row, + row_size); + if (ROW_INUSE(table_row)) { + empty_row = false; + printf("%5u %5u %4u", + row, + TF_TCAM_PRIORITY_MAX - table_row->priority - 1, + table_row->entry_size); + for (i = 0; + i < table_data->max_slices / table_row->entry_size; + i++) { + if (ROW_ENTRY_INUSE(table_row, i)) + printf(" %5u", table_row->entries[i]); + else + printf(" x"); + } + printf("\n"); + row_found = true; + } else if (!empty_row) { + empty_row = true; + printf("\n"); + } + } + + if (!row_found) + printf("No rows in use.\n"); +} + +static void +cfa_tcam_mgr_table_dump(int sess_idx, enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type) +{ + struct cfa_tcam_mgr_table_data *table_data = + &cfa_tcam_mgr_tables[sess_idx][dir][type]; + + printf("%3s %-22s %5u %5u %5u %5u %6u %7u %2u\n", + tf_dir_2_str(dir), + cfa_tcam_mgr_tbl_2_str(type), + table_data->row_width, + table_data->num_rows, + table_data->start_row, + table_data->end_row, + table_data->max_entries, + table_data->used_entries, + table_data->max_slices); +} + +#define TABLE_DUMP_HEADER \ + "Dir Table Width Rows Start End " \ + "MaxEnt UsedEnt Slices\n" + +void +cfa_tcam_mgr_tables_dump(int sess_idx, enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type) +{ + if (global_data_initialized[sess_idx] == 0) { + printf("PANIC: TCAM not initialized for sess_idx %d.\n", sess_idx); + return; + } + + printf("\nTCAM Table(s) for sess_idx %d:\n", sess_idx); + printf(TABLE_DUMP_HEADER); + if (dir >= TF_DIR_MAX) { + /* Iterate over all directions */ + for (dir = 0; dir < TF_DIR_MAX; dir++) { + if (type >= CFA_TCAM_MGR_TBL_TYPE_MAX) { + /* Iterate over all types */ + for (type = 0; + type < CFA_TCAM_MGR_TBL_TYPE_MAX; + type++) { + cfa_tcam_mgr_table_dump(sess_idx, dir, type); + } + } else { + /* Display a specific type */ + cfa_tcam_mgr_table_dump(sess_idx, dir, type); + } + } + } else if (type >= CFA_TCAM_MGR_TBL_TYPE_MAX) { + /* Iterate over all types for a direction */ + for (type = 0; type < CFA_TCAM_MGR_TBL_TYPE_MAX; type++) + cfa_tcam_mgr_table_dump(sess_idx, dir, type); + } else { + /* Display a specific direction and type */ + cfa_tcam_mgr_table_dump(sess_idx, dir, type); + } +} + +#define ENTRY_DUMP_HEADER "Entry RefCnt Row Slice\n" + +void +cfa_tcam_mgr_entries_dump(int sess_idx) +{ + struct cfa_tcam_mgr_entry_data *entry; + bool entry_found = false; + uint16_t id; + + if (global_data_initialized[sess_idx] == 0) { + CFA_TCAM_MGR_LOG(INFO, "PANIC: No TCAM data created for sess_idx %d\n", + sess_idx); + return; + } + + printf("\nGlobal Maximum Entries: %d\n\n", + cfa_tcam_mgr_max_entries[sess_idx]); + printf("TCAM Entry Table:\n"); + for (id = 0; id < cfa_tcam_mgr_max_entries[sess_idx]; id++) { + if (entry_data[sess_idx][id].ref_cnt > 0) { + entry = &entry_data[sess_idx][id]; + if (!entry_found) + printf(ENTRY_DUMP_HEADER); + printf("%5u %5u %5u %5u", + id, entry->ref_cnt, + entry->row, entry->slice); + printf("\n"); + entry_found = true; + } + } + + if (!entry_found) + printf("No entries found.\n"); +} diff --git a/drivers/net/bnxt/tf_core/cfa_tcam_mgr.h b/drivers/net/bnxt/tf_core/cfa_tcam_mgr.h new file mode 100644 index 0000000000..40bfe8e225 --- /dev/null +++ b/drivers/net/bnxt/tf_core/cfa_tcam_mgr.h @@ -0,0 +1,523 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021-2023 Broadcom + * All rights reserved. + */ + +#ifndef _CFA_TCAM_MGR_H_ +#define _CFA_TCAM_MGR_H_ + +#include +#include "rte_common.h" +#include "hsi_struct_def_dpdk.h" +#include "tf_core.h" + +#ifndef __rte_unused +#define __rte_unused __attribute__((unused)) +#endif + +/** + * The TCAM module provides processing of Internal TCAM types. + */ + +#ifndef TF_TCAM_MAX_SESSIONS +#define TF_TCAM_MAX_SESSIONS 16 +#endif + +#define ENTRY_ID_INVALID UINT16_MAX + +#define TF_TCAM_PRIORITY_MIN 0 +#define TF_TCAM_PRIORITY_MAX UINT16_MAX + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(_array) (sizeof(_array) / sizeof(_array[0])) +#endif + +/* Use TFP_DRV_LOG definition in tfp.h */ +#define CFA_TCAM_MGR_LOG(level, fmt, args...) \ + TFP_DRV_LOG(level, fmt, ## args) +#define CFA_TCAM_MGR_LOG_DIR(level, dir, fmt, args...) \ + TFP_DRV_LOG(level, "%s: " fmt, tf_dir_2_str(dir), ## args) +#define CFA_TCAM_MGR_LOG_DIR_TYPE(level, dir, type, fmt, args...) \ + TFP_DRV_LOG(level, "%s: %s " fmt, tf_dir_2_str(dir), \ + cfa_tcam_mgr_tbl_2_str(type), ## args) + +#define CFA_TCAM_MGR_LOG_0(level, fmt) \ + TFP_DRV_LOG(level, fmt) +#define CFA_TCAM_MGR_LOG_DIR_0(level, dir, fmt) \ + TFP_DRV_LOG(level, "%s: " fmt, tf_dir_2_str(dir)) +#define CFA_TCAM_MGR_LOG_DIR_TYPE_0(level, dir, type, fmt) \ + TFP_DRV_LOG(level, "%s: %s " fmt, tf_dir_2_str(dir), \ + cfa_tcam_mgr_tbl_2_str(type)) + +#define CFA_TCAM_MGR_ERR_CODE(type) E ## type + +/** + * Checks 1 parameter against NULL. + */ +#define CFA_TCAM_MGR_CHECK_PARMS1(parms) do { \ + if ((parms) == NULL) { \ + CFA_TCAM_MGR_LOG_0(ERR, "Invalid Argument(s)\n"); \ + return -CFA_TCAM_MGR_ERR_CODE(INVAL); \ + } \ + } while (0) + +/** + * Checks 2 parameters against NULL. + */ +#define CFA_TCAM_MGR_CHECK_PARMS2(parms1, parms2) do { \ + if ((parms1) == NULL || (parms2) == NULL) { \ + CFA_TCAM_MGR_LOG_0(ERR, "Invalid Argument(s)\n"); \ + return -CFA_TCAM_MGR_ERR_CODE(INVAL); \ + } \ + } while (0) + +/** + * Checks 3 parameters against NULL. + */ +#define CFA_TCAM_MGR_CHECK_PARMS3(parms1, parms2, parms3) do { \ + if ((parms1) == NULL || \ + (parms2) == NULL || \ + (parms3) == NULL) { \ + CFA_TCAM_MGR_LOG_0(ERR, "Invalid Argument(s)\n"); \ + return -CFA_TCAM_MGR_ERR_CODE(INVAL); \ + } \ + } while (0) + +enum cfa_tcam_mgr_tbl_type { + /* Logical TCAM tables */ + CFA_TCAM_MGR_TBL_TYPE_START, + CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_AFM = + CFA_TCAM_MGR_TBL_TYPE_START, + CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_APPS, + CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_AFM, + CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_APPS, + CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_AFM, + CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_APPS, + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_AFM, + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS, + CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_AFM, + CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_APPS, + CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_AFM, + CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_APPS, + CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_AFM, + CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_APPS, + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_AFM, + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS, + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_AFM, + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS, + CFA_TCAM_MGR_TBL_TYPE_MAX +}; + +enum cfa_tcam_mgr_device_type { + CFA_TCAM_MGR_DEVICE_TYPE_P4 = 0, + CFA_TCAM_MGR_DEVICE_TYPE_SR, + CFA_TCAM_MGR_DEVICE_TYPE_P5, + CFA_TCAM_MGR_DEVICE_TYPE_MAX +}; + +struct cfa_tcam_mgr_context { + struct tf *tfp; +}; + +/** + * TCAM Manager initialization parameters + */ +struct cfa_tcam_mgr_init_parms { + /** + * [in] TCAM resources reserved + * type element is not used. + */ + struct tf_rm_resc_entry resc[TF_DIR_MAX][CFA_TCAM_MGR_TBL_TYPE_MAX]; + /** + * [out] maximum number of entries available. + */ + uint32_t max_entries; +}; + +/** + * TCAM Manager initialization parameters + */ +struct cfa_tcam_mgr_qcaps_parms { + /** + * [out] Bitmasks. Set if TCAM Manager is managing a logical TCAM. + * Each bitmask is indexed by logical TCAM table ID. + */ + uint32_t rx_tcam_supported; + uint32_t tx_tcam_supported; +}; + +/** + * TCAM Manager configuration parameters + */ +struct cfa_tcam_mgr_cfg_parms { + /** + * [in] Number of tcam types in each of the configuration arrays + */ + uint16_t num_elements; + /** + * [in] Session resource allocations + */ + uint16_t tcam_cnt[TF_DIR_MAX][CFA_TCAM_MGR_TBL_TYPE_MAX]; + + /** + * [in] TCAM Locations reserved + */ + struct tf_rm_resc_entry (*resv_res)[CFA_TCAM_MGR_TBL_TYPE_MAX]; +}; + +/** + * TCAM Manager allocation parameters + */ +struct cfa_tcam_mgr_alloc_parms { + /** + * [in] Receive or transmit direction + */ + enum tf_dir dir; + /** + * [in] Type of the allocation + */ + enum cfa_tcam_mgr_tbl_type type; + /** + * [in] Type of HCAPI + */ + uint16_t hcapi_type; + /** + * [in] key size (bytes) + */ + uint16_t key_size; + /** + * [in] Priority of entry requested (definition TBD) + */ + uint16_t priority; + /** + * [out] Id of allocated entry or found entry (if search_enable) + */ + uint16_t id; +}; + +/** + * TCAM Manager free parameters + */ +struct cfa_tcam_mgr_free_parms { + /** + * [in] Receive or transmit direction + */ + enum tf_dir dir; + /** + * [in] Type of the allocation + * If the type is not known, set the type to CFA_TCAM_MGR_TBL_TYPE_MAX. + */ + enum cfa_tcam_mgr_tbl_type type; + /** + * [in] Type of HCAPI + */ + uint16_t hcapi_type; + /** + * [in] Entry ID to free + */ + uint16_t id; +}; + +/** + * TCAM Manager set parameters + */ +struct cfa_tcam_mgr_set_parms { + /** + * [in] Receive or transmit direction + */ + enum tf_dir dir; + /** + * [in] Type of object to set + */ + enum cfa_tcam_mgr_tbl_type type; + /** + * [in] Type of HCAPI + */ + uint16_t hcapi_type; + /** + * [in] Entry ID to write to + */ + uint16_t id; + /** + * [in] array containing key + */ + uint8_t *key; + /** + * [in] array containing mask fields + */ + uint8_t *mask; + /** + * [in] key size (bytes) + */ + uint16_t key_size; + /** + * [in] array containing result + */ + uint8_t *result; + /** + * [in] result size (bytes) + */ + uint16_t result_size; +}; + +/** + * TCAM Manager get parameters + */ +struct cfa_tcam_mgr_get_parms { + /** + * [in] Receive or transmit direction + */ + enum tf_dir dir; + /** + * [in] Type of object to get + */ + enum cfa_tcam_mgr_tbl_type type; + /** + * [in] Type of HCAPI + */ + uint16_t hcapi_type; + /** + * [in] Entry ID to read + */ + uint16_t id; + /** + * [out] array containing key + */ + uint8_t *key; + /** + * [out] array containing mask fields + */ + uint8_t *mask; + /** + * [out] key size (bytes) + */ + uint16_t key_size; + /** + * [out] array containing result + */ + uint8_t *result; + /** + * [out] result size (bytes) + */ + uint16_t result_size; +}; + +/** + * cfa_tcam_mgr_shared_clear_parms parameter definition + */ +struct cfa_tcam_mgr_shared_clear_parms { + /** + * [in] receive or transmit direction + */ + enum tf_dir dir; + /** + * [in] TCAM table type + */ + enum cfa_tcam_mgr_tbl_type type; +}; + +/** + * cfa_tcam_mgr_shared_move_parms parameter definition + */ +struct cfa_tcam_mgr_shared_move_parms { + /** + * [in] receive or transmit direction + */ + enum tf_dir dir; + /** + * [in] TCAM table type + */ + enum cfa_tcam_mgr_tbl_type type; +}; + +/** + * @page tcam TCAM Manager + * + * @ref cfa_tcam_mgr_init + * + * @ref cfa_tcam_mgr_get_phys_table_type + * + * @ref cfa_tcam_mgr_bind + * + * @ref cfa_tcam_mgr_unbind + * + * @ref cfa_tcam_mgr_alloc + * + * @ref cfa_tcam_mgr_free + * + * @ref cfa_tcam_mgr_set + * + * @ref cfa_tcam_mgr_get + * + */ + +const char * +cfa_tcam_mgr_tbl_2_str(enum cfa_tcam_mgr_tbl_type tcam_type); + +/** + * Initializes the TCAM Manager + * + * [in] type + * Device type + * + * Returns + * - (0) if successful. + * - (<0) on failure. + */ +int +cfa_tcam_mgr_init(int sess_idx, enum cfa_tcam_mgr_device_type type, + struct cfa_tcam_mgr_init_parms *parms); + +/** + * Returns the physical TCAM table that a logical TCAM table uses. + * + * [in] type + * Logical table type + * + * Returns + * - (tf_tcam_tbl_type) if successful. + * - (<0) on failure. + */ +int +cfa_tcam_mgr_get_phys_table_type(enum cfa_tcam_mgr_tbl_type type); + +/** + * Queries the capabilities of TCAM Manager. + * + * [in] context + * Pointer to context information + * + * [out] parms + * Pointer to parameters to be returned + * + * Returns + * - (0) if successful. + * - (<0) on failure. + */ +int +cfa_tcam_mgr_qcaps(struct cfa_tcam_mgr_context *context __rte_unused, + struct cfa_tcam_mgr_qcaps_parms *parms); + +/** + * Initializes the TCAM module with the requested DBs. Must be + * invoked as the first thing before any of the access functions. + * + * [in] context + * Pointer to context information + * + * [in] parms + * Pointer to parameters + * + * Returns + * - (0) if successful. + * - (-EINVAL) on failure. + */ +int cfa_tcam_mgr_bind(struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_cfg_parms *parms); + +/** + * Cleans up the private DBs and releases all the data. + * + * [in] context + * Pointer to context information + * + * [in] parms + * Pointer to parameters + * + * Returns + * - (0) if successful. + * - (-EINVAL) on failure. + */ +int cfa_tcam_mgr_unbind(struct cfa_tcam_mgr_context *context); + +/** + * Allocates the requested tcam type from the internal RM DB. + * + * [in] context + * Pointer to context information + * + * [in] parms + * Pointer to parameters + * + * Returns + * - (0) if successful. + * - (-EINVAL) on failure. + */ +int cfa_tcam_mgr_alloc(struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_alloc_parms *parms); + +/** + * Free's the requested table type and returns it to the DB. + * If refcount goes to 0 then it is returned to the table type DB. + * + * [in] context + * Pointer to context information + * + * [in] parms + * Pointer to parameters + * + * Returns + * - (0) if successful. + * - (-EINVAL) on failure. + */ +int cfa_tcam_mgr_free(struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_free_parms *parms); + +/** + * Configures the requested element by sending a firmware request which + * then installs it into the device internal structures. + * + * [in] context + * Pointer to context information + * + * [in] parms + * Pointer to parameters + * + * Returns + * - (0) if successful. + * - (-EINVAL) on failure. + */ +int cfa_tcam_mgr_set(struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_set_parms *parms); + +/** + * Retrieves the requested element by sending a firmware request to get + * the element. + * + * [in] context + * Pointer to context information + * + * [in] parms + * Pointer to parameters + * + * Returns + * - (0) if successful. + * - (-EINVAL) on failure. + */ +int cfa_tcam_mgr_get(struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_get_parms *parms); + +int +cfa_tcam_mgr_tables_get(int sess_idx, enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type, + uint16_t *start_row, + uint16_t *end_row, + uint16_t *max_entries, + uint16_t *slices); +int +cfa_tcam_mgr_tables_set(int sess_idx, enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type, + uint16_t start_row, + uint16_t end_row, + uint16_t max_entries); + +int cfa_tcam_mgr_shared_clear(struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_shared_clear_parms *parms); + +int cfa_tcam_mgr_shared_move(struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_shared_move_parms *parms); + +void cfa_tcam_mgr_rows_dump(int sess_idx, enum tf_dir dir, enum cfa_tcam_mgr_tbl_type type); +void cfa_tcam_mgr_tables_dump(int sess_idx, enum tf_dir dir, enum cfa_tcam_mgr_tbl_type type); +void cfa_tcam_mgr_entries_dump(int sess_idx); +#endif /* _CFA_TCAM_MGR_H */ diff --git a/drivers/net/bnxt/tf_core/cfa_tcam_mgr_device.h b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_device.h new file mode 100644 index 0000000000..6ab9b5e118 --- /dev/null +++ b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_device.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021-2023 Broadcom + * All rights reserved. + */ + +#ifndef CFA_TCAM_MGR_DEVICE_H +#define CFA_TCAM_MGR_DEVICE_H + +#include +#include "cfa_tcam_mgr.h" + +/* + * This identifier is to be used for one-off variable sizes. Do not use it for + * sizing keys in an array. + */ +#define CFA_TCAM_MGR_MAX_KEY_SIZE 96 + +/* Note that this macro's arguments are not macro expanded due to + * concatenation. + */ +#define TF_TCAM_TABLE_ROWS_DEF(_slices) \ + struct cfa_tcam_mgr_table_rows_ ## _slices { \ + uint16_t priority; \ + uint8_t entry_size; /* Slices per entry */ \ + uint8_t entry_inuse; /* bit[entry] set if in use */ \ + uint16_t entries[_slices]; \ + } + +/* + * Have to explicitly declare this struct since some compilers don't accept the + * GNU C extension of zero length arrays. + */ +struct cfa_tcam_mgr_table_rows_0 { + uint16_t priority; + uint8_t entry_size; /* Slices per entry */ + uint8_t entry_inuse; /* bit[entry] set if in use */ + uint16_t entries[]; +}; + +TF_TCAM_TABLE_ROWS_DEF(1); +TF_TCAM_TABLE_ROWS_DEF(2); +TF_TCAM_TABLE_ROWS_DEF(4); +TF_TCAM_TABLE_ROWS_DEF(8); + +#define TF_TCAM_MAX_ENTRIES (L2_CTXT_TCAM_RX_MAX_ENTRIES + \ + L2_CTXT_TCAM_TX_MAX_ENTRIES + \ + PROF_TCAM_RX_MAX_ENTRIES + \ + PROF_TCAM_TX_MAX_ENTRIES + \ + WC_TCAM_RX_MAX_ENTRIES + \ + WC_TCAM_TX_MAX_ENTRIES + \ + SP_TCAM_RX_MAX_ENTRIES + \ + SP_TCAM_TX_MAX_ENTRIES + \ + CT_RULE_TCAM_RX_MAX_ENTRIES + \ + CT_RULE_TCAM_TX_MAX_ENTRIES + \ + VEB_TCAM_RX_MAX_ENTRIES + \ + VEB_TCAM_TX_MAX_ENTRIES) + +struct cfa_tcam_mgr_entry_data { + uint16_t row; + uint8_t slice; + uint8_t ref_cnt; +}; + +struct cfa_tcam_mgr_table_data { + struct cfa_tcam_mgr_table_rows_0 *tcam_rows; + uint16_t hcapi_type; + uint16_t num_rows; /* Rows in physical TCAM */ + uint16_t start_row; /* Where the logical TCAM starts */ + uint16_t end_row; /* Where the logical TCAM ends */ + uint16_t max_entries; + uint16_t used_entries; + uint8_t row_width; /* bytes */ + uint8_t result_size; /* bytes */ + uint8_t max_slices; +}; + +extern int cfa_tcam_mgr_max_entries[TF_TCAM_MAX_SESSIONS]; + +extern struct cfa_tcam_mgr_table_data +cfa_tcam_mgr_tables[TF_TCAM_MAX_SESSIONS][TF_DIR_MAX][CFA_TCAM_MGR_TBL_TYPE_MAX]; + +/* HW OP definitions begin here */ +typedef int (*cfa_tcam_mgr_hwop_set_func_t)(int sess_idx, + struct cfa_tcam_mgr_set_parms + *parms, int row, int slice, + int max_slices); +typedef int (*cfa_tcam_mgr_hwop_get_func_t)(int sess_idx, + struct cfa_tcam_mgr_get_parms + *parms, int row, int slice, + int max_slices); +typedef int (*cfa_tcam_mgr_hwop_free_func_t)(int sess_idx, + struct cfa_tcam_mgr_free_parms + *parms, int row, int slice, + int max_slices); + +struct cfa_tcam_mgr_hwops_funcs { + cfa_tcam_mgr_hwop_set_func_t set; + cfa_tcam_mgr_hwop_get_func_t get; + cfa_tcam_mgr_hwop_free_func_t free; +}; +#endif /* CFA_TCAM_MGR_DEVICE_H */ diff --git a/drivers/net/bnxt/tf_core/cfa_tcam_mgr_hwop_msg.c b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_hwop_msg.c new file mode 100644 index 0000000000..0fb5563cc3 --- /dev/null +++ b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_hwop_msg.c @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021-2023 Broadcom + * All rights reserved. + */ + +/* + * This file will "do the right thing" for each of the primitives set, get and + * free. The TCAM manager is running in the core, so the tables will be cached. + * Set and free messages will also be sent to the firmware. Instead of sending + * get messages, the entry will be read from the cached copy thus saving a + * firmware message. + */ + +#include "tf_tcam.h" +#include "hcapi_cfa_defs.h" +#include "cfa_tcam_mgr.h" +#include "cfa_tcam_mgr_hwop_msg.h" +#include "cfa_tcam_mgr_device.h" +#include "cfa_tcam_mgr_p58.h" +#include "cfa_tcam_mgr_p4.h" +#include "tf_session.h" +#include "tf_msg.h" +#include "tfp.h" +#include "tf_util.h" + +/* + * The free hwop will free more than a single slice so cannot be used. + */ +struct cfa_tcam_mgr_hwops_funcs hwop_funcs; + +int +cfa_tcam_mgr_hwops_init(enum cfa_tcam_mgr_device_type type) +{ + switch (type) { + case CFA_TCAM_MGR_DEVICE_TYPE_P4: + case CFA_TCAM_MGR_DEVICE_TYPE_SR: + return cfa_tcam_mgr_hwops_get_funcs_p4(&hwop_funcs); + case CFA_TCAM_MGR_DEVICE_TYPE_P5: + return cfa_tcam_mgr_hwops_get_funcs_p58(&hwop_funcs); + default: + CFA_TCAM_MGR_LOG(ERR, "No such device\n"); + return -CFA_TCAM_MGR_ERR_CODE(NODEV); + } +} + +/* + * This is the glue between the TCAM manager and the firmware HW operations. It + * is intended to abstract out the location of the TCAM manager so that the TCAM + * manager code will be the same whether or not it is actually using the + * firmware. + */ + +int +cfa_tcam_mgr_entry_set_msg(int sess_idx, struct cfa_tcam_mgr_context *context + __rte_unused, + struct cfa_tcam_mgr_set_parms *parms, + int row, int slice, + int max_slices __rte_unused) +{ + cfa_tcam_mgr_hwop_set_func_t set_func; + + set_func = hwop_funcs.set; + if (set_func == NULL) + return -CFA_TCAM_MGR_ERR_CODE(PERM); + + struct tf_tcam_set_parms sparms; + struct tf_session *tfs; + struct tf_dev_info *dev; + int rc; + enum tf_tcam_tbl_type type = + cfa_tcam_mgr_get_phys_table_type(parms->type); + + /* Retrieve the session information */ + rc = tf_session_get_session_internal(context->tfp, &tfs); + if (rc) + return rc; + + /* Retrieve the device information */ + rc = tf_session_get_device(tfs, &dev); + if (rc) + return rc; + + memset(&sparms, 0, sizeof(sparms)); + sparms.dir = parms->dir; + sparms.type = type; + sparms.hcapi_type = parms->hcapi_type; + sparms.idx = (row * max_slices) + slice; + sparms.key = parms->key; + sparms.mask = parms->mask; + sparms.key_size = parms->key_size; + sparms.result = parms->result; + sparms.result_size = parms->result_size; + + rc = tf_msg_tcam_entry_set(context->tfp, dev, &sparms); + if (rc) { + /* Log error */ + CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, parms->dir, parms->type, + "Entry %d set failed, rc:%d\n", + parms->id, -rc); + return rc; + } + + return set_func(sess_idx, parms, row, slice, max_slices); +} + +int +cfa_tcam_mgr_entry_get_msg(int sess_idx, struct cfa_tcam_mgr_context *context + __rte_unused, + struct cfa_tcam_mgr_get_parms *parms, + int row, int slice, + int max_slices __rte_unused) +{ + cfa_tcam_mgr_hwop_get_func_t get_func; + + get_func = hwop_funcs.get; + if (get_func == NULL) + return -CFA_TCAM_MGR_ERR_CODE(PERM); + + return get_func(sess_idx, parms, row, slice, max_slices); +} + +int +cfa_tcam_mgr_entry_free_msg(int sess_idx, struct cfa_tcam_mgr_context *context + __rte_unused, + struct cfa_tcam_mgr_free_parms *parms, + int row, int slice, + int key_size, + int result_size, + int max_slices) +{ + cfa_tcam_mgr_hwop_free_func_t free_func; + + free_func = hwop_funcs.free; + if (free_func == NULL) + return -CFA_TCAM_MGR_ERR_CODE(PERM); + + struct tf_dev_info *dev; + struct tf_session *tfs; + int rc; + enum tf_tcam_tbl_type type = + cfa_tcam_mgr_get_phys_table_type(parms->type); + + /* Free will clear an entire row. */ + /* Use set message to clear an individual entry */ + struct tf_tcam_set_parms sparms; + uint8_t key[CFA_TCAM_MGR_MAX_KEY_SIZE] = { 0 }; + uint8_t mask[CFA_TCAM_MGR_MAX_KEY_SIZE] = { 0 }; + + /* Retrieve the session information */ + rc = tf_session_get_session_internal(context->tfp, &tfs); + if (rc) + return rc; + + /* Retrieve the device information */ + rc = tf_session_get_device(tfs, &dev); + if (rc) + return rc; + + if (key_size > CFA_TCAM_MGR_MAX_KEY_SIZE) { + CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, parms->dir, parms->type, + "Entry %d key size is %d greater than:%d\n", + parms->id, key_size, + CFA_TCAM_MGR_MAX_KEY_SIZE); + return -EINVAL; + } + + if (result_size > CFA_TCAM_MGR_MAX_KEY_SIZE) { + CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, parms->dir, parms->type, + "Entry %d result size is %d greater than:%d\n", + parms->id, result_size, + CFA_TCAM_MGR_MAX_KEY_SIZE); + return -EINVAL; + } + + memset(&sparms, 0, sizeof(sparms)); + memset(&key, 0, sizeof(key)); + memset(&mask, 0xff, sizeof(mask)); + + sparms.dir = parms->dir; + sparms.type = type; + sparms.hcapi_type = parms->hcapi_type; + sparms.key = key; + sparms.mask = mask; + sparms.result = key; + sparms.idx = (row * max_slices) + slice; + sparms.key_size = key_size; + sparms.result_size = result_size; + + rc = tf_msg_tcam_entry_set(context->tfp, dev, &sparms); + if (rc) { + /* Log error */ + CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, parms->dir, parms->type, + "Row %d, slice %d set failed, " + "rc:%d.\n", + row, + slice, + rc); + return rc; + } + return free_func(sess_idx, parms, row, slice, max_slices); +} diff --git a/drivers/net/bnxt/tf_core/cfa_tcam_mgr_hwop_msg.h b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_hwop_msg.h new file mode 100644 index 0000000000..f7ba625c07 --- /dev/null +++ b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_hwop_msg.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021-2023 Broadcom + * All rights reserved. + */ + +#ifndef CFA_TCAM_MGR_HWOP_MSG_H +#define CFA_TCAM_MGR_HWOP_MSG_H + +int +cfa_tcam_mgr_hwops_init(enum cfa_tcam_mgr_device_type type); + +int +cfa_tcam_mgr_entry_set_msg(int sess_idx, + struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_set_parms *parms, + int row, int slice, int max_slices); +int +cfa_tcam_mgr_entry_get_msg(int sess_idx, + struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_get_parms *parms, + int row, int slice, int max_slices); +int +cfa_tcam_mgr_entry_free_msg(int sess_idx, + struct cfa_tcam_mgr_context *context, + struct cfa_tcam_mgr_free_parms *parms, + int row, int slice, int key_size, + int result_size, int max_slices); +#endif /* CFA_TCAM_MGR_HWOP_MSG_H */ diff --git a/drivers/net/bnxt/tf_core/cfa_tcam_mgr_p4.c b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_p4.c new file mode 100644 index 0000000000..63c84c5938 --- /dev/null +++ b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_p4.c @@ -0,0 +1,921 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021-2023 Broadcom + * All rights reserved. + */ + +#include "hcapi_cfa_defs.h" + +#include "cfa_tcam_mgr.h" +#include "cfa_tcam_mgr_p4.h" +#include "cfa_tcam_mgr_device.h" +#include "cfa_resource_types.h" +#include "tfp.h" +#include "assert.h" +#include "tf_util.h" + +/* + * Sizings of the TCAMs on P4 + */ + +#define MAX_ROW_WIDTH 48 +#define MAX_RESULT_SIZE 8 + +#if MAX_ROW_WIDTH > CFA_TCAM_MGR_MAX_KEY_SIZE +#error MAX_ROW_WIDTH > CFA_TCAM_MGR_MAX_KEY_SIZE +#endif + +/* + * TCAM definitions + * + * These define the TCAMs in HW. + * + * Note: Set xxx_TCAM_[R|T]X_NUM_ROWS to zero if a TCAM is either not supported + * by HW or not supported by TCAM Manager. + */ + +/** L2 Context TCAM */ +#define L2_CTXT_TCAM_RX_MAX_SLICES 1 +#define L2_CTXT_TCAM_RX_ROW_WIDTH TF_BITS2BYTES_WORD_ALIGN(167) +#define L2_CTXT_TCAM_RX_NUM_ROWS 1024 +#define L2_CTXT_TCAM_RX_MAX_ENTRIES (L2_CTXT_TCAM_RX_MAX_SLICES * \ + L2_CTXT_TCAM_RX_NUM_ROWS) +#define L2_CTXT_TCAM_RX_RESULT_SIZE 8 + +#define L2_CTXT_TCAM_TX_MAX_SLICES L2_CTXT_TCAM_RX_MAX_SLICES +#define L2_CTXT_TCAM_TX_ROW_WIDTH L2_CTXT_TCAM_RX_ROW_WIDTH +#define L2_CTXT_TCAM_TX_NUM_ROWS L2_CTXT_TCAM_RX_NUM_ROWS +#define L2_CTXT_TCAM_TX_MAX_ENTRIES L2_CTXT_TCAM_RX_MAX_ENTRIES +#define L2_CTXT_TCAM_TX_RESULT_SIZE L2_CTXT_TCAM_RX_RESULT_SIZE + +/** Profile TCAM */ +#define PROF_TCAM_RX_MAX_SLICES 1 +#define PROF_TCAM_RX_ROW_WIDTH TF_BITS2BYTES_WORD_ALIGN(81) +#define PROF_TCAM_RX_NUM_ROWS 1024 +#define PROF_TCAM_RX_MAX_ENTRIES (PROF_TCAM_RX_MAX_SLICES * \ + PROF_TCAM_RX_NUM_ROWS) +#define PROF_TCAM_RX_RESULT_SIZE 8 + +#define PROF_TCAM_TX_MAX_SLICES PROF_TCAM_RX_MAX_SLICES +#define PROF_TCAM_TX_ROW_WIDTH PROF_TCAM_RX_ROW_WIDTH +#define PROF_TCAM_TX_NUM_ROWS PROF_TCAM_RX_NUM_ROWS +#define PROF_TCAM_TX_MAX_ENTRIES PROF_TCAM_RX_MAX_ENTRIES +#define PROF_TCAM_TX_RESULT_SIZE PROF_TCAM_RX_RESULT_SIZE + +/** Wildcard TCAM */ +#define WC_TCAM_RX_MAX_SLICES 4 +/* 82 bits per slice */ +#define WC_TCAM_RX_ROW_WIDTH (TF_BITS2BYTES_WORD_ALIGN(82) * \ + WC_TCAM_RX_MAX_SLICES) +#define WC_TCAM_RX_NUM_ROWS 256 +#define WC_TCAM_RX_MAX_ENTRIES (WC_TCAM_RX_MAX_SLICES * WC_TCAM_RX_NUM_ROWS) +#define WC_TCAM_RX_RESULT_SIZE 4 + +#define WC_TCAM_TX_MAX_SLICES WC_TCAM_RX_MAX_SLICES +#define WC_TCAM_TX_ROW_WIDTH WC_TCAM_RX_ROW_WIDTH +#define WC_TCAM_TX_NUM_ROWS WC_TCAM_RX_NUM_ROWS +#define WC_TCAM_TX_MAX_ENTRIES WC_TCAM_RX_MAX_ENTRIES +#define WC_TCAM_TX_RESULT_SIZE WC_TCAM_RX_RESULT_SIZE + +/** Source Properties TCAM */ +#define SP_TCAM_RX_MAX_SLICES 1 +#define SP_TCAM_RX_ROW_WIDTH TF_BITS2BYTES_WORD_ALIGN(89) +#define SP_TCAM_RX_NUM_ROWS 512 +#define SP_TCAM_RX_MAX_ENTRIES (SP_TCAM_RX_MAX_SLICES * SP_TCAM_RX_NUM_ROWS) +#define SP_TCAM_RX_RESULT_SIZE 8 + +#define SP_TCAM_TX_MAX_SLICES SP_TCAM_RX_MAX_SLICES +#define SP_TCAM_TX_ROW_WIDTH SP_TCAM_RX_ROW_WIDTH +#define SP_TCAM_TX_NUM_ROWS SP_TCAM_RX_NUM_ROWS +#define SP_TCAM_TX_MAX_ENTRIES SP_TCAM_RX_MAX_ENTRIES +#define SP_TCAM_TX_RESULT_SIZE SP_TCAM_RX_RESULT_SIZE + +/** Connection Tracking Rule TCAM */ +#define CT_RULE_TCAM_RX_MAX_SLICES 1 +#define CT_RULE_TCAM_RX_ROW_WIDTH TF_BITS2BYTES_WORD_ALIGN(16) +#define CT_RULE_TCAM_RX_NUM_ROWS 0 +#define CT_RULE_TCAM_RX_MAX_ENTRIES (CT_RULE_TCAM_RX_MAX_SLICES * \ + CT_RULE_TCAM_RX_NUM_ROWS) +#define CT_RULE_TCAM_RX_RESULT_SIZE 8 + +#define CT_RULE_TCAM_TX_MAX_SLICES CT_RULE_TCAM_RX_MAX_SLICES +#define CT_RULE_TCAM_TX_ROW_WIDTH CT_RULE_TCAM_RX_ROW_WIDTH +#define CT_RULE_TCAM_TX_NUM_ROWS CT_RULE_TCAM_RX_NUM_ROWS +#define CT_RULE_TCAM_TX_MAX_ENTRIES CT_RULE_TCAM_RX_MAX_ENTRIES +#define CT_RULE_TCAM_TX_RESULT_SIZE CT_RULE_TCAM_RX_RESULT_SIZE + +/** Virtual Edge Bridge TCAM */ +#define VEB_TCAM_RX_MAX_SLICES 1 +#define VEB_TCAM_RX_ROW_WIDTH TF_BITS2BYTES_WORD_ALIGN(78) +/* Tx only */ +#define VEB_TCAM_RX_NUM_ROWS 0 +#define VEB_TCAM_RX_MAX_ENTRIES (VEB_TCAM_RX_MAX_SLICES * VEB_TCAM_RX_NUM_ROWS) +#define VEB_TCAM_RX_RESULT_SIZE 8 + +#define VEB_TCAM_TX_MAX_SLICES VEB_TCAM_RX_MAX_SLICES +#define VEB_TCAM_TX_ROW_WIDTH VEB_TCAM_RX_ROW_WIDTH +#define VEB_TCAM_TX_NUM_ROWS 1024 +#define VEB_TCAM_TX_MAX_ENTRIES (VEB_TCAM_TX_MAX_SLICES * VEB_TCAM_TX_NUM_ROWS) +#define VEB_TCAM_TX_RESULT_SIZE VEB_TCAM_RX_RESULT_SIZE + +/* Declare the table rows for each table here. If new tables are added to the + * enum tf_tcam_tbl_type, then new declarations will be needed here. + * + * The numeric suffix of the structure type indicates how many slices a + * particular TCAM supports. + * + * Array sizes have 1 added to avoid zero length arrays. + */ + +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_RX[TF_TCAM_MAX_SESSIONS][L2_CTXT_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_TX[TF_TCAM_MAX_SESSIONS][L2_CTXT_TCAM_TX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_PROF_TCAM_RX[TF_TCAM_MAX_SESSIONS][PROF_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_PROF_TCAM_TX[TF_TCAM_MAX_SESSIONS][PROF_TCAM_TX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_4 + cfa_tcam_mgr_table_rows_WC_TCAM_RX[TF_TCAM_MAX_SESSIONS][WC_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_4 + cfa_tcam_mgr_table_rows_WC_TCAM_TX[TF_TCAM_MAX_SESSIONS][WC_TCAM_TX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_SP_TCAM_RX[TF_TCAM_MAX_SESSIONS][SP_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_SP_TCAM_TX[TF_TCAM_MAX_SESSIONS][SP_TCAM_TX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_CT_RULE_TCAM_RX[TF_TCAM_MAX_SESSIONS][CT_RULE_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_CT_RULE_TCAM_TX[TF_TCAM_MAX_SESSIONS][CT_RULE_TCAM_TX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_VEB_TCAM_RX[TF_TCAM_MAX_SESSIONS][VEB_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_VEB_TCAM_TX[TF_TCAM_MAX_SESSIONS][VEB_TCAM_TX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_4 + cfa_tcam_mgr_table_rows_WC_TCAM_RX_HIGH[TF_TCAM_MAX_SESSIONS][WC_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_4 + cfa_tcam_mgr_table_rows_WC_TCAM_RX_LOW[TF_TCAM_MAX_SESSIONS][WC_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_4 + cfa_tcam_mgr_table_rows_WC_TCAM_TX_HIGH[TF_TCAM_MAX_SESSIONS][WC_TCAM_TX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_4 + cfa_tcam_mgr_table_rows_WC_TCAM_TX_LOW[TF_TCAM_MAX_SESSIONS][WC_TCAM_TX_NUM_ROWS + 1]; + +struct cfa_tcam_mgr_table_data +cfa_tcam_mgr_tables_p4[TF_DIR_MAX][CFA_TCAM_MGR_TBL_TYPE_MAX] = { + { /* RX */ + { /* High AFM */ + .max_slices = L2_CTXT_TCAM_RX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_RX_ROW_WIDTH, + .num_rows = L2_CTXT_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = L2_CTXT_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_L2_CTXT_TCAM_HIGH, + }, + { /* High APPS */ + .max_slices = L2_CTXT_TCAM_RX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_RX_ROW_WIDTH, + .num_rows = L2_CTXT_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = (L2_CTXT_TCAM_RX_NUM_ROWS / 2) - 1, + .max_entries = (L2_CTXT_TCAM_RX_MAX_ENTRIES / 2), + .result_size = L2_CTXT_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_L2_CTXT_TCAM_HIGH, + }, + { /* Low AFM */ + .max_slices = L2_CTXT_TCAM_RX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_RX_ROW_WIDTH, + .num_rows = L2_CTXT_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = L2_CTXT_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_L2_CTXT_TCAM_LOW, + }, + { /* Low APPS */ + .max_slices = L2_CTXT_TCAM_RX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_RX_ROW_WIDTH, + .num_rows = L2_CTXT_TCAM_RX_NUM_ROWS, + .start_row = (L2_CTXT_TCAM_RX_NUM_ROWS / 2), + .end_row = L2_CTXT_TCAM_RX_NUM_ROWS - 1, + .max_entries = (L2_CTXT_TCAM_RX_MAX_ENTRIES / 2), + .result_size = L2_CTXT_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_L2_CTXT_TCAM_LOW, + }, + { /* AFM */ + .max_slices = PROF_TCAM_RX_MAX_SLICES, + .row_width = PROF_TCAM_RX_ROW_WIDTH, + .num_rows = PROF_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = PROF_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_PROF_TCAM, + }, + { /* APPS */ + .max_slices = PROF_TCAM_RX_MAX_SLICES, + .row_width = PROF_TCAM_RX_ROW_WIDTH, + .num_rows = PROF_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = PROF_TCAM_RX_NUM_ROWS - 1, + .max_entries = PROF_TCAM_RX_MAX_ENTRIES, + .result_size = PROF_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_PROF_TCAM, + }, + { /* AFM */ + .max_slices = WC_TCAM_RX_MAX_SLICES, + .row_width = WC_TCAM_RX_ROW_WIDTH, + .num_rows = WC_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = WC_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_WC_TCAM, + }, + { /* APPS */ + .max_slices = WC_TCAM_RX_MAX_SLICES, + .row_width = WC_TCAM_RX_ROW_WIDTH, + .num_rows = WC_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = WC_TCAM_RX_NUM_ROWS - 1, + .max_entries = WC_TCAM_RX_MAX_ENTRIES, + .result_size = WC_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_WC_TCAM, + }, + { /* AFM */ + .max_slices = SP_TCAM_RX_MAX_SLICES, + .row_width = SP_TCAM_RX_ROW_WIDTH, + .num_rows = SP_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = SP_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_SP_TCAM, + }, + { /* APPS */ + .max_slices = SP_TCAM_RX_MAX_SLICES, + .row_width = SP_TCAM_RX_ROW_WIDTH, + .num_rows = SP_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = SP_TCAM_RX_NUM_ROWS - 1, + .max_entries = SP_TCAM_RX_MAX_ENTRIES, + .result_size = SP_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_SP_TCAM, + }, + { /* AFM */ + .max_slices = CT_RULE_TCAM_RX_MAX_SLICES, + .row_width = CT_RULE_TCAM_RX_ROW_WIDTH, + .num_rows = CT_RULE_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = CT_RULE_TCAM_RX_RESULT_SIZE, + }, + { /* APPS */ + .max_slices = CT_RULE_TCAM_RX_MAX_SLICES, + .row_width = CT_RULE_TCAM_RX_ROW_WIDTH, + .num_rows = CT_RULE_TCAM_RX_NUM_ROWS, + .start_row = 0, +#if CT_RULE_TCAM_RX_NUM_ROWS > 0 + .end_row = CT_RULE_TCAM_RX_NUM_ROWS - 1, +#else + .end_row = CT_RULE_TCAM_RX_NUM_ROWS, +#endif + .max_entries = CT_RULE_TCAM_RX_MAX_ENTRIES, + .result_size = CT_RULE_TCAM_RX_RESULT_SIZE, + }, + { /* AFM */ + .max_slices = VEB_TCAM_RX_MAX_SLICES, + .row_width = VEB_TCAM_RX_ROW_WIDTH, + .num_rows = VEB_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = VEB_TCAM_RX_RESULT_SIZE, + }, + { /* APPS */ + .max_slices = VEB_TCAM_RX_MAX_SLICES, + .row_width = VEB_TCAM_RX_ROW_WIDTH, + .num_rows = VEB_TCAM_RX_NUM_ROWS, + .start_row = 0, +#if VEB_TCAM_RX_NUM_ROWS > 0 + .end_row = VEB_TCAM_RX_NUM_ROWS - 1, +#else + .end_row = VEB_TCAM_RX_NUM_ROWS, +#endif + .max_entries = VEB_TCAM_RX_MAX_ENTRIES, + .result_size = VEB_TCAM_RX_RESULT_SIZE, + }, + { /* AFM */ + .max_slices = WC_TCAM_RX_MAX_SLICES, + .row_width = WC_TCAM_RX_ROW_WIDTH, + .num_rows = WC_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = WC_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_WC_TCAM, + }, + { /* APPS */ + .max_slices = WC_TCAM_RX_MAX_SLICES, + .row_width = WC_TCAM_RX_ROW_WIDTH, + .num_rows = WC_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = WC_TCAM_RX_NUM_ROWS - 1, + .max_entries = WC_TCAM_RX_MAX_ENTRIES, + .result_size = WC_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_WC_TCAM, + }, + { /* AFM */ + .max_slices = WC_TCAM_RX_MAX_SLICES, + .row_width = WC_TCAM_RX_ROW_WIDTH, + .num_rows = WC_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = WC_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_WC_TCAM, + }, + { /* APPS */ + .max_slices = WC_TCAM_RX_MAX_SLICES, + .row_width = WC_TCAM_RX_ROW_WIDTH, + .num_rows = WC_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = WC_TCAM_RX_NUM_ROWS - 1, + .max_entries = WC_TCAM_RX_MAX_ENTRIES, + .result_size = WC_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_WC_TCAM, + }, + }, + { /* TX */ + { /* AFM */ + .max_slices = L2_CTXT_TCAM_TX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_TX_ROW_WIDTH, + .num_rows = L2_CTXT_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = L2_CTXT_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_L2_CTXT_TCAM_HIGH, + }, + { /* APPS */ + .max_slices = L2_CTXT_TCAM_TX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_TX_ROW_WIDTH, + .num_rows = L2_CTXT_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = (L2_CTXT_TCAM_TX_NUM_ROWS / 2) - 1, + .max_entries = (L2_CTXT_TCAM_TX_MAX_ENTRIES / 2), + .result_size = L2_CTXT_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_L2_CTXT_TCAM_HIGH, + }, + { /* AFM */ + .max_slices = L2_CTXT_TCAM_TX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_TX_ROW_WIDTH, + .num_rows = L2_CTXT_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = L2_CTXT_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_L2_CTXT_TCAM_LOW, + }, + { /* APPS */ + .max_slices = L2_CTXT_TCAM_TX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_TX_ROW_WIDTH, + .num_rows = L2_CTXT_TCAM_TX_NUM_ROWS, + .start_row = (L2_CTXT_TCAM_TX_NUM_ROWS / 2), + .end_row = L2_CTXT_TCAM_TX_NUM_ROWS - 1, + .max_entries = (L2_CTXT_TCAM_TX_MAX_ENTRIES / 2), + .result_size = L2_CTXT_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_L2_CTXT_TCAM_LOW, + }, + { /* AFM */ + .max_slices = PROF_TCAM_TX_MAX_SLICES, + .row_width = PROF_TCAM_TX_ROW_WIDTH, + .num_rows = PROF_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = PROF_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_PROF_TCAM, + }, + { /* APPS */ + .max_slices = PROF_TCAM_TX_MAX_SLICES, + .row_width = PROF_TCAM_TX_ROW_WIDTH, + .num_rows = PROF_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = PROF_TCAM_TX_NUM_ROWS - 1, + .max_entries = PROF_TCAM_TX_MAX_ENTRIES, + .result_size = PROF_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_PROF_TCAM, + }, + { /* AFM */ + .max_slices = WC_TCAM_TX_MAX_SLICES, + .row_width = WC_TCAM_TX_ROW_WIDTH, + .num_rows = WC_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = WC_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_WC_TCAM, + }, + { /* APPS */ + .max_slices = WC_TCAM_TX_MAX_SLICES, + .row_width = WC_TCAM_TX_ROW_WIDTH, + .num_rows = WC_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = WC_TCAM_TX_NUM_ROWS - 1, + .max_entries = WC_TCAM_TX_MAX_ENTRIES, + .result_size = WC_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_WC_TCAM, + }, + { /* AFM */ + .max_slices = SP_TCAM_TX_MAX_SLICES, + .row_width = SP_TCAM_TX_ROW_WIDTH, + .num_rows = SP_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = SP_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_SP_TCAM, + }, + { /* APPS */ + .max_slices = SP_TCAM_TX_MAX_SLICES, + .row_width = SP_TCAM_TX_ROW_WIDTH, + .num_rows = SP_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = SP_TCAM_TX_NUM_ROWS - 1, + .max_entries = SP_TCAM_TX_MAX_ENTRIES, + .result_size = SP_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_SP_TCAM, + }, + { /* AFM */ + .max_slices = CT_RULE_TCAM_TX_MAX_SLICES, + .row_width = CT_RULE_TCAM_TX_ROW_WIDTH, + .num_rows = CT_RULE_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = CT_RULE_TCAM_RX_RESULT_SIZE, + }, + { /* APPS */ + .max_slices = CT_RULE_TCAM_TX_MAX_SLICES, + .row_width = CT_RULE_TCAM_TX_ROW_WIDTH, + .num_rows = CT_RULE_TCAM_TX_NUM_ROWS, + .start_row = 0, +#if CT_RULE_TCAM_TX_NUM_ROWS > 0 + .end_row = CT_RULE_TCAM_TX_NUM_ROWS - 1, +#else + .end_row = CT_RULE_TCAM_TX_NUM_ROWS, +#endif + .max_entries = CT_RULE_TCAM_TX_MAX_ENTRIES, + .result_size = CT_RULE_TCAM_RX_RESULT_SIZE, + }, + { /* AFM */ + .max_slices = VEB_TCAM_TX_MAX_SLICES, + .row_width = VEB_TCAM_TX_ROW_WIDTH, + .num_rows = VEB_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = VEB_TCAM_RX_RESULT_SIZE, + }, + { /* APPS */ + .max_slices = VEB_TCAM_TX_MAX_SLICES, + .row_width = VEB_TCAM_TX_ROW_WIDTH, + .num_rows = VEB_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = VEB_TCAM_TX_NUM_ROWS - 1, + .max_entries = VEB_TCAM_TX_MAX_ENTRIES, + .result_size = VEB_TCAM_RX_RESULT_SIZE, + }, + { /* AFM */ + .max_slices = WC_TCAM_TX_MAX_SLICES, + .row_width = WC_TCAM_TX_ROW_WIDTH, + .num_rows = WC_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = WC_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_WC_TCAM, + }, + { /* APPS */ + .max_slices = WC_TCAM_TX_MAX_SLICES, + .row_width = WC_TCAM_TX_ROW_WIDTH, + .num_rows = WC_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = WC_TCAM_TX_NUM_ROWS - 1, + .max_entries = WC_TCAM_TX_MAX_ENTRIES, + .result_size = WC_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_WC_TCAM, + }, + { /* AFM */ + .max_slices = WC_TCAM_TX_MAX_SLICES, + .row_width = WC_TCAM_TX_ROW_WIDTH, + .num_rows = WC_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = WC_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_WC_TCAM, + }, + { /* APPS */ + .max_slices = WC_TCAM_TX_MAX_SLICES, + .row_width = WC_TCAM_TX_ROW_WIDTH, + .num_rows = WC_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = WC_TCAM_TX_NUM_ROWS - 1, + .max_entries = WC_TCAM_TX_MAX_ENTRIES, + .result_size = WC_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P4_WC_TCAM, + }, + }, +}; + +static struct cfa_tcam_mgr_entry_data entry_data_p4[TF_TCAM_MAX_SESSIONS][TF_TCAM_MAX_ENTRIES]; + +static struct sbmp session_bmp_p4[TF_TCAM_MAX_SESSIONS][TF_TCAM_MAX_ENTRIES]; + +int +cfa_tcam_mgr_sess_table_get_p4(int sess_idx, struct sbmp **session_bmp) +{ + *session_bmp = session_bmp_p4[sess_idx]; + return 0; +} + +int +cfa_tcam_mgr_init_p4(int sess_idx, struct cfa_tcam_mgr_entry_data **global_entry_data) +{ + int max_row_width = 0; + int max_result_size = 0; + int dir, type; + + *global_entry_data = entry_data_p4[sess_idx]; + + memcpy(&cfa_tcam_mgr_tables[sess_idx], + &cfa_tcam_mgr_tables_p4, + sizeof(cfa_tcam_mgr_tables[sess_idx])); + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_RX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_RX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_TX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_RX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_RX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_TX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_PROF_TCAM_RX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_PROF_TCAM_RX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_PROF_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_PROF_TCAM_TX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_RX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_RX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_TX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_SP_TCAM_RX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_SP_TCAM_RX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_SP_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_SP_TCAM_TX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_CT_RULE_TCAM_RX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_CT_RULE_TCAM_RX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_CT_RULE_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_CT_RULE_TCAM_TX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_VEB_TCAM_RX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_VEB_TCAM_RX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_VEB_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_VEB_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_RX_HIGH[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_RX_HIGH[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_TX_HIGH[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_TX_HIGH[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_RX_LOW[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_RX_LOW[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_TX_LOW[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_TX_LOW[sess_idx]; + + for (dir = 0; dir < TF_DIR_MAX; dir++) { + for (type = 0; type < CFA_TCAM_MGR_TBL_TYPE_MAX; type++) { + if (cfa_tcam_mgr_tables[sess_idx][dir][type].row_width > + max_row_width) + max_row_width = + cfa_tcam_mgr_tables[sess_idx][dir][type].row_width; + if (cfa_tcam_mgr_tables[sess_idx][dir][type].result_size > + max_result_size) + max_result_size = + cfa_tcam_mgr_tables[sess_idx][dir][type].result_size; + } + } + + if (max_row_width != MAX_ROW_WIDTH) { + CFA_TCAM_MGR_LOG(ERR, + "MAX_ROW_WIDTH (%d) does not match actual " + "value (%d).\n", + MAX_ROW_WIDTH, + max_row_width); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + if (max_result_size != MAX_RESULT_SIZE) { + CFA_TCAM_MGR_LOG(ERR, + "MAX_RESULT_SIZE (%d) does not match actual " + "value (%d).\n", + MAX_RESULT_SIZE, + max_result_size); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + return 0; +} + +/* HW OP declarations begin here */ +struct cfa_tcam_mgr_TCAM_row_data { + int key_size; + int result_size; + uint8_t key[MAX_ROW_WIDTH]; + uint8_t mask[MAX_ROW_WIDTH]; + uint8_t result[MAX_RESULT_SIZE]; +}; + +/* These macros are only needed to avoid exceeding 80 columns */ +#define L2_CTXT_RX_MAX_ROWS \ + (L2_CTXT_TCAM_RX_MAX_SLICES * L2_CTXT_TCAM_RX_NUM_ROWS) +#define PROF_RX_MAX_ROWS (PROF_TCAM_RX_MAX_SLICES * PROF_TCAM_RX_NUM_ROWS) +#define WC_RX_MAX_ROWS (WC_TCAM_RX_MAX_SLICES * WC_TCAM_RX_NUM_ROWS) +#define SP_RX_MAX_ROWS (SP_TCAM_RX_MAX_SLICES * SP_TCAM_RX_NUM_ROWS) +#define CT_RULE_RX_MAX_ROWS \ + (CT_RULE_TCAM_RX_MAX_SLICES * CT_RULE_TCAM_RX_NUM_ROWS) +#define VEB_RX_MAX_ROWS (VEB_TCAM_RX_MAX_SLICES * VEB_TCAM_RX_NUM_ROWS) + +#define L2_CTXT_TX_MAX_ROWS \ + (L2_CTXT_TCAM_TX_MAX_SLICES * L2_CTXT_TCAM_TX_NUM_ROWS) +#define PROF_TX_MAX_ROWS (PROF_TCAM_TX_MAX_SLICES * PROF_TCAM_TX_NUM_ROWS) +#define WC_TX_MAX_ROWS (WC_TCAM_TX_MAX_SLICES * WC_TCAM_TX_NUM_ROWS) +#define SP_TX_MAX_ROWS (SP_TCAM_TX_MAX_SLICES * SP_TCAM_TX_NUM_ROWS) +#define CT_RULE_TX_MAX_ROWS \ + (CT_RULE_TCAM_TX_MAX_SLICES * CT_RULE_TCAM_TX_NUM_ROWS) +#define VEB_TX_MAX_ROWS (VEB_TCAM_TX_MAX_SLICES * VEB_TCAM_TX_NUM_ROWS) + +static int cfa_tcam_mgr_max_rows[TF_TCAM_TBL_TYPE_MAX] = { + L2_CTXT_RX_MAX_ROWS, + L2_CTXT_RX_MAX_ROWS, + PROF_RX_MAX_ROWS, + WC_RX_MAX_ROWS, + SP_RX_MAX_ROWS, + CT_RULE_RX_MAX_ROWS, + VEB_RX_MAX_ROWS, + WC_RX_MAX_ROWS, + WC_RX_MAX_ROWS +}; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_L2_CTXT_TCAM_RX_row_data[TF_TCAM_MAX_SESSIONS][L2_CTXT_RX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_PROF_TCAM_RX_row_data[TF_TCAM_MAX_SESSIONS][PROF_RX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_WC_TCAM_RX_row_data[TF_TCAM_MAX_SESSIONS][WC_RX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_SP_TCAM_RX_row_data[TF_TCAM_MAX_SESSIONS][SP_RX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_CT_RULE_TCAM_RX_row_data[TF_TCAM_MAX_SESSIONS][CT_RULE_RX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_VEB_TCAM_RX_row_data[TF_TCAM_MAX_SESSIONS][VEB_RX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_WC_TCAM_RX_row_data[TF_TCAM_MAX_SESSIONS][WC_RX_MAX_ROWS]; + +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_L2_CTXT_TCAM_TX_row_data[TF_TCAM_MAX_SESSIONS][L2_CTXT_TX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_PROF_TCAM_TX_row_data[TF_TCAM_MAX_SESSIONS][PROF_TX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_WC_TCAM_TX_row_data[TF_TCAM_MAX_SESSIONS][WC_TX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_SP_TCAM_TX_row_data[TF_TCAM_MAX_SESSIONS][SP_TX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_CT_RULE_TCAM_TX_row_data[TF_TCAM_MAX_SESSIONS][CT_RULE_TX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_VEB_TCAM_TX_row_data[TF_TCAM_MAX_SESSIONS][VEB_TX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_WC_TCAM_TX_row_data[TF_TCAM_MAX_SESSIONS][WC_TX_MAX_ROWS]; + +static struct cfa_tcam_mgr_TCAM_row_data * +row_tables[TF_DIR_MAX][TF_TCAM_TBL_TYPE_MAX] = { + { + cfa_tcam_mgr_L2_CTXT_TCAM_RX_row_data[0], + cfa_tcam_mgr_L2_CTXT_TCAM_RX_row_data[0], + cfa_tcam_mgr_PROF_TCAM_RX_row_data[0], + cfa_tcam_mgr_WC_TCAM_RX_row_data[0], + cfa_tcam_mgr_SP_TCAM_RX_row_data[0], + cfa_tcam_mgr_CT_RULE_TCAM_RX_row_data[0], + cfa_tcam_mgr_VEB_TCAM_RX_row_data[0], + cfa_tcam_mgr_WC_TCAM_RX_row_data[0], + cfa_tcam_mgr_WC_TCAM_RX_row_data[0], + }, + { + cfa_tcam_mgr_L2_CTXT_TCAM_TX_row_data[0], + cfa_tcam_mgr_L2_CTXT_TCAM_TX_row_data[0], + cfa_tcam_mgr_PROF_TCAM_TX_row_data[0], + cfa_tcam_mgr_WC_TCAM_TX_row_data[0], + cfa_tcam_mgr_SP_TCAM_TX_row_data[0], + cfa_tcam_mgr_CT_RULE_TCAM_TX_row_data[0], + cfa_tcam_mgr_VEB_TCAM_TX_row_data[0], + cfa_tcam_mgr_WC_TCAM_TX_row_data[0], + cfa_tcam_mgr_WC_TCAM_TX_row_data[0], + } +}; + +static int cfa_tcam_mgr_get_max_rows(enum tf_tcam_tbl_type type) +{ + if (type >= TF_TCAM_TBL_TYPE_MAX) + assert(0); + else + return cfa_tcam_mgr_max_rows[type]; +} + +static int cfa_tcam_mgr_hwop_set(int sess_idx, + struct cfa_tcam_mgr_set_parms *parms, int row, + int slice, int max_slices) +{ + struct cfa_tcam_mgr_TCAM_row_data *this_table; + struct cfa_tcam_mgr_TCAM_row_data *this_row; + this_table = row_tables[parms->dir] + [cfa_tcam_mgr_get_phys_table_type(parms->type)]; + this_table += (sess_idx * + cfa_tcam_mgr_get_max_rows(cfa_tcam_mgr_get_phys_table_type(parms->type))); + this_row = &this_table[row * max_slices + slice]; + this_row->key_size = parms->key_size; + memcpy(&this_row->key, parms->key, parms->key_size); + memcpy(&this_row->mask, parms->mask, parms->key_size); + this_row->result_size = parms->result_size; + if (parms->result != ((void *)0)) + memcpy(&this_row->result, parms->result, parms->result_size); + return 0; +}; + +static int cfa_tcam_mgr_hwop_get(int sess_idx, + struct cfa_tcam_mgr_get_parms *parms, int row, + int slice, int max_slices) +{ + struct cfa_tcam_mgr_TCAM_row_data *this_table; + struct cfa_tcam_mgr_TCAM_row_data *this_row; + this_table = row_tables[parms->dir] + [cfa_tcam_mgr_get_phys_table_type(parms->type)]; + this_table += (sess_idx * + cfa_tcam_mgr_get_max_rows(cfa_tcam_mgr_get_phys_table_type(parms->type))); + this_row = &this_table[row * max_slices + slice]; + parms->key_size = this_row->key_size; + parms->result_size = this_row->result_size; + if (parms->key != ((void *)0)) + memcpy(parms->key, &this_row->key, parms->key_size); + if (parms->mask != ((void *)0)) + memcpy(parms->mask, &this_row->mask, parms->key_size); + if (parms->result != ((void *)0)) + memcpy(parms->result, &this_row->result, parms->result_size); + return 0; +}; + +static int cfa_tcam_mgr_hwop_free(int sess_idx, + struct cfa_tcam_mgr_free_parms *parms, + int row, int slice, int max_slices) +{ + struct cfa_tcam_mgr_TCAM_row_data *this_table; + struct cfa_tcam_mgr_TCAM_row_data *this_row; + this_table = row_tables[parms->dir] + [cfa_tcam_mgr_get_phys_table_type(parms->type)]; + this_table += (sess_idx * + cfa_tcam_mgr_get_max_rows(cfa_tcam_mgr_get_phys_table_type(parms->type))); + this_row = &this_table[row * max_slices + slice]; + memset(&this_row->key, 0, sizeof(this_row->key)); + memset(&this_row->mask, 0, sizeof(this_row->mask)); + memset(&this_row->result, 0, sizeof(this_row->result)); + this_row->key_size = 0; + this_row->result_size = 0; + return 0; +}; + +int cfa_tcam_mgr_hwops_get_funcs_p4(struct cfa_tcam_mgr_hwops_funcs *hwop_funcs) +{ + hwop_funcs->set = cfa_tcam_mgr_hwop_set; + hwop_funcs->get = cfa_tcam_mgr_hwop_get; + hwop_funcs->free = cfa_tcam_mgr_hwop_free; + return 0; +} diff --git a/drivers/net/bnxt/tf_core/cfa_tcam_mgr_p4.h b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_p4.h new file mode 100644 index 0000000000..3ca59b2aeb --- /dev/null +++ b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_p4.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021-2023 Broadcom + * All rights reserved. + */ + +#ifndef CFA_TCAM_MGR_P4_H +#define CFA_TCAM_MGR_P4_H + +#include "cfa_tcam_mgr_device.h" +#include "cfa_tcam_mgr_sbmp.h" + +int +cfa_tcam_mgr_init_p4(int sess_idx, struct cfa_tcam_mgr_entry_data **global_entry_data); + +int +cfa_tcam_mgr_sess_table_get_p4(int sess_idx, struct sbmp **session_bmp); + +int +cfa_tcam_mgr_hwops_get_funcs_p4(struct cfa_tcam_mgr_hwops_funcs *hwop_funcs); +#endif /* CFA_TCAM_MGR_P4_H */ diff --git a/drivers/net/bnxt/tf_core/cfa_tcam_mgr_p58.c b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_p58.c new file mode 100644 index 0000000000..c9a04dc4e9 --- /dev/null +++ b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_p58.c @@ -0,0 +1,926 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021-2023 Broadcom + * All rights reserved. + */ + +#include "hcapi_cfa_defs.h" + +#include "cfa_tcam_mgr.h" +#include "cfa_tcam_mgr_p58.h" +#include "cfa_tcam_mgr.h" +#include "cfa_tcam_mgr_device.h" +#include "cfa_resource_types.h" +#include "tfp.h" +#include "assert.h" +#include "tf_util.h" + +/* + * Sizings of the TCAMs on P5 + */ + +#define MAX_ROW_WIDTH 96 +#define MAX_RESULT_SIZE 8 + +#if MAX_ROW_WIDTH > CFA_TCAM_MGR_MAX_KEY_SIZE +#error MAX_ROW_WIDTH > CFA_TCAM_MGR_MAX_KEY_SIZE +#endif + +/* + * TCAM definitions + * + * These define the TCAMs in HW. + * + * Note: Set xxx_TCAM_[R|T]X_NUM_ROWS to zero if a TCAM is either not supported + * by HW or not supported by TCAM Manager. + */ + +/** L2 Context TCAM */ +#define L2_CTXT_TCAM_RX_MAX_SLICES 1 +#define L2_CTXT_TCAM_RX_ROW_WIDTH TF_BITS2BYTES_64B_WORD_ALIGN(214) +#define L2_CTXT_TCAM_RX_NUM_ROWS 1024 +#define L2_CTXT_TCAM_RX_MAX_ENTRIES (L2_CTXT_TCAM_RX_MAX_SLICES * \ + L2_CTXT_TCAM_RX_NUM_ROWS) +#define L2_CTXT_TCAM_RX_RESULT_SIZE 8 + +#define L2_CTXT_TCAM_TX_MAX_SLICES L2_CTXT_TCAM_RX_MAX_SLICES +#define L2_CTXT_TCAM_TX_ROW_WIDTH L2_CTXT_TCAM_RX_ROW_WIDTH +#define L2_CTXT_TCAM_TX_NUM_ROWS L2_CTXT_TCAM_RX_NUM_ROWS +#define L2_CTXT_TCAM_TX_MAX_ENTRIES L2_CTXT_TCAM_RX_MAX_ENTRIES +#define L2_CTXT_TCAM_TX_RESULT_SIZE L2_CTXT_TCAM_RX_RESULT_SIZE + +/** Profile TCAM */ +#define PROF_TCAM_RX_MAX_SLICES 1 +#define PROF_TCAM_RX_ROW_WIDTH TF_BITS2BYTES_64B_WORD_ALIGN(94) +#define PROF_TCAM_RX_NUM_ROWS 256 +#define PROF_TCAM_RX_MAX_ENTRIES (PROF_TCAM_RX_MAX_SLICES * \ + PROF_TCAM_RX_NUM_ROWS) +#define PROF_TCAM_RX_RESULT_SIZE 8 + +#define PROF_TCAM_TX_MAX_SLICES PROF_TCAM_RX_MAX_SLICES +#define PROF_TCAM_TX_ROW_WIDTH PROF_TCAM_RX_ROW_WIDTH +#define PROF_TCAM_TX_NUM_ROWS PROF_TCAM_RX_NUM_ROWS +#define PROF_TCAM_TX_MAX_ENTRIES PROF_TCAM_RX_MAX_ENTRIES +#define PROF_TCAM_TX_RESULT_SIZE PROF_TCAM_RX_RESULT_SIZE + +/** Wildcard TCAM */ +#define WC_TCAM_RX_MAX_SLICES 4 +/* 162 bits per slice */ +#define WC_TCAM_RX_ROW_WIDTH (TF_BITS2BYTES_64B_WORD_ALIGN(162) * \ + WC_TCAM_RX_MAX_SLICES) +#define WC_TCAM_RX_NUM_ROWS 2048 +#define WC_TCAM_RX_MAX_ENTRIES (WC_TCAM_RX_MAX_SLICES * WC_TCAM_RX_NUM_ROWS) +#define WC_TCAM_RX_RESULT_SIZE 8 + +#define WC_TCAM_TX_MAX_SLICES WC_TCAM_RX_MAX_SLICES +#define WC_TCAM_TX_ROW_WIDTH WC_TCAM_RX_ROW_WIDTH +#define WC_TCAM_TX_NUM_ROWS WC_TCAM_RX_NUM_ROWS +#define WC_TCAM_TX_MAX_ENTRIES WC_TCAM_RX_MAX_ENTRIES +#define WC_TCAM_TX_RESULT_SIZE WC_TCAM_RX_RESULT_SIZE + +/** Source Properties TCAM */ +#define SP_TCAM_RX_MAX_SLICES 1 +#define SP_TCAM_RX_ROW_WIDTH TF_BITS2BYTES_64B_WORD_ALIGN(89) +#define SP_TCAM_RX_NUM_ROWS 0 +#define SP_TCAM_RX_MAX_ENTRIES (SP_TCAM_RX_MAX_SLICES * SP_TCAM_RX_NUM_ROWS) +#define SP_TCAM_RX_RESULT_SIZE 8 + +#define SP_TCAM_TX_MAX_SLICES SP_TCAM_RX_MAX_SLICES +#define SP_TCAM_TX_ROW_WIDTH SP_TCAM_RX_ROW_WIDTH +#define SP_TCAM_TX_NUM_ROWS SP_TCAM_RX_NUM_ROWS +#define SP_TCAM_TX_MAX_ENTRIES SP_TCAM_RX_MAX_ENTRIES +#define SP_TCAM_TX_RESULT_SIZE SP_TCAM_RX_RESULT_SIZE + +/** Connection Tracking Rule TCAM */ +#define CT_RULE_TCAM_RX_MAX_SLICES 1 +#define CT_RULE_TCAM_RX_ROW_WIDTH TF_BITS2BYTES_64B_WORD_ALIGN(16) +#define CT_RULE_TCAM_RX_NUM_ROWS 0 +#define CT_RULE_TCAM_RX_MAX_ENTRIES (CT_RULE_TCAM_RX_MAX_SLICES * \ + CT_RULE_TCAM_RX_NUM_ROWS) +#define CT_RULE_TCAM_RX_RESULT_SIZE 8 + +#define CT_RULE_TCAM_TX_MAX_SLICES CT_RULE_TCAM_RX_MAX_SLICES +#define CT_RULE_TCAM_TX_ROW_WIDTH CT_RULE_TCAM_RX_ROW_WIDTH +#define CT_RULE_TCAM_TX_NUM_ROWS CT_RULE_TCAM_RX_NUM_ROWS +#define CT_RULE_TCAM_TX_MAX_ENTRIES CT_RULE_TCAM_RX_MAX_ENTRIES +#define CT_RULE_TCAM_TX_RESULT_SIZE CT_RULE_TCAM_RX_RESULT_SIZE + +/** Virtual Edge Bridge TCAM */ +#define VEB_TCAM_RX_MAX_SLICES 1 +#define VEB_TCAM_RX_ROW_WIDTH TF_BITS2BYTES_WORD_ALIGN(79) +/* Tx only */ +#define VEB_TCAM_RX_NUM_ROWS 0 +#define VEB_TCAM_RX_MAX_ENTRIES (VEB_TCAM_RX_MAX_SLICES * VEB_TCAM_RX_NUM_ROWS) +#define VEB_TCAM_RX_RESULT_SIZE 8 + +#define VEB_TCAM_TX_MAX_SLICES VEB_TCAM_RX_MAX_SLICES +#define VEB_TCAM_TX_ROW_WIDTH VEB_TCAM_RX_ROW_WIDTH +#define VEB_TCAM_TX_NUM_ROWS 1024 +#define VEB_TCAM_TX_MAX_ENTRIES (VEB_TCAM_TX_MAX_SLICES * VEB_TCAM_TX_NUM_ROWS) +#define VEB_TCAM_TX_RESULT_SIZE VEB_TCAM_RX_RESULT_SIZE + +/* Declare the table rows for each table here. If new tables are added to the + * enum tf_tcam_tbl_type, then new declarations will be needed here. + * + * The numeric suffix of the structure type indicates how many slices a + * particular TCAM supports. + * + * Array sizes have 1 added to avoid zero length arrays. + */ + +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_RX[TF_TCAM_MAX_SESSIONS][L2_CTXT_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_TX[TF_TCAM_MAX_SESSIONS][L2_CTXT_TCAM_TX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_PROF_TCAM_RX[TF_TCAM_MAX_SESSIONS][PROF_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_PROF_TCAM_TX[TF_TCAM_MAX_SESSIONS][PROF_TCAM_TX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_4 + cfa_tcam_mgr_table_rows_WC_TCAM_RX[TF_TCAM_MAX_SESSIONS][WC_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_4 + cfa_tcam_mgr_table_rows_WC_TCAM_TX[TF_TCAM_MAX_SESSIONS][WC_TCAM_TX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_SP_TCAM_RX[TF_TCAM_MAX_SESSIONS][SP_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_SP_TCAM_TX[TF_TCAM_MAX_SESSIONS][SP_TCAM_TX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_CT_RULE_TCAM_RX[TF_TCAM_MAX_SESSIONS][CT_RULE_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_CT_RULE_TCAM_TX[TF_TCAM_MAX_SESSIONS][CT_RULE_TCAM_TX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_VEB_TCAM_RX[TF_TCAM_MAX_SESSIONS][VEB_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_1 + cfa_tcam_mgr_table_rows_VEB_TCAM_TX[TF_TCAM_MAX_SESSIONS][VEB_TCAM_TX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_4 + cfa_tcam_mgr_table_rows_WC_TCAM_RX_HIGH[TF_TCAM_MAX_SESSIONS][WC_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_4 + cfa_tcam_mgr_table_rows_WC_TCAM_RX_LOW[TF_TCAM_MAX_SESSIONS][WC_TCAM_RX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_4 + cfa_tcam_mgr_table_rows_WC_TCAM_TX_HIGH[TF_TCAM_MAX_SESSIONS][WC_TCAM_TX_NUM_ROWS + 1]; +static struct cfa_tcam_mgr_table_rows_4 + cfa_tcam_mgr_table_rows_WC_TCAM_TX_LOW[TF_TCAM_MAX_SESSIONS][WC_TCAM_TX_NUM_ROWS + 1]; + +struct cfa_tcam_mgr_table_data +cfa_tcam_mgr_tables_p58[TF_DIR_MAX][CFA_TCAM_MGR_TBL_TYPE_MAX] = { + { /* RX */ + { /* High AFM */ + .max_slices = L2_CTXT_TCAM_RX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_RX_ROW_WIDTH, + .num_rows = 0, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = L2_CTXT_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_L2_CTXT_TCAM_HIGH, + }, + { /* High APPS */ + .max_slices = L2_CTXT_TCAM_RX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_RX_ROW_WIDTH, + .num_rows = L2_CTXT_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = (L2_CTXT_TCAM_RX_NUM_ROWS / 2) - 1, + .max_entries = (L2_CTXT_TCAM_RX_MAX_ENTRIES / 2), + .result_size = L2_CTXT_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_L2_CTXT_TCAM_HIGH, + }, + { /* Low AFM */ + .max_slices = L2_CTXT_TCAM_RX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_RX_ROW_WIDTH, + .num_rows = 0, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = L2_CTXT_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_L2_CTXT_TCAM_LOW, + }, + { /* Low APPS */ + .max_slices = L2_CTXT_TCAM_RX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_RX_ROW_WIDTH, + .num_rows = L2_CTXT_TCAM_RX_NUM_ROWS, + .start_row = (L2_CTXT_TCAM_RX_NUM_ROWS / 2), + .end_row = L2_CTXT_TCAM_RX_NUM_ROWS - 1, + .max_entries = (L2_CTXT_TCAM_RX_MAX_ENTRIES / 2), + .result_size = L2_CTXT_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_L2_CTXT_TCAM_LOW, + }, + { /* AFM */ + .max_slices = PROF_TCAM_RX_MAX_SLICES, + .row_width = PROF_TCAM_RX_ROW_WIDTH, + .num_rows = 0, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = PROF_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_PROF_TCAM, + }, + { /* APPS */ + .max_slices = PROF_TCAM_RX_MAX_SLICES, + .row_width = PROF_TCAM_RX_ROW_WIDTH, + .num_rows = PROF_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = PROF_TCAM_RX_NUM_ROWS - 1, + .max_entries = PROF_TCAM_RX_MAX_ENTRIES, + .result_size = PROF_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_PROF_TCAM, + }, + { /* AFM */ + .max_slices = WC_TCAM_RX_MAX_SLICES, + .row_width = WC_TCAM_RX_ROW_WIDTH, + .num_rows = WC_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = WC_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_WC_TCAM, + }, + { /* APPS */ + .max_slices = WC_TCAM_RX_MAX_SLICES, + .row_width = WC_TCAM_RX_ROW_WIDTH, + .num_rows = WC_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = WC_TCAM_RX_NUM_ROWS - 1, + .max_entries = WC_TCAM_RX_MAX_ENTRIES, + .result_size = WC_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_WC_TCAM, + }, + { /* AFM */ + .max_slices = SP_TCAM_RX_MAX_SLICES, + .row_width = SP_TCAM_RX_ROW_WIDTH, + .num_rows = 0, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = SP_TCAM_RX_RESULT_SIZE, + }, + { /* APPS */ + .max_slices = SP_TCAM_RX_MAX_SLICES, + .row_width = SP_TCAM_RX_ROW_WIDTH, + .num_rows = SP_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = SP_TCAM_RX_NUM_ROWS - 1, + .max_entries = SP_TCAM_RX_MAX_ENTRIES, + .result_size = SP_TCAM_RX_RESULT_SIZE, + }, + { /* AFM */ + .max_slices = CT_RULE_TCAM_RX_MAX_SLICES, + .row_width = CT_RULE_TCAM_RX_ROW_WIDTH, + .num_rows = CT_RULE_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = CT_RULE_TCAM_RX_RESULT_SIZE, + }, + { /* APPS */ + .max_slices = CT_RULE_TCAM_RX_MAX_SLICES, + .row_width = CT_RULE_TCAM_RX_ROW_WIDTH, + .num_rows = CT_RULE_TCAM_RX_NUM_ROWS, + .start_row = 0, +#if CT_RULE_TCAM_RX_NUM_ROWS > 0 + .end_row = CT_RULE_TCAM_RX_NUM_ROWS - 1, +#else + .end_row = CT_RULE_TCAM_RX_NUM_ROWS, +#endif + .max_entries = CT_RULE_TCAM_RX_MAX_ENTRIES, + .result_size = CT_RULE_TCAM_RX_RESULT_SIZE, + }, + { /* AFM */ + .max_slices = VEB_TCAM_RX_MAX_SLICES, + .row_width = VEB_TCAM_RX_ROW_WIDTH, + .num_rows = VEB_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = VEB_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_VEB_TCAM, + }, + { /* APPS */ + .max_slices = VEB_TCAM_RX_MAX_SLICES, + .row_width = VEB_TCAM_RX_ROW_WIDTH, + .num_rows = VEB_TCAM_RX_NUM_ROWS, + .start_row = 0, +#if VEB_TCAM_RX_NUM_ROWS > 0 + .end_row = VEB_TCAM_RX_NUM_ROWS - 1, +#else + .end_row = VEB_TCAM_RX_NUM_ROWS, +#endif + .max_entries = VEB_TCAM_RX_MAX_ENTRIES, + .result_size = VEB_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_VEB_TCAM, + }, + { /* AFM */ + .max_slices = WC_TCAM_RX_MAX_SLICES, + .row_width = WC_TCAM_RX_ROW_WIDTH, + .num_rows = WC_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = WC_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_WC_TCAM, + }, + { /* APPS */ + .max_slices = WC_TCAM_RX_MAX_SLICES, + .row_width = WC_TCAM_RX_ROW_WIDTH, + .num_rows = WC_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = WC_TCAM_RX_NUM_ROWS - 1, + .max_entries = WC_TCAM_RX_MAX_ENTRIES, + .result_size = WC_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_WC_TCAM, + }, + { /* AFM */ + .max_slices = WC_TCAM_RX_MAX_SLICES, + .row_width = WC_TCAM_RX_ROW_WIDTH, + .num_rows = WC_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = WC_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_WC_TCAM, + }, + { /* APPS */ + .max_slices = WC_TCAM_RX_MAX_SLICES, + .row_width = WC_TCAM_RX_ROW_WIDTH, + .num_rows = WC_TCAM_RX_NUM_ROWS, + .start_row = 0, + .end_row = WC_TCAM_RX_NUM_ROWS - 1, + .max_entries = WC_TCAM_RX_MAX_ENTRIES, + .result_size = WC_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_WC_TCAM, + }, + }, + { /* TX */ + { /* AFM */ + .max_slices = L2_CTXT_TCAM_TX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_TX_ROW_WIDTH, + .num_rows = L2_CTXT_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = L2_CTXT_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_L2_CTXT_TCAM_HIGH, + }, + { /* APPS */ + .max_slices = L2_CTXT_TCAM_TX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_TX_ROW_WIDTH, + .num_rows = L2_CTXT_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = (L2_CTXT_TCAM_TX_NUM_ROWS / 2) - 1, + .max_entries = (L2_CTXT_TCAM_TX_MAX_ENTRIES / 2), + .result_size = L2_CTXT_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_L2_CTXT_TCAM_HIGH, + }, + { /* AFM */ + .max_slices = L2_CTXT_TCAM_TX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_TX_ROW_WIDTH, + .num_rows = L2_CTXT_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = L2_CTXT_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_L2_CTXT_TCAM_LOW, + }, + { /* APPS */ + .max_slices = L2_CTXT_TCAM_TX_MAX_SLICES, + .row_width = L2_CTXT_TCAM_TX_ROW_WIDTH, + .num_rows = L2_CTXT_TCAM_TX_NUM_ROWS, + .start_row = (L2_CTXT_TCAM_TX_NUM_ROWS / 2), + .end_row = L2_CTXT_TCAM_TX_NUM_ROWS - 1, + .max_entries = (L2_CTXT_TCAM_TX_MAX_ENTRIES / 2), + .result_size = L2_CTXT_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_L2_CTXT_TCAM_LOW, + }, + { /* AFM */ + .max_slices = PROF_TCAM_TX_MAX_SLICES, + .row_width = PROF_TCAM_TX_ROW_WIDTH, + .num_rows = PROF_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = PROF_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_PROF_TCAM, + }, + { /* APPS */ + .max_slices = PROF_TCAM_TX_MAX_SLICES, + .row_width = PROF_TCAM_TX_ROW_WIDTH, + .num_rows = PROF_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = PROF_TCAM_TX_NUM_ROWS - 1, + .max_entries = PROF_TCAM_TX_MAX_ENTRIES, + .result_size = PROF_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_PROF_TCAM, + }, + { /* AFM */ + .max_slices = WC_TCAM_TX_MAX_SLICES, + .row_width = WC_TCAM_TX_ROW_WIDTH, + .num_rows = WC_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = WC_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_WC_TCAM, + }, + { /* APPS */ + .max_slices = WC_TCAM_TX_MAX_SLICES, + .row_width = WC_TCAM_TX_ROW_WIDTH, + .num_rows = WC_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = WC_TCAM_TX_NUM_ROWS - 1, + .max_entries = WC_TCAM_TX_MAX_ENTRIES, + .result_size = WC_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_WC_TCAM, + }, + { /* AFM */ + .max_slices = SP_TCAM_TX_MAX_SLICES, + .row_width = SP_TCAM_TX_ROW_WIDTH, + .num_rows = SP_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = SP_TCAM_TX_RESULT_SIZE, + }, + { /* APPS */ + .max_slices = SP_TCAM_TX_MAX_SLICES, + .row_width = SP_TCAM_TX_ROW_WIDTH, + .num_rows = SP_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = SP_TCAM_TX_NUM_ROWS - 1, + .max_entries = SP_TCAM_TX_MAX_ENTRIES, + .result_size = SP_TCAM_TX_RESULT_SIZE, + }, + { /* AFM */ + .max_slices = CT_RULE_TCAM_TX_MAX_SLICES, + .row_width = CT_RULE_TCAM_TX_ROW_WIDTH, + .num_rows = CT_RULE_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = CT_RULE_TCAM_RX_RESULT_SIZE, + }, + { /* APPS */ + .max_slices = CT_RULE_TCAM_TX_MAX_SLICES, + .row_width = CT_RULE_TCAM_TX_ROW_WIDTH, + .num_rows = CT_RULE_TCAM_TX_NUM_ROWS, + .start_row = 0, +#if CT_RULE_TCAM_TX_NUM_ROWS > 0 + .end_row = CT_RULE_TCAM_TX_NUM_ROWS - 1, +#else + .end_row = CT_RULE_TCAM_TX_NUM_ROWS, +#endif + .max_entries = CT_RULE_TCAM_TX_MAX_ENTRIES, + .result_size = CT_RULE_TCAM_RX_RESULT_SIZE, + }, + { /* AFM */ + .max_slices = VEB_TCAM_TX_MAX_SLICES, + .row_width = VEB_TCAM_TX_ROW_WIDTH, + .num_rows = VEB_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = VEB_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_VEB_TCAM, + }, + { /* APPS */ + .max_slices = VEB_TCAM_TX_MAX_SLICES, + .row_width = VEB_TCAM_TX_ROW_WIDTH, + .num_rows = VEB_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = VEB_TCAM_TX_NUM_ROWS - 1, + .max_entries = VEB_TCAM_TX_MAX_ENTRIES, + .result_size = VEB_TCAM_RX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_VEB_TCAM, + }, + { /* AFM */ + .max_slices = WC_TCAM_TX_MAX_SLICES, + .row_width = WC_TCAM_TX_ROW_WIDTH, + .num_rows = WC_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = WC_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_WC_TCAM, + }, + { /* APPS */ + .max_slices = WC_TCAM_TX_MAX_SLICES, + .row_width = WC_TCAM_TX_ROW_WIDTH, + .num_rows = WC_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = WC_TCAM_TX_NUM_ROWS - 1, + .max_entries = WC_TCAM_TX_MAX_ENTRIES, + .result_size = WC_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_WC_TCAM, + }, + { /* AFM */ + .max_slices = WC_TCAM_TX_MAX_SLICES, + .row_width = WC_TCAM_TX_ROW_WIDTH, + .num_rows = WC_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = 0, + .max_entries = 0, + .result_size = WC_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_WC_TCAM, + }, + { /* APPS */ + .max_slices = WC_TCAM_TX_MAX_SLICES, + .row_width = WC_TCAM_TX_ROW_WIDTH, + .num_rows = WC_TCAM_TX_NUM_ROWS, + .start_row = 0, + .end_row = WC_TCAM_TX_NUM_ROWS - 1, + .max_entries = WC_TCAM_TX_MAX_ENTRIES, + .result_size = WC_TCAM_TX_RESULT_SIZE, + .hcapi_type = CFA_RESOURCE_TYPE_P58_WC_TCAM, + }, + }, +}; + +static struct cfa_tcam_mgr_entry_data entry_data_p58[TF_TCAM_MAX_SESSIONS][TF_TCAM_MAX_ENTRIES]; + +static struct sbmp session_bmp_p58[TF_TCAM_MAX_SESSIONS][TF_TCAM_MAX_ENTRIES]; + +int +cfa_tcam_mgr_sess_table_get_p58(int sess_idx, struct sbmp **session_bmp) +{ + *session_bmp = session_bmp_p58[sess_idx]; + return 0; +} + +int +cfa_tcam_mgr_init_p58(int sess_idx, struct cfa_tcam_mgr_entry_data **global_entry_data) +{ + int max_row_width = 0; + int max_result_size = 0; + int dir, type; + + *global_entry_data = entry_data_p58[sess_idx]; + + memcpy(&cfa_tcam_mgr_tables[sess_idx], + &cfa_tcam_mgr_tables_p58, + sizeof(cfa_tcam_mgr_tables[sess_idx])); + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_RX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_RX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_TX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_RX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_RX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_L2_CTXT_TCAM_TX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_PROF_TCAM_RX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_PROF_TCAM_RX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_PROF_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_PROF_TCAM_TX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_RX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_RX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_TX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_SP_TCAM_RX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_SP_TCAM_RX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_SP_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_SP_TCAM_TX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_CT_RULE_TCAM_RX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_CT_RULE_TCAM_RX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_CT_RULE_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_CT_RULE_TCAM_TX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_VEB_TCAM_RX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_VEB_TCAM_RX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_VEB_TCAM_TX[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_VEB_TCAM_TX[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_RX_HIGH[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_RX_HIGH[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_TX_HIGH[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_TX_HIGH[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_RX_LOW[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_RX_LOW[sess_idx]; + + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_AFM].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_TX_LOW[sess_idx]; + cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX] + [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS].tcam_rows = + (struct cfa_tcam_mgr_table_rows_0 *) + &cfa_tcam_mgr_table_rows_WC_TCAM_TX_LOW[sess_idx]; + + for (dir = 0; dir < TF_DIR_MAX; dir++) { + for (type = 0; type < CFA_TCAM_MGR_TBL_TYPE_MAX; type++) { + if (cfa_tcam_mgr_tables[sess_idx][dir][type].row_width > + max_row_width) + max_row_width = + cfa_tcam_mgr_tables[sess_idx][dir][type].row_width; + if (cfa_tcam_mgr_tables[sess_idx][dir][type].result_size > + max_result_size) + max_result_size = + cfa_tcam_mgr_tables[sess_idx][dir][type].result_size; + } + } + + if (max_row_width != MAX_ROW_WIDTH) { + CFA_TCAM_MGR_LOG(ERR, + "MAX_ROW_WIDTH (%d) does not match actual " + "value (%d).\n", + MAX_ROW_WIDTH, + max_row_width); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + if (max_result_size != MAX_RESULT_SIZE) { + CFA_TCAM_MGR_LOG(ERR, + "MAX_RESULT_SIZE (%d) does not match actual " + "value (%d).\n", + MAX_RESULT_SIZE, + max_result_size); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + return 0; +} + +/* HW OP declarations begin here */ + +struct cfa_tcam_mgr_TCAM_row_data { + int key_size; + int result_size; + uint8_t key[MAX_ROW_WIDTH]; + uint8_t mask[MAX_ROW_WIDTH]; + uint8_t result[MAX_RESULT_SIZE]; +}; + +/* These macros are only needed to avoid exceeding 80 columns */ +#define L2_CTXT_RX_MAX_ROWS \ + (L2_CTXT_TCAM_RX_MAX_SLICES * L2_CTXT_TCAM_RX_NUM_ROWS) +#define PROF_RX_MAX_ROWS (PROF_TCAM_RX_MAX_SLICES * PROF_TCAM_RX_NUM_ROWS) +#define WC_RX_MAX_ROWS (WC_TCAM_RX_MAX_SLICES * WC_TCAM_RX_NUM_ROWS) +#define SP_RX_MAX_ROWS (SP_TCAM_RX_MAX_SLICES * SP_TCAM_RX_NUM_ROWS) +#define CT_RULE_RX_MAX_ROWS \ + (CT_RULE_TCAM_RX_MAX_SLICES * CT_RULE_TCAM_RX_NUM_ROWS) +#define VEB_RX_MAX_ROWS (VEB_TCAM_RX_MAX_SLICES * VEB_TCAM_RX_NUM_ROWS) + +#define L2_CTXT_TX_MAX_ROWS \ + (L2_CTXT_TCAM_TX_MAX_SLICES * L2_CTXT_TCAM_TX_NUM_ROWS) +#define PROF_TX_MAX_ROWS (PROF_TCAM_TX_MAX_SLICES * PROF_TCAM_TX_NUM_ROWS) +#define WC_TX_MAX_ROWS (WC_TCAM_TX_MAX_SLICES * WC_TCAM_TX_NUM_ROWS) +#define SP_TX_MAX_ROWS (SP_TCAM_TX_MAX_SLICES * SP_TCAM_TX_NUM_ROWS) +#define CT_RULE_TX_MAX_ROWS \ + (CT_RULE_TCAM_TX_MAX_SLICES * CT_RULE_TCAM_TX_NUM_ROWS) +#define VEB_TX_MAX_ROWS (VEB_TCAM_TX_MAX_SLICES * VEB_TCAM_TX_NUM_ROWS) + +static int cfa_tcam_mgr_max_rows[TF_TCAM_TBL_TYPE_MAX] = { + L2_CTXT_RX_MAX_ROWS, + L2_CTXT_RX_MAX_ROWS, + PROF_RX_MAX_ROWS, + WC_RX_MAX_ROWS, + SP_RX_MAX_ROWS, + CT_RULE_RX_MAX_ROWS, + VEB_RX_MAX_ROWS, + WC_RX_MAX_ROWS, + WC_RX_MAX_ROWS +}; + +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_L2_CTXT_TCAM_RX_row_data[TF_TCAM_MAX_SESSIONS][L2_CTXT_RX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_PROF_TCAM_RX_row_data[TF_TCAM_MAX_SESSIONS][PROF_RX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_WC_TCAM_RX_row_data[TF_TCAM_MAX_SESSIONS][WC_RX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_SP_TCAM_RX_row_data[TF_TCAM_MAX_SESSIONS][SP_RX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_CT_RULE_TCAM_RX_row_data[TF_TCAM_MAX_SESSIONS][CT_RULE_RX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_VEB_TCAM_RX_row_data[TF_TCAM_MAX_SESSIONS][VEB_RX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_WC_TCAM_RX_row_data[TF_TCAM_MAX_SESSIONS][WC_RX_MAX_ROWS]; + +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_L2_CTXT_TCAM_TX_row_data[TF_TCAM_MAX_SESSIONS][L2_CTXT_TX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_PROF_TCAM_TX_row_data[TF_TCAM_MAX_SESSIONS][PROF_TX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_WC_TCAM_TX_row_data[TF_TCAM_MAX_SESSIONS][WC_TX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_SP_TCAM_TX_row_data[TF_TCAM_MAX_SESSIONS][SP_TX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_CT_RULE_TCAM_TX_row_data[TF_TCAM_MAX_SESSIONS][CT_RULE_TX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_VEB_TCAM_TX_row_data[TF_TCAM_MAX_SESSIONS][VEB_TX_MAX_ROWS]; +static struct cfa_tcam_mgr_TCAM_row_data + cfa_tcam_mgr_WC_TCAM_TX_row_data[TF_TCAM_MAX_SESSIONS][WC_TX_MAX_ROWS]; + +static struct cfa_tcam_mgr_TCAM_row_data * +row_tables[TF_DIR_MAX][TF_TCAM_TBL_TYPE_MAX] = { + { + cfa_tcam_mgr_L2_CTXT_TCAM_RX_row_data[0], + cfa_tcam_mgr_L2_CTXT_TCAM_RX_row_data[0], + cfa_tcam_mgr_PROF_TCAM_RX_row_data[0], + cfa_tcam_mgr_WC_TCAM_RX_row_data[0], + cfa_tcam_mgr_SP_TCAM_RX_row_data[0], + cfa_tcam_mgr_CT_RULE_TCAM_RX_row_data[0], + cfa_tcam_mgr_VEB_TCAM_RX_row_data[0], + cfa_tcam_mgr_WC_TCAM_RX_row_data[0], + cfa_tcam_mgr_WC_TCAM_RX_row_data[0], + }, + { + cfa_tcam_mgr_L2_CTXT_TCAM_TX_row_data[0], + cfa_tcam_mgr_L2_CTXT_TCAM_TX_row_data[0], + cfa_tcam_mgr_PROF_TCAM_TX_row_data[0], + cfa_tcam_mgr_WC_TCAM_TX_row_data[0], + cfa_tcam_mgr_SP_TCAM_TX_row_data[0], + cfa_tcam_mgr_CT_RULE_TCAM_TX_row_data[0], + cfa_tcam_mgr_VEB_TCAM_TX_row_data[0], + cfa_tcam_mgr_WC_TCAM_TX_row_data[0], + cfa_tcam_mgr_WC_TCAM_TX_row_data[0], + } +}; + +static int cfa_tcam_mgr_get_max_rows(enum tf_tcam_tbl_type type) +{ + if (type >= TF_TCAM_TBL_TYPE_MAX) + assert(0); + else + return cfa_tcam_mgr_max_rows[type]; +} + +static int cfa_tcam_mgr_hwop_set(int sess_idx, + struct cfa_tcam_mgr_set_parms *parms, int row, + int slice, int max_slices) +{ + struct cfa_tcam_mgr_TCAM_row_data *this_table; + struct cfa_tcam_mgr_TCAM_row_data *this_row; + this_table = row_tables[parms->dir] + [cfa_tcam_mgr_get_phys_table_type(parms->type)]; + this_table += (sess_idx * + cfa_tcam_mgr_get_max_rows(cfa_tcam_mgr_get_phys_table_type(parms->type))); + this_row = &this_table[row * max_slices + slice]; + this_row->key_size = parms->key_size; + memcpy(&this_row->key, parms->key, parms->key_size); + memcpy(&this_row->mask, parms->mask, parms->key_size); + this_row->result_size = parms->result_size; + if (parms->result != ((void *)0)) + memcpy(&this_row->result, parms->result, parms->result_size); + return 0; +}; + +static int cfa_tcam_mgr_hwop_get(int sess_idx, + struct cfa_tcam_mgr_get_parms *parms, int row, + int slice, int max_slices) +{ + struct cfa_tcam_mgr_TCAM_row_data *this_table; + struct cfa_tcam_mgr_TCAM_row_data *this_row; + this_table = row_tables[parms->dir] + [cfa_tcam_mgr_get_phys_table_type(parms->type)]; + this_table += (sess_idx * + cfa_tcam_mgr_get_max_rows(cfa_tcam_mgr_get_phys_table_type(parms->type))); + this_row = &this_table[row * max_slices + slice]; + parms->key_size = this_row->key_size; + parms->result_size = this_row->result_size; + if (parms->key != ((void *)0)) + memcpy(parms->key, &this_row->key, parms->key_size); + if (parms->mask != ((void *)0)) + memcpy(parms->mask, &this_row->mask, parms->key_size); + if (parms->result != ((void *)0)) + memcpy(parms->result, &this_row->result, parms->result_size); + return 0; +}; + +static int cfa_tcam_mgr_hwop_free(int sess_idx, + struct cfa_tcam_mgr_free_parms *parms, + int row, int slice, int max_slices) +{ + struct cfa_tcam_mgr_TCAM_row_data *this_table; + struct cfa_tcam_mgr_TCAM_row_data *this_row; + this_table = row_tables[parms->dir] + [cfa_tcam_mgr_get_phys_table_type(parms->type)]; + this_table += (sess_idx * + cfa_tcam_mgr_get_max_rows(cfa_tcam_mgr_get_phys_table_type(parms->type))); + this_row = &this_table[row * max_slices + slice]; + memset(&this_row->key, 0, sizeof(this_row->key)); + memset(&this_row->mask, 0, sizeof(this_row->mask)); + memset(&this_row->result, 0, sizeof(this_row->result)); + this_row->key_size = 0; + this_row->result_size = 0; + return 0; +}; + +int cfa_tcam_mgr_hwops_get_funcs_p58(struct cfa_tcam_mgr_hwops_funcs + *hwop_funcs) +{ + hwop_funcs->set = cfa_tcam_mgr_hwop_set; + hwop_funcs->get = cfa_tcam_mgr_hwop_get; + hwop_funcs->free = cfa_tcam_mgr_hwop_free; + return 0; +} diff --git a/drivers/net/bnxt/tf_core/cfa_tcam_mgr_p58.h b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_p58.h new file mode 100644 index 0000000000..7640f91911 --- /dev/null +++ b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_p58.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021-2023 Broadcom + * All rights reserved. + */ + +#ifndef CFA_TCAM_MGR_P58_H +#define CFA_TCAM_MGR_P58_H + +#include "cfa_tcam_mgr_device.h" +#include "cfa_tcam_mgr_sbmp.h" + +int +cfa_tcam_mgr_init_p58(int sess_idx, struct cfa_tcam_mgr_entry_data **global_entry_data); + +int +cfa_tcam_mgr_sess_table_get_p58(int sess_idx, struct sbmp **session_bmp); + +int +cfa_tcam_mgr_hwops_get_funcs_p58(struct cfa_tcam_mgr_hwops_funcs *hwop_funcs); +#endif /* CFA_TCAM_MGR_P58_H */ diff --git a/drivers/net/bnxt/tf_core/cfa_tcam_mgr_sbmp.h b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_sbmp.h new file mode 100644 index 0000000000..6ad158abe8 --- /dev/null +++ b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_sbmp.h @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021-2023 Broadcom + * All rights reserved. + */ + +#ifndef CFA_TCAM_MGR_SBMP_H +#define CFA_TCAM_MGR_SBMP_H + +#include + +#include "cfa_tcam_mgr.h" + +#define SBMP_SESSION_MAX TF_TCAM_MAX_SESSIONS +#if SBMP_SESSION_MAX <= 16 +#define SBMP_WORD_WIDTH 16 +#else +#define SBMP_WORD_WIDTH 32 +#endif + +#define SBMP_WIDTH (((SBMP_SESSION_MAX + SBMP_WORD_WIDTH - 1) / \ + SBMP_WORD_WIDTH) * SBMP_WORD_WIDTH) +#define SBMP_WORD_MAX ((SBMP_WIDTH + SBMP_WORD_WIDTH - 1) / SBMP_WORD_WIDTH) + +struct sbmp { +#if SBMP_WORD_WIDTH == 16 + uint16_t bits[SBMP_WORD_MAX]; +#elif SBMP_WORD_WIDTH == 32 + uint32_t bits[SBMP_WORD_MAX]; +#else + uint64_t bits[SBMP_WORD_MAX]; +#endif +}; + +#define SBMP_WORD_GET(bm, word) ((bm).bits[(word)]) + +#if SBMP_WORD_MAX == 1 +#define SBMP_WENT(session) (0) +#define SBMP_WBIT(session) (1U << (session)) +#define SBMP_CLEAR(bm) (SBMP_WORD_GET(bm, 0) = 0) +#define SBMP_IS_NULL(bm) (SBMP_WORD_GET(bm, 0) == 0) +#define SBMP_COUNT(bm, count) \ + (count = __builtin_popcount(SBMP_WORD_GET(bm, 0))) +#elif SBMP_WORD_MAX == 2 +#define SBMP_WENT(session) ((session) / SBMP_WORD_WIDTH) +#define SBMP_WBIT(session) (1U << ((session) % SBMP_WORD_WIDTH)) +#define SBMP_CLEAR(bm) \ + do { \ + typeof(bm) *_bm = &(bm); \ + SBMP_WORD_GET(*_bm, 0) = SBMP_WORD_GET(*_bm, 1) = 0; \ + } while (0) +#define SBMP_IS_NULL(bm) \ + (SBMP_WORD_GET(bm, 0) == 0 && SBMP_WORD_GET(bm, 1) == 0) +#define SBMP_COUNT(bm, count) \ + do { \ + typeof(bm) *_bm = &(bm); \ + count = __builtin_popcount(SBMP_WORD_GET(*_bm, 0)) + \ + __builtin_popcount(SBMP_WORD_GET(*_bm, 1))); \ + } while (0) +#elif SBMP_WORD_MAX == 3 +#define SBMP_WENT(session) ((session) / SBMP_WORD_WIDTH) +#define SBMP_WBIT(session) (1U << ((session) % SBMP_WORD_WIDTH)) +#define SBMP_CLEAR(bm) \ + do { \ + typeof(bm) *_bm = &(bm); \ + SBMP_WORD_GET(*_bm, 0) = SBMP_WORD_GET(*_bm, 1) = \ + SBMP_WORD_GET(*_bm, 2) = 0; \ + } while (0) +#define SBMP_IS_NULL(bm) \ + (SBMP_WORD_GET(bm, 0) == 0 && SBMP_WORD_GET(bm, 1) == 0 && \ + SBMP_WORD_GET(bm, 2) == 0) +#define SBMP_COUNT(bm, count) \ + do { \ + typeof(bm) *_bm = &(bm); \ + count = __builtin_popcount(SBMP_WORD_GET(*_bm, 0)) + \ + __builtin_popcount(SBMP_WORD_GET(*_bm, 1)) + \ + __builtin_popcount(SBMP_WORD_GET(*_bm, 2)); \ + } while (0) +#else /* SBMP_WORD_MAX > 3 */ +#define SBMP_WENT(session) ((session) / SBMP_WORD_WIDTH) +#define SBMP_WBIT(session) (1U << ((session) % SBMP_WORD_WIDTH)) +#define SBMP_CLEAR(bm) \ + do { \ + typeof(bm) *_bm = &(bm); \ + int _w; \ + for (_w = 0; _w < SBMP_WORD_MAX; _w++) { \ + SBMP_WORD_GET(*_bm, _w) = 0; \ + } \ + } while (0) +#define SBMP_IS_NULL(bm) (sbmp_bmnull(&(bm))) +#define SBMP_COUNT(bm, count) \ + do { \ + typeof(bm) *_bm = &(bm); \ + int _count, _w; \ + _count = 0; \ + for (_w = 0; _w < SBMP_WORD_MAX; _w++) { \ + _count += __builtin_popcount(SBMP_WORD_GET(*_bm, _w)); \ + } \ + count = _count; \ + } while (0) + +/* Only needed if SBMP_WORD_MAX > 3 */ +static int +sbmp_bmnull(struct ebmp *bmp) +{ + int i; + + for (i = 0; i < SBMP_WORD_MAX; i++) { + if (SBMP_WORD_GET(*bmp, i) != 0) + return 0; + } + return 1; +} +#endif + +/* generics that use the previously defined helpers */ +#define SBMP_NOT_NULL(bm) (!SBMP_IS_NULL(bm)) + +#define SBMP_ENTRY(bm, session) \ + (SBMP_WORD_GET(bm, SBMP_WENT(session))) +#define SBMP_MEMBER(bm, session) \ + ((SBMP_ENTRY(bm, session) & SBMP_WBIT(session)) != 0) +#define SBMP_SESSION_ADD(bm, session) \ + (SBMP_ENTRY(bm, session) |= SBMP_WBIT(session)) +#define SBMP_SESSION_REMOVE(bm, session) \ + (SBMP_ENTRY(bm, session) &= ~SBMP_WBIT(session)) +#endif /* CFA_TCAM_MGR_SBMP_H */ diff --git a/drivers/net/bnxt/tf_core/cfa_tcam_mgr_session.c b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_session.c new file mode 100644 index 0000000000..3d085bc69e --- /dev/null +++ b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_session.c @@ -0,0 +1,377 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021-2023 Broadcom + * All rights reserved. + */ + +#include +#include "hcapi_cfa_defs.h" +#include "tf_util.h" +#include "cfa_tcam_mgr.h" +#include "cfa_tcam_mgr_device.h" +#include "cfa_tcam_mgr_session.h" +#include "cfa_tcam_mgr_sbmp.h" +#include "tfp.h" +#include "cfa_tcam_mgr_p58.h" +#include "cfa_tcam_mgr_p4.h" + +struct cfa_tcam_mgr_session_data { + uint32_t session_id; + /* The following are per-session values */ + uint16_t max_entries[TF_DIR_MAX][CFA_TCAM_MGR_TBL_TYPE_MAX]; + uint16_t used_entries[TF_DIR_MAX][CFA_TCAM_MGR_TBL_TYPE_MAX]; +}; + +static struct cfa_tcam_mgr_session_data session_data[TF_TCAM_MAX_SESSIONS]; + +static uint16_t last_entry_id; + +static struct sbmp *session_bmp[TF_TCAM_MAX_SESSIONS]; + +int +cfa_tcam_mgr_session_init(int sess_idx, enum cfa_tcam_mgr_device_type type) +{ + int rc; + + switch (type) { + case CFA_TCAM_MGR_DEVICE_TYPE_P4: + case CFA_TCAM_MGR_DEVICE_TYPE_SR: + rc = cfa_tcam_mgr_sess_table_get_p4(sess_idx, &session_bmp[sess_idx]); + break; + case CFA_TCAM_MGR_DEVICE_TYPE_P5: + rc = cfa_tcam_mgr_sess_table_get_p58(sess_idx, &session_bmp[sess_idx]); + break; + default: + CFA_TCAM_MGR_LOG(ERR, "No such device %d\n", type); + rc = -CFA_TCAM_MGR_ERR_CODE(NODEV); + } + + return rc; +} + +int +cfa_tcam_mgr_get_session_from_context(struct cfa_tcam_mgr_context *context, + uint32_t *session_id) +{ + if (context == NULL) { + CFA_TCAM_MGR_LOG_0(ERR, "context passed as NULL pointer.\n"); + return -CFA_TCAM_MGR_ERR_CODE(INVAL); + } + + *session_id = context->tfp->session->session_id.id; + return 0; +} + +int +cfa_tcam_mgr_session_find(unsigned int session_id) +{ + unsigned int sess_idx; + + for (sess_idx = 0; sess_idx < ARRAY_SIZE(session_data); sess_idx++) { + if (session_data[sess_idx].session_id == session_id) + return sess_idx; + } + + return -CFA_TCAM_MGR_ERR_CODE(INVAL); +} + +int +cfa_tcam_mgr_session_add(unsigned int session_id) +{ + int sess_idx; + + sess_idx = cfa_tcam_mgr_session_find(session_id); + if (sess_idx >= 0) { + CFA_TCAM_MGR_LOG_0(ERR, "Session is already bound.\n"); + return -CFA_TCAM_MGR_ERR_CODE(BUSY); + } + + /* Session not found in table, find first empty entry. */ + for (sess_idx = 0; + sess_idx < (signed int)ARRAY_SIZE(session_data); + sess_idx++) { + if (session_data[sess_idx].session_id == 0) + break; + } + + if (sess_idx >= (signed int)ARRAY_SIZE(session_data)) { + /* No room in the session table */ + CFA_TCAM_MGR_LOG_0(ERR, "Session table is full.\n"); + return -CFA_TCAM_MGR_ERR_CODE(NOMEM); + } + + session_data[sess_idx].session_id = session_id; + + return sess_idx; +} + +int +cfa_tcam_mgr_session_free(unsigned int session_id, + struct cfa_tcam_mgr_context *context) +{ + struct cfa_tcam_mgr_free_parms free_parms; + int entry_id; + int sess_idx = cfa_tcam_mgr_session_find(session_id); + + if (sess_idx < 0) + return sess_idx; + + memset(&free_parms, 0, sizeof(free_parms)); + /* Since we are freeing all pending TCAM entries (which is typically + * done during tcam_unbind), we don't know the type of each entry. + * So we set the type to MAX as a hint to cfa_tcam_mgr_free() to + * figure out the actual type. We need to set it through each + * iteration in the loop below; otherwise, the type determined for + * the first entry would be used for subsequent entries that may or + * may not be of the same type, resulting in errors. + */ + for (entry_id = 0; entry_id < cfa_tcam_mgr_max_entries[sess_idx]; entry_id++) { + if (SBMP_MEMBER(session_bmp[sess_idx][entry_id], sess_idx)) { + SBMP_SESSION_REMOVE(session_bmp[sess_idx][entry_id], sess_idx); + + free_parms.id = entry_id; + free_parms.type = CFA_TCAM_MGR_TBL_TYPE_MAX; + cfa_tcam_mgr_free(context, &free_parms); + } + } + + memset(&session_data[sess_idx], 0, sizeof(session_data[sess_idx])); + return 0; +} + +int +cfa_tcam_mgr_session_cfg(unsigned int session_id, + uint16_t tcam_cnt[][CFA_TCAM_MGR_TBL_TYPE_MAX]) +{ + struct cfa_tcam_mgr_table_data *table_data; + struct cfa_tcam_mgr_session_data *session_entry; + unsigned int dir, type; + int sess_idx = cfa_tcam_mgr_session_find(session_id); + uint16_t requested_cnt; + + if (sess_idx < 0) + return sess_idx; + + session_entry = &session_data[sess_idx]; + + /* Validate session request */ + for (dir = 0; dir < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx]); dir++) { + for (type = 0; + type < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx][dir]); + type++) { + table_data = &cfa_tcam_mgr_tables[sess_idx][dir][type]; + requested_cnt = tcam_cnt[dir][type]; + /* + * Only check if table supported (max_entries > 0). + */ + if (table_data->max_entries > 0 && + requested_cnt > table_data->max_entries) { + CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, dir, type, + "Requested %d, available %d.\n", + requested_cnt, + table_data->max_entries); + return -CFA_TCAM_MGR_ERR_CODE(NOSPC); + } + } + } + + memcpy(session_entry->max_entries, tcam_cnt, + sizeof(session_entry->max_entries)); + return 0; +} + +void +cfa_tcam_mgr_mv_session_used_entries_cnt(int sess_idx, enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type dst_type, + enum cfa_tcam_mgr_tbl_type src_type) +{ + session_data[sess_idx].used_entries[dir][dst_type]++; + session_data[sess_idx].used_entries[dir][src_type]--; +} + +int +cfa_tcam_mgr_session_entry_alloc(unsigned int session_id, + enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type) +{ + int sess_idx; + + sess_idx = cfa_tcam_mgr_session_find(session_id); + if (sess_idx < 0) { + CFA_TCAM_MGR_LOG_0(ERR, "Session not found.\n"); + return -CFA_TCAM_MGR_ERR_CODE(NODEV); + } + + if (session_data[sess_idx].used_entries[dir][type] >= + session_data[sess_idx].max_entries[dir][type]) { + CFA_TCAM_MGR_LOG_0(ERR, "Table full (session).\n"); + return -CFA_TCAM_MGR_ERR_CODE(NOSPC); + } + + do { + last_entry_id++; + if (cfa_tcam_mgr_max_entries[sess_idx] <= last_entry_id) + last_entry_id = 0; + } while (!SBMP_IS_NULL(session_bmp[sess_idx][last_entry_id])); + + SBMP_SESSION_ADD(session_bmp[sess_idx][last_entry_id], sess_idx); + + session_data[sess_idx].used_entries[dir][type] += 1; + + return last_entry_id; +} + +int +cfa_tcam_mgr_session_entry_free(unsigned int session_id, + unsigned int entry_id, + enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type) +{ + int sess_idx; + + sess_idx = cfa_tcam_mgr_session_find(session_id); + if (sess_idx < 0) { + CFA_TCAM_MGR_LOG_0(ERR, "Session not found.\n"); + return -CFA_TCAM_MGR_ERR_CODE(NODEV); + } + + SBMP_SESSION_REMOVE(session_bmp[sess_idx][entry_id], sess_idx); + session_data[sess_idx].used_entries[dir][type] -= 1; + + return 0; +} + +#if SBMP_WORD_WIDTH == 16 +#define SBMP_FORMAT PRIX16 +#define SBMP_PRECISION "4" +#elif SBMP_WORD_WIDTH == 32 +#define SBMP_FORMAT PRIX32 +#define SBMP_PRECISION "8" +#elif SBMP_WORD_WIDTH == 64 +#define SBMP_FORMAT PRIX64 +#define SBMP_PRECISION "16" +#else +#error "Invalid value for SBMP_WORD_WIDTH." +#endif + +static void +cfa_tcam_mgr_session_bitmap_print(struct sbmp *session_bmp) +{ + unsigned int i; + + printf("0x"); + for (i = 0; + i < ARRAY_SIZE(session_bmp->bits); + i++) { + printf("%0" SBMP_PRECISION SBMP_FORMAT, + session_bmp->bits[i]); + } +} + +#define SESSION_DUMP_HEADER_1 " RX TX\n" +#define SESSION_DUMP_HEADER_2 \ + " Max Used Max Used\n" + +static void +cfa_tcam_mgr_session_printf(struct cfa_tcam_mgr_session_data *session, + enum cfa_tcam_mgr_tbl_type tbl_type) +{ + printf("%-22s: %5u %5u %5u %5u\n", + cfa_tcam_mgr_tbl_2_str(tbl_type), + session->max_entries[TF_DIR_RX][tbl_type], + session->used_entries[TF_DIR_RX][tbl_type], + session->max_entries[TF_DIR_TX][tbl_type], + session->used_entries[TF_DIR_TX][tbl_type]); +} + +void +cfa_tcam_mgr_sessions_dump(void) +{ + struct cfa_tcam_mgr_session_data *session; + unsigned int sess_idx; + bool sess_found = false; + enum cfa_tcam_mgr_tbl_type tbl_type; + + printf("\nTCAM Sessions Table:\n"); + for (sess_idx = 0; sess_idx < ARRAY_SIZE(session_data); sess_idx++) { + if (session_data[sess_idx].session_id != 0) { + session = &session_data[sess_idx]; + if (!sess_found) { + printf(SESSION_DUMP_HEADER_1); + printf(SESSION_DUMP_HEADER_2); + } + printf("Session 0x%08x:\n", + session->session_id); + for (tbl_type = CFA_TCAM_MGR_TBL_TYPE_START; + tbl_type < CFA_TCAM_MGR_TBL_TYPE_MAX; + tbl_type++) { + cfa_tcam_mgr_session_printf(session, tbl_type); + } + sess_found = true; + } + } + + if (!sess_found) + printf("No sessions found.\n"); +} + +/* This dumps all the sessions using an entry */ +void +cfa_tcam_mgr_entry_sessions_dump(int sess_idx, uint16_t id) +{ + bool session_found = false; + + if (id >= cfa_tcam_mgr_max_entries[sess_idx]) { + printf("Entry ID %u out of range for sess_idx %d. Max ID %u.\n", + id, sess_idx, cfa_tcam_mgr_max_entries[sess_idx] - 1); + return; + } + + if (!SBMP_IS_NULL(session_bmp[sess_idx][id])) { + printf("Sessions using entry ID %u:\n", id); + for (sess_idx = 0; sess_idx < SBMP_SESSION_MAX; sess_idx++) + if (SBMP_MEMBER(session_bmp[sess_idx][id], (sess_idx))) { + if (session_data[sess_idx].session_id != 0) { + printf("0x%08x (index %d)\n", + session_data[sess_idx].session_id, + sess_idx); + session_found = true; + } else { + printf("Error! Entry ID %u used by " + "session index %d which is not " + "in use.\n", + id, sess_idx); + } + } + if (!session_found) + printf("No sessions using entry ID %u.\n", id); + } else { + printf("Entry ID %u not in use.\n", + id); + return; + } +} + +/* This dumps all the entries in use by any session */ +void +cfa_tcam_mgr_session_entries_dump(int sess_idx) +{ + bool entry_found = false; + uint16_t id; + + printf("\nGlobal Maximum Entries for sess_idx %d: %d\n\n", + sess_idx, cfa_tcam_mgr_max_entries[sess_idx]); + printf("TCAM Session Entry Table:\n"); + for (id = 0; id < cfa_tcam_mgr_max_entries[sess_idx]; id++) { + if (!SBMP_IS_NULL(session_bmp[sess_idx][id])) { + if (!entry_found) + printf(" EID Session bitmap\n"); + printf("%5u ", id); + cfa_tcam_mgr_session_bitmap_print(&session_bmp[sess_idx][id]); + printf("\n"); + entry_found = true; + } + } + + if (!entry_found) + printf("No entries found.\n"); +} diff --git a/drivers/net/bnxt/tf_core/cfa_tcam_mgr_session.h b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_session.h new file mode 100644 index 0000000000..69311b7e1d --- /dev/null +++ b/drivers/net/bnxt/tf_core/cfa_tcam_mgr_session.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019-2023 Broadcom + * All rights reserved. + */ + +#ifndef CFA_TCAM_MGR_SESSION_H +#define CFA_TCAM_MGR_SESSION_H + +#include +#include "cfa_tcam_mgr.h" + +int +cfa_tcam_mgr_session_init(int sess_idx, enum cfa_tcam_mgr_device_type type); + +int +cfa_tcam_mgr_get_session_from_context(struct cfa_tcam_mgr_context *context, + uint32_t *session_id); + +int +cfa_tcam_mgr_session_find(unsigned int session_id); + +int +cfa_tcam_mgr_session_add(unsigned int session_id); + +int +cfa_tcam_mgr_session_free(unsigned int session_id, + struct cfa_tcam_mgr_context *context); + +int +cfa_tcam_mgr_session_cfg(unsigned int session_id, + uint16_t tcam_cnt[][CFA_TCAM_MGR_TBL_TYPE_MAX]); + +int +cfa_tcam_mgr_session_entry_alloc(unsigned int session_id, + enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type); +int +cfa_tcam_mgr_session_entry_free(unsigned int session_id, + unsigned int entry_id, + enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type type); + +void +cfa_tcam_mgr_sessions_dump(void); +void +cfa_tcam_mgr_entry_sessions_dump(int sess_idx, uint16_t id); +void +cfa_tcam_mgr_session_entries_dump(int sess_idx); + +void +cfa_tcam_mgr_mv_session_used_entries_cnt(int sess_idx, enum tf_dir dir, + enum cfa_tcam_mgr_tbl_type dst_type, + enum cfa_tcam_mgr_tbl_type src_type); +#endif /* CFA_TCAM_MGR_SESSION_H */ diff --git a/drivers/net/bnxt/tf_core/meson.build b/drivers/net/bnxt/tf_core/meson.build index f812e471d1..ae44aa34cf 100644 --- a/drivers/net/bnxt/tf_core/meson.build +++ b/drivers/net/bnxt/tf_core/meson.build @@ -1,36 +1,42 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2018 Intel Corporation -# Copyright(c) 2021 Broadcom +# Copyright(c) 2023 Broadcom #Include the folder for headers includes += include_directories('.') #Add the source files sources += files( - 'tf_core.c', 'bitalloc.c', - 'tf_msg.c', - 'll.c', + 'cfa_tcam_mgr.c', + 'cfa_tcam_mgr_hwop_msg.c', + 'cfa_tcam_mgr_p4.c', + 'cfa_tcam_mgr_p58.c', + 'cfa_tcam_mgr_session.c', 'dpool.c', + 'll.c', 'rand.c', 'stack.c', - 'tf_rm.c', - 'tf_tbl.c', - 'tf_tbl_sram.c', - 'tf_sram_mgr.c', + 'tf_core.c', + 'tf_device.c', + 'tf_device_p4.c', + 'tf_device_p58.c', 'tf_em_common.c', + 'tf_em_hash_internal.c', 'tf_em_host.c', 'tf_em_internal.c', - 'tf_em_hash_internal.c', - 'tfp.c', - 'tf_util.c', - 'tf_device.c', - 'tf_device_p4.c', 'tf_global_cfg.c', + 'tf_hash.c', 'tf_identifier.c', 'tf_if_tbl.c', + 'tf_msg.c', + 'tfp.c', + 'tf_rm.c', 'tf_session.c', + 'tf_sram_mgr.c', + 'tf_tbl.c', + 'tf_tbl_sram.c', 'tf_tcam.c', + 'tf_tcam_mgr_msg.c', 'tf_tcam_shared.c', - 'tf_hash.c', - 'tf_device_p58.c') + 'tf_util.c') diff --git a/drivers/net/bnxt/tf_core/tf_core.c b/drivers/net/bnxt/tf_core/tf_core.c index 038e439101..3a812bee3a 100644 --- a/drivers/net/bnxt/tf_core/tf_core.c +++ b/drivers/net/bnxt/tf_core/tf_core.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ @@ -34,8 +34,8 @@ tf_open_session(struct tf *tfp, * side. It is assumed that the Firmware will be supported if * firmware open session succeeds. */ - if (parms->device_type != TF_DEVICE_TYPE_WH && - parms->device_type != TF_DEVICE_TYPE_THOR && + if (parms->device_type != TF_DEVICE_TYPE_P4 && + parms->device_type != TF_DEVICE_TYPE_P5 && parms->device_type != TF_DEVICE_TYPE_SR) { TFP_DRV_LOG(ERR, "Unsupported device type %d\n", @@ -83,7 +83,7 @@ tf_open_session(struct tf *tfp, return rc; TFP_DRV_LOG(INFO, - "domain:%d, bus:%d, device:%u\n", + "domain:%x, bus:%x, device:%u\n", parms->session_id.internal.domain, parms->session_id.internal.bus, parms->session_id.internal.device); @@ -176,7 +176,7 @@ tf_close_session(struct tf *tfp) return rc; TFP_DRV_LOG(INFO, - "domain:%d, bus:%d, device:%d\n", + "domain:%d, bus:%x, device:%d\n", cparms.session_id->internal.domain, cparms.session_id->internal.bus, cparms.session_id->internal.device); @@ -742,7 +742,6 @@ tf_set_tcam_entry(struct tf *tfp, memset(&sparms, 0, sizeof(struct tf_tcam_set_parms)); - /* Retrieve the session information */ rc = tf_session_get_session(tfp, &tfs); if (rc) { @@ -790,6 +789,10 @@ tf_set_tcam_entry(struct tf *tfp, strerror(-rc)); return rc; } + TFP_DRV_LOG(DEBUG, + "%s: TCAM type %d set idx:%d key size %d result size %d\n", + tf_dir_2_str(parms->dir), sparms.type, + sparms.idx, sparms.key_size, sparms.result_size); return 0; } @@ -807,7 +810,6 @@ tf_get_tcam_entry(struct tf *tfp __rte_unused, memset(&gparms, 0, sizeof(struct tf_tcam_get_parms)); - /* Retrieve the session information */ rc = tf_session_get_session(tfp, &tfs); if (rc) { @@ -1812,8 +1814,8 @@ int tf_get_version(struct tf *tfp, /* This function can be called before open session, filter * out any non-supported device types on the Core side. */ - if (parms->device_type != TF_DEVICE_TYPE_WH && - parms->device_type != TF_DEVICE_TYPE_THOR && + if (parms->device_type != TF_DEVICE_TYPE_P4 && + parms->device_type != TF_DEVICE_TYPE_P5 && parms->device_type != TF_DEVICE_TYPE_SR) { TFP_DRV_LOG(ERR, "Unsupported device type %d\n", @@ -1845,7 +1847,7 @@ int tf_query_sram_resources(struct tf *tfp, /* This function can be called before open session, filter * out any non-supported device types on the Core side. */ - if (parms->device_type != TF_DEVICE_TYPE_THOR) { + if (parms->device_type != TF_DEVICE_TYPE_P5) { TFP_DRV_LOG(ERR, "Unsupported device type %d\n", parms->device_type); @@ -1927,7 +1929,7 @@ int tf_set_sram_policy(struct tf *tfp, /* This function can be called before open session, filter * out any non-supported device types on the Core side. */ - if (parms->device_type != TF_DEVICE_TYPE_THOR) { + if (parms->device_type != TF_DEVICE_TYPE_P5) { TFP_DRV_LOG(ERR, "Unsupported device type %d\n", parms->device_type); @@ -1968,7 +1970,7 @@ int tf_get_sram_policy(struct tf *tfp, /* This function can be called before open session, filter * out any non-supported device types on the Core side. */ - if (parms->device_type != TF_DEVICE_TYPE_THOR) { + if (parms->device_type != TF_DEVICE_TYPE_P5) { TFP_DRV_LOG(ERR, "Unsupported device type %d\n", parms->device_type); @@ -1997,3 +1999,31 @@ int tf_get_sram_policy(struct tf *tfp, return rc; } + +int tf_set_session_hotup_state(struct tf *tfp, + struct tf_set_session_hotup_state_parms *parms) +{ + int rc = 0; + + TF_CHECK_PARMS1(tfp); + + rc = tf_session_set_hotup_state(tfp, parms); + if (rc) + return rc; + + return rc; +} + +int tf_get_session_hotup_state(struct tf *tfp, + struct tf_get_session_hotup_state_parms *parms) +{ + int rc = 0; + + TF_CHECK_PARMS1(tfp); + + rc = tf_session_get_hotup_state(tfp, parms); + if (rc) + return rc; + + return rc; +} diff --git a/drivers/net/bnxt/tf_core/tf_core.h b/drivers/net/bnxt/tf_core/tf_core.h index f5fe0a9098..3da1d2a5ca 100644 --- a/drivers/net/bnxt/tf_core/tf_core.h +++ b/drivers/net/bnxt/tf_core/tf_core.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ @@ -112,6 +112,10 @@ enum tf_sram_bank_id { * @ref tf_attach_session * * @ref tf_close_session + * + * @ref tf_get_session_info + * + * @ref tf_get_session_info */ /** @@ -188,10 +192,10 @@ struct tf_session_version { * Session supported device types */ enum tf_device_type { - TF_DEVICE_TYPE_WH = 0, /**< Whitney+ */ - TF_DEVICE_TYPE_SR, /**< Stingray */ - TF_DEVICE_TYPE_THOR, /**< Thor */ - TF_DEVICE_TYPE_MAX /**< Maximum */ + TF_DEVICE_TYPE_P4 = 0, + TF_DEVICE_TYPE_SR, + TF_DEVICE_TYPE_P5, + TF_DEVICE_TYPE_MAX }; /** @@ -286,6 +290,8 @@ enum tf_tbl_type { TF_TBL_TYPE_ACT_ENCAP_32B, /** Wh+/SR/TH Action Encap 64 Bytes */ TF_TBL_TYPE_ACT_ENCAP_64B, + /* TH Action Encap 128 Bytes */ + TF_TBL_TYPE_ACT_ENCAP_128B, /** WH+/SR/TH Action Source Properties SMAC */ TF_TBL_TYPE_ACT_SP_SMAC, /** Wh+/SR/TH Action Source Properties SMAC IPv4 */ @@ -331,7 +337,7 @@ enum tf_tbl_type { * External table type - initially 1 poolsize entries. * All External table types are associated with a table * scope. Internal types are not. Currently this is - * a pool of 64B entries. + * a pool of 128B entries. */ TF_TBL_TYPE_EXT, TF_TBL_TYPE_MAX @@ -914,6 +920,71 @@ int tf_attach_session(struct tf *tfp, */ int tf_close_session(struct tf *tfp); +/** + * tf_set_session_hotup_state parameter definition. + */ +struct tf_set_session_hotup_state_parms { + /** + * [in] the structure is used to set the state of + * the hotup shared session. + * + */ + uint16_t state; +}; + +/** + * set hot upgrade shared session state + * + * This API is used to set the state of the shared session. + * + * [in] tfp + * Pointer to TF handle + * + * [in] parms + * Pointer to set hotup state parameters + * + * Returns + * - (0) if successful. + * - (-EINVAL) on failure. + */ +int tf_set_session_hotup_state(struct tf *tfp, + struct tf_set_session_hotup_state_parms *parms); + +/** + * tf_get_session_hotup_state parameter definition. + */ +struct tf_get_session_hotup_state_parms { + /** + * [out] the structure is used to get the state of + * the hotup shared session. + * + */ + uint16_t state; + /** + * [out] get the ref_cnt of the hotup shared session. + * + */ + uint16_t ref_cnt; +}; + +/** + * get hot upgrade shared session state + * + * This API is used to set the state of the shared session. + * + * [in] tfp + * Pointer to TF handle + * + * [in] parms + * Pointer to get hotup state parameters + * + * Returns + * - (0) if successful. + * - (-EINVAL) on failure. + */ +int tf_get_session_hotup_state(struct tf *tfp, + struct tf_get_session_hotup_state_parms *parms); + /** * @page ident Identity Management * @@ -1192,8 +1263,6 @@ int tf_free_tbl_scope(struct tf *tfp, * * @ref tf_get_tcam_entry * - * @ref tf_free_tcam_entry - * * @ref tf_move_tcam_shared_entries * * @ref tf_clear_tcam_shared_entries @@ -1258,7 +1327,7 @@ struct tf_search_tcam_entry_parms { }; /** - * search TCAM entry (experimental) + * search TCAM entry * * Search for a TCAM entry * @@ -1732,7 +1801,7 @@ struct tf_get_shared_tbl_increment_parms { * tf_get_shared_tbl_increment * * This API is currently only required for use in the shared - * session for Thor (p58) actions. An increment count is returned per + * session for P5 actions. An increment count is returned per * type to indicate how much to increment the start by for each * entry (see tf_resource_info) * @@ -1898,6 +1967,7 @@ struct tf_insert_em_entry_parms { */ uint64_t flow_id; }; + /** * tf_delete_em_entry parameter definition */ @@ -1927,6 +1997,7 @@ struct tf_delete_em_entry_parms { */ uint64_t flow_handle; }; + /** * tf_move_em_entry parameter definition */ @@ -1969,6 +2040,7 @@ struct tf_move_em_entry_parms { */ uint64_t flow_handle; }; + /** * tf_search_em_entry parameter definition (Future) */ @@ -2108,6 +2180,7 @@ int tf_search_em_entry(struct tf *tfp, * * @ref tf_get_global_cfg */ + /** * Tunnel Encapsulation Offsets */ @@ -2121,6 +2194,7 @@ enum tf_tunnel_encap_offsets { TF_TUNNEL_ENCAP_GRE, TF_TUNNEL_ENCAP_FULL_GENERIC }; + /** * Global Configuration Table Types */ @@ -2193,9 +2267,8 @@ int tf_set_global_cfg(struct tf *tfp, * @ref tf_set_if_tbl_entry * * @ref tf_get_if_tbl_entry - * - * @ref tf_restore_if_tbl_entry */ + /** * Enumeration of TruFlow interface table types. */ diff --git a/drivers/net/bnxt/tf_core/tf_device.c b/drivers/net/bnxt/tf_core/tf_device.c index 1c97218b5b..02a9ebd7b2 100644 --- a/drivers/net/bnxt/tf_core/tf_device.c +++ b/drivers/net/bnxt/tf_core/tf_device.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ @@ -332,7 +332,7 @@ tf_dev_unbind_p4(struct tf *tfp) } /** - * Device specific bind function, THOR + * Device specific bind function, P5 * * [in] tfp * Pointer to TF handle @@ -504,7 +504,7 @@ tf_dev_bind_p58(struct tf *tfp, } /** - * Device specific unbind function, THOR + * Device specific unbind function, P5 * * [in] tfp * Pointer to TF handle @@ -602,14 +602,14 @@ tf_dev_bind(struct tf *tfp __rte_unused, struct tf_dev_info *dev_handle) { switch (type) { - case TF_DEVICE_TYPE_WH: + case TF_DEVICE_TYPE_P4: case TF_DEVICE_TYPE_SR: dev_handle->type = type; return tf_dev_bind_p4(tfp, resources, dev_handle, wc_num_slices); - case TF_DEVICE_TYPE_THOR: + case TF_DEVICE_TYPE_P5: dev_handle->type = type; return tf_dev_bind_p58(tfp, resources, @@ -627,11 +627,11 @@ 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_P4: case TF_DEVICE_TYPE_SR: dev_handle->ops = &tf_dev_ops_p4_init; break; - case TF_DEVICE_TYPE_THOR: + case TF_DEVICE_TYPE_P5: dev_handle->ops = &tf_dev_ops_p58_init; break; default: @@ -648,10 +648,10 @@ tf_dev_unbind(struct tf *tfp, struct tf_dev_info *dev_handle) { switch (dev_handle->type) { - case TF_DEVICE_TYPE_WH: + case TF_DEVICE_TYPE_P4: case TF_DEVICE_TYPE_SR: return tf_dev_unbind_p4(tfp); - case TF_DEVICE_TYPE_THOR: + case TF_DEVICE_TYPE_P5: return tf_dev_unbind_p58(tfp); default: TFP_DRV_LOG(ERR, diff --git a/drivers/net/bnxt/tf_core/tf_device.h b/drivers/net/bnxt/tf_core/tf_device.h index 5a42180719..06c17a7212 100644 --- a/drivers/net/bnxt/tf_core/tf_device.h +++ b/drivers/net/bnxt/tf_core/tf_device.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ diff --git a/drivers/net/bnxt/tf_core/tf_device_p4.c b/drivers/net/bnxt/tf_core/tf_device_p4.c index 72c6b1cde8..911ea92471 100644 --- a/drivers/net/bnxt/tf_core/tf_device_p4.c +++ b/drivers/net/bnxt/tf_core/tf_device_p4.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ @@ -296,11 +296,15 @@ tf_dev_p4_get_tcam_slice_info(struct tf *tfp, return rc; /* Single slice support */ -#define CFA_P4_WC_TCAM_SLICE_SIZE 12 - +#define CFA_P4_WC_TCAM_SLICE_SIZE (12) if (type == TF_TCAM_TBL_TYPE_WC_TCAM) { - *num_slices_per_row = tfs->wc_num_slices_per_row; - if (key_sz > *num_slices_per_row * CFA_P4_WC_TCAM_SLICE_SIZE) + if (key_sz <= 1 * CFA_P4_WC_TCAM_SLICE_SIZE) + *num_slices_per_row = TF_WC_TCAM_1_SLICE_PER_ROW; + else if (key_sz <= 2 * CFA_P4_WC_TCAM_SLICE_SIZE) + *num_slices_per_row = TF_WC_TCAM_2_SLICE_PER_ROW; + else if (key_sz <= 4 * CFA_P4_WC_TCAM_SLICE_SIZE) + *num_slices_per_row = TF_WC_TCAM_4_SLICE_PER_ROW; + else return -ENOTSUP; } else { /* for other type of tcam */ *num_slices_per_row = 1; diff --git a/drivers/net/bnxt/tf_core/tf_device_p58.c b/drivers/net/bnxt/tf_core/tf_device_p58.c index f8b424ebc9..6916c50fdc 100644 --- a/drivers/net/bnxt/tf_core/tf_device_p58.c +++ b/drivers/net/bnxt/tf_core/tf_device_p58.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ @@ -16,6 +16,7 @@ #include "tfp.h" #include "tf_msg_common.h" #include "tf_tbl_sram.h" +#include "tf_util.h" #define TF_DEV_P58_PARIF_MAX 16 #define TF_DEV_P58_PF_MASK 0xfUL @@ -79,33 +80,39 @@ struct tf_rm_element_cfg tf_tbl_p58[TF_DIR_MAX][TF_TBL_TYPE_MAX] = { [TF_DIR_RX][TF_TBL_TYPE_FULL_ACT_RECORD] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_PARENT, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_1, - .slices = 4, + .slices = 8, }, [TF_DIR_RX][TF_TBL_TYPE_COMPACT_ACT_RECORD] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_FULL_ACT_RECORD, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_1, - .slices = 8, + .slices = 16, }, /* Policy - Encaps in bank 2 */ [TF_DIR_RX][TF_TBL_TYPE_ACT_ENCAP_8B] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_PARENT, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, - .slices = 8, + .slices = 16, }, [TF_DIR_RX][TF_TBL_TYPE_ACT_ENCAP_16B] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, - .slices = 4, + .slices = 8, }, [TF_DIR_RX][TF_TBL_TYPE_ACT_ENCAP_32B] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, - .slices = 2, + .slices = 4, }, [TF_DIR_RX][TF_TBL_TYPE_ACT_ENCAP_64B] = { + .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, + .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, + .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, + .slices = 2, + }, + [TF_DIR_RX][TF_TBL_TYPE_ACT_ENCAP_128B] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, @@ -116,49 +123,49 @@ struct tf_rm_element_cfg tf_tbl_p58[TF_DIR_MAX][TF_TBL_TYPE_MAX] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, - .slices = 8, + .slices = 16, }, [TF_DIR_RX][TF_TBL_TYPE_ACT_MODIFY_16B] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, - .slices = 4, + .slices = 8, }, [TF_DIR_RX][TF_TBL_TYPE_ACT_MODIFY_32B] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, - .slices = 2, + .slices = 4, }, [TF_DIR_RX][TF_TBL_TYPE_ACT_MODIFY_64B] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, - .slices = 1, + .slices = 2, }, /* Policy - SP in bank 0 */ [TF_DIR_RX][TF_TBL_TYPE_ACT_SP_SMAC] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_PARENT, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_0, - .slices = 8, + .slices = 16, }, [TF_DIR_RX][TF_TBL_TYPE_ACT_SP_SMAC_IPV4] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_SP_SMAC, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_0, - .slices = 4, + .slices = 8, }, [TF_DIR_RX][TF_TBL_TYPE_ACT_SP_SMAC_IPV6] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_SP_SMAC, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_0, - .slices = 2, + .slices = 4, }, /* Policy - Stats in bank 3 */ [TF_DIR_RX][TF_TBL_TYPE_ACT_STATS_64] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_PARENT, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_3, - .slices = 8, + .slices = 16, }, [TF_DIR_TX][TF_TBL_TYPE_EM_FKB] = { TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_EM_FKB, @@ -192,33 +199,39 @@ struct tf_rm_element_cfg tf_tbl_p58[TF_DIR_MAX][TF_TBL_TYPE_MAX] = { [TF_DIR_TX][TF_TBL_TYPE_FULL_ACT_RECORD] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_PARENT, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_1, - .slices = 4, + .slices = 8, }, [TF_DIR_TX][TF_TBL_TYPE_COMPACT_ACT_RECORD] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_FULL_ACT_RECORD, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_1, - .slices = 8, + .slices = 16, }, /* Policy - Encaps in bank 2 */ [TF_DIR_TX][TF_TBL_TYPE_ACT_ENCAP_8B] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_PARENT, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, - .slices = 8, + .slices = 16, }, [TF_DIR_TX][TF_TBL_TYPE_ACT_ENCAP_16B] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, - .slices = 4, + .slices = 8, }, [TF_DIR_TX][TF_TBL_TYPE_ACT_ENCAP_32B] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, - .slices = 2, + .slices = 4, }, [TF_DIR_TX][TF_TBL_TYPE_ACT_ENCAP_64B] = { + .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, + .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, + .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, + .slices = 2, + }, + [TF_DIR_TX][TF_TBL_TYPE_ACT_ENCAP_128B] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, @@ -229,49 +242,49 @@ struct tf_rm_element_cfg tf_tbl_p58[TF_DIR_MAX][TF_TBL_TYPE_MAX] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, - .slices = 8, + .slices = 16, }, [TF_DIR_TX][TF_TBL_TYPE_ACT_MODIFY_16B] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, - .slices = 4, + .slices = 8, }, [TF_DIR_TX][TF_TBL_TYPE_ACT_MODIFY_32B] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, - .slices = 2, + .slices = 4, }, [TF_DIR_TX][TF_TBL_TYPE_ACT_MODIFY_64B] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_ENCAP_8B, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2, - .slices = 1, + .slices = 2, }, /* Policy - SP in bank 0 */ [TF_DIR_TX][TF_TBL_TYPE_ACT_SP_SMAC] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_PARENT, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_0, - .slices = 8, + .slices = 16, }, [TF_DIR_TX][TF_TBL_TYPE_ACT_SP_SMAC_IPV4] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_SP_SMAC, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_0, - .slices = 4, + .slices = 8, }, [TF_DIR_TX][TF_TBL_TYPE_ACT_SP_SMAC_IPV6] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_CHILD, .parent_subtype = TF_TBL_TYPE_ACT_SP_SMAC, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_0, - .slices = 2, + .slices = 4, }, /* Policy - Stats in bank 3 */ [TF_DIR_TX][TF_TBL_TYPE_ACT_STATS_64] = { .cfg_type = TF_RM_ELEM_CFG_HCAPI_BA_PARENT, .hcapi_type = CFA_RESOURCE_TYPE_P58_SRAM_BANK_3, - .slices = 8, + .slices = 16, }, }; @@ -406,10 +419,15 @@ tf_dev_p58_get_tcam_slice_info(struct tf *tfp, if (rc) return rc; -#define CFA_P58_WC_TCAM_SLICE_SIZE 24 +#define CFA_P58_WC_TCAM_SLICE_SIZE (24) if (type == TF_TCAM_TBL_TYPE_WC_TCAM) { - *num_slices_per_row = tfs->wc_num_slices_per_row; - if (key_sz > *num_slices_per_row * CFA_P58_WC_TCAM_SLICE_SIZE) + if (key_sz <= 1 * CFA_P58_WC_TCAM_SLICE_SIZE) + *num_slices_per_row = TF_WC_TCAM_1_SLICE_PER_ROW; + else if (key_sz <= 2 * CFA_P58_WC_TCAM_SLICE_SIZE) + *num_slices_per_row = TF_WC_TCAM_2_SLICE_PER_ROW; + else if (key_sz <= 4 * CFA_P58_WC_TCAM_SLICE_SIZE) + *num_slices_per_row = TF_WC_TCAM_4_SLICE_PER_ROW; + else return -ENOTSUP; } else { /* for other type of tcam */ *num_slices_per_row = 1; @@ -452,6 +470,7 @@ static int tf_dev_p58_get_shared_tbl_increment(struct tf *tfp __rte_unused, case TF_TBL_TYPE_ACT_ENCAP_16B: case TF_TBL_TYPE_ACT_ENCAP_32B: case TF_TBL_TYPE_ACT_ENCAP_64B: + case TF_TBL_TYPE_ACT_ENCAP_128B: case TF_TBL_TYPE_ACT_SP_SMAC: case TF_TBL_TYPE_ACT_SP_SMAC_IPV4: case TF_TBL_TYPE_ACT_SP_SMAC_IPV6: @@ -461,7 +480,7 @@ static int tf_dev_p58_get_shared_tbl_increment(struct tf *tfp __rte_unused, case TF_TBL_TYPE_ACT_MODIFY_16B: case TF_TBL_TYPE_ACT_MODIFY_32B: case TF_TBL_TYPE_ACT_MODIFY_64B: - parms->increment_cnt = 8; + parms->increment_cnt = 16; break; default: parms->increment_cnt = 1; @@ -493,6 +512,7 @@ static bool tf_dev_p58_is_sram_managed(struct tf *tfp __rte_unused, case TF_TBL_TYPE_ACT_ENCAP_16B: case TF_TBL_TYPE_ACT_ENCAP_32B: case TF_TBL_TYPE_ACT_ENCAP_64B: + case TF_TBL_TYPE_ACT_ENCAP_128B: case TF_TBL_TYPE_ACT_SP_SMAC: case TF_TBL_TYPE_ACT_SP_SMAC_IPV4: case TF_TBL_TYPE_ACT_SP_SMAC_IPV6: @@ -527,7 +547,7 @@ static bool tf_dev_p58_is_sram_managed(struct tf *tfp __rte_unused, * * [in/out] shift * Pointer to the factor to be used as a multiplier to translate - * between the RM units to the user address. SRAM manages 64B entries + * between the RM units to the user address. SRAM manages 128B entries * Addresses must be shifted to an 8B address. * * Returns diff --git a/drivers/net/bnxt/tf_core/tf_em_common.c b/drivers/net/bnxt/tf_core/tf_em_common.c index b56b7cc188..c518150d1f 100644 --- a/drivers/net/bnxt/tf_core/tf_em_common.c +++ b/drivers/net/bnxt/tf_core/tf_em_common.c @@ -1000,8 +1000,8 @@ tf_em_ext_common_unbind(struct tf *tfp) strerror(-rc)); return rc; } - ext_db = (struct em_ext_db *)ext_ptr; + ext_db = (struct em_ext_db *)ext_ptr; if (ext_db != NULL) { entry = ext_db->tbl_scope_ll.head; while (entry != NULL) { diff --git a/drivers/net/bnxt/tf_core/tf_em_internal.c b/drivers/net/bnxt/tf_core/tf_em_internal.c index 8ea5d93672..46de63a9da 100644 --- a/drivers/net/bnxt/tf_core/tf_em_internal.c +++ b/drivers/net/bnxt/tf_core/tf_em_internal.c @@ -7,7 +7,6 @@ #include #include #include - #include "tf_core.h" #include "tf_util.h" #include "tf_common.h" @@ -63,7 +62,6 @@ tf_em_insert_int_entry(struct tf *tfp, return -1; } - rptr_index = index; rc = tf_msg_insert_em_internal_entry(tfp, parms, @@ -75,6 +73,7 @@ tf_em_insert_int_entry(struct tf *tfp, dpool_free(pool, index); return -1; } + TF_SET_GFID(gfid, ((rptr_index << TF_EM_INTERNAL_INDEX_SHIFT) | rptr_entry), @@ -95,7 +94,6 @@ tf_em_insert_int_entry(struct tf *tfp, return 0; } - /** Delete EM internal entry API * * returns: @@ -253,7 +251,6 @@ tf_em_int_bind(struct tf *tfp, return db_rc[TF_DIR_RX]; } - if (!tf_session_is_shared_session(tfs)) { for (i = 0; i < TF_DIR_MAX; i++) { iparms.rm_db = em_db->em_db[i]; @@ -335,11 +332,10 @@ tf_em_int_unbind(struct tf *tfp) } rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr); - if (rc) { + if (rc) return 0; - } - em_db = (struct em_rm_db *)em_db_ptr; + em_db = (struct em_rm_db *)em_db_ptr; for (i = 0; i < TF_DIR_MAX; i++) { if (em_db->em_db[i] == NULL) continue; diff --git a/drivers/net/bnxt/tf_core/tf_identifier.c b/drivers/net/bnxt/tf_core/tf_identifier.c index 1846675916..7d9d9595dd 100644 --- a/drivers/net/bnxt/tf_core/tf_identifier.c +++ b/drivers/net/bnxt/tf_core/tf_identifier.c @@ -89,6 +89,7 @@ tf_ident_unbind(struct tf *tfp) rc = tf_session_get_db(tfp, TF_MODULE_TYPE_IDENTIFIER, &ident_db_ptr); if (rc) return 0; + ident_db = (struct ident_rm_db *)ident_db_ptr; for (i = 0; i < TF_DIR_MAX; i++) { diff --git a/drivers/net/bnxt/tf_core/tf_if_tbl.c b/drivers/net/bnxt/tf_core/tf_if_tbl.c index e667d6fa6d..578d361417 100644 --- a/drivers/net/bnxt/tf_core/tf_if_tbl.c +++ b/drivers/net/bnxt/tf_core/tf_if_tbl.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ @@ -21,12 +21,6 @@ struct tf_if_tbl_db { struct tf_if_tbl_cfg *if_tbl_cfg_db[TF_DIR_MAX]; }; -/** - * Init flag, set on bind and cleared on unbind - * TODO: Store this data in session db - */ -static uint8_t init; - /** * Convert if_tbl_type to hwrm type. * @@ -80,8 +74,6 @@ tf_if_tbl_bind(struct tf *tfp, if_tbl_db->if_tbl_cfg_db[TF_DIR_TX] = parms->cfg; tf_session_set_if_tbl_db(tfp, (void *)if_tbl_db); - init = 1; - TFP_DRV_LOG(INFO, "Table Type - initialized\n"); @@ -92,14 +84,7 @@ int tf_if_tbl_unbind(struct tf *tfp) { int rc; - struct tf_if_tbl_db *if_tbl_db_ptr; - - /* Bail if nothing has been initialized */ - if (!init) { - TFP_DRV_LOG(INFO, - "No Table DBs created\n"); - return 0; - } + struct tf_if_tbl_db *if_tbl_db_ptr = NULL; TF_CHECK_PARMS1(tfp); @@ -108,9 +93,15 @@ tf_if_tbl_unbind(struct tf *tfp) TFP_DRV_LOG(INFO, "No IF Table DBs initialized\n"); return 0; } + /* Bail if nothing has been initialized */ + if (!if_tbl_db_ptr) { + TFP_DRV_LOG(INFO, + "No Table DBs created\n"); + return 0; + } tfp_free((void *)if_tbl_db_ptr); - init = 0; + tf_session_set_if_tbl_db(tfp, NULL); return 0; } @@ -120,24 +111,24 @@ tf_if_tbl_set(struct tf *tfp, struct tf_if_tbl_set_parms *parms) { int rc; - struct tf_if_tbl_db *if_tbl_db_ptr; + struct tf_if_tbl_db *if_tbl_db_ptr = NULL; struct tf_if_tbl_get_hcapi_parms hparms; TF_CHECK_PARMS3(tfp, parms, parms->data); - if (!init) { - TFP_DRV_LOG(ERR, - "%s: No Table DBs created\n", - tf_dir_2_str(parms->dir)); - return -EINVAL; - } - rc = tf_session_get_if_tbl_db(tfp, (void **)&if_tbl_db_ptr); if (rc) { TFP_DRV_LOG(INFO, "No IF Table DBs initialized\n"); return 0; } + if (!if_tbl_db_ptr) { + TFP_DRV_LOG(ERR, + "%s: No Table DBs created\n", + tf_dir_2_str(parms->dir)); + return -EINVAL; + } + /* Convert TF type to HCAPI type */ hparms.tbl_db = if_tbl_db_ptr->if_tbl_cfg_db[parms->dir]; hparms.db_index = parms->type; @@ -163,24 +154,24 @@ tf_if_tbl_get(struct tf *tfp, struct tf_if_tbl_get_parms *parms) { int rc = 0; - struct tf_if_tbl_db *if_tbl_db_ptr; + struct tf_if_tbl_db *if_tbl_db_ptr = NULL; struct tf_if_tbl_get_hcapi_parms hparms; TF_CHECK_PARMS3(tfp, parms, parms->data); - if (!init) { - TFP_DRV_LOG(ERR, - "%s: No Table DBs created\n", - tf_dir_2_str(parms->dir)); - return -EINVAL; - } - rc = tf_session_get_if_tbl_db(tfp, (void **)&if_tbl_db_ptr); if (rc) { TFP_DRV_LOG(INFO, "No IF Table DBs initialized\n"); return 0; } + if (!if_tbl_db_ptr) { + TFP_DRV_LOG(ERR, + "%s: No Table DBs created\n", + tf_dir_2_str(parms->dir)); + return -EINVAL; + } + /* Convert TF type to HCAPI type */ hparms.tbl_db = if_tbl_db_ptr->if_tbl_cfg_db[parms->dir]; hparms.db_index = parms->type; diff --git a/drivers/net/bnxt/tf_core/tf_msg.c b/drivers/net/bnxt/tf_core/tf_msg.c index fbc96d374c..1c66c7e01a 100644 --- a/drivers/net/bnxt/tf_core/tf_msg.c +++ b/drivers/net/bnxt/tf_core/tf_msg.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ @@ -47,7 +47,6 @@ static_assert(sizeof(struct hwrm_tf_global_cfg_set_input) == static_assert(sizeof(struct hwrm_tf_em_insert_input) == TF_MSG_SIZE_HWRM_TF_EM_INSERT, "HWRM message size changed: hwrm_tf_em_insert_input"); - #define TF_MSG_SIZE_HWRM_TF_TBL_TYPE_SET 128 static_assert(sizeof(struct hwrm_tf_tbl_type_set_input) == TF_MSG_SIZE_HWRM_TF_TBL_TYPE_SET, @@ -61,13 +60,18 @@ static_assert(sizeof(struct hwrm_tf_tbl_type_set_input) == /** * This is the length of shared session name "tf_share" */ -#define TF_SHARED_SESSION_NAME_LEN 8 +#define TF_SHARED_SESSION_NAME_LEN 9 /** * This is the length of tcam shared session name "tf_shared-wc_tcam" */ #define TF_TCAM_SHARED_SESSION_NAME_LEN 17 +/** + * This is the length of tcam shared session name "tf_shared-poolx" + */ +#define TF_POOL_SHARED_SESSION_NAME_LEN 16 + /** * If data bigger than TF_PCI_BUF_SIZE_MAX then use DMA method */ @@ -135,18 +139,30 @@ tf_msg_session_open(struct bnxt *bp, struct hwrm_tf_session_open_input req = { 0 }; struct hwrm_tf_session_open_output resp = { 0 }; struct tfp_send_msg_parms parms = { 0 }; - int name_len; char *session_name; char *tcam_session_name; + char *pool_session_name; - /* Populate the request */ - name_len = strnlen(ctrl_chan_name, TF_SESSION_NAME_MAX); - session_name = &ctrl_chan_name[name_len - strlen("tf_shared")]; - tcam_session_name = &ctrl_chan_name[name_len - strlen("tf_shared-wc_tcam")]; - if (!strncmp(tcam_session_name, "tf_shared-wc_tcam", strlen("tf_shared-wc_tcam"))) - tfp_memcpy(&req.session_name, tcam_session_name, TF_TCAM_SHARED_SESSION_NAME_LEN); - else if (!strncmp(session_name, "tf_shared", strlen("tf_shared"))) - tfp_memcpy(&req.session_name, session_name, TF_SHARED_SESSION_NAME_LEN); + /* + * "tf_shared-wc_tcam" is defined for tf_fw version 1.0.0. + * "tf_shared-pool" is defined for version 1.0.1. + * "tf_shared" is used by both verions. + */ + tcam_session_name = strstr(ctrl_chan_name, "tf_shared-wc_tcam"); + pool_session_name = strstr(ctrl_chan_name, "tf_shared-pool"); + session_name = strstr(ctrl_chan_name, "tf_shared"); + if (tcam_session_name) + tfp_memcpy(&req.session_name, + tcam_session_name, + TF_TCAM_SHARED_SESSION_NAME_LEN); + else if (pool_session_name) + tfp_memcpy(&req.session_name, + pool_session_name, + TF_POOL_SHARED_SESSION_NAME_LEN); + else if (session_name) + tfp_memcpy(&req.session_name, + session_name, + TF_SHARED_SESSION_NAME_LEN); else tfp_memcpy(&req.session_name, ctrl_chan_name, TF_SESSION_NAME_MAX); @@ -191,9 +207,9 @@ tf_msg_session_client_register(struct tf *tfp, struct tfp_send_msg_parms parms = { 0 }; uint8_t fw_session_id; struct tf_dev_info *dev; - int name_len; char *session_name; char *tcam_session_name; + char *pool_session_name; /* Retrieve the device information */ rc = tf_session_get_device(tfs, &dev); @@ -214,24 +230,31 @@ tf_msg_session_client_register(struct tf *tfp, /* Populate the request */ req.fw_session_id = tfp_cpu_to_le_32(fw_session_id); - name_len = strnlen(ctrl_channel_name, TF_SESSION_NAME_MAX); - session_name = &ctrl_channel_name[name_len - strlen("tf_shared")]; - tcam_session_name = &ctrl_channel_name[name_len - - strlen("tf_shared-wc_tcam")]; - if (!strncmp(tcam_session_name, - "tf_shared-wc_tcam", - strlen("tf_shared-wc_tcam"))) + + /* + * "tf_shared-wc_tcam" is defined for tf_fw version 1.0.0. + * "tf_shared-pool" is defined for version 1.0.1. + * "tf_shared" is used by both verions. + */ + tcam_session_name = strstr(ctrl_channel_name, "tf_shared-wc_tcam"); + pool_session_name = strstr(ctrl_channel_name, "tf_shared-pool"); + session_name = strstr(ctrl_channel_name, "tf_shared"); + if (tcam_session_name) + tfp_memcpy(&req.session_client_name, + tcam_session_name, + TF_TCAM_SHARED_SESSION_NAME_LEN); + else if (pool_session_name) tfp_memcpy(&req.session_client_name, - tcam_session_name, - TF_TCAM_SHARED_SESSION_NAME_LEN); - else if (!strncmp(session_name, "tf_shared", strlen("tf_shared"))) + pool_session_name, + TF_POOL_SHARED_SESSION_NAME_LEN); + else if (session_name) tfp_memcpy(&req.session_client_name, - session_name, - TF_SHARED_SESSION_NAME_LEN); + session_name, + TF_SHARED_SESSION_NAME_LEN); else tfp_memcpy(&req.session_client_name, - ctrl_channel_name, - TF_SESSION_NAME_MAX); + ctrl_channel_name, + TF_SESSION_NAME_MAX); parms.tf_type = HWRM_TF_SESSION_REGISTER; parms.req_data = (uint32_t *)&req; @@ -431,7 +454,6 @@ tf_msg_session_resc_qcaps(struct tf *tfp, /* Post process the response */ data = (struct tf_rm_resc_req_entry *)qcaps_buf.va_addr; - for (i = 0; i < resp.size; i++) { query[i].type = tfp_le_to_cpu_32(data[i].type); query[i].min = tfp_le_to_cpu_16(data[i].min); @@ -1757,6 +1779,7 @@ tf_msg_set_tbl_entry(struct tf *tfp, struct hwrm_tf_tbl_type_set_input req = { 0 }; struct hwrm_tf_tbl_type_set_output resp = { 0 }; struct tfp_send_msg_parms parms = { 0 }; + struct tf_msg_dma_buf buf = { 0 }; uint8_t fw_session_id; struct tf_dev_info *dev; struct tf_session *tfs; @@ -1802,18 +1825,19 @@ tf_msg_set_tbl_entry(struct tf *tfp, /* Check for data size conformity */ if (size > TF_MSG_TBL_TYPE_SET_DATA_SIZE) { - rc = -EINVAL; - TFP_DRV_LOG(ERR, - "%s: Invalid parameters for msg type, rc:%s\n", - tf_dir_2_str(dir), - strerror(-rc)); - return rc; + /* use dma buffer */ + req.flags |= HWRM_TF_TBL_TYPE_SET_INPUT_FLAGS_DMA; + rc = tf_msg_alloc_dma_buf(&buf, size); + if (rc) + goto cleanup; + tfp_memcpy(buf.va_addr, data, size); + tfp_memcpy(&req.data[0], + &buf.pa_addr, + sizeof(buf.pa_addr)); + } else { + tfp_memcpy(&req.data, data, size); } - tfp_memcpy(&req.data, - data, - size); - parms.tf_type = HWRM_TF_TBL_TYPE_SET; parms.req_data = (uint32_t *)&req; parms.req_size = sizeof(req); @@ -1823,10 +1847,10 @@ tf_msg_set_tbl_entry(struct tf *tfp, rc = tfp_send_msg_direct(tf_session_get_bp(tfp), &parms); - if (rc) - return rc; +cleanup: + tf_msg_free_dma_buf(&buf); - return 0; + return rc; } int @@ -2325,3 +2349,114 @@ tf_msg_get_version(struct bnxt *bp, return rc; } + +int +tf_msg_session_set_hotup_state(struct tf *tfp, uint16_t state) +{ + int rc; + struct hwrm_tf_session_hotup_state_set_input req = { 0 }; + struct hwrm_tf_session_hotup_state_set_output resp = { 0 }; + struct tfp_send_msg_parms parms = { 0 }; + uint8_t fw_session_id; + struct tf_dev_info *dev; + struct tf_session *tfs; + + /* Retrieve the session information */ + rc = tf_session_get_session_internal(tfp, &tfs); + if (rc) { + TFP_DRV_LOG(ERR, + "Failed to lookup session, rc:%s\n", + strerror(-rc)); + return rc; + } + + /* Retrieve the device information */ + rc = tf_session_get_device(tfs, &dev); + if (rc) { + TFP_DRV_LOG(ERR, + "Failed to lookup device, rc:%s\n", + strerror(-rc)); + return rc; + } + + rc = tf_session_get_fw_session_id(tfp, &fw_session_id); + if (rc) { + TFP_DRV_LOG(ERR, + "Unable to lookup FW id, rc:%s\n", + strerror(-rc)); + return rc; + } + + /* Populate the request */ + req.fw_session_id = tfp_cpu_to_le_32(fw_session_id); + req.state = tfp_cpu_to_le_16(state); + + parms.tf_type = HWRM_TF_SESSION_HOTUP_STATE_SET; + parms.req_data = (uint32_t *)&req; + parms.req_size = sizeof(req); + parms.resp_data = (uint32_t *)&resp; + parms.resp_size = sizeof(resp); + parms.mailbox = dev->ops->tf_dev_get_mailbox(); + + rc = tfp_send_msg_direct(tf_session_get_bp(tfp), + &parms); + return rc; +} + +int +tf_msg_session_get_hotup_state(struct tf *tfp, + uint16_t *state, + uint16_t *ref_cnt) +{ + int rc; + struct hwrm_tf_session_hotup_state_get_input req = { 0 }; + struct hwrm_tf_session_hotup_state_get_output resp = { 0 }; + struct tfp_send_msg_parms parms = { 0 }; + uint8_t fw_session_id; + struct tf_dev_info *dev; + struct tf_session *tfs; + + /* Retrieve the session information */ + rc = tf_session_get_session_internal(tfp, &tfs); + if (rc) { + TFP_DRV_LOG(ERR, + "Failed to lookup session, rc:%s\n", + strerror(-rc)); + return rc; + } + + /* Retrieve the device information */ + rc = tf_session_get_device(tfs, &dev); + if (rc) { + TFP_DRV_LOG(ERR, + "Failed to lookup device, rc:%s\n", + strerror(-rc)); + return rc; + } + + rc = tf_session_get_fw_session_id(tfp, &fw_session_id); + if (rc) { + TFP_DRV_LOG(ERR, + "Unable to lookup FW id, rc:%s\n", + strerror(-rc)); + return rc; + } + + /* Populate the request */ + req.fw_session_id = tfp_cpu_to_le_32(fw_session_id); + + parms.tf_type = HWRM_TF_SESSION_HOTUP_STATE_GET; + parms.req_data = (uint32_t *)&req; + parms.req_size = sizeof(req); + parms.resp_data = (uint32_t *)&resp; + parms.resp_size = sizeof(resp); + parms.mailbox = dev->ops->tf_dev_get_mailbox(); + + rc = tfp_send_msg_direct(tf_session_get_bp(tfp), + &parms); + + *state = tfp_le_to_cpu_16(resp.state); + *ref_cnt = tfp_le_to_cpu_16(resp.ref_cnt); + + return rc; +} diff --git a/drivers/net/bnxt/tf_core/tf_msg.h b/drivers/net/bnxt/tf_core/tf_msg.h index 188b361d71..24d0ae5f43 100644 --- a/drivers/net/bnxt/tf_core/tf_msg.h +++ b/drivers/net/bnxt/tf_core/tf_msg.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ @@ -761,4 +761,40 @@ int tf_msg_get_version(struct bnxt *bp, struct tf_dev_info *dev, struct tf_get_version_parms *parms); + +/** + * Send set hot upgrade state request to the firmware. + * + * [in] tfp + * Pointer to session handle + * + * [in] state + * Hot upgrade session state + * + * Returns: + * 0 on Success else internal Truflow error + */ +int +tf_msg_session_set_hotup_state(struct tf *tfp, + uint16_t state); + +/** + * Send get hot upgrade state request to the firmware. + * + * [in] tfp + * Pointer to session handle + * + * [out] state + * Pointer to hot upgrade session state + * + * [out] ref_cnt + * Pointer to hot upgrade session reference count + * + * Returns: + * 0 on Success else internal Truflow error + */ +int +tf_msg_session_get_hotup_state(struct tf *tfp, + uint16_t *state, + uint16_t *ref_cnt); #endif /* _TF_MSG_H_ */ diff --git a/drivers/net/bnxt/tf_core/tf_rm.c b/drivers/net/bnxt/tf_core/tf_rm.c index d2045921b9..1fccb698d0 100644 --- a/drivers/net/bnxt/tf_core/tf_rm.c +++ b/drivers/net/bnxt/tf_core/tf_rm.c @@ -1,15 +1,12 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ #include - #include #include - #include - #include "tf_rm.h" #include "tf_common.h" #include "tf_util.h" @@ -18,9 +15,6 @@ #include "tfp.h" #include "tf_msg.h" -/* Logging defines */ -#define TF_RM_DEBUG 0 - /** * Generic RM Element data type that an RM DB is build upon. */ @@ -210,45 +204,6 @@ tf_rm_adjust_index(struct tf_rm_element *db, return rc; } -/** - * Logs an array of found residual entries to the console. - * - * [in] dir - * Receive or transmit direction - * - * [in] module - * Type of Device Module - * - * [in] count - * Number of entries in the residual array - * - * [in] residuals - * Pointer to an array of residual entries. Array is index same as - * the DB in which this function is used. Each entry holds residual - * value for that entry. - */ -#if (TF_RM_DEBUG == 1) -static void -tf_rm_log_residuals(enum tf_dir dir, - enum tf_module_type module, - uint16_t count, - uint16_t *residuals) -{ - int i; - - /* Walk the residual array and log the types that wasn't - * cleaned up to the console. - */ - for (i = 0; i < count; i++) { - if (residuals[i] != 0) - TFP_DRV_LOG(INFO, - "%s, %s was not cleaned up, %d outstanding\n", - tf_dir_2_str(dir), - tf_module_subtype_2_str(module, i), - residuals[i]); - } -} -#endif /* TF_RM_DEBUG == 1 */ /** * Performs a check of the passed in DB for any lingering elements. If * a resource type was found to not have been cleaned up by the caller @@ -364,12 +319,6 @@ tf_rm_check_residuals(struct tf_rm_new_db *rm_db, *resv_size = found; } -#if (TF_RM_DEBUG == 1) - tf_rm_log_residuals(rm_db->dir, - rm_db->module, - rm_db->num_entries, - residuals); -#endif tfp_free((void *)residuals); *resv = local_resv; @@ -419,7 +368,7 @@ tf_rm_update_parent_reservations(struct tf *tfp, bool shared_session) { int parent, child; - const char *type_str; + const char *type_str = NULL; /* Search through all the elements */ for (parent = 0; parent < num_elements; parent++) { @@ -444,11 +393,6 @@ tf_rm_update_parent_reservations(struct tf *tfp, dev->ops->tf_dev_get_resource_str(tfp, cfg[parent].hcapi_type, &type_str); -#if (TF_RM_DEBUG == 1) - printf("%s:%s cnt(%d) slices(%d)\n", - type_str, tf_tbl_type_2_str(parent), - alloc_cnt[parent], p_slices); -#endif /* (TF_RM_DEBUG == 1) */ } /* Search again through all the elements */ @@ -469,13 +413,7 @@ tf_rm_update_parent_reservations(struct tf *tfp, dev->ops->tf_dev_get_resource_str(tfp, cfg[child].hcapi_type, &type_str); -#if (TF_RM_DEBUG == 1) - printf("%s:%s cnt(%d) slices(%d)\n", - type_str, - tf_tbl_type_2_str(child), - alloc_cnt[child], - c_slices); -#endif /* (TF_RM_DEBUG == 1) */ + /* Increment the parents combined count * with each child's count adjusted for * number of slices per RM alloc item. @@ -492,10 +430,6 @@ tf_rm_update_parent_reservations(struct tf *tfp, } /* Save the parent count to be requested */ req_cnt[parent] = combined_cnt; -#if (TF_RM_DEBUG == 1) - printf("%s calculated total:%d\n\n", - type_str, req_cnt[parent]); -#endif /* (TF_RM_DEBUG == 1) */ } } return 0; @@ -595,12 +529,6 @@ tf_rm_create_db(struct tf *tfp, &hcapi_items); if (hcapi_items == 0) { -#if (TF_RM_DEBUG == 1) - TFP_DRV_LOG(INFO, - "%s: module: %s Empty RM DB create request\n", - tf_dir_2_str(parms->dir), - tf_module_2_str(parms->module)); -#endif parms->rm_db = NULL; return -ENOMEM; } @@ -746,7 +674,7 @@ tf_rm_create_db(struct tf *tfp, rc = ba_init(db[i].pool, resv[j].stride, - !tf_session_is_shared_session(tfs)); + true); if (rc) { TFP_DRV_LOG(ERR, "%s: Pool init failed, type:%d:%s\n", @@ -773,13 +701,6 @@ tf_rm_create_db(struct tf *tfp, rm_db->module = parms->module; *parms->rm_db = (void *)rm_db; -#if (TF_RM_DEBUG == 1) - - printf("%s: module:%s\n", - tf_dir_2_str(parms->dir), - tf_module_2_str(parms->module)); -#endif /* (TF_RM_DEBUG == 1) */ - tfp_free((void *)req); tfp_free((void *)resv); tfp_free((void *)req_cnt); @@ -812,6 +733,7 @@ tf_rm_create_db_no_reservation(struct tf *tfp, struct tf_rm_new_db *rm_db; struct tf_rm_element *db; uint32_t pool_size; + bool shared_session = 0; TF_CHECK_PARMS2(tfp, parms); @@ -841,6 +763,16 @@ tf_rm_create_db_no_reservation(struct tf *tfp, tfp_memcpy(req_cnt, parms->alloc_cnt, parms->num_elements * sizeof(uint16_t)); + shared_session = tf_session_is_shared_session(tfs); + + /* Update the req_cnt based upon the element configuration + */ + tf_rm_update_parent_reservations(tfp, dev, parms->cfg, + parms->alloc_cnt, + parms->num_elements, + req_cnt, + shared_session); + /* Process capabilities against DB requirements. However, as a * DB can hold elements that are not HCAPI we can reduce the * req msg content by removing those out of the request yet @@ -855,11 +787,6 @@ tf_rm_create_db_no_reservation(struct tf *tfp, &hcapi_items); if (hcapi_items == 0) { - TFP_DRV_LOG(ERR, - "%s: module:%s Empty RM DB create request\n", - tf_dir_2_str(parms->dir), - tf_module_2_str(parms->module)); - parms->rm_db = NULL; return -ENOMEM; } @@ -938,6 +865,7 @@ tf_rm_create_db_no_reservation(struct tf *tfp, db[i].cfg_type = cfg->cfg_type; db[i].hcapi_type = cfg->hcapi_type; + db[i].slices = cfg->slices; /* Save the parent subtype for later use to find the pool */ @@ -986,7 +914,7 @@ tf_rm_create_db_no_reservation(struct tf *tfp, rc = ba_init(db[i].pool, resv[j].stride, - !tf_session_is_shared_session(tfs)); + true); if (rc) { TFP_DRV_LOG(ERR, "%s: Pool init failed, type:%d:%s\n", @@ -1013,13 +941,6 @@ tf_rm_create_db_no_reservation(struct tf *tfp, rm_db->module = parms->module; *parms->rm_db = (void *)rm_db; -#if (TF_RM_DEBUG == 1) - - printf("%s: module:%s\n", - tf_dir_2_str(parms->dir), - tf_module_2_str(parms->module)); -#endif /* (TF_RM_DEBUG == 1) */ - tfp_free((void *)req); tfp_free((void *)resv); tfp_free((void *)req_cnt); @@ -1036,6 +957,7 @@ tf_rm_create_db_no_reservation(struct tf *tfp, return -EINVAL; } + int tf_rm_free_db(struct tf *tfp, struct tf_rm_free_db_parms *parms) @@ -1110,6 +1032,7 @@ tf_rm_free_db(struct tf *tfp, return rc; } + /** * Get the bit allocator pool associated with the subtype and the db * @@ -1388,6 +1311,7 @@ tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms) return 0; } + int tf_rm_get_slices(struct tf_rm_get_slices_parms *parms) { @@ -1440,6 +1364,7 @@ tf_rm_get_inuse_count(struct tf_rm_get_inuse_count_parms *parms) return rc; } + /* Only used for table bulk get at this time */ int diff --git a/drivers/net/bnxt/tf_core/tf_session.c b/drivers/net/bnxt/tf_core/tf_session.c index 2373facc95..321dc52dd1 100644 --- a/drivers/net/bnxt/tf_core/tf_session.c +++ b/drivers/net/bnxt/tf_core/tf_session.c @@ -1,12 +1,10 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ #include - #include - #include "tf_session.h" #include "tf_common.h" #include "tf_msg.h" @@ -59,8 +57,9 @@ tf_session_create(struct tf *tfp, union tf_session_id *session_id; struct tf_dev_info dev; bool shared_session_creator; - int name_len; - char *name; + char *shared_name; + char *tcam_session_name; + char *pool_session_name; TF_CHECK_PARMS2(tfp, parms); @@ -180,16 +179,18 @@ tf_session_create(struct tf *tfp, session->em_ext_db_handle = NULL; /* Populate the request */ - name_len = strnlen(parms->open_cfg->ctrl_chan_name, - TF_SESSION_NAME_MAX); - name = &parms->open_cfg->ctrl_chan_name[name_len - strlen("tf_shared")]; - if (!strncmp(name, "tf_shared", strlen("tf_shared"))) - session->shared_session = true; - - name = &parms->open_cfg->ctrl_chan_name[name_len - - strlen("tf_shared-wc_tcam")]; - if (!strncmp(name, "tf_shared-wc_tcam", strlen("tf_shared-wc_tcam"))) + shared_name = strstr(parms->open_cfg->ctrl_chan_name, "tf_shared"); + if (shared_name) { session->shared_session = true; + /* + * "tf_shared-wc_tcam" is defined for tf_fw version 1.0.0. + * "tf_shared-pool" is defined for version 1.0.1. + */ + tcam_session_name = strstr(parms->open_cfg->ctrl_chan_name, "tf_shared-wc_tcam"); + pool_session_name = strstr(parms->open_cfg->ctrl_chan_name, "tf_shared-pool"); + if (tcam_session_name || pool_session_name) + session->shared_session_hotup = true; + } if (session->shared_session && shared_session_creator) { session->shared_session_creator = true; @@ -342,7 +343,6 @@ tf_session_client_create(struct tf *tfp, return rc; } - /** * Destroys a Session Client on an existing Session. * @@ -441,7 +441,7 @@ tf_session_open_session(struct tf *tfp, TFP_DRV_LOG(INFO, "Session created, session_client_id:%d," - "session_id:0x%08x, fw_session_id:%d\n", + " session_id:0x%08x, fw_session_id:%d\n", parms->open_cfg->session_client_id.id, parms->open_cfg->session_id.id, parms->open_cfg->session_id.internal.fw_session_id); @@ -462,7 +462,7 @@ tf_session_open_session(struct tf *tfp, } TFP_DRV_LOG(INFO, - "Session Client:%d registered on session:0x%8x\n", + "Session Client:%d registered on session:0x%08x\n", scparms.session_client_id->internal.fw_session_client_id, tfp->session->session_id.id); } @@ -535,6 +535,11 @@ tf_session_close_session(struct tf *tfp, return rc; } + /* Record the session we're closing so the caller knows the + * details. + */ + *parms->session_id = tfs->session_id; + /* In case multiple clients we chose to close those first */ if (tfs->ref_count > 1) { /* Linaro gcc can't static init this structure */ @@ -567,11 +572,6 @@ tf_session_close_session(struct tf *tfp, return 0; } - /* Record the session we're closing so the caller knows the - * details. - */ - *parms->session_id = tfs->session_id; - rc = tf_session_get_device(tfs, &tfd); if (rc) { TFP_DRV_LOG(ERR, @@ -1140,3 +1140,71 @@ tf_session_set_if_tbl_db(struct tf *tfp, tfs->if_tbl_db_handle = if_tbl_handle; return rc; } + +int +tf_session_set_hotup_state(struct tf *tfp, + struct tf_set_session_hotup_state_parms *parms) +{ + int rc = 0; + struct tf_session *tfs = NULL; + + rc = tf_session_get_session(tfp, &tfs); + if (rc) { + TFP_DRV_LOG(ERR, + "Session lookup failed, rc:%s\n", + strerror(-rc)); + return rc; + } + + if (!tf_session_is_shared_session(tfs)) { + rc = -EINVAL; + TFP_DRV_LOG(ERR, + "Only shared session able to set state, rc:%s\n", + strerror(-rc)); + return rc; + } + + rc = tf_msg_session_set_hotup_state(tfp, parms->state); + if (rc) { + /* Log error */ + TFP_DRV_LOG(ERR, + "Set session hot upgrade state failed, rc:%s\n", + strerror(-rc)); + } + + return rc; +} + +int +tf_session_get_hotup_state(struct tf *tfp, + struct tf_get_session_hotup_state_parms *parms) +{ + int rc = 0; + struct tf_session *tfs = NULL; + + rc = tf_session_get_session(tfp, &tfs); + if (rc) { + TFP_DRV_LOG(ERR, + "Session lookup failed, rc:%s\n", + strerror(-rc)); + return rc; + } + + if (!tf_session_is_shared_session(tfs)) { + rc = -EINVAL; + TFP_DRV_LOG(ERR, + "Only shared session able to get state, rc:%s\n", + strerror(-rc)); + return rc; + } + + rc = tf_msg_session_get_hotup_state(tfp, &parms->state, &parms->ref_cnt); + if (rc) { + /* Log error */ + TFP_DRV_LOG(ERR, + "Get session hot upgrade state failed, rc:%s\n", + strerror(-rc)); + } + + return rc; +} diff --git a/drivers/net/bnxt/tf_core/tf_session.h b/drivers/net/bnxt/tf_core/tf_session.h index 5a94b941fa..9bbbccf125 100644 --- a/drivers/net/bnxt/tf_core/tf_session.h +++ b/drivers/net/bnxt/tf_core/tf_session.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ @@ -8,7 +8,6 @@ #include #include - #include "bitalloc.h" #include "tf_core.h" #include "tf_device.h" @@ -48,7 +47,7 @@ * * Shared memory containing private TruFlow session information. * Through this structure the session can keep track of resource - * allocations. It also holds info about Session Clients. + * allocations. It also holds info about Session Clients. * * Memory is assigned to the Truflow instance by way of * tf_open_session. Memory is allocated and owned by i.e. ULP. @@ -78,6 +77,11 @@ struct tf_session { */ bool shared_session; + /** + * Boolean controlling the split of hardware resources for hotupgrade. + */ + bool shared_session_hotup; + /** * This flag indicates the shared session on firmware side is created * by this session. Some privileges may be assigned to this session. @@ -169,6 +173,12 @@ struct tf_session { * Number of slices per row for WC TCAM */ uint16_t wc_num_slices_per_row; + + /** + * Indicates if TCAM is controlled by TCAM Manager + */ + int tcam_mgr_control[TF_DIR_MAX][TF_TCAM_TBL_TYPE_MAX]; + }; /** @@ -276,11 +286,9 @@ struct tf_session_close_session_parms { * * @ref tf_session_is_shared_session * - * #define TF_SHARED * @ref tf_session_get_tcam_shared_db * * @ref tf_session_set_tcam_shared_db - * #endif * * @ref tf_session_get_sram_db * @@ -588,6 +596,21 @@ tf_session_is_shared_session(struct tf_session *tfs) return tfs->shared_session; } +/** + * Check if the session is shared session for hot upgrade. + * + * [in] session, pointer to the session + * + * Returns: + * - true if it is shared session for hot upgrade + * - false if it is not shared session for hot upgrade + */ +static inline bool +tf_session_is_shared_hotup_session(struct tf_session *tfs) +{ + return tfs->shared_session_hotup; +} + /** * Check if the session is the shared session creator * @@ -716,4 +739,36 @@ tf_session_set_if_tbl_db(struct tf *tfp, int tf_session_get_if_tbl_db(struct tf *tfp, void **if_tbl_handle); + +/** + * Set hot upgrade session state. + * + * [in] tfp + * Pointer to session handle + * + * [in] parms + * Hot upgrade session state parms + * + * Returns: + * 0 on Success else internal Truflow error + */ +int +tf_session_set_hotup_state(struct tf *tfp, + struct tf_set_session_hotup_state_parms *parms); + +/** + * Get hot upgrade session state. + * + * [in] tfp + * Pointer to session handle + * + * [out] parms + * Pointer to hot upgrade session state parms + * + * Returns: + * 0 on Success else internal Truflow error + */ +int +tf_session_get_hotup_state(struct tf *tfp, + struct tf_get_session_hotup_state_parms *parms); #endif /* _TF_SESSION_H_ */ diff --git a/drivers/net/bnxt/tf_core/tf_sram_mgr.c b/drivers/net/bnxt/tf_core/tf_sram_mgr.c index acb3372486..87e8882fed 100644 --- a/drivers/net/bnxt/tf_core/tf_sram_mgr.c +++ b/drivers/net/bnxt/tf_core/tf_sram_mgr.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ #include @@ -21,7 +21,7 @@ /** * TF SRAM block info * - * Contains all the information about a particular 64B SRAM + * Contains all the information about a particular 128B SRAM * block and the slices within it. */ struct tf_sram_block { @@ -36,9 +36,9 @@ struct tf_sram_block { * If a bit is set, it indicates the slice * in the row is in use. */ - uint8_t in_use_mask; + uint16_t in_use_mask; - /** Block id - this is a 64B offset + /** Block id - this is a 128B offset */ uint16_t block_id; }; @@ -46,7 +46,7 @@ struct tf_sram_block { /** * TF SRAM block list * - * List of 64B SRAM blocks used for fixed size slices (8, 16, 32, 64B) + * List of 128B SRAM blocks used for fixed size slices (8, 16, 32, 64B, 128B) */ struct tf_sram_slice_list { /** Pointer to head of linked list of blocks. @@ -70,7 +70,6 @@ struct tf_sram_slice_list { enum tf_sram_slice_size size; }; - /** * TF SRAM bank info consists of lists of different slice sizes per bank */ @@ -111,6 +110,8 @@ const char return "32B slice"; case TF_SRAM_SLICE_SIZE_64B: return "64B slice"; + case TF_SRAM_SLICE_SIZE_128B: + return "128B slice"; default: return "Invalid slice size"; } @@ -179,8 +180,8 @@ static void tf_sram_offset_2_block_id(enum tf_sram_bank_id bank_id, uint16_t offset, uint16_t *block_id, uint16_t *slice_offset) { - *slice_offset = offset & 0x7; - *block_id = ((offset & ~0x7) >> 3) - + *slice_offset = offset & 0xf; + *block_id = ((offset & ~0xf) >> 3) - tf_sram_bank_2_base_offset[bank_id]; } @@ -232,31 +233,37 @@ tf_sram_free_slice(enum tf_sram_slice_size slice_size, bool *block_is_empty) { int rc = 0; - uint8_t shift; - uint8_t slice_mask = 0; + uint16_t shift; + uint16_t slice_mask = 0; TF_CHECK_PARMS2(block, block_is_empty); switch (slice_size) { case TF_SRAM_SLICE_SIZE_8B: shift = slice_offset >> 0; - assert(shift < 8); + assert(shift < 16); slice_mask = 1 << shift; break; case TF_SRAM_SLICE_SIZE_16B: shift = slice_offset >> 1; - assert(shift < 4); + assert(shift < 8); slice_mask = 1 << shift; break; case TF_SRAM_SLICE_SIZE_32B: shift = slice_offset >> 2; - assert(shift < 2); + assert(shift < 4); slice_mask = 1 << shift; break; case TF_SRAM_SLICE_SIZE_64B: + shift = slice_offset >> 3; + assert(shift < 2); + slice_mask = 1 << shift; + break; + + case TF_SRAM_SLICE_SIZE_128B: default: shift = slice_offset >> 0; assert(shift < 1); @@ -294,27 +301,32 @@ tf_sram_get_next_slice_in_block(struct tf_sram_block *block, bool *block_is_full) { int rc, free_id = -1; - uint8_t shift, max_slices, mask, i, full_mask; + uint16_t shift, max_slices, mask, i, full_mask; TF_CHECK_PARMS3(block, slice_offset, block_is_full); switch (slice_size) { case TF_SRAM_SLICE_SIZE_8B: shift = 0; - max_slices = 8; - full_mask = 0xff; + max_slices = 16; + full_mask = 0xffff; break; case TF_SRAM_SLICE_SIZE_16B: shift = 1; - max_slices = 4; - full_mask = 0xf; + max_slices = 8; + full_mask = 0xff; break; case TF_SRAM_SLICE_SIZE_32B: shift = 2; + max_slices = 4; + full_mask = 0xf; + break; + case TF_SRAM_SLICE_SIZE_64B: + shift = 3; max_slices = 2; full_mask = 0x3; break; - case TF_SRAM_SLICE_SIZE_64B: + case TF_SRAM_SLICE_SIZE_128B: default: shift = 0; max_slices = 1; @@ -338,7 +350,6 @@ tf_sram_get_next_slice_in_block(struct tf_sram_block *block, else *block_is_full = false; - if (free_id >= 0) { *slice_offset = free_id << shift; rc = 0; @@ -362,8 +373,8 @@ tf_sram_is_slice_allocated_in_block(struct tf_sram_block *block, bool *is_allocated) { int rc = 0; - uint8_t shift; - uint8_t slice_mask = 0; + uint16_t shift; + uint16_t slice_mask = 0; TF_CHECK_PARMS2(block, is_allocated); @@ -372,23 +383,29 @@ tf_sram_is_slice_allocated_in_block(struct tf_sram_block *block, switch (slice_size) { case TF_SRAM_SLICE_SIZE_8B: shift = slice_offset >> 0; - assert(shift < 8); + assert(shift < 16); slice_mask = 1 << shift; break; case TF_SRAM_SLICE_SIZE_16B: shift = slice_offset >> 1; - assert(shift < 4); + assert(shift < 8); slice_mask = 1 << shift; break; case TF_SRAM_SLICE_SIZE_32B: shift = slice_offset >> 2; - assert(shift < 2); + assert(shift < 4); slice_mask = 1 << shift; break; case TF_SRAM_SLICE_SIZE_64B: + shift = slice_offset >> 3; + assert(shift < 2); + slice_mask = 1 << shift; + break; + + case TF_SRAM_SLICE_SIZE_128B: default: shift = slice_offset >> 0; assert(shift < 1); @@ -416,7 +433,6 @@ tf_sram_get_block_cnt(struct tf_sram_slice_list *slice_list) return slice_list->cnt; } - /** * Free a block data structure - does not free to the RM */ @@ -508,22 +524,26 @@ tf_sram_find_first_not_full_block(struct tf_sram_slice_list *slice_list, struct tf_sram_block **first_not_full_block) { struct tf_sram_block *block = slice_list->head; - uint8_t slice_mask, mask; + uint16_t slice_mask, mask; switch (slice_size) { case TF_SRAM_SLICE_SIZE_8B: - slice_mask = 0xff; + slice_mask = 0xffff; break; case TF_SRAM_SLICE_SIZE_16B: - slice_mask = 0xf; + slice_mask = 0xff; break; case TF_SRAM_SLICE_SIZE_32B: - slice_mask = 0x3; + slice_mask = 0xf; break; case TF_SRAM_SLICE_SIZE_64B: + slice_mask = 0x3; + break; + + case TF_SRAM_SLICE_SIZE_128B: default: slice_mask = 0x1; break; @@ -543,7 +563,7 @@ tf_sram_find_first_not_full_block(struct tf_sram_slice_list *slice_list, static void tf_sram_dump_block(struct tf_sram_block *block) { - TFP_DRV_LOG(INFO, "block_id(0x%x) in_use_mask(0x%02x)\n", + TFP_DRV_LOG(INFO, "block_id(0x%x) in_use_mask(0x%04x)\n", block->block_id, block->in_use_mask); } @@ -631,9 +651,10 @@ int tf_sram_mgr_alloc(void *sram_handle, struct tf_sram *sram; struct tf_sram_slice_list *slice_list; uint16_t block_id, slice_offset = 0; - uint32_t index; + uint32_t index, next_index; struct tf_sram_block *block; struct tf_rm_allocate_parms aparms = { 0 }; + struct tf_rm_free_parms fparms = { 0 }; bool block_is_full; uint16_t block_offset; @@ -662,11 +683,34 @@ int tf_sram_mgr_alloc(void *sram_handle, aparms.subtype = parms->tbl_type; aparms.rm_db = parms->rm_db; rc = tf_rm_allocate(&aparms); + if (rc) + return rc; + /* to support 128B block rows, we are allocating + * 2 sequential 64B blocks from RM, if they are not next to + * each other we are going to have issues + */ + aparms.index = &next_index; + rc = tf_rm_allocate(&aparms); if (rc) return rc; + /* make sure we do get the next 64B block, else free the + * allocated indexes and return error + */ + if (unlikely(index + 1 != next_index)) { + fparms.index = index; + fparms.subtype = parms->tbl_type; + fparms.rm_db = parms->rm_db; + tf_rm_free(&fparms); + fparms.index = next_index; + tf_rm_free(&fparms); + TFP_DRV_LOG(ERR, + "Could not allocate two sequential 64B blocks\n"); + return -ENOMEM; + } block_id = index; block = tf_sram_alloc_block(slice_list, block_id); + } else { /* Block exists */ @@ -742,7 +786,7 @@ tf_sram_mgr_free(void *sram_handle, } #if (STATS_CLEAR_ON_READ_SUPPORT == 0) /* If this is a counter, clear it. In the future we need to switch to - * using the special access registers on Thor to automatically clear on + * using the special access registers on P5 to automatically clear on * read. */ /* If this is counter table, clear the entry on free */ @@ -794,6 +838,13 @@ tf_sram_mgr_free(void *sram_handle, TFP_DRV_LOG(ERR, "Free block_id(%d) failed error(%s)\n", block_id, strerror(-rc)); } + fparms.index = block_id + 1; + rc = tf_rm_free(&fparms); + + if (rc) { + TFP_DRV_LOG(ERR, "Free next block_id(%d) failed error(%s)\n", + block_id + 1, strerror(-rc)); + } /* Free local entry regardless */ tf_sram_free_block(slice_list, block); diff --git a/drivers/net/bnxt/tf_core/tf_sram_mgr.h b/drivers/net/bnxt/tf_core/tf_sram_mgr.h index fc78426130..878195c404 100644 --- a/drivers/net/bnxt/tf_core/tf_sram_mgr.h +++ b/drivers/net/bnxt/tf_core/tf_sram_mgr.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ @@ -26,28 +26,28 @@ */ #define STATS_CLEAR_ON_READ_SUPPORT 0 -#define TF_SRAM_MGR_BLOCK_SZ_BYTES 64 +#define TF_SRAM_MGR_BLOCK_SZ_BYTES 128 #define TF_SRAM_MGR_MIN_SLICE_BYTES 8 /** * TF slice size. * - * A slice is part of a 64B row + * A slice is part of a 128B row * * Each slice is a multiple of 8B */ enum tf_sram_slice_size { - TF_SRAM_SLICE_SIZE_8B, /**< 8 byte SRAM slice */ - TF_SRAM_SLICE_SIZE_16B, /**< 16 byte SRAM slice */ - TF_SRAM_SLICE_SIZE_32B, /**< 32 byte SRAM slice */ - TF_SRAM_SLICE_SIZE_64B, /**< 64 byte SRAM slice */ - TF_SRAM_SLICE_SIZE_MAX /**< slice limit */ + TF_SRAM_SLICE_SIZE_8B, /**< 8 byte SRAM slice */ + TF_SRAM_SLICE_SIZE_16B, /**< 16 byte SRAM slice */ + TF_SRAM_SLICE_SIZE_32B, /**< 32 byte SRAM slice */ + TF_SRAM_SLICE_SIZE_64B, /**< 64 byte SRAM slice */ + TF_SRAM_SLICE_SIZE_128B, /**< 128 byte SRAM slice */ + TF_SRAM_SLICE_SIZE_MAX /**< slice limit */ }; - /** Initialize the SRAM slice manager * - * The SRAM slice manager manages slices within 64B rows. Slices are of size + * The SRAM slice manager manages slices within 128B rows. Slices are of size * tf_sram_slice_size. This function provides a handle to the SRAM manager * data. * @@ -181,7 +181,7 @@ struct tf_sram_mgr_free_parms { /** * Free an SRAM Slice * - * Free an SRAM slice to the indicated bank. This may result in a 64B row + * Free an SRAM slice to the indicated bank. This may result in a 128B row * being returned to the RM SRAM bank pool. * * [in] sram_handle diff --git a/drivers/net/bnxt/tf_core/tf_tbl.c b/drivers/net/bnxt/tf_core/tf_tbl.c index f18e4ba346..f5f3889934 100644 --- a/drivers/net/bnxt/tf_core/tf_tbl.c +++ b/drivers/net/bnxt/tf_core/tf_tbl.c @@ -1,12 +1,11 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ /* Truflow Table APIs and supporting code */ #include - #include "tf_tbl.h" #include "tf_common.h" #include "tf_rm.h" @@ -18,8 +17,8 @@ struct tf; -#define TF_TBL_RM_TO_PTR(new_idx, idx, base, shift) { \ - *(new_idx) = (((idx) + (base)) << (shift)); \ +#define TF_TBL_RM_TO_PTR(new_idx, idx, base, shift) { \ + *(new_idx) = (((idx) + (base)) << (shift)); \ } int @@ -98,6 +97,7 @@ tf_tbl_unbind(struct tf *tfp) rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr); if (rc) return 0; + tbl_db = (struct tbl_rm_db *)tbl_db_ptr; for (i = 0; i < TF_DIR_MAX; i++) { diff --git a/drivers/net/bnxt/tf_core/tf_tbl_sram.c b/drivers/net/bnxt/tf_core/tf_tbl_sram.c index 567f912dfa..3a6f1c68c7 100644 --- a/drivers/net/bnxt/tf_core/tf_tbl_sram.c +++ b/drivers/net/bnxt/tf_core/tf_tbl_sram.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ @@ -73,11 +73,12 @@ const uint16_t tf_tbl_sram_hcapi_2_bank[CFA_RESOURCE_TYPE_P58_LAST] = { * Translate HCAPI type to SRAM Manager bank */ const uint8_t tf_tbl_sram_slices_2_size[TF_TBL_SRAM_SLICES_MAX + 1] = { - [0] = TF_SRAM_SLICE_SIZE_64B, /* if 0 slices assume 1 64B block */ - [1] = TF_SRAM_SLICE_SIZE_64B, /* 1 slice per 64B block */ - [2] = TF_SRAM_SLICE_SIZE_32B, /* 2 slices per 64B block */ - [4] = TF_SRAM_SLICE_SIZE_16B, /* 4 slices per 64B block */ - [8] = TF_SRAM_SLICE_SIZE_8B /* 8 slices per 64B block */ + [0] = TF_SRAM_SLICE_SIZE_128B, /* if 0 slices assume 1 128B block */ + [1] = TF_SRAM_SLICE_SIZE_128B, /* 1 slice per 128B block */ + [2] = TF_SRAM_SLICE_SIZE_64B, /* 2 slice per 128B block */ + [4] = TF_SRAM_SLICE_SIZE_32B, /* 4 slices per 128B block */ + [8] = TF_SRAM_SLICE_SIZE_16B, /* 8 slices per 128B block */ + [16] = TF_SRAM_SLICE_SIZE_8B /* 16 slices per 128B block */ }; /** @@ -340,7 +341,7 @@ tf_tbl_sram_free(struct tf *tfp __rte_unused, rc = tf_sram_mgr_is_allocated(sram_handle, &aparms); if (rc || !allocated) { TFP_DRV_LOG(ERR, - "%s: Free of invalid entry:%s idx(%d):(%s)\n", + "%s: Free of invalid entry:%s idx(0x%x):(%s)\n", tf_dir_2_str(parms->dir), tf_tbl_type_2_str(parms->type), parms->idx, @@ -361,7 +362,7 @@ tf_tbl_sram_free(struct tf *tfp __rte_unused, rc = tf_sram_mgr_free(sram_handle, &fparms); if (rc) { TFP_DRV_LOG(ERR, - "%s: Failed to free entry:%s idx(%d)\n", + "%s: Failed to free entry:%s idx(0x%x)\n", tf_dir_2_str(parms->dir), tf_tbl_type_2_str(parms->type), parms->idx); @@ -469,7 +470,7 @@ tf_tbl_sram_set(struct tf *tfp, if (rallocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { TFP_DRV_LOG(ERR, - "%s, Invalid or not allocated index, type:%s, idx:%d\n", + "%s, Invalid or not allocated index, type:%s, idx:0x%x\n", tf_dir_2_str(parms->dir), tf_tbl_type_2_str(parms->type), parms->idx); @@ -484,7 +485,7 @@ tf_tbl_sram_set(struct tf *tfp, rc = tf_sram_mgr_is_allocated(sram_handle, &aparms); if (rc || !allocated) { TFP_DRV_LOG(ERR, - "%s: Entry not allocated:%s idx(%d):(%s)\n", + "%s: Entry not allocated:%s idx(0x%x):(%s)\n", tf_dir_2_str(parms->dir), tf_tbl_type_2_str(parms->type), parms->idx, @@ -587,7 +588,7 @@ tf_tbl_sram_get(struct tf *tfp, rc = tf_sram_mgr_is_allocated(sram_handle, &aparms); if (rc || !allocated) { TFP_DRV_LOG(ERR, - "%s: Entry not allocated:%s idx(%d):(%s)\n", + "%s: Entry not allocated:%s idx(0x%x):(%s)\n", tf_dir_2_str(parms->dir), tf_tbl_type_2_str(parms->type), parms->idx, @@ -711,7 +712,7 @@ tf_tbl_sram_bulk_get(struct tf *tfp, rc = tf_sram_mgr_is_allocated(sram_handle, &aparms); if (rc || !allocated) { TFP_DRV_LOG(ERR, - "%s: Entry not allocated:%s last_idx(%d):(%s)\n", + "%s: Entry not allocated:%s last_idx(0x%x):(%s)\n", tf_dir_2_str(parms->dir), tf_tbl_type_2_str(parms->type), idx, diff --git a/drivers/net/bnxt/tf_core/tf_tcam.c b/drivers/net/bnxt/tf_core/tf_tcam.c index 1c42a6adc7..9e0671d47b 100644 --- a/drivers/net/bnxt/tf_core/tf_tcam.c +++ b/drivers/net/bnxt/tf_core/tf_tcam.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ @@ -14,6 +14,7 @@ #include "tfp.h" #include "tf_session.h" #include "tf_msg.h" +#include "tf_tcam_mgr_msg.h" struct tf; @@ -23,17 +24,22 @@ tf_tcam_bind(struct tf *tfp, { int rc; int db_rc[TF_DIR_MAX] = { 0 }; - int i, d; + int d, t; struct tf_rm_alloc_info info; struct tf_rm_free_db_parms fparms; struct tf_rm_create_db_parms db_cfg; + struct tf_tcam_resources local_tcam_cnt[TF_DIR_MAX]; struct tf_tcam_resources *tcam_cnt; struct tf_rm_get_alloc_info_parms ainfo; - uint16_t num_slices = parms->wc_num_slices; + uint16_t num_slices = 1; struct tf_session *tfs; struct tf_dev_info *dev; struct tcam_rm_db *tcam_db; struct tfp_calloc_parms cparms; + struct tf_resource_info resv_res[TF_DIR_MAX][TF_TCAM_TBL_TYPE_MAX]; + uint32_t rx_supported; + uint32_t tx_supported; + bool no_req = true; TF_CHECK_PARMS2(tfp, parms); @@ -47,7 +53,7 @@ tf_tcam_bind(struct tf *tfp, if (rc) return rc; - if (dev->ops->tf_dev_set_tcam_slice_info == NULL) { + if (dev->ops->tf_dev_get_tcam_slice_info == NULL) { rc = -EOPNOTSUPP; TFP_DRV_LOG(ERR, "Operation not supported, rc:%s\n", @@ -55,18 +61,28 @@ tf_tcam_bind(struct tf *tfp, return rc; } - rc = dev->ops->tf_dev_set_tcam_slice_info(tfp, - num_slices); + tcam_cnt = parms->resources->tcam_cnt; + + for (d = 0; d < TF_DIR_MAX; d++) { + for (t = 0; t < TF_TCAM_TBL_TYPE_MAX; t++) { + rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, t, 0, + &num_slices); if (rc) return rc; - tcam_cnt = parms->resources->tcam_cnt; - if ((tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % num_slices) || - (tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % num_slices)) { - TFP_DRV_LOG(ERR, - "Requested num of WC TCAM entries has to be multiple %d\n", - num_slices); - return -EINVAL; + if (num_slices == 1) + continue; + + if (tcam_cnt[d].cnt[t] % num_slices) { + TFP_DRV_LOG(ERR, + "%s: Requested num of %s entries " + "has to be multiple of %d\n", + tf_dir_2_str(d), + tf_tcam_tbl_2_str(t), + num_slices); + return -EINVAL; + } + } } memset(&db_cfg, 0, sizeof(db_cfg)); @@ -80,8 +96,8 @@ tf_tcam_bind(struct tf *tfp, } tcam_db = cparms.mem_va; - for (i = 0; i < TF_DIR_MAX; i++) - tcam_db->tcam_db[i] = NULL; + for (d = 0; d < TF_DIR_MAX; d++) + tcam_db->tcam_db[d] = NULL; tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, tcam_db); db_cfg.module = TF_MODULE_TYPE_TCAM; @@ -90,7 +106,7 @@ tf_tcam_bind(struct tf *tfp, for (d = 0; d < TF_DIR_MAX; d++) { db_cfg.dir = d; - db_cfg.alloc_cnt = parms->resources->tcam_cnt[d].cnt; + db_cfg.alloc_cnt = tcam_cnt[d].cnt; db_cfg.rm_db = (void *)&tcam_db->tcam_db[d]; if (tf_session_is_shared_session(tfs) && (!tf_session_is_shared_session_creator(tfs))) @@ -98,53 +114,112 @@ tf_tcam_bind(struct tf *tfp, else db_rc[d] = tf_rm_create_db(tfp, &db_cfg); } - /* No db created */ if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) { TFP_DRV_LOG(ERR, "No TCAM DB created\n"); return db_rc[TF_DIR_RX]; } - /* check if reserved resource for WC is multiple of num_slices */ + /* Collect info on which entries were reserved. */ for (d = 0; d < TF_DIR_MAX; d++) { - if (!tcam_db->tcam_db[d]) - continue; + for (t = 0; t < TF_TCAM_TBL_TYPE_MAX; t++) { + memset(&info, 0, sizeof(info)); + if (tcam_cnt[d].cnt[t] == 0) { + resv_res[d][t].start = 0; + resv_res[d][t].stride = 0; + continue; + } + ainfo.rm_db = tcam_db->tcam_db[d]; + ainfo.subtype = t; + ainfo.info = &info; + rc = tf_rm_get_info(&ainfo); + if (rc) + goto error; + + rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, t, 0, + &num_slices); + if (rc) + return rc; + + if (num_slices > 1) { + /* check if reserved resource for is multiple of + * num_slices + */ + if (info.entry.start % num_slices != 0 || + info.entry.stride % num_slices != 0) { + TFP_DRV_LOG(ERR, + "%s: %s reserved resource" + " is not multiple of %d\n", + tf_dir_2_str(d), + tf_tcam_tbl_2_str(t), + num_slices); + rc = -EINVAL; + goto error; + } + } + + resv_res[d][t].start = info.entry.start; + resv_res[d][t].stride = info.entry.stride; + } + } - memset(&info, 0, sizeof(info)); - ainfo.rm_db = tcam_db->tcam_db[d]; - ainfo.subtype = TF_TCAM_TBL_TYPE_WC_TCAM; - ainfo.info = &info; - rc = tf_rm_get_info(&ainfo); - if (rc) - goto error; - - if (info.entry.start % num_slices != 0 || - info.entry.stride % num_slices != 0) { - TFP_DRV_LOG(ERR, - "%s: TCAM reserved resource is not multiple of %d\n", - tf_dir_2_str(d), - num_slices); - rc = -EINVAL; - goto error; + rc = tf_tcam_mgr_bind_msg(tfp, dev, parms, resv_res); + if (rc) + return rc; + + rc = tf_tcam_mgr_qcaps_msg(tfp, dev, + &rx_supported, &tx_supported); + if (rc) + return rc; + + for (t = 0; t < TF_TCAM_TBL_TYPE_MAX; t++) { + if (rx_supported & 1 << t) + tfs->tcam_mgr_control[TF_DIR_RX][t] = 1; + if (tx_supported & 1 << t) + tfs->tcam_mgr_control[TF_DIR_TX][t] = 1; + } + + /* + * Make a local copy of tcam_cnt with only resources not managed by TCAM + * Manager requested. + */ + memcpy(&local_tcam_cnt, tcam_cnt, sizeof(local_tcam_cnt)); + tcam_cnt = local_tcam_cnt; + for (d = 0; d < TF_DIR_MAX; d++) { + for (t = 0; t < TF_TCAM_TBL_TYPE_MAX; t++) { + /* If controlled by TCAM Manager */ + if (tfs->tcam_mgr_control[d][t]) + tcam_cnt[d].cnt[t] = 0; + else if (tcam_cnt[d].cnt[t] > 0) + no_req = false; } } - /* Initialize the TCAM manager. */ + /* If no resources left to request */ + if (no_req) + goto finished; + +finished: TFP_DRV_LOG(INFO, "TCAM - initialized\n"); return 0; error: - for (i = 0; i < TF_DIR_MAX; i++) { - memset(&fparms, 0, sizeof(fparms)); - fparms.dir = i; - fparms.rm_db = tcam_db->tcam_db[i]; - /* Ignoring return here since we are in the error case */ - (void)tf_rm_free_db(tfp, &fparms); - tcam_db->tcam_db[i] = NULL; + for (d = 0; d < TF_DIR_MAX; d++) { + if (tcam_db->tcam_db[d] != NULL) { + memset(&fparms, 0, sizeof(fparms)); + fparms.dir = d; + fparms.rm_db = tcam_db->tcam_db[d]; + /* + * Ignoring return here since we are in the error case + */ + (void)tf_rm_free_db(tfp, &fparms); + + tcam_db->tcam_db[d] = NULL; + } + tcam_db->tcam_db[d] = NULL; tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, NULL); } - return rc; } @@ -156,27 +231,43 @@ tf_tcam_unbind(struct tf *tfp) struct tf_rm_free_db_parms fparms; struct tcam_rm_db *tcam_db; void *tcam_db_ptr = NULL; + struct tf_session *tfs; + struct tf_dev_info *dev; TF_CHECK_PARMS1(tfp); + /* 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; rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr); - if (rc) { + if (rc) return 0; - } + tcam_db = (struct tcam_rm_db *)tcam_db_ptr; for (i = 0; i < TF_DIR_MAX; i++) { - if (tcam_db->tcam_db[i] == NULL) - continue; - memset(&fparms, 0, sizeof(fparms)); - fparms.dir = i; - fparms.rm_db = tcam_db->tcam_db[i]; - rc = tf_rm_free_db(tfp, &fparms); - if (rc) - return rc; + if (tcam_db->tcam_db[i] != NULL) { + memset(&fparms, 0, sizeof(fparms)); + fparms.dir = i; + fparms.rm_db = tcam_db->tcam_db[i]; + rc = tf_rm_free_db(tfp, &fparms); + if (rc) + return rc; + + tcam_db->tcam_db[i] = NULL; + } - tcam_db->tcam_db[i] = NULL; } + rc = tf_tcam_mgr_unbind_msg(tfp, dev); + if (rc) + return rc; + return 0; } @@ -222,6 +313,9 @@ tf_tcam_alloc(struct tf *tfp, if (rc) return rc; + /* If TCAM controlled by TCAM Manager */ + if (tfs->tcam_mgr_control[parms->dir][parms->type]) + return tf_tcam_mgr_alloc_msg(tfp, dev, parms); rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr); if (rc) { TFP_DRV_LOG(ERR, @@ -251,12 +345,8 @@ tf_tcam_alloc(struct tf *tfp, } /* return the start index of each row */ - if (parms->priority == 0) { if (i == 0) parms->idx = index; - } else { - parms->idx = index; - } } return 0; @@ -307,6 +397,14 @@ tf_tcam_free(struct tf *tfp, if (rc) return rc; + /* If TCAM controlled by TCAM Manager */ + if (tfs->tcam_mgr_control[parms->dir][parms->type]) + /* + * If a session can have multiple references to an entry, check + * the reference count here before actually freeing the entry. + */ + return tf_tcam_mgr_free_msg(tfp, dev, parms); + if (parms->idx % num_slices) { TFP_DRV_LOG(ERR, "%s: TCAM reserved resource is not multiple of %d\n", @@ -429,6 +527,10 @@ tf_tcam_set(struct tf *tfp __rte_unused, if (rc) return rc; + /* If TCAM controlled by TCAM Manager */ + if (tfs->tcam_mgr_control[parms->dir][parms->type]) + return tf_tcam_mgr_set_msg(tfp, dev, parms); + rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr); if (rc) { TFP_DRV_LOG(ERR, @@ -508,6 +610,10 @@ tf_tcam_get(struct tf *tfp __rte_unused, if (rc) return rc; + /* If TCAM controlled by TCAM Manager */ + if (tfs->tcam_mgr_control[parms->dir][parms->type]) + return tf_tcam_mgr_get_msg(tfp, dev, parms); + rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr); if (rc) { TFP_DRV_LOG(ERR, diff --git a/drivers/net/bnxt/tf_core/tf_tcam_mgr_msg.c b/drivers/net/bnxt/tf_core/tf_tcam_mgr_msg.c new file mode 100644 index 0000000000..c535f4f4f6 --- /dev/null +++ b/drivers/net/bnxt/tf_core/tf_tcam_mgr_msg.c @@ -0,0 +1,286 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021-2023 Broadcom + * All rights reserved. + */ + +#include + +#include "tfp.h" +#include "tf_tcam.h" +#include "cfa_tcam_mgr.h" +#include "tf_tcam_mgr_msg.h" + +/* + * Table to convert TCAM type to logical TCAM type for applications. + * Index is tf_tcam_tbl_type. + */ +static enum cfa_tcam_mgr_tbl_type tcam_types[TF_TCAM_TBL_TYPE_MAX] = { + [TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] = + CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_APPS, + [TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] = + CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_APPS, + [TF_TCAM_TBL_TYPE_PROF_TCAM] = + CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_APPS, + [TF_TCAM_TBL_TYPE_WC_TCAM] = + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS, + [TF_TCAM_TBL_TYPE_SP_TCAM] = + CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_APPS, + [TF_TCAM_TBL_TYPE_CT_RULE_TCAM] = + CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_APPS, + [TF_TCAM_TBL_TYPE_VEB_TCAM] = + CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_APPS, + [TF_TCAM_TBL_TYPE_WC_TCAM_HIGH] = + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS, + [TF_TCAM_TBL_TYPE_WC_TCAM_LOW] = + CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS, +}; + +static uint16_t hcapi_type[TF_TCAM_TBL_TYPE_MAX]; + +/* + * This is the glue between the core tf_tcam and the TCAM manager. It is + * intended to abstract out the location of the TCAM manager so that the core + * code will be the same if the TCAM manager is in the core or in firmware. + * + * If the TCAM manager is in the core, then this file will just translate to + * TCAM manager APIs. If TCAM manager is in firmware, then this file will cause + * messages to be sent (except for bind and unbind). + */ + +int +tf_tcam_mgr_qcaps_msg(struct tf *tfp, + struct tf_dev_info *dev __rte_unused, + uint32_t *rx_tcam_supported, + uint32_t *tx_tcam_supported) +{ + struct cfa_tcam_mgr_context context; + struct cfa_tcam_mgr_qcaps_parms mgr_parms; + int rc; + + context.tfp = tfp; + memset(&mgr_parms, 0, sizeof(mgr_parms)); + rc = cfa_tcam_mgr_qcaps(&context, &mgr_parms); + if (rc >= 0) { + *rx_tcam_supported = mgr_parms.rx_tcam_supported; + *tx_tcam_supported = mgr_parms.tx_tcam_supported; + } + return rc; +} + +int +tf_tcam_mgr_bind_msg(struct tf *tfp, + struct tf_dev_info *dev __rte_unused, + struct tf_tcam_cfg_parms *parms, + struct tf_resource_info resv_res[][TF_TCAM_TBL_TYPE_MAX] + __rte_unused + ) +{ + /* Common Code */ + int type; + + if (parms->num_elements != TF_TCAM_TBL_TYPE_MAX) { + TFP_DRV_LOG(ERR, + "Invalid number of elements in bind request.\n"); + TFP_DRV_LOG(ERR, + "Expected %d, received %d.\n", + TF_TCAM_TBL_TYPE_MAX, + parms->num_elements); + return -EINVAL; + } + + for (type = 0; type < TF_TCAM_TBL_TYPE_MAX; type++) + hcapi_type[type] = parms->cfg[type].hcapi_type; + + struct cfa_tcam_mgr_context context; + struct cfa_tcam_mgr_cfg_parms mgr_parms; + struct tf_rm_resc_entry + mgr_resv_res[TF_DIR_MAX][CFA_TCAM_MGR_TBL_TYPE_MAX]; + int dir, rc; + + context.tfp = tfp; + + memset(&mgr_parms, 0, sizeof(mgr_parms)); + + mgr_parms.num_elements = CFA_TCAM_MGR_TBL_TYPE_MAX; + + /* Convert the data to logical tables */ + for (dir = 0; dir < TF_DIR_MAX; dir++) { + for (type = 0; type < TF_TCAM_TBL_TYPE_MAX; type++) { + mgr_parms.tcam_cnt[dir][tcam_types[type]] = + parms->resources->tcam_cnt[dir].cnt[type]; + mgr_resv_res[dir][tcam_types[type]].start = + resv_res[dir][type].start; + mgr_resv_res[dir][tcam_types[type]].stride = + resv_res[dir][type].stride; + } + } + mgr_parms.resv_res = mgr_resv_res; + + rc = cfa_tcam_mgr_bind(&context, &mgr_parms); + + return rc; +} + +int +tf_tcam_mgr_unbind_msg(struct tf *tfp, + struct tf_dev_info *dev __rte_unused) +{ + struct cfa_tcam_mgr_context context; + + context.tfp = tfp; + + return cfa_tcam_mgr_unbind(&context); +} + +int +tf_tcam_mgr_alloc_msg(struct tf *tfp, + struct tf_dev_info *dev __rte_unused, + struct tf_tcam_alloc_parms *parms) +{ + struct cfa_tcam_mgr_context context; + struct cfa_tcam_mgr_alloc_parms mgr_parms; + int rc; + + if (parms->type >= TF_TCAM_TBL_TYPE_MAX) { + TFP_DRV_LOG(ERR, + "No such TCAM table %d.\n", + parms->type); + return -EINVAL; + } + + context.tfp = tfp; + + mgr_parms.dir = parms->dir; + mgr_parms.type = tcam_types[parms->type]; + mgr_parms.hcapi_type = hcapi_type[parms->type]; + mgr_parms.key_size = parms->key_size; + if (parms->priority > TF_TCAM_PRIORITY_MAX) + mgr_parms.priority = 0; + else + mgr_parms.priority = TF_TCAM_PRIORITY_MAX - parms->priority - 1; + + rc = cfa_tcam_mgr_alloc(&context, &mgr_parms); + if (rc) + return rc; + + parms->idx = mgr_parms.id; + return 0; +} + +int +tf_tcam_mgr_free_msg(struct tf *tfp, + struct tf_dev_info *dev __rte_unused, + struct tf_tcam_free_parms *parms) +{ + struct cfa_tcam_mgr_context context; + struct cfa_tcam_mgr_free_parms mgr_parms; + + if (parms->type >= TF_TCAM_TBL_TYPE_MAX) { + TFP_DRV_LOG(ERR, + "No such TCAM table %d.\n", + parms->type); + return -EINVAL; + } + + context.tfp = tfp; + mgr_parms.dir = parms->dir; + mgr_parms.type = tcam_types[parms->type]; + mgr_parms.hcapi_type = hcapi_type[parms->type]; + mgr_parms.id = parms->idx; + + return cfa_tcam_mgr_free(&context, &mgr_parms); +} + +int +tf_tcam_mgr_set_msg(struct tf *tfp, + struct tf_dev_info *dev __rte_unused, + struct tf_tcam_set_parms *parms) +{ + struct cfa_tcam_mgr_context context; + struct cfa_tcam_mgr_set_parms mgr_parms; + + if (parms->type >= TF_TCAM_TBL_TYPE_MAX) { + TFP_DRV_LOG(ERR, + "No such TCAM table %d.\n", + parms->type); + return -EINVAL; + } + + context.tfp = tfp; + mgr_parms.dir = parms->dir; + mgr_parms.type = tcam_types[parms->type]; + mgr_parms.hcapi_type = hcapi_type[parms->type]; + mgr_parms.id = parms->idx; + mgr_parms.key = parms->key; + mgr_parms.mask = parms->mask; + mgr_parms.key_size = parms->key_size; + mgr_parms.result = parms->result; + mgr_parms.result_size = parms->result_size; + + return cfa_tcam_mgr_set(&context, &mgr_parms); +} + +int +tf_tcam_mgr_get_msg(struct tf *tfp, + struct tf_dev_info *dev __rte_unused, + struct tf_tcam_get_parms *parms) +{ + int rc; + struct cfa_tcam_mgr_context context; + struct cfa_tcam_mgr_get_parms mgr_parms; + + if (parms->type >= TF_TCAM_TBL_TYPE_MAX) { + TFP_DRV_LOG(ERR, + "No such TCAM table %d.\n", + parms->type); + return -EINVAL; + } + + context.tfp = tfp; + mgr_parms.dir = parms->dir; + mgr_parms.type = tcam_types[parms->type]; + mgr_parms.hcapi_type = hcapi_type[parms->type]; + mgr_parms.id = parms->idx; + mgr_parms.key = parms->key; + mgr_parms.mask = parms->mask; + mgr_parms.key_size = parms->key_size; + mgr_parms.result = parms->result; + mgr_parms.result_size = parms->result_size; + + rc = cfa_tcam_mgr_get(&context, &mgr_parms); + if (rc) + return rc; + + parms->key_size = mgr_parms.key_size; + parms->result_size = mgr_parms.result_size; + + return rc; +} + +int +tf_tcam_mgr_shared_clear_msg(struct tf *tfp, + struct tf_clear_tcam_shared_entries_parms *parms) +{ + struct cfa_tcam_mgr_context context; + struct cfa_tcam_mgr_shared_clear_parms mgr_parms; + + context.tfp = tfp; + mgr_parms.dir = parms->dir; + mgr_parms.type = tcam_types[parms->tcam_tbl_type]; + + return cfa_tcam_mgr_shared_clear(&context, &mgr_parms); +} + +int +tf_tcam_mgr_shared_move_msg(struct tf *tfp, + struct tf_move_tcam_shared_entries_parms *parms) +{ + struct cfa_tcam_mgr_context context; + struct cfa_tcam_mgr_shared_move_parms mgr_parms; + + context.tfp = tfp; + mgr_parms.dir = parms->dir; + mgr_parms.type = tcam_types[parms->tcam_tbl_type]; + + return cfa_tcam_mgr_shared_move(&context, &mgr_parms); +} diff --git a/drivers/net/bnxt/tf_core/tf_tcam_mgr_msg.h b/drivers/net/bnxt/tf_core/tf_tcam_mgr_msg.h new file mode 100644 index 0000000000..8a8d136f5e --- /dev/null +++ b/drivers/net/bnxt/tf_core/tf_tcam_mgr_msg.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021-2023 Broadcom + * All rights reserved. + */ + +#ifndef _TF_TCAM_MGR_MSG_H_ +#define _TF_TCAM_MGR_MSG_H_ + +#include "tf_tcam.h" +#include "tf_rm.h" + +int +tf_tcam_mgr_qcaps_msg(struct tf *tfp, + struct tf_dev_info *dev __rte_unused, + uint32_t *rx_tcam_supported, + uint32_t *tx_tcam_supported); + +int +tf_tcam_mgr_bind_msg(struct tf *tfp, + struct tf_dev_info *dev, + struct tf_tcam_cfg_parms *parms, + struct tf_resource_info resv_res[][TF_TCAM_TBL_TYPE_MAX]); +int +tf_tcam_mgr_unbind_msg(struct tf *tfp, + struct tf_dev_info *dev); +int +tf_tcam_mgr_alloc_msg(struct tf *tfp, + struct tf_dev_info *dev, + struct tf_tcam_alloc_parms *parms); +int +tf_tcam_mgr_free_msg(struct tf *tfp, + struct tf_dev_info *dev, + struct tf_tcam_free_parms *parms); +int +tf_tcam_mgr_set_msg(struct tf *tfp, + struct tf_dev_info *dev, + struct tf_tcam_set_parms *parms); +int +tf_tcam_mgr_get_msg(struct tf *tfp, + struct tf_dev_info *dev, + struct tf_tcam_get_parms *parms); +int +tf_tcam_mgr_shared_clear_msg(struct tf *tfp, + struct tf_clear_tcam_shared_entries_parms *parms); + +int +tf_tcam_mgr_shared_move_msg(struct tf *tfp, + struct tf_move_tcam_shared_entries_parms *parms); +#endif /* _TF_TCAM_MGR_MSG_H_ */ diff --git a/drivers/net/bnxt/tf_core/tf_tcam_shared.c b/drivers/net/bnxt/tf_core/tf_tcam_shared.c index c120c6f577..e853f616f9 100644 --- a/drivers/net/bnxt/tf_core/tf_tcam_shared.c +++ b/drivers/net/bnxt/tf_core/tf_tcam_shared.c @@ -1,11 +1,13 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ #include #include +#include "tf_core.h" + #include "tf_tcam_shared.h" #include "tf_tcam.h" #include "tf_common.h" @@ -16,229 +18,8 @@ #include "tf_session.h" #include "tf_msg.h" #include "bitalloc.h" -#include "tf_core.h" - -/** Shared WC TCAM pool identifiers - */ -enum tf_tcam_shared_wc_pool_id { - TF_TCAM_SHARED_WC_POOL_HI = 0, - TF_TCAM_SHARED_WC_POOL_LO = 1, - TF_TCAM_SHARED_WC_POOL_MAX = 2 -}; - -/** Get string representation of a WC TCAM shared pool id - */ -static const char * -tf_pool_2_str(enum tf_tcam_shared_wc_pool_id id) -{ - switch (id) { - case TF_TCAM_SHARED_WC_POOL_HI: - return "TCAM_SHARED_WC_POOL_HI"; - case TF_TCAM_SHARED_WC_POOL_LO: - return "TCAM_SHARED_WC_POOL_LO"; - default: - return "Invalid TCAM_SHARED_WC_POOL"; - } -} - -/** The WC TCAM shared pool datastructure - */ -struct tf_tcam_shared_wc_pool { - /** Start and stride data */ - struct tf_resource_info info; - /** bitalloc pool */ - struct bitalloc *pool; -}; - -struct tf_tcam_shared_wc_pools { - struct tf_tcam_shared_wc_pool db[TF_DIR_MAX][TF_TCAM_SHARED_WC_POOL_MAX]; -}; - -/** The WC TCAM shared pool declarations - */ -/* struct tf_tcam_shared_wc_pool tcam_shared_wc[TF_DIR_MAX][TF_TCAM_SHARED_WC_POOL_MAX]; */ - -static int -tf_tcam_shared_create_db(struct tf_tcam_shared_wc_pools **db) -{ - struct tfp_calloc_parms cparms; - int rc = 0; - - cparms.nitems = 1; - cparms.alignment = 0; - cparms.size = sizeof(struct tf_tcam_shared_wc_pools); - rc = tfp_calloc(&cparms); - if (rc) { - TFP_DRV_LOG(ERR, - "TCAM shared db allocation failed (%s)\n", - strerror(-rc)); - return rc; - } - *db = cparms.mem_va; - - return rc; -} - -/** Create a WC TCAM shared pool - */ -static int -tf_tcam_shared_create_wc_pool(int dir, - enum tf_tcam_shared_wc_pool_id id, - int start, - int stride, - struct tf_tcam_shared_wc_pools *tcam_shared_wc) -{ - int rc = 0; - bool free = true; - struct tfp_calloc_parms cparms; - uint32_t pool_size; - - /* Create pool */ - pool_size = (BITALLOC_SIZEOF(stride) / sizeof(struct bitalloc)); - cparms.nitems = pool_size; - cparms.alignment = 0; - cparms.size = sizeof(struct bitalloc); - rc = tfp_calloc(&cparms); - if (rc) { - TFP_DRV_LOG(ERR, - "%s: pool memory alloc failed %s:%s\n", - tf_dir_2_str(dir), tf_pool_2_str(id), - strerror(-rc)); - return rc; - } - tcam_shared_wc->db[dir][id].pool = (struct bitalloc *)cparms.mem_va; - - rc = ba_init(tcam_shared_wc->db[dir][id].pool, - stride, - free); - - if (rc) { - TFP_DRV_LOG(ERR, - "%s: pool bitalloc failed %s\n", - tf_dir_2_str(dir), tf_pool_2_str(id)); - return rc; - } - - tcam_shared_wc->db[dir][id].info.start = start; - tcam_shared_wc->db[dir][id].info.stride = stride; - - return rc; -} -/** Free a WC TCAM shared pool - */ -static int -tf_tcam_shared_free_wc_pool(int dir, - enum tf_tcam_shared_wc_pool_id id, - struct tf_tcam_shared_wc_pools *tcam_shared_wc) -{ - int rc = 0; - TF_CHECK_PARMS1(tcam_shared_wc); - - tcam_shared_wc->db[dir][id].info.start = 0; - tcam_shared_wc->db[dir][id].info.stride = 0; - - if (tcam_shared_wc->db[dir][id].pool) - tfp_free((void *)tcam_shared_wc->db[dir][id].pool); - return rc; -} - -/** Get the number of WC TCAM slices allocated during 1 allocation/free - */ -static int -tf_tcam_shared_get_slices(struct tf *tfp, - struct tf_dev_info *dev, - uint16_t *num_slices) -{ - int rc; - - if (dev->ops->tf_dev_get_tcam_slice_info == NULL) { - rc = -EOPNOTSUPP; - TFP_DRV_LOG(ERR, - "Operation not supported, rc:%s\n", strerror(-rc)); - return rc; - } - rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, - TF_TCAM_TBL_TYPE_WC_TCAM, - 0, - num_slices); - return rc; -} - -static bool -tf_tcam_db_valid(struct tf *tfp, - enum tf_dir dir) -{ - struct tcam_rm_db *tcam_db; - void *tcam_db_ptr = NULL; - int rc; - - TF_CHECK_PARMS1(tfp); - - rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr); - if (rc) - return false; - - tcam_db = (struct tcam_rm_db *)tcam_db_ptr; - - if (tcam_db->tcam_db[dir]) - return true; - - return false; -} - -static int -tf_tcam_shared_get_rm_info(struct tf *tfp, - enum tf_dir dir, - uint16_t *hcapi_type, - struct tf_rm_alloc_info *info) -{ - int rc; - struct tcam_rm_db *tcam_db; - void *tcam_db_ptr = NULL; - struct tf_rm_get_alloc_info_parms ainfo; - struct tf_rm_get_hcapi_parms hparms; - - TF_CHECK_PARMS3(tfp, hcapi_type, info); - - rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr); - if (rc) { - TFP_DRV_LOG(INFO, - "Tcam_db is not initialized, rc:%s\n", - strerror(-rc)); - return 0; - } - tcam_db = (struct tcam_rm_db *)tcam_db_ptr; - - /* Convert TF type to HCAPI RM type */ - memset(&hparms, 0, sizeof(hparms)); - hparms.rm_db = tcam_db->tcam_db[dir]; - hparms.subtype = TF_TCAM_TBL_TYPE_WC_TCAM; - hparms.hcapi_type = hcapi_type; - - rc = tf_rm_get_hcapi_type(&hparms); - if (rc) { - TFP_DRV_LOG(ERR, - "%s: Get RM hcapi type failed %s\n", - tf_dir_2_str(dir), - strerror(-rc)); - return rc; - } - - memset(info, 0, sizeof(struct tf_rm_alloc_info)); - ainfo.rm_db = tcam_db->tcam_db[dir]; - ainfo.subtype = TF_TCAM_TBL_TYPE_WC_TCAM; - ainfo.info = info; - - rc = tf_rm_get_info(&ainfo); - if (rc) { - TFP_DRV_LOG(ERR, - "%s: TCAM rm info get failed %s\n", - tf_dir_2_str(dir), - strerror(-rc)); - return rc; - } - return rc; -} +#include "tf_rm.h" +#include "tf_tcam_mgr_msg.h" /** * tf_tcam_shared_bind @@ -247,92 +28,15 @@ int tf_tcam_shared_bind(struct tf *tfp, struct tf_tcam_cfg_parms *parms) { - int rc, dir; - struct tf_session *tfs; - struct tf_dev_info *dev; - struct tf_rm_alloc_info info; - uint16_t start, stride; - uint16_t num_slices; - uint16_t hcapi_type; - struct tf_tcam_shared_wc_pools *tcam_shared_wc = NULL; + int rc; TF_CHECK_PARMS2(tfp, parms); /* Perform normal bind */ rc = tf_tcam_bind(tfp, parms); - if (rc) - return rc; - - /* After the normal TCAM bind, if this is a shared session - * create all required databases for the WC_HI and WC_LO pools - */ - rc = tf_session_get_session_internal(tfp, &tfs); - if (rc) { - TFP_DRV_LOG(ERR, - "Session access failure: %s\n", strerror(-rc)); - return rc; - } - if (tf_session_is_shared_session(tfs)) { - /* Retrieve the device information */ - rc = tf_session_get_device(tfs, &dev); - if (rc) - return rc; - - tf_tcam_shared_create_db(&tcam_shared_wc); - - - /* If there are WC TCAM entries, create 2 pools each with 1/2 - * the total number of entries - */ - for (dir = 0; dir < TF_DIR_MAX; dir++) { - if (!tf_tcam_db_valid(tfp, dir)) - continue; - - rc = tf_tcam_shared_get_rm_info(tfp, - dir, - &hcapi_type, - &info); - if (rc) { - TFP_DRV_LOG(ERR, - "%s: TCAM rm info get failed\n", - tf_dir_2_str(dir)); - goto done; - } - - start = info.entry.start; - stride = info.entry.stride / 2; - - tf_tcam_shared_create_wc_pool(dir, - TF_TCAM_SHARED_WC_POOL_HI, - start, - stride, - tcam_shared_wc); - - start += stride; - tf_tcam_shared_create_wc_pool(dir, - TF_TCAM_SHARED_WC_POOL_LO, - start, - stride, - tcam_shared_wc); - - tf_session_set_tcam_shared_db(tfp, (void *)tcam_shared_wc); - } - - rc = tf_tcam_shared_get_slices(tfp, - dev, - &num_slices); - if (rc) - return rc; - - if (num_slices > 1) { - TFP_DRV_LOG(ERR, - "Only single slice supported\n"); - return -EOPNOTSUPP; - } - } -done: return rc; + } /** * tf_tcam_shared_unbind @@ -340,132 +44,10 @@ tf_tcam_shared_bind(struct tf *tfp, int tf_tcam_shared_unbind(struct tf *tfp) { - int rc, dir; - struct tf_dev_info *dev; - struct tf_session *tfs; - void *tcam_shared_db_ptr = NULL; - struct tf_tcam_shared_wc_pools *tcam_shared_wc; - enum tf_tcam_shared_wc_pool_id pool_id; - struct tf_tcam_free_parms parms; - struct bitalloc *pool; - uint16_t start; - int log_idx, phy_idx; - uint16_t hcapi_type; - struct tf_rm_alloc_info info; - int i, pool_cnt; + int rc; TF_CHECK_PARMS1(tfp); - /* Retrieve the session information */ - rc = tf_session_get_session_internal(tfp, &tfs); - if (rc) - return rc; - - /* If not the shared session, call the normal - * tcam unbind and exit - */ - if (!tf_session_is_shared_session(tfs)) { - rc = tf_tcam_unbind(tfp); - return rc; - } - - /* We must be a shared session, get the database - */ - rc = tf_session_get_tcam_shared_db(tfp, - (void *)&tcam_shared_db_ptr); - if (rc) { - TFP_DRV_LOG(ERR, - "Failed to get tcam_shared_db, rc:%s\n", - strerror(-rc)); - return rc; - } - - tcam_shared_wc = - (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr; - - - /* Get the device - */ - rc = tf_session_get_device(tfs, &dev); - if (rc) - return rc; - - - /* If there are WC TCAM entries allocated, free them - */ - for (dir = 0; dir < TF_DIR_MAX; dir++) { - /* If the database is invalid, skip - */ - if (!tf_tcam_db_valid(tfp, dir)) - continue; - - rc = tf_tcam_shared_get_rm_info(tfp, - dir, - &hcapi_type, - &info); - if (rc) { - TFP_DRV_LOG(ERR, - "%s: TCAM shared rm info get failed\n", - tf_dir_2_str(dir)); - return rc; - } - - for (pool_id = TF_TCAM_SHARED_WC_POOL_HI; - pool_id < TF_TCAM_SHARED_WC_POOL_MAX; - pool_id++) { - pool = tcam_shared_wc->db[dir][pool_id].pool; - start = tcam_shared_wc->db[dir][pool_id].info.start; - pool_cnt = ba_inuse_count(pool); - - if (pool_cnt) { - TFP_DRV_LOG(INFO, - "%s: %s: %d residuals found, freeing\n", - tf_dir_2_str(dir), - tf_pool_2_str(pool_id), - pool_cnt); - } - - log_idx = 0; - - for (i = 0; i < pool_cnt; i++) { - log_idx = ba_find_next_inuse(pool, log_idx); - - if (log_idx < 0) { - TFP_DRV_LOG(ERR, - "Expected a found %s entry %d\n", - tf_pool_2_str(pool_id), - i); - /* attempt normal unbind - */ - goto done; - } - phy_idx = start + log_idx; - - parms.type = TF_TCAM_TBL_TYPE_WC_TCAM; - parms.hcapi_type = hcapi_type; - parms.idx = phy_idx; - parms.dir = dir; - rc = tf_msg_tcam_entry_free(tfp, dev, &parms); - if (rc) { - /* Log error */ - TFP_DRV_LOG(ERR, - "%s: %s: %d free failed, rc:%s\n", - tf_dir_2_str(parms.dir), - tf_tcam_tbl_2_str(parms.type), - phy_idx, - strerror(-rc)); - return rc; - } - } - /* Free the pool once all the entries - * have been cleared - */ - tf_tcam_shared_free_wc_pool(dir, - pool_id, - tcam_shared_wc); - } - } -done: rc = tf_tcam_unbind(tfp); return rc; } @@ -478,79 +60,11 @@ tf_tcam_shared_alloc(struct tf *tfp, struct tf_tcam_alloc_parms *parms) { int rc; - struct tf_session *tfs; - struct tf_dev_info *dev; - int log_idx; - struct bitalloc *pool; - enum tf_tcam_shared_wc_pool_id id; - struct tf_tcam_shared_wc_pools *tcam_shared_wc; - void *tcam_shared_db_ptr = NULL; TF_CHECK_PARMS2(tfp, parms); - /* Retrieve the session information */ - rc = tf_session_get_session_internal(tfp, &tfs); - if (rc) - return rc; - - /* If we aren't the shared session or the type is - * not one of the special WC TCAM types, call the normal - * allocation. - */ - if (!tf_session_is_shared_session(tfs) || - (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH && - parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) { - /* Perform normal alloc - */ - rc = tf_tcam_alloc(tfp, parms); - return rc; - } - - if (!tf_tcam_db_valid(tfp, parms->dir)) { - TFP_DRV_LOG(ERR, - "%s: tcam shared pool doesn't exist\n", - tf_dir_2_str(parms->dir)); - return -ENOMEM; - } - - rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr); - if (rc) { - TFP_DRV_LOG(ERR, - "Failed to get tcam_shared_db from session, rc:%s\n", - strerror(-rc)); - return rc; - } - tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr; - - if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH) - id = TF_TCAM_SHARED_WC_POOL_HI; - else - id = TF_TCAM_SHARED_WC_POOL_LO; - - /* Retrieve the device information */ - rc = tf_session_get_device(tfs, &dev); - if (rc) - return rc; - - pool = tcam_shared_wc->db[parms->dir][id].pool; - - /* - * priority 0: allocate from top of the tcam i.e. high - * priority !0: allocate index from bottom i.e lowest - */ - if (parms->priority) - log_idx = ba_alloc_reverse(pool); - else - log_idx = ba_alloc(pool); - if (log_idx == BA_FAIL) { - TFP_DRV_LOG(ERR, - "%s: Allocation failed, rc:%s\n", - tf_dir_2_str(parms->dir), - strerror(ENOMEM)); - return -ENOMEM; - } - parms->idx = log_idx; - return 0; + rc = tf_tcam_alloc(tfp, parms); + return rc; } int @@ -558,118 +72,11 @@ tf_tcam_shared_free(struct tf *tfp, struct tf_tcam_free_parms *parms) { int rc; - struct tf_session *tfs; - struct tf_dev_info *dev; - int allocated = 0; - uint16_t start; - int phy_idx; - struct bitalloc *pool; - enum tf_tcam_shared_wc_pool_id id; - struct tf_tcam_free_parms nparms; - uint16_t hcapi_type; - struct tf_rm_alloc_info info; - void *tcam_shared_db_ptr = NULL; - struct tf_tcam_shared_wc_pools *tcam_shared_wc; TF_CHECK_PARMS2(tfp, parms); - /* Retrieve the session information */ - rc = tf_session_get_session_internal(tfp, &tfs); - if (rc) - return rc; - - /* If we aren't the shared session or the type is - * not one of the special WC TCAM types, call the normal - * allocation. - */ - if (!tf_session_is_shared_session(tfs) || - (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH && - parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) { - /* Perform normal free - */ - rc = tf_tcam_free(tfp, parms); - return rc; - } - - if (!tf_tcam_db_valid(tfp, parms->dir)) { - TFP_DRV_LOG(ERR, - "%s: tcam shared pool doesn't exist\n", - tf_dir_2_str(parms->dir)); - return -ENOMEM; - } - - rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr); - if (rc) { - TFP_DRV_LOG(ERR, - "Failed to get tcam_shared_db from session, rc:%s\n", - strerror(-rc)); - return rc; - } - tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr; - - - if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH) - id = TF_TCAM_SHARED_WC_POOL_HI; - else - id = TF_TCAM_SHARED_WC_POOL_LO; - - /* Retrieve the device information */ - rc = tf_session_get_device(tfs, &dev); - if (rc) - return rc; - - rc = tf_tcam_shared_get_rm_info(tfp, - parms->dir, - &hcapi_type, - &info); - if (rc) { - TFP_DRV_LOG(ERR, - "%s: TCAM rm info get failed\n", - tf_dir_2_str(parms->dir)); - return rc; - } - - pool = tcam_shared_wc->db[parms->dir][id].pool; - start = tcam_shared_wc->db[parms->dir][id].info.start; - - phy_idx = parms->idx + start; - allocated = ba_inuse(pool, parms->idx); - - if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { - TFP_DRV_LOG(ERR, - "%s: Entry already free, type:%d, idx:%d\n", - tf_dir_2_str(parms->dir), parms->type, parms->idx); - return -EINVAL; - } - - rc = ba_free(pool, parms->idx); - if (rc) { - TFP_DRV_LOG(ERR, - "%s: Free failed, type:%s, idx:%d\n", - tf_dir_2_str(parms->dir), - tf_tcam_tbl_2_str(parms->type), - parms->idx); - return rc; - } - - /* Override HI/LO type with parent WC TCAM type */ - nparms = *parms; - nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM; - nparms.hcapi_type = hcapi_type; - nparms.idx = phy_idx; - - rc = tf_msg_tcam_entry_free(tfp, dev, &nparms); - if (rc) { - /* Log error */ - TFP_DRV_LOG(ERR, - "%s: %s: log%d free failed, rc:%s\n", - tf_dir_2_str(nparms.dir), - tf_tcam_tbl_2_str(nparms.type), - phy_idx, - strerror(-rc)); - return rc; - } - return 0; + rc = tf_tcam_free(tfp, parms); + return rc; } int @@ -677,109 +84,11 @@ tf_tcam_shared_set(struct tf *tfp __rte_unused, struct tf_tcam_set_parms *parms __rte_unused) { int rc; - struct tf_session *tfs; - struct tf_dev_info *dev; - int allocated = 0; - int phy_idx, log_idx; - struct tf_tcam_set_parms nparms; - struct bitalloc *pool; - uint16_t start; - enum tf_tcam_shared_wc_pool_id id; - uint16_t hcapi_type; - struct tf_rm_alloc_info info; - struct tf_tcam_shared_wc_pools *tcam_shared_wc; - void *tcam_shared_db_ptr = NULL; - TF_CHECK_PARMS2(tfp, parms); - /* Retrieve the session information */ - rc = tf_session_get_session_internal(tfp, &tfs); - if (rc) - return rc; - - /* If we aren't the shared session or one of our - * special types - */ - if (!tf_session_is_shared_session(tfs) || - (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH && - parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) { - /* Perform normal set and exit - */ - rc = tf_tcam_set(tfp, parms); - return rc; - } - - if (!tf_tcam_db_valid(tfp, parms->dir)) { - TFP_DRV_LOG(ERR, - "%s: tcam shared pool doesn't exist\n", - tf_dir_2_str(parms->dir)); - return -ENOMEM; - } - - /* Retrieve the device information */ - rc = tf_session_get_device(tfs, &dev); - if (rc) - return rc; - - if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH) - id = TF_TCAM_SHARED_WC_POOL_HI; - else - id = TF_TCAM_SHARED_WC_POOL_LO; - - rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr); - if (rc) { - TFP_DRV_LOG(ERR, - "Failed to get tcam_shared_db from session, rc:%s\n", - strerror(-rc)); - return rc; - } - tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr; - - pool = tcam_shared_wc->db[parms->dir][id].pool; - start = tcam_shared_wc->db[parms->dir][id].info.start; - - log_idx = parms->idx; - phy_idx = parms->idx + start; - allocated = ba_inuse(pool, parms->idx); - - if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { - TFP_DRV_LOG(ERR, - "%s: Entry is not allocated, type:%d, logid:%d\n", - tf_dir_2_str(parms->dir), parms->type, log_idx); - return -EINVAL; - } - - rc = tf_tcam_shared_get_rm_info(tfp, - parms->dir, - &hcapi_type, - &info); - if (rc) - return rc; - - /* Override HI/LO type with parent WC TCAM type */ - nparms.hcapi_type = hcapi_type; - nparms.dir = parms->dir; - nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM; - nparms.idx = phy_idx; - nparms.key = parms->key; - nparms.mask = parms->mask; - nparms.key_size = parms->key_size; - nparms.result = parms->result; - nparms.result_size = parms->result_size; - - rc = tf_msg_tcam_entry_set(tfp, dev, &nparms); - if (rc) { - /* Log error */ - TFP_DRV_LOG(ERR, - "%s: %s: phy entry %d set failed, rc:%s", - tf_dir_2_str(parms->dir), - tf_tcam_tbl_2_str(nparms.type), - phy_idx, - strerror(-rc)); - return rc; - } - return 0; + rc = tf_tcam_set(tfp, parms); + return rc; } int @@ -787,226 +96,10 @@ tf_tcam_shared_get(struct tf *tfp __rte_unused, struct tf_tcam_get_parms *parms) { int rc; - struct tf_session *tfs; - struct tf_dev_info *dev; - int allocated = 0; - int phy_idx, log_idx; - struct tf_tcam_get_parms nparms; - struct bitalloc *pool; - uint16_t start; - enum tf_tcam_shared_wc_pool_id id; - uint16_t hcapi_type; - struct tf_rm_alloc_info info; - struct tf_tcam_shared_wc_pools *tcam_shared_wc; - void *tcam_shared_db_ptr = NULL; TF_CHECK_PARMS2(tfp, parms); - /* Retrieve the session information */ - rc = tf_session_get_session_internal(tfp, &tfs); - if (rc) - return rc; - - /* If we aren't the shared session or one of our - * special types - */ - if (!tf_session_is_shared_session(tfs) || - (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH && - parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) { - /* Perform normal get and exit - */ - rc = tf_tcam_get(tfp, parms); - return rc; - } - - if (!tf_tcam_db_valid(tfp, parms->dir)) { - TFP_DRV_LOG(ERR, - "%s: tcam shared pool doesn't exist\n", - tf_dir_2_str(parms->dir)); - return -ENOMEM; - } - - /* Retrieve the device information */ - rc = tf_session_get_device(tfs, &dev); - if (rc) - return rc; - if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH) - id = TF_TCAM_SHARED_WC_POOL_HI; - else - id = TF_TCAM_SHARED_WC_POOL_LO; - - - rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr); - if (rc) { - TFP_DRV_LOG(ERR, - "Failed to get tcam_shared_db from session, rc:%s\n", - strerror(-rc)); - return rc; - } - tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr; - - pool = tcam_shared_wc->db[parms->dir][id].pool; - start = tcam_shared_wc->db[parms->dir][id].info.start; - - log_idx = parms->idx; - phy_idx = parms->idx + start; - allocated = ba_inuse(pool, parms->idx); - - if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { - TFP_DRV_LOG(ERR, - "%s: Entry is not allocated, type:%d, logid:%d\n", - tf_dir_2_str(parms->dir), parms->type, log_idx); - return -EINVAL; - } - - rc = tf_tcam_shared_get_rm_info(tfp, - parms->dir, - &hcapi_type, - &info); - if (rc) - return rc; - - /* Override HI/LO type with parent WC TCAM type */ - nparms = *parms; - nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM; - nparms.hcapi_type = hcapi_type; - nparms.idx = phy_idx; - - rc = tf_msg_tcam_entry_get(tfp, dev, &nparms); - if (rc) { - /* Log error */ - TFP_DRV_LOG(ERR, - "%s: %s: Entry %d set failed, rc:%s", - tf_dir_2_str(nparms.dir), - tf_tcam_tbl_2_str(nparms.type), - nparms.idx, - strerror(-rc)); - return rc; - } - return 0; -} - -/* Normally, device specific code wouldn't reside here, it belongs - * in a separate device specific function in tf_device_pxx.c. - * But this code is placed here as it is not a long term solution - * and we would like to have this code centrally located for easy - * removal - */ -#define TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P4 12 -#define TF_TCAM_SHARED_REMAP_SZ_BYTES_P4 4 -#define TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58 24 -#define TF_TCAM_SHARED_REMAP_SZ_BYTES_P58 8 - -/* Temporary builder defines pulled in here and adjusted - * for max WC TCAM values - */ -union tf_tmp_field_obj { - uint32_t words[(TF_TCAM_SHARED_REMAP_SZ_BYTES_P58 + 3) / 4]; - uint8_t bytes[TF_TCAM_SHARED_REMAP_SZ_BYTES_P58]; -}; - -union tf_tmp_key { - uint32_t words[(TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58 + 3) / 4]; - uint8_t bytes[TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58]; -}; - -/** p58 has an enable bit, p4 does not - */ -#define TF_TCAM_SHARED_ENTRY_ENABLE 0x8 - -/** Move a WC TCAM entry from the high offset to the same low offset - */ -static int -tf_tcam_shared_move_entry(struct tf *tfp, - struct tf_dev_info *dev, - uint16_t hcapi_type, - enum tf_dir dir, - int sphy_idx, - int dphy_idx, - int key_sz_bytes, - int remap_sz_bytes, - bool set_enable_bit) -{ - int rc = 0; - struct tf_tcam_get_parms gparms; - struct tf_tcam_set_parms sparms; - struct tf_tcam_free_parms fparms; - union tf_tmp_key tcam_key_obj; - union tf_tmp_key tcam_key_msk_obj; - union tf_tmp_field_obj tcam_remap_obj; - - memset(&tcam_key_obj, 0, sizeof(tcam_key_obj)); - memset(&tcam_key_msk_obj, 0, sizeof(tcam_key_msk_obj)); - memset(&tcam_remap_obj, 0, sizeof(tcam_remap_obj)); - memset(&gparms, 0, sizeof(gparms)); - - gparms.hcapi_type = hcapi_type; - gparms.dir = dir; - gparms.type = TF_TCAM_TBL_TYPE_WC_TCAM; - gparms.idx = sphy_idx; - gparms.key = (uint8_t *)&tcam_key_obj; - gparms.key_size = key_sz_bytes; - gparms.mask = (uint8_t *)&tcam_key_msk_obj; - gparms.result = (uint8_t *)&tcam_remap_obj; - gparms.result_size = remap_sz_bytes; - - rc = tf_msg_tcam_entry_get(tfp, dev, &gparms); - if (rc) { - /* Log error */ - TFP_DRV_LOG(ERR, - "%s: %s: phyid(%d) get failed, rc:%s\n", - tf_tcam_tbl_2_str(gparms.type), - tf_dir_2_str(dir), - gparms.idx, - strerror(-rc)); - return rc; - } - - if (set_enable_bit) - tcam_key_obj.bytes[0] |= TF_TCAM_SHARED_ENTRY_ENABLE; - - /* Override HI/LO type with parent WC TCAM type */ - sparms.hcapi_type = hcapi_type; - sparms.dir = dir; - sparms.type = TF_TCAM_TBL_TYPE_WC_TCAM; - sparms.idx = dphy_idx; - sparms.key = gparms.key; - sparms.mask = gparms.mask; - sparms.key_size = key_sz_bytes; - sparms.result = gparms.result; - sparms.result_size = remap_sz_bytes; - - rc = tf_msg_tcam_entry_set(tfp, dev, &sparms); - if (rc) { - /* Log error */ - TFP_DRV_LOG(ERR, - "%s: %s phyid(%d/0x%x) set failed, rc:%s\n", - tf_tcam_tbl_2_str(sparms.type), - tf_dir_2_str(dir), - sparms.idx, - sparms.idx, - strerror(-rc)); - return rc; - } - - /* Override HI/LO type with parent WC TCAM type */ - fparms.dir = dir; - fparms.type = TF_TCAM_TBL_TYPE_WC_TCAM; - fparms.hcapi_type = hcapi_type; - fparms.idx = sphy_idx; - - rc = tf_msg_tcam_entry_free(tfp, dev, &fparms); - if (rc) { - /* Log error */ - TFP_DRV_LOG(ERR, - "%s: %s: phyid(%d/0x%x) free failed, rc:%s\n", - tf_dir_2_str(dir), - tf_tcam_tbl_2_str(fparms.type), - sphy_idx, - sphy_idx, - strerror(-rc)); - return rc; - } + rc = tf_tcam_get(tfp, parms); return rc; } @@ -1015,23 +108,10 @@ tf_tcam_shared_move_entry(struct tf *tfp, */ static int tf_tcam_shared_move(struct tf *tfp, - struct tf_move_tcam_shared_entries_parms *parms, - int key_sz_bytes, - int remap_sz_bytes, - bool set_enable_bit) + struct tf_move_tcam_shared_entries_parms *parms) { - int rc; struct tf_session *tfs; - struct tf_dev_info *dev; - int log_idx; - struct bitalloc *hi_pool, *lo_pool; - uint16_t hi_start, lo_start; - enum tf_tcam_shared_wc_pool_id hi_id, lo_id; - uint16_t hcapi_type; - struct tf_rm_alloc_info info; - int hi_cnt, i; - struct tf_tcam_shared_wc_pools *tcam_shared_wc; - void *tcam_shared_db_ptr = NULL; + int rc; TF_CHECK_PARMS2(tfp, parms); @@ -1052,104 +132,7 @@ int tf_tcam_shared_move(struct tf *tfp, return -EOPNOTSUPP; } - if (!tf_tcam_db_valid(tfp, parms->dir)) { - TFP_DRV_LOG(ERR, - "%s: tcam shared pool doesn't exist\n", - tf_dir_2_str(parms->dir)); - return -ENOMEM; - } - - /* Retrieve the device information */ - rc = tf_session_get_device(tfs, &dev); - if (rc) { - /* TODO print amazing error */ - return rc; - } - - rc = tf_tcam_shared_get_rm_info(tfp, - parms->dir, - &hcapi_type, - &info); - if (rc) { - TFP_DRV_LOG(ERR, - "%s: TCAM rm info get failed\n", - tf_dir_2_str(parms->dir)); - return rc; - } - - rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr); - if (rc) { - TFP_DRV_LOG(ERR, - "Failed to get tcam_shared_db from session, rc:%s\n", - strerror(-rc)); - return rc; - } - tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr; - - hi_id = TF_TCAM_SHARED_WC_POOL_HI; - hi_pool = tcam_shared_wc->db[parms->dir][hi_id].pool; - hi_start = tcam_shared_wc->db[parms->dir][hi_id].info.start; - - lo_id = TF_TCAM_SHARED_WC_POOL_LO; - lo_pool = tcam_shared_wc->db[parms->dir][lo_id].pool; - lo_start = tcam_shared_wc->db[parms->dir][lo_id].info.start; - - if (hi_pool == NULL || lo_pool == NULL) - return -ENOMEM; - - /* Get the total count of in use entries in the high pool - */ - hi_cnt = ba_inuse_count(hi_pool); - - /* Copy each valid entry to the same low pool logical offset - */ - log_idx = 0; - - for (i = 0; i < hi_cnt; i++) { - /* Find next free index starting from where we left off - */ - log_idx = ba_find_next_inuse(hi_pool, log_idx); - if (log_idx < 0) { - TFP_DRV_LOG(ERR, - "Expected a found %s entry %d\n", - tf_pool_2_str(hi_id), - i); - goto done; - } - /* The user should have never allocated from the low - * pool because the move only happens when switching - * from the high to the low pool - */ - if (ba_alloc_index(lo_pool, log_idx) < 0) { - TFP_DRV_LOG(ERR, - "Warning %s index %d already allocated\n", - tf_pool_2_str(lo_id), - i); - - /* Since already allocated, continue with move - */ - } - - rc = tf_tcam_shared_move_entry(tfp, dev, - hcapi_type, - parms->dir, - hi_start + log_idx, - lo_start + log_idx, - key_sz_bytes, - remap_sz_bytes, - set_enable_bit); - if (rc) { - TFP_DRV_LOG(ERR, - "%s: Move error %s to %s index %d\n", - tf_dir_2_str(parms->dir), - tf_pool_2_str(hi_id), - tf_pool_2_str(lo_id), - i); - goto done; - } - ba_free(hi_pool, log_idx); - } -done: + rc = tf_tcam_mgr_shared_move_msg(tfp, parms); return rc; } @@ -1159,24 +142,17 @@ tf_tcam_shared_move_p4(struct tf *tfp, { int rc = 0; rc = tf_tcam_shared_move(tfp, - parms, - TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P4, - TF_TCAM_SHARED_REMAP_SZ_BYTES_P4, - false); /* no enable bit */ + parms); return rc; } - int tf_tcam_shared_move_p58(struct tf *tfp, struct tf_move_tcam_shared_entries_parms *parms) { int rc = 0; rc = tf_tcam_shared_move(tfp, - parms, - TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58, - TF_TCAM_SHARED_REMAP_SZ_BYTES_P58, - true); /* set enable bit */ + parms); return rc; } @@ -1186,16 +162,6 @@ tf_tcam_shared_clear(struct tf *tfp, { int rc = 0; struct tf_session *tfs; - struct tf_dev_info *dev; - uint16_t start; - int phy_idx; - enum tf_tcam_shared_wc_pool_id id; - struct tf_tcam_free_parms nparms; - uint16_t hcapi_type; - struct tf_rm_alloc_info info; - void *tcam_shared_db_ptr = NULL; - struct tf_tcam_shared_wc_pools *tcam_shared_wc; - int i, cnt; TF_CHECK_PARMS2(tfp, parms); @@ -1209,74 +175,6 @@ tf_tcam_shared_clear(struct tf *tfp, parms->tcam_tbl_type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) return -EOPNOTSUPP; - if (!tf_tcam_db_valid(tfp, parms->dir)) { - TFP_DRV_LOG(ERR, - "%s: tcam shared pool doesn't exist\n", - tf_dir_2_str(parms->dir)); - return -ENOMEM; - } - - rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr); - if (rc) { - TFP_DRV_LOG(ERR, - "Failed to get tcam_shared_db from session, rc:%s\n", - strerror(-rc)); - return rc; - } - tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr; - - - if (parms->tcam_tbl_type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH) - id = TF_TCAM_SHARED_WC_POOL_HI; - else - id = TF_TCAM_SHARED_WC_POOL_LO; - - - /* Retrieve the device information */ - rc = tf_session_get_device(tfs, &dev); - if (rc) - return rc; - - rc = tf_tcam_shared_get_rm_info(tfp, - parms->dir, - &hcapi_type, - &info); - if (rc) { - TFP_DRV_LOG(ERR, - "%s: TCAM rm info get failed\n", - tf_dir_2_str(parms->dir)); - return rc; - } - - start = tcam_shared_wc->db[parms->dir][id].info.start; - cnt = tcam_shared_wc->db[parms->dir][id].info.stride; - - /* Override HI/LO type with parent WC TCAM type */ - nparms.dir = parms->dir; - nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM; - nparms.hcapi_type = hcapi_type; - - for (i = 0; i < cnt; i++) { - phy_idx = start + i; - nparms.idx = phy_idx; - - /* Clear entry */ - rc = tf_msg_tcam_entry_free(tfp, dev, &nparms); - if (rc) { - /* Log error */ - TFP_DRV_LOG(ERR, - "%s: %s: log%d free failed, rc:%s\n", - tf_dir_2_str(nparms.dir), - tf_tcam_tbl_2_str(nparms.type), - phy_idx, - strerror(-rc)); - return rc; - } - } - - TFP_DRV_LOG(DEBUG, - "%s: TCAM shared clear pool(%s)\n", - tf_dir_2_str(nparms.dir), - tf_pool_2_str(id)); - return 0; + rc = tf_tcam_mgr_shared_clear_msg(tfp, parms); + return rc; } diff --git a/drivers/net/bnxt/tf_core/tf_tcam_shared.h b/drivers/net/bnxt/tf_core/tf_tcam_shared.h index 524631f262..e25babcd18 100644 --- a/drivers/net/bnxt/tf_core/tf_tcam_shared.h +++ b/drivers/net/bnxt/tf_core/tf_tcam_shared.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2021 Broadcom + * Copyright(c) 2019-2023 Broadcom * All rights reserved. */ @@ -129,7 +129,6 @@ int tf_tcam_shared_set(struct tf *tfp, int tf_tcam_shared_get(struct tf *tfp, struct tf_tcam_get_parms *parms); - /** * Moves entries from the WC_TCAM_HI to the WC_TCAM_LO shared pools * for the P4 device. diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c index 1bb38399e4..8513ee06a9 100644 --- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c +++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c @@ -448,13 +448,13 @@ ulp_ctx_shared_session_open(struct bnxt *bp, switch (ulp_dev_id) { case BNXT_ULP_DEVICE_ID_WH_PLUS: - parms.device_type = TF_DEVICE_TYPE_WH; + parms.device_type = TF_DEVICE_TYPE_P5; 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; + parms.device_type = TF_DEVICE_TYPE_P4; break; default: BNXT_TF_DBG(ERR, "Unable to determine dev for opening session.\n"); @@ -563,13 +563,13 @@ ulp_ctx_session_open(struct bnxt *bp, switch (ulp_dev_id) { case BNXT_ULP_DEVICE_ID_WH_PLUS: - params.device_type = TF_DEVICE_TYPE_WH; + params.device_type = TF_DEVICE_TYPE_P5; break; case BNXT_ULP_DEVICE_ID_STINGRAY: params.device_type = TF_DEVICE_TYPE_SR; break; case BNXT_ULP_DEVICE_ID_THOR: - params.device_type = TF_DEVICE_TYPE_THOR; + params.device_type = TF_DEVICE_TYPE_P4; break; default: BNXT_TF_DBG(ERR, "Unable to determine device for opening session.\n");