From patchwork Mon Aug 21 13:54:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mykola Kostenok X-Patchwork-Id: 130586 X-Patchwork-Delegate: thomas@monjalon.net 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 DDB1B430C1; Mon, 21 Aug 2023 15:56:37 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 9B43243245; Mon, 21 Aug 2023 15:55:03 +0200 (CEST) Received: from egress-ip4a.ess.de.barracuda.com (egress-ip4a.ess.de.barracuda.com [18.184.203.227]) by mails.dpdk.org (Postfix) with ESMTP id 1398943245 for ; Mon, 21 Aug 2023 15:55:02 +0200 (CEST) Received: from EUR01-DB5-obe.outbound.protection.outlook.com (mail-db5eur01lp2058.outbound.protection.outlook.com [104.47.2.58]) by mx-outbound13-194.eu-central-1a.ess.aws.cudaops.com (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 21 Aug 2023 13:55:00 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ltJ6VuC5/ypzzDre7sTqdUILa6t/RZZwl9I1blZl6kSuclGmUzDfXGT8krnjZHMRvndvnxQYBAh0v7PCXd1qoaS74z5NXQsA7pRf/YpandbycrFr7ph4UAcwhi+VmtW1b8pdYzbmOiSGRVZamzLrdaIGHTH24xYh6FIyLLYDYTcKdfmgoaWO69U36qzZG8dxy0C20bSv0jn7QAKPO1dfhjvbFOeFRsMT+LMhNKK1+r4HSD0qlGGxyotUvG5Wp6fmWVWh5EvuDlvnaenBcLWm0+G1YFewa6hXTeehlkNYROdvm1yQoRiFgYeElnbEfSva79gWbregRnd0loeOj5q7HQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=PJv1Uia5K7CVSaUvWjZ89ZWQJcI6EHNk5FgU7WK8qqQ=; b=maqLtEBzJ2RgctBZAA4jS7j7E0z3zVvtnmSbifoPZirZRXQeMaioQC/XOWq2U/jzbTUg8bf6sqvZOx6IgZXpiv8Bwe0F+RVFZ2pp0CMv+8iEkytG7o4ikiF4CwQw+g6AsTSXvdiLhuaiTPJfttzjg1pFmbFTGhKrONiayOy8EB6Bpx9O/FLnv5ek8IFZoCjkFi8GYD3i1wgpwJLPEXKCLBEYPgbKuyR5u5XCjXM2dcnsSl41kq04CUgPOkAnkD5V/eZiWfluFi6ZzltHaRtGNaV/KL1l06T42oCX0IAAihU8mOGl/tRoeDGfafk0I/zrZtGjziIGBvwLgXUdVK1kpA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=fail (sender ip is 178.72.21.4) smtp.rcpttodomain=dpdk.org smtp.mailfrom=napatech.com; dmarc=fail (p=none sp=none pct=100) action=none header.from=napatech.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=napatech.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=PJv1Uia5K7CVSaUvWjZ89ZWQJcI6EHNk5FgU7WK8qqQ=; b=Kf/hjNT3GLYpfH4TzawkFUZVDf6P0QcMo15fRVFdpe27gfC7t0i3V4oxFqycVo6DJx4nYLQ7TJi/yxgiIRTERCDYIZcWnYeXVQfiaolRSs7eQoELausjGlBbQ5lF0xYqwmyhlHyhet9Ll5CarKCAEV/NDz8j29zzN1ybw2zzJls= Received: from DB8PR04CA0008.eurprd04.prod.outlook.com (2603:10a6:10:110::18) by DB9P190MB1961.EURP190.PROD.OUTLOOK.COM (2603:10a6:10:395::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.20; Mon, 21 Aug 2023 13:54:27 +0000 Received: from DU2PEPF0001E9C5.eurprd03.prod.outlook.com (2603:10a6:10:110:cafe::a) by DB8PR04CA0008.outlook.office365.com (2603:10a6:10:110::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.20 via Frontend Transport; Mon, 21 Aug 2023 13:54:27 +0000 X-MS-Exchange-Authentication-Results: spf=fail (sender IP is 178.72.21.4) smtp.mailfrom=napatech.com; dkim=none (message not signed) header.d=none;dmarc=fail action=none header.from=napatech.com; Received-SPF: Fail (protection.outlook.com: domain of napatech.com does not designate 178.72.21.4 as permitted sender) receiver=protection.outlook.com; client-ip=178.72.21.4; helo=localhost.localdomain.com; Received: from localhost.localdomain.com (178.72.21.4) by DU2PEPF0001E9C5.mail.protection.outlook.com (10.167.8.74) with Microsoft SMTP Server id 15.20.6699.14 via Frontend Transport; Mon, 21 Aug 2023 13:54:27 +0000 From: Mykola Kostenok To: dev@dpdk.org, mko-plv@napatech.com Cc: ckm@napatech.com Subject: [PATCH v6 1/8] net/ntnic: initial commit which adds register defines Date: Mon, 21 Aug 2023 15:54:19 +0200 Message-Id: <20230821135426.1478754-1-mko-plv@napatech.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20230816132552.2483752-1-mko-plv@napatech.com> References: <20230816132552.2483752-1-mko-plv@napatech.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU2PEPF0001E9C5:EE_|DB9P190MB1961:EE_ X-MS-Office365-Filtering-Correlation-Id: 0ff324bc-958f-4c25-2ad0-08dba24e2279 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: K/bq6vNgIPRZVCjFl1dLs9ydAyF/CQC4gKRev8BjjEFr+XAuwCaU/sOdXimg/hZiKRH8NPNiwBfe3WNASUfUD2vWMTk4IZ0jr5AESJTCzKnGh5rKq/puvdoMZL5ohtmriuzeDuT8WOSn3VeAauB2+52ESdjA4D/Q4OANA8zIl7CWTrIEMSqa5iYeRmA0to1ReprJdlBC6wVLjDSG7gniOOImkMeS5Way4bNn2tmNkRKbB5DpaTUZaN5WQBmVCdQHYIo9Uzj1iPR4mvV1t/nOtCNeL9G3+au4Pf37g0R7Q83inUbFdEw+/w1gTllQCNJbJI3ANvkYg4lZ2XxPeJhhwMji0fYg5L870obYPXBvX4EhjtVm4r2MJ++x+dyZjWKT5cte+X2KwWeMRnddfENSLa8jwxGDnFs6LI/OavanY4QY3X7k8W+z2ve7SlCXTV5uNrHr/FAjp72+LXYgfVAOrLbHDXmYir7iSSsdi0AFMkucFmyxDSJEAHBZMNjhUhKxsT7vN2oYEreSD4LJdgXtDll4ySsAV7SCDycmJ6qv+3U50soJEdDusvVuAmx5g+8pYxE70cFTTdEPiyI6xHJVAgFM6cvjrCZvamIrc/reKaRVmzS1swNK79kropbbZWX8ABoniGbUdbG3gZ7+tLq2nN8AwjFEhNJJLtzajf6G46MSXuwnck1LqIB1th4fKWCwrdyz65VOf3ucMYGIcxWyqfVYIxUxB6CarghxRh0N5Q6N4IX0/YczkCpo2WvYYsmLP18tW5QR7ZhV/csGtK9kPA== X-Forefront-Antispam-Report: CIP:178.72.21.4; CTRY:DK; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:localhost.localdomain.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230031)(6069001)(346002)(39840400004)(376002)(136003)(396003)(82310400011)(451199024)(186009)(1800799009)(36840700001)(46966006)(118246002)(2906002)(30864003)(40480700001)(6506007)(6486002)(83380400001)(5660300002)(336012)(26005)(34020700004)(86362001)(36860700001)(47076005)(8676002)(2616005)(8936002)(956004)(107886003)(4326008)(70206006)(316002)(6512007)(70586007)(36736006)(9316004)(478600001)(356005)(81166007)(6666004)(36756003)(41300700001)(1076003)(36900700001)(559001)(579004); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: cTv9X3uzWzL4jVuRKN0r7O/Gzugwu8R/u6DR/KNA830REBcrynE3wLlt2WxCx4isE3p/2uRsEiCtlAcEPPZRCD47VljHYfxwDt4OBLF1cvg5vxAidP00I26MUOeuVlMLzzCaCxowEtNTxyxh0a2LBSa+d1BRzR+2GPteUjQqoGvgznfDNktOb6l0xUJWISU/VAOt/AvBspwqhazCCtr05CdcuW81MX/n8jsUfFEvNeyHkJxZxi7Xmyi8EEyU8r4hiFqsNpZBzuO8JqpW9BL7lWykPJnvR7+FwO+CRqjhYnNIZAKtYvdFPsi1cBmlQzNpxfWWOcCw3XWqWp1uZUjRRXYs7o75PtDKESer7xY2DeCJyOOaFY2ZMEPtpa6uEf+Ns71j8daXRTIRI5Ljw7fjm5JC6D6XrZUGG8+HUa2iOSh9ncgjhl4lFnMhtnkcMEGagug/61c7FP6EAqp/ZkaRucq/3xcuSZhmGilKTfPWdtIOJoG9OkXtDsYyCx/znwRa45+lgTJyAiWndefyXrZcK40GTNZ4A1494ZARFqCEYmKTbCeHrkaAQr6NL1PbV20tOWXGVUgd22dWAJdONDOadgqFNSrwfFpwZ6Oo+PHeH4viG9X1tXzMNxBUjmSJUPN9t7VJD5vQ0M/rBRVcbj8a82UwxOckyx+EENXYR7bxqSt8GRJVq/jAcbh9ZddmY64bj77HBv3bzyg/g4ASj9YXy22TH/xBGMd+8HckGVVyoYvM1rQvaL0LuKII3ZgMl2dd1Dl+bPTjPmaKtsjYXM/ObomfbOYP7rnGXaBtUgQK5R8= X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Aug 2023 13:54:27.0697 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 0ff324bc-958f-4c25-2ad0-08dba24e2279 X-MS-Exchange-CrossTenant-Id: c4540d0b-728a-4233-9da5-9ea30c7ec3ed X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=c4540d0b-728a-4233-9da5-9ea30c7ec3ed; Ip=[178.72.21.4]; Helo=[localhost.localdomain.com] X-MS-Exchange-CrossTenant-AuthSource: DU2PEPF0001E9C5.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9P190MB1961 X-BESS-ID: 1692626100-303522-12323-18280-1 X-BESS-VER: 2019.1_20230817.1828 X-BESS-Apparent-Source-IP: 104.47.2.58 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKViamZuYWZkB2BlDYMNnY0Nww0d AgMS3ZyNLC0NLMwCQ5MdXQKNXUwsw00VSpNhYAAS5v6UMAAAA= X-BESS-Outbound-Spam-Score: 0.00 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.250292 [from cloudscan9-251.eu-central-1a.ess.aws.cudaops.com] Rule breakdown below pts rule name description ---- ---------------------- -------------------------------- 0.00 LARGE_BODY_SHORTCUT META: X-BESS-Outbound-Spam-Status: SCORE=0.00 using account:ESS113687 scores of KILL_LEVEL=7.0 tests=LARGE_BODY_SHORTCUT X-BESS-BRTS-Status: 1 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 From: Christian Koue Muf The NTNIC PMD does not rely on a kernel space Napatech driver, thus all defines related to the register layout is part of the PMD code, which will be added in later commits. Signed-off-by: Christian Koue Muf Reviewed-by: Mykola Kostenok --- v3: * Fixed not needed cflags as suggested in comments. v5: * Disable build for unsupported platforms. --- drivers/net/meson.build | 1 + drivers/net/ntnic/include/fpga_model.h | 99 + drivers/net/ntnic/meson.build | 36 + drivers/net/ntnic/nthw/nthw_register.h | 19 + .../supported/nthw_fpga_9563_055_024_0000.c | 4190 ++++++++++ .../nthw/supported/nthw_fpga_instances.h | 14 + .../nthw/supported/nthw_fpga_modules_defs.h | 166 + .../supported/nthw_fpga_parameters_defs.h | 209 + .../nthw/supported/nthw_fpga_registers_defs.h | 7277 +++++++++++++++++ 9 files changed, 12011 insertions(+) create mode 100644 drivers/net/ntnic/include/fpga_model.h create mode 100644 drivers/net/ntnic/meson.build create mode 100644 drivers/net/ntnic/nthw/nthw_register.h create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_9563_055_024_0000.c create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_modules_defs.h create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_parameters_defs.h create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_registers_defs.h diff --git a/drivers/net/meson.build b/drivers/net/meson.build index bd38b533c5..fb6d34b782 100644 --- a/drivers/net/meson.build +++ b/drivers/net/meson.build @@ -45,6 +45,7 @@ drivers = [ 'nfb', 'nfp', 'ngbe', + 'ntnic', 'null', 'octeontx', 'octeon_ep', diff --git a/drivers/net/ntnic/include/fpga_model.h b/drivers/net/ntnic/include/fpga_model.h new file mode 100644 index 0000000000..89f1ae9736 --- /dev/null +++ b/drivers/net/ntnic/include/fpga_model.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef FPGA_MODEL_H_ +#define FPGA_MODEL_H_ + +#include +#include +#include + +enum nt_fpga_bus_type { + BUS_TYPE_UNKNOWN = + 0, /* Unknown/uninitialized - keep this as the first enum element */ + BUS_TYPE_BAR, + BUS_TYPE_PCI, + BUS_TYPE_CCIP, + BUS_TYPE_RAB0, + BUS_TYPE_RAB1, + BUS_TYPE_RAB2, + BUS_TYPE_NMB, + BUS_TYPE_NDM, + BUS_TYPE_SPI0, + BUS_TYPE_SPI = BUS_TYPE_SPI0, +}; + +typedef enum nt_fpga_bus_type nt_fpga_bus_type_t; + +enum nt_fpga_register_type { + REGISTER_TYPE_UNKNOWN = + 0, /* Unknown/uninitialized - keep this as the first enum element */ + REGISTER_TYPE_RW, + REGISTER_TYPE_RO, + REGISTER_TYPE_WO, + REGISTER_TYPE_RC1, + REGISTER_TYPE_MIXED, +}; + +typedef enum nt_fpga_register_type nt_fpga_register_type_t; + +struct nt_fpga_field_init { + int id; + uint16_t bw; + uint16_t low; + uint64_t reset_val; +}; + +typedef struct nt_fpga_field_init nt_fpga_field_init_t; + +struct nt_fpga_register_init { + int id; + uint32_t addr_rel; + uint16_t bw; + nt_fpga_register_type_t type; + uint64_t reset_val; + int nb_fields; + struct nt_fpga_field_init *fields; +}; + +typedef struct nt_fpga_register_init nt_fpga_register_init_t; + +struct nt_fpga_module_init { + int id; + int instance; + int def_id; + int major_version; + int minor_version; + nt_fpga_bus_type_t bus_id; + uint32_t addr_base; + int nb_registers; + struct nt_fpga_register_init *registers; +}; + +typedef struct nt_fpga_module_init nt_fpga_module_init_t; + +struct nt_fpga_prod_param { + const int param_id; + const int param_value; +}; + +typedef struct nt_fpga_prod_param nt_fpga_prod_param_t; + +struct nt_fpga_prod_init { + int fpga_item_id; + int fpga_product_id; + int fpga_version; + int fpga_revision; + int fpga_patch_no; + int fpga_build_no; + uint32_t fpga_build_time; + int nb_prod_params; + struct nt_fpga_prod_param *product_params; + int nb_modules; + struct nt_fpga_module_init *modules; +}; + +typedef struct nt_fpga_prod_init nt_fpga_prod_init_t; + +#endif /* FPGA_MODEL_H_ */ diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build new file mode 100644 index 0000000000..0e2c2d38cc --- /dev/null +++ b/drivers/net/ntnic/meson.build @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2020-2023 Napatech A/S + +if is_windows + build = false + reason = 'not supported on Windows' + subdir_done() +endif + +if not dpdk_conf.has('RTE_ARCH_X86_64') + build = false + reason = 'only supported on x86_64' + subdir_done() +endif + +# includes +includes = [ + include_directories('.'), + include_directories('include'), + include_directories('nthw'), + include_directories('nthw/supported'), +] + +# all sources +sources = files( + 'nthw/supported/nthw_fpga_9563_055_024_0000.c', +) + +if is_variable('default_cflags') + cflags += default_cflags +else + cflags += machine_args + cflags += ['-DALLOW_INTERNAL_API'] +endif + +# END diff --git a/drivers/net/ntnic/nthw/nthw_register.h b/drivers/net/ntnic/nthw/nthw_register.h new file mode 100644 index 0000000000..5cdbd9fc5d --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_register.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NTHW_REGISTER_H_ +#define NTHW_REGISTER_H_ + +#include +#include +#include +#include + +#include "fpga_model.h" + +#include "nthw_fpga_modules_defs.h" +#include "nthw_fpga_parameters_defs.h" +#include "nthw_fpga_registers_defs.h" + +#endif /* NTHW_REGISTER_H_ */ diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_9563_055_024_0000.c b/drivers/net/ntnic/nthw/supported/nthw_fpga_9563_055_024_0000.c new file mode 100644 index 0000000000..b8113b40da --- /dev/null +++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_9563_055_024_0000.c @@ -0,0 +1,4190 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nthw_register.h" + +static nt_fpga_field_init_t cat_cct_ctrl_fields[] = { + { CAT_CCT_CTRL_ADR, 8, 0, 0x0000 }, + { CAT_CCT_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_cct_data_fields[] = { + { CAT_CCT_DATA_COLOR, 32, 0, 0x0000 }, + { CAT_CCT_DATA_KM, 4, 32, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_cfn_ctrl_fields[] = { + { CAT_CFN_CTRL_ADR, 6, 0, 0x0000 }, + { CAT_CFN_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_cfn_data_fields[] = { + { CAT_CFN_DATA_ENABLE, 1, 0, 0x0000 }, + { CAT_CFN_DATA_ERR_CV, 2, 99, 0x0000 }, + { CAT_CFN_DATA_ERR_FCS, 2, 101, 0x0000 }, + { CAT_CFN_DATA_ERR_INV, 1, 98, 0x0000 }, + { CAT_CFN_DATA_ERR_L3_CS, 2, 105, 0x0000 }, + { CAT_CFN_DATA_ERR_L4_CS, 2, 107, 0x0000 }, + { CAT_CFN_DATA_ERR_TNL_L3_CS, 2, 109, 0x0000 }, + { CAT_CFN_DATA_ERR_TNL_L4_CS, 2, 111, 0x0000 }, + { CAT_CFN_DATA_ERR_TNL_TTL_EXP, 2, 115, 0x0000 }, + { CAT_CFN_DATA_ERR_TRUNC, 2, 103, 0x0000 }, + { CAT_CFN_DATA_ERR_TTL_EXP, 2, 113, 0x0000 }, + { CAT_CFN_DATA_INV, 1, 1, 0x0000 }, + { CAT_CFN_DATA_KM0_OR, 3, 173, 0x0000 }, + { CAT_CFN_DATA_KM1_OR, 3, 176, 0x0000 }, + { CAT_CFN_DATA_LC, 8, 164, 0x0000 }, + { CAT_CFN_DATA_LC_INV, 1, 172, 0x0000 }, + { CAT_CFN_DATA_MAC_PORT, 2, 117, 0x0000 }, + { CAT_CFN_DATA_PM_AND_INV, 1, 161, 0x0000 }, + { CAT_CFN_DATA_PM_CMB, 4, 157, 0x0000 }, + { CAT_CFN_DATA_PM_CMP, 32, 119, 0x0000 }, + { CAT_CFN_DATA_PM_DCT, 2, 151, 0x0000 }, + { CAT_CFN_DATA_PM_EXT_INV, 4, 153, 0x0000 }, + { CAT_CFN_DATA_PM_INV, 1, 163, 0x0000 }, + { CAT_CFN_DATA_PM_OR_INV, 1, 162, 0x0000 }, + { CAT_CFN_DATA_PTC_CFP, 2, 5, 0x0000 }, + { CAT_CFN_DATA_PTC_FRAG, 4, 36, 0x0000 }, + { CAT_CFN_DATA_PTC_INV, 1, 2, 0x0000 }, + { CAT_CFN_DATA_PTC_IP_PROT, 8, 40, 0x0000 }, + { CAT_CFN_DATA_PTC_ISL, 2, 3, 0x0000 }, + { CAT_CFN_DATA_PTC_L2, 7, 12, 0x0000 }, + { CAT_CFN_DATA_PTC_L3, 3, 33, 0x0000 }, + { CAT_CFN_DATA_PTC_L4, 5, 48, 0x0000 }, + { CAT_CFN_DATA_PTC_MAC, 5, 7, 0x0000 }, + { CAT_CFN_DATA_PTC_MPLS, 8, 25, 0x0000 }, + { CAT_CFN_DATA_PTC_TNL_FRAG, 4, 81, 0x0000 }, + { CAT_CFN_DATA_PTC_TNL_IP_PROT, 8, 85, 0x0000 }, + { CAT_CFN_DATA_PTC_TNL_L2, 2, 64, 0x0000 }, + { CAT_CFN_DATA_PTC_TNL_L3, 3, 78, 0x0000 }, + { CAT_CFN_DATA_PTC_TNL_L4, 5, 93, 0x0000 }, + { CAT_CFN_DATA_PTC_TNL_MPLS, 8, 70, 0x0000 }, + { CAT_CFN_DATA_PTC_TNL_VLAN, 4, 66, 0x0000 }, + { CAT_CFN_DATA_PTC_TUNNEL, 11, 53, 0x0000 }, + { CAT_CFN_DATA_PTC_VLAN, 4, 21, 0x0000 }, + { CAT_CFN_DATA_PTC_VNTAG, 2, 19, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_cot_ctrl_fields[] = { + { CAT_COT_CTRL_ADR, 6, 0, 0x0000 }, + { CAT_COT_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_cot_data_fields[] = { + { CAT_COT_DATA_COLOR, 32, 0, 0x0000 }, + { CAT_COT_DATA_KM, 4, 32, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_cte_ctrl_fields[] = { + { CAT_CTE_CTRL_ADR, 6, 0, 0x0000 }, + { CAT_CTE_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_cte_data_fields[] = { + { CAT_CTE_DATA_COL_ENABLE, 1, 0, 0x0000 }, + { CAT_CTE_DATA_COR_ENABLE, 1, 1, 0x0000 }, + { CAT_CTE_DATA_EPP_ENABLE, 1, 9, 0x0000 }, + { CAT_CTE_DATA_HSH_ENABLE, 1, 2, 0x0000 }, + { CAT_CTE_DATA_HST_ENABLE, 1, 8, 0x0000 }, + { CAT_CTE_DATA_IPF_ENABLE, 1, 4, 0x0000 }, + { CAT_CTE_DATA_MSK_ENABLE, 1, 7, 0x0000 }, + { CAT_CTE_DATA_PDB_ENABLE, 1, 6, 0x0000 }, + { CAT_CTE_DATA_QSL_ENABLE, 1, 3, 0x0000 }, + { CAT_CTE_DATA_SLC_ENABLE, 1, 5, 0x0000 }, + { CAT_CTE_DATA_TPE_ENABLE, 1, 10, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_cts_ctrl_fields[] = { + { CAT_CTS_CTRL_ADR, 9, 0, 0x0000 }, + { CAT_CTS_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_cts_data_fields[] = { + { CAT_CTS_DATA_CAT_A, 6, 0, 0x0000 }, + { CAT_CTS_DATA_CAT_B, 6, 6, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_dct_ctrl_fields[] = { + { CAT_DCT_CTRL_ADR, 13, 0, 0x0000 }, + { CAT_DCT_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_dct_data_fields[] = { + { CAT_DCT_DATA_RES, 16, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_dct_sel_fields[] = { + { CAT_DCT_SEL_LU, 2, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_exo_ctrl_fields[] = { + { CAT_EXO_CTRL_ADR, 2, 0, 0x0000 }, + { CAT_EXO_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_exo_data_fields[] = { + { CAT_EXO_DATA_DYN, 5, 0, 0x0000 }, + { CAT_EXO_DATA_OFS, 11, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_fte0_ctrl_fields[] = { + { CAT_FTE0_CTRL_ADR, 9, 0, 0x0000 }, + { CAT_FTE0_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_fte0_data_fields[] = { + { CAT_FTE0_DATA_ENABLE, 8, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_fte1_ctrl_fields[] = { + { CAT_FTE1_CTRL_ADR, 9, 0, 0x0000 }, + { CAT_FTE1_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_fte1_data_fields[] = { + { CAT_FTE1_DATA_ENABLE, 8, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_join_fields[] = { + { CAT_JOIN_J1, 2, 0, 0x0000 }, + { CAT_JOIN_J2, 1, 8, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_kcc_ctrl_fields[] = { + { CAT_KCC_CTRL_ADR, 11, 0, 0x0000 }, + { CAT_KCC_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_kcc_data_fields[] = { + { CAT_KCC_DATA_CATEGORY, 8, 64, 0x0000 }, + { CAT_KCC_DATA_ID, 12, 72, 0x0000 }, + { CAT_KCC_DATA_KEY, 64, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_kce0_ctrl_fields[] = { + { CAT_KCE0_CTRL_ADR, 3, 0, 0x0000 }, + { CAT_KCE0_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_kce0_data_fields[] = { + { CAT_KCE0_DATA_ENABLE, 8, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_kce1_ctrl_fields[] = { + { CAT_KCE1_CTRL_ADR, 3, 0, 0x0000 }, + { CAT_KCE1_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_kce1_data_fields[] = { + { CAT_KCE1_DATA_ENABLE, 8, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_kcs0_ctrl_fields[] = { + { CAT_KCS0_CTRL_ADR, 6, 0, 0x0000 }, + { CAT_KCS0_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_kcs0_data_fields[] = { + { CAT_KCS0_DATA_CATEGORY, 6, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_kcs1_ctrl_fields[] = { + { CAT_KCS1_CTRL_ADR, 6, 0, 0x0000 }, + { CAT_KCS1_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_kcs1_data_fields[] = { + { CAT_KCS1_DATA_CATEGORY, 6, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_len_ctrl_fields[] = { + { CAT_LEN_CTRL_ADR, 3, 0, 0x0000 }, + { CAT_LEN_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_len_data_fields[] = { + { CAT_LEN_DATA_DYN1, 5, 28, 0x0000 }, + { CAT_LEN_DATA_DYN2, 5, 33, 0x0000 }, + { CAT_LEN_DATA_INV, 1, 38, 0x0000 }, + { CAT_LEN_DATA_LOWER, 14, 0, 0x0000 }, + { CAT_LEN_DATA_UPPER, 14, 14, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_rck_ctrl_fields[] = { + { CAT_RCK_CTRL_ADR, 8, 0, 0x0000 }, + { CAT_RCK_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cat_rck_data_fields[] = { + { CAT_RCK_DATA_CM0U, 1, 1, 0x0000 }, + { CAT_RCK_DATA_CM1U, 1, 5, 0x0000 }, + { CAT_RCK_DATA_CM2U, 1, 9, 0x0000 }, + { CAT_RCK_DATA_CM3U, 1, 13, 0x0000 }, + { CAT_RCK_DATA_CM4U, 1, 17, 0x0000 }, + { CAT_RCK_DATA_CM5U, 1, 21, 0x0000 }, + { CAT_RCK_DATA_CM6U, 1, 25, 0x0000 }, + { CAT_RCK_DATA_CM7U, 1, 29, 0x0000 }, + { CAT_RCK_DATA_CML0, 1, 0, 0x0000 }, + { CAT_RCK_DATA_CML1, 1, 4, 0x0000 }, + { CAT_RCK_DATA_CML2, 1, 8, 0x0000 }, + { CAT_RCK_DATA_CML3, 1, 12, 0x0000 }, + { CAT_RCK_DATA_CML4, 1, 16, 0x0000 }, + { CAT_RCK_DATA_CML5, 1, 20, 0x0000 }, + { CAT_RCK_DATA_CML6, 1, 24, 0x0000 }, + { CAT_RCK_DATA_CML7, 1, 28, 0x0000 }, + { CAT_RCK_DATA_SEL0, 1, 2, 0x0000 }, + { CAT_RCK_DATA_SEL1, 1, 6, 0x0000 }, + { CAT_RCK_DATA_SEL2, 1, 10, 0x0000 }, + { CAT_RCK_DATA_SEL3, 1, 14, 0x0000 }, + { CAT_RCK_DATA_SEL4, 1, 18, 0x0000 }, + { CAT_RCK_DATA_SEL5, 1, 22, 0x0000 }, + { CAT_RCK_DATA_SEL6, 1, 26, 0x0000 }, + { CAT_RCK_DATA_SEL7, 1, 30, 0x0000 }, + { CAT_RCK_DATA_SEU0, 1, 3, 0x0000 }, + { CAT_RCK_DATA_SEU1, 1, 7, 0x0000 }, + { CAT_RCK_DATA_SEU2, 1, 11, 0x0000 }, + { CAT_RCK_DATA_SEU3, 1, 15, 0x0000 }, + { CAT_RCK_DATA_SEU4, 1, 19, 0x0000 }, + { CAT_RCK_DATA_SEU5, 1, 23, 0x0000 }, + { CAT_RCK_DATA_SEU6, 1, 27, 0x0000 }, + { CAT_RCK_DATA_SEU7, 1, 31, 0x0000 }, +}; + +static nt_fpga_register_init_t cat_registers[] = { + { CAT_CCT_CTRL, 30, 32, REGISTER_TYPE_WO, 0, 2, cat_cct_ctrl_fields }, + { CAT_CCT_DATA, 31, 36, REGISTER_TYPE_WO, 0, 2, cat_cct_data_fields }, + { CAT_CFN_CTRL, 10, 32, REGISTER_TYPE_WO, 0, 2, cat_cfn_ctrl_fields }, + { CAT_CFN_DATA, 11, 179, REGISTER_TYPE_WO, 0, 44, cat_cfn_data_fields }, + { CAT_COT_CTRL, 28, 32, REGISTER_TYPE_WO, 0, 2, cat_cot_ctrl_fields }, + { CAT_COT_DATA, 29, 36, REGISTER_TYPE_WO, 0, 2, cat_cot_data_fields }, + { CAT_CTE_CTRL, 24, 32, REGISTER_TYPE_WO, 0, 2, cat_cte_ctrl_fields }, + { CAT_CTE_DATA, 25, 11, REGISTER_TYPE_WO, 0, 11, cat_cte_data_fields }, + { CAT_CTS_CTRL, 26, 32, REGISTER_TYPE_WO, 0, 2, cat_cts_ctrl_fields }, + { CAT_CTS_DATA, 27, 12, REGISTER_TYPE_WO, 0, 2, cat_cts_data_fields }, + { CAT_DCT_CTRL, 6, 32, REGISTER_TYPE_WO, 0, 2, cat_dct_ctrl_fields }, + { CAT_DCT_DATA, 7, 16, REGISTER_TYPE_WO, 0, 1, cat_dct_data_fields }, + { CAT_DCT_SEL, 4, 2, REGISTER_TYPE_WO, 0, 1, cat_dct_sel_fields }, + { CAT_EXO_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, cat_exo_ctrl_fields }, + { CAT_EXO_DATA, 1, 27, REGISTER_TYPE_WO, 0, 2, cat_exo_data_fields }, + { CAT_FTE0_CTRL, 16, 32, REGISTER_TYPE_WO, 0, 2, cat_fte0_ctrl_fields }, + { CAT_FTE0_DATA, 17, 8, REGISTER_TYPE_WO, 0, 1, cat_fte0_data_fields }, + { CAT_FTE1_CTRL, 22, 32, REGISTER_TYPE_WO, 0, 2, cat_fte1_ctrl_fields }, + { CAT_FTE1_DATA, 23, 8, REGISTER_TYPE_WO, 0, 1, cat_fte1_data_fields }, + { CAT_JOIN, 5, 9, REGISTER_TYPE_WO, 0, 2, cat_join_fields }, + { CAT_KCC_CTRL, 32, 32, REGISTER_TYPE_WO, 0, 2, cat_kcc_ctrl_fields }, + { CAT_KCC_DATA, 33, 84, REGISTER_TYPE_WO, 0, 3, cat_kcc_data_fields }, + { CAT_KCE0_CTRL, 12, 32, REGISTER_TYPE_WO, 0, 2, cat_kce0_ctrl_fields }, + { CAT_KCE0_DATA, 13, 8, REGISTER_TYPE_WO, 0, 1, cat_kce0_data_fields }, + { CAT_KCE1_CTRL, 18, 32, REGISTER_TYPE_WO, 0, 2, cat_kce1_ctrl_fields }, + { CAT_KCE1_DATA, 19, 8, REGISTER_TYPE_WO, 0, 1, cat_kce1_data_fields }, + { CAT_KCS0_CTRL, 14, 32, REGISTER_TYPE_WO, 0, 2, cat_kcs0_ctrl_fields }, + { CAT_KCS0_DATA, 15, 6, REGISTER_TYPE_WO, 0, 1, cat_kcs0_data_fields }, + { CAT_KCS1_CTRL, 20, 32, REGISTER_TYPE_WO, 0, 2, cat_kcs1_ctrl_fields }, + { CAT_KCS1_DATA, 21, 6, REGISTER_TYPE_WO, 0, 1, cat_kcs1_data_fields }, + { CAT_LEN_CTRL, 8, 32, REGISTER_TYPE_WO, 0, 2, cat_len_ctrl_fields }, + { CAT_LEN_DATA, 9, 39, REGISTER_TYPE_WO, 0, 5, cat_len_data_fields }, + { CAT_RCK_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2, cat_rck_ctrl_fields }, + { CAT_RCK_DATA, 3, 32, REGISTER_TYPE_WO, 0, 32, cat_rck_data_fields }, +}; + +static nt_fpga_field_init_t cpy_writer0_ctrl_fields[] = { + { CPY_WRITER0_CTRL_ADR, 4, 0, 0x0000 }, + { CPY_WRITER0_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer0_data_fields[] = { + { CPY_WRITER0_DATA_DYN, 5, 17, 0x0000 }, + { CPY_WRITER0_DATA_LEN, 4, 22, 0x0000 }, + { CPY_WRITER0_DATA_MASK_POINTER, 4, 26, 0x0000 }, + { CPY_WRITER0_DATA_OFS, 14, 3, 0x0000 }, + { CPY_WRITER0_DATA_READER_SELECT, 3, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer0_mask_ctrl_fields[] = { + { CPY_WRITER0_MASK_CTRL_ADR, 4, 0, 0x0000 }, + { CPY_WRITER0_MASK_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer0_mask_data_fields[] = { + { CPY_WRITER0_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer1_ctrl_fields[] = { + { CPY_WRITER1_CTRL_ADR, 4, 0, 0x0000 }, + { CPY_WRITER1_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer1_data_fields[] = { + { CPY_WRITER1_DATA_DYN, 5, 17, 0x0000 }, + { CPY_WRITER1_DATA_LEN, 4, 22, 0x0000 }, + { CPY_WRITER1_DATA_MASK_POINTER, 4, 26, 0x0000 }, + { CPY_WRITER1_DATA_OFS, 14, 3, 0x0000 }, + { CPY_WRITER1_DATA_READER_SELECT, 3, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer1_mask_ctrl_fields[] = { + { CPY_WRITER1_MASK_CTRL_ADR, 4, 0, 0x0000 }, + { CPY_WRITER1_MASK_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer1_mask_data_fields[] = { + { CPY_WRITER1_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer2_ctrl_fields[] = { + { CPY_WRITER2_CTRL_ADR, 4, 0, 0x0000 }, + { CPY_WRITER2_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer2_data_fields[] = { + { CPY_WRITER2_DATA_DYN, 5, 17, 0x0000 }, + { CPY_WRITER2_DATA_LEN, 4, 22, 0x0000 }, + { CPY_WRITER2_DATA_MASK_POINTER, 4, 26, 0x0000 }, + { CPY_WRITER2_DATA_OFS, 14, 3, 0x0000 }, + { CPY_WRITER2_DATA_READER_SELECT, 3, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer2_mask_ctrl_fields[] = { + { CPY_WRITER2_MASK_CTRL_ADR, 4, 0, 0x0000 }, + { CPY_WRITER2_MASK_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer2_mask_data_fields[] = { + { CPY_WRITER2_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer3_ctrl_fields[] = { + { CPY_WRITER3_CTRL_ADR, 4, 0, 0x0000 }, + { CPY_WRITER3_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer3_data_fields[] = { + { CPY_WRITER3_DATA_DYN, 5, 17, 0x0000 }, + { CPY_WRITER3_DATA_LEN, 4, 22, 0x0000 }, + { CPY_WRITER3_DATA_MASK_POINTER, 4, 26, 0x0000 }, + { CPY_WRITER3_DATA_OFS, 14, 3, 0x0000 }, + { CPY_WRITER3_DATA_READER_SELECT, 3, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer3_mask_ctrl_fields[] = { + { CPY_WRITER3_MASK_CTRL_ADR, 4, 0, 0x0000 }, + { CPY_WRITER3_MASK_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer3_mask_data_fields[] = { + { CPY_WRITER3_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer4_ctrl_fields[] = { + { CPY_WRITER4_CTRL_ADR, 4, 0, 0x0000 }, + { CPY_WRITER4_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer4_data_fields[] = { + { CPY_WRITER4_DATA_DYN, 5, 17, 0x0000 }, + { CPY_WRITER4_DATA_LEN, 4, 22, 0x0000 }, + { CPY_WRITER4_DATA_MASK_POINTER, 4, 26, 0x0000 }, + { CPY_WRITER4_DATA_OFS, 14, 3, 0x0000 }, + { CPY_WRITER4_DATA_READER_SELECT, 3, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer4_mask_ctrl_fields[] = { + { CPY_WRITER4_MASK_CTRL_ADR, 4, 0, 0x0000 }, + { CPY_WRITER4_MASK_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t cpy_writer4_mask_data_fields[] = { + { CPY_WRITER4_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 }, +}; + +static nt_fpga_register_init_t cpy_registers[] = { + { CPY_WRITER0_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, + cpy_writer0_ctrl_fields + }, + { CPY_WRITER0_DATA, 1, 30, REGISTER_TYPE_WO, 0, 5, + cpy_writer0_data_fields + }, + { CPY_WRITER0_MASK_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2, + cpy_writer0_mask_ctrl_fields + }, + { CPY_WRITER0_MASK_DATA, 3, 16, REGISTER_TYPE_WO, 0, 1, + cpy_writer0_mask_data_fields + }, + { CPY_WRITER1_CTRL, 4, 32, REGISTER_TYPE_WO, 0, 2, + cpy_writer1_ctrl_fields + }, + { CPY_WRITER1_DATA, 5, 30, REGISTER_TYPE_WO, 0, 5, + cpy_writer1_data_fields + }, + { CPY_WRITER1_MASK_CTRL, 6, 32, REGISTER_TYPE_WO, 0, 2, + cpy_writer1_mask_ctrl_fields + }, + { CPY_WRITER1_MASK_DATA, 7, 16, REGISTER_TYPE_WO, 0, 1, + cpy_writer1_mask_data_fields + }, + { CPY_WRITER2_CTRL, 8, 32, REGISTER_TYPE_WO, 0, 2, + cpy_writer2_ctrl_fields + }, + { CPY_WRITER2_DATA, 9, 30, REGISTER_TYPE_WO, 0, 5, + cpy_writer2_data_fields + }, + { CPY_WRITER2_MASK_CTRL, 10, 32, REGISTER_TYPE_WO, 0, 2, + cpy_writer2_mask_ctrl_fields + }, + { CPY_WRITER2_MASK_DATA, 11, 16, REGISTER_TYPE_WO, 0, 1, + cpy_writer2_mask_data_fields + }, + { CPY_WRITER3_CTRL, 12, 32, REGISTER_TYPE_WO, 0, 2, + cpy_writer3_ctrl_fields + }, + { CPY_WRITER3_DATA, 13, 30, REGISTER_TYPE_WO, 0, 5, + cpy_writer3_data_fields + }, + { CPY_WRITER3_MASK_CTRL, 14, 32, REGISTER_TYPE_WO, 0, 2, + cpy_writer3_mask_ctrl_fields + }, + { CPY_WRITER3_MASK_DATA, 15, 16, REGISTER_TYPE_WO, 0, 1, + cpy_writer3_mask_data_fields + }, + { CPY_WRITER4_CTRL, 16, 32, REGISTER_TYPE_WO, 0, 2, + cpy_writer4_ctrl_fields + }, + { CPY_WRITER4_DATA, 17, 30, REGISTER_TYPE_WO, 0, 5, + cpy_writer4_data_fields + }, + { CPY_WRITER4_MASK_CTRL, 18, 32, REGISTER_TYPE_WO, 0, 2, + cpy_writer4_mask_ctrl_fields + }, + { CPY_WRITER4_MASK_DATA, 19, 16, REGISTER_TYPE_WO, 0, 1, + cpy_writer4_mask_data_fields + }, +}; + +static nt_fpga_field_init_t csu_rcp_ctrl_fields[] = { + { CSU_RCP_CTRL_ADR, 4, 0, 0x0000 }, + { CSU_RCP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t csu_rcp_data_fields[] = { + { CSU_RCP_DATA_IL3_CMD, 2, 5, 0x0000 }, + { CSU_RCP_DATA_IL4_CMD, 3, 7, 0x0000 }, + { CSU_RCP_DATA_OL3_CMD, 2, 0, 0x0000 }, + { CSU_RCP_DATA_OL4_CMD, 3, 2, 0x0000 }, +}; + +static nt_fpga_register_init_t csu_registers[] = { + { CSU_RCP_CTRL, 1, 32, REGISTER_TYPE_WO, 0, 2, csu_rcp_ctrl_fields }, + { CSU_RCP_DATA, 2, 10, REGISTER_TYPE_WO, 0, 4, csu_rcp_data_fields }, +}; + +static nt_fpga_field_init_t dbs_rx_am_ctrl_fields[] = { + { DBS_RX_AM_CTRL_ADR, 7, 0, 0x0000 }, + { DBS_RX_AM_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_rx_am_data_fields[] = { + { DBS_RX_AM_DATA_ENABLE, 1, 72, 0x0000 }, + { DBS_RX_AM_DATA_GPA, 64, 0, 0x0000 }, + { DBS_RX_AM_DATA_HID, 8, 64, 0x0000 }, + { DBS_RX_AM_DATA_INT, 1, 74, 0x0000 }, + { DBS_RX_AM_DATA_PCKED, 1, 73, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_rx_control_fields[] = { + { DBS_RX_CONTROL_AME, 1, 7, 0 }, { DBS_RX_CONTROL_AMS, 4, 8, 8 }, + { DBS_RX_CONTROL_LQ, 7, 0, 0 }, { DBS_RX_CONTROL_QE, 1, 17, 0 }, + { DBS_RX_CONTROL_UWE, 1, 12, 0 }, { DBS_RX_CONTROL_UWS, 4, 13, 5 }, +}; + +static nt_fpga_field_init_t dbs_rx_dr_ctrl_fields[] = { + { DBS_RX_DR_CTRL_ADR, 7, 0, 0x0000 }, + { DBS_RX_DR_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_rx_dr_data_fields[] = { + { DBS_RX_DR_DATA_GPA, 64, 0, 0x0000 }, + { DBS_RX_DR_DATA_HDR, 1, 88, 0x0000 }, + { DBS_RX_DR_DATA_HID, 8, 64, 0x0000 }, + { DBS_RX_DR_DATA_PCKED, 1, 87, 0x0000 }, + { DBS_RX_DR_DATA_QS, 15, 72, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_rx_idle_fields[] = { + { DBS_RX_IDLE_BUSY, 1, 8, 0 }, + { DBS_RX_IDLE_IDLE, 1, 0, 0x0000 }, + { DBS_RX_IDLE_QUEUE, 7, 1, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_rx_init_fields[] = { + { DBS_RX_INIT_BUSY, 1, 8, 0 }, + { DBS_RX_INIT_INIT, 1, 0, 0x0000 }, + { DBS_RX_INIT_QUEUE, 7, 1, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_rx_init_val_fields[] = { + { DBS_RX_INIT_VAL_IDX, 16, 0, 0x0000 }, + { DBS_RX_INIT_VAL_PTR, 15, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_rx_ptr_fields[] = { + { DBS_RX_PTR_PTR, 16, 0, 0x0000 }, + { DBS_RX_PTR_QUEUE, 7, 16, 0x0000 }, + { DBS_RX_PTR_VALID, 1, 23, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_rx_uw_ctrl_fields[] = { + { DBS_RX_UW_CTRL_ADR, 7, 0, 0x0000 }, + { DBS_RX_UW_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_rx_uw_data_fields[] = { + { DBS_RX_UW_DATA_GPA, 64, 0, 0x0000 }, + { DBS_RX_UW_DATA_HID, 8, 64, 0x0000 }, + { DBS_RX_UW_DATA_INT, 1, 88, 0x0000 }, + { DBS_RX_UW_DATA_ISTK, 1, 92, 0x0000 }, + { DBS_RX_UW_DATA_PCKED, 1, 87, 0x0000 }, + { DBS_RX_UW_DATA_QS, 15, 72, 0x0000 }, + { DBS_RX_UW_DATA_VEC, 3, 89, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_tx_am_ctrl_fields[] = { + { DBS_TX_AM_CTRL_ADR, 7, 0, 0x0000 }, + { DBS_TX_AM_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_tx_am_data_fields[] = { + { DBS_TX_AM_DATA_ENABLE, 1, 72, 0x0000 }, + { DBS_TX_AM_DATA_GPA, 64, 0, 0x0000 }, + { DBS_TX_AM_DATA_HID, 8, 64, 0x0000 }, + { DBS_TX_AM_DATA_INT, 1, 74, 0x0000 }, + { DBS_TX_AM_DATA_PCKED, 1, 73, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_tx_control_fields[] = { + { DBS_TX_CONTROL_AME, 1, 7, 0 }, { DBS_TX_CONTROL_AMS, 4, 8, 5 }, + { DBS_TX_CONTROL_LQ, 7, 0, 0 }, { DBS_TX_CONTROL_QE, 1, 17, 0 }, + { DBS_TX_CONTROL_UWE, 1, 12, 0 }, { DBS_TX_CONTROL_UWS, 4, 13, 8 }, +}; + +static nt_fpga_field_init_t dbs_tx_dr_ctrl_fields[] = { + { DBS_TX_DR_CTRL_ADR, 7, 0, 0x0000 }, + { DBS_TX_DR_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_tx_dr_data_fields[] = { + { DBS_TX_DR_DATA_GPA, 64, 0, 0x0000 }, + { DBS_TX_DR_DATA_HDR, 1, 88, 0x0000 }, + { DBS_TX_DR_DATA_HID, 8, 64, 0x0000 }, + { DBS_TX_DR_DATA_PCKED, 1, 87, 0x0000 }, + { DBS_TX_DR_DATA_PORT, 1, 89, 0x0000 }, + { DBS_TX_DR_DATA_QS, 15, 72, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_tx_idle_fields[] = { + { DBS_TX_IDLE_BUSY, 1, 8, 0 }, + { DBS_TX_IDLE_IDLE, 1, 0, 0x0000 }, + { DBS_TX_IDLE_QUEUE, 7, 1, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_tx_init_fields[] = { + { DBS_TX_INIT_BUSY, 1, 8, 0 }, + { DBS_TX_INIT_INIT, 1, 0, 0x0000 }, + { DBS_TX_INIT_QUEUE, 7, 1, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_tx_init_val_fields[] = { + { DBS_TX_INIT_VAL_IDX, 16, 0, 0x0000 }, + { DBS_TX_INIT_VAL_PTR, 15, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_tx_ptr_fields[] = { + { DBS_TX_PTR_PTR, 16, 0, 0x0000 }, + { DBS_TX_PTR_QUEUE, 7, 16, 0x0000 }, + { DBS_TX_PTR_VALID, 1, 23, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_tx_qos_ctrl_fields[] = { + { DBS_TX_QOS_CTRL_ADR, 1, 0, 0x0000 }, + { DBS_TX_QOS_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_tx_qos_data_fields[] = { + { DBS_TX_QOS_DATA_BS, 27, 17, 0x0000 }, + { DBS_TX_QOS_DATA_EN, 1, 0, 0x0000 }, + { DBS_TX_QOS_DATA_IR, 16, 1, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_tx_qos_rate_fields[] = { + { DBS_TX_QOS_RATE_DIV, 19, 16, 2 }, + { DBS_TX_QOS_RATE_MUL, 16, 0, 1 }, +}; + +static nt_fpga_field_init_t dbs_tx_qp_ctrl_fields[] = { + { DBS_TX_QP_CTRL_ADR, 7, 0, 0x0000 }, + { DBS_TX_QP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_tx_qp_data_fields[] = { + { DBS_TX_QP_DATA_VPORT, 1, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_tx_uw_ctrl_fields[] = { + { DBS_TX_UW_CTRL_ADR, 7, 0, 0x0000 }, + { DBS_TX_UW_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t dbs_tx_uw_data_fields[] = { + { DBS_TX_UW_DATA_GPA, 64, 0, 0x0000 }, + { DBS_TX_UW_DATA_HID, 8, 64, 0x0000 }, + { DBS_TX_UW_DATA_INO, 1, 93, 0x0000 }, + { DBS_TX_UW_DATA_INT, 1, 88, 0x0000 }, + { DBS_TX_UW_DATA_ISTK, 1, 92, 0x0000 }, + { DBS_TX_UW_DATA_PCKED, 1, 87, 0x0000 }, + { DBS_TX_UW_DATA_QS, 15, 72, 0x0000 }, + { DBS_TX_UW_DATA_VEC, 3, 89, 0x0000 }, +}; + +static nt_fpga_register_init_t dbs_registers[] = { + { DBS_RX_AM_CTRL, 10, 32, REGISTER_TYPE_WO, 0, 2, + dbs_rx_am_ctrl_fields + }, + { DBS_RX_AM_DATA, 11, 75, REGISTER_TYPE_WO, 0, 5, + dbs_rx_am_data_fields + }, + { DBS_RX_CONTROL, 0, 18, REGISTER_TYPE_RW, 43008, 6, + dbs_rx_control_fields + }, + { DBS_RX_DR_CTRL, 18, 32, REGISTER_TYPE_WO, 0, 2, + dbs_rx_dr_ctrl_fields + }, + { DBS_RX_DR_DATA, 19, 89, REGISTER_TYPE_WO, 0, 5, + dbs_rx_dr_data_fields + }, + { DBS_RX_IDLE, 8, 9, REGISTER_TYPE_MIXED, 0, 3, dbs_rx_idle_fields }, + { DBS_RX_INIT, 2, 9, REGISTER_TYPE_MIXED, 0, 3, dbs_rx_init_fields }, + { DBS_RX_INIT_VAL, 3, 31, REGISTER_TYPE_WO, 0, 2, + dbs_rx_init_val_fields + }, + { DBS_RX_PTR, 4, 24, REGISTER_TYPE_MIXED, 0, 3, dbs_rx_ptr_fields }, + { DBS_RX_UW_CTRL, 14, 32, REGISTER_TYPE_WO, 0, 2, + dbs_rx_uw_ctrl_fields + }, + { DBS_RX_UW_DATA, 15, 93, REGISTER_TYPE_WO, 0, 7, + dbs_rx_uw_data_fields + }, + { DBS_TX_AM_CTRL, 12, 32, REGISTER_TYPE_WO, 0, 2, + dbs_tx_am_ctrl_fields + }, + { DBS_TX_AM_DATA, 13, 75, REGISTER_TYPE_WO, 0, 5, + dbs_tx_am_data_fields + }, + { DBS_TX_CONTROL, 1, 18, REGISTER_TYPE_RW, 66816, 6, + dbs_tx_control_fields + }, + { DBS_TX_DR_CTRL, 20, 32, REGISTER_TYPE_WO, 0, 2, + dbs_tx_dr_ctrl_fields + }, + { DBS_TX_DR_DATA, 21, 90, REGISTER_TYPE_WO, 0, 6, + dbs_tx_dr_data_fields + }, + { DBS_TX_IDLE, 9, 9, REGISTER_TYPE_MIXED, 0, 3, dbs_tx_idle_fields }, + { DBS_TX_INIT, 5, 9, REGISTER_TYPE_MIXED, 0, 3, dbs_tx_init_fields }, + { DBS_TX_INIT_VAL, 6, 31, REGISTER_TYPE_WO, 0, 2, + dbs_tx_init_val_fields + }, + { DBS_TX_PTR, 7, 24, REGISTER_TYPE_MIXED, 0, 3, dbs_tx_ptr_fields }, + { DBS_TX_QOS_CTRL, 24, 32, REGISTER_TYPE_WO, 0, 2, + dbs_tx_qos_ctrl_fields + }, + { DBS_TX_QOS_DATA, 25, 44, REGISTER_TYPE_WO, 0, 3, + dbs_tx_qos_data_fields + }, + { DBS_TX_QOS_RATE, 26, 35, REGISTER_TYPE_RW, 131073, 2, + dbs_tx_qos_rate_fields + }, + { DBS_TX_QP_CTRL, 22, 32, REGISTER_TYPE_WO, 0, 2, + dbs_tx_qp_ctrl_fields + }, + { DBS_TX_QP_DATA, 23, 1, REGISTER_TYPE_WO, 0, 1, + dbs_tx_qp_data_fields + }, + { DBS_TX_UW_CTRL, 16, 32, REGISTER_TYPE_WO, 0, 2, + dbs_tx_uw_ctrl_fields + }, + { DBS_TX_UW_DATA, 17, 94, REGISTER_TYPE_WO, 0, 8, + dbs_tx_uw_data_fields + }, +}; + +static nt_fpga_field_init_t flm_buf_ctrl_fields[] = { + { FLM_BUF_CTRL_INF_AVAIL, 16, 16, 0x0000 }, + { FLM_BUF_CTRL_LRN_FREE, 16, 0, 0x0000 }, + { FLM_BUF_CTRL_STA_AVAIL, 16, 32, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_control_fields[] = { + { FLM_CONTROL_CRCRD, 1, 12, 0x0000 }, + { FLM_CONTROL_CRCWR, 1, 11, 0x0000 }, + { FLM_CONTROL_EAB, 5, 18, 0 }, + { FLM_CONTROL_ENABLE, 1, 0, 0 }, + { FLM_CONTROL_INIT, 1, 1, 0x0000 }, + { FLM_CONTROL_LDS, 1, 2, 0x0000 }, + { FLM_CONTROL_LFS, 1, 3, 0x0000 }, + { FLM_CONTROL_LIS, 1, 4, 0x0000 }, + { FLM_CONTROL_PDS, 1, 9, 0x0000 }, + { FLM_CONTROL_PIS, 1, 10, 0x0000 }, + { FLM_CONTROL_RBL, 4, 13, 0 }, + { FLM_CONTROL_RDS, 1, 7, 0x0000 }, + { FLM_CONTROL_RIS, 1, 8, 0x0000 }, + { FLM_CONTROL_SPLIT_SDRAM_USAGE, 5, 23, 16 }, + { FLM_CONTROL_UDS, 1, 5, 0x0000 }, + { FLM_CONTROL_UIS, 1, 6, 0x0000 }, + { FLM_CONTROL_WPD, 1, 17, 0 }, +}; + +static nt_fpga_field_init_t flm_inf_data_fields[] = { + { FLM_INF_DATA_BYTES, 64, 0, 0x0000 }, + { FLM_INF_DATA_CAUSE, 3, 264, 0x0000 }, + { FLM_INF_DATA_EOR, 1, 287, 0x0000 }, + { FLM_INF_DATA_ID, 72, 192, 0x0000 }, + { FLM_INF_DATA_PACKETS, 64, 64, 0x0000 }, + { FLM_INF_DATA_TS, 64, 128, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_load_aps_fields[] = { + { FLM_LOAD_APS_APS, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_load_bin_fields[] = { + { FLM_LOAD_BIN_BIN, 30, 0, 8388607 }, +}; + +static nt_fpga_field_init_t flm_load_lps_fields[] = { + { FLM_LOAD_LPS_LPS, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_load_pps_fields[] = { + { FLM_LOAD_PPS_PPS, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_lrn_data_fields[] = { + { FLM_LRN_DATA_ADJ, 32, 480, 0x0000 }, + { FLM_LRN_DATA_COLOR, 32, 448, 0x0000 }, + { FLM_LRN_DATA_DSCP, 6, 734, 0x0000 }, + { FLM_LRN_DATA_ENT, 1, 729, 0x0000 }, + { FLM_LRN_DATA_EOR, 1, 767, 0x0000 }, + { FLM_LRN_DATA_FILL, 12, 584, 0x0000 }, + { FLM_LRN_DATA_FT, 4, 596, 0x0000 }, + { FLM_LRN_DATA_FT_MBR, 4, 600, 0x0000 }, + { FLM_LRN_DATA_FT_MISS, 4, 604, 0x0000 }, + { FLM_LRN_DATA_ID, 72, 512, 0x0000 }, + { FLM_LRN_DATA_KID, 8, 328, 0x0000 }, + { FLM_LRN_DATA_MBR_ID1, 28, 608, 0x0000 }, + { FLM_LRN_DATA_MBR_ID2, 28, 636, 0x0000 }, + { FLM_LRN_DATA_MBR_ID3, 28, 664, 0x0000 }, + { FLM_LRN_DATA_MBR_ID4, 28, 692, 0x0000 }, + { FLM_LRN_DATA_NAT_EN, 1, 747, 0x0000 }, + { FLM_LRN_DATA_NAT_IP, 32, 336, 0x0000 }, + { FLM_LRN_DATA_NAT_PORT, 16, 400, 0x0000 }, + { FLM_LRN_DATA_OP, 4, 730, 0x0000 }, + { FLM_LRN_DATA_PRIO, 2, 727, 0x0000 }, + { FLM_LRN_DATA_PROT, 8, 320, 0x0000 }, + { FLM_LRN_DATA_QFI, 6, 740, 0x0000 }, + { FLM_LRN_DATA_QW0, 128, 192, 0x0000 }, + { FLM_LRN_DATA_QW4, 128, 64, 0x0000 }, + { FLM_LRN_DATA_RATE, 16, 416, 0x0000 }, + { FLM_LRN_DATA_RQI, 1, 746, 0x0000 }, + { FLM_LRN_DATA_SIZE, 16, 432, 0x0000 }, + { FLM_LRN_DATA_STAT_PROF, 4, 723, 0x0000 }, + { FLM_LRN_DATA_SW8, 32, 32, 0x0000 }, + { FLM_LRN_DATA_SW9, 32, 0, 0x0000 }, + { FLM_LRN_DATA_TEID, 32, 368, 0x0000 }, + { FLM_LRN_DATA_VOL_IDX, 3, 720, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_prio_fields[] = { + { FLM_PRIO_FT0, 4, 4, 1 }, { FLM_PRIO_FT1, 4, 12, 1 }, + { FLM_PRIO_FT2, 4, 20, 1 }, { FLM_PRIO_FT3, 4, 28, 1 }, + { FLM_PRIO_LIMIT0, 4, 0, 0 }, { FLM_PRIO_LIMIT1, 4, 8, 0 }, + { FLM_PRIO_LIMIT2, 4, 16, 0 }, { FLM_PRIO_LIMIT3, 4, 24, 0 }, +}; + +static nt_fpga_field_init_t flm_pst_ctrl_fields[] = { + { FLM_PST_CTRL_ADR, 4, 0, 0x0000 }, + { FLM_PST_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_pst_data_fields[] = { + { FLM_PST_DATA_BP, 5, 0, 0x0000 }, + { FLM_PST_DATA_PP, 5, 5, 0x0000 }, + { FLM_PST_DATA_TP, 5, 10, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_rcp_ctrl_fields[] = { + { FLM_RCP_CTRL_ADR, 5, 0, 0x0000 }, + { FLM_RCP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_rcp_data_fields[] = { + { FLM_RCP_DATA_AUTO_IPV4_MASK, 1, 402, 0x0000 }, + { FLM_RCP_DATA_BYT_DYN, 5, 387, 0x0000 }, + { FLM_RCP_DATA_BYT_OFS, 8, 392, 0x0000 }, + { FLM_RCP_DATA_IPN, 1, 386, 0x0000 }, + { FLM_RCP_DATA_KID, 8, 377, 0x0000 }, + { FLM_RCP_DATA_LOOKUP, 1, 0, 0x0000 }, + { FLM_RCP_DATA_MASK, 320, 57, 0x0000 }, + { FLM_RCP_DATA_OPN, 1, 385, 0x0000 }, + { FLM_RCP_DATA_QW0_DYN, 5, 1, 0x0000 }, + { FLM_RCP_DATA_QW0_OFS, 8, 6, 0x0000 }, + { FLM_RCP_DATA_QW0_SEL, 2, 14, 0x0000 }, + { FLM_RCP_DATA_QW4_DYN, 5, 16, 0x0000 }, + { FLM_RCP_DATA_QW4_OFS, 8, 21, 0x0000 }, + { FLM_RCP_DATA_SW8_DYN, 5, 29, 0x0000 }, + { FLM_RCP_DATA_SW8_OFS, 8, 34, 0x0000 }, + { FLM_RCP_DATA_SW8_SEL, 2, 42, 0x0000 }, + { FLM_RCP_DATA_SW9_DYN, 5, 44, 0x0000 }, + { FLM_RCP_DATA_SW9_OFS, 8, 49, 0x0000 }, + { FLM_RCP_DATA_TXPLM, 2, 400, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_scrub_fields[] = { + { FLM_SCRUB_I, 16, 0, 0 }, +}; + +static nt_fpga_field_init_t flm_status_fields[] = { + { FLM_STATUS_CALIBDONE, 1, 0, 0x0000 }, + { FLM_STATUS_CRCERR, 1, 5, 0x0000 }, + { FLM_STATUS_CRITICAL, 1, 3, 0x0000 }, + { FLM_STATUS_EFT_BP, 1, 6, 0x0000 }, + { FLM_STATUS_IDLE, 1, 2, 0x0000 }, + { FLM_STATUS_INITDONE, 1, 1, 0x0000 }, + { FLM_STATUS_PANIC, 1, 4, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_aul_done_fields[] = { + { FLM_STAT_AUL_DONE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_aul_fail_fields[] = { + { FLM_STAT_AUL_FAIL_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_aul_ignore_fields[] = { + { FLM_STAT_AUL_IGNORE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_csh_hit_fields[] = { + { FLM_STAT_CSH_HIT_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_csh_miss_fields[] = { + { FLM_STAT_CSH_MISS_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_csh_unh_fields[] = { + { FLM_STAT_CSH_UNH_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_cuc_move_fields[] = { + { FLM_STAT_CUC_MOVE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_cuc_start_fields[] = { + { FLM_STAT_CUC_START_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_flows_fields[] = { + { FLM_STAT_FLOWS_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_inf_done_fields[] = { + { FLM_STAT_INF_DONE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_inf_skip_fields[] = { + { FLM_STAT_INF_SKIP_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_lrn_done_fields[] = { + { FLM_STAT_LRN_DONE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_lrn_fail_fields[] = { + { FLM_STAT_LRN_FAIL_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_lrn_ignore_fields[] = { + { FLM_STAT_LRN_IGNORE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_pck_dis_fields[] = { + { FLM_STAT_PCK_DIS_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_pck_hit_fields[] = { + { FLM_STAT_PCK_HIT_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_pck_miss_fields[] = { + { FLM_STAT_PCK_MISS_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_pck_unh_fields[] = { + { FLM_STAT_PCK_UNH_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_prb_done_fields[] = { + { FLM_STAT_PRB_DONE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_prb_ignore_fields[] = { + { FLM_STAT_PRB_IGNORE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_rel_done_fields[] = { + { FLM_STAT_REL_DONE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_rel_ignore_fields[] = { + { FLM_STAT_REL_IGNORE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_sta_done_fields[] = { + { FLM_STAT_STA_DONE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_tul_done_fields[] = { + { FLM_STAT_TUL_DONE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_unl_done_fields[] = { + { FLM_STAT_UNL_DONE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_stat_unl_ignore_fields[] = { + { FLM_STAT_UNL_IGNORE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_sta_data_fields[] = { + { FLM_STA_DATA_EOR, 1, 95, 0x0000 }, + { FLM_STA_DATA_ID, 72, 0, 0x0000 }, + { FLM_STA_DATA_LDS, 1, 72, 0x0000 }, + { FLM_STA_DATA_LFS, 1, 73, 0x0000 }, + { FLM_STA_DATA_LIS, 1, 74, 0x0000 }, + { FLM_STA_DATA_PDS, 1, 79, 0x0000 }, + { FLM_STA_DATA_PIS, 1, 80, 0x0000 }, + { FLM_STA_DATA_RDS, 1, 77, 0x0000 }, + { FLM_STA_DATA_RIS, 1, 78, 0x0000 }, + { FLM_STA_DATA_UDS, 1, 75, 0x0000 }, + { FLM_STA_DATA_UIS, 1, 76, 0x0000 }, +}; + +static nt_fpga_field_init_t flm_timeout_fields[] = { + { FLM_TIMEOUT_T, 32, 0, 0 }, +}; + +static nt_fpga_register_init_t flm_registers[] = { + { FLM_BUF_CTRL, 14, 48, REGISTER_TYPE_RW, 0, 3, flm_buf_ctrl_fields }, + { FLM_CONTROL, 0, 28, REGISTER_TYPE_MIXED, 134217728, 17, + flm_control_fields + }, + { FLM_INF_DATA, 16, 288, REGISTER_TYPE_RO, 0, 6, flm_inf_data_fields }, + { FLM_LOAD_APS, 7, 32, REGISTER_TYPE_RO, 0, 1, flm_load_aps_fields }, + { FLM_LOAD_BIN, 4, 30, REGISTER_TYPE_WO, 8388607, 1, + flm_load_bin_fields + }, + { FLM_LOAD_LPS, 6, 32, REGISTER_TYPE_RO, 0, 1, flm_load_lps_fields }, + { FLM_LOAD_PPS, 5, 32, REGISTER_TYPE_RO, 0, 1, flm_load_pps_fields }, + { FLM_LRN_DATA, 15, 768, REGISTER_TYPE_WO, 0, 32, flm_lrn_data_fields }, + { FLM_PRIO, 8, 32, REGISTER_TYPE_WO, 269488144, 8, flm_prio_fields }, + { FLM_PST_CTRL, 10, 32, REGISTER_TYPE_WO, 0, 2, flm_pst_ctrl_fields }, + { FLM_PST_DATA, 11, 15, REGISTER_TYPE_WO, 0, 3, flm_pst_data_fields }, + { FLM_RCP_CTRL, 12, 32, REGISTER_TYPE_WO, 0, 2, flm_rcp_ctrl_fields }, + { FLM_RCP_DATA, 13, 403, REGISTER_TYPE_WO, 0, 19, flm_rcp_data_fields }, + { FLM_SCRUB, 3, 16, REGISTER_TYPE_WO, 0, 1, flm_scrub_fields }, + { FLM_STATUS, 1, 12, REGISTER_TYPE_MIXED, 0, 7, flm_status_fields }, + { FLM_STAT_AUL_DONE, 41, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_aul_done_fields + }, + { FLM_STAT_AUL_FAIL, 43, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_aul_fail_fields + }, + { FLM_STAT_AUL_IGNORE, 42, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_aul_ignore_fields + }, + { FLM_STAT_CSH_HIT, 52, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_csh_hit_fields + }, + { FLM_STAT_CSH_MISS, 53, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_csh_miss_fields + }, + { FLM_STAT_CSH_UNH, 54, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_csh_unh_fields + }, + { FLM_STAT_CUC_MOVE, 57, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_cuc_move_fields + }, + { FLM_STAT_CUC_START, 56, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_cuc_start_fields + }, + { FLM_STAT_FLOWS, 18, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_flows_fields + }, + { FLM_STAT_INF_DONE, 46, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_inf_done_fields + }, + { FLM_STAT_INF_SKIP, 47, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_inf_skip_fields + }, + { FLM_STAT_LRN_DONE, 32, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_lrn_done_fields + }, + { FLM_STAT_LRN_FAIL, 34, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_lrn_fail_fields + }, + { FLM_STAT_LRN_IGNORE, 33, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_lrn_ignore_fields + }, + { FLM_STAT_PCK_DIS, 51, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_pck_dis_fields + }, + { FLM_STAT_PCK_HIT, 48, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_pck_hit_fields + }, + { FLM_STAT_PCK_MISS, 49, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_pck_miss_fields + }, + { FLM_STAT_PCK_UNH, 50, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_pck_unh_fields + }, + { FLM_STAT_PRB_DONE, 39, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_prb_done_fields + }, + { FLM_STAT_PRB_IGNORE, 40, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_prb_ignore_fields + }, + { FLM_STAT_REL_DONE, 37, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_rel_done_fields + }, + { FLM_STAT_REL_IGNORE, 38, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_rel_ignore_fields + }, + { FLM_STAT_STA_DONE, 45, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_sta_done_fields + }, + { FLM_STAT_TUL_DONE, 44, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_tul_done_fields + }, + { FLM_STAT_UNL_DONE, 35, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_unl_done_fields + }, + { FLM_STAT_UNL_IGNORE, 36, 32, REGISTER_TYPE_RO, 0, 1, + flm_stat_unl_ignore_fields + }, + { FLM_STA_DATA, 17, 96, REGISTER_TYPE_RO, 0, 11, flm_sta_data_fields }, + { FLM_TIMEOUT, 2, 32, REGISTER_TYPE_WO, 0, 1, flm_timeout_fields }, +}; + +static nt_fpga_field_init_t gfg_burstsize0_fields[] = { + { GFG_BURSTSIZE0_VAL, 24, 0, 0 }, +}; + +static nt_fpga_field_init_t gfg_burstsize1_fields[] = { + { GFG_BURSTSIZE1_VAL, 24, 0, 0 }, +}; + +static nt_fpga_field_init_t gfg_ctrl0_fields[] = { + { GFG_CTRL0_ENABLE, 1, 0, 0 }, + { GFG_CTRL0_MODE, 3, 1, 0 }, + { GFG_CTRL0_PRBS_EN, 1, 4, 0 }, + { GFG_CTRL0_SIZE, 14, 16, 64 }, +}; + +static nt_fpga_field_init_t gfg_ctrl1_fields[] = { + { GFG_CTRL1_ENABLE, 1, 0, 0 }, + { GFG_CTRL1_MODE, 3, 1, 0 }, + { GFG_CTRL1_PRBS_EN, 1, 4, 0 }, + { GFG_CTRL1_SIZE, 14, 16, 64 }, +}; + +static nt_fpga_field_init_t gfg_run0_fields[] = { + { GFG_RUN0_RUN, 1, 0, 0 }, +}; + +static nt_fpga_field_init_t gfg_run1_fields[] = { + { GFG_RUN1_RUN, 1, 0, 0 }, +}; + +static nt_fpga_field_init_t gfg_sizemask0_fields[] = { + { GFG_SIZEMASK0_VAL, 14, 0, 0 }, +}; + +static nt_fpga_field_init_t gfg_sizemask1_fields[] = { + { GFG_SIZEMASK1_VAL, 14, 0, 0 }, +}; + +static nt_fpga_field_init_t gfg_streamid0_fields[] = { + { GFG_STREAMID0_VAL, 8, 0, 0 }, +}; + +static nt_fpga_field_init_t gfg_streamid1_fields[] = { + { GFG_STREAMID1_VAL, 8, 0, 1 }, +}; + +static nt_fpga_register_init_t gfg_registers[] = { + { GFG_BURSTSIZE0, 3, 24, REGISTER_TYPE_WO, 0, 1, + gfg_burstsize0_fields + }, + { GFG_BURSTSIZE1, 8, 24, REGISTER_TYPE_WO, 0, 1, + gfg_burstsize1_fields + }, + { GFG_CTRL0, 0, 30, REGISTER_TYPE_WO, 4194304, 4, gfg_ctrl0_fields }, + { GFG_CTRL1, 5, 30, REGISTER_TYPE_WO, 4194304, 4, gfg_ctrl1_fields }, + { GFG_RUN0, 1, 1, REGISTER_TYPE_WO, 0, 1, gfg_run0_fields }, + { GFG_RUN1, 6, 1, REGISTER_TYPE_WO, 0, 1, gfg_run1_fields }, + { GFG_SIZEMASK0, 4, 14, REGISTER_TYPE_WO, 0, 1, gfg_sizemask0_fields }, + { GFG_SIZEMASK1, 9, 14, REGISTER_TYPE_WO, 0, 1, gfg_sizemask1_fields }, + { GFG_STREAMID0, 2, 8, REGISTER_TYPE_WO, 0, 1, gfg_streamid0_fields }, + { GFG_STREAMID1, 7, 8, REGISTER_TYPE_WO, 1, 1, gfg_streamid1_fields }, +}; + +static nt_fpga_field_init_t gmf_ctrl_fields[] = { + { GMF_CTRL_ENABLE, 1, 0, 0 }, + { GMF_CTRL_FCS_ALWAYS, 1, 1, 0 }, + { GMF_CTRL_IFG_AUTO_ADJUST_ENABLE, 1, 7, 0 }, + { GMF_CTRL_IFG_ENABLE, 1, 2, 0 }, + { GMF_CTRL_IFG_TX_NOW_ALWAYS, 1, 3, 0 }, + { GMF_CTRL_IFG_TX_NOW_ON_TS_ENABLE, 1, 5, 0 }, + { GMF_CTRL_IFG_TX_ON_TS_ADJUST_ON_SET_CLOCK, 1, 6, 0 }, + { GMF_CTRL_IFG_TX_ON_TS_ALWAYS, 1, 4, 0 }, + { GMF_CTRL_TS_INJECT_ALWAYS, 1, 8, 0 }, + { GMF_CTRL_TS_INJECT_DUAL_STEP, 1, 9, 0 }, +}; + +static nt_fpga_field_init_t gmf_debug_lane_marker_fields[] = { + { GMF_DEBUG_LANE_MARKER_COMPENSATION, 16, 0, 16384 }, +}; + +static nt_fpga_field_init_t gmf_ifg_max_adjust_slack_fields[] = { + { GMF_IFG_MAX_ADJUST_SLACK_SLACK, 64, 0, 0 }, +}; + +static nt_fpga_field_init_t gmf_ifg_set_clock_delta_fields[] = { + { GMF_IFG_SET_CLOCK_DELTA_DELTA, 64, 0, 0 }, +}; + +static nt_fpga_field_init_t gmf_ifg_set_clock_delta_adjust_fields[] = { + { GMF_IFG_SET_CLOCK_DELTA_ADJUST_DELTA, 64, 0, 0 }, +}; + +static nt_fpga_field_init_t gmf_ifg_tx_now_on_ts_fields[] = { + { GMF_IFG_TX_NOW_ON_TS_TS, 64, 0, 0 }, +}; + +static nt_fpga_field_init_t gmf_speed_fields[] = { + { GMF_SPEED_IFG_SPEED, 64, 0, 0 }, +}; + +static nt_fpga_field_init_t gmf_stat_data_buffer_fields[] = { + { GMF_STAT_DATA_BUFFER_USED, 15, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t gmf_stat_max_delayed_pkt_fields[] = { + { GMF_STAT_MAX_DELAYED_PKT_NS, 64, 0, 0 }, +}; + +static nt_fpga_field_init_t gmf_stat_next_pkt_fields[] = { + { GMF_STAT_NEXT_PKT_NS, 64, 0, 0 }, +}; + +static nt_fpga_field_init_t gmf_stat_sticky_fields[] = { + { GMF_STAT_STICKY_DATA_UNDERFLOWED, 1, 0, 0 }, + { GMF_STAT_STICKY_IFG_ADJUSTED, 1, 1, 0 }, +}; + +static nt_fpga_field_init_t gmf_ts_inject_fields[] = { + { GMF_TS_INJECT_OFFSET, 14, 0, 0 }, + { GMF_TS_INJECT_POS, 2, 14, 0 }, +}; + +static nt_fpga_register_init_t gmf_registers[] = { + { GMF_CTRL, 0, 10, REGISTER_TYPE_WO, 0, 10, gmf_ctrl_fields }, + { GMF_DEBUG_LANE_MARKER, 7, 16, REGISTER_TYPE_WO, 16384, 1, + gmf_debug_lane_marker_fields + }, + { GMF_IFG_MAX_ADJUST_SLACK, 4, 64, REGISTER_TYPE_WO, 0, 1, + gmf_ifg_max_adjust_slack_fields + }, + { GMF_IFG_SET_CLOCK_DELTA, 2, 64, REGISTER_TYPE_WO, 0, 1, + gmf_ifg_set_clock_delta_fields + }, + { GMF_IFG_SET_CLOCK_DELTA_ADJUST, 3, 64, REGISTER_TYPE_WO, 0, 1, + gmf_ifg_set_clock_delta_adjust_fields + }, + { GMF_IFG_TX_NOW_ON_TS, 5, 64, REGISTER_TYPE_WO, 0, 1, + gmf_ifg_tx_now_on_ts_fields + }, + { GMF_SPEED, 1, 64, REGISTER_TYPE_WO, 0, 1, gmf_speed_fields }, + { GMF_STAT_DATA_BUFFER, 9, 15, REGISTER_TYPE_RO, 0, 1, + gmf_stat_data_buffer_fields + }, + { GMF_STAT_MAX_DELAYED_PKT, 11, 64, REGISTER_TYPE_RC1, 0, 1, + gmf_stat_max_delayed_pkt_fields + }, + { GMF_STAT_NEXT_PKT, 10, 64, REGISTER_TYPE_RO, 0, 1, + gmf_stat_next_pkt_fields + }, + { GMF_STAT_STICKY, 8, 2, REGISTER_TYPE_RC1, 0, 2, + gmf_stat_sticky_fields + }, + { GMF_TS_INJECT, 6, 16, REGISTER_TYPE_WO, 0, 2, gmf_ts_inject_fields }, +}; + +static nt_fpga_field_init_t gpio_phy_cfg_fields[] = { + { GPIO_PHY_CFG_E_PORT0_RXLOS, 1, 8, 0 }, + { GPIO_PHY_CFG_E_PORT1_RXLOS, 1, 9, 0 }, + { GPIO_PHY_CFG_PORT0_INT_B, 1, 1, 1 }, + { GPIO_PHY_CFG_PORT0_LPMODE, 1, 0, 0 }, + { GPIO_PHY_CFG_PORT0_MODPRS_B, 1, 3, 1 }, + { GPIO_PHY_CFG_PORT0_RESET_B, 1, 2, 0 }, + { GPIO_PHY_CFG_PORT1_INT_B, 1, 5, 1 }, + { GPIO_PHY_CFG_PORT1_LPMODE, 1, 4, 0 }, + { GPIO_PHY_CFG_PORT1_MODPRS_B, 1, 7, 1 }, + { GPIO_PHY_CFG_PORT1_RESET_B, 1, 6, 0 }, +}; + +static nt_fpga_field_init_t gpio_phy_gpio_fields[] = { + { GPIO_PHY_GPIO_E_PORT0_RXLOS, 1, 8, 0 }, + { GPIO_PHY_GPIO_E_PORT1_RXLOS, 1, 9, 0 }, + { GPIO_PHY_GPIO_PORT0_INT_B, 1, 1, 0x0000 }, + { GPIO_PHY_GPIO_PORT0_LPMODE, 1, 0, 1 }, + { GPIO_PHY_GPIO_PORT0_MODPRS_B, 1, 3, 0x0000 }, + { GPIO_PHY_GPIO_PORT0_RESET_B, 1, 2, 0 }, + { GPIO_PHY_GPIO_PORT1_INT_B, 1, 5, 0x0000 }, + { GPIO_PHY_GPIO_PORT1_LPMODE, 1, 4, 1 }, + { GPIO_PHY_GPIO_PORT1_MODPRS_B, 1, 7, 0x0000 }, + { GPIO_PHY_GPIO_PORT1_RESET_B, 1, 6, 0 }, +}; + +static nt_fpga_register_init_t gpio_phy_registers[] = { + { GPIO_PHY_CFG, 0, 10, REGISTER_TYPE_RW, 170, 10, gpio_phy_cfg_fields }, + { GPIO_PHY_GPIO, 1, 10, REGISTER_TYPE_RW, 17, 10, + gpio_phy_gpio_fields + }, +}; + +static nt_fpga_field_init_t hfu_rcp_ctrl_fields[] = { + { HFU_RCP_CTRL_ADR, 6, 0, 0x0000 }, + { HFU_RCP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t hfu_rcp_data_fields[] = { + { HFU_RCP_DATA_CSINF, 1, 111, 0x0000 }, + { HFU_RCP_DATA_IL3OFS, 8, 139, 0x0000 }, + { HFU_RCP_DATA_IL4OFS, 8, 147, 0x0000 }, + { HFU_RCP_DATA_L3FRAG, 2, 114, 0x0000 }, + { HFU_RCP_DATA_L3PRT, 2, 112, 0x0000 }, + { HFU_RCP_DATA_L4PRT, 3, 120, 0x0000 }, + { HFU_RCP_DATA_LEN_A_ADD_DYN, 5, 15, 0x0000 }, + { HFU_RCP_DATA_LEN_A_ADD_OFS, 8, 20, 0x0000 }, + { HFU_RCP_DATA_LEN_A_OL4LEN, 1, 1, 0x0000 }, + { HFU_RCP_DATA_LEN_A_POS_DYN, 5, 2, 0x0000 }, + { HFU_RCP_DATA_LEN_A_POS_OFS, 8, 7, 0x0000 }, + { HFU_RCP_DATA_LEN_A_SUB_DYN, 5, 28, 0x0000 }, + { HFU_RCP_DATA_LEN_A_WR, 1, 0, 0x0000 }, + { HFU_RCP_DATA_LEN_B_ADD_DYN, 5, 47, 0x0000 }, + { HFU_RCP_DATA_LEN_B_ADD_OFS, 8, 52, 0x0000 }, + { HFU_RCP_DATA_LEN_B_POS_DYN, 5, 34, 0x0000 }, + { HFU_RCP_DATA_LEN_B_POS_OFS, 8, 39, 0x0000 }, + { HFU_RCP_DATA_LEN_B_SUB_DYN, 5, 60, 0x0000 }, + { HFU_RCP_DATA_LEN_B_WR, 1, 33, 0x0000 }, + { HFU_RCP_DATA_LEN_C_ADD_DYN, 5, 79, 0x0000 }, + { HFU_RCP_DATA_LEN_C_ADD_OFS, 8, 84, 0x0000 }, + { HFU_RCP_DATA_LEN_C_POS_DYN, 5, 66, 0x0000 }, + { HFU_RCP_DATA_LEN_C_POS_OFS, 8, 71, 0x0000 }, + { HFU_RCP_DATA_LEN_C_SUB_DYN, 5, 92, 0x0000 }, + { HFU_RCP_DATA_LEN_C_WR, 1, 65, 0x0000 }, + { HFU_RCP_DATA_OL3OFS, 8, 123, 0x0000 }, + { HFU_RCP_DATA_OL4OFS, 8, 131, 0x0000 }, + { HFU_RCP_DATA_TTL_POS_DYN, 5, 98, 0x0000 }, + { HFU_RCP_DATA_TTL_POS_OFS, 8, 103, 0x0000 }, + { HFU_RCP_DATA_TTL_WR, 1, 97, 0x0000 }, + { HFU_RCP_DATA_TUNNEL, 4, 116, 0x0000 }, +}; + +static nt_fpga_register_init_t hfu_registers[] = { + { HFU_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, hfu_rcp_ctrl_fields }, + { HFU_RCP_DATA, 1, 155, REGISTER_TYPE_WO, 0, 31, hfu_rcp_data_fields }, +}; + +static nt_fpga_field_init_t hif_build_time_fields[] = { + { HIF_BUILD_TIME_TIME, 32, 0, 1689706895 }, +}; + +static nt_fpga_field_init_t hif_config_fields[] = { + { HIF_CONFIG_EXT_TAG, 1, 6, 0x0000 }, + { HIF_CONFIG_MAX_READ, 3, 3, 0x0000 }, + { HIF_CONFIG_MAX_TLP, 3, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t hif_control_fields[] = { + { HIF_CONTROL_BLESSED, 8, 4, 0 }, + { HIF_CONTROL_WRAW, 4, 0, 1 }, +}; + +static nt_fpga_field_init_t hif_prod_id_ex_fields[] = { + { HIF_PROD_ID_EX_LAYOUT, 1, 31, 0 }, + { HIF_PROD_ID_EX_LAYOUT_VERSION, 8, 0, 1 }, + { HIF_PROD_ID_EX_RESERVED, 23, 8, 0 }, +}; + +static nt_fpga_field_init_t hif_prod_id_lsb_fields[] = { + { HIF_PROD_ID_LSB_GROUP_ID, 16, 16, 9563 }, + { HIF_PROD_ID_LSB_REV_ID, 8, 0, 24 }, + { HIF_PROD_ID_LSB_VER_ID, 8, 8, 55 }, +}; + +static nt_fpga_field_init_t hif_prod_id_msb_fields[] = { + { HIF_PROD_ID_MSB_BUILD_NO, 10, 12, 0 }, + { HIF_PROD_ID_MSB_TYPE_ID, 12, 0, 200 }, +}; + +static nt_fpga_field_init_t hif_sample_time_fields[] = { + { HIF_SAMPLE_TIME_SAMPLE_TIME, 1, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t hif_status_fields[] = { + { HIF_STATUS_RD_ERR, 1, 9, 0 }, + { HIF_STATUS_TAGS_IN_USE, 8, 0, 0 }, + { HIF_STATUS_WR_ERR, 1, 8, 0 }, +}; + +static nt_fpga_field_init_t hif_stat_ctrl_fields[] = { + { HIF_STAT_CTRL_STAT_ENA, 1, 1, 0 }, + { HIF_STAT_CTRL_STAT_REQ, 1, 0, 0 }, +}; + +static nt_fpga_field_init_t hif_stat_refclk_fields[] = { + { HIF_STAT_REFCLK_REFCLK250, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t hif_stat_rx_fields[] = { + { HIF_STAT_RX_COUNTER, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t hif_stat_tx_fields[] = { + { HIF_STAT_TX_COUNTER, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t hif_test0_fields[] = { + { HIF_TEST0_DATA, 32, 0, 287454020 }, +}; + +static nt_fpga_field_init_t hif_test1_fields[] = { + { HIF_TEST1_DATA, 32, 0, 2864434397 }, +}; + +static nt_fpga_field_init_t hif_uuid0_fields[] = { + { HIF_UUID0_UUID0, 32, 0, 456073826 }, +}; + +static nt_fpga_field_init_t hif_uuid1_fields[] = { + { HIF_UUID1_UUID1, 32, 0, 3051597623 }, +}; + +static nt_fpga_field_init_t hif_uuid2_fields[] = { + { HIF_UUID2_UUID2, 32, 0, 3265543206 }, +}; + +static nt_fpga_field_init_t hif_uuid3_fields[] = { + { HIF_UUID3_UUID3, 32, 0, 599637710 }, +}; + +static nt_fpga_register_init_t hif_registers[] = { + { HIF_BUILD_TIME, 16, 32, REGISTER_TYPE_RO, 1689706895, 1, + hif_build_time_fields + }, + { HIF_CONFIG, 24, 7, REGISTER_TYPE_RW, 0, 3, hif_config_fields }, + { HIF_CONTROL, 40, 12, REGISTER_TYPE_RW, 1, 2, hif_control_fields }, + { HIF_PROD_ID_EX, 112, 32, REGISTER_TYPE_RO, 1, 3, + hif_prod_id_ex_fields + }, + { HIF_PROD_ID_LSB, 0, 32, REGISTER_TYPE_RO, 626734872, 3, + hif_prod_id_lsb_fields + }, + { HIF_PROD_ID_MSB, 8, 22, REGISTER_TYPE_RO, 200, 2, + hif_prod_id_msb_fields + }, + { HIF_SAMPLE_TIME, 96, 1, REGISTER_TYPE_WO, 0, 1, + hif_sample_time_fields + }, + { HIF_STATUS, 32, 10, REGISTER_TYPE_MIXED, 0, 3, hif_status_fields }, + { HIF_STAT_CTRL, 64, 2, REGISTER_TYPE_WO, 0, 2, hif_stat_ctrl_fields }, + { HIF_STAT_REFCLK, 72, 32, REGISTER_TYPE_RO, 0, 1, + hif_stat_refclk_fields + }, + { HIF_STAT_RX, 88, 32, REGISTER_TYPE_RO, 0, 1, hif_stat_rx_fields }, + { HIF_STAT_TX, 80, 32, REGISTER_TYPE_RO, 0, 1, hif_stat_tx_fields }, + { HIF_TEST0, 48, 32, REGISTER_TYPE_RW, 287454020, 1, hif_test0_fields }, + { HIF_TEST1, 56, 32, REGISTER_TYPE_RW, 2864434397, 1, + hif_test1_fields + }, + { HIF_UUID0, 128, 32, REGISTER_TYPE_RO, 456073826, 1, + hif_uuid0_fields + }, + { HIF_UUID1, 144, 32, REGISTER_TYPE_RO, 3051597623, 1, + hif_uuid1_fields + }, + { HIF_UUID2, 160, 32, REGISTER_TYPE_RO, 3265543206, 1, + hif_uuid2_fields + }, + { HIF_UUID3, 176, 32, REGISTER_TYPE_RO, 599637710, 1, + hif_uuid3_fields + }, +}; + +static nt_fpga_field_init_t hsh_rcp_ctrl_fields[] = { + { HSH_RCP_CTRL_ADR, 4, 0, 0x0000 }, + { HSH_RCP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t hsh_rcp_data_fields[] = { + { HSH_RCP_DATA_AUTO_IPV4_MASK, 1, 742, 0x0000 }, + { HSH_RCP_DATA_HSH_TYPE, 5, 416, 0x0000 }, + { HSH_RCP_DATA_HSH_VALID, 1, 415, 0x0000 }, + { HSH_RCP_DATA_K, 320, 422, 0x0000 }, + { HSH_RCP_DATA_LOAD_DIST_TYPE, 2, 0, 0x0000 }, + { HSH_RCP_DATA_MAC_PORT_MASK, 2, 2, 0x0000 }, + { HSH_RCP_DATA_P_MASK, 1, 61, 0x0000 }, + { HSH_RCP_DATA_QW0_OFS, 8, 11, 0x0000 }, + { HSH_RCP_DATA_QW0_PE, 5, 6, 0x0000 }, + { HSH_RCP_DATA_QW4_OFS, 8, 24, 0x0000 }, + { HSH_RCP_DATA_QW4_PE, 5, 19, 0x0000 }, + { HSH_RCP_DATA_SEED, 32, 382, 0x0000 }, + { HSH_RCP_DATA_SORT, 2, 4, 0x0000 }, + { HSH_RCP_DATA_TNL_P, 1, 414, 0x0000 }, + { HSH_RCP_DATA_TOEPLITZ, 1, 421, 0x0000 }, + { HSH_RCP_DATA_W8_OFS, 8, 37, 0x0000 }, + { HSH_RCP_DATA_W8_PE, 5, 32, 0x0000 }, + { HSH_RCP_DATA_W8_SORT, 1, 45, 0x0000 }, + { HSH_RCP_DATA_W9_OFS, 8, 51, 0x0000 }, + { HSH_RCP_DATA_W9_P, 1, 60, 0x0000 }, + { HSH_RCP_DATA_W9_PE, 5, 46, 0x0000 }, + { HSH_RCP_DATA_W9_SORT, 1, 59, 0x0000 }, + { HSH_RCP_DATA_WORD_MASK, 320, 62, 0x0000 }, +}; + +static nt_fpga_register_init_t hsh_registers[] = { + { HSH_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, hsh_rcp_ctrl_fields }, + { HSH_RCP_DATA, 1, 743, REGISTER_TYPE_WO, 0, 23, hsh_rcp_data_fields }, +}; + +static nt_fpga_field_init_t hst_rcp_ctrl_fields[] = { + { HST_RCP_CTRL_ADR, 5, 0, 0x0000 }, + { HST_RCP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t hst_rcp_data_fields[] = { + { HST_RCP_DATA_END_DYN, 5, 16, 0x0000 }, + { HST_RCP_DATA_END_OFS, 10, 21, 0x0000 }, + { HST_RCP_DATA_MODIF0_CMD, 3, 31, 0x0000 }, + { HST_RCP_DATA_MODIF0_DYN, 5, 34, 0x0000 }, + { HST_RCP_DATA_MODIF0_OFS, 10, 39, 0x0000 }, + { HST_RCP_DATA_MODIF0_VALUE, 16, 49, 0x0000 }, + { HST_RCP_DATA_MODIF1_CMD, 3, 65, 0x0000 }, + { HST_RCP_DATA_MODIF1_DYN, 5, 68, 0x0000 }, + { HST_RCP_DATA_MODIF1_OFS, 10, 73, 0x0000 }, + { HST_RCP_DATA_MODIF1_VALUE, 16, 83, 0x0000 }, + { HST_RCP_DATA_MODIF2_CMD, 3, 99, 0x0000 }, + { HST_RCP_DATA_MODIF2_DYN, 5, 102, 0x0000 }, + { HST_RCP_DATA_MODIF2_OFS, 10, 107, 0x0000 }, + { HST_RCP_DATA_MODIF2_VALUE, 16, 117, 0x0000 }, + { HST_RCP_DATA_START_DYN, 5, 1, 0x0000 }, + { HST_RCP_DATA_START_OFS, 10, 6, 0x0000 }, + { HST_RCP_DATA_STRIP_MODE, 1, 0, 0x0000 }, +}; + +static nt_fpga_register_init_t hst_registers[] = { + { HST_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, hst_rcp_ctrl_fields }, + { HST_RCP_DATA, 1, 133, REGISTER_TYPE_WO, 0, 17, hst_rcp_data_fields }, +}; + +static nt_fpga_field_init_t ifr_rcp_ctrl_fields[] = { + { IFR_RCP_CTRL_ADR, 4, 0, 0x0000 }, + { IFR_RCP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t ifr_rcp_data_fields[] = { + { IFR_RCP_DATA_EN, 1, 0, 0x0000 }, + { IFR_RCP_DATA_MTU, 14, 1, 0x0000 }, +}; + +static nt_fpga_register_init_t ifr_registers[] = { + { IFR_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, ifr_rcp_ctrl_fields }, + { IFR_RCP_DATA, 1, 15, REGISTER_TYPE_WO, 0, 2, ifr_rcp_data_fields }, +}; + +static nt_fpga_field_init_t iic_adr_fields[] = { + { IIC_ADR_SLV_ADR, 7, 1, 0 }, +}; + +static nt_fpga_field_init_t iic_cr_fields[] = { + { IIC_CR_EN, 1, 0, 0 }, { IIC_CR_GC_EN, 1, 6, 0 }, + { IIC_CR_MSMS, 1, 2, 0 }, { IIC_CR_RST, 1, 7, 0 }, + { IIC_CR_RSTA, 1, 5, 0 }, { IIC_CR_TX, 1, 3, 0 }, + { IIC_CR_TXAK, 1, 4, 0 }, { IIC_CR_TXFIFO_RESET, 1, 1, 0 }, +}; + +static nt_fpga_field_init_t iic_dgie_fields[] = { + { IIC_DGIE_GIE, 1, 31, 0 }, +}; + +static nt_fpga_field_init_t iic_gpo_fields[] = { + { IIC_GPO_GPO_VAL, 1, 0, 0 }, +}; + +static nt_fpga_field_init_t iic_ier_fields[] = { + { IIC_IER_INT0, 1, 0, 0 }, { IIC_IER_INT1, 1, 1, 0 }, + { IIC_IER_INT2, 1, 2, 0 }, { IIC_IER_INT3, 1, 3, 0 }, + { IIC_IER_INT4, 1, 4, 0 }, { IIC_IER_INT5, 1, 5, 0 }, + { IIC_IER_INT6, 1, 6, 0 }, { IIC_IER_INT7, 1, 7, 0 }, +}; + +static nt_fpga_field_init_t iic_isr_fields[] = { + { IIC_ISR_INT0, 1, 0, 0 }, { IIC_ISR_INT1, 1, 1, 0 }, + { IIC_ISR_INT2, 1, 2, 0 }, { IIC_ISR_INT3, 1, 3, 0 }, + { IIC_ISR_INT4, 1, 4, 0 }, { IIC_ISR_INT5, 1, 5, 0 }, + { IIC_ISR_INT6, 1, 6, 0 }, { IIC_ISR_INT7, 1, 7, 0 }, +}; + +static nt_fpga_field_init_t iic_rx_fifo_fields[] = { + { IIC_RX_FIFO_RXDATA, 8, 0, 0 }, +}; + +static nt_fpga_field_init_t iic_rx_fifo_ocy_fields[] = { + { IIC_RX_FIFO_OCY_OCY_VAL, 4, 0, 0 }, +}; + +static nt_fpga_field_init_t iic_rx_fifo_pirq_fields[] = { + { IIC_RX_FIFO_PIRQ_CMP_VAL, 4, 0, 0 }, +}; + +static nt_fpga_field_init_t iic_softr_fields[] = { + { IIC_SOFTR_RKEY, 4, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t iic_sr_fields[] = { + { IIC_SR_AAS, 1, 1, 0 }, { IIC_SR_ABGC, 1, 0, 0 }, + { IIC_SR_BB, 1, 2, 0 }, { IIC_SR_RXFIFO_EMPTY, 1, 6, 1 }, + { IIC_SR_RXFIFO_FULL, 1, 5, 0 }, { IIC_SR_SRW, 1, 3, 0 }, + { IIC_SR_TXFIFO_EMPTY, 1, 7, 1 }, { IIC_SR_TXFIFO_FULL, 1, 4, 0 }, +}; + +static nt_fpga_field_init_t iic_tbuf_fields[] = { + { IIC_TBUF_TBUF_VAL, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t iic_ten_adr_fields[] = { + { IIC_TEN_ADR_MSB_SLV_ADR, 3, 0, 0 }, +}; + +static nt_fpga_field_init_t iic_thddat_fields[] = { + { IIC_THDDAT_THDDAT_VAL, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t iic_thdsta_fields[] = { + { IIC_THDSTA_THDSTA_VAL, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t iic_thigh_fields[] = { + { IIC_THIGH_THIGH_VAL, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t iic_tlow_fields[] = { + { IIC_TLOW_TLOW_VAL, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t iic_tsudat_fields[] = { + { IIC_TSUDAT_TSUDAT_VAL, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t iic_tsusta_fields[] = { + { IIC_TSUSTA_TSUSTA_VAL, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t iic_tsusto_fields[] = { + { IIC_TSUSTO_TSUSTO_VAL, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t iic_tx_fifo_fields[] = { + { IIC_TX_FIFO_START, 1, 8, 0 }, + { IIC_TX_FIFO_STOP, 1, 9, 0 }, + { IIC_TX_FIFO_TXDATA, 8, 0, 0 }, +}; + +static nt_fpga_field_init_t iic_tx_fifo_ocy_fields[] = { + { IIC_TX_FIFO_OCY_OCY_VAL, 4, 0, 0 }, +}; + +static nt_fpga_register_init_t iic_registers[] = { + { IIC_ADR, 68, 8, REGISTER_TYPE_RW, 0, 1, iic_adr_fields }, + { IIC_CR, 64, 8, REGISTER_TYPE_RW, 0, 8, iic_cr_fields }, + { IIC_DGIE, 7, 32, REGISTER_TYPE_RW, 0, 1, iic_dgie_fields }, + { IIC_GPO, 73, 1, REGISTER_TYPE_RW, 0, 1, iic_gpo_fields }, + { IIC_IER, 10, 8, REGISTER_TYPE_RW, 0, 8, iic_ier_fields }, + { IIC_ISR, 8, 8, REGISTER_TYPE_RW, 0, 8, iic_isr_fields }, + { IIC_RX_FIFO, 67, 8, REGISTER_TYPE_RO, 0, 1, iic_rx_fifo_fields }, + { IIC_RX_FIFO_OCY, 70, 4, REGISTER_TYPE_RO, 0, 1, + iic_rx_fifo_ocy_fields + }, + { IIC_RX_FIFO_PIRQ, 72, 4, REGISTER_TYPE_RW, 0, 1, + iic_rx_fifo_pirq_fields + }, + { IIC_SOFTR, 16, 4, REGISTER_TYPE_WO, 0, 1, iic_softr_fields }, + { IIC_SR, 65, 8, REGISTER_TYPE_RO, 192, 8, iic_sr_fields }, + { IIC_TBUF, 78, 32, REGISTER_TYPE_RW, 0, 1, iic_tbuf_fields }, + { IIC_TEN_ADR, 71, 3, REGISTER_TYPE_RO, 0, 1, iic_ten_adr_fields }, + { IIC_THDDAT, 81, 32, REGISTER_TYPE_RW, 0, 1, iic_thddat_fields }, + { IIC_THDSTA, 76, 32, REGISTER_TYPE_RW, 0, 1, iic_thdsta_fields }, + { IIC_THIGH, 79, 32, REGISTER_TYPE_RW, 0, 1, iic_thigh_fields }, + { IIC_TLOW, 80, 32, REGISTER_TYPE_RW, 0, 1, iic_tlow_fields }, + { IIC_TSUDAT, 77, 32, REGISTER_TYPE_RW, 0, 1, iic_tsudat_fields }, + { IIC_TSUSTA, 74, 32, REGISTER_TYPE_RW, 0, 1, iic_tsusta_fields }, + { IIC_TSUSTO, 75, 32, REGISTER_TYPE_RW, 0, 1, iic_tsusto_fields }, + { IIC_TX_FIFO, 66, 10, REGISTER_TYPE_WO, 0, 3, iic_tx_fifo_fields }, + { IIC_TX_FIFO_OCY, 69, 4, REGISTER_TYPE_RO, 0, 1, + iic_tx_fifo_ocy_fields + }, +}; + +static nt_fpga_field_init_t ins_rcp_ctrl_fields[] = { + { INS_RCP_CTRL_ADR, 4, 0, 0x0000 }, + { INS_RCP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t ins_rcp_data_fields[] = { + { INS_RCP_DATA_DYN, 5, 0, 0x0000 }, + { INS_RCP_DATA_LEN, 8, 15, 0x0000 }, + { INS_RCP_DATA_OFS, 10, 5, 0x0000 }, +}; + +static nt_fpga_register_init_t ins_registers[] = { + { INS_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, ins_rcp_ctrl_fields }, + { INS_RCP_DATA, 1, 23, REGISTER_TYPE_WO, 0, 3, ins_rcp_data_fields }, +}; + +static nt_fpga_field_init_t km_cam_ctrl_fields[] = { + { KM_CAM_CTRL_ADR, 13, 0, 0x0000 }, + { KM_CAM_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t km_cam_data_fields[] = { + { KM_CAM_DATA_FT0, 4, 192, 0x0000 }, + { KM_CAM_DATA_FT1, 4, 196, 0x0000 }, + { KM_CAM_DATA_FT2, 4, 200, 0x0000 }, + { KM_CAM_DATA_FT3, 4, 204, 0x0000 }, + { KM_CAM_DATA_FT4, 4, 208, 0x0000 }, + { KM_CAM_DATA_FT5, 4, 212, 0x0000 }, + { KM_CAM_DATA_W0, 32, 0, 0x0000 }, + { KM_CAM_DATA_W1, 32, 32, 0x0000 }, + { KM_CAM_DATA_W2, 32, 64, 0x0000 }, + { KM_CAM_DATA_W3, 32, 96, 0x0000 }, + { KM_CAM_DATA_W4, 32, 128, 0x0000 }, + { KM_CAM_DATA_W5, 32, 160, 0x0000 }, +}; + +static nt_fpga_field_init_t km_rcp_ctrl_fields[] = { + { KM_RCP_CTRL_ADR, 5, 0, 0x0000 }, + { KM_RCP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t km_rcp_data_fields[] = { + { KM_RCP_DATA_BANK_A, 12, 694, 0x0000 }, + { KM_RCP_DATA_BANK_B, 12, 706, 0x0000 }, + { KM_RCP_DATA_DUAL, 1, 651, 0x0000 }, + { KM_RCP_DATA_DW0_B_DYN, 5, 729, 0x0000 }, + { KM_RCP_DATA_DW0_B_OFS, 8, 734, 0x0000 }, + { KM_RCP_DATA_DW10_DYN, 5, 55, 0x0000 }, + { KM_RCP_DATA_DW10_OFS, 8, 60, 0x0000 }, + { KM_RCP_DATA_DW10_SEL_A, 2, 68, 0x0000 }, + { KM_RCP_DATA_DW10_SEL_B, 2, 70, 0x0000 }, + { KM_RCP_DATA_DW2_B_DYN, 5, 742, 0x0000 }, + { KM_RCP_DATA_DW2_B_OFS, 8, 747, 0x0000 }, + { KM_RCP_DATA_DW8_DYN, 5, 36, 0x0000 }, + { KM_RCP_DATA_DW8_OFS, 8, 41, 0x0000 }, + { KM_RCP_DATA_DW8_SEL_A, 3, 49, 0x0000 }, + { KM_RCP_DATA_DW8_SEL_B, 3, 52, 0x0000 }, + { KM_RCP_DATA_EL_A, 4, 653, 0x0000 }, + { KM_RCP_DATA_EL_B, 3, 657, 0x0000 }, + { KM_RCP_DATA_FTM_A, 16, 662, 0x0000 }, + { KM_RCP_DATA_FTM_B, 16, 678, 0x0000 }, + { KM_RCP_DATA_INFO_A, 1, 660, 0x0000 }, + { KM_RCP_DATA_INFO_B, 1, 661, 0x0000 }, + { KM_RCP_DATA_KEYWAY_A, 1, 725, 0x0000 }, + { KM_RCP_DATA_KEYWAY_B, 1, 726, 0x0000 }, + { KM_RCP_DATA_KL_A, 4, 718, 0x0000 }, + { KM_RCP_DATA_KL_B, 3, 722, 0x0000 }, + { KM_RCP_DATA_MASK_A, 384, 75, 0x0000 }, + { KM_RCP_DATA_MASK_B, 192, 459, 0x0000 }, + { KM_RCP_DATA_PAIRED, 1, 652, 0x0000 }, + { KM_RCP_DATA_QW0_DYN, 5, 0, 0x0000 }, + { KM_RCP_DATA_QW0_OFS, 8, 5, 0x0000 }, + { KM_RCP_DATA_QW0_SEL_A, 3, 13, 0x0000 }, + { KM_RCP_DATA_QW0_SEL_B, 3, 16, 0x0000 }, + { KM_RCP_DATA_QW4_DYN, 5, 19, 0x0000 }, + { KM_RCP_DATA_QW4_OFS, 8, 24, 0x0000 }, + { KM_RCP_DATA_QW4_SEL_A, 2, 32, 0x0000 }, + { KM_RCP_DATA_QW4_SEL_B, 2, 34, 0x0000 }, + { KM_RCP_DATA_SW4_B_DYN, 5, 755, 0x0000 }, + { KM_RCP_DATA_SW4_B_OFS, 8, 760, 0x0000 }, + { KM_RCP_DATA_SW5_B_DYN, 5, 768, 0x0000 }, + { KM_RCP_DATA_SW5_B_OFS, 8, 773, 0x0000 }, + { KM_RCP_DATA_SWX_CCH, 1, 72, 0x0000 }, + { KM_RCP_DATA_SWX_SEL_A, 1, 73, 0x0000 }, + { KM_RCP_DATA_SWX_SEL_B, 1, 74, 0x0000 }, + { KM_RCP_DATA_SYNERGY_MODE, 2, 727, 0x0000 }, +}; + +static nt_fpga_field_init_t km_status_fields[] = { + { KM_STATUS_TCQ_RDY, 1, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t km_tcam_ctrl_fields[] = { + { KM_TCAM_CTRL_ADR, 14, 0, 0x0000 }, + { KM_TCAM_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t km_tcam_data_fields[] = { + { KM_TCAM_DATA_T, 72, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t km_tci_ctrl_fields[] = { + { KM_TCI_CTRL_ADR, 10, 0, 0x0000 }, + { KM_TCI_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t km_tci_data_fields[] = { + { KM_TCI_DATA_COLOR, 32, 0, 0x0000 }, + { KM_TCI_DATA_FT, 4, 32, 0x0000 }, +}; + +static nt_fpga_field_init_t km_tcq_ctrl_fields[] = { + { KM_TCQ_CTRL_ADR, 7, 0, 0x0000 }, + { KM_TCQ_CTRL_CNT, 5, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t km_tcq_data_fields[] = { + { KM_TCQ_DATA_BANK_MASK, 12, 0, 0x0000 }, + { KM_TCQ_DATA_QUAL, 3, 12, 0x0000 }, +}; + +static nt_fpga_register_init_t km_registers[] = { + { KM_CAM_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2, km_cam_ctrl_fields }, + { KM_CAM_DATA, 3, 216, REGISTER_TYPE_WO, 0, 12, km_cam_data_fields }, + { KM_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, km_rcp_ctrl_fields }, + { KM_RCP_DATA, 1, 781, REGISTER_TYPE_WO, 0, 44, km_rcp_data_fields }, + { KM_STATUS, 10, 1, REGISTER_TYPE_RO, 0, 1, km_status_fields }, + { KM_TCAM_CTRL, 4, 32, REGISTER_TYPE_WO, 0, 2, km_tcam_ctrl_fields }, + { KM_TCAM_DATA, 5, 72, REGISTER_TYPE_WO, 0, 1, km_tcam_data_fields }, + { KM_TCI_CTRL, 6, 32, REGISTER_TYPE_WO, 0, 2, km_tci_ctrl_fields }, + { KM_TCI_DATA, 7, 36, REGISTER_TYPE_WO, 0, 2, km_tci_data_fields }, + { KM_TCQ_CTRL, 8, 21, REGISTER_TYPE_WO, 0, 2, km_tcq_ctrl_fields }, + { KM_TCQ_DATA, 9, 15, REGISTER_TYPE_WO, 0, 2, km_tcq_data_fields }, +}; + +static nt_fpga_field_init_t mac_pcs_bad_code_fields[] = { + { MAC_PCS_BAD_CODE_CODE_ERR, 16, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_bip_err_fields[] = { + { MAC_PCS_BIP_ERR_BIP_ERR, 640, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_block_lock_fields[] = { + { MAC_PCS_BLOCK_LOCK_LOCK, 20, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_block_lock_chg_fields[] = { + { MAC_PCS_BLOCK_LOCK_CHG_LOCK_CHG, 20, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_debounce_ctrl_fields[] = { + { MAC_PCS_DEBOUNCE_CTRL_NT_DEBOUNCE_LATENCY, 8, 8, 10 }, + { MAC_PCS_DEBOUNCE_CTRL_NT_FORCE_LINK_DOWN, 1, 16, 0 }, + { MAC_PCS_DEBOUNCE_CTRL_NT_LINKUP_LATENCY, 8, 0, 10 }, + { MAC_PCS_DEBOUNCE_CTRL_NT_PORT_CTRL, 2, 17, 2 }, +}; + +static nt_fpga_field_init_t mac_pcs_drp_ctrl_fields[] = { + { MAC_PCS_DRP_CTRL_ADR, 10, 16, 0 }, + { MAC_PCS_DRP_CTRL_DATA, 16, 0, 0 }, + { MAC_PCS_DRP_CTRL_DBG_BUSY, 1, 30, 0x0000 }, + { MAC_PCS_DRP_CTRL_DONE, 1, 31, 0x0000 }, + { MAC_PCS_DRP_CTRL_MOD_ADR, 3, 26, 0 }, + { MAC_PCS_DRP_CTRL_WREN, 1, 29, 0 }, +}; + +static nt_fpga_field_init_t mac_pcs_fec_ctrl_fields[] = { + { MAC_PCS_FEC_CTRL_RS_FEC_CTRL_IN, 5, 0, 0 }, +}; + +static nt_fpga_field_init_t mac_pcs_fec_cw_cnt_fields[] = { + { MAC_PCS_FEC_CW_CNT_CW_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_fec_err_cnt_0_fields[] = { + { MAC_PCS_FEC_ERR_CNT_0_ERR_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_fec_err_cnt_1_fields[] = { + { MAC_PCS_FEC_ERR_CNT_1_ERR_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_fec_err_cnt_2_fields[] = { + { MAC_PCS_FEC_ERR_CNT_2_ERR_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_fec_err_cnt_3_fields[] = { + { MAC_PCS_FEC_ERR_CNT_3_ERR_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_fec_lane_dly_0_fields[] = { + { MAC_PCS_FEC_LANE_DLY_0_DLY, 14, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_fec_lane_dly_1_fields[] = { + { MAC_PCS_FEC_LANE_DLY_1_DLY, 14, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_fec_lane_dly_2_fields[] = { + { MAC_PCS_FEC_LANE_DLY_2_DLY, 14, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_fec_lane_dly_3_fields[] = { + { MAC_PCS_FEC_LANE_DLY_3_DLY, 14, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_fec_lane_map_fields[] = { + { MAC_PCS_FEC_LANE_MAP_MAPPING, 8, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_fec_stat_fields[] = { + { MAC_PCS_FEC_STAT_AM_LOCK, 1, 10, 0x0000 }, + { MAC_PCS_FEC_STAT_AM_LOCK_0, 1, 3, 0x0000 }, + { MAC_PCS_FEC_STAT_AM_LOCK_1, 1, 4, 0x0000 }, + { MAC_PCS_FEC_STAT_AM_LOCK_2, 1, 5, 0x0000 }, + { MAC_PCS_FEC_STAT_AM_LOCK_3, 1, 6, 0x0000 }, + { MAC_PCS_FEC_STAT_BLOCK_LOCK, 1, 9, 0x0000 }, + { MAC_PCS_FEC_STAT_BYPASS, 1, 0, 0x0000 }, + { MAC_PCS_FEC_STAT_FEC_LANE_ALGN, 1, 7, 0x0000 }, + { MAC_PCS_FEC_STAT_HI_SER, 1, 2, 0x0000 }, + { MAC_PCS_FEC_STAT_PCS_LANE_ALGN, 1, 8, 0x0000 }, + { MAC_PCS_FEC_STAT_VALID, 1, 1, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_fec_ucw_cnt_fields[] = { + { MAC_PCS_FEC_UCW_CNT_UCW_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_gty_ctl_rx_fields[] = { + { MAC_PCS_GTY_CTL_RX_CDR_HOLD_0, 1, 24, 0 }, + { MAC_PCS_GTY_CTL_RX_CDR_HOLD_1, 1, 25, 0 }, + { MAC_PCS_GTY_CTL_RX_CDR_HOLD_2, 1, 26, 0 }, + { MAC_PCS_GTY_CTL_RX_CDR_HOLD_3, 1, 27, 0 }, + { MAC_PCS_GTY_CTL_RX_EQUA_RST_0, 1, 20, 0 }, + { MAC_PCS_GTY_CTL_RX_EQUA_RST_1, 1, 21, 0 }, + { MAC_PCS_GTY_CTL_RX_EQUA_RST_2, 1, 22, 0 }, + { MAC_PCS_GTY_CTL_RX_EQUA_RST_3, 1, 23, 0 }, + { MAC_PCS_GTY_CTL_RX_LPM_EN_0, 1, 16, 0 }, + { MAC_PCS_GTY_CTL_RX_LPM_EN_1, 1, 17, 0 }, + { MAC_PCS_GTY_CTL_RX_LPM_EN_2, 1, 18, 0 }, + { MAC_PCS_GTY_CTL_RX_LPM_EN_3, 1, 19, 0 }, + { MAC_PCS_GTY_CTL_RX_POLARITY_0, 1, 0, 0 }, + { MAC_PCS_GTY_CTL_RX_POLARITY_1, 1, 1, 0 }, + { MAC_PCS_GTY_CTL_RX_POLARITY_2, 1, 2, 0 }, + { MAC_PCS_GTY_CTL_RX_POLARITY_3, 1, 3, 0 }, + { MAC_PCS_GTY_CTL_RX_RATE_0, 3, 4, 0 }, + { MAC_PCS_GTY_CTL_RX_RATE_1, 3, 7, 0 }, + { MAC_PCS_GTY_CTL_RX_RATE_2, 3, 10, 0 }, + { MAC_PCS_GTY_CTL_RX_RATE_3, 3, 13, 0 }, +}; + +static nt_fpga_field_init_t mac_pcs_gty_ctl_tx_fields[] = { + { MAC_PCS_GTY_CTL_TX_INHIBIT_0, 1, 4, 0 }, + { MAC_PCS_GTY_CTL_TX_INHIBIT_1, 1, 5, 0 }, + { MAC_PCS_GTY_CTL_TX_INHIBIT_2, 1, 6, 0 }, + { MAC_PCS_GTY_CTL_TX_INHIBIT_3, 1, 7, 0 }, + { MAC_PCS_GTY_CTL_TX_POLARITY_0, 1, 0, 0 }, + { MAC_PCS_GTY_CTL_TX_POLARITY_1, 1, 1, 0 }, + { MAC_PCS_GTY_CTL_TX_POLARITY_2, 1, 2, 0 }, + { MAC_PCS_GTY_CTL_TX_POLARITY_3, 1, 3, 0 }, +}; + +static nt_fpga_field_init_t mac_pcs_gty_diff_ctl_fields[] = { + { MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_0, 5, 0, 24 }, + { MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_1, 5, 5, 24 }, + { MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_2, 5, 10, 24 }, + { MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_3, 5, 15, 24 }, +}; + +static nt_fpga_field_init_t mac_pcs_gty_loop_fields[] = { + { MAC_PCS_GTY_LOOP_GT_LOOP_0, 3, 0, 0 }, + { MAC_PCS_GTY_LOOP_GT_LOOP_1, 3, 3, 0 }, + { MAC_PCS_GTY_LOOP_GT_LOOP_2, 3, 6, 0 }, + { MAC_PCS_GTY_LOOP_GT_LOOP_3, 3, 9, 0 }, +}; + +static nt_fpga_field_init_t mac_pcs_gty_post_cursor_fields[] = { + { MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_0, 5, 0, 20 }, + { MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_1, 5, 5, 20 }, + { MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_2, 5, 10, 20 }, + { MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_3, 5, 15, 20 }, +}; + +static nt_fpga_field_init_t mac_pcs_gty_prbs_sel_fields[] = { + { MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_0, 4, 16, 0 }, + { MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_1, 4, 20, 0 }, + { MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_2, 4, 24, 0 }, + { MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_3, 4, 28, 0 }, + { MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_0, 4, 0, 0 }, + { MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_1, 4, 4, 0 }, + { MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_2, 4, 8, 0 }, + { MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_3, 4, 12, 0 }, +}; + +static nt_fpga_field_init_t mac_pcs_gty_pre_cursor_fields[] = { + { MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_0, 5, 0, 0 }, + { MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_1, 5, 5, 0 }, + { MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_2, 5, 10, 0 }, + { MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_3, 5, 15, 0 }, +}; + +static nt_fpga_field_init_t mac_pcs_gty_rx_buf_stat_fields[] = { + { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_0, 3, 0, 0x0000 }, + { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_1, 3, 3, 0x0000 }, + { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_2, 3, 6, 0x0000 }, + { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_3, 3, 9, 0x0000 }, + { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_0, 3, 12, 0x0000 }, + { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_1, 3, 15, 0x0000 }, + { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_2, 3, 18, 0x0000 }, + { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_3, 3, 21, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_gty_scan_ctl_fields[] = { + { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_0, 1, 0, 0 }, + { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_1, 1, 1, 0 }, + { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_2, 1, 2, 0 }, + { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_3, 1, 3, 0 }, + { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_0, 1, 4, 0 }, + { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_1, 1, 5, 0 }, + { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_2, 1, 6, 0 }, + { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_3, 1, 7, 0 }, + { MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_0, 1, 12, 0 }, + { MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_1, 1, 13, 0 }, + { MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_2, 1, 14, 0 }, + { MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_3, 1, 15, 0 }, + { MAC_PCS_GTY_SCAN_CTL_PRBS_RST_0, 1, 8, 0 }, + { MAC_PCS_GTY_SCAN_CTL_PRBS_RST_1, 1, 9, 0 }, + { MAC_PCS_GTY_SCAN_CTL_PRBS_RST_2, 1, 10, 0 }, + { MAC_PCS_GTY_SCAN_CTL_PRBS_RST_3, 1, 11, 0 }, +}; + +static nt_fpga_field_init_t mac_pcs_gty_scan_stat_fields[] = { + { MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_0, 1, 0, 0x0000 }, + { MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_1, 1, 1, 0x0000 }, + { MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_2, 1, 2, 0x0000 }, + { MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_3, 1, 3, 0x0000 }, + { MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_0, 1, 4, 0x0000 }, + { MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_1, 1, 5, 0x0000 }, + { MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_2, 1, 6, 0x0000 }, + { MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_3, 1, 7, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_gty_stat_fields[] = { + { MAC_PCS_GTY_STAT_RX_RST_DONE_0, 1, 4, 0x0000 }, + { MAC_PCS_GTY_STAT_RX_RST_DONE_1, 1, 5, 0x0000 }, + { MAC_PCS_GTY_STAT_RX_RST_DONE_2, 1, 6, 0x0000 }, + { MAC_PCS_GTY_STAT_RX_RST_DONE_3, 1, 7, 0x0000 }, + { MAC_PCS_GTY_STAT_TX_BUF_STAT_0, 2, 8, 0x0000 }, + { MAC_PCS_GTY_STAT_TX_BUF_STAT_1, 2, 10, 0x0000 }, + { MAC_PCS_GTY_STAT_TX_BUF_STAT_2, 2, 12, 0x0000 }, + { MAC_PCS_GTY_STAT_TX_BUF_STAT_3, 2, 14, 0x0000 }, + { MAC_PCS_GTY_STAT_TX_RST_DONE_0, 1, 0, 0x0000 }, + { MAC_PCS_GTY_STAT_TX_RST_DONE_1, 1, 1, 0x0000 }, + { MAC_PCS_GTY_STAT_TX_RST_DONE_2, 1, 2, 0x0000 }, + { MAC_PCS_GTY_STAT_TX_RST_DONE_3, 1, 3, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_link_summary_fields[] = { + { MAC_PCS_LINK_SUMMARY_ABS, 1, 0, 0x0000 }, + { MAC_PCS_LINK_SUMMARY_LH_ABS, 1, 2, 0x0000 }, + { MAC_PCS_LINK_SUMMARY_LH_LOCAL_FAULT, 1, 13, 0 }, + { MAC_PCS_LINK_SUMMARY_LH_REMOTE_FAULT, 1, 14, 0 }, + { MAC_PCS_LINK_SUMMARY_LINK_DOWN_CNT, 8, 4, 0 }, + { MAC_PCS_LINK_SUMMARY_LL_PHY_LINK_STATE, 1, 3, 0x0000 }, + { MAC_PCS_LINK_SUMMARY_LOCAL_FAULT, 1, 17, 0x0000 }, + { MAC_PCS_LINK_SUMMARY_NIM_INTERR, 1, 12, 0x0000 }, + { MAC_PCS_LINK_SUMMARY_NT_PHY_LINK_STATE, 1, 1, 0x0000 }, + { MAC_PCS_LINK_SUMMARY_REMOTE_FAULT, 1, 18, 0x0000 }, + { MAC_PCS_LINK_SUMMARY_RESERVED, 2, 15, 0 }, +}; + +static nt_fpga_field_init_t mac_pcs_mac_pcs_config_fields[] = { + { MAC_PCS_MAC_PCS_CONFIG_RX_CORE_RST, 1, 3, 0 }, + { MAC_PCS_MAC_PCS_CONFIG_RX_ENABLE, 1, 5, 0 }, + { MAC_PCS_MAC_PCS_CONFIG_RX_FORCE_RESYNC, 1, 6, 0 }, + { MAC_PCS_MAC_PCS_CONFIG_RX_PATH_RST, 1, 1, 0 }, + { MAC_PCS_MAC_PCS_CONFIG_RX_TEST_PATTERN, 1, 7, 0 }, + { MAC_PCS_MAC_PCS_CONFIG_TX_CORE_RST, 1, 2, 0 }, + { MAC_PCS_MAC_PCS_CONFIG_TX_ENABLE, 1, 8, 1 }, + { MAC_PCS_MAC_PCS_CONFIG_TX_FCS_REMOVE, 1, 4, 1 }, + { MAC_PCS_MAC_PCS_CONFIG_TX_PATH_RST, 1, 0, 0 }, + { MAC_PCS_MAC_PCS_CONFIG_TX_SEND_IDLE, 1, 9, 0 }, + { MAC_PCS_MAC_PCS_CONFIG_TX_SEND_RFI, 1, 10, 0 }, + { MAC_PCS_MAC_PCS_CONFIG_TX_TEST_PATTERN, 1, 11, 0 }, +}; + +static nt_fpga_field_init_t mac_pcs_max_pkt_len_fields[] = { + { MAC_PCS_MAX_PKT_LEN_MAX_LEN, 14, 0, 10000 }, +}; + +static nt_fpga_field_init_t mac_pcs_phymac_misc_fields[] = { + { MAC_PCS_PHYMAC_MISC_TS_EOP, 1, 3, 1 }, + { MAC_PCS_PHYMAC_MISC_TX_MUX_STATE, 4, 4, 0x0000 }, + { MAC_PCS_PHYMAC_MISC_TX_SEL_HOST, 1, 0, 1 }, + { MAC_PCS_PHYMAC_MISC_TX_SEL_RX_LOOP, 1, 2, 0 }, + { MAC_PCS_PHYMAC_MISC_TX_SEL_TFG, 1, 1, 0 }, +}; + +static nt_fpga_field_init_t mac_pcs_phy_stat_fields[] = { + { MAC_PCS_PHY_STAT_ALARM, 1, 2, 0x0000 }, + { MAC_PCS_PHY_STAT_MOD_PRS, 1, 1, 0x0000 }, + { MAC_PCS_PHY_STAT_RX_LOS, 1, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_stat_pcs_rx_fields[] = { + { MAC_PCS_STAT_PCS_RX_ALIGNED, 1, 1, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_ALIGNED_ERR, 1, 2, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_GOT_SIGNAL_OS, 1, 9, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_HI_BER, 1, 8, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_INTERNAL_LOCAL_FAULT, 1, 4, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_LOCAL_FAULT, 1, 6, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_MISALIGNED, 1, 3, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_RECEIVED_LOCAL_FAULT, 1, 5, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_REMOTE_FAULT, 1, 7, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_STATUS, 1, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_stat_pcs_rx_latch_fields[] = { + { MAC_PCS_STAT_PCS_RX_LATCH_ALIGNED, 1, 1, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_LATCH_ALIGNED_ERR, 1, 2, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_LATCH_GOT_SIGNAL_OS, 1, 9, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_LATCH_HI_BER, 1, 8, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_LATCH_INTERNAL_LOCAL_FAULT, 1, 4, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_LATCH_LOCAL_FAULT, 1, 6, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_LATCH_MISALIGNED, 1, 3, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_LATCH_RECEIVED_LOCAL_FAULT, 1, 5, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_LATCH_REMOTE_FAULT, 1, 7, 0x0000 }, + { MAC_PCS_STAT_PCS_RX_LATCH_STATUS, 1, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_stat_pcs_tx_fields[] = { + { MAC_PCS_STAT_PCS_TX_LOCAL_FAULT, 1, 0, 0x0000 }, + { MAC_PCS_STAT_PCS_TX_LOCAL_FAULT_CHANGED, 1, 5, 0x0000 }, + { MAC_PCS_STAT_PCS_TX_PTP_FIFO_READ_ERROR, 1, 4, 0x0000 }, + { MAC_PCS_STAT_PCS_TX_PTP_FIFO_READ_ERROR_CHANGED, 1, 9, 0x0000 }, + { MAC_PCS_STAT_PCS_TX_PTP_FIFO_WRITE_ERROR, 1, 3, 0x0000 }, + { MAC_PCS_STAT_PCS_TX_PTP_FIFO_WRITE_ERROR_CHANGED, 1, 8, 0x0000 }, + { MAC_PCS_STAT_PCS_TX_TX_OVFOUT, 1, 2, 0x0000 }, + { MAC_PCS_STAT_PCS_TX_TX_OVFOUT_CHANGED, 1, 7, 0x0000 }, + { MAC_PCS_STAT_PCS_TX_TX_UNFOUT, 1, 1, 0x0000 }, + { MAC_PCS_STAT_PCS_TX_TX_UNFOUT_CHANGED, 1, 6, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_synced_fields[] = { + { MAC_PCS_SYNCED_SYNC, 20, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_synced_err_fields[] = { + { MAC_PCS_SYNCED_ERR_SYNC_ERROR, 20, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_test_err_fields[] = { + { MAC_PCS_TEST_ERR_CODE_ERR, 16, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_timestamp_comp_fields[] = { + { MAC_PCS_TIMESTAMP_COMP_RX_DLY, 16, 0, 1451 }, + { MAC_PCS_TIMESTAMP_COMP_TX_DLY, 16, 16, 1440 }, +}; + +static nt_fpga_field_init_t mac_pcs_vl_demuxed_fields[] = { + { MAC_PCS_VL_DEMUXED_LOCK, 20, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_pcs_vl_demuxed_chg_fields[] = { + { MAC_PCS_VL_DEMUXED_CHG_LOCK_CHG, 20, 0, 0x0000 }, +}; + +static nt_fpga_register_init_t mac_pcs_registers[] = { + { MAC_PCS_BAD_CODE, 26, 16, REGISTER_TYPE_RO, 0, 1, + mac_pcs_bad_code_fields + }, + { MAC_PCS_BIP_ERR, 31, 640, REGISTER_TYPE_RO, 0, 1, + mac_pcs_bip_err_fields + }, + { MAC_PCS_BLOCK_LOCK, 27, 20, REGISTER_TYPE_RO, 0, 1, + mac_pcs_block_lock_fields + }, + { MAC_PCS_BLOCK_LOCK_CHG, 28, 20, REGISTER_TYPE_RO, 0, 1, + mac_pcs_block_lock_chg_fields + }, + { MAC_PCS_DEBOUNCE_CTRL, 1, 19, REGISTER_TYPE_RW, 264714, 4, + mac_pcs_debounce_ctrl_fields + }, + { MAC_PCS_DRP_CTRL, 43, 32, REGISTER_TYPE_MIXED, 0, 6, + mac_pcs_drp_ctrl_fields + }, + { MAC_PCS_FEC_CTRL, 2, 5, REGISTER_TYPE_RW, 0, 1, + mac_pcs_fec_ctrl_fields + }, + { MAC_PCS_FEC_CW_CNT, 9, 32, REGISTER_TYPE_RO, 0, 1, + mac_pcs_fec_cw_cnt_fields + }, + { MAC_PCS_FEC_ERR_CNT_0, 11, 32, REGISTER_TYPE_RO, 0, 1, + mac_pcs_fec_err_cnt_0_fields + }, + { MAC_PCS_FEC_ERR_CNT_1, 12, 32, REGISTER_TYPE_RO, 0, 1, + mac_pcs_fec_err_cnt_1_fields + }, + { MAC_PCS_FEC_ERR_CNT_2, 13, 32, REGISTER_TYPE_RO, 0, 1, + mac_pcs_fec_err_cnt_2_fields + }, + { MAC_PCS_FEC_ERR_CNT_3, 14, 32, REGISTER_TYPE_RO, 0, 1, + mac_pcs_fec_err_cnt_3_fields + }, + { MAC_PCS_FEC_LANE_DLY_0, 5, 14, REGISTER_TYPE_RO, 0, 1, + mac_pcs_fec_lane_dly_0_fields + }, + { MAC_PCS_FEC_LANE_DLY_1, 6, 14, REGISTER_TYPE_RO, 0, 1, + mac_pcs_fec_lane_dly_1_fields + }, + { MAC_PCS_FEC_LANE_DLY_2, 7, 14, REGISTER_TYPE_RO, 0, 1, + mac_pcs_fec_lane_dly_2_fields + }, + { MAC_PCS_FEC_LANE_DLY_3, 8, 14, REGISTER_TYPE_RO, 0, 1, + mac_pcs_fec_lane_dly_3_fields + }, + { MAC_PCS_FEC_LANE_MAP, 4, 8, REGISTER_TYPE_RO, 0, 1, + mac_pcs_fec_lane_map_fields + }, + { MAC_PCS_FEC_STAT, 3, 11, REGISTER_TYPE_RO, 0, 11, + mac_pcs_fec_stat_fields + }, + { MAC_PCS_FEC_UCW_CNT, 10, 32, REGISTER_TYPE_RO, 0, 1, + mac_pcs_fec_ucw_cnt_fields + }, + { MAC_PCS_GTY_CTL_RX, 38, 28, REGISTER_TYPE_RW, 0, 20, + mac_pcs_gty_ctl_rx_fields + }, + { MAC_PCS_GTY_CTL_TX, 39, 8, REGISTER_TYPE_RW, 0, 8, + mac_pcs_gty_ctl_tx_fields + }, + { MAC_PCS_GTY_DIFF_CTL, 35, 20, REGISTER_TYPE_RW, 811800, 4, + mac_pcs_gty_diff_ctl_fields + }, + { MAC_PCS_GTY_LOOP, 20, 12, REGISTER_TYPE_RW, 0, 4, + mac_pcs_gty_loop_fields + }, + { MAC_PCS_GTY_POST_CURSOR, 36, 20, REGISTER_TYPE_RW, 676500, 4, + mac_pcs_gty_post_cursor_fields + }, + { MAC_PCS_GTY_PRBS_SEL, 40, 32, REGISTER_TYPE_RW, 0, 8, + mac_pcs_gty_prbs_sel_fields + }, + { MAC_PCS_GTY_PRE_CURSOR, 37, 20, REGISTER_TYPE_RW, 0, 4, + mac_pcs_gty_pre_cursor_fields + }, + { MAC_PCS_GTY_RX_BUF_STAT, 34, 24, REGISTER_TYPE_RO, 0, 8, + mac_pcs_gty_rx_buf_stat_fields + }, + { MAC_PCS_GTY_SCAN_CTL, 41, 16, REGISTER_TYPE_RW, 0, 16, + mac_pcs_gty_scan_ctl_fields + }, + { MAC_PCS_GTY_SCAN_STAT, 42, 8, REGISTER_TYPE_RO, 0, 8, + mac_pcs_gty_scan_stat_fields + }, + { MAC_PCS_GTY_STAT, 33, 16, REGISTER_TYPE_RO, 0, 12, + mac_pcs_gty_stat_fields + }, + { MAC_PCS_LINK_SUMMARY, 0, 19, REGISTER_TYPE_RO, 0, 11, + mac_pcs_link_summary_fields + }, + { MAC_PCS_MAC_PCS_CONFIG, 19, 12, REGISTER_TYPE_RW, 272, 12, + mac_pcs_mac_pcs_config_fields + }, + { MAC_PCS_MAX_PKT_LEN, 17, 14, REGISTER_TYPE_RW, 10000, 1, + mac_pcs_max_pkt_len_fields + }, + { MAC_PCS_PHYMAC_MISC, 16, 8, REGISTER_TYPE_MIXED, 9, 5, + mac_pcs_phymac_misc_fields + }, + { MAC_PCS_PHY_STAT, 15, 3, REGISTER_TYPE_RO, 0, 3, + mac_pcs_phy_stat_fields + }, + { MAC_PCS_STAT_PCS_RX, 21, 10, REGISTER_TYPE_RO, 0, 10, + mac_pcs_stat_pcs_rx_fields + }, + { MAC_PCS_STAT_PCS_RX_LATCH, 22, 10, REGISTER_TYPE_RO, 0, 10, + mac_pcs_stat_pcs_rx_latch_fields + }, + { MAC_PCS_STAT_PCS_TX, 23, 10, REGISTER_TYPE_RO, 0, 10, + mac_pcs_stat_pcs_tx_fields + }, + { MAC_PCS_SYNCED, 24, 20, REGISTER_TYPE_RO, 0, 1, + mac_pcs_synced_fields + }, + { MAC_PCS_SYNCED_ERR, 25, 20, REGISTER_TYPE_RO, 0, 1, + mac_pcs_synced_err_fields + }, + { MAC_PCS_TEST_ERR, 32, 16, REGISTER_TYPE_RO, 0, 1, + mac_pcs_test_err_fields + }, + { MAC_PCS_TIMESTAMP_COMP, 18, 32, REGISTER_TYPE_RW, 94373291, 2, + mac_pcs_timestamp_comp_fields + }, + { MAC_PCS_VL_DEMUXED, 29, 20, REGISTER_TYPE_RO, 0, 1, + mac_pcs_vl_demuxed_fields + }, + { MAC_PCS_VL_DEMUXED_CHG, 30, 20, REGISTER_TYPE_RO, 0, 1, + mac_pcs_vl_demuxed_chg_fields + }, +}; + +static nt_fpga_field_init_t mac_rx_bad_fcs_fields[] = { + { MAC_RX_BAD_FCS_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_rx_fragment_fields[] = { + { MAC_RX_FRAGMENT_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_rx_packet_bad_fcs_fields[] = { + { MAC_RX_PACKET_BAD_FCS_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_rx_packet_small_fields[] = { + { MAC_RX_PACKET_SMALL_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_rx_total_bytes_fields[] = { + { MAC_RX_TOTAL_BYTES_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_rx_total_good_bytes_fields[] = { + { MAC_RX_TOTAL_GOOD_BYTES_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_rx_total_good_packets_fields[] = { + { MAC_RX_TOTAL_GOOD_PACKETS_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_rx_total_packets_fields[] = { + { MAC_RX_TOTAL_PACKETS_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_rx_undersize_fields[] = { + { MAC_RX_UNDERSIZE_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_register_init_t mac_rx_registers[] = { + { MAC_RX_BAD_FCS, 0, 32, REGISTER_TYPE_RO, 0, 1, + mac_rx_bad_fcs_fields + }, + { MAC_RX_FRAGMENT, 6, 32, REGISTER_TYPE_RO, 0, 1, + mac_rx_fragment_fields + }, + { MAC_RX_PACKET_BAD_FCS, 7, 32, REGISTER_TYPE_RO, 0, 1, + mac_rx_packet_bad_fcs_fields + }, + { MAC_RX_PACKET_SMALL, 3, 32, REGISTER_TYPE_RO, 0, 1, + mac_rx_packet_small_fields + }, + { MAC_RX_TOTAL_BYTES, 4, 32, REGISTER_TYPE_RO, 0, 1, + mac_rx_total_bytes_fields + }, + { MAC_RX_TOTAL_GOOD_BYTES, 5, 32, REGISTER_TYPE_RO, 0, 1, + mac_rx_total_good_bytes_fields + }, + { MAC_RX_TOTAL_GOOD_PACKETS, 2, 32, REGISTER_TYPE_RO, 0, 1, + mac_rx_total_good_packets_fields + }, + { MAC_RX_TOTAL_PACKETS, 1, 32, REGISTER_TYPE_RO, 0, 1, + mac_rx_total_packets_fields + }, + { MAC_RX_UNDERSIZE, 8, 32, REGISTER_TYPE_RO, 0, 1, + mac_rx_undersize_fields + }, +}; + +static nt_fpga_field_init_t mac_tx_packet_small_fields[] = { + { MAC_TX_PACKET_SMALL_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_tx_total_bytes_fields[] = { + { MAC_TX_TOTAL_BYTES_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_tx_total_good_bytes_fields[] = { + { MAC_TX_TOTAL_GOOD_BYTES_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_tx_total_good_packets_fields[] = { + { MAC_TX_TOTAL_GOOD_PACKETS_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t mac_tx_total_packets_fields[] = { + { MAC_TX_TOTAL_PACKETS_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_register_init_t mac_tx_registers[] = { + { MAC_TX_PACKET_SMALL, 2, 32, REGISTER_TYPE_RO, 0, 1, + mac_tx_packet_small_fields + }, + { MAC_TX_TOTAL_BYTES, 3, 32, REGISTER_TYPE_RO, 0, 1, + mac_tx_total_bytes_fields + }, + { MAC_TX_TOTAL_GOOD_BYTES, 4, 32, REGISTER_TYPE_RO, 0, 1, + mac_tx_total_good_bytes_fields + }, + { MAC_TX_TOTAL_GOOD_PACKETS, 1, 32, REGISTER_TYPE_RO, 0, 1, + mac_tx_total_good_packets_fields + }, + { MAC_TX_TOTAL_PACKETS, 0, 32, REGISTER_TYPE_RO, 0, 1, + mac_tx_total_packets_fields + }, +}; + +static nt_fpga_field_init_t pci_rd_tg_tg_ctrl_fields[] = { + { PCI_RD_TG_TG_CTRL_TG_RD_RDY, 1, 0, 0 }, +}; + +static nt_fpga_field_init_t pci_rd_tg_tg_rdaddr_fields[] = { + { PCI_RD_TG_TG_RDADDR_RAM_ADDR, 9, 0, 0 }, +}; + +static nt_fpga_field_init_t pci_rd_tg_tg_rddata0_fields[] = { + { PCI_RD_TG_TG_RDDATA0_PHYS_ADDR_LOW, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t pci_rd_tg_tg_rddata1_fields[] = { + { PCI_RD_TG_TG_RDDATA1_PHYS_ADDR_HIGH, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t pci_rd_tg_tg_rddata2_fields[] = { + { PCI_RD_TG_TG_RDDATA2_REQ_HID, 6, 22, 0 }, + { PCI_RD_TG_TG_RDDATA2_REQ_SIZE, 22, 0, 0 }, + { PCI_RD_TG_TG_RDDATA2_WAIT, 1, 30, 0 }, + { PCI_RD_TG_TG_RDDATA2_WRAP, 1, 31, 0 }, +}; + +static nt_fpga_field_init_t pci_rd_tg_tg_rd_run_fields[] = { + { PCI_RD_TG_TG_RD_RUN_RD_ITERATION, 16, 0, 0 }, +}; + +static nt_fpga_register_init_t pci_rd_tg_registers[] = { + { PCI_RD_TG_TG_CTRL, 5, 1, REGISTER_TYPE_RO, 0, 1, + pci_rd_tg_tg_ctrl_fields + }, + { PCI_RD_TG_TG_RDADDR, 3, 9, REGISTER_TYPE_WO, 0, 1, + pci_rd_tg_tg_rdaddr_fields + }, + { PCI_RD_TG_TG_RDDATA0, 0, 32, REGISTER_TYPE_WO, 0, 1, + pci_rd_tg_tg_rddata0_fields + }, + { PCI_RD_TG_TG_RDDATA1, 1, 32, REGISTER_TYPE_WO, 0, 1, + pci_rd_tg_tg_rddata1_fields + }, + { PCI_RD_TG_TG_RDDATA2, 2, 32, REGISTER_TYPE_WO, 0, 4, + pci_rd_tg_tg_rddata2_fields + }, + { PCI_RD_TG_TG_RD_RUN, 4, 16, REGISTER_TYPE_WO, 0, 1, + pci_rd_tg_tg_rd_run_fields + }, +}; + +static nt_fpga_field_init_t pci_ta_control_fields[] = { + { PCI_TA_CONTROL_ENABLE, 1, 0, 0 }, +}; + +static nt_fpga_field_init_t pci_ta_length_error_fields[] = { + { PCI_TA_LENGTH_ERROR_AMOUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t pci_ta_packet_bad_fields[] = { + { PCI_TA_PACKET_BAD_AMOUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t pci_ta_packet_good_fields[] = { + { PCI_TA_PACKET_GOOD_AMOUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t pci_ta_payload_error_fields[] = { + { PCI_TA_PAYLOAD_ERROR_AMOUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_register_init_t pci_ta_registers[] = { + { PCI_TA_CONTROL, 0, 1, REGISTER_TYPE_WO, 0, 1, pci_ta_control_fields }, + { PCI_TA_LENGTH_ERROR, 3, 32, REGISTER_TYPE_RO, 0, 1, + pci_ta_length_error_fields + }, + { PCI_TA_PACKET_BAD, 2, 32, REGISTER_TYPE_RO, 0, 1, + pci_ta_packet_bad_fields + }, + { PCI_TA_PACKET_GOOD, 1, 32, REGISTER_TYPE_RO, 0, 1, + pci_ta_packet_good_fields + }, + { PCI_TA_PAYLOAD_ERROR, 4, 32, REGISTER_TYPE_RO, 0, 1, + pci_ta_payload_error_fields + }, +}; + +static nt_fpga_field_init_t pci_wr_tg_tg_ctrl_fields[] = { + { PCI_WR_TG_TG_CTRL_TG_WR_RDY, 1, 0, 0 }, +}; + +static nt_fpga_field_init_t pci_wr_tg_tg_seq_fields[] = { + { PCI_WR_TG_TG_SEQ_SEQUENCE, 16, 0, 0 }, +}; + +static nt_fpga_field_init_t pci_wr_tg_tg_wraddr_fields[] = { + { PCI_WR_TG_TG_WRADDR_RAM_ADDR, 9, 0, 0 }, +}; + +static nt_fpga_field_init_t pci_wr_tg_tg_wrdata0_fields[] = { + { PCI_WR_TG_TG_WRDATA0_PHYS_ADDR_LOW, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t pci_wr_tg_tg_wrdata1_fields[] = { + { PCI_WR_TG_TG_WRDATA1_PHYS_ADDR_HIGH, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t pci_wr_tg_tg_wrdata2_fields[] = { + { PCI_WR_TG_TG_WRDATA2_INC_MODE, 1, 29, 0 }, + { PCI_WR_TG_TG_WRDATA2_REQ_HID, 6, 22, 0 }, + { PCI_WR_TG_TG_WRDATA2_REQ_SIZE, 22, 0, 0 }, + { PCI_WR_TG_TG_WRDATA2_WAIT, 1, 30, 0 }, + { PCI_WR_TG_TG_WRDATA2_WRAP, 1, 31, 0 }, +}; + +static nt_fpga_field_init_t pci_wr_tg_tg_wr_run_fields[] = { + { PCI_WR_TG_TG_WR_RUN_WR_ITERATION, 16, 0, 0 }, +}; + +static nt_fpga_register_init_t pci_wr_tg_registers[] = { + { PCI_WR_TG_TG_CTRL, 5, 1, REGISTER_TYPE_RO, 0, 1, + pci_wr_tg_tg_ctrl_fields + }, + { PCI_WR_TG_TG_SEQ, 6, 16, REGISTER_TYPE_RW, 0, 1, + pci_wr_tg_tg_seq_fields + }, + { PCI_WR_TG_TG_WRADDR, 3, 9, REGISTER_TYPE_WO, 0, 1, + pci_wr_tg_tg_wraddr_fields + }, + { PCI_WR_TG_TG_WRDATA0, 0, 32, REGISTER_TYPE_WO, 0, 1, + pci_wr_tg_tg_wrdata0_fields + }, + { PCI_WR_TG_TG_WRDATA1, 1, 32, REGISTER_TYPE_WO, 0, 1, + pci_wr_tg_tg_wrdata1_fields + }, + { PCI_WR_TG_TG_WRDATA2, 2, 32, REGISTER_TYPE_WO, 0, 5, + pci_wr_tg_tg_wrdata2_fields + }, + { PCI_WR_TG_TG_WR_RUN, 4, 16, REGISTER_TYPE_WO, 0, 1, + pci_wr_tg_tg_wr_run_fields + }, +}; + +static nt_fpga_field_init_t pdb_config_fields[] = { + { PDB_CONFIG_PORT_OFS, 6, 3, 0 }, + { PDB_CONFIG_TS_FORMAT, 3, 0, 0 }, +}; + +static nt_fpga_field_init_t pdb_rcp_ctrl_fields[] = { + { PDB_RCP_CTRL_ADR, 4, 0, 0x0000 }, + { PDB_RCP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t pdb_rcp_data_fields[] = { + { PDB_RCP_DATA_ALIGN, 1, 17, 0x0000 }, + { PDB_RCP_DATA_CRC_OVERWRITE, 1, 16, 0x0000 }, + { PDB_RCP_DATA_DESCRIPTOR, 4, 0, 0x0000 }, + { PDB_RCP_DATA_DESC_LEN, 5, 4, 0 }, + { PDB_RCP_DATA_DUPLICATE_BIT, 5, 61, 0x0000 }, + { PDB_RCP_DATA_DUPLICATE_EN, 1, 60, 0x0000 }, + { PDB_RCP_DATA_IP_PROT_TNL, 1, 57, 0x0000 }, + { PDB_RCP_DATA_OFS0_DYN, 5, 18, 0x0000 }, + { PDB_RCP_DATA_OFS0_REL, 8, 23, 0x0000 }, + { PDB_RCP_DATA_OFS1_DYN, 5, 31, 0x0000 }, + { PDB_RCP_DATA_OFS1_REL, 8, 36, 0x0000 }, + { PDB_RCP_DATA_OFS2_DYN, 5, 44, 0x0000 }, + { PDB_RCP_DATA_OFS2_REL, 8, 49, 0x0000 }, + { PDB_RCP_DATA_PCAP_KEEP_FCS, 1, 66, 0x0000 }, + { PDB_RCP_DATA_PPC_HSH, 2, 58, 0x0000 }, + { PDB_RCP_DATA_TX_IGNORE, 1, 14, 0x0000 }, + { PDB_RCP_DATA_TX_NOW, 1, 15, 0x0000 }, + { PDB_RCP_DATA_TX_PORT, 5, 9, 0x0000 }, +}; + +static nt_fpga_register_init_t pdb_registers[] = { + { PDB_CONFIG, 2, 10, REGISTER_TYPE_WO, 0, 2, pdb_config_fields }, + { PDB_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, pdb_rcp_ctrl_fields }, + { PDB_RCP_DATA, 1, 67, REGISTER_TYPE_WO, 0, 18, pdb_rcp_data_fields }, +}; + +static nt_fpga_field_init_t pdi_cr_fields[] = { + { PDI_CR_EN, 1, 0, 0 }, { PDI_CR_PARITY, 1, 4, 0 }, + { PDI_CR_RST, 1, 1, 0 }, { PDI_CR_RXRST, 1, 2, 0 }, + { PDI_CR_STOP, 1, 5, 0 }, { PDI_CR_TXRST, 1, 3, 0 }, +}; + +static nt_fpga_field_init_t pdi_drr_fields[] = { + { PDI_DRR_DRR, 8, 0, 0 }, +}; + +static nt_fpga_field_init_t pdi_dtr_fields[] = { + { PDI_DTR_DTR, 8, 0, 0 }, +}; + +static nt_fpga_field_init_t pdi_pre_fields[] = { + { PDI_PRE_PRE, 7, 0, 3 }, +}; + +static nt_fpga_field_init_t pdi_sr_fields[] = { + { PDI_SR_DISABLE_BUSY, 1, 2, 0 }, { PDI_SR_DONE, 1, 0, 0 }, + { PDI_SR_ENABLE_BUSY, 1, 1, 0 }, { PDI_SR_FRAME_ERR, 1, 5, 0 }, + { PDI_SR_OVERRUN_ERR, 1, 7, 0 }, { PDI_SR_PARITY_ERR, 1, 6, 0 }, + { PDI_SR_RXLVL, 7, 8, 0 }, { PDI_SR_RX_BUSY, 1, 4, 0 }, + { PDI_SR_TXLVL, 7, 15, 0 }, { PDI_SR_TX_BUSY, 1, 3, 0 }, +}; + +static nt_fpga_field_init_t pdi_srr_fields[] = { + { PDI_SRR_RST, 4, 0, 0 }, +}; + +static nt_fpga_register_init_t pdi_registers[] = { + { PDI_CR, 1, 6, REGISTER_TYPE_WO, 0, 6, pdi_cr_fields }, + { PDI_DRR, 4, 8, REGISTER_TYPE_RO, 0, 1, pdi_drr_fields }, + { PDI_DTR, 3, 8, REGISTER_TYPE_WO, 0, 1, pdi_dtr_fields }, + { PDI_PRE, 5, 7, REGISTER_TYPE_WO, 3, 1, pdi_pre_fields }, + { PDI_SR, 2, 22, REGISTER_TYPE_RO, 0, 10, pdi_sr_fields }, + { PDI_SRR, 0, 4, REGISTER_TYPE_WO, 0, 1, pdi_srr_fields }, +}; + +static nt_fpga_field_init_t ptp1588_conf_fields[] = { + { PTP1588_CONF_MII_RX_TX_LOOP, 1, 0, 0 }, + { PTP1588_CONF_MII_TX_RX_LOOP, 1, 1, 0 }, + { PTP1588_CONF_PHY_RST1, 1, 10, 1 }, + { PTP1588_CONF_PHY_RST2, 1, 11, 1 }, + { PTP1588_CONF_PTP_CTRL_LOCAL, 1, 24, 0 }, + { PTP1588_CONF_PTP_RX_CTRL, 2, 19, 0 }, + { PTP1588_CONF_PTP_TX_CTRL, 2, 21, 0 }, + { PTP1588_CONF_PTP_TX_CTRL_OS, 1, 23, 0 }, + { PTP1588_CONF_RX_IGNORE_DEST_ADDR, 1, 25, 0 }, + { PTP1588_CONF_TG_CMD, 2, 13, 0 }, + { PTP1588_CONF_TG_MODE, 1, 12, 0 }, + { PTP1588_CONF_TSM_MI_ACK, 1, 16, 0 }, + { PTP1588_CONF_TSM_MI_BUSY, 1, 15, 0 }, + { PTP1588_CONF_TSM_MI_ENA, 1, 18, 0 }, + { PTP1588_CONF_TSM_MI_REQ, 1, 17, 0 }, + { PTP1588_CONF_TX_IFG, 8, 2, 0 }, + { PTP1588_CONF_TX_IGNORE_DEST_ADDR, 1, 26, 0 }, +}; + +static nt_fpga_field_init_t ptp1588_gp_data_fields[] = { + { PTP1588_GP_DATA_GPIO, 9, 1, 0 }, + { PTP1588_GP_DATA_PWRDOWN_INTN, 1, 0, 0 }, +}; + +static nt_fpga_field_init_t ptp1588_gp_data_lh_fields[] = { + { PTP1588_GP_DATA_LH_GPIO, 9, 1, 0 }, + { PTP1588_GP_DATA_LH_PWRDOWN_INTN, 1, 0, 0 }, +}; + +static nt_fpga_field_init_t ptp1588_gp_data_ll_fields[] = { + { PTP1588_GP_DATA_LL_GPIO, 9, 1, 511 }, + { PTP1588_GP_DATA_LL_PWRDOWN_INTN, 1, 0, 1 }, +}; + +static nt_fpga_field_init_t ptp1588_gp_oe_fields[] = { + { PTP1588_GP_OE_GPIO, 9, 1, 0 }, + { PTP1588_GP_OE_PWRDOWN_INTN, 1, 0, 0 }, +}; + +static nt_fpga_field_init_t ptp1588_mac_inband_stat_fields[] = { + { PTP1588_MAC_INBAND_STAT_DUPLEX, 1, 3, 0x0000 }, + { PTP1588_MAC_INBAND_STAT_LINK, 1, 0, 0x0000 }, + { PTP1588_MAC_INBAND_STAT_SPEED, 2, 1, 0x0000 }, +}; + +static nt_fpga_field_init_t ptp1588_mac_mi_conf_fields[] = { + { PTP1588_MAC_MI_CONF_ACCESS_TYPE, 1, 16, 0 }, + { PTP1588_MAC_MI_CONF_ADDRESS, 16, 0, 0 }, + { PTP1588_MAC_MI_CONF_RDY, 1, 17, 1 }, +}; + +static nt_fpga_field_init_t ptp1588_mac_mi_data_fields[] = { + { PTP1588_MAC_MI_DATA_DATA, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t ptp1588_rx_host_adr_lsb_fields[] = { + { PTP1588_RX_HOST_ADR_LSB_LSB, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t ptp1588_rx_host_adr_msb_fields[] = { + { PTP1588_RX_HOST_ADR_MSB_MSB, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t ptp1588_rx_host_conf_fields[] = { + { PTP1588_RX_HOST_CONF_ENA, 1, 11, 0 }, + { PTP1588_RX_HOST_CONF_RDPTR, 11, 0, 0 }, + { PTP1588_RX_HOST_CONF_REDUCED, 1, 12, 0 }, +}; + +static nt_fpga_field_init_t ptp1588_stat_fields[] = { + { PTP1588_STAT_DATA, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t ptp1588_stat_conf_fields[] = { + { PTP1588_STAT_CONF_INDEX, 5, 0, 0 }, + { PTP1588_STAT_CONF_LOCK, 1, 5, 0 }, +}; + +static nt_fpga_field_init_t ptp1588_tx_first_dat_fields[] = { + { PTP1588_TX_FIRST_DAT_DAT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t ptp1588_tx_last1_dat_fields[] = { + { PTP1588_TX_LAST1_DAT_DAT, 8, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t ptp1588_tx_last2_dat_fields[] = { + { PTP1588_TX_LAST2_DAT_DAT, 16, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t ptp1588_tx_last3_dat_fields[] = { + { PTP1588_TX_LAST3_DAT_DAT, 24, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t ptp1588_tx_last4_dat_fields[] = { + { PTP1588_TX_LAST4_DAT_DAT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t ptp1588_tx_mid_dat_fields[] = { + { PTP1588_TX_MID_DAT_DAT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t ptp1588_tx_packet_state_fields[] = { + { PTP1588_TX_PACKET_STATE_MSG_TYPE, 4, 16, 0x0000 }, + { PTP1588_TX_PACKET_STATE_PCK_TYPE, 3, 20, 0x0000 }, + { PTP1588_TX_PACKET_STATE_SEQ_ID, 16, 0, 0x0000 }, + { PTP1588_TX_PACKET_STATE_TEST_MARGIN, 7, 23, 0x0000 }, + { PTP1588_TX_PACKET_STATE_VALID, 1, 30, 0x0000 }, +}; + +static nt_fpga_field_init_t ptp1588_tx_status_fields[] = { + { PTP1588_TX_STATUS_DB_ERR, 1, 10, 1 }, + { PTP1588_TX_STATUS_DB_FULL, 1, 9, 1 }, + { PTP1588_TX_STATUS_FIFO_STATUS, 9, 0, 0 }, + { PTP1588_TX_STATUS_RDY, 1, 11, 1 }, +}; + +static nt_fpga_field_init_t ptp1588_tx_timestamp_ns_fields[] = { + { PTP1588_TX_TIMESTAMP_NS_TIMESTAMP, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t ptp1588_tx_timestamp_sec_fields[] = { + { PTP1588_TX_TIMESTAMP_SEC_TIMESTAMP, 32, 0, 0x0000 }, +}; + +static nt_fpga_register_init_t ptp1588_registers[] = { + { PTP1588_CONF, 0, 27, REGISTER_TYPE_MIXED, 3072, 17, + ptp1588_conf_fields + }, + { PTP1588_GP_DATA, 20, 10, REGISTER_TYPE_RW, 0, 2, + ptp1588_gp_data_fields + }, + { PTP1588_GP_DATA_LH, 22, 10, REGISTER_TYPE_RO, 0, 2, + ptp1588_gp_data_lh_fields + }, + { PTP1588_GP_DATA_LL, 21, 10, REGISTER_TYPE_RO, 1023, 2, + ptp1588_gp_data_ll_fields + }, + { PTP1588_GP_OE, 19, 10, REGISTER_TYPE_WO, 0, 2, ptp1588_gp_oe_fields }, + { PTP1588_MAC_INBAND_STAT, 3, 4, REGISTER_TYPE_RO, 0, 3, + ptp1588_mac_inband_stat_fields + }, + { PTP1588_MAC_MI_CONF, 17, 18, REGISTER_TYPE_MIXED, 131072, 3, + ptp1588_mac_mi_conf_fields + }, + { PTP1588_MAC_MI_DATA, 18, 32, REGISTER_TYPE_RW, 0, 1, + ptp1588_mac_mi_data_fields + }, + { PTP1588_RX_HOST_ADR_LSB, 8, 32, REGISTER_TYPE_WO, 0, 1, + ptp1588_rx_host_adr_lsb_fields + }, + { PTP1588_RX_HOST_ADR_MSB, 9, 32, REGISTER_TYPE_WO, 0, 1, + ptp1588_rx_host_adr_msb_fields + }, + { PTP1588_RX_HOST_CONF, 7, 13, REGISTER_TYPE_RW, 0, 3, + ptp1588_rx_host_conf_fields + }, + { PTP1588_STAT, 6, 32, REGISTER_TYPE_RO, 0, 1, ptp1588_stat_fields }, + { PTP1588_STAT_CONF, 5, 6, REGISTER_TYPE_WO, 0, 2, + ptp1588_stat_conf_fields + }, + { PTP1588_TX_FIRST_DAT, 10, 32, REGISTER_TYPE_WO, 0, 1, + ptp1588_tx_first_dat_fields + }, + { PTP1588_TX_LAST1_DAT, 12, 8, REGISTER_TYPE_WO, 0, 1, + ptp1588_tx_last1_dat_fields + }, + { PTP1588_TX_LAST2_DAT, 13, 16, REGISTER_TYPE_WO, 0, 1, + ptp1588_tx_last2_dat_fields + }, + { PTP1588_TX_LAST3_DAT, 14, 24, REGISTER_TYPE_WO, 0, 1, + ptp1588_tx_last3_dat_fields + }, + { PTP1588_TX_LAST4_DAT, 15, 32, REGISTER_TYPE_WO, 0, 1, + ptp1588_tx_last4_dat_fields + }, + { PTP1588_TX_MID_DAT, 11, 32, REGISTER_TYPE_WO, 0, 1, + ptp1588_tx_mid_dat_fields + }, + { PTP1588_TX_PACKET_STATE, 4, 31, REGISTER_TYPE_RO, 0, 5, + ptp1588_tx_packet_state_fields + }, + { PTP1588_TX_STATUS, 16, 12, REGISTER_TYPE_RO, 3584, 4, + ptp1588_tx_status_fields + }, + { PTP1588_TX_TIMESTAMP_NS, 2, 32, REGISTER_TYPE_RO, 0, 1, + ptp1588_tx_timestamp_ns_fields + }, + { PTP1588_TX_TIMESTAMP_SEC, 1, 32, REGISTER_TYPE_RO, 0, 1, + ptp1588_tx_timestamp_sec_fields + }, +}; + +static nt_fpga_field_init_t qsl_qen_ctrl_fields[] = { + { QSL_QEN_CTRL_ADR, 5, 0, 0x0000 }, + { QSL_QEN_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t qsl_qen_data_fields[] = { + { QSL_QEN_DATA_EN, 4, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t qsl_qst_ctrl_fields[] = { + { QSL_QST_CTRL_ADR, 12, 0, 0x0000 }, + { QSL_QST_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t qsl_qst_data_fields[] = { + { QSL_QST_DATA_LRE, 1, 9, 0x0000 }, + { QSL_QST_DATA_QEN, 1, 7, 0x0000 }, + { QSL_QST_DATA_QUEUE, 7, 0, 0x0000 }, + { QSL_QST_DATA_TCI, 16, 10, 0x0000 }, + { QSL_QST_DATA_TX_PORT, 1, 8, 0x0000 }, + { QSL_QST_DATA_VEN, 1, 26, 0x0000 }, +}; + +static nt_fpga_field_init_t qsl_rcp_ctrl_fields[] = { + { QSL_RCP_CTRL_ADR, 5, 0, 0x0000 }, + { QSL_RCP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t qsl_rcp_data_fields[] = { + { QSL_RCP_DATA_DISCARD, 1, 0, 0x0000 }, + { QSL_RCP_DATA_DROP, 2, 1, 0x0000 }, + { QSL_RCP_DATA_LR, 2, 51, 0x0000 }, + { QSL_RCP_DATA_TBL_HI, 12, 15, 0x0000 }, + { QSL_RCP_DATA_TBL_IDX, 12, 27, 0x0000 }, + { QSL_RCP_DATA_TBL_LO, 12, 3, 0x0000 }, + { QSL_RCP_DATA_TBL_MSK, 12, 39, 0x0000 }, + { QSL_RCP_DATA_TSA, 1, 53, 0x0000 }, + { QSL_RCP_DATA_VLI, 2, 54, 0x0000 }, +}; + +static nt_fpga_field_init_t qsl_unmq_ctrl_fields[] = { + { QSL_UNMQ_CTRL_ADR, 1, 0, 0x0000 }, + { QSL_UNMQ_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t qsl_unmq_data_fields[] = { + { QSL_UNMQ_DATA_DEST_QUEUE, 7, 0, 0x0000 }, + { QSL_UNMQ_DATA_EN, 1, 7, 0x0000 }, +}; + +static nt_fpga_register_init_t qsl_registers[] = { + { QSL_QEN_CTRL, 4, 32, REGISTER_TYPE_WO, 0, 2, qsl_qen_ctrl_fields }, + { QSL_QEN_DATA, 5, 4, REGISTER_TYPE_WO, 0, 1, qsl_qen_data_fields }, + { QSL_QST_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2, qsl_qst_ctrl_fields }, + { QSL_QST_DATA, 3, 27, REGISTER_TYPE_WO, 0, 6, qsl_qst_data_fields }, + { QSL_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, qsl_rcp_ctrl_fields }, + { QSL_RCP_DATA, 1, 56, REGISTER_TYPE_WO, 0, 9, qsl_rcp_data_fields }, + { QSL_UNMQ_CTRL, 6, 32, REGISTER_TYPE_WO, 0, 2, qsl_unmq_ctrl_fields }, + { QSL_UNMQ_DATA, 7, 8, REGISTER_TYPE_WO, 0, 2, qsl_unmq_data_fields }, +}; + +static nt_fpga_field_init_t qspi_cr_fields[] = { + { QSPI_CR_CPHA, 1, 4, 0 }, { QSPI_CR_CPOL, 1, 3, 0 }, + { QSPI_CR_LOOP, 1, 0, 0 }, { QSPI_CR_LSBF, 1, 9, 0 }, + { QSPI_CR_MSSAE, 1, 7, 1 }, { QSPI_CR_MST, 1, 2, 0 }, + { QSPI_CR_MTI, 1, 8, 1 }, { QSPI_CR_RXFIFO_RST, 1, 6, 0 }, + { QSPI_CR_SPE, 1, 1, 0 }, { QSPI_CR_TXFIFO_RST, 1, 5, 0 }, +}; + +static nt_fpga_field_init_t qspi_dgie_fields[] = { + { QSPI_DGIE_GIE, 1, 31, 0 }, +}; + +static nt_fpga_field_init_t qspi_drr_fields[] = { + { QSPI_DRR_DATA_VAL, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t qspi_dtr_fields[] = { + { QSPI_DTR_DATA_VAL, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t qspi_ier_fields[] = { + { QSPI_IER_CMD_ERR, 1, 13, 0 }, { QSPI_IER_CPOL_CPHA_ERR, 1, 9, 0 }, + { QSPI_IER_DRR_FULL, 1, 4, 0 }, { QSPI_IER_DRR_NEMPTY, 1, 8, 0 }, + { QSPI_IER_DRR_OR, 1, 5, 0 }, { QSPI_IER_DTR_EMPTY, 1, 2, 0 }, + { QSPI_IER_DTR_UR, 1, 3, 0 }, { QSPI_IER_LOOP_ERR, 1, 12, 0 }, + { QSPI_IER_MODF, 1, 0, 0 }, { QSPI_IER_MSB_ERR, 1, 11, 0 }, + { QSPI_IER_SLV_ERR, 1, 10, 0 }, { QSPI_IER_SLV_MODF, 1, 1, 0 }, + { QSPI_IER_SLV_MS, 1, 7, 0 }, { QSPI_IER_TXFIFO_HEMPTY, 1, 6, 0 }, +}; + +static nt_fpga_field_init_t qspi_isr_fields[] = { + { QSPI_ISR_CMD_ERR, 1, 13, 0 }, { QSPI_ISR_CPOL_CPHA_ERR, 1, 9, 0 }, + { QSPI_ISR_DRR_FULL, 1, 4, 0 }, { QSPI_ISR_DRR_NEMPTY, 1, 8, 0 }, + { QSPI_ISR_DRR_OR, 1, 5, 0 }, { QSPI_ISR_DTR_EMPTY, 1, 2, 0 }, + { QSPI_ISR_DTR_UR, 1, 3, 0 }, { QSPI_ISR_LOOP_ERR, 1, 12, 0 }, + { QSPI_ISR_MODF, 1, 0, 0 }, { QSPI_ISR_MSB_ERR, 1, 11, 0 }, + { QSPI_ISR_SLV_ERR, 1, 10, 0 }, { QSPI_ISR_SLV_MODF, 1, 1, 0 }, + { QSPI_ISR_SLV_MS, 1, 7, 0 }, { QSPI_ISR_TXFIFO_HEMPTY, 1, 6, 0 }, +}; + +static nt_fpga_field_init_t qspi_rx_fifo_ocy_fields[] = { + { QSPI_RX_FIFO_OCY_OCY_VAL, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t qspi_sr_fields[] = { + { QSPI_SR_CMD_ERR, 1, 10, 0 }, { QSPI_SR_CPOL_CPHA_ERR, 1, 6, 0 }, + { QSPI_SR_LOOP_ERR, 1, 9, 0 }, { QSPI_SR_MODF, 1, 4, 0 }, + { QSPI_SR_MSB_ERR, 1, 8, 0 }, { QSPI_SR_RXEMPTY, 1, 0, 1 }, + { QSPI_SR_RXFULL, 1, 1, 0 }, { QSPI_SR_SLVMS, 1, 5, 1 }, + { QSPI_SR_SLV_ERR, 1, 7, 0 }, { QSPI_SR_TXEMPTY, 1, 2, 1 }, + { QSPI_SR_TXFULL, 1, 3, 0 }, +}; + +static nt_fpga_field_init_t qspi_srr_fields[] = { + { QSPI_SRR_RST, 4, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t qspi_ssr_fields[] = { + { QSPI_SSR_SEL_SLV, 32, 0, 4294967295 }, +}; + +static nt_fpga_field_init_t qspi_tx_fifo_ocy_fields[] = { + { QSPI_TX_FIFO_OCY_OCY_VAL, 32, 0, 0 }, +}; + +static nt_fpga_register_init_t qspi_registers[] = { + { QSPI_CR, 24, 10, REGISTER_TYPE_RW, 384, 10, qspi_cr_fields }, + { QSPI_DGIE, 7, 32, REGISTER_TYPE_RW, 0, 1, qspi_dgie_fields }, + { QSPI_DRR, 27, 32, REGISTER_TYPE_RO, 0, 1, qspi_drr_fields }, + { QSPI_DTR, 26, 32, REGISTER_TYPE_WO, 0, 1, qspi_dtr_fields }, + { QSPI_IER, 10, 14, REGISTER_TYPE_RW, 0, 14, qspi_ier_fields }, + { QSPI_ISR, 8, 14, REGISTER_TYPE_RW, 0, 14, qspi_isr_fields }, + { QSPI_RX_FIFO_OCY, 30, 32, REGISTER_TYPE_RO, 0, 1, + qspi_rx_fifo_ocy_fields + }, + { QSPI_SR, 25, 11, REGISTER_TYPE_RO, 37, 11, qspi_sr_fields }, + { QSPI_SRR, 16, 4, REGISTER_TYPE_WO, 0, 1, qspi_srr_fields }, + { QSPI_SSR, 28, 32, REGISTER_TYPE_RW, 4294967295, 1, qspi_ssr_fields }, + { QSPI_TX_FIFO_OCY, 29, 32, REGISTER_TYPE_RO, 0, 1, + qspi_tx_fifo_ocy_fields + }, +}; + +static nt_fpga_field_init_t rac_dbg_ctrl_fields[] = { + { RAC_DBG_CTRL_C, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t rac_dbg_data_fields[] = { + { RAC_DBG_DATA_D, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t rac_rab_buf_free_fields[] = { + { RAC_RAB_BUF_FREE_IB_FREE, 9, 0, 511 }, + { RAC_RAB_BUF_FREE_IB_OVF, 1, 12, 0 }, + { RAC_RAB_BUF_FREE_OB_FREE, 9, 16, 511 }, + { RAC_RAB_BUF_FREE_OB_OVF, 1, 28, 0 }, + { RAC_RAB_BUF_FREE_TIMEOUT, 1, 31, 0 }, +}; + +static nt_fpga_field_init_t rac_rab_buf_used_fields[] = { + { RAC_RAB_BUF_USED_FLUSH, 1, 31, 0 }, + { RAC_RAB_BUF_USED_IB_USED, 9, 0, 0 }, + { RAC_RAB_BUF_USED_OB_USED, 9, 16, 0 }, +}; + +static nt_fpga_field_init_t rac_rab_dma_ib_hi_fields[] = { + { RAC_RAB_DMA_IB_HI_PHYADDR, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t rac_rab_dma_ib_lo_fields[] = { + { RAC_RAB_DMA_IB_LO_PHYADDR, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t rac_rab_dma_ib_rd_fields[] = { + { RAC_RAB_DMA_IB_RD_PTR, 16, 0, 0 }, +}; + +static nt_fpga_field_init_t rac_rab_dma_ib_wr_fields[] = { + { RAC_RAB_DMA_IB_WR_PTR, 16, 0, 0 }, +}; + +static nt_fpga_field_init_t rac_rab_dma_ob_hi_fields[] = { + { RAC_RAB_DMA_OB_HI_PHYADDR, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t rac_rab_dma_ob_lo_fields[] = { + { RAC_RAB_DMA_OB_LO_PHYADDR, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t rac_rab_dma_ob_wr_fields[] = { + { RAC_RAB_DMA_OB_WR_PTR, 16, 0, 0 }, +}; + +static nt_fpga_field_init_t rac_rab_ib_data_fields[] = { + { RAC_RAB_IB_DATA_D, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t rac_rab_init_fields[] = { + { RAC_RAB_INIT_RAB, 3, 0, 7 }, +}; + +static nt_fpga_field_init_t rac_rab_ob_data_fields[] = { + { RAC_RAB_OB_DATA_D, 32, 0, 0x0000 }, +}; + +static nt_fpga_register_init_t rac_registers[] = { + { RAC_DBG_CTRL, 4200, 32, REGISTER_TYPE_RW, 0, 1, rac_dbg_ctrl_fields }, + { RAC_DBG_DATA, 4208, 32, REGISTER_TYPE_RW, 0, 1, rac_dbg_data_fields }, + { RAC_RAB_BUF_FREE, 4176, 32, REGISTER_TYPE_MIXED, 33489407, 5, + rac_rab_buf_free_fields + }, + { RAC_RAB_BUF_USED, 4184, 32, REGISTER_TYPE_MIXED, 0, 3, + rac_rab_buf_used_fields + }, + { RAC_RAB_DMA_IB_HI, 4360, 32, REGISTER_TYPE_WO, 0, 1, + rac_rab_dma_ib_hi_fields + }, + { RAC_RAB_DMA_IB_LO, 4352, 32, REGISTER_TYPE_WO, 0, 1, + rac_rab_dma_ib_lo_fields + }, + { RAC_RAB_DMA_IB_RD, 4424, 16, REGISTER_TYPE_RO, 0, 1, + rac_rab_dma_ib_rd_fields + }, + { RAC_RAB_DMA_IB_WR, 4416, 16, REGISTER_TYPE_WO, 0, 1, + rac_rab_dma_ib_wr_fields + }, + { RAC_RAB_DMA_OB_HI, 4376, 32, REGISTER_TYPE_WO, 0, 1, + rac_rab_dma_ob_hi_fields + }, + { RAC_RAB_DMA_OB_LO, 4368, 32, REGISTER_TYPE_WO, 0, 1, + rac_rab_dma_ob_lo_fields + }, + { RAC_RAB_DMA_OB_WR, 4480, 16, REGISTER_TYPE_RO, 0, 1, + rac_rab_dma_ob_wr_fields + }, + { RAC_RAB_IB_DATA, 4160, 32, REGISTER_TYPE_WO, 0, 1, + rac_rab_ib_data_fields + }, + { RAC_RAB_INIT, 4192, 3, REGISTER_TYPE_RW, 7, 1, rac_rab_init_fields }, + { RAC_RAB_OB_DATA, 4168, 32, REGISTER_TYPE_RC1, 0, 1, + rac_rab_ob_data_fields + }, +}; + +static nt_fpga_field_init_t rfd_ctrl_fields[] = { + { RFD_CTRL_CFP, 1, 2, 1 }, + { RFD_CTRL_ISL, 1, 0, 1 }, + { RFD_CTRL_PWMCW, 1, 1, 1 }, +}; + +static nt_fpga_field_init_t rfd_max_frame_size_fields[] = { + { RFD_MAX_FRAME_SIZE_MAX, 14, 0, 9018 }, +}; + +static nt_fpga_field_init_t rfd_tnl_vlan_fields[] = { + { RFD_TNL_VLAN_TPID0, 16, 0, 33024 }, + { RFD_TNL_VLAN_TPID1, 16, 16, 33024 }, +}; + +static nt_fpga_field_init_t rfd_vlan_fields[] = { + { RFD_VLAN_TPID0, 16, 0, 33024 }, + { RFD_VLAN_TPID1, 16, 16, 33024 }, +}; + +static nt_fpga_field_init_t rfd_vxlan_fields[] = { + { RFD_VXLAN_DP0, 16, 0, 4789 }, + { RFD_VXLAN_DP1, 16, 16, 4789 }, +}; + +static nt_fpga_register_init_t rfd_registers[] = { + { RFD_CTRL, 0, 3, REGISTER_TYPE_WO, 7, 3, rfd_ctrl_fields }, + { RFD_MAX_FRAME_SIZE, 1, 14, REGISTER_TYPE_WO, 9018, 1, + rfd_max_frame_size_fields + }, + { RFD_TNL_VLAN, 3, 32, REGISTER_TYPE_WO, 2164293888, 2, + rfd_tnl_vlan_fields + }, + { RFD_VLAN, 2, 32, REGISTER_TYPE_WO, 2164293888, 2, rfd_vlan_fields }, + { RFD_VXLAN, 4, 32, REGISTER_TYPE_WO, 313856693, 2, rfd_vxlan_fields }, +}; + +static nt_fpga_field_init_t rmc_ctrl_fields[] = { + { RMC_CTRL_BLOCK_KEEPA, 1, 1, 1 }, + { RMC_CTRL_BLOCK_MAC_PORT, 2, 8, 3 }, + { RMC_CTRL_BLOCK_RPP_SLICE, 8, 10, 0 }, + { RMC_CTRL_BLOCK_STATT, 1, 0, 1 }, + { RMC_CTRL_LAG_PHY_ODD_EVEN, 1, 24, 0 }, +}; + +static nt_fpga_field_init_t rmc_dbg_fields[] = { + { RMC_DBG_MERGE, 31, 0, 0 }, +}; + +static nt_fpga_field_init_t rmc_mac_if_fields[] = { + { RMC_MAC_IF_ERR, 31, 0, 0 }, +}; + +static nt_fpga_field_init_t rmc_status_fields[] = { + { RMC_STATUS_DESCR_FIFO_OF, 1, 16, 0 }, + { RMC_STATUS_SF_RAM_OF, 1, 0, 0 }, +}; + +static nt_fpga_register_init_t rmc_registers[] = { + { RMC_CTRL, 0, 25, REGISTER_TYPE_RW, 771, 5, rmc_ctrl_fields }, + { RMC_DBG, 2, 31, REGISTER_TYPE_RO, 0, 1, rmc_dbg_fields }, + { RMC_MAC_IF, 3, 31, REGISTER_TYPE_RO, 0, 1, rmc_mac_if_fields }, + { RMC_STATUS, 1, 17, REGISTER_TYPE_RO, 0, 2, rmc_status_fields }, +}; + +static nt_fpga_field_init_t rpl_ext_ctrl_fields[] = { + { RPL_EXT_CTRL_ADR, 10, 0, 0x0000 }, + { RPL_EXT_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t rpl_ext_data_fields[] = { + { RPL_EXT_DATA_RPL_PTR, 12, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t rpl_rcp_ctrl_fields[] = { + { RPL_RCP_CTRL_ADR, 4, 0, 0x0000 }, + { RPL_RCP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t rpl_rcp_data_fields[] = { + { RPL_RCP_DATA_DYN, 5, 0, 0x0000 }, + { RPL_RCP_DATA_EXT_PRIO, 1, 35, 0x0000 }, + { RPL_RCP_DATA_LEN, 8, 15, 0x0000 }, + { RPL_RCP_DATA_OFS, 10, 5, 0x0000 }, + { RPL_RCP_DATA_RPL_PTR, 12, 23, 0x0000 }, +}; + +static nt_fpga_field_init_t rpl_rpl_ctrl_fields[] = { + { RPL_RPL_CTRL_ADR, 12, 0, 0x0000 }, + { RPL_RPL_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t rpl_rpl_data_fields[] = { + { RPL_RPL_DATA_VALUE, 128, 0, 0x0000 }, +}; + +static nt_fpga_register_init_t rpl_registers[] = { + { RPL_EXT_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2, rpl_ext_ctrl_fields }, + { RPL_EXT_DATA, 3, 12, REGISTER_TYPE_WO, 0, 1, rpl_ext_data_fields }, + { RPL_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, rpl_rcp_ctrl_fields }, + { RPL_RCP_DATA, 1, 36, REGISTER_TYPE_WO, 0, 5, rpl_rcp_data_fields }, + { RPL_RPL_CTRL, 4, 32, REGISTER_TYPE_WO, 0, 2, rpl_rpl_ctrl_fields }, + { RPL_RPL_DATA, 5, 128, REGISTER_TYPE_WO, 0, 1, rpl_rpl_data_fields }, +}; + +static nt_fpga_field_init_t rpp_lr_ifr_rcp_ctrl_fields[] = { + { RPP_LR_IFR_RCP_CTRL_ADR, 4, 0, 0x0000 }, + { RPP_LR_IFR_RCP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t rpp_lr_ifr_rcp_data_fields[] = { + { RPP_LR_IFR_RCP_DATA_EN, 1, 0, 0x0000 }, + { RPP_LR_IFR_RCP_DATA_MTU, 14, 1, 0x0000 }, +}; + +static nt_fpga_field_init_t rpp_lr_rcp_ctrl_fields[] = { + { RPP_LR_RCP_CTRL_ADR, 4, 0, 0x0000 }, + { RPP_LR_RCP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t rpp_lr_rcp_data_fields[] = { + { RPP_LR_RCP_DATA_EXP, 14, 0, 0x0000 }, +}; + +static nt_fpga_register_init_t rpp_lr_registers[] = { + { RPP_LR_IFR_RCP_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2, + rpp_lr_ifr_rcp_ctrl_fields + }, + { RPP_LR_IFR_RCP_DATA, 3, 15, REGISTER_TYPE_WO, 0, 2, + rpp_lr_ifr_rcp_data_fields + }, + { RPP_LR_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, + rpp_lr_rcp_ctrl_fields + }, + { RPP_LR_RCP_DATA, 1, 14, REGISTER_TYPE_WO, 0, 1, + rpp_lr_rcp_data_fields + }, +}; + +static nt_fpga_field_init_t rst9563_ctrl_fields[] = { + { RST9563_CTRL_PTP_MMCM_CLKSEL, 1, 2, 1 }, + { RST9563_CTRL_TS_CLKSEL, 1, 1, 1 }, + { RST9563_CTRL_TS_CLKSEL_OVERRIDE, 1, 0, 1 }, +}; + +static nt_fpga_field_init_t rst9563_power_fields[] = { + { RST9563_POWER_PU_NSEB, 1, 1, 0 }, + { RST9563_POWER_PU_PHY, 1, 0, 0 }, +}; + +static nt_fpga_field_init_t rst9563_rst_fields[] = { + { RST9563_RST_CORE_MMCM, 1, 15, 0 }, { RST9563_RST_DDR4, 3, 3, 7 }, + { RST9563_RST_MAC_RX, 2, 9, 3 }, { RST9563_RST_PERIPH, 1, 13, 0 }, + { RST9563_RST_PHY, 2, 7, 3 }, { RST9563_RST_PTP, 1, 11, 1 }, + { RST9563_RST_PTP_MMCM, 1, 16, 0 }, { RST9563_RST_RPP, 1, 2, 1 }, + { RST9563_RST_SDC, 1, 6, 1 }, { RST9563_RST_SYS, 1, 0, 1 }, + { RST9563_RST_SYS_MMCM, 1, 14, 0 }, { RST9563_RST_TMC, 1, 1, 1 }, + { RST9563_RST_TS, 1, 12, 1 }, { RST9563_RST_TS_MMCM, 1, 17, 0 }, +}; + +static nt_fpga_field_init_t rst9563_stat_fields[] = { + { RST9563_STAT_CORE_MMCM_LOCKED, 1, 5, 0x0000 }, + { RST9563_STAT_DDR4_MMCM_LOCKED, 1, 2, 0x0000 }, + { RST9563_STAT_DDR4_PLL_LOCKED, 1, 3, 0x0000 }, + { RST9563_STAT_PTP_MMCM_LOCKED, 1, 0, 0x0000 }, + { RST9563_STAT_SYS_MMCM_LOCKED, 1, 4, 0x0000 }, + { RST9563_STAT_TS_MMCM_LOCKED, 1, 1, 0x0000 }, +}; + +static nt_fpga_field_init_t rst9563_sticky_fields[] = { + { RST9563_STICKY_CORE_MMCM_UNLOCKED, 1, 5, 0x0000 }, + { RST9563_STICKY_DDR4_MMCM_UNLOCKED, 1, 2, 0x0000 }, + { RST9563_STICKY_DDR4_PLL_UNLOCKED, 1, 3, 0x0000 }, + { RST9563_STICKY_PTP_MMCM_UNLOCKED, 1, 0, 0x0000 }, + { RST9563_STICKY_SYS_MMCM_UNLOCKED, 1, 4, 0x0000 }, + { RST9563_STICKY_TS_MMCM_UNLOCKED, 1, 1, 0x0000 }, +}; + +static nt_fpga_register_init_t rst9563_registers[] = { + { RST9563_CTRL, 1, 3, REGISTER_TYPE_RW, 7, 3, rst9563_ctrl_fields }, + { RST9563_POWER, 4, 2, REGISTER_TYPE_RW, 0, 2, rst9563_power_fields }, + { RST9563_RST, 0, 18, REGISTER_TYPE_RW, 8191, 14, rst9563_rst_fields }, + { RST9563_STAT, 2, 6, REGISTER_TYPE_RO, 0, 6, rst9563_stat_fields }, + { RST9563_STICKY, 3, 6, REGISTER_TYPE_RC1, 0, 6, + rst9563_sticky_fields + }, +}; + +static nt_fpga_field_init_t slc_rcp_ctrl_fields[] = { + { SLC_RCP_CTRL_ADR, 6, 0, 0x0000 }, + { SLC_RCP_CTRL_CNT, 16, 16, 0x0000 }, +}; + +static nt_fpga_field_init_t slc_rcp_data_fields[] = { + { SLC_RCP_DATA_PCAP, 1, 35, 0x0000 }, + { SLC_RCP_DATA_TAIL_DYN, 5, 15, 0x0000 }, + { SLC_RCP_DATA_TAIL_OFS, 15, 20, 0x0000 }, + { SLC_RCP_DATA_TAIL_SLC_EN, 1, 14, 0x0000 }, +}; + +static nt_fpga_register_init_t slc_registers[] = { + { SLC_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, slc_rcp_ctrl_fields }, + { SLC_RCP_DATA, 1, 36, REGISTER_TYPE_WO, 0, 4, slc_rcp_data_fields }, +}; + +static nt_fpga_field_init_t spim_cfg_fields[] = { + { SPIM_CFG_PRE, 3, 0, 5 }, +}; + +static nt_fpga_field_init_t spim_cr_fields[] = { + { SPIM_CR_EN, 1, 1, 0 }, + { SPIM_CR_LOOP, 1, 0, 0 }, + { SPIM_CR_RXRST, 1, 3, 0 }, + { SPIM_CR_TXRST, 1, 2, 0 }, +}; + +static nt_fpga_field_init_t spim_drr_fields[] = { + { SPIM_DRR_DRR, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t spim_dtr_fields[] = { + { SPIM_DTR_DTR, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t spim_sr_fields[] = { + { SPIM_SR_DONE, 1, 0, 0 }, { SPIM_SR_RXEMPTY, 1, 2, 1 }, + { SPIM_SR_RXFULL, 1, 4, 0 }, { SPIM_SR_RXLVL, 8, 16, 0 }, + { SPIM_SR_TXEMPTY, 1, 1, 1 }, { SPIM_SR_TXFULL, 1, 3, 0 }, + { SPIM_SR_TXLVL, 8, 8, 0 }, +}; + +static nt_fpga_field_init_t spim_srr_fields[] = { + { SPIM_SRR_RST, 4, 0, 0 }, +}; + +static nt_fpga_register_init_t spim_registers[] = { + { SPIM_CFG, 5, 3, REGISTER_TYPE_WO, 5, 1, spim_cfg_fields }, + { SPIM_CR, 1, 4, REGISTER_TYPE_WO, 0, 4, spim_cr_fields }, + { SPIM_DRR, 4, 32, REGISTER_TYPE_RO, 0, 1, spim_drr_fields }, + { SPIM_DTR, 3, 32, REGISTER_TYPE_WO, 0, 1, spim_dtr_fields }, + { SPIM_SR, 2, 24, REGISTER_TYPE_RO, 6, 7, spim_sr_fields }, + { SPIM_SRR, 0, 4, REGISTER_TYPE_WO, 0, 1, spim_srr_fields }, +}; + +static nt_fpga_field_init_t spis_cr_fields[] = { + { SPIS_CR_DEBUG, 1, 4, 0 }, { SPIS_CR_EN, 1, 1, 0 }, + { SPIS_CR_LOOP, 1, 0, 0 }, { SPIS_CR_RXRST, 1, 3, 0 }, + { SPIS_CR_TXRST, 1, 2, 0 }, +}; + +static nt_fpga_field_init_t spis_drr_fields[] = { + { SPIS_DRR_DRR, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t spis_dtr_fields[] = { + { SPIS_DTR_DTR, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t spis_ram_ctrl_fields[] = { + { SPIS_RAM_CTRL_ADR, 6, 0, 0 }, + { SPIS_RAM_CTRL_CNT, 6, 6, 0 }, +}; + +static nt_fpga_field_init_t spis_ram_data_fields[] = { + { SPIS_RAM_DATA_DATA, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t spis_sr_fields[] = { + { SPIS_SR_DONE, 1, 0, 0 }, { SPIS_SR_FRAME_ERR, 1, 24, 0 }, + { SPIS_SR_READ_ERR, 1, 25, 0 }, { SPIS_SR_RXEMPTY, 1, 2, 1 }, + { SPIS_SR_RXFULL, 1, 4, 0 }, { SPIS_SR_RXLVL, 8, 16, 0 }, + { SPIS_SR_TXEMPTY, 1, 1, 1 }, { SPIS_SR_TXFULL, 1, 3, 0 }, + { SPIS_SR_TXLVL, 8, 8, 0 }, { SPIS_SR_WRITE_ERR, 1, 26, 0 }, +}; + +static nt_fpga_field_init_t spis_srr_fields[] = { + { SPIS_SRR_RST, 4, 0, 0 }, +}; + +static nt_fpga_register_init_t spis_registers[] = { + { SPIS_CR, 1, 5, REGISTER_TYPE_WO, 0, 5, spis_cr_fields }, + { SPIS_DRR, 4, 32, REGISTER_TYPE_RO, 0, 1, spis_drr_fields }, + { SPIS_DTR, 3, 32, REGISTER_TYPE_WO, 0, 1, spis_dtr_fields }, + { SPIS_RAM_CTRL, 5, 12, REGISTER_TYPE_RW, 0, 2, spis_ram_ctrl_fields }, + { SPIS_RAM_DATA, 6, 32, REGISTER_TYPE_RW, 0, 1, spis_ram_data_fields }, + { SPIS_SR, 2, 27, REGISTER_TYPE_RO, 6, 10, spis_sr_fields }, + { SPIS_SRR, 0, 4, REGISTER_TYPE_WO, 0, 1, spis_srr_fields }, +}; + +static nt_fpga_field_init_t sta_byte_fields[] = { + { STA_BYTE_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t sta_cfg_fields[] = { + { STA_CFG_CNT_CLEAR, 1, 1, 0 }, + { STA_CFG_DMA_ENA, 1, 0, 0 }, +}; + +static nt_fpga_field_init_t sta_cv_err_fields[] = { + { STA_CV_ERR_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t sta_fcs_err_fields[] = { + { STA_FCS_ERR_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t sta_host_adr_lsb_fields[] = { + { STA_HOST_ADR_LSB_LSB, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t sta_host_adr_msb_fields[] = { + { STA_HOST_ADR_MSB_MSB, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t sta_pckt_fields[] = { + { STA_PCKT_CNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t sta_status_fields[] = { + { STA_STATUS_STAT_TOGGLE_MISSED, 1, 0, 0x0000 }, +}; + +static nt_fpga_register_init_t sta_registers[] = { + { STA_BYTE, 4, 32, REGISTER_TYPE_RO, 0, 1, sta_byte_fields }, + { STA_CFG, 0, 2, REGISTER_TYPE_RW, 0, 2, sta_cfg_fields }, + { STA_CV_ERR, 5, 32, REGISTER_TYPE_RO, 0, 1, sta_cv_err_fields }, + { STA_FCS_ERR, 6, 32, REGISTER_TYPE_RO, 0, 1, sta_fcs_err_fields }, + { STA_HOST_ADR_LSB, 1, 32, REGISTER_TYPE_WO, 0, 1, + sta_host_adr_lsb_fields + }, + { STA_HOST_ADR_MSB, 2, 32, REGISTER_TYPE_WO, 0, 1, + sta_host_adr_msb_fields + }, + { STA_PCKT, 3, 32, REGISTER_TYPE_RO, 0, 1, sta_pckt_fields }, + { STA_STATUS, 7, 1, REGISTER_TYPE_RC1, 0, 1, sta_status_fields }, +}; + +static nt_fpga_field_init_t tempmon_alarms_fields[] = { + { TEMPMON_ALARMS_OT, 1, 1, 0x0000 }, + { TEMPMON_ALARMS_OT_OVERWR, 1, 2, 0 }, + { TEMPMON_ALARMS_OT_OVERWRVAL, 1, 3, 0 }, + { TEMPMON_ALARMS_TEMP, 1, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tempmon_stat_fields[] = { + { TEMPMON_STAT_TEMP, 12, 0, 0x0000 }, +}; + +static nt_fpga_register_init_t tempmon_registers[] = { + { TEMPMON_ALARMS, 1, 4, REGISTER_TYPE_MIXED, 0, 4, + tempmon_alarms_fields + }, + { TEMPMON_STAT, 0, 12, REGISTER_TYPE_RO, 0, 1, tempmon_stat_fields }, +}; + +static nt_fpga_field_init_t tint_ctrl_fields[] = { + { TINT_CTRL_INTERVAL, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t tint_status_fields[] = { + { TINT_STATUS_DELAYED, 8, 8, 0 }, + { TINT_STATUS_SKIPPED, 8, 0, 0 }, +}; + +static nt_fpga_register_init_t tint_registers[] = { + { TINT_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 1, tint_ctrl_fields }, + { TINT_STATUS, 1, 16, REGISTER_TYPE_RC1, 0, 2, tint_status_fields }, +}; + +static nt_fpga_field_init_t tmc_port_rpl_fields[] = { + { TMC_PORT_RPL_P0, 1, 0, 0 }, + { TMC_PORT_RPL_P1, 1, 1, 1 }, +}; + +static nt_fpga_register_init_t tmc_registers[] = { + { TMC_PORT_RPL, 0, 2, REGISTER_TYPE_WO, 2, 2, tmc_port_rpl_fields }, +}; + +static nt_fpga_field_init_t tsm_con0_config_fields[] = { + { TSM_CON0_CONFIG_BLIND, 5, 8, 9 }, + { TSM_CON0_CONFIG_DC_SRC, 3, 5, 0 }, + { TSM_CON0_CONFIG_PORT, 3, 0, 0 }, + { TSM_CON0_CONFIG_PPSIN_2_5V, 1, 13, 0 }, + { TSM_CON0_CONFIG_SAMPLE_EDGE, 2, 3, 2 }, +}; + +static nt_fpga_field_init_t tsm_con0_interface_fields[] = { + { TSM_CON0_INTERFACE_EX_TERM, 2, 0, 3 }, + { TSM_CON0_INTERFACE_IN_REF_PWM, 8, 12, 128 }, + { TSM_CON0_INTERFACE_PWM_ENA, 1, 2, 0 }, + { TSM_CON0_INTERFACE_RESERVED, 1, 3, 0 }, + { TSM_CON0_INTERFACE_VTERM_PWM, 8, 4, 0 }, +}; + +static nt_fpga_field_init_t tsm_con0_sample_hi_fields[] = { + { TSM_CON0_SAMPLE_HI_SEC, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con0_sample_lo_fields[] = { + { TSM_CON0_SAMPLE_LO_NS, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con1_config_fields[] = { + { TSM_CON1_CONFIG_BLIND, 5, 8, 9 }, + { TSM_CON1_CONFIG_DC_SRC, 3, 5, 0 }, + { TSM_CON1_CONFIG_PORT, 3, 0, 0 }, + { TSM_CON1_CONFIG_PPSIN_2_5V, 1, 13, 0 }, + { TSM_CON1_CONFIG_SAMPLE_EDGE, 2, 3, 2 }, +}; + +static nt_fpga_field_init_t tsm_con1_sample_hi_fields[] = { + { TSM_CON1_SAMPLE_HI_SEC, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con1_sample_lo_fields[] = { + { TSM_CON1_SAMPLE_LO_NS, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con2_config_fields[] = { + { TSM_CON2_CONFIG_BLIND, 5, 8, 9 }, + { TSM_CON2_CONFIG_DC_SRC, 3, 5, 0 }, + { TSM_CON2_CONFIG_PORT, 3, 0, 0 }, + { TSM_CON2_CONFIG_PPSIN_2_5V, 1, 13, 0 }, + { TSM_CON2_CONFIG_SAMPLE_EDGE, 2, 3, 2 }, +}; + +static nt_fpga_field_init_t tsm_con2_sample_hi_fields[] = { + { TSM_CON2_SAMPLE_HI_SEC, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con2_sample_lo_fields[] = { + { TSM_CON2_SAMPLE_LO_NS, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con3_config_fields[] = { + { TSM_CON3_CONFIG_BLIND, 5, 5, 26 }, + { TSM_CON3_CONFIG_PORT, 3, 0, 1 }, + { TSM_CON3_CONFIG_SAMPLE_EDGE, 2, 3, 1 }, +}; + +static nt_fpga_field_init_t tsm_con3_sample_hi_fields[] = { + { TSM_CON3_SAMPLE_HI_SEC, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con3_sample_lo_fields[] = { + { TSM_CON3_SAMPLE_LO_NS, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con4_config_fields[] = { + { TSM_CON4_CONFIG_BLIND, 5, 5, 26 }, + { TSM_CON4_CONFIG_PORT, 3, 0, 1 }, + { TSM_CON4_CONFIG_SAMPLE_EDGE, 2, 3, 1 }, +}; + +static nt_fpga_field_init_t tsm_con4_sample_hi_fields[] = { + { TSM_CON4_SAMPLE_HI_SEC, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con4_sample_lo_fields[] = { + { TSM_CON4_SAMPLE_LO_NS, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con5_config_fields[] = { + { TSM_CON5_CONFIG_BLIND, 5, 5, 26 }, + { TSM_CON5_CONFIG_PORT, 3, 0, 1 }, + { TSM_CON5_CONFIG_SAMPLE_EDGE, 2, 3, 1 }, +}; + +static nt_fpga_field_init_t tsm_con5_sample_hi_fields[] = { + { TSM_CON5_SAMPLE_HI_SEC, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con5_sample_lo_fields[] = { + { TSM_CON5_SAMPLE_LO_TIME, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con6_config_fields[] = { + { TSM_CON6_CONFIG_BLIND, 5, 5, 26 }, + { TSM_CON6_CONFIG_PORT, 3, 0, 1 }, + { TSM_CON6_CONFIG_SAMPLE_EDGE, 2, 3, 1 }, +}; + +static nt_fpga_field_init_t tsm_con6_sample_hi_fields[] = { + { TSM_CON6_SAMPLE_HI_SEC, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con6_sample_lo_fields[] = { + { TSM_CON6_SAMPLE_LO_NS, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con7_host_sample_hi_fields[] = { + { TSM_CON7_HOST_SAMPLE_HI_SEC, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_con7_host_sample_lo_fields[] = { + { TSM_CON7_HOST_SAMPLE_LO_NS, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_config_fields[] = { + { TSM_CONFIG_NTTS_SRC, 2, 5, 0 }, + { TSM_CONFIG_NTTS_SYNC, 1, 4, 0 }, + { TSM_CONFIG_TIMESET_EDGE, 2, 8, 1 }, + { TSM_CONFIG_TIMESET_SRC, 3, 10, 0 }, + { TSM_CONFIG_TIMESET_UP, 1, 7, 0 }, + { TSM_CONFIG_TS_FORMAT, 4, 0, 1 }, +}; + +static nt_fpga_field_init_t tsm_int_config_fields[] = { + { TSM_INT_CONFIG_AUTO_DISABLE, 1, 0, 0 }, + { TSM_INT_CONFIG_MASK, 19, 1, 0 }, +}; + +static nt_fpga_field_init_t tsm_int_stat_fields[] = { + { TSM_INT_STAT_CAUSE, 19, 1, 0 }, + { TSM_INT_STAT_ENABLE, 1, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_led_fields[] = { + { TSM_LED_LED0_BG_COLOR, 2, 3, 0 }, { TSM_LED_LED0_COLOR, 2, 1, 0 }, + { TSM_LED_LED0_MODE, 1, 0, 0 }, { TSM_LED_LED0_SRC, 4, 5, 0 }, + { TSM_LED_LED1_BG_COLOR, 2, 12, 0 }, { TSM_LED_LED1_COLOR, 2, 10, 0 }, + { TSM_LED_LED1_MODE, 1, 9, 0 }, { TSM_LED_LED1_SRC, 4, 14, 1 }, + { TSM_LED_LED2_BG_COLOR, 2, 21, 0 }, { TSM_LED_LED2_COLOR, 2, 19, 0 }, + { TSM_LED_LED2_MODE, 1, 18, 0 }, { TSM_LED_LED2_SRC, 4, 23, 2 }, +}; + +static nt_fpga_field_init_t tsm_ntts_config_fields[] = { + { TSM_NTTS_CONFIG_AUTO_HARDSET, 1, 5, 1 }, + { TSM_NTTS_CONFIG_EXT_CLK_ADJ, 1, 6, 0 }, + { TSM_NTTS_CONFIG_HIGH_SAMPLE, 1, 4, 0 }, + { TSM_NTTS_CONFIG_TS_SRC_FORMAT, 4, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_ntts_ext_stat_fields[] = { + { TSM_NTTS_EXT_STAT_MASTER_ID, 8, 16, 0x0000 }, + { TSM_NTTS_EXT_STAT_MASTER_REV, 8, 24, 0x0000 }, + { TSM_NTTS_EXT_STAT_MASTER_STAT, 16, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_ntts_limit_hi_fields[] = { + { TSM_NTTS_LIMIT_HI_SEC, 16, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_ntts_limit_lo_fields[] = { + { TSM_NTTS_LIMIT_LO_NS, 32, 0, 100000 }, +}; + +static nt_fpga_field_init_t tsm_ntts_offset_fields[] = { + { TSM_NTTS_OFFSET_NS, 30, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_ntts_sample_hi_fields[] = { + { TSM_NTTS_SAMPLE_HI_SEC, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_ntts_sample_lo_fields[] = { + { TSM_NTTS_SAMPLE_LO_NS, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_ntts_stat_fields[] = { + { TSM_NTTS_STAT_NTTS_VALID, 1, 0, 0 }, + { TSM_NTTS_STAT_SIGNAL_LOST, 8, 1, 0 }, + { TSM_NTTS_STAT_SYNC_LOST, 8, 9, 0 }, +}; + +static nt_fpga_field_init_t tsm_ntts_ts_t0_hi_fields[] = { + { TSM_NTTS_TS_T0_HI_TIME, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_ntts_ts_t0_lo_fields[] = { + { TSM_NTTS_TS_T0_LO_TIME, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_ntts_ts_t0_offset_fields[] = { + { TSM_NTTS_TS_T0_OFFSET_COUNT, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_pb_ctrl_fields[] = { + { TSM_PB_CTRL_INSTMEM_WR, 1, 1, 0 }, + { TSM_PB_CTRL_RST, 1, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_pb_instmem_fields[] = { + { TSM_PB_INSTMEM_MEM_ADDR, 14, 0, 0 }, + { TSM_PB_INSTMEM_MEM_DATA, 18, 14, 0 }, +}; + +static nt_fpga_field_init_t tsm_pi_ctrl_i_fields[] = { + { TSM_PI_CTRL_I_VAL, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_pi_ctrl_ki_fields[] = { + { TSM_PI_CTRL_KI_GAIN, 24, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_pi_ctrl_kp_fields[] = { + { TSM_PI_CTRL_KP_GAIN, 24, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_pi_ctrl_shl_fields[] = { + { TSM_PI_CTRL_SHL_VAL, 4, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_stat_fields[] = { + { TSM_STAT_HARD_SYNC, 8, 8, 0 }, { TSM_STAT_LINK_CON0, 1, 0, 0 }, + { TSM_STAT_LINK_CON1, 1, 1, 0 }, { TSM_STAT_LINK_CON2, 1, 2, 0 }, + { TSM_STAT_LINK_CON3, 1, 3, 0 }, { TSM_STAT_LINK_CON4, 1, 4, 0 }, + { TSM_STAT_LINK_CON5, 1, 5, 0 }, { TSM_STAT_NTTS_INSYNC, 1, 6, 0 }, + { TSM_STAT_PTP_MI_PRESENT, 1, 7, 0 }, +}; + +static nt_fpga_field_init_t tsm_timer_ctrl_fields[] = { + { TSM_TIMER_CTRL_TIMER_EN_T0, 1, 0, 0 }, + { TSM_TIMER_CTRL_TIMER_EN_T1, 1, 1, 0 }, +}; + +static nt_fpga_field_init_t tsm_timer_t0_fields[] = { + { TSM_TIMER_T0_MAX_COUNT, 30, 0, 50000 }, +}; + +static nt_fpga_field_init_t tsm_timer_t1_fields[] = { + { TSM_TIMER_T1_MAX_COUNT, 30, 0, 50000 }, +}; + +static nt_fpga_field_init_t tsm_time_hardset_hi_fields[] = { + { TSM_TIME_HARDSET_HI_TIME, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_time_hardset_lo_fields[] = { + { TSM_TIME_HARDSET_LO_TIME, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_time_hi_fields[] = { + { TSM_TIME_HI_SEC, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_time_lo_fields[] = { + { TSM_TIME_LO_NS, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_time_rate_adj_fields[] = { + { TSM_TIME_RATE_ADJ_FRACTION, 29, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_ts_hi_fields[] = { + { TSM_TS_HI_TIME, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_ts_lo_fields[] = { + { TSM_TS_LO_TIME, 32, 0, 0x0000 }, +}; + +static nt_fpga_field_init_t tsm_ts_offset_fields[] = { + { TSM_TS_OFFSET_NS, 30, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_ts_stat_fields[] = { + { TSM_TS_STAT_OVERRUN, 1, 16, 0 }, + { TSM_TS_STAT_SAMPLES, 16, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_ts_stat_hi_offset_fields[] = { + { TSM_TS_STAT_HI_OFFSET_NS, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_ts_stat_lo_offset_fields[] = { + { TSM_TS_STAT_LO_OFFSET_NS, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_ts_stat_tar_hi_fields[] = { + { TSM_TS_STAT_TAR_HI_SEC, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_ts_stat_tar_lo_fields[] = { + { TSM_TS_STAT_TAR_LO_NS, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_ts_stat_x_fields[] = { + { TSM_TS_STAT_X_NS, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_ts_stat_x2_hi_fields[] = { + { TSM_TS_STAT_X2_HI_NS, 16, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_ts_stat_x2_lo_fields[] = { + { TSM_TS_STAT_X2_LO_NS, 32, 0, 0 }, +}; + +static nt_fpga_field_init_t tsm_utc_offset_fields[] = { + { TSM_UTC_OFFSET_SEC, 8, 0, 0 }, +}; + +static nt_fpga_register_init_t tsm_registers[] = { + { TSM_CON0_CONFIG, 24, 14, REGISTER_TYPE_RW, 2320, 5, + tsm_con0_config_fields + }, + { TSM_CON0_INTERFACE, 25, 20, REGISTER_TYPE_RW, 524291, 5, + tsm_con0_interface_fields + }, + { TSM_CON0_SAMPLE_HI, 27, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con0_sample_hi_fields + }, + { TSM_CON0_SAMPLE_LO, 26, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con0_sample_lo_fields + }, + { TSM_CON1_CONFIG, 28, 14, REGISTER_TYPE_RW, 2320, 5, + tsm_con1_config_fields + }, + { TSM_CON1_SAMPLE_HI, 30, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con1_sample_hi_fields + }, + { TSM_CON1_SAMPLE_LO, 29, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con1_sample_lo_fields + }, + { TSM_CON2_CONFIG, 31, 14, REGISTER_TYPE_RW, 2320, 5, + tsm_con2_config_fields + }, + { TSM_CON2_SAMPLE_HI, 33, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con2_sample_hi_fields + }, + { TSM_CON2_SAMPLE_LO, 32, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con2_sample_lo_fields + }, + { TSM_CON3_CONFIG, 34, 10, REGISTER_TYPE_RW, 841, 3, + tsm_con3_config_fields + }, + { TSM_CON3_SAMPLE_HI, 36, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con3_sample_hi_fields + }, + { TSM_CON3_SAMPLE_LO, 35, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con3_sample_lo_fields + }, + { TSM_CON4_CONFIG, 37, 10, REGISTER_TYPE_RW, 841, 3, + tsm_con4_config_fields + }, + { TSM_CON4_SAMPLE_HI, 39, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con4_sample_hi_fields + }, + { TSM_CON4_SAMPLE_LO, 38, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con4_sample_lo_fields + }, + { TSM_CON5_CONFIG, 40, 10, REGISTER_TYPE_RW, 841, 3, + tsm_con5_config_fields + }, + { TSM_CON5_SAMPLE_HI, 42, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con5_sample_hi_fields + }, + { TSM_CON5_SAMPLE_LO, 41, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con5_sample_lo_fields + }, + { TSM_CON6_CONFIG, 43, 10, REGISTER_TYPE_RW, 841, 3, + tsm_con6_config_fields + }, + { TSM_CON6_SAMPLE_HI, 45, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con6_sample_hi_fields + }, + { TSM_CON6_SAMPLE_LO, 44, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con6_sample_lo_fields + }, + { TSM_CON7_HOST_SAMPLE_HI, 47, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con7_host_sample_hi_fields + }, + { TSM_CON7_HOST_SAMPLE_LO, 46, 32, REGISTER_TYPE_RO, 0, 1, + tsm_con7_host_sample_lo_fields + }, + { TSM_CONFIG, 0, 13, REGISTER_TYPE_RW, 257, 6, tsm_config_fields }, + { TSM_INT_CONFIG, 2, 20, REGISTER_TYPE_RW, 0, 2, + tsm_int_config_fields + }, + { TSM_INT_STAT, 3, 20, REGISTER_TYPE_MIXED, 0, 2, tsm_int_stat_fields }, + { TSM_LED, 4, 27, REGISTER_TYPE_RW, 16793600, 12, tsm_led_fields }, + { TSM_NTTS_CONFIG, 13, 7, REGISTER_TYPE_RW, 32, 4, + tsm_ntts_config_fields + }, + { TSM_NTTS_EXT_STAT, 15, 32, REGISTER_TYPE_MIXED, 0, 3, + tsm_ntts_ext_stat_fields + }, + { TSM_NTTS_LIMIT_HI, 23, 16, REGISTER_TYPE_RW, 0, 1, + tsm_ntts_limit_hi_fields + }, + { TSM_NTTS_LIMIT_LO, 22, 32, REGISTER_TYPE_RW, 100000, 1, + tsm_ntts_limit_lo_fields + }, + { TSM_NTTS_OFFSET, 21, 30, REGISTER_TYPE_RW, 0, 1, + tsm_ntts_offset_fields + }, + { TSM_NTTS_SAMPLE_HI, 19, 32, REGISTER_TYPE_RO, 0, 1, + tsm_ntts_sample_hi_fields + }, + { TSM_NTTS_SAMPLE_LO, 18, 32, REGISTER_TYPE_RO, 0, 1, + tsm_ntts_sample_lo_fields + }, + { TSM_NTTS_STAT, 14, 17, REGISTER_TYPE_RO, 0, 3, tsm_ntts_stat_fields }, + { TSM_NTTS_TS_T0_HI, 17, 32, REGISTER_TYPE_RO, 0, 1, + tsm_ntts_ts_t0_hi_fields + }, + { TSM_NTTS_TS_T0_LO, 16, 32, REGISTER_TYPE_RO, 0, 1, + tsm_ntts_ts_t0_lo_fields + }, + { TSM_NTTS_TS_T0_OFFSET, 20, 32, REGISTER_TYPE_RO, 0, 1, + tsm_ntts_ts_t0_offset_fields + }, + { TSM_PB_CTRL, 63, 2, REGISTER_TYPE_WO, 0, 2, tsm_pb_ctrl_fields }, + { TSM_PB_INSTMEM, 64, 32, REGISTER_TYPE_WO, 0, 2, + tsm_pb_instmem_fields + }, + { TSM_PI_CTRL_I, 54, 32, REGISTER_TYPE_WO, 0, 1, tsm_pi_ctrl_i_fields }, + { TSM_PI_CTRL_KI, 52, 24, REGISTER_TYPE_RW, 0, 1, + tsm_pi_ctrl_ki_fields + }, + { TSM_PI_CTRL_KP, 51, 24, REGISTER_TYPE_RW, 0, 1, + tsm_pi_ctrl_kp_fields + }, + { TSM_PI_CTRL_SHL, 53, 4, REGISTER_TYPE_WO, 0, 1, + tsm_pi_ctrl_shl_fields + }, + { TSM_STAT, 1, 16, REGISTER_TYPE_RO, 0, 9, tsm_stat_fields }, + { TSM_TIMER_CTRL, 48, 2, REGISTER_TYPE_RW, 0, 2, + tsm_timer_ctrl_fields + }, + { TSM_TIMER_T0, 49, 30, REGISTER_TYPE_RW, 50000, 1, + tsm_timer_t0_fields + }, + { TSM_TIMER_T1, 50, 30, REGISTER_TYPE_RW, 50000, 1, + tsm_timer_t1_fields + }, + { TSM_TIME_HARDSET_HI, 12, 32, REGISTER_TYPE_RO, 0, 1, + tsm_time_hardset_hi_fields + }, + { TSM_TIME_HARDSET_LO, 11, 32, REGISTER_TYPE_RO, 0, 1, + tsm_time_hardset_lo_fields + }, + { TSM_TIME_HI, 9, 32, REGISTER_TYPE_RW, 0, 1, tsm_time_hi_fields }, + { TSM_TIME_LO, 8, 32, REGISTER_TYPE_RW, 0, 1, tsm_time_lo_fields }, + { TSM_TIME_RATE_ADJ, 10, 29, REGISTER_TYPE_RW, 0, 1, + tsm_time_rate_adj_fields + }, + { TSM_TS_HI, 6, 32, REGISTER_TYPE_RO, 0, 1, tsm_ts_hi_fields }, + { TSM_TS_LO, 5, 32, REGISTER_TYPE_RO, 0, 1, tsm_ts_lo_fields }, + { TSM_TS_OFFSET, 7, 30, REGISTER_TYPE_RW, 0, 1, tsm_ts_offset_fields }, + { TSM_TS_STAT, 55, 17, REGISTER_TYPE_RO, 0, 2, tsm_ts_stat_fields }, + { TSM_TS_STAT_HI_OFFSET, 62, 32, REGISTER_TYPE_RO, 0, 1, + tsm_ts_stat_hi_offset_fields + }, + { TSM_TS_STAT_LO_OFFSET, 61, 32, REGISTER_TYPE_RO, 0, 1, + tsm_ts_stat_lo_offset_fields + }, + { TSM_TS_STAT_TAR_HI, 57, 32, REGISTER_TYPE_RO, 0, 1, + tsm_ts_stat_tar_hi_fields + }, + { TSM_TS_STAT_TAR_LO, 56, 32, REGISTER_TYPE_RO, 0, 1, + tsm_ts_stat_tar_lo_fields + }, + { TSM_TS_STAT_X, 58, 32, REGISTER_TYPE_RO, 0, 1, tsm_ts_stat_x_fields }, + { TSM_TS_STAT_X2_HI, 60, 16, REGISTER_TYPE_RO, 0, 1, + tsm_ts_stat_x2_hi_fields + }, + { TSM_TS_STAT_X2_LO, 59, 32, REGISTER_TYPE_RO, 0, 1, + tsm_ts_stat_x2_lo_fields + }, + { TSM_UTC_OFFSET, 65, 8, REGISTER_TYPE_RW, 0, 1, + tsm_utc_offset_fields + }, +}; + +static nt_fpga_module_init_t fpga_modules[] = { + { MOD_CAT, 0, MOD_CAT, 0, 21, BUS_TYPE_RAB1, 768, 34, + cat_registers + }, /* CAT:0 CAT v0.21: CAT @ RAB1,768 (CAT CAT CAT) */ + { MOD_CSU, 0, MOD_CSU, 0, 0, BUS_TYPE_RAB1, 9728, 2, + csu_registers + }, /* CSU:0 CSU v0.0: CSU @ RAB1,9728 (CSU CSU CSU) */ + { MOD_DBS, 0, MOD_DBS, 0, 11, BUS_TYPE_RAB2, 12832, 27, + dbs_registers + }, /* DBS:0 DBS v0.11: DBS @ RAB2,12832 (DBS DBS DBS) */ + { MOD_FLM, 0, MOD_FLM, 0, 20, BUS_TYPE_RAB1, 1280, 43, + flm_registers + }, /* FLM:0 FLM v0.20: FLM @ RAB1,1280 (FLM FLM FLM) */ + { MOD_GFG, 0, MOD_GFG, 1, 1, BUS_TYPE_RAB2, 8704, 10, + gfg_registers + }, /* GFG:0 GFG v1.1: GFG @ RAB2,8704 (GFG GFG GFG) */ + { MOD_GMF, 0, MOD_GMF, 2, 5, BUS_TYPE_RAB2, 9216, 12, + gmf_registers + }, /* GMF:0 GMF v2.5: GMF_0 @ RAB2,9216 (GMF GMF_0 GMF) */ + { MOD_GMF, 1, MOD_GMF, 2, 5, BUS_TYPE_RAB2, 9728, 12, + gmf_registers + }, /* GMF:1 GMF v2.5: GMF_1 @ RAB2,9728 (GMF GMF_1 GMF) */ + { MOD_GPIO_PHY, 0, MOD_GPIO_PHY, 1, 0, BUS_TYPE_RAB0, 16386, 2, + gpio_phy_registers + }, /* GPIO_PHY:0 GPIO_PHY v1.0: GPIO_PHY @ RAB0,16386 (GPIO_PHY GPIO_PHY GPIO_PHY) */ + { MOD_HFU, 0, MOD_HFU, 0, 1, BUS_TYPE_RAB1, 9472, 2, + hfu_registers + }, /* HFU:0 HFU v0.1: HFU @ RAB1,9472 (HFU HFU HFU) */ + { MOD_HIF, 0, MOD_HIF, 0, 0, BUS_TYPE_PCI, 0, 18, + hif_registers + }, /* HIF:0 HIF v0.0: HIF @ PCI,0 (HIF HIF HIF) */ + { MOD_HSH, 0, MOD_HSH, 0, 5, BUS_TYPE_RAB1, 1536, 2, + hsh_registers + }, /* HSH:0 HSH v0.5: HSH @ RAB1,1536 (HSH HSH HSH) */ + { MOD_HST, 0, MOD_HST, 0, 2, BUS_TYPE_RAB1, 2048, 2, + hst_registers + }, /* HST:0 HST v0.2: HST @ RAB1,2048 (HST HST HST) */ + { MOD_IFR, 0, MOD_IFR, 0, 1, BUS_TYPE_RAB1, 9984, 2, + ifr_registers + }, /* IFR:0 IFR v0.1: IFR @ RAB1,9984 (IFR IFR IFR) */ + { MOD_IIC, 0, MOD_IIC, 0, 1, BUS_TYPE_RAB0, 768, 22, + iic_registers + }, /* IIC:0 IIC v0.1: IIC0 @ RAB0,768 (IIC IIC0 IIC) */ + { MOD_IIC, 1, MOD_IIC, 0, 1, BUS_TYPE_RAB0, 896, 22, + iic_registers + }, /* IIC:1 IIC v0.1: IIC1 @ RAB0,896 (IIC IIC1 IIC) */ + { MOD_IIC, 2, MOD_IIC, 0, 1, BUS_TYPE_RAB0, 24832, 22, + iic_registers + }, /* IIC:2 IIC v0.1: IIC2 @ RAB0,24832 (IIC IIC2 IIC) */ + { MOD_IIC, 3, MOD_IIC, 0, 1, BUS_TYPE_RAB0, 24960, 22, + iic_registers + }, /* IIC:3 IIC v0.1: IIC3 @ RAB0,24960 (IIC IIC3 IIC) */ + { MOD_KM, 0, MOD_KM, 0, 7, BUS_TYPE_RAB1, 1024, 11, + km_registers + }, /* KM:0 KM v0.7: KM @ RAB1,1024 (KM KM KM) */ + { MOD_MAC_PCS, 0, MOD_MAC_PCS, 0, 2, BUS_TYPE_RAB2, 10240, 44, + mac_pcs_registers + }, /* MAC_PCS:0 MAC_PCS v0.2: MAC_PCS_0 @ RAB2,10240 (MAC_PCS MAC_PCS_0 MAC_PCS) */ + { MOD_MAC_PCS, 1, MOD_MAC_PCS, 0, 2, BUS_TYPE_RAB2, 11776, 44, + mac_pcs_registers + }, /* MAC_PCS:1 MAC_PCS v0.2: MAC_PCS_1 @ RAB2,11776 (MAC_PCS MAC_PCS_1 MAC_PCS) */ + { MOD_MAC_RX, 0, MOD_MAC_RX, 0, 0, BUS_TYPE_RAB2, 10752, 9, + mac_rx_registers + }, /* MAC_RX:0 MAC_RX v0.0: MAC_RX_0 @ RAB2,10752 (MAC_RX MAC_RX_0 MAC_RX) */ + { MOD_MAC_RX, 1, MOD_MAC_RX, 0, 0, BUS_TYPE_RAB2, 12288, 9, + mac_rx_registers + }, /* MAC_RX:1 MAC_RX v0.0: MAC_RX_1 @ RAB2,12288 (MAC_RX MAC_RX_1 MAC_RX) */ + { MOD_MAC_TX, 0, MOD_MAC_TX, 0, 0, BUS_TYPE_RAB2, 11264, 5, + mac_tx_registers + }, /* MAC_TX:0 MAC_TX v0.0: MAC_TX_0 @ RAB2,11264 (MAC_TX MAC_TX_0 MAC_TX) */ + { MOD_MAC_TX, 1, MOD_MAC_TX, 0, 0, BUS_TYPE_RAB2, 12800, 5, + mac_tx_registers + }, /* MAC_TX:1 MAC_TX v0.0: MAC_TX_1 @ RAB2,12800 (MAC_TX MAC_TX_1 MAC_TX) */ + { MOD_PCI_RD_TG, 0, MOD_PCI_RD_TG, 0, 1, BUS_TYPE_RAB0, 2320, 6, + pci_rd_tg_registers + }, /* PCI_RD_TG:0 PCI_RD_TG v0.1: PCI_RD_TG @ RAB0,2320 (PCI_RD_TG PCI_RD_TG PCI_RD_TG) */ + { MOD_PCI_TA, 0, MOD_PCI_TA, 0, 0, BUS_TYPE_RAB0, 2336, 5, + pci_ta_registers + }, /* PCI_TA:0 PCI_TA v0.0: PCI_TA @ RAB0,2336 (PCI_TA PCI_TA PCI_TA) */ + { MOD_PCI_WR_TG, 0, MOD_PCI_WR_TG, 0, 1, BUS_TYPE_RAB0, 2304, 7, + pci_wr_tg_registers + }, /* PCI_WR_TG:0 PCI_WR_TG v0.1: PCI_WR_TG @ RAB0,2304 (PCI_WR_TG PCI_WR_TG PCI_WR_TG) */ + { MOD_PDB, 0, MOD_PDB, 0, 9, BUS_TYPE_RAB1, 2816, 3, + pdb_registers + }, /* PDB:0 PDB v0.9: PDB @ RAB1,2816 (PDB PDB PDB) */ + { MOD_PDI, 0, MOD_PDI, 1, 1, BUS_TYPE_RAB0, 64, 6, + pdi_registers + }, /* PDI:0 PDI v1.1: PDI @ RAB0,64 (PDI PDI PDI) */ + { MOD_PTP1588, 0, MOD_PTP1588, 2, 1, BUS_TYPE_RAB2, 512, 23, + ptp1588_registers + }, /* PTP1588:0 PTP1588 v2.1: PTP1588 @ RAB2,512 (PTP1588 PTP1588 PTP1588) */ + { MOD_QSL, 0, MOD_QSL, 0, 7, BUS_TYPE_RAB1, 1792, 8, + qsl_registers + }, /* QSL:0 QSL v0.7: QSL @ RAB1,1792 (QSL QSL QSL) */ + { MOD_QSPI, 0, MOD_QSPI, 0, 0, BUS_TYPE_RAB0, 512, 11, + qspi_registers + }, /* QSPI:0 QSPI v0.0: QSPI @ RAB0,512 (QSPI QSPI QSPI) */ + { MOD_RAC, 0, MOD_RAC, 3, 0, BUS_TYPE_PCI, 8192, 14, + rac_registers + }, /* RAC:0 RAC v3.0: RAC @ PCI,8192 (RAC RAC RAC) */ + { MOD_RFD, 0, MOD_RFD, 0, 4, BUS_TYPE_RAB1, 256, 5, + rfd_registers + }, /* RFD:0 RFD v0.4: RFD @ RAB1,256 (RFD RFD RFD) */ + { MOD_RMC, 0, MOD_RMC, 1, 3, BUS_TYPE_RAB0, 12288, 4, + rmc_registers + }, /* RMC:0 RMC v1.3: RMC @ RAB0,12288 (RMC RMC RMC) */ + { MOD_RPP_LR, 0, MOD_RPP_LR, 0, 1, BUS_TYPE_RAB1, 2560, 4, + rpp_lr_registers + }, /* RPP_LR:0 RPP_LR v0.1: RPP_LR @ RAB1,2560 (RPP_LR RPP_LR RPP_LR) */ + { MOD_RST9563, 0, MOD_RST9563, 0, 5, BUS_TYPE_RAB0, 1024, 5, + rst9563_registers + }, /* RST9563:0 RST9563 v0.5: RST9563 @ RAB0,1024 (RST9563 RST9563 RST9563) */ + { MOD_SLC_LR, 0, MOD_SLC, 0, 2, BUS_TYPE_RAB1, 2304, 2, + slc_registers + }, /* SLC_LR:0 SLC v0.2: SLC_LR @ RAB1,2304 (SLC SLC_LR SLC_LR) */ + { MOD_SPIM, 0, MOD_SPIM, 1, 0, BUS_TYPE_RAB0, 80, 6, + spim_registers + }, /* SPIM:0 SPIM v1.0: SPIM @ RAB0,80 (SPIM SPIM SPIM) */ + { MOD_SPIS, 0, MOD_SPIS, 1, 0, BUS_TYPE_RAB0, 256, 7, + spis_registers + }, /* SPIS:0 SPIS v1.0: SPIS @ RAB0,256 (SPIS SPIS SPIS) */ + { MOD_STA, 0, MOD_STA, 0, 8, BUS_TYPE_RAB0, 2048, 8, + sta_registers + }, /* STA:0 STA v0.8: STA @ RAB0,2048 (STA STA STA) */ + { MOD_TEMPMON, 0, MOD_TEMPMON, 0, 0, BUS_TYPE_RAB0, 16384, 2, + tempmon_registers + }, /* TEMPMON:0 TEMPMON v0.0: TEMPMON @ RAB0,16384 (TEMPMON TEMPMON TEMPMON) */ + { MOD_TINT, 0, MOD_TINT, 0, 0, BUS_TYPE_RAB0, 1280, 2, + tint_registers + }, /* TINT:0 TINT v0.0: TINT @ RAB0,1280 (TINT TINT TINT) */ + { MOD_TMC, 0, MOD_TMC, 0, 1, BUS_TYPE_RAB2, 8192, 1, + tmc_registers + }, /* TMC:0 TMC v0.1: TMC @ RAB2,8192 (TMC TMC TMC) */ + { MOD_TSM, 0, MOD_TSM, 0, 8, BUS_TYPE_RAB2, 1024, 66, + tsm_registers + }, /* TSM:0 TSM v0.8: TSM @ RAB2,1024 (TSM TSM TSM) */ + { MOD_TX_CPY, 0, MOD_CPY, 0, 1, BUS_TYPE_RAB1, 9216, 20, + cpy_registers + }, /* TX_CPY:0 CPY v0.1: TX_CPY @ RAB1,9216 (CPY TX_CPY TX_CPY) */ + { MOD_TX_INS, 0, MOD_INS, 0, 1, BUS_TYPE_RAB1, 8704, 2, + ins_registers + }, /* TX_INS:0 INS v0.1: TX_INS @ RAB1,8704 (INS TX_INS TX_INS) */ + { MOD_TX_RPL, 0, MOD_RPL, 0, 2, BUS_TYPE_RAB1, 8960, 6, + rpl_registers + }, /* TX_RPL:0 RPL v0.2: TX_RPL @ RAB1,8960 (RPL TX_RPL TX_RPL) */ +}; + +static nt_fpga_prod_param_t product_parameters[] = { + { NT_BUILD_NUMBER, 0 }, + { NT_BUILD_TIME, 1689706895 }, + { NT_CATEGORIES, 64 }, + { NT_CAT_DCT_PRESENT, 0 }, + { NT_CAT_END_OFS_SUPPORT, 0 }, + { NT_CAT_FUNCS, 64 }, + { NT_CAT_KCC_BANKS, 3 }, + { NT_CAT_KCC_PRESENT, 0 }, + { NT_CAT_KCC_SIZE, 1536 }, + { NT_CAT_KM_IF_CNT, 2 }, + { NT_CAT_KM_IF_M0, 0 }, + { NT_CAT_KM_IF_M1, 1 }, + { NT_CAT_N_CMP, 8 }, + { NT_CAT_N_EXT, 4 }, + { NT_CAT_N_LEN, 8 }, + { NT_CB_DEBUG, 0 }, + { NT_COR_CATEGORIES, 16 }, + { NT_COR_PRESENT, 0 }, + { NT_CSU_PRESENT, 1 }, + { NT_DBS_PRESENT, 1 }, + { NT_DBS_RX_QUEUES, 128 }, + { NT_DBS_TX_PORTS, 2 }, + { NT_DBS_TX_QUEUES, 128 }, + { NT_DDP_PRESENT, 0 }, + { NT_DDP_TBL_DEPTH, 4096 }, + { NT_EMI_SPLIT_STEPS, 16 }, + { NT_EOF_TIMESTAMP_ONLY, 1 }, + { NT_EPP_CATEGORIES, 32 }, + { NT_FLM_CACHE, 1 }, + { NT_FLM_CATEGORIES, 32 }, + { NT_FLM_ENTRY_SIZE, 64 }, + { NT_FLM_PRESENT, 1 }, + { NT_FLM_PRIOS, 4 }, + { NT_FLM_PST_PROFILES, 16 }, + { NT_FLM_SIZE_MB, 12288 }, + { NT_FLM_STATEFUL, 1 }, + { NT_FLM_VARIANT, 2 }, + { NT_GFG_PRESENT, 1 }, + { NT_GFG_TX_LIVE_RECONFIG_SUPPORT, 1 }, + { NT_GMF_FCS_PRESENT, 0 }, + { NT_GMF_IFG_SPEED_DIV, 33 }, + { NT_GMF_IFG_SPEED_DIV100G, 33 }, + { NT_GMF_IFG_SPEED_MUL, 20 }, + { NT_GMF_IFG_SPEED_MUL100G, 20 }, + { NT_GROUP_ID, 9563 }, + { NT_HFU_PRESENT, 1 }, + { NT_HIF_MSIX_BAR, 1 }, + { NT_HIF_MSIX_PBA_OFS, 8192 }, + { NT_HIF_MSIX_PRESENT, 1 }, + { NT_HIF_MSIX_TBL_OFS, 0 }, + { NT_HIF_MSIX_TBL_SIZE, 8 }, + { NT_HIF_PER_PS, 4000 }, + { NT_HIF_SRIOV_PRESENT, 1 }, + { NT_HSH_CATEGORIES, 16 }, + { NT_HSH_TOEPLITZ, 1 }, + { NT_HST_CATEGORIES, 32 }, + { NT_HST_PRESENT, 1 }, + { NT_IOA_CATEGORIES, 1024 }, + { NT_IOA_PRESENT, 0 }, + { NT_IPF_PRESENT, 0 }, + { NT_KM_CAM_BANKS, 3 }, + { NT_KM_CAM_RECORDS, 2048 }, + { NT_KM_CAM_REC_WORDS, 6 }, + { NT_KM_CATEGORIES, 32 }, + { NT_KM_END_OFS_SUPPORT, 0 }, + { NT_KM_EXT_EXTRACTORS, 0 }, + { NT_KM_FLOW_TYPES, 16 }, + { NT_KM_PRESENT, 1 }, + { NT_KM_SWX_PRESENT, 0 }, + { NT_KM_SYNERGY_MATCH, 0 }, + { NT_KM_TCAM_BANKS, 12 }, + { NT_KM_TCAM_BANK_WIDTH, 72 }, + { NT_KM_TCAM_HIT_QUAL, 0 }, + { NT_KM_TCAM_KEYWAY, 1 }, + { NT_KM_WIDE, 1 }, + { NT_LR_PRESENT, 1 }, + { NT_MCU_PRESENT, 0 }, + { NT_MDG_DEBUG_FLOW_CONTROL, 0 }, + { NT_MDG_DEBUG_REG_READ_BACK, 0 }, + { NT_MSK_CATEGORIES, 32 }, + { NT_MSK_PRESENT, 0 }, + { NT_NFV_OVS_PRODUCT, 0 }, + { NT_NIMS, 2 }, + { NT_PCI_DEVICE_ID, 453 }, + { NT_PCI_TA_TG_PRESENT, 1 }, + { NT_PCI_VENDOR_ID, 6388 }, + { NT_PDB_CATEGORIES, 16 }, + { NT_PHY_ANEG_PRESENT, 0 }, + { NT_PHY_KRFEC_PRESENT, 0 }, + { NT_PHY_PORTS, 2 }, + { NT_PHY_PORTS_PER_QUAD, 1 }, + { NT_PHY_QUADS, 2 }, + { NT_PHY_RSFEC_PRESENT, 1 }, + { NT_QM_CELLS, 2097152 }, + { NT_QM_CELL_SIZE, 6144 }, + { NT_QM_PRESENT, 0 }, + { NT_QSL_CATEGORIES, 32 }, + { NT_QSL_COLOR_SEL_BW, 7 }, + { NT_QSL_QST_SIZE, 4096 }, + { NT_QUEUES, 128 }, + { NT_RAC_RAB_INTERFACES, 3 }, + { NT_RAC_RAB_OB_UPDATE, 0 }, + { NT_REVISION_ID, 24 }, + { NT_RMC_LAG_GROUPS, 1 }, + { NT_ROA_CATEGORIES, 1024 }, + { NT_ROA_PRESENT, 0 }, + { NT_RPP_PER_PS, 3333 }, + { NT_RTX_PRESENT, 0 }, + { NT_RX_HOST_BUFFERS, 128 }, + { NT_RX_PORTS, 2 }, + { NT_RX_PORT_REPLICATE, 0 }, + { NT_SLB_PRESENT, 0 }, + { NT_SLC_LR_PRESENT, 1 }, + { NT_STA_COLORS, 64 }, + { NT_STA_RX_PORTS, 2 }, + { NT_TBH_DEBUG_DLN, 1 }, + { NT_TBH_PRESENT, 0 }, + { NT_TFD_PRESENT, 1 }, + { NT_TPE_CATEGORIES, 16 }, + { NT_TSM_OST_ONLY, 0 }, + { NT_TS_APPEND, 0 }, + { NT_TS_INJECT_PRESENT, 0 }, + { NT_TX_CPY_PACKET_READERS, 0 }, + { NT_TX_CPY_PRESENT, 1 }, + { NT_TX_CPY_SIDEBAND_READERS, 6 }, + { NT_TX_CPY_VARIANT, 0 }, + { NT_TX_CPY_WRITERS, 5 }, + { NT_TX_HOST_BUFFERS, 128 }, + { NT_TX_INS_PRESENT, 1 }, + { NT_TX_MTU_PROFILE_IFR, 16 }, + { NT_TX_ON_TIMESTAMP, 1 }, + { NT_TX_PORTS, 2 }, + { NT_TX_PORT_REPLICATE, 1 }, + { NT_TX_RPL_DEPTH, 4096 }, + { NT_TX_RPL_EXT_CATEGORIES, 1024 }, + { NT_TX_RPL_PRESENT, 1 }, + { NT_TYPE_ID, 200 }, + { NT_USE_TRIPLE_SPEED, 0 }, + { NT_VERSION_ID, 55 }, + { NT_VLI_PRESENT, 0 }, + { 0, -1 }, /* END */ +}; + +nt_fpga_prod_init_t nthw_fpga_9563_055_024_0000 = { + 200, /* fpgaTypeId */ + 9563, /* fpga_product_id */ + 55, /* fpga_version */ + 24, /* fpga_revision */ + 0, /* fpga_patch_no */ + 0, /* fpga_build_no */ + 1689706895, /* fpga_build_time */ + 140, product_parameters, 48, fpga_modules, +}; diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h new file mode 100644 index 0000000000..1d707d6925 --- /dev/null +++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NTHW_FPGA_INSTANCES_H +#define NTHW_FPGA_INSTANCES_H + +#include "fpga_model.h" + +extern nt_fpga_prod_init_t *nthw_fpga_instances[]; + +extern nt_fpga_prod_init_t nthw_fpga_9563_055_024_0000; + +#endif /* NTHW_FPGA_INSTANCES_H */ diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_modules_defs.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_modules_defs.h new file mode 100644 index 0000000000..38a15bec87 --- /dev/null +++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_modules_defs.h @@ -0,0 +1,166 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTHW_FPGA_MODULES_DEFS_H_ +#define _NTHW_FPGA_MODULES_DEFS_H_ + +/* Unknown/uninitialized - keep this as the first element */ +#define MOD_UNKNOWN (0L) +#define MOD_CAT (1L) +#define MOD_CB (2L) +#define MOD_CCIP (3L) +#define MOD_CFP4_CTRL_GBOX (4L) +#define MOD_COR (5L) +#define MOD_CPY (6L) +#define MOD_CSU (7L) +#define MOD_DBS (8L) +#define MOD_DDP (9L) +#define MOD_EPP (10L) +#define MOD_EQM (11L) +#define MOD_FHM (12L) +#define MOD_FLM (13L) +#define MOD_GFG (14L) +#define MOD_GMF (15L) +#define MOD_GPIO_PHY (16L) +#define MOD_GPIO_PHY_PORTS (17L) +#define MOD_GPIO_SFPP (18L) +#define MOD_HFU (19L) +#define MOD_HIF (20L) +#define MOD_HSH (21L) +#define MOD_HST (22L) +#define MOD_ICORE_10G (23L) +#define MOD_IFR (24L) +#define MOD_IIC (25L) +#define MOD_INS (26L) +#define MOD_IOA (27L) +#define MOD_IPF (28L) +#define MOD_KM (29L) +#define MOD_LAO (30L) +#define MOD_MAC (31L) +#define MOD_MAC100 (33L) +#define MOD_MAC10G (34L) +#define MOD_MAC1G (35L) +#define MOD_MAC_PCS (36L) +#define MOD_MAC_PCS_XXV (37L) +#define MOD_MAC_RX (38L) +#define MOD_MAC_TFG (39L) +#define MOD_MAC_TX (40L) +#define MOD_MCU (41L) +#define MOD_MDG (42L) +#define MOD_MSK (43L) +#define MOD_NIF (44L) +#define MOD_PCIE3 (45L) +#define MOD_PCI_RD_TG (46L) +#define MOD_PCI_TA (47L) +#define MOD_PCI_WR_TG (48L) +#define MOD_PCM_NT100A01_01 (49L) +#define MOD_PCM_NT50B01_01 (50L) +#define MOD_PCS (51L) +#define MOD_PCS100 (52L) +#define MOD_PDB (53L) +#define MOD_PDI (54L) +#define MOD_PHY10G (55L) +#define MOD_PHY3S10G (56L) +#define MOD_PM (57L) +#define MOD_PRM_NT100A01_01 (58L) +#define MOD_PRM_NT50B01_01 (59L) +#define MOD_PTP1588 (60L) +#define MOD_QM (61L) +#define MOD_QSL (62L) +#define MOD_QSPI (63L) +#define MOD_R2DRP (64L) +#define MOD_RAC (65L) +#define MOD_RBH (66L) +#define MOD_RFD (67L) +#define MOD_RMC (68L) +#define MOD_RNTC (69L) +#define MOD_ROA (70L) +#define MOD_RPL (71L) +#define MOD_RPP_LR (72L) +#define MOD_RST7000 (73L) +#define MOD_RST7001 (74L) +#define MOD_RST9500 (75L) +#define MOD_RST9501 (76L) +#define MOD_RST9502 (77L) +#define MOD_RST9503 (78L) +#define MOD_RST9504 (79L) +#define MOD_RST9505 (80L) +#define MOD_RST9506 (81L) +#define MOD_RST9507 (82L) +#define MOD_RST9508 (83L) +#define MOD_RST9509 (84L) +#define MOD_RST9510 (85L) +#define MOD_RST9512 (86L) +#define MOD_RST9513 (87L) +#define MOD_RST9515 (88L) +#define MOD_RST9516 (89L) +#define MOD_RST9517 (90L) +#define MOD_RST9519 (91L) +#define MOD_RST9520 (92L) +#define MOD_RST9521 (93L) +#define MOD_RST9522 (94L) +#define MOD_RST9523 (95L) +#define MOD_RST9524 (96L) +#define MOD_RST9525 (97L) +#define MOD_RST9526 (98L) +#define MOD_RST9527 (99L) +#define MOD_RST9528 (100L) +#define MOD_RST9529 (101L) +#define MOD_RST9530 (102L) +#define MOD_RST9531 (103L) +#define MOD_RST9532 (104L) +#define MOD_RST9533 (105L) +#define MOD_RST9534 (106L) +#define MOD_RST9535 (107L) +#define MOD_RST9536 (108L) +#define MOD_RST9537 (109L) +#define MOD_RST9538 (110L) +#define MOD_RST9539 (111L) +#define MOD_RST9540 (112L) +#define MOD_RST9541 (113L) +#define MOD_RST9542 (114L) +#define MOD_RST9543 (115L) +#define MOD_RST9544 (116L) +#define MOD_RST9545 (117L) +#define MOD_RST9546 (118L) +#define MOD_RST9547 (119L) +#define MOD_RST9548 (120L) +#define MOD_RST9549 (121L) +#define MOD_RST9553 (122L) +#define MOD_RST9555 (123L) +#define MOD_RST9559 (124L) +#define MOD_RST9563 (125L) +#define MOD_RTD (126L) +#define MOD_RTD_HMP (127L) +#define MOD_RTX (128L) +#define MOD_SDC (129L) +#define MOD_SLC (130L) +#define MOD_SLC_LR (131L) +#define MOD_SMM (132L) +#define MOD_SMM_RX (133L) +#define MOD_SMM_TX (134L) +#define MOD_SPIM (135L) +#define MOD_SPIS (136L) +#define MOD_STA (137L) +#define MOD_TBH (138L) +#define MOD_TEMPMON (139L) +#define MOD_TINT (140L) +#define MOD_TMC (141L) +#define MOD_TSM (142L) +#define MOD_TX_CPY (143L) +#define MOD_TX_CSI (144L) +#define MOD_TX_CSO (145L) +#define MOD_TX_INS (146L) +#define MOD_TX_RPL (147L) +/* + * NOTE: Keep this as the last element! + * End indicator - keep this as the last element - only aliases go below this point + */ +#define MOD_UNKNOWN_MAX (148L) +/* End indicator - keep this as the last element - only aliases go below this point */ +#define MOD_COUNT_MAX (148L) +/* aliases */ +#define MOD_MAC10 (MOD_MAC10G) /* alias */ + +#endif /* _NTHW_FPGA_MODULES_DEFS_H_ */ diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_parameters_defs.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_parameters_defs.h new file mode 100644 index 0000000000..b6187a257f --- /dev/null +++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_parameters_defs.h @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTHW_FPGA_PARAMETERS_DEFS_ +#define _NTHW_FPGA_PARAMETERS_DEFS_ + +#define NT_PARAM_UNKNOWN (0L) +#define NT_BUILD_NUMBER (1L) +#define NT_BUILD_TIME (2L) +#define NT_CATEGORIES (3L) +#define NT_CAT_CCT_SIZE (4L) +#define NT_CAT_CTE_SIZE (5L) +#define NT_CAT_CTS_SIZE (6L) +#define NT_CAT_DCT_PRESENT (7L) +#define NT_CAT_DCT_SIZE (8L) +#define NT_CAT_END_OFS_SUPPORT (9L) +#define NT_CAT_FPC (10L) +#define NT_CAT_FTE_SIZE (11L) +#define NT_CAT_FUNCS (12L) +#define NT_CAT_KCC_BANKS (13L) +#define NT_CAT_KCC_PRESENT (14L) +#define NT_CAT_KCC_SIZE (15L) +#define NT_CAT_KCE_SIZE (16L) +#define NT_CAT_KM_IF_CNT (17L) +#define NT_CAT_KM_IF_M0 (18L) +#define NT_CAT_KM_IF_M1 (19L) +#define NT_CAT_N_CMP (20L) +#define NT_CAT_N_EXT (21L) +#define NT_CAT_N_LEN (22L) +#define NT_CAT_RCK_SIZE (23L) +#define NT_CAT_VALUES (24L) +#define NT_CB_DEBUG (25L) +#define NT_COR_CATEGORIES (26L) +#define NT_COR_PRESENT (27L) +#define NT_CPY_MASK_MEM (28L) +#define NT_CSU_PRESENT (29L) +#define NT_DBS_PRESENT (30L) +#define NT_DBS_RX_QUEUES (31L) +#define NT_DBS_TX_PORTS (32L) +#define NT_DBS_TX_QUEUES (33L) +#define NT_DDP_PRESENT (34L) +#define NT_DDP_TBL_DEPTH (35L) +#define NT_EMI_SPLIT_STEPS (36L) +#define NT_EOF_TIMESTAMP_ONLY (37L) +#define NT_EPP_CATEGORIES (38L) +#define NT_EXT_MEM_NUM (39L) +#define NT_EXT_MEM_SINGLE_SIZE_GB (40L) +#define NT_FLM_CACHE (41L) +#define NT_FLM_CATEGORIES (42L) +#define NT_FLM_ENTRY_SIZE (43L) +#define NT_FLM_PRESENT (44L) +#define NT_FLM_PRIOS (45L) +#define NT_FLM_PST_PROFILES (46L) +#define NT_FLM_SIZE_MB (47L) +#define NT_FLM_STATEFUL (48L) +#define NT_FLM_VARIANT (49L) +#define NT_GFG_PRESENT (50L) +#define NT_GFG_TX_LIVE_RECONFIG_SUPPORT (51L) +#define NT_GMF_FCS_PRESENT (52L) +#define NT_GMF_IFG_SPEED_DIV (53L) +#define NT_GMF_IFG_SPEED_DIV100G (54L) +#define NT_GMF_IFG_SPEED_DIV100M (55L) +#define NT_GMF_IFG_SPEED_DIV10G (56L) +#define NT_GMF_IFG_SPEED_DIV1G (57L) +#define NT_GMF_IFG_SPEED_DIV2 (58L) +#define NT_GMF_IFG_SPEED_DIV25G (59L) +#define NT_GMF_IFG_SPEED_DIV3 (60L) +#define NT_GMF_IFG_SPEED_DIV4 (61L) +#define NT_GMF_IFG_SPEED_DIV40G (62L) +#define NT_GMF_IFG_SPEED_DIV50G (63L) +#define NT_GMF_IFG_SPEED_MUL (64L) +#define NT_GMF_IFG_SPEED_MUL100G (65L) +#define NT_GMF_IFG_SPEED_MUL100M (66L) +#define NT_GMF_IFG_SPEED_MUL10G (67L) +#define NT_GMF_IFG_SPEED_MUL1G (68L) +#define NT_GMF_IFG_SPEED_MUL2 (69L) +#define NT_GMF_IFG_SPEED_MUL25G (70L) +#define NT_GMF_IFG_SPEED_MUL3 (71L) +#define NT_GMF_IFG_SPEED_MUL4 (72L) +#define NT_GMF_IFG_SPEED_MUL40G (73L) +#define NT_GMF_IFG_SPEED_MUL50G (74L) +#define NT_GROUP_ID (75L) +#define NT_HFU_PRESENT (76L) +#define NT_HIF_MSIX_BAR (77L) +#define NT_HIF_MSIX_PBA_OFS (78L) +#define NT_HIF_MSIX_PRESENT (79L) +#define NT_HIF_MSIX_TBL_OFS (80L) +#define NT_HIF_MSIX_TBL_SIZE (81L) +#define NT_HIF_PER_PS (82L) +#define NT_HIF_SRIOV_PRESENT (83L) +#define NT_HSH_CATEGORIES (84L) +#define NT_HSH_TOEPLITZ (85L) +#define NT_HST_CATEGORIES (86L) +#define NT_HST_PRESENT (87L) +#define NT_IOA_CATEGORIES (88L) +#define NT_IOA_PRESENT (89L) +#define NT_IPF_PRESENT (90L) +#define NT_KM_CAM_BANKS (91L) +#define NT_KM_CAM_RECORDS (92L) +#define NT_KM_CAM_REC_WORDS (93L) +#define NT_KM_CATEGORIES (94L) +#define NT_KM_END_OFS_SUPPORT (95L) +#define NT_KM_EXT_EXTRACTORS (96L) +#define NT_KM_FLOW_SETS (97L) +#define NT_KM_FLOW_TYPES (98L) +#define NT_KM_PRESENT (99L) +#define NT_KM_SWX_PRESENT (100L) +#define NT_KM_SYNERGY_MATCH (101L) +#define NT_KM_TCAM_BANKS (102L) +#define NT_KM_TCAM_BANK_WIDTH (103L) +#define NT_KM_TCAM_HIT_QUAL (104L) +#define NT_KM_TCAM_KEYWAY (105L) +#define NT_KM_WIDE (106L) +#define NT_LR_PRESENT (107L) +#define NT_LTX_CATEGORIES (108L) +#define NT_MCU_DRAM_SIZE (109L) +#define NT_MCU_PRESENT (110L) +#define NT_MCU_TYPE (111L) +#define NT_MDG_DEBUG_FLOW_CONTROL (112L) +#define NT_MDG_DEBUG_REG_READ_BACK (113L) +#define NT_MSK_CATEGORIES (114L) +#define NT_MSK_PRESENT (115L) +#define NT_NAME (116L) +#define NT_NFV_OVS_PRODUCT (117L) +#define NT_NIMS (118L) +#define NT_PATCH_NUMBER (119L) +#define NT_PCI_DEVICE_ID (120L) +#define NT_PCI_INT_AVR (121L) +#define NT_PCI_INT_EQM (122L) +#define NT_PCI_INT_IIC0 (123L) +#define NT_PCI_INT_IIC1 (124L) +#define NT_PCI_INT_IIC2 (125L) +#define NT_PCI_INT_IIC3 (126L) +#define NT_PCI_INT_IIC4 (127L) +#define NT_PCI_INT_IIC5 (128L) +#define NT_PCI_INT_PORT (129L) +#define NT_PCI_INT_PORT0 (130L) +#define NT_PCI_INT_PORT1 (131L) +#define NT_PCI_INT_PPS (132L) +#define NT_PCI_INT_QSPI (133L) +#define NT_PCI_INT_SPIM (134L) +#define NT_PCI_INT_SPIS (135L) +#define NT_PCI_INT_STA (136L) +#define NT_PCI_INT_TIMER (137L) +#define NT_PCI_INT_TINT (138L) +#define NT_PCI_TA_TG_PRESENT (139L) +#define NT_PCI_VENDOR_ID (140L) +#define NT_PDB_CATEGORIES (141L) +#define NT_PHY_ANEG_PRESENT (142L) +#define NT_PHY_KRFEC_PRESENT (143L) +#define NT_PHY_PORTS (144L) +#define NT_PHY_PORTS_PER_QUAD (145L) +#define NT_PHY_QUADS (146L) +#define NT_PHY_RSFEC_PRESENT (147L) +#define NT_PORTS (148L) +#define NT_PROD_ID_LAYOUT_VERSION (149L) +#define NT_QM_BLOCKS (150L) +#define NT_QM_CELLS (151L) +#define NT_QM_CELL_SIZE (152L) +#define NT_QM_PRESENT (153L) +#define NT_QSL_CATEGORIES (154L) +#define NT_QSL_COLOR_SEL_BW (155L) +#define NT_QSL_QST_SIZE (156L) +#define NT_QUEUES (157L) +#define NT_RAC_RAB_INTERFACES (158L) +#define NT_RAC_RAB_OB_UPDATE (159L) +#define NT_REVISION_ID (160L) +#define NT_RMC_LAG_GROUPS (161L) +#define NT_ROA_CATEGORIES (162L) +#define NT_ROA_PRESENT (163L) +#define NT_RPP_PER_PS (164L) +#define NT_RTX_PRESENT (165L) +#define NT_RX_HOST_BUFFERS (166L) +#define NT_RX_PORTS (167L) +#define NT_RX_PORT_REPLICATE (168L) +#define NT_SLB_PRESENT (169L) +#define NT_SLC_LR_PRESENT (170L) +#define NT_STA_COLORS (171L) +#define NT_STA_RX_PORTS (172L) +#define NT_TBH_DEBUG_DLN (173L) +#define NT_TBH_PRESENT (174L) +#define NT_TFD_PRESENT (175L) +#define NT_TPE_CATEGORIES (176L) +#define NT_TSM_OST_ONLY (177L) +#define NT_TS_APPEND (178L) +#define NT_TS_INJECT_PRESENT (179L) +#define NT_TX_CPY_PACKET_READERS (180L) +#define NT_TX_CPY_PRESENT (181L) +#define NT_TX_CPY_SIDEBAND_READERS (182L) +#define NT_TX_CPY_VARIANT (183L) +#define NT_TX_CPY_WRITERS (184L) +#define NT_TX_HOST_BUFFERS (185L) +#define NT_TX_INS_PRESENT (186L) +#define NT_TX_MTU_PROFILE_IFR (187L) +#define NT_TX_ON_TIMESTAMP (188L) +#define NT_TX_PORTS (189L) +#define NT_TX_PORT_REPLICATE (190L) +#define NT_TX_RPL_DEPTH (191L) +#define NT_TX_RPL_EXT_CATEGORIES (192L) +#define NT_TX_RPL_PRESENT (193L) +#define NT_TYPE_ID (194L) +#define NT_USE_TRIPLE_SPEED (195L) +#define NT_UUID (196L) +#define NT_VERSION (197L) +#define NT_VERSION_ID (198L) +#define NT_VLI_PRESENT (199L) + +#endif /* _NTHW_FPGA_PARAMETERS_DEFS_ */ diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_registers_defs.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_registers_defs.h new file mode 100644 index 0000000000..3948ed3ae3 --- /dev/null +++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_registers_defs.h @@ -0,0 +1,7277 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTHW_FPGA_REGISTERS_DEFS_ +#define _NTHW_FPGA_REGISTERS_DEFS_ + +/* CAT */ +#define CAT_CCE_CTRL (1000L) +#define CAT_CCE_CTRL_ADR (1001L) +#define CAT_CCE_CTRL_CNT (1002L) +#define CAT_CCE_DATA (1003L) +#define CAT_CCE_DATA_IMM (1004L) +#define CAT_CCE_DATA_IND (1005L) +#define CAT_CCS_CTRL (1006L) +#define CAT_CCS_CTRL_ADR (1007L) +#define CAT_CCS_CTRL_CNT (1008L) +#define CAT_CCS_DATA (1009L) +#define CAT_CCS_DATA_COR (1010L) +#define CAT_CCS_DATA_COR_EN (1011L) +#define CAT_CCS_DATA_EPP (1012L) +#define CAT_CCS_DATA_EPP_EN (1013L) +#define CAT_CCS_DATA_HSH (1014L) +#define CAT_CCS_DATA_HSH_EN (1015L) +#define CAT_CCS_DATA_HST (1016L) +#define CAT_CCS_DATA_HST_EN (1017L) +#define CAT_CCS_DATA_IPF (1018L) +#define CAT_CCS_DATA_IPF_EN (1019L) +#define CAT_CCS_DATA_MSK (1020L) +#define CAT_CCS_DATA_MSK_EN (1021L) +#define CAT_CCS_DATA_PDB (1022L) +#define CAT_CCS_DATA_PDB_EN (1023L) +#define CAT_CCS_DATA_QSL (1024L) +#define CAT_CCS_DATA_QSL_EN (1025L) +#define CAT_CCS_DATA_RRB (1026L) +#define CAT_CCS_DATA_RRB_EN (1027L) +#define CAT_CCS_DATA_SB0_DATA (1028L) +#define CAT_CCS_DATA_SB0_TYPE (1029L) +#define CAT_CCS_DATA_SB1_DATA (1030L) +#define CAT_CCS_DATA_SB1_TYPE (1031L) +#define CAT_CCS_DATA_SB2_DATA (1032L) +#define CAT_CCS_DATA_SB2_TYPE (1033L) +#define CAT_CCS_DATA_SLC (1034L) +#define CAT_CCS_DATA_SLC_EN (1035L) +#define CAT_CCS_DATA_TPE (1036L) +#define CAT_CCS_DATA_TPE_EN (1037L) +#define CAT_CCT_CTRL (1038L) +#define CAT_CCT_CTRL_ADR (1039L) +#define CAT_CCT_CTRL_CNT (1040L) +#define CAT_CCT_DATA (1041L) +#define CAT_CCT_DATA_COLOR (1042L) +#define CAT_CCT_DATA_KM (1043L) +#define CAT_CFN_CTRL (1044L) +#define CAT_CFN_CTRL_ADR (1045L) +#define CAT_CFN_CTRL_CNT (1046L) +#define CAT_CFN_DATA (1047L) +#define CAT_CFN_DATA_ENABLE (1048L) +#define CAT_CFN_DATA_ERR_CV (1049L) +#define CAT_CFN_DATA_ERR_FCS (1050L) +#define CAT_CFN_DATA_ERR_INV (1051L) +#define CAT_CFN_DATA_ERR_L3_CS (1052L) +#define CAT_CFN_DATA_ERR_L4_CS (1053L) +#define CAT_CFN_DATA_ERR_TNL_L3_CS (1054L) +#define CAT_CFN_DATA_ERR_TNL_L4_CS (1055L) +#define CAT_CFN_DATA_ERR_TNL_TTL_EXP (1056L) +#define CAT_CFN_DATA_ERR_TRUNC (1057L) +#define CAT_CFN_DATA_ERR_TTL_EXP (1058L) +#define CAT_CFN_DATA_FLM_OR (1059L) +#define CAT_CFN_DATA_INV (1060L) +#define CAT_CFN_DATA_KM0_OR (1061L) +#define CAT_CFN_DATA_KM1_OR (1062L) +#define CAT_CFN_DATA_KM_OR (1063L) +#define CAT_CFN_DATA_LC (1064L) +#define CAT_CFN_DATA_LC_INV (1065L) +#define CAT_CFN_DATA_MAC_PORT (1066L) +#define CAT_CFN_DATA_PM_AND_INV (1067L) +#define CAT_CFN_DATA_PM_CMB (1068L) +#define CAT_CFN_DATA_PM_CMP (1069L) +#define CAT_CFN_DATA_PM_DCT (1070L) +#define CAT_CFN_DATA_PM_EXT_INV (1071L) +#define CAT_CFN_DATA_PM_INV (1072L) +#define CAT_CFN_DATA_PM_OR_INV (1073L) +#define CAT_CFN_DATA_PTC_CFP (1074L) +#define CAT_CFN_DATA_PTC_FRAG (1075L) +#define CAT_CFN_DATA_PTC_INV (1076L) +#define CAT_CFN_DATA_PTC_IP_PROT (1077L) +#define CAT_CFN_DATA_PTC_ISL (1078L) +#define CAT_CFN_DATA_PTC_L2 (1079L) +#define CAT_CFN_DATA_PTC_L3 (1080L) +#define CAT_CFN_DATA_PTC_L4 (1081L) +#define CAT_CFN_DATA_PTC_MAC (1082L) +#define CAT_CFN_DATA_PTC_MPLS (1083L) +#define CAT_CFN_DATA_PTC_TNL_FRAG (1084L) +#define CAT_CFN_DATA_PTC_TNL_IP_PROT (1085L) +#define CAT_CFN_DATA_PTC_TNL_L2 (1086L) +#define CAT_CFN_DATA_PTC_TNL_L3 (1087L) +#define CAT_CFN_DATA_PTC_TNL_L4 (1088L) +#define CAT_CFN_DATA_PTC_TNL_MPLS (1089L) +#define CAT_CFN_DATA_PTC_TNL_VLAN (1090L) +#define CAT_CFN_DATA_PTC_TUNNEL (1091L) +#define CAT_CFN_DATA_PTC_VLAN (1092L) +#define CAT_CFN_DATA_PTC_VNTAG (1093L) +#define CAT_COT_CTRL (1094L) +#define CAT_COT_CTRL_ADR (1095L) +#define CAT_COT_CTRL_CNT (1096L) +#define CAT_COT_DATA (1097L) +#define CAT_COT_DATA_COLOR (1098L) +#define CAT_COT_DATA_KM (1099L) +#define CAT_COT_DATA_NFV_SB (1100L) +#define CAT_CTE_CTRL (1101L) +#define CAT_CTE_CTRL_ADR (1102L) +#define CAT_CTE_CTRL_CNT (1103L) +#define CAT_CTE_DATA (1104L) +#define CAT_CTE_DATA_COL_ENABLE (1105L) +#define CAT_CTE_DATA_COR_ENABLE (1106L) +#define CAT_CTE_DATA_EPP_ENABLE (1107L) +#define CAT_CTE_DATA_HSH_ENABLE (1108L) +#define CAT_CTE_DATA_HST_ENABLE (1109L) +#define CAT_CTE_DATA_IPF_ENABLE (1110L) +#define CAT_CTE_DATA_MSK_ENABLE (1111L) +#define CAT_CTE_DATA_PDB_ENABLE (1112L) +#define CAT_CTE_DATA_QSL_ENABLE (1113L) +#define CAT_CTE_DATA_RRB_ENABLE (1114L) +#define CAT_CTE_DATA_SLC_ENABLE (1115L) +#define CAT_CTE_DATA_TPE_ENABLE (1116L) +#define CAT_CTE_DATA_TX_INS_ENABLE (1117L) +#define CAT_CTE_DATA_TX_RPL_ENABLE (1118L) +#define CAT_CTS_CTRL (1119L) +#define CAT_CTS_CTRL_ADR (1120L) +#define CAT_CTS_CTRL_CNT (1121L) +#define CAT_CTS_DATA (1122L) +#define CAT_CTS_DATA_CAT_A (1123L) +#define CAT_CTS_DATA_CAT_B (1124L) +#define CAT_DCT_CTRL (1125L) +#define CAT_DCT_CTRL_ADR (1126L) +#define CAT_DCT_CTRL_CNT (1127L) +#define CAT_DCT_DATA (1128L) +#define CAT_DCT_DATA_RES (1129L) +#define CAT_DCT_SEL (1130L) +#define CAT_DCT_SEL_LU (1131L) +#define CAT_EXO_CTRL (1132L) +#define CAT_EXO_CTRL_ADR (1133L) +#define CAT_EXO_CTRL_CNT (1134L) +#define CAT_EXO_DATA (1135L) +#define CAT_EXO_DATA_DYN (1136L) +#define CAT_EXO_DATA_OFS (1137L) +#define CAT_FCE_CTRL (1138L) +#define CAT_FCE_CTRL_ADR (1139L) +#define CAT_FCE_CTRL_CNT (1140L) +#define CAT_FCE_DATA (1141L) +#define CAT_FCE_DATA_ENABLE (1142L) +#define CAT_FCS_CTRL (1143L) +#define CAT_FCS_CTRL_ADR (1144L) +#define CAT_FCS_CTRL_CNT (1145L) +#define CAT_FCS_DATA (1146L) +#define CAT_FCS_DATA_CATEGORY (1147L) +#define CAT_FTE0_CTRL (1148L) +#define CAT_FTE0_CTRL_ADR (1149L) +#define CAT_FTE0_CTRL_CNT (1150L) +#define CAT_FTE0_DATA (1151L) +#define CAT_FTE0_DATA_ENABLE (1152L) +#define CAT_FTE1_CTRL (1153L) +#define CAT_FTE1_CTRL_ADR (1154L) +#define CAT_FTE1_CTRL_CNT (1155L) +#define CAT_FTE1_DATA (1156L) +#define CAT_FTE1_DATA_ENABLE (1157L) +#define CAT_FTE_CTRL (1158L) +#define CAT_FTE_CTRL_ADR (1159L) +#define CAT_FTE_CTRL_CNT (1160L) +#define CAT_FTE_DATA (1161L) +#define CAT_FTE_DATA_ENABLE (1162L) +#define CAT_FTE_FLM_CTRL (1163L) +#define CAT_FTE_FLM_CTRL_ADR (1164L) +#define CAT_FTE_FLM_CTRL_CNT (1165L) +#define CAT_FTE_FLM_DATA (1166L) +#define CAT_FTE_FLM_DATA_ENABLE (1167L) +#define CAT_JOIN (1168L) +#define CAT_JOIN_J1 (1169L) +#define CAT_JOIN_J2 (1170L) +#define CAT_KCC (1171L) +#define CAT_KCC_CTRL (1172L) +#define CAT_KCC_CTRL_ADR (1173L) +#define CAT_KCC_CTRL_CNT (1174L) +#define CAT_KCC_DATA (1175L) +#define CAT_KCC_DATA_CATEGORY (1176L) +#define CAT_KCC_DATA_ID (1177L) +#define CAT_KCC_DATA_KEY (1178L) +#define CAT_KCE0_CTRL (1179L) +#define CAT_KCE0_CTRL_ADR (1180L) +#define CAT_KCE0_CTRL_CNT (1181L) +#define CAT_KCE0_DATA (1182L) +#define CAT_KCE0_DATA_ENABLE (1183L) +#define CAT_KCE1_CTRL (1184L) +#define CAT_KCE1_CTRL_ADR (1185L) +#define CAT_KCE1_CTRL_CNT (1186L) +#define CAT_KCE1_DATA (1187L) +#define CAT_KCE1_DATA_ENABLE (1188L) +#define CAT_KCE_CTRL (1189L) +#define CAT_KCE_CTRL_ADR (1190L) +#define CAT_KCE_CTRL_CNT (1191L) +#define CAT_KCE_DATA (1192L) +#define CAT_KCE_DATA_ENABLE (1193L) +#define CAT_KCS0_CTRL (1194L) +#define CAT_KCS0_CTRL_ADR (1195L) +#define CAT_KCS0_CTRL_CNT (1196L) +#define CAT_KCS0_DATA (1197L) +#define CAT_KCS0_DATA_CATEGORY (1198L) +#define CAT_KCS1_CTRL (1199L) +#define CAT_KCS1_CTRL_ADR (1200L) +#define CAT_KCS1_CTRL_CNT (1201L) +#define CAT_KCS1_DATA (1202L) +#define CAT_KCS1_DATA_CATEGORY (1203L) +#define CAT_KCS_CTRL (1204L) +#define CAT_KCS_CTRL_ADR (1205L) +#define CAT_KCS_CTRL_CNT (1206L) +#define CAT_KCS_DATA (1207L) +#define CAT_KCS_DATA_CATEGORY (1208L) +#define CAT_LEN_CTRL (1209L) +#define CAT_LEN_CTRL_ADR (1210L) +#define CAT_LEN_CTRL_CNT (1211L) +#define CAT_LEN_DATA (1212L) +#define CAT_LEN_DATA_DYN1 (1213L) +#define CAT_LEN_DATA_DYN2 (1214L) +#define CAT_LEN_DATA_INV (1215L) +#define CAT_LEN_DATA_LOWER (1216L) +#define CAT_LEN_DATA_UPPER (1217L) +#define CAT_RCK_CTRL (1218L) +#define CAT_RCK_CTRL_ADR (1219L) +#define CAT_RCK_CTRL_CNT (1220L) +#define CAT_RCK_DATA (1221L) +#define CAT_RCK_DATA_CM0U (1222L) +#define CAT_RCK_DATA_CM1U (1223L) +#define CAT_RCK_DATA_CM2U (1224L) +#define CAT_RCK_DATA_CM3U (1225L) +#define CAT_RCK_DATA_CM4U (1226L) +#define CAT_RCK_DATA_CM5U (1227L) +#define CAT_RCK_DATA_CM6U (1228L) +#define CAT_RCK_DATA_CM7U (1229L) +#define CAT_RCK_DATA_CML0 (1230L) +#define CAT_RCK_DATA_CML1 (1231L) +#define CAT_RCK_DATA_CML2 (1232L) +#define CAT_RCK_DATA_CML3 (1233L) +#define CAT_RCK_DATA_CML4 (1234L) +#define CAT_RCK_DATA_CML5 (1235L) +#define CAT_RCK_DATA_CML6 (1236L) +#define CAT_RCK_DATA_CML7 (1237L) +#define CAT_RCK_DATA_SEL0 (1238L) +#define CAT_RCK_DATA_SEL1 (1239L) +#define CAT_RCK_DATA_SEL2 (1240L) +#define CAT_RCK_DATA_SEL3 (1241L) +#define CAT_RCK_DATA_SEL4 (1242L) +#define CAT_RCK_DATA_SEL5 (1243L) +#define CAT_RCK_DATA_SEL6 (1244L) +#define CAT_RCK_DATA_SEL7 (1245L) +#define CAT_RCK_DATA_SEU0 (1246L) +#define CAT_RCK_DATA_SEU1 (1247L) +#define CAT_RCK_DATA_SEU2 (1248L) +#define CAT_RCK_DATA_SEU3 (1249L) +#define CAT_RCK_DATA_SEU4 (1250L) +#define CAT_RCK_DATA_SEU5 (1251L) +#define CAT_RCK_DATA_SEU6 (1252L) +#define CAT_RCK_DATA_SEU7 (1253L) +/* CB */ +#define CB_CTRL (1254L) +#define CB_CTRL_BP (1255L) +#define CB_CTRL_BYPASS (1256L) +#define CB_CTRL_ENABLE (1257L) +#define CB_CTRL_QMA (1258L) +#define CB_CTRL_QME (1259L) +#define CB_DBG_BP (1260L) +#define CB_DBG_BP_CNT (1261L) +#define CB_DBG_DQ (1262L) +#define CB_DBG_DQ_MAX (1263L) +#define CB_DBG_EGS_QUEUE (1264L) +#define CB_DBG_EGS_QUEUE_ADD (1265L) +#define CB_DBG_EGS_QUEUE_AND (1266L) +#define CB_DBG_FREE1200 (1267L) +#define CB_DBG_FREE1200_CNT (1268L) +#define CB_DBG_FREE1800 (1269L) +#define CB_DBG_FREE1800_CNT (1270L) +#define CB_DBG_FREE600 (1271L) +#define CB_DBG_FREE600_CNT (1272L) +#define CB_DBG_H16 (1273L) +#define CB_DBG_H16_CNT (1274L) +#define CB_DBG_H32 (1275L) +#define CB_DBG_H32_CNT (1276L) +#define CB_DBG_H64 (1277L) +#define CB_DBG_H64_CNT (1278L) +#define CB_DBG_HAVE (1279L) +#define CB_DBG_HAVE_CNT (1280L) +#define CB_DBG_IGS_QUEUE (1281L) +#define CB_DBG_IGS_QUEUE_ADD (1282L) +#define CB_DBG_IGS_QUEUE_AND (1283L) +#define CB_DBG_QM_CELL_CNT (1284L) +#define CB_DBG_QM_CELL_CNT_CNT (1285L) +#define CB_DBG_QM_CELL_XOR (1286L) +#define CB_DBG_QM_CELL_XOR_XOR (1287L) +#define CB_QPM_CTRL (1288L) +#define CB_QPM_CTRL_ADR (1289L) +#define CB_QPM_CTRL_CNT (1290L) +#define CB_QPM_DATA (1291L) +#define CB_QPM_DATA_P (1292L) +#define CB_QUEUE_MAX (1293L) +#define CB_QUEUE_MAX_MAX (1294L) +#define CB_STATUS (1295L) +#define CB_STATUS_BP (1296L) +#define CB_STATUS_DB (1297L) +#define CB_STATUS_EMPTY (1298L) +#define CB_STATUS_IDLE (1299L) +#define CB_STATUS_OVF (1300L) +#define CB_TS_RATE (1301L) +#define CB_TS_RATE_CNT (1302L) +#define CB_TS_SAVE (1303L) +#define CB_TS_SAVE_MAX (1304L) +/* CCIP */ +#define CCIP_AFU_ID_L (1305L) +#define CCIP_AFU_ID_L_ID (1306L) +#define CCIP_AFU_ID_U (1307L) +#define CCIP_AFU_ID_U_ID (1308L) +#define CCIP_CONTROL (1309L) +#define CCIP_CONTROL_FENCE (1310L) +#define CCIP_DFH (1311L) +#define CCIP_DFH_AFU_VER_MAJOR (1312L) +#define CCIP_DFH_AFU_VER_MINOR (1313L) +#define CCIP_DFH_CCIP_VER (1314L) +#define CCIP_DFH_END (1315L) +#define CCIP_DFH_FEATURE_TYPE (1316L) +#define CCIP_DFH_NEXT (1317L) +#define CCIP_RSVD0 (1318L) +#define CCIP_RSVD0_RSVD (1319L) +#define CCIP_RSVD1 (1320L) +#define CCIP_RSVD1_RSVD (1321L) +#define CCIP_STATUS (1322L) +#define CCIP_STATUS_ERR (1323L) +#define CCIP_STATUS_PWR (1324L) +/* CFP4_CTRL_GBOX */ +#define CFP4_CTRL_GBOX_CFG (1325L) +#define CFP4_CTRL_GBOX_CFG_GLB_ALARMN (1326L) +#define CFP4_CTRL_GBOX_CFG_INTERR (1327L) +#define CFP4_CTRL_GBOX_CFG_MOD_ABS (1328L) +#define CFP4_CTRL_GBOX_CFG_MOD_LOPWR (1329L) +#define CFP4_CTRL_GBOX_CFG_MOD_RSTN (1330L) +#define CFP4_CTRL_GBOX_CFG_NRESET (1331L) +#define CFP4_CTRL_GBOX_CFG_RXLOS (1332L) +#define CFP4_CTRL_GBOX_CFG_TXDIS (1333L) +#define CFP4_CTRL_GBOX_CFP4 (1334L) +#define CFP4_CTRL_GBOX_CFP4_GLB_ALARMN (1335L) +#define CFP4_CTRL_GBOX_CFP4_MOD_ABS (1336L) +#define CFP4_CTRL_GBOX_CFP4_MOD_LOPWR (1337L) +#define CFP4_CTRL_GBOX_CFP4_MOD_RSTN (1338L) +#define CFP4_CTRL_GBOX_CFP4_RXLOS (1339L) +#define CFP4_CTRL_GBOX_CFP4_TXDIS (1340L) +#define CFP4_CTRL_GBOX_GBOX (1341L) +#define CFP4_CTRL_GBOX_GBOX_INTERR (1342L) +#define CFP4_CTRL_GBOX_GBOX_NRESET (1343L) +#define CFP4_CTRL_GBOX_GPIO (1344L) +#define CFP4_CTRL_GBOX_GPIO_GLB_ALARMN (1345L) +#define CFP4_CTRL_GBOX_GPIO_INTERR (1346L) +#define CFP4_CTRL_GBOX_GPIO_MOD_ABS (1347L) +#define CFP4_CTRL_GBOX_GPIO_MOD_LOPWR (1348L) +#define CFP4_CTRL_GBOX_GPIO_MOD_RSTN (1349L) +#define CFP4_CTRL_GBOX_GPIO_NRESET (1350L) +#define CFP4_CTRL_GBOX_GPIO_RXLOS (1351L) +#define CFP4_CTRL_GBOX_GPIO_TXDIS (1352L) +/* COR */ +#define COR_CTRL (1393L) +#define COR_CTRL_EN (1394L) +#define COR_DBG_COR_CNT (1395L) +#define COR_DBG_COR_CNT_VAL (1396L) +#define COR_DBG_COR_ID (1397L) +#define COR_DBG_COR_ID_VAL (1398L) +#define COR_DBG_COR_LO (1399L) +#define COR_DBG_COR_LO_VAL (1400L) +#define COR_DBG_COR_UP (1401L) +#define COR_DBG_COR_UP_VAL (1402L) +#define COR_DCEO (1403L) +#define COR_DCEO_VAL (1404L) +#define COR_DCSO (1405L) +#define COR_DCSO_VAL (1406L) +#define COR_DEEO (1407L) +#define COR_DEEO_VAL (1408L) +#define COR_DEO (1409L) +#define COR_DEO_VAL (1410L) +#define COR_DESO (1411L) +#define COR_DESO_VAL (1412L) +#define COR_DSEO (1413L) +#define COR_DSEO_VAL (1414L) +#define COR_DSO (1415L) +#define COR_DSO_VAL (1416L) +#define COR_DSSO (1417L) +#define COR_DSSO_VAL (1418L) +#define COR_RCP_CTRL (1419L) +#define COR_RCP_CTRL_ADR (1420L) +#define COR_RCP_CTRL_CNT (1421L) +#define COR_RCP_DATA (1422L) +#define COR_RCP_DATA_CBM1 (1423L) +#define COR_RCP_DATA_EN (1424L) +#define COR_RCP_DATA_END_PROT (1425L) +#define COR_RCP_DATA_END_STATIC (1426L) +#define COR_RCP_DATA_IP_CHK (1427L) +#define COR_RCP_DATA_IP_DSCP (1428L) +#define COR_RCP_DATA_IP_DST (1429L) +#define COR_RCP_DATA_IP_ECN (1430L) +#define COR_RCP_DATA_IP_FLAGS (1431L) +#define COR_RCP_DATA_IP_FLOW (1432L) +#define COR_RCP_DATA_IP_HOP (1433L) +#define COR_RCP_DATA_IP_IDENT (1434L) +#define COR_RCP_DATA_IP_NXTHDR (1435L) +#define COR_RCP_DATA_IP_SRC (1436L) +#define COR_RCP_DATA_IP_TC (1437L) +#define COR_RCP_DATA_IP_TTL (1438L) +#define COR_RCP_DATA_MAX_LEN (1439L) +#define COR_RCP_DATA_PROT_OFS1 (1440L) +#define COR_RCP_DATA_START_PROT (1441L) +#define COR_RCP_DATA_START_STATIC (1442L) +#define COR_RCP_DATA_STTC_OFS1 (1443L) +#define COR_RCP_DATA_TCP_CHK (1444L) +#define COR_RCP_DATA_TCP_DST (1445L) +#define COR_RCP_DATA_TCP_SEQ (1446L) +#define COR_RCP_DATA_TCP_SRC (1447L) +#define COR_RCP_DATA_TNL (1448L) +#define COR_RCP_DATA_UDP_CHK (1449L) +#define COR_RCP_DATA_UDP_DST (1450L) +#define COR_RCP_DATA_UDP_SRC (1451L) +/* CPY */ +#define CPY_WRITER0_CTRL (1452L) +#define CPY_WRITER0_CTRL_ADR (1453L) +#define CPY_WRITER0_CTRL_CNT (1454L) +#define CPY_WRITER0_DATA (1455L) +#define CPY_WRITER0_DATA_DYN (1456L) +#define CPY_WRITER0_DATA_LEN (1457L) +#define CPY_WRITER0_DATA_MASK_POINTER (1458L) +#define CPY_WRITER0_DATA_OFS (1459L) +#define CPY_WRITER0_DATA_READER_SELECT (1460L) +#define CPY_WRITER0_MASK_CTRL (1461L) +#define CPY_WRITER0_MASK_CTRL_ADR (1462L) +#define CPY_WRITER0_MASK_CTRL_CNT (1463L) +#define CPY_WRITER0_MASK_DATA (1464L) +#define CPY_WRITER0_MASK_DATA_BYTE_MASK (1465L) +#define CPY_WRITER1_CTRL (1466L) +#define CPY_WRITER1_CTRL_ADR (1467L) +#define CPY_WRITER1_CTRL_CNT (1468L) +#define CPY_WRITER1_DATA (1469L) +#define CPY_WRITER1_DATA_DYN (1470L) +#define CPY_WRITER1_DATA_LEN (1471L) +#define CPY_WRITER1_DATA_MASK_POINTER (1472L) +#define CPY_WRITER1_DATA_OFS (1473L) +#define CPY_WRITER1_DATA_READER_SELECT (1474L) +#define CPY_WRITER1_MASK_CTRL (1475L) +#define CPY_WRITER1_MASK_CTRL_ADR (1476L) +#define CPY_WRITER1_MASK_CTRL_CNT (1477L) +#define CPY_WRITER1_MASK_DATA (1478L) +#define CPY_WRITER1_MASK_DATA_BYTE_MASK (1479L) +#define CPY_WRITER2_CTRL (1480L) +#define CPY_WRITER2_CTRL_ADR (1481L) +#define CPY_WRITER2_CTRL_CNT (1482L) +#define CPY_WRITER2_DATA (1483L) +#define CPY_WRITER2_DATA_DYN (1484L) +#define CPY_WRITER2_DATA_LEN (1485L) +#define CPY_WRITER2_DATA_MASK_POINTER (1486L) +#define CPY_WRITER2_DATA_OFS (1487L) +#define CPY_WRITER2_DATA_READER_SELECT (1488L) +#define CPY_WRITER2_MASK_CTRL (1489L) +#define CPY_WRITER2_MASK_CTRL_ADR (1490L) +#define CPY_WRITER2_MASK_CTRL_CNT (1491L) +#define CPY_WRITER2_MASK_DATA (1492L) +#define CPY_WRITER2_MASK_DATA_BYTE_MASK (1493L) +#define CPY_WRITER3_CTRL (1494L) +#define CPY_WRITER3_CTRL_ADR (1495L) +#define CPY_WRITER3_CTRL_CNT (1496L) +#define CPY_WRITER3_DATA (1497L) +#define CPY_WRITER3_DATA_DYN (1498L) +#define CPY_WRITER3_DATA_LEN (1499L) +#define CPY_WRITER3_DATA_MASK_POINTER (1500L) +#define CPY_WRITER3_DATA_OFS (1501L) +#define CPY_WRITER3_DATA_READER_SELECT (1502L) +#define CPY_WRITER3_MASK_CTRL (1503L) +#define CPY_WRITER3_MASK_CTRL_ADR (1504L) +#define CPY_WRITER3_MASK_CTRL_CNT (1505L) +#define CPY_WRITER3_MASK_DATA (1506L) +#define CPY_WRITER3_MASK_DATA_BYTE_MASK (1507L) +#define CPY_WRITER4_CTRL (1508L) +#define CPY_WRITER4_CTRL_ADR (1509L) +#define CPY_WRITER4_CTRL_CNT (1510L) +#define CPY_WRITER4_DATA (1511L) +#define CPY_WRITER4_DATA_DYN (1512L) +#define CPY_WRITER4_DATA_LEN (1513L) +#define CPY_WRITER4_DATA_MASK_POINTER (1514L) +#define CPY_WRITER4_DATA_OFS (1515L) +#define CPY_WRITER4_DATA_READER_SELECT (1516L) +#define CPY_WRITER4_MASK_CTRL (1517L) +#define CPY_WRITER4_MASK_CTRL_ADR (1518L) +#define CPY_WRITER4_MASK_CTRL_CNT (1519L) +#define CPY_WRITER4_MASK_DATA (1520L) +#define CPY_WRITER4_MASK_DATA_BYTE_MASK (1521L) +#define CPY_WRITER5_CTRL (1522L) +#define CPY_WRITER5_CTRL_ADR (1523L) +#define CPY_WRITER5_CTRL_CNT (1524L) +#define CPY_WRITER5_DATA (1525L) +#define CPY_WRITER5_DATA_DYN (1526L) +#define CPY_WRITER5_DATA_LEN (1527L) +#define CPY_WRITER5_DATA_MASK_POINTER (1528L) +#define CPY_WRITER5_DATA_OFS (1529L) +#define CPY_WRITER5_DATA_READER_SELECT (1530L) +#define CPY_WRITER5_MASK_CTRL (1531L) +#define CPY_WRITER5_MASK_CTRL_ADR (1532L) +#define CPY_WRITER5_MASK_CTRL_CNT (1533L) +#define CPY_WRITER5_MASK_DATA (1534L) +#define CPY_WRITER5_MASK_DATA_BYTE_MASK (1535L) +/* CSU */ +#define CSU_RCP_CTRL (1536L) +#define CSU_RCP_CTRL_ADR (1537L) +#define CSU_RCP_CTRL_CNT (1538L) +#define CSU_RCP_DATA (1539L) +#define CSU_RCP_DATA_IL3_CMD (1540L) +#define CSU_RCP_DATA_IL4_CMD (1541L) +#define CSU_RCP_DATA_OL3_CMD (1542L) +#define CSU_RCP_DATA_OL4_CMD (1543L) +/* DBS */ +#define DBS_RX_AM_CTRL (1544L) +#define DBS_RX_AM_CTRL_ADR (1545L) +#define DBS_RX_AM_CTRL_CNT (1546L) +#define DBS_RX_AM_DATA (1547L) +#define DBS_RX_AM_DATA_ENABLE (1548L) +#define DBS_RX_AM_DATA_GPA (1549L) +#define DBS_RX_AM_DATA_HID (1550L) +#define DBS_RX_AM_DATA_INT (1551L) +#define DBS_RX_AM_DATA_PCKED (1552L) +#define DBS_RX_CONTROL (1553L) +#define DBS_RX_CONTROL_AME (1554L) +#define DBS_RX_CONTROL_AMS (1555L) +#define DBS_RX_CONTROL_LQ (1556L) +#define DBS_RX_CONTROL_QE (1557L) +#define DBS_RX_CONTROL_UWE (1558L) +#define DBS_RX_CONTROL_UWS (1559L) +#define DBS_RX_DR_CTRL (1560L) +#define DBS_RX_DR_CTRL_ADR (1561L) +#define DBS_RX_DR_CTRL_CNT (1562L) +#define DBS_RX_DR_DATA (1563L) +#define DBS_RX_DR_DATA_GPA (1564L) +#define DBS_RX_DR_DATA_HDR (1565L) +#define DBS_RX_DR_DATA_HID (1566L) +#define DBS_RX_DR_DATA_PCKED (1567L) +#define DBS_RX_DR_DATA_QS (1568L) +#define DBS_RX_IDLE (1569L) +#define DBS_RX_IDLE_BUSY (1570L) +#define DBS_RX_IDLE_IDLE (1571L) +#define DBS_RX_IDLE_QUEUE (1572L) +#define DBS_RX_INIT (1573L) +#define DBS_RX_INIT_BUSY (1574L) +#define DBS_RX_INIT_INIT (1575L) +#define DBS_RX_INIT_QUEUE (1576L) +#define DBS_RX_INIT_VAL (1577L) +#define DBS_RX_INIT_VAL_IDX (1578L) +#define DBS_RX_INIT_VAL_PTR (1579L) +#define DBS_RX_PTR (1580L) +#define DBS_RX_PTR_PTR (1581L) +#define DBS_RX_PTR_QUEUE (1582L) +#define DBS_RX_PTR_VALID (1583L) +#define DBS_RX_UW_CTRL (1584L) +#define DBS_RX_UW_CTRL_ADR (1585L) +#define DBS_RX_UW_CTRL_CNT (1586L) +#define DBS_RX_UW_DATA (1587L) +#define DBS_RX_UW_DATA_GPA (1588L) +#define DBS_RX_UW_DATA_HID (1589L) +#define DBS_RX_UW_DATA_INT (1590L) +#define DBS_RX_UW_DATA_ISTK (1591L) +#define DBS_RX_UW_DATA_PCKED (1592L) +#define DBS_RX_UW_DATA_QS (1593L) +#define DBS_RX_UW_DATA_VEC (1594L) +#define DBS_STATUS (1595L) +#define DBS_STATUS_OK (1596L) +#define DBS_TX_AM_CTRL (1597L) +#define DBS_TX_AM_CTRL_ADR (1598L) +#define DBS_TX_AM_CTRL_CNT (1599L) +#define DBS_TX_AM_DATA (1600L) +#define DBS_TX_AM_DATA_ENABLE (1601L) +#define DBS_TX_AM_DATA_GPA (1602L) +#define DBS_TX_AM_DATA_HID (1603L) +#define DBS_TX_AM_DATA_INT (1604L) +#define DBS_TX_AM_DATA_PCKED (1605L) +#define DBS_TX_CONTROL (1606L) +#define DBS_TX_CONTROL_AME (1607L) +#define DBS_TX_CONTROL_AMS (1608L) +#define DBS_TX_CONTROL_LQ (1609L) +#define DBS_TX_CONTROL_QE (1610L) +#define DBS_TX_CONTROL_UWE (1611L) +#define DBS_TX_CONTROL_UWS (1612L) +#define DBS_TX_DR_CTRL (1613L) +#define DBS_TX_DR_CTRL_ADR (1614L) +#define DBS_TX_DR_CTRL_CNT (1615L) +#define DBS_TX_DR_DATA (1616L) +#define DBS_TX_DR_DATA_GPA (1617L) +#define DBS_TX_DR_DATA_HDR (1618L) +#define DBS_TX_DR_DATA_HID (1619L) +#define DBS_TX_DR_DATA_PCKED (1620L) +#define DBS_TX_DR_DATA_PORT (1621L) +#define DBS_TX_DR_DATA_QS (1622L) +#define DBS_TX_IDLE (1623L) +#define DBS_TX_IDLE_BUSY (1624L) +#define DBS_TX_IDLE_IDLE (1625L) +#define DBS_TX_IDLE_QUEUE (1626L) +#define DBS_TX_INIT (1627L) +#define DBS_TX_INIT_BUSY (1628L) +#define DBS_TX_INIT_INIT (1629L) +#define DBS_TX_INIT_QUEUE (1630L) +#define DBS_TX_INIT_VAL (1631L) +#define DBS_TX_INIT_VAL_IDX (1632L) +#define DBS_TX_INIT_VAL_PTR (1633L) +#define DBS_TX_PTR (1634L) +#define DBS_TX_PTR_PTR (1635L) +#define DBS_TX_PTR_QUEUE (1636L) +#define DBS_TX_PTR_VALID (1637L) +#define DBS_TX_QOS_CTRL (1638L) +#define DBS_TX_QOS_CTRL_ADR (1639L) +#define DBS_TX_QOS_CTRL_CNT (1640L) +#define DBS_TX_QOS_DATA (1641L) +#define DBS_TX_QOS_DATA_BS (1642L) +#define DBS_TX_QOS_DATA_EN (1643L) +#define DBS_TX_QOS_DATA_IR (1644L) +#define DBS_TX_QOS_DATA_MUL (1645L) +#define DBS_TX_QOS_RATE (1646L) +#define DBS_TX_QOS_RATE_DIV (1647L) +#define DBS_TX_QOS_RATE_MUL (1648L) +#define DBS_TX_QP_CTRL (1649L) +#define DBS_TX_QP_CTRL_ADR (1650L) +#define DBS_TX_QP_CTRL_CNT (1651L) +#define DBS_TX_QP_DATA (1652L) +#define DBS_TX_QP_DATA_VPORT (1653L) +#define DBS_TX_UW_CTRL (1654L) +#define DBS_TX_UW_CTRL_ADR (1655L) +#define DBS_TX_UW_CTRL_CNT (1656L) +#define DBS_TX_UW_DATA (1657L) +#define DBS_TX_UW_DATA_GPA (1658L) +#define DBS_TX_UW_DATA_HID (1659L) +#define DBS_TX_UW_DATA_INO (1660L) +#define DBS_TX_UW_DATA_INT (1661L) +#define DBS_TX_UW_DATA_ISTK (1662L) +#define DBS_TX_UW_DATA_PCKED (1663L) +#define DBS_TX_UW_DATA_QS (1664L) +#define DBS_TX_UW_DATA_VEC (1665L) +/* DDP */ +#define DDP_AGING_CTRL (1666L) +#define DDP_AGING_CTRL_AGING_RATE (1667L) +#define DDP_AGING_CTRL_MAX_CNT (1668L) +#define DDP_CTRL (1669L) +#define DDP_CTRL_INIT (1670L) +#define DDP_CTRL_INIT_DONE (1671L) +#define DDP_RCP_CTRL (1672L) +#define DDP_RCP_CTRL_ADR (1673L) +#define DDP_RCP_CTRL_CNT (1674L) +#define DDP_RCP_DATA (1675L) +#define DDP_RCP_DATA_EN (1676L) +#define DDP_RCP_DATA_GROUPID (1677L) +/* EPP */ +#define EPP_QUEUE_MTU_CTRL (1755L) +#define EPP_QUEUE_MTU_CTRL_ADR (1756L) +#define EPP_QUEUE_MTU_CTRL_CNT (1757L) +#define EPP_QUEUE_MTU_DATA (1758L) +#define EPP_QUEUE_MTU_DATA_MAX_MTU (1759L) +#define EPP_QUEUE_VPORT_CTRL (1760L) +#define EPP_QUEUE_VPORT_CTRL_ADR (1761L) +#define EPP_QUEUE_VPORT_CTRL_CNT (1762L) +#define EPP_QUEUE_VPORT_DATA (1763L) +#define EPP_QUEUE_VPORT_DATA_VPORT (1764L) +#define EPP_RCP_CTRL (1765L) +#define EPP_RCP_CTRL_ADR (1766L) +#define EPP_RCP_CTRL_CNT (1767L) +#define EPP_RCP_DATA (1768L) +#define EPP_RCP_DATA_FIXED_18B_L2_MTU (1769L) +#define EPP_RCP_DATA_QUEUE_MTU_EPP_EN (1770L) +#define EPP_RCP_DATA_QUEUE_QOS_EPP_EN (1771L) +#define EPP_RCP_DATA_SIZE_ADJUST_TXP (1772L) +#define EPP_RCP_DATA_SIZE_ADJUST_VPORT (1773L) +#define EPP_RCP_DATA_TX_MTU_EPP_EN (1774L) +#define EPP_RCP_DATA_TX_QOS_EPP_EN (1775L) +#define EPP_TXP_MTU_CTRL (1776L) +#define EPP_TXP_MTU_CTRL_ADR (1777L) +#define EPP_TXP_MTU_CTRL_CNT (1778L) +#define EPP_TXP_MTU_DATA (1779L) +#define EPP_TXP_MTU_DATA_MAX_MTU (1780L) +#define EPP_TXP_QOS_CTRL (1781L) +#define EPP_TXP_QOS_CTRL_ADR (1782L) +#define EPP_TXP_QOS_CTRL_CNT (1783L) +#define EPP_TXP_QOS_DATA (1784L) +#define EPP_TXP_QOS_DATA_BS (1785L) +#define EPP_TXP_QOS_DATA_EN (1786L) +#define EPP_TXP_QOS_DATA_IR (1787L) +#define EPP_TXP_QOS_DATA_IR_FRACTION (1788L) +#define EPP_VPORT_QOS_CTRL (1789L) +#define EPP_VPORT_QOS_CTRL_ADR (1790L) +#define EPP_VPORT_QOS_CTRL_CNT (1791L) +#define EPP_VPORT_QOS_DATA (1792L) +#define EPP_VPORT_QOS_DATA_BS (1793L) +#define EPP_VPORT_QOS_DATA_EN (1794L) +#define EPP_VPORT_QOS_DATA_IR (1795L) +#define EPP_VPORT_QOS_DATA_IR_FRACTION (1796L) +/* EQM */ +#define EQM_CTRL (1797L) +#define EQM_CTRL_DBG_CRC_ERR (1798L) +#define EQM_CTRL_DBG_FORCE_ERR (1799L) +#define EQM_CTRL_DBG_RMT_ERR (1800L) +#define EQM_CTRL_DBG_SYNC_ERR (1801L) +#define EQM_CTRL_ENABLE (1802L) +#define EQM_CTRL_MODE (1803L) +#define EQM_CTRL_PP_RST (1804L) +#define EQM_DBG (1805L) +#define EQM_DBG_FIFO_OF (1806L) +#define EQM_DBG_LCL_EGS_QKA_OF (1807L) +#define EQM_DBG_LCL_EGS_QLVL_OF (1808L) +#define EQM_DBG_QBLK_CREDITS (1809L) +#define EQM_STATUS (1810L) +#define EQM_STATUS_LCL_EGS_OF_ERR (1811L) +#define EQM_STATUS_NIF_CRC_ERR (1812L) +#define EQM_STATUS_NIF_PP_LOOP_LCK (1813L) +#define EQM_STATUS_NIF_RX_OF_ERR (1814L) +#define EQM_STATUS_NIF_SYNC_ERR (1815L) +#define EQM_STATUS_QM_CRC_ERR (1816L) +#define EQM_STATUS_RMT_EGS_OF_ERR (1817L) +#define EQM_STATUS_RMT_ERR (1818L) +#define EQM_STATUS_RMT_IGS_OF_ERR (1819L) +/* FHM */ +#define FHM_BACK_PRESSURE (1820L) +#define FHM_BACK_PRESSURE_NIF (1821L) +#define FHM_BACK_PRESSURE_RMC (1822L) +#define FHM_BACK_PRESSURE_RMC_S (1823L) +#define FHM_CRC_ERROR_NIF (1824L) +#define FHM_CRC_ERROR_NIF_CNT (1825L) +#define FHM_CRC_ERROR_SDC (1826L) +#define FHM_CRC_ERROR_SDC_CNT (1827L) +#define FHM_CTRL (1828L) +#define FHM_CTRL_CNT_CLR (1829L) +#define FHM_CTRL_ENABLE (1830L) +#define FHM_CTRL_MODE (1831L) +#define FHM_DEBUG_CRC (1832L) +#define FHM_DEBUG_CRC_FORCE_ERROR (1833L) +#define FHM_DEBUG_SDRAM_SIZE (1834L) +#define FHM_DEBUG_SDRAM_SIZE_MASK (1835L) +#define FHM_FILL_LEVEL (1836L) +#define FHM_FILL_LEVEL_CELLS (1837L) +#define FHM_MAC_MICRO_DROP (1838L) +#define FHM_MAC_MICRO_DROP_CNT (1839L) +#define FHM_MAX_FILL_LEVEL (1840L) +#define FHM_MAX_FILL_LEVEL_CELLS (1841L) +#define FHM_PKT_DROP (1842L) +#define FHM_PKT_DROP_CNT (1843L) +#define FHM_PKT_DROP_BYTES (1844L) +#define FHM_PKT_DROP_BYTES_CNT (1845L) +/* FLM */ +#define FLM_BUF_CTRL (1855L) +#define FLM_BUF_CTRL_INF_AVAIL (1856L) +#define FLM_BUF_CTRL_LRN_FREE (1857L) +#define FLM_BUF_CTRL_STA_AVAIL (1858L) +#define FLM_CONTROL (1859L) +#define FLM_CONTROL_CRCRD (1860L) +#define FLM_CONTROL_CRCWR (1861L) +#define FLM_CONTROL_EAB (1862L) +#define FLM_CONTROL_ENABLE (1863L) +#define FLM_CONTROL_INIT (1864L) +#define FLM_CONTROL_LDS (1865L) +#define FLM_CONTROL_LFS (1866L) +#define FLM_CONTROL_LIS (1867L) +#define FLM_CONTROL_PDS (1868L) +#define FLM_CONTROL_PIS (1869L) +#define FLM_CONTROL_RBL (1870L) +#define FLM_CONTROL_RDS (1871L) +#define FLM_CONTROL_RIS (1872L) +#define FLM_CONTROL_SPLIT_SDRAM_USAGE (1873L) +#define FLM_CONTROL_UDS (1874L) +#define FLM_CONTROL_UIS (1875L) +#define FLM_CONTROL_WPD (1876L) +#define FLM_INF_DATA (1877L) +#define FLM_INF_DATA_BYTES (1878L) +#define FLM_INF_DATA_BYT_A (1879L) +#define FLM_INF_DATA_BYT_B (1880L) +#define FLM_INF_DATA_CAUSE (1881L) +#define FLM_INF_DATA_EOR (1882L) +#define FLM_INF_DATA_ID (1883L) +#define FLM_INF_DATA_PACKETS (1884L) +#define FLM_INF_DATA_PCK_A (1885L) +#define FLM_INF_DATA_PCK_B (1886L) +#define FLM_INF_DATA_RTX_A (1887L) +#define FLM_INF_DATA_RTX_B (1888L) +#define FLM_INF_DATA_TCP_A (1889L) +#define FLM_INF_DATA_TCP_B (1890L) +#define FLM_INF_DATA_TS (1891L) +#define FLM_LOAD_APS (1892L) +#define FLM_LOAD_APS_APS (1893L) +#define FLM_LOAD_BIN (1894L) +#define FLM_LOAD_BIN_BIN (1895L) +#define FLM_LOAD_LPS (1896L) +#define FLM_LOAD_LPS_LPS (1897L) +#define FLM_LOAD_PPS (1898L) +#define FLM_LOAD_PPS_PPS (1899L) +#define FLM_LRN_CTRL (1900L) +#define FLM_LRN_CTRL_FREE (1901L) +#define FLM_LRN_DATA (1902L) +#define FLM_LRN_DATA_ADJ (1903L) +#define FLM_LRN_DATA_COLOR (1904L) +#define FLM_LRN_DATA_DSCP (1905L) +#define FLM_LRN_DATA_ENT (1906L) +#define FLM_LRN_DATA_EOR (1907L) +#define FLM_LRN_DATA_FILL (1908L) +#define FLM_LRN_DATA_FT (1909L) +#define FLM_LRN_DATA_FT_MBR (1910L) +#define FLM_LRN_DATA_FT_MISS (1911L) +#define FLM_LRN_DATA_GFI (1912L) +#define FLM_LRN_DATA_ID (1913L) +#define FLM_LRN_DATA_KID (1914L) +#define FLM_LRN_DATA_MBR_ID1 (1915L) +#define FLM_LRN_DATA_MBR_ID2 (1916L) +#define FLM_LRN_DATA_MBR_ID3 (1917L) +#define FLM_LRN_DATA_MBR_ID4 (1918L) +#define FLM_LRN_DATA_NAT_EN (1919L) +#define FLM_LRN_DATA_NAT_IP (1920L) +#define FLM_LRN_DATA_NAT_PORT (1921L) +#define FLM_LRN_DATA_OP (1922L) +#define FLM_LRN_DATA_PRIO (1923L) +#define FLM_LRN_DATA_PROT (1924L) +#define FLM_LRN_DATA_QFI (1925L) +#define FLM_LRN_DATA_QW0 (1926L) +#define FLM_LRN_DATA_QW4 (1927L) +#define FLM_LRN_DATA_RATE (1928L) +#define FLM_LRN_DATA_RQI (1929L) +#define FLM_LRN_DATA_SIZE (1930L) +#define FLM_LRN_DATA_STAT_PROF (1931L) +#define FLM_LRN_DATA_SW8 (1932L) +#define FLM_LRN_DATA_SW9 (1933L) +#define FLM_LRN_DATA_TAU (1934L) +#define FLM_LRN_DATA_TEID (1935L) +#define FLM_LRN_DATA_TTL (1936L) +#define FLM_LRN_DATA_VOL_IDX (1937L) +#define FLM_PRIO (1938L) +#define FLM_PRIO_FT0 (1939L) +#define FLM_PRIO_FT1 (1940L) +#define FLM_PRIO_FT2 (1941L) +#define FLM_PRIO_FT3 (1942L) +#define FLM_PRIO_LIMIT0 (1943L) +#define FLM_PRIO_LIMIT1 (1944L) +#define FLM_PRIO_LIMIT2 (1945L) +#define FLM_PRIO_LIMIT3 (1946L) +#define FLM_PST_CTRL (1947L) +#define FLM_PST_CTRL_ADR (1948L) +#define FLM_PST_CTRL_CNT (1949L) +#define FLM_PST_DATA (1950L) +#define FLM_PST_DATA_BP (1951L) +#define FLM_PST_DATA_PP (1952L) +#define FLM_PST_DATA_TP (1953L) +#define FLM_RCP_CTRL (1954L) +#define FLM_RCP_CTRL_ADR (1955L) +#define FLM_RCP_CTRL_CNT (1956L) +#define FLM_RCP_DATA (1957L) +#define FLM_RCP_DATA_A (1958L) +#define FLM_RCP_DATA_AUTO_IPV4_MASK (1959L) +#define FLM_RCP_DATA_B (1960L) +#define FLM_RCP_DATA_BYT_DYN (1961L) +#define FLM_RCP_DATA_BYT_OFS (1962L) +#define FLM_RCP_DATA_IPN (1963L) +#define FLM_RCP_DATA_ITF (1964L) +#define FLM_RCP_DATA_KID (1965L) +#define FLM_RCP_DATA_LOOKUP (1966L) +#define FLM_RCP_DATA_MASK (1967L) +#define FLM_RCP_DATA_OPN (1968L) +#define FLM_RCP_DATA_QW0_DYN (1969L) +#define FLM_RCP_DATA_QW0_OFS (1970L) +#define FLM_RCP_DATA_QW0_SEL (1971L) +#define FLM_RCP_DATA_QW4_DYN (1972L) +#define FLM_RCP_DATA_QW4_OFS (1973L) +#define FLM_RCP_DATA_SW8_DYN (1974L) +#define FLM_RCP_DATA_SW8_OFS (1975L) +#define FLM_RCP_DATA_SW8_SEL (1976L) +#define FLM_RCP_DATA_SW9_DYN (1977L) +#define FLM_RCP_DATA_SW9_OFS (1978L) +#define FLM_RCP_DATA_TXPLM (1979L) +#define FLM_SCRUB (1980L) +#define FLM_SCRUB_I (1981L) +#define FLM_STATUS (1982L) +#define FLM_STATUS_CALIBDONE (1983L) +#define FLM_STATUS_CRCERR (1984L) +#define FLM_STATUS_CRITICAL (1985L) +#define FLM_STATUS_EFT_BP (1986L) +#define FLM_STATUS_EFT_EVICT_BP (1987L) +#define FLM_STATUS_IDLE (1988L) +#define FLM_STATUS_INITDONE (1989L) +#define FLM_STATUS_PANIC (1990L) +#define FLM_STAT_AUL_DONE (1991L) +#define FLM_STAT_AUL_DONE_CNT (1992L) +#define FLM_STAT_AUL_FAIL (1993L) +#define FLM_STAT_AUL_FAIL_CNT (1994L) +#define FLM_STAT_AUL_IGNORE (1995L) +#define FLM_STAT_AUL_IGNORE_CNT (1996L) +#define FLM_STAT_CSH_HIT (1997L) +#define FLM_STAT_CSH_HIT_CNT (1998L) +#define FLM_STAT_CSH_MISS (1999L) +#define FLM_STAT_CSH_MISS_CNT (2000L) +#define FLM_STAT_CSH_UNH (2001L) +#define FLM_STAT_CSH_UNH_CNT (2002L) +#define FLM_STAT_CUC_MOVE (2003L) +#define FLM_STAT_CUC_MOVE_CNT (2004L) +#define FLM_STAT_CUC_START (2005L) +#define FLM_STAT_CUC_START_CNT (2006L) +#define FLM_STAT_FLOWS (2007L) +#define FLM_STAT_FLOWS_CNT (2008L) +#define FLM_STAT_INF_DONE (2009L) +#define FLM_STAT_INF_DONE_CNT (2010L) +#define FLM_STAT_INF_SKIP (2011L) +#define FLM_STAT_INF_SKIP_CNT (2012L) +#define FLM_STAT_LRN_DONE (2013L) +#define FLM_STAT_LRN_DONE_CNT (2014L) +#define FLM_STAT_LRN_FAIL (2015L) +#define FLM_STAT_LRN_FAIL_CNT (2016L) +#define FLM_STAT_LRN_IGNORE (2017L) +#define FLM_STAT_LRN_IGNORE_CNT (2018L) +#define FLM_STAT_PCK_DIS (2019L) +#define FLM_STAT_PCK_DIS_CNT (2020L) +#define FLM_STAT_PCK_HIT (2021L) +#define FLM_STAT_PCK_HIT_CNT (2022L) +#define FLM_STAT_PCK_MISS (2023L) +#define FLM_STAT_PCK_MISS_CNT (2024L) +#define FLM_STAT_PCK_UNH (2025L) +#define FLM_STAT_PCK_UNH_CNT (2026L) +#define FLM_STAT_PRB_DONE (2027L) +#define FLM_STAT_PRB_DONE_CNT (2028L) +#define FLM_STAT_PRB_IGNORE (2029L) +#define FLM_STAT_PRB_IGNORE_CNT (2030L) +#define FLM_STAT_REL_DONE (2031L) +#define FLM_STAT_REL_DONE_CNT (2032L) +#define FLM_STAT_REL_IGNORE (2033L) +#define FLM_STAT_REL_IGNORE_CNT (2034L) +#define FLM_STAT_STA_DONE (2035L) +#define FLM_STAT_STA_DONE_CNT (2036L) +#define FLM_STAT_TUL_DONE (2037L) +#define FLM_STAT_TUL_DONE_CNT (2038L) +#define FLM_STAT_UNL_DONE (2039L) +#define FLM_STAT_UNL_DONE_CNT (2040L) +#define FLM_STAT_UNL_IGNORE (2041L) +#define FLM_STAT_UNL_IGNORE_CNT (2042L) +#define FLM_STA_DATA (2043L) +#define FLM_STA_DATA_EOR (2044L) +#define FLM_STA_DATA_ID (2045L) +#define FLM_STA_DATA_LDS (2046L) +#define FLM_STA_DATA_LFS (2047L) +#define FLM_STA_DATA_LIS (2048L) +#define FLM_STA_DATA_PDS (2049L) +#define FLM_STA_DATA_PIS (2050L) +#define FLM_STA_DATA_RDS (2051L) +#define FLM_STA_DATA_RIS (2052L) +#define FLM_STA_DATA_UDS (2053L) +#define FLM_STA_DATA_UIS (2054L) +#define FLM_TIMEOUT (2055L) +#define FLM_TIMEOUT_T (2056L) +#define FLM_TRSWIN (2057L) +#define FLM_TRSWIN_S (2058L) +#define FLM_TRTWIN (2059L) +#define FLM_TRTWIN_T (2060L) +/* GFG */ +#define GFG_BURSTSIZE0 (2061L) +#define GFG_BURSTSIZE0_VAL (2062L) +#define GFG_BURSTSIZE1 (2063L) +#define GFG_BURSTSIZE1_VAL (2064L) +#define GFG_BURSTSIZE2 (2065L) +#define GFG_BURSTSIZE2_VAL (2066L) +#define GFG_BURSTSIZE3 (2067L) +#define GFG_BURSTSIZE3_VAL (2068L) +#define GFG_BURSTSIZE4 (2069L) +#define GFG_BURSTSIZE4_VAL (2070L) +#define GFG_BURSTSIZE5 (2071L) +#define GFG_BURSTSIZE5_VAL (2072L) +#define GFG_BURSTSIZE6 (2073L) +#define GFG_BURSTSIZE6_VAL (2074L) +#define GFG_BURSTSIZE7 (2075L) +#define GFG_BURSTSIZE7_VAL (2076L) +#define GFG_CTRL0 (2077L) +#define GFG_CTRL0_ENABLE (2078L) +#define GFG_CTRL0_MODE (2079L) +#define GFG_CTRL0_PRBS_EN (2080L) +#define GFG_CTRL0_SIZE (2081L) +#define GFG_CTRL1 (2082L) +#define GFG_CTRL1_ENABLE (2083L) +#define GFG_CTRL1_MODE (2084L) +#define GFG_CTRL1_PRBS_EN (2085L) +#define GFG_CTRL1_SIZE (2086L) +#define GFG_CTRL2 (2087L) +#define GFG_CTRL2_ENABLE (2088L) +#define GFG_CTRL2_MODE (2089L) +#define GFG_CTRL2_PRBS_EN (2090L) +#define GFG_CTRL2_SIZE (2091L) +#define GFG_CTRL3 (2092L) +#define GFG_CTRL3_ENABLE (2093L) +#define GFG_CTRL3_MODE (2094L) +#define GFG_CTRL3_PRBS_EN (2095L) +#define GFG_CTRL3_SIZE (2096L) +#define GFG_CTRL4 (2097L) +#define GFG_CTRL4_ENABLE (2098L) +#define GFG_CTRL4_MODE (2099L) +#define GFG_CTRL4_PRBS_EN (2100L) +#define GFG_CTRL4_SIZE (2101L) +#define GFG_CTRL5 (2102L) +#define GFG_CTRL5_ENABLE (2103L) +#define GFG_CTRL5_MODE (2104L) +#define GFG_CTRL5_PRBS_EN (2105L) +#define GFG_CTRL5_SIZE (2106L) +#define GFG_CTRL6 (2107L) +#define GFG_CTRL6_ENABLE (2108L) +#define GFG_CTRL6_MODE (2109L) +#define GFG_CTRL6_PRBS_EN (2110L) +#define GFG_CTRL6_SIZE (2111L) +#define GFG_CTRL7 (2112L) +#define GFG_CTRL7_ENABLE (2113L) +#define GFG_CTRL7_MODE (2114L) +#define GFG_CTRL7_PRBS_EN (2115L) +#define GFG_CTRL7_SIZE (2116L) +#define GFG_RUN0 (2117L) +#define GFG_RUN0_RUN (2118L) +#define GFG_RUN1 (2119L) +#define GFG_RUN1_RUN (2120L) +#define GFG_RUN2 (2121L) +#define GFG_RUN2_RUN (2122L) +#define GFG_RUN3 (2123L) +#define GFG_RUN3_RUN (2124L) +#define GFG_RUN4 (2125L) +#define GFG_RUN4_RUN (2126L) +#define GFG_RUN5 (2127L) +#define GFG_RUN5_RUN (2128L) +#define GFG_RUN6 (2129L) +#define GFG_RUN6_RUN (2130L) +#define GFG_RUN7 (2131L) +#define GFG_RUN7_RUN (2132L) +#define GFG_SIZEMASK0 (2133L) +#define GFG_SIZEMASK0_VAL (2134L) +#define GFG_SIZEMASK1 (2135L) +#define GFG_SIZEMASK1_VAL (2136L) +#define GFG_SIZEMASK2 (2137L) +#define GFG_SIZEMASK2_VAL (2138L) +#define GFG_SIZEMASK3 (2139L) +#define GFG_SIZEMASK3_VAL (2140L) +#define GFG_SIZEMASK4 (2141L) +#define GFG_SIZEMASK4_VAL (2142L) +#define GFG_SIZEMASK5 (2143L) +#define GFG_SIZEMASK5_VAL (2144L) +#define GFG_SIZEMASK6 (2145L) +#define GFG_SIZEMASK6_VAL (2146L) +#define GFG_SIZEMASK7 (2147L) +#define GFG_SIZEMASK7_VAL (2148L) +#define GFG_STREAMID0 (2149L) +#define GFG_STREAMID0_VAL (2150L) +#define GFG_STREAMID1 (2151L) +#define GFG_STREAMID1_VAL (2152L) +#define GFG_STREAMID2 (2153L) +#define GFG_STREAMID2_VAL (2154L) +#define GFG_STREAMID3 (2155L) +#define GFG_STREAMID3_VAL (2156L) +#define GFG_STREAMID4 (2157L) +#define GFG_STREAMID4_VAL (2158L) +#define GFG_STREAMID5 (2159L) +#define GFG_STREAMID5_VAL (2160L) +#define GFG_STREAMID6 (2161L) +#define GFG_STREAMID6_VAL (2162L) +#define GFG_STREAMID7 (2163L) +#define GFG_STREAMID7_VAL (2164L) +/* GMF */ +#define GMF_CTRL (2165L) +#define GMF_CTRL_ENABLE (2166L) +#define GMF_CTRL_FCS_ALWAYS (2167L) +#define GMF_CTRL_IFG_AUTO_ADJUST_ENABLE (2168L) +#define GMF_CTRL_IFG_ENABLE (2169L) +#define GMF_CTRL_IFG_TX_NOW_ALWAYS (2170L) +#define GMF_CTRL_IFG_TX_NOW_ON_TS_ENABLE (2171L) +#define GMF_CTRL_IFG_TX_ON_TS_ADJUST_ON_SET_CLOCK (2172L) +#define GMF_CTRL_IFG_TX_ON_TS_ALWAYS (2173L) +#define GMF_CTRL_TS_INJECT_ALWAYS (2174L) +#define GMF_CTRL_TS_INJECT_DUAL_STEP (2175L) +#define GMF_DEBUG_LANE_MARKER (2176L) +#define GMF_DEBUG_LANE_MARKER_COMPENSATION (2177L) +#define GMF_IFG_MAX_ADJUST_SLACK (2178L) +#define GMF_IFG_MAX_ADJUST_SLACK_SLACK (2179L) +#define GMF_IFG_SET_CLOCK_DELTA (2180L) +#define GMF_IFG_SET_CLOCK_DELTA_DELTA (2181L) +#define GMF_IFG_SET_CLOCK_DELTA_ADJUST (2182L) +#define GMF_IFG_SET_CLOCK_DELTA_ADJUST_DELTA (2183L) +#define GMF_IFG_TX_NOW_ON_TS (2184L) +#define GMF_IFG_TX_NOW_ON_TS_TS (2185L) +#define GMF_SPEED (2186L) +#define GMF_SPEED_IFG_SPEED (2187L) +#define GMF_STAT (2188L) +#define GMF_STAT_CTRL_EMPTY (2189L) +#define GMF_STAT_DATA_CTRL_EMPTY (2190L) +#define GMF_STAT_SB_EMPTY (2191L) +#define GMF_STAT_CTRL (2192L) +#define GMF_STAT_CTRL_FILL_LEVEL (2193L) +#define GMF_STAT_DATA0 (2194L) +#define GMF_STAT_DATA0_EMPTY (2195L) +#define GMF_STAT_DATA1 (2196L) +#define GMF_STAT_DATA1_EMPTY (2197L) +#define GMF_STAT_DATA_BUFFER (2198L) +#define GMF_STAT_DATA_BUFFER_FREE (2199L) +#define GMF_STAT_DATA_BUFFER_USED (2200L) +#define GMF_STAT_MAX_DELAYED_PKT (2201L) +#define GMF_STAT_MAX_DELAYED_PKT_NS (2202L) +#define GMF_STAT_NEXT_PKT (2203L) +#define GMF_STAT_NEXT_PKT_NS (2204L) +#define GMF_STAT_STICKY (2205L) +#define GMF_STAT_STICKY_DATA_UNDERFLOWED (2206L) +#define GMF_STAT_STICKY_IFG_ADJUSTED (2207L) +#define GMF_TS_INJECT (2208L) +#define GMF_TS_INJECT_OFFSET (2209L) +#define GMF_TS_INJECT_POS (2210L) +/* GPIO_PHY */ +#define GPIO_PHY_CFG (2211L) +#define GPIO_PHY_CFG_E_PORT0_RXLOS (2212L) +#define GPIO_PHY_CFG_E_PORT1_RXLOS (2213L) +#define GPIO_PHY_CFG_PORT0_INT_B (2214L) +#define GPIO_PHY_CFG_PORT0_LPMODE (2215L) +#define GPIO_PHY_CFG_PORT0_MODPRS_B (2216L) +#define GPIO_PHY_CFG_PORT0_PLL_INTR (2217L) +#define GPIO_PHY_CFG_PORT0_RESET_B (2218L) +#define GPIO_PHY_CFG_PORT1_INT_B (2219L) +#define GPIO_PHY_CFG_PORT1_LPMODE (2220L) +#define GPIO_PHY_CFG_PORT1_MODPRS_B (2221L) +#define GPIO_PHY_CFG_PORT1_PLL_INTR (2222L) +#define GPIO_PHY_CFG_PORT1_RESET_B (2223L) +#define GPIO_PHY_GPIO (2224L) +#define GPIO_PHY_GPIO_E_PORT0_RXLOS (2225L) +#define GPIO_PHY_GPIO_E_PORT1_RXLOS (2226L) +#define GPIO_PHY_GPIO_PORT0_INT_B (2227L) +#define GPIO_PHY_GPIO_PORT0_LPMODE (2228L) +#define GPIO_PHY_GPIO_PORT0_MODPRS_B (2229L) +#define GPIO_PHY_GPIO_PORT0_PLL_INTR (2230L) +#define GPIO_PHY_GPIO_PORT0_RESET_B (2231L) +#define GPIO_PHY_GPIO_PORT1_INT_B (2232L) +#define GPIO_PHY_GPIO_PORT1_LPMODE (2233L) +#define GPIO_PHY_GPIO_PORT1_MODPRS_B (2234L) +#define GPIO_PHY_GPIO_PORT1_PLL_INTR (2235L) +#define GPIO_PHY_GPIO_PORT1_RESET_B (2236L) +/* GPIO_PHY_PORTS */ +#define GPIO_PHY_PORTS_CFG (2237L) +#define GPIO_PHY_PORTS_CFG_E_PORT0_RXLOS (2238L) +#define GPIO_PHY_PORTS_CFG_E_PORT0_TXDISABLE (2239L) +#define GPIO_PHY_PORTS_CFG_E_PORT0_TXFAULT (2240L) +#define GPIO_PHY_PORTS_CFG_E_PORT1_RXLOS (2241L) +#define GPIO_PHY_PORTS_CFG_E_PORT1_TXDISABLE (2242L) +#define GPIO_PHY_PORTS_CFG_E_PORT1_TXFAULT (2243L) +#define GPIO_PHY_PORTS_CFG_E_PORT2_RXLOS (2244L) +#define GPIO_PHY_PORTS_CFG_E_PORT2_TXDISABLE (2245L) +#define GPIO_PHY_PORTS_CFG_E_PORT2_TXFAULT (2246L) +#define GPIO_PHY_PORTS_CFG_E_PORT3_RXLOS (2247L) +#define GPIO_PHY_PORTS_CFG_E_PORT3_TXDISABLE (2248L) +#define GPIO_PHY_PORTS_CFG_E_PORT3_TXFAULT (2249L) +#define GPIO_PHY_PORTS_CFG_E_PORT4_RXLOS (2250L) +#define GPIO_PHY_PORTS_CFG_E_PORT4_TXDISABLE (2251L) +#define GPIO_PHY_PORTS_CFG_E_PORT4_TXFAULT (2252L) +#define GPIO_PHY_PORTS_CFG_E_PORT5_RXLOS (2253L) +#define GPIO_PHY_PORTS_CFG_E_PORT5_TXDISABLE (2254L) +#define GPIO_PHY_PORTS_CFG_E_PORT5_TXFAULT (2255L) +#define GPIO_PHY_PORTS_CFG_E_PORT6_RXLOS (2256L) +#define GPIO_PHY_PORTS_CFG_E_PORT6_TXDISABLE (2257L) +#define GPIO_PHY_PORTS_CFG_E_PORT6_TXFAULT (2258L) +#define GPIO_PHY_PORTS_CFG_E_PORT7_RXLOS (2259L) +#define GPIO_PHY_PORTS_CFG_E_PORT7_TXDISABLE (2260L) +#define GPIO_PHY_PORTS_CFG_E_PORT7_TXFAULT (2261L) +#define GPIO_PHY_PORTS_GPIO (2262L) +#define GPIO_PHY_PORTS_GPIO_E_PORT0_RXLOS (2263L) +#define GPIO_PHY_PORTS_GPIO_E_PORT0_TXDISABLE (2264L) +#define GPIO_PHY_PORTS_GPIO_E_PORT0_TXFAULT (2265L) +#define GPIO_PHY_PORTS_GPIO_E_PORT1_RXLOS (2266L) +#define GPIO_PHY_PORTS_GPIO_E_PORT1_TXDISABLE (2267L) +#define GPIO_PHY_PORTS_GPIO_E_PORT1_TXFAULT (2268L) +#define GPIO_PHY_PORTS_GPIO_E_PORT2_RXLOS (2269L) +#define GPIO_PHY_PORTS_GPIO_E_PORT2_TXDISABLE (2270L) +#define GPIO_PHY_PORTS_GPIO_E_PORT2_TXFAULT (2271L) +#define GPIO_PHY_PORTS_GPIO_E_PORT3_RXLOS (2272L) +#define GPIO_PHY_PORTS_GPIO_E_PORT3_TXDISABLE (2273L) +#define GPIO_PHY_PORTS_GPIO_E_PORT3_TXFAULT (2274L) +#define GPIO_PHY_PORTS_GPIO_E_PORT4_RXLOS (2275L) +#define GPIO_PHY_PORTS_GPIO_E_PORT4_TXDISABLE (2276L) +#define GPIO_PHY_PORTS_GPIO_E_PORT4_TXFAULT (2277L) +#define GPIO_PHY_PORTS_GPIO_E_PORT5_RXLOS (2278L) +#define GPIO_PHY_PORTS_GPIO_E_PORT5_TXDISABLE (2279L) +#define GPIO_PHY_PORTS_GPIO_E_PORT5_TXFAULT (2280L) +#define GPIO_PHY_PORTS_GPIO_E_PORT6_RXLOS (2281L) +#define GPIO_PHY_PORTS_GPIO_E_PORT6_TXDISABLE (2282L) +#define GPIO_PHY_PORTS_GPIO_E_PORT6_TXFAULT (2283L) +#define GPIO_PHY_PORTS_GPIO_E_PORT7_RXLOS (2284L) +#define GPIO_PHY_PORTS_GPIO_E_PORT7_TXDISABLE (2285L) +#define GPIO_PHY_PORTS_GPIO_E_PORT7_TXFAULT (2286L) +/* GPIO_SFPP */ +#define GPIO_SFPP_CFG (2287L) +#define GPIO_SFPP_CFG_ABS (2288L) +#define GPIO_SFPP_CFG_RS (2289L) +#define GPIO_SFPP_CFG_RXLOS (2290L) +#define GPIO_SFPP_CFG_TXDISABLE (2291L) +#define GPIO_SFPP_CFG_TXFAULT (2292L) +#define GPIO_SFPP_GPIO (2293L) +#define GPIO_SFPP_GPIO_ABS (2294L) +#define GPIO_SFPP_GPIO_RS (2295L) +#define GPIO_SFPP_GPIO_RXLOS (2296L) +#define GPIO_SFPP_GPIO_TXDISABLE (2297L) +#define GPIO_SFPP_GPIO_TXFAULT (2298L) +/* HFU */ +#define HFU_RCP_CTRL (2381L) +#define HFU_RCP_CTRL_ADR (2382L) +#define HFU_RCP_CTRL_CNT (2383L) +#define HFU_RCP_DATA (2384L) +#define HFU_RCP_DATA_CSINF (2385L) +#define HFU_RCP_DATA_IL3OFS (2386L) +#define HFU_RCP_DATA_IL4OFS (2387L) +#define HFU_RCP_DATA_L3FRAG (2388L) +#define HFU_RCP_DATA_L3PRT (2389L) +#define HFU_RCP_DATA_L4PRT (2390L) +#define HFU_RCP_DATA_LEN_A_ADD_DYN (2391L) +#define HFU_RCP_DATA_LEN_A_ADD_OFS (2392L) +#define HFU_RCP_DATA_LEN_A_OL4LEN (2393L) +#define HFU_RCP_DATA_LEN_A_POS_DYN (2394L) +#define HFU_RCP_DATA_LEN_A_POS_OFS (2395L) +#define HFU_RCP_DATA_LEN_A_SUB_DYN (2396L) +#define HFU_RCP_DATA_LEN_A_WR (2397L) +#define HFU_RCP_DATA_LEN_B_ADD_DYN (2398L) +#define HFU_RCP_DATA_LEN_B_ADD_OFS (2399L) +#define HFU_RCP_DATA_LEN_B_POS_DYN (2400L) +#define HFU_RCP_DATA_LEN_B_POS_OFS (2401L) +#define HFU_RCP_DATA_LEN_B_SUB_DYN (2402L) +#define HFU_RCP_DATA_LEN_B_WR (2403L) +#define HFU_RCP_DATA_LEN_C_ADD_DYN (2404L) +#define HFU_RCP_DATA_LEN_C_ADD_OFS (2405L) +#define HFU_RCP_DATA_LEN_C_POS_DYN (2406L) +#define HFU_RCP_DATA_LEN_C_POS_OFS (2407L) +#define HFU_RCP_DATA_LEN_C_SUB_DYN (2408L) +#define HFU_RCP_DATA_LEN_C_WR (2409L) +#define HFU_RCP_DATA_OL3OFS (2410L) +#define HFU_RCP_DATA_OL4OFS (2411L) +#define HFU_RCP_DATA_TTL_POS_DYN (2412L) +#define HFU_RCP_DATA_TTL_POS_OFS (2413L) +#define HFU_RCP_DATA_TTL_WR (2414L) +#define HFU_RCP_DATA_TUNNEL (2415L) +/* HIF */ +#define HIF_BUILD_TIME (2416L) +#define HIF_BUILD_TIME_TIME (2417L) +#define HIF_CONFIG (2418L) +#define HIF_CONFIG_EXT_TAG (2419L) +#define HIF_CONFIG_MAX_READ (2420L) +#define HIF_CONFIG_MAX_TLP (2421L) +#define HIF_CONTROL (2422L) +#define HIF_CONTROL_BLESSED (2423L) +#define HIF_CONTROL_WRAW (2424L) +#define HIF_PROD_ID_EX (2425L) +#define HIF_PROD_ID_EX_LAYOUT (2426L) +#define HIF_PROD_ID_EX_LAYOUT_VERSION (2427L) +#define HIF_PROD_ID_EX_RESERVED (2428L) +#define HIF_PROD_ID_EXT (2429L) +#define HIF_PROD_ID_EXT_LAYOUT (2430L) +#define HIF_PROD_ID_EXT_LAYOUT_VERSION (2431L) +#define HIF_PROD_ID_EXT_RESERVED (2432L) +#define HIF_PROD_ID_LSB (2433L) +#define HIF_PROD_ID_LSB_GROUP_ID (2434L) +#define HIF_PROD_ID_LSB_REV_ID (2435L) +#define HIF_PROD_ID_LSB_VER_ID (2436L) +#define HIF_PROD_ID_MSB (2437L) +#define HIF_PROD_ID_MSB_BUILD_NO (2438L) +#define HIF_PROD_ID_MSB_PATCH_NO (2439L) +#define HIF_PROD_ID_MSB_TYPE_ID (2440L) +#define HIF_SAMPLE_TIME (2441L) +#define HIF_SAMPLE_TIME_SAMPLE_TIME (2442L) +#define HIF_STATUS (2443L) +#define HIF_STATUS_RD_ERR (2444L) +#define HIF_STATUS_TAGS_IN_USE (2445L) +#define HIF_STATUS_WR_ERR (2446L) +#define HIF_STAT_CTRL (2447L) +#define HIF_STAT_CTRL_STAT_ENA (2448L) +#define HIF_STAT_CTRL_STAT_REQ (2449L) +#define HIF_STAT_REFCLK (2450L) +#define HIF_STAT_REFCLK_REFCLK250 (2451L) +#define HIF_STAT_RX (2452L) +#define HIF_STAT_RX_COUNTER (2453L) +#define HIF_STAT_TX (2454L) +#define HIF_STAT_TX_COUNTER (2455L) +#define HIF_TEST0 (2456L) +#define HIF_TEST0_DATA (2457L) +#define HIF_TEST1 (2458L) +#define HIF_TEST1_DATA (2459L) +#define HIF_TEST2 (2460L) +#define HIF_TEST2_DATA (2461L) +#define HIF_TEST3 (2462L) +#define HIF_TEST3_DATA (2463L) +#define HIF_UUID0 (2464L) +#define HIF_UUID0_UUID0 (2465L) +#define HIF_UUID1 (2466L) +#define HIF_UUID1_UUID1 (2467L) +#define HIF_UUID2 (2468L) +#define HIF_UUID2_UUID2 (2469L) +#define HIF_UUID3 (2470L) +#define HIF_UUID3_UUID3 (2471L) +/* HSH */ +#define HSH_RCP_CTRL (2472L) +#define HSH_RCP_CTRL_ADR (2473L) +#define HSH_RCP_CTRL_CNT (2474L) +#define HSH_RCP_DATA (2475L) +#define HSH_RCP_DATA_AUTO_IPV4_MASK (2476L) +#define HSH_RCP_DATA_HSH_TYPE (2477L) +#define HSH_RCP_DATA_HSH_VALID (2478L) +#define HSH_RCP_DATA_K (2479L) +#define HSH_RCP_DATA_LOAD_DIST_TYPE (2480L) +#define HSH_RCP_DATA_MAC_PORT_MASK (2481L) +#define HSH_RCP_DATA_P_MASK (2482L) +#define HSH_RCP_DATA_QW0_OFS (2483L) +#define HSH_RCP_DATA_QW0_PE (2484L) +#define HSH_RCP_DATA_QW4_OFS (2485L) +#define HSH_RCP_DATA_QW4_PE (2486L) +#define HSH_RCP_DATA_SEED (2487L) +#define HSH_RCP_DATA_SORT (2488L) +#define HSH_RCP_DATA_TNL_P (2489L) +#define HSH_RCP_DATA_TOEPLITZ (2490L) +#define HSH_RCP_DATA_W8_OFS (2491L) +#define HSH_RCP_DATA_W8_PE (2492L) +#define HSH_RCP_DATA_W8_SORT (2493L) +#define HSH_RCP_DATA_W9_OFS (2494L) +#define HSH_RCP_DATA_W9_P (2495L) +#define HSH_RCP_DATA_W9_PE (2496L) +#define HSH_RCP_DATA_W9_SORT (2497L) +#define HSH_RCP_DATA_WORD_MASK (2498L) +/* HST */ +#define HST_RCP_CTRL (2499L) +#define HST_RCP_CTRL_ADR (2500L) +#define HST_RCP_CTRL_CNT (2501L) +#define HST_RCP_DATA (2502L) +#define HST_RCP_DATA_END_DYN (2503L) +#define HST_RCP_DATA_END_OFS (2504L) +#define HST_RCP_DATA_MODIF0_CMD (2505L) +#define HST_RCP_DATA_MODIF0_DYN (2506L) +#define HST_RCP_DATA_MODIF0_OFS (2507L) +#define HST_RCP_DATA_MODIF0_VALUE (2508L) +#define HST_RCP_DATA_MODIF1_CMD (2509L) +#define HST_RCP_DATA_MODIF1_DYN (2510L) +#define HST_RCP_DATA_MODIF1_OFS (2511L) +#define HST_RCP_DATA_MODIF1_VALUE (2512L) +#define HST_RCP_DATA_MODIF2_CMD (2513L) +#define HST_RCP_DATA_MODIF2_DYN (2514L) +#define HST_RCP_DATA_MODIF2_OFS (2515L) +#define HST_RCP_DATA_MODIF2_VALUE (2516L) +#define HST_RCP_DATA_START_DYN (2517L) +#define HST_RCP_DATA_START_OFS (2518L) +#define HST_RCP_DATA_STRIP_MODE (2519L) +/* ICORE_10G */ +#define ICORE_10G_INDIR_CTRL (2549L) +#define ICORE_10G_INDIR_CTRL_RD_ENABLE (2550L) +#define ICORE_10G_INDIR_CTRL_RD_READY (2551L) +#define ICORE_10G_INDIR_CTRL_SUB_ADDR (2552L) +#define ICORE_10G_INDIR_DATA (2553L) +#define ICORE_10G_INDIR_DATA_DATA (2554L) +#define ICORE_10G_MISC_CTRL (2555L) +#define ICORE_10G_MISC_CTRL_LINE_LOOP (2556L) +#define ICORE_10G_MISC_CTRL_LINK_LATENCY (2557L) +#define ICORE_10G_MISC_CTRL_RES_MAC_RX (2558L) +#define ICORE_10G_MISC_CTRL_RES_MAC_TX (2559L) +#define ICORE_10G_MISC_CTRL_SERIAL_LOOP (2560L) +#define ICORE_10G_MISC_CTRL_SET_LOCK2DATA (2561L) +#define ICORE_10G_MISC_CTRL_SET_LOCK2REF (2562L) +#define ICORE_10G_PHY_STATUS (2563L) +#define ICORE_10G_PHY_STATUS_BLOCK_LOCK (2564L) +#define ICORE_10G_PHY_STATUS_HI_BER (2565L) +#define ICORE_10G_PHY_STATUS_HI_BER_CHANGED (2566L) +#define ICORE_10G_PHY_STATUS_LINK_STATE (2567L) +#define ICORE_10G_PHY_STATUS_LINK_STATE_CHANGED (2568L) +#define ICORE_10G_PHY_STATUS_RXCLK_LOCKED (2569L) +#define ICORE_10G_PHY_STATUS_RXCLK_LOCKED2DATA (2570L) +#define ICORE_10G_PHY_STATUS_RX_CAL_BUSY (2571L) +#define ICORE_10G_PHY_STATUS_TXCLK_LOCKED (2572L) +#define ICORE_10G_PHY_STATUS_TX_CAL_BUSY (2573L) +#define ICORE_10G_TFG_ADDR (2574L) +#define ICORE_10G_TFG_ADDR_ADR (2575L) +#define ICORE_10G_TFG_ADDR_RDENA (2576L) +#define ICORE_10G_TFG_ADDR_RD_DONE (2577L) +#define ICORE_10G_TFG_CTRL (2578L) +#define ICORE_10G_TFG_CTRL_ID_ENA (2579L) +#define ICORE_10G_TFG_CTRL_ID_POS (2580L) +#define ICORE_10G_TFG_CTRL_RESTART (2581L) +#define ICORE_10G_TFG_CTRL_TG_ACT (2582L) +#define ICORE_10G_TFG_CTRL_TG_ENA (2583L) +#define ICORE_10G_TFG_CTRL_TIME_MODE (2584L) +#define ICORE_10G_TFG_CTRL_WRAP (2585L) +#define ICORE_10G_TFG_DATA (2586L) +#define ICORE_10G_TFG_DATA_ID (2587L) +#define ICORE_10G_TFG_DATA_LENGTH (2588L) +#define ICORE_10G_TFG_FRAME_HDR_0 (2589L) +#define ICORE_10G_TFG_FRAME_HDR_0_HDR (2590L) +#define ICORE_10G_TFG_FRAME_HDR_1 (2591L) +#define ICORE_10G_TFG_FRAME_HDR_1_HDR (2592L) +#define ICORE_10G_TFG_FRAME_HDR_2 (2593L) +#define ICORE_10G_TFG_FRAME_HDR_2_HDR (2594L) +#define ICORE_10G_TFG_FRAME_HDR_3 (2595L) +#define ICORE_10G_TFG_FRAME_HDR_3_HDR (2596L) +#define ICORE_10G_TFG_REPETITION (2597L) +#define ICORE_10G_TFG_REPETITION_CNT (2598L) +/* IFR */ +#define IFR_RCP_CTRL (2642L) +#define IFR_RCP_CTRL_ADR (2643L) +#define IFR_RCP_CTRL_CNT (2644L) +#define IFR_RCP_DATA (2645L) +#define IFR_RCP_DATA_EN (2646L) +#define IFR_RCP_DATA_MTU (2647L) +/* IIC */ +#define IIC_ADR (2648L) +#define IIC_ADR_SLV_ADR (2649L) +#define IIC_CR (2650L) +#define IIC_CR_EN (2651L) +#define IIC_CR_GC_EN (2652L) +#define IIC_CR_MSMS (2653L) +#define IIC_CR_RST (2654L) +#define IIC_CR_RSTA (2655L) +#define IIC_CR_TX (2656L) +#define IIC_CR_TXAK (2657L) +#define IIC_CR_TXFIFO_RESET (2658L) +#define IIC_DGIE (2659L) +#define IIC_DGIE_GIE (2660L) +#define IIC_GPO (2661L) +#define IIC_GPO_GPO_VAL (2662L) +#define IIC_IER (2663L) +#define IIC_IER_INT0 (2664L) +#define IIC_IER_INT1 (2665L) +#define IIC_IER_INT2 (2666L) +#define IIC_IER_INT3 (2667L) +#define IIC_IER_INT4 (2668L) +#define IIC_IER_INT5 (2669L) +#define IIC_IER_INT6 (2670L) +#define IIC_IER_INT7 (2671L) +#define IIC_ISR (2672L) +#define IIC_ISR_INT0 (2673L) +#define IIC_ISR_INT1 (2674L) +#define IIC_ISR_INT2 (2675L) +#define IIC_ISR_INT3 (2676L) +#define IIC_ISR_INT4 (2677L) +#define IIC_ISR_INT5 (2678L) +#define IIC_ISR_INT6 (2679L) +#define IIC_ISR_INT7 (2680L) +#define IIC_RX_FIFO (2681L) +#define IIC_RX_FIFO_RXDATA (2682L) +#define IIC_RX_FIFO_OCY (2683L) +#define IIC_RX_FIFO_OCY_OCY_VAL (2684L) +#define IIC_RX_FIFO_PIRQ (2685L) +#define IIC_RX_FIFO_PIRQ_CMP_VAL (2686L) +#define IIC_SOFTR (2687L) +#define IIC_SOFTR_RKEY (2688L) +#define IIC_SR (2689L) +#define IIC_SR_AAS (2690L) +#define IIC_SR_ABGC (2691L) +#define IIC_SR_BB (2692L) +#define IIC_SR_RXFIFO_EMPTY (2693L) +#define IIC_SR_RXFIFO_FULL (2694L) +#define IIC_SR_SRW (2695L) +#define IIC_SR_TXFIFO_EMPTY (2696L) +#define IIC_SR_TXFIFO_FULL (2697L) +#define IIC_TBUF (2698L) +#define IIC_TBUF_TBUF_VAL (2699L) +#define IIC_TEN_ADR (2700L) +#define IIC_TEN_ADR_MSB_SLV_ADR (2701L) +#define IIC_THDDAT (2702L) +#define IIC_THDDAT_THDDAT_VAL (2703L) +#define IIC_THDSTA (2704L) +#define IIC_THDSTA_THDSTA_VAL (2705L) +#define IIC_THIGH (2706L) +#define IIC_THIGH_THIGH_VAL (2707L) +#define IIC_TLOW (2708L) +#define IIC_TLOW_TLOW_VAL (2709L) +#define IIC_TSUDAT (2710L) +#define IIC_TSUDAT_TSUDAT_VAL (2711L) +#define IIC_TSUSTA (2712L) +#define IIC_TSUSTA_TSUSTA_VAL (2713L) +#define IIC_TSUSTO (2714L) +#define IIC_TSUSTO_TSUSTO_VAL (2715L) +#define IIC_TX_FIFO (2716L) +#define IIC_TX_FIFO_START (2717L) +#define IIC_TX_FIFO_STOP (2718L) +#define IIC_TX_FIFO_TXDATA (2719L) +#define IIC_TX_FIFO_OCY (2720L) +#define IIC_TX_FIFO_OCY_OCY_VAL (2721L) +/* INS */ +#define INS_RCP_CTRL (2722L) +#define INS_RCP_CTRL_ADR (2723L) +#define INS_RCP_CTRL_CNT (2724L) +#define INS_RCP_DATA (2725L) +#define INS_RCP_DATA_DYN (2726L) +#define INS_RCP_DATA_LEN (2727L) +#define INS_RCP_DATA_OFS (2728L) +/* IOA */ +#define IOA_RECIPE_CTRL (2778L) +#define IOA_RECIPE_CTRL_ADR (2779L) +#define IOA_RECIPE_CTRL_CNT (2780L) +#define IOA_RECIPE_DATA (2781L) +#define IOA_RECIPE_DATA_QUEUE_ID (2782L) +#define IOA_RECIPE_DATA_QUEUE_OVERRIDE_EN (2783L) +#define IOA_RECIPE_DATA_TUNNEL_POP (2784L) +#define IOA_RECIPE_DATA_VLAN_DEI (2785L) +#define IOA_RECIPE_DATA_VLAN_PCP (2786L) +#define IOA_RECIPE_DATA_VLAN_POP (2787L) +#define IOA_RECIPE_DATA_VLAN_PUSH (2788L) +#define IOA_RECIPE_DATA_VLAN_TPID_SEL (2789L) +#define IOA_RECIPE_DATA_VLAN_VID (2790L) +#define IOA_ROA_EPP_CTRL (2791L) +#define IOA_ROA_EPP_CTRL_ADR (2792L) +#define IOA_ROA_EPP_CTRL_CNT (2793L) +#define IOA_ROA_EPP_DATA (2794L) +#define IOA_ROA_EPP_DATA_PUSH_TUNNEL (2795L) +#define IOA_ROA_EPP_DATA_TX_PORT (2796L) +#define IOA_VLAN_TPID_SPECIAL (2797L) +#define IOA_VLAN_TPID_SPECIAL_CUSTTPID0 (2798L) +#define IOA_VLAN_TPID_SPECIAL_CUSTTPID1 (2799L) +/* IPF */ +#define IPF_CTRL (2800L) +#define IPF_CTRL_ALL_UNM (2801L) +#define IPF_CTRL_ALL_UNM_INNER (2802L) +#define IPF_CTRL_DEL_UNM (2803L) +#define IPF_CTRL_ENABLE (2804L) +#define IPF_CTRL_FST_UNM (2805L) +#define IPF_CTRL_PASSIVE (2806L) +#define IPF_CTRL_PERSIST (2807L) +#define IPF_DEBUG (2808L) +#define IPF_DEBUG_FTF_N (2809L) +#define IPF_DEBUG_LIMIT_N (2810L) +#define IPF_EXPIRE (2811L) +#define IPF_EXPIRE_PERSIST (2812L) +#define IPF_EXPIRE_T (2813L) +#define IPF_FTF_DEBUG (2814L) +#define IPF_FTF_DEBUG_N (2815L) +#define IPF_RCP_CTRL (2816L) +#define IPF_RCP_CTRL_ADR (2817L) +#define IPF_RCP_CTRL_CNT (2818L) +#define IPF_RCP_DATA (2819L) +#define IPF_RCP_DATA_ALL_UNM (2820L) +#define IPF_RCP_DATA_COL_INH (2821L) +#define IPF_RCP_DATA_DEL_UNM (2822L) +#define IPF_RCP_DATA_DISC_INH (2823L) +#define IPF_RCP_DATA_DUP_INH (2824L) +#define IPF_RCP_DATA_ENABLE (2825L) +#define IPF_RCP_DATA_FST_UNM (2826L) +#define IPF_RCP_DATA_GROUP_ID (2827L) +#define IPF_RCP_DATA_HASH_CENC (2828L) +#define IPF_RCP_DATA_HSH_INH (2829L) +#define IPF_RCP_DATA_PORT_GROUP_ID (2830L) +#define IPF_RCP_DATA_QUEUE_INH (2831L) +#define IPF_RCP_DATA_UNMQ_HI (2832L) +#define IPF_RCP_DATA_UNMQ_LO (2833L) +#define IPF_RCP_DATA_UNM_FLAG_CENC (2834L) +#define IPF_SIZE_DEBUG (2835L) +#define IPF_SIZE_DEBUG_N (2836L) +#define IPF_STAT_MAX1 (2837L) +#define IPF_STAT_MAX1_N (2838L) +#define IPF_STAT_MAX2 (2839L) +#define IPF_STAT_MAX2_N (2840L) +#define IPF_STAT_MAX3 (2841L) +#define IPF_STAT_MAX3_N (2842L) +#define IPF_STAT_MAX4 (2843L) +#define IPF_STAT_MAX4_N (2844L) +#define IPF_TIMEOUT (2845L) +#define IPF_TIMEOUT_T (2846L) +#define IPF_UNMQ_CTRL (2847L) +#define IPF_UNMQ_CTRL_ADR (2848L) +#define IPF_UNMQ_CTRL_CNT (2849L) +#define IPF_UNMQ_DATA (2850L) +#define IPF_UNMQ_DATA_CENC (2851L) +#define IPF_UNMQ_DATA_EN (2852L) +#define IPF_UNMQ_DATA_ID (2853L) +#define IPF_UNM_FEED (2854L) +#define IPF_UNM_FEED_ADDR (2855L) +#define IPF_UNM_FEED_CNT (2856L) +#define IPF_UNM_FEED_FEED (2857L) +#define IPF_UNM_FEED_FEED_VALID (2858L) +#define IPF_UNM_FEED_RES1 (2859L) +#define IPF_UNM_FEED_RES2 (2860L) +#define IPF_UNM_FEED_RES3 (2861L) +/* KM */ +#define KM_CAM_CTRL (2862L) +#define KM_CAM_CTRL_ADR (2863L) +#define KM_CAM_CTRL_CNT (2864L) +#define KM_CAM_DATA (2865L) +#define KM_CAM_DATA_FT0 (2866L) +#define KM_CAM_DATA_FT1 (2867L) +#define KM_CAM_DATA_FT2 (2868L) +#define KM_CAM_DATA_FT3 (2869L) +#define KM_CAM_DATA_FT4 (2870L) +#define KM_CAM_DATA_FT5 (2871L) +#define KM_CAM_DATA_W0 (2872L) +#define KM_CAM_DATA_W1 (2873L) +#define KM_CAM_DATA_W2 (2874L) +#define KM_CAM_DATA_W3 (2875L) +#define KM_CAM_DATA_W4 (2876L) +#define KM_CAM_DATA_W5 (2877L) +#define KM_RCP_CTRL (2878L) +#define KM_RCP_CTRL_ADR (2879L) +#define KM_RCP_CTRL_CNT (2880L) +#define KM_RCP_DATA (2881L) +#define KM_RCP_DATA_BANK_A (2882L) +#define KM_RCP_DATA_BANK_B (2883L) +#define KM_RCP_DATA_DUAL (2884L) +#define KM_RCP_DATA_DW0_B_DYN (2885L) +#define KM_RCP_DATA_DW0_B_OFS (2886L) +#define KM_RCP_DATA_DW10_DYN (2887L) +#define KM_RCP_DATA_DW10_OFS (2888L) +#define KM_RCP_DATA_DW10_SEL_A (2889L) +#define KM_RCP_DATA_DW10_SEL_B (2890L) +#define KM_RCP_DATA_DW2_B_DYN (2891L) +#define KM_RCP_DATA_DW2_B_OFS (2892L) +#define KM_RCP_DATA_DW8_B_DYN (2893L) +#define KM_RCP_DATA_DW8_B_OFS (2894L) +#define KM_RCP_DATA_DW8_DYN (2895L) +#define KM_RCP_DATA_DW8_OFS (2896L) +#define KM_RCP_DATA_DW8_SEL_A (2897L) +#define KM_RCP_DATA_DW8_SEL_B (2898L) +#define KM_RCP_DATA_EL_A (2899L) +#define KM_RCP_DATA_EL_B (2900L) +#define KM_RCP_DATA_FLOW_SET (2901L) +#define KM_RCP_DATA_FTM_A (2902L) +#define KM_RCP_DATA_FTM_B (2903L) +#define KM_RCP_DATA_INFO_A (2904L) +#define KM_RCP_DATA_INFO_B (2905L) +#define KM_RCP_DATA_KEYWAY_A (2906L) +#define KM_RCP_DATA_KEYWAY_B (2907L) +#define KM_RCP_DATA_KL_A (2908L) +#define KM_RCP_DATA_KL_B (2909L) +#define KM_RCP_DATA_MASK_A (2910L) +#define KM_RCP_DATA_MASK_B (2911L) +#define KM_RCP_DATA_PAIRED (2912L) +#define KM_RCP_DATA_QW0_B_DYN (2913L) +#define KM_RCP_DATA_QW0_B_OFS (2914L) +#define KM_RCP_DATA_QW0_DYN (2915L) +#define KM_RCP_DATA_QW0_OFS (2916L) +#define KM_RCP_DATA_QW0_SEL_A (2917L) +#define KM_RCP_DATA_QW0_SEL_B (2918L) +#define KM_RCP_DATA_QW4_B_DYN (2919L) +#define KM_RCP_DATA_QW4_B_OFS (2920L) +#define KM_RCP_DATA_QW4_DYN (2921L) +#define KM_RCP_DATA_QW4_OFS (2922L) +#define KM_RCP_DATA_QW4_SEL_A (2923L) +#define KM_RCP_DATA_QW4_SEL_B (2924L) +#define KM_RCP_DATA_SW4_B_DYN (2925L) +#define KM_RCP_DATA_SW4_B_OFS (2926L) +#define KM_RCP_DATA_SW5_B_DYN (2927L) +#define KM_RCP_DATA_SW5_B_OFS (2928L) +#define KM_RCP_DATA_SW8_B_DYN (2929L) +#define KM_RCP_DATA_SW8_B_OFS (2930L) +#define KM_RCP_DATA_SW8_DYN (2931L) +#define KM_RCP_DATA_SW8_OFS (2932L) +#define KM_RCP_DATA_SW8_SEL_A (2933L) +#define KM_RCP_DATA_SW8_SEL_B (2934L) +#define KM_RCP_DATA_SW9_B_DYN (2935L) +#define KM_RCP_DATA_SW9_B_OFS (2936L) +#define KM_RCP_DATA_SW9_DYN (2937L) +#define KM_RCP_DATA_SW9_OFS (2938L) +#define KM_RCP_DATA_SW9_SEL_A (2939L) +#define KM_RCP_DATA_SW9_SEL_B (2940L) +#define KM_RCP_DATA_SWX_CCH (2941L) +#define KM_RCP_DATA_SWX_OVS_SB (2942L) +#define KM_RCP_DATA_SWX_SEL_A (2943L) +#define KM_RCP_DATA_SWX_SEL_B (2944L) +#define KM_RCP_DATA_SYNERGY_MODE (2945L) +#define KM_STATUS (2946L) +#define KM_STATUS_TCQ_RDY (2947L) +#define KM_TCAM_CTRL (2948L) +#define KM_TCAM_CTRL_ADR (2949L) +#define KM_TCAM_CTRL_CNT (2950L) +#define KM_TCAM_DATA (2951L) +#define KM_TCAM_DATA_T (2952L) +#define KM_TCI_CTRL (2953L) +#define KM_TCI_CTRL_ADR (2954L) +#define KM_TCI_CTRL_CNT (2955L) +#define KM_TCI_DATA (2956L) +#define KM_TCI_DATA_COLOR (2957L) +#define KM_TCI_DATA_FT (2958L) +#define KM_TCQ_CTRL (2959L) +#define KM_TCQ_CTRL_ADR (2960L) +#define KM_TCQ_CTRL_CNT (2961L) +#define KM_TCQ_DATA (2962L) +#define KM_TCQ_DATA_BANK_MASK (2963L) +#define KM_TCQ_DATA_QUAL (2964L) +/* LAO */ +/* MAC */ +#define MAC_CONF_SERDES_BITFRAG (2965L) +#define MAC_CONF_SERDES_BITFRAG_BITFRAG (2966L) +#define MAC_CONF_SERDES_DELAY (2967L) +#define MAC_CONF_SERDES_DELAY_DELAY (2968L) +#define MAC_CONF_SERDES_REORDER (2969L) +#define MAC_CONF_SERDES_REORDER_REORDER (2970L) +#define MAC_FAULTY_BLK (2971L) +#define MAC_FAULTY_BLK_DATA (2972L) +#define MAC_HOST_STAT_BYTE_FILL (2973L) +#define MAC_HOST_STAT_BYTE_FILL_CNT (2974L) +#define MAC_INT (2975L) +#define MAC_INT_EN (2976L) +#define MAC_INT_MAX_PACE (2977L) +#define MAC_LINK_SUMMARY (2978L) +#define MAC_LINK_SUMMARY_ABS (2979L) +#define MAC_LINK_SUMMARY_GBOX_INTERR (2980L) +#define MAC_LINK_SUMMARY_GLB_ALARMN (2981L) +#define MAC_LINK_SUMMARY_LH_ABS (2982L) +#define MAC_LINK_SUMMARY_LH_GLB_ALARMN (2983L) +#define MAC_LINK_SUMMARY_LH_LOCAL_FAULT (2984L) +#define MAC_LINK_SUMMARY_LH_REMOTE_FAULT (2985L) +#define MAC_LINK_SUMMARY_LH_RX_LOS (2986L) +#define MAC_LINK_SUMMARY_LINK_DOWN_CNT (2987L) +#define MAC_LINK_SUMMARY_LL_PHY_LINK_STATE (2988L) +#define MAC_LINK_SUMMARY_LOCAL_FAULT (2989L) +#define MAC_LINK_SUMMARY_NT_PHY_LINK_STATE (2990L) +#define MAC_LINK_SUMMARY_REMOTE_FAULT (2991L) +#define MAC_LINK_SUMMARY_RX_LOS (2992L) +#define MAC_MAC_STAT_BYTE (2993L) +#define MAC_MAC_STAT_BYTE_CNT (2994L) +#define MAC_MAC_STAT_CRC (2995L) +#define MAC_MAC_STAT_CRC_CNT (2996L) +#define MAC_MAC_STAT_CV (2997L) +#define MAC_MAC_STAT_CV_CNT (2998L) +#define MAC_MAC_STAT_FRAME (2999L) +#define MAC_MAC_STAT_FRAME_CNT (3000L) +#define MAC_MAC_STAT_MICRO_DROP (3001L) +#define MAC_MAC_STAT_MICRO_DROP_CNT (3002L) +#define MAC_MAC_STAT_RATE_DROP (3003L) +#define MAC_MAC_STAT_RATE_DROP_CNT (3004L) +#define MAC_MAC_STAT_TRUNC (3005L) +#define MAC_MAC_STAT_TRUNC_CNT (3006L) +#define MAC_MDS_CEN_VAL (3007L) +#define MAC_MDS_CEN_VAL_VAL (3008L) +#define MAC_MDS_CONF (3009L) +#define MAC_MDS_CONF_CENTER_REC_ENA (3010L) +#define MAC_MDS_CONF_CLR_STAT (3011L) +#define MAC_MDS_CONF_ENA_TS_MOD (3012L) +#define MAC_MDS_CONF_REC_ENA (3013L) +#define MAC_MDS_CONF_TIME_MODE (3014L) +#define MAC_MDS_DATA (3015L) +#define MAC_MDS_DATA_DATA (3016L) +#define MAC_MDS_FRAMES (3017L) +#define MAC_MDS_FRAMES_CNT (3018L) +#define MAC_MDS_MAX (3019L) +#define MAC_MDS_MAX_MAX (3020L) +#define MAC_MDS_MIN (3021L) +#define MAC_MDS_MIN_MIN (3022L) +#define MAC_MDS_STAT (3023L) +#define MAC_MDS_STAT_CLR_BUSY (3024L) +#define MAC_MDS_STAT_HIT_MAX (3025L) +#define MAC_MDS_STAT_HIT_MIN (3026L) +#define MAC_MDS_VAL_REC (3027L) +#define MAC_MDS_VAL_REC_VALUE (3028L) +#define MAC_MDS_VAL_REC_FRAME (3029L) +#define MAC_MDS_VAL_REC_FRAME_VALUE (3030L) +#define MAC_NT_PORT_CTRL (3031L) +#define MAC_NT_PORT_CTRL_LED_MODE (3032L) +#define MAC_RAM_MDS_ADDR (3033L) +#define MAC_RAM_MDS_ADDR_ADR (3034L) +#define MAC_RAM_MDS_ADDR_CLR_RAM (3035L) +#define MAC_RAM_MDS_ADDR_RD_DONE (3036L) +#define MAC_RAM_MDS_ADDR_RD_ENA (3037L) +#define MAC_RAW_ADDR (3038L) +#define MAC_RAW_ADDR_ADR (3039L) +#define MAC_RAW_ADDR_RDENA (3040L) +#define MAC_RAW_ADDR_RD_DONE (3041L) +#define MAC_RAW_CTRL (3042L) +#define MAC_RAW_CTRL_OVERWR_LM (3043L) +#define MAC_RAW_CTRL_RESTART (3044L) +#define MAC_RAW_CTRL_TG_ACT (3045L) +#define MAC_RAW_CTRL_TG_ENA (3046L) +#define MAC_RAW_CTRL_WRAP (3047L) +#define MAC_RAW_DATA (3048L) +#define MAC_RAW_DATA_RAW_DATA (3049L) +#define MAC_RAW_REPETITION (3050L) +#define MAC_RAW_REPETITION_CNT (3051L) +#define MAC_RX_CONFIG (3052L) +#define MAC_RX_CONFIG_DESCRAMB (3053L) +#define MAC_RX_CONFIG_HOST_CLR_CNT (3054L) +#define MAC_RX_CONFIG_MAC_CLR_CNT (3055L) +#define MAC_RX_CONFIG_MIN_RX_FRAME (3056L) +#define MAC_RX_CONFIG_NT_DEBOUNCE_LATENCY (3057L) +#define MAC_RX_CONFIG_NT_FORCE_LINK_DOWN (3058L) +#define MAC_RX_CONFIG_NT_LINKUP_LATENCY (3059L) +#define MAC_RX_CONFIG_RST_BLK_ERR (3060L) +#define MAC_RX_CONFIG_RX_MAC_EN (3061L) +#define MAC_RX_CONFIG_TS_EOP (3062L) +#define MAC_RX_CONFIG_TXRX_LOOP (3063L) +#define MAC_RX_CONFIG2 (3064L) +#define MAC_RX_CONFIG2_NT_MOD_ABS_MASK_INT (3065L) +#define MAC_RX_CONFIG2_NT_MOD_ABS_MASK_LINK (3066L) +#define MAC_RX_CONFIG2_NT_MOD_ABS_MASK_RST (3067L) +#define MAC_RX_CONFIG2_NT_RXLOS_MASK_INT (3068L) +#define MAC_RX_CONFIG2_NT_RXLOS_MASK_LINK (3069L) +#define MAC_RX_CONFIG2_NT_RXLOS_MASK_RST (3070L) +#define MAC_RX_STATUS (3071L) +#define MAC_RX_STATUS_CORE_MODE (3072L) +#define MAC_RX_STATUS_LOCAL_FAULT (3073L) +#define MAC_RX_STATUS_REMOTE_FAULT (3074L) +#define MAC_RX_STATUS_RXTX_OVERFLOW (3075L) +#define MAC_RX_STATUS_VERSION (3076L) +#define MAC_TFG_ADDR (3077L) +#define MAC_TFG_ADDR_ADR (3078L) +#define MAC_TFG_ADDR_RDENA (3079L) +#define MAC_TFG_ADDR_RD_DONE (3080L) +#define MAC_TFG_CTRL (3081L) +#define MAC_TFG_CTRL_ID_ENA (3082L) +#define MAC_TFG_CTRL_ID_POS (3083L) +#define MAC_TFG_CTRL_RESTART (3084L) +#define MAC_TFG_CTRL_TG_ACT (3085L) +#define MAC_TFG_CTRL_TG_ENA (3086L) +#define MAC_TFG_CTRL_TIME_MODE (3087L) +#define MAC_TFG_CTRL_WRAP (3088L) +#define MAC_TFG_DATA (3089L) +#define MAC_TFG_DATA_GAP (3090L) +#define MAC_TFG_DATA_ID (3091L) +#define MAC_TFG_DATA_LENGTH (3092L) +#define MAC_TFG_FRAME_HDR (3093L) +#define MAC_TFG_FRAME_HDR_HDR (3094L) +#define MAC_TFG_REPETITION (3095L) +#define MAC_TFG_REPETITION_CNT (3096L) +#define MAC_TX_CONFIG (3097L) +#define MAC_TX_CONFIG_CLR_STICKY (3098L) +#define MAC_TX_CONFIG_CRC_ERR_INS (3099L) +#define MAC_TX_CONFIG_HOST_TX_ENA (3100L) +#define MAC_TX_CONFIG_MAC_LOOP (3101L) +#define MAC_TX_CONFIG_PCS_BIP_ERR (3102L) +#define MAC_TX_CONFIG_PCS_DIS_BIP_INS (3103L) +#define MAC_TX_CONFIG_PCS_IDLE (3104L) +#define MAC_TX_CONFIG_PCS_IDLE_DIS (3105L) +#define MAC_TX_CONFIG_PCS_LOCAL_FAULT (3106L) +#define MAC_TX_CONFIG_PCS_LOCAL_FAULT_DIS (3107L) +#define MAC_TX_CONFIG_PCS_REMOTE_FAULT (3108L) +#define MAC_TX_CONFIG_PCS_REMOTE_FAULT_DIS (3109L) +#define MAC_TX_CONFIG_PCS_SCRAMB_ENA (3110L) +#define MAC_TX_CONFIG_PCS_SCRAMB_ERR (3111L) +#define MAC_TX_CONFIG_TIME_OFFSET_TX (3112L) +#define MAC_TX_CONFIG_TS_EOP (3113L) +#define MAC_TX_STATUS (3114L) +#define MAC_TX_STATUS_PCS_ERR (3115L) +#define MAC_TX_STATUS_TX_MAC_ST (3116L) +#define MAC_TX_STATUS_UNDER_FLOW (3117L) +#define MAC_UPD_RX_COUNTERS (3118L) +#define MAC_UPD_RX_COUNTERS_TRIGGER (3119L) +/* MAC10 */ +#define MAC10_CFG_0 (3135L) +#define MAC10_CFG_0_PAD_ENA (3136L) +#define MAC10_CFG_0_RX_ENA (3137L) +#define MAC10_CFG_0_RX_PAUSE_ENA (3138L) +#define MAC10_CFG_0_STR_ENA (3139L) +#define MAC10_CFG_0_TX_ENA (3140L) +#define MAC10_CFG_0_TX_PAUSE_ENA (3141L) +#define MAC10_MA (3142L) +#define MAC10_MA_MAC10_ADR_0 (3143L) +#define MAC10_MA_MAC_ADR_0 (3144L) +#define MAC10_MA_LO (3145L) +#define MAC10_MA_LO_MA_LO (3146L) +#define MAC10_MA_MAX_SIZE (3147L) +#define MAC10_MA_MAX_SIZE_MAC10_ADR_1 (3148L) +#define MAC10_MA_MAX_SIZE_MAC_ADR_1 (3149L) +#define MAC10_MA_MAX_SIZE_MTU (3150L) +#define MAC10_MA_UP (3151L) +#define MAC10_MA_UP_MA_UP (3152L) +#define MAC10_STICKY_XAUI (3153L) +#define MAC10_STICKY_XAUI_STICKY_XAUI (3154L) +/* MAC100 */ +#define MAC100_CONF_SERDES_BITFRAG (3155L) +#define MAC100_CONF_SERDES_BITFRAG_BITFRAG (3156L) +#define MAC100_CONF_SERDES_DELAY (3157L) +#define MAC100_CONF_SERDES_DELAY_DELAY (3158L) +#define MAC100_CONF_SERDES_REORDER (3159L) +#define MAC100_CONF_SERDES_REORDER_REORDER (3160L) +#define MAC100_FAULTY_BLK (3161L) +#define MAC100_FAULTY_BLK_DATA (3162L) +#define MAC100_HOST_STAT_BYTE (3163L) +#define MAC100_HOST_STAT_BYTE_CNT (3164L) +#define MAC100_HOST_STAT_BYTE_FILL (3165L) +#define MAC100_HOST_STAT_BYTE_FILL_CNT (3166L) +#define MAC100_HOST_STAT_CRC (3167L) +#define MAC100_HOST_STAT_CRC_CNT (3168L) +#define MAC100_HOST_STAT_CV (3169L) +#define MAC100_HOST_STAT_CV_CNT (3170L) +#define MAC100_HOST_STAT_DROP (3171L) +#define MAC100_HOST_STAT_DROP_CNT (3172L) +#define MAC100_HOST_STAT_DROP_BYTE (3173L) +#define MAC100_HOST_STAT_DROP_BYTE_CNT (3174L) +#define MAC100_HOST_STAT_FRAME (3175L) +#define MAC100_HOST_STAT_FRAME_CNT (3176L) +#define MAC100_HOST_STAT_FRAME_FILL (3177L) +#define MAC100_HOST_STAT_FRAME_FILL_CNT (3178L) +#define MAC100_INT (3179L) +#define MAC100_INT_EN (3180L) +#define MAC100_INT_MAX_PACE (3181L) +#define MAC100_LINK_SUMMARY (3182L) +#define MAC100_LINK_SUMMARY_ABS (3183L) +#define MAC100_LINK_SUMMARY_GBOX_INTERR (3184L) +#define MAC100_LINK_SUMMARY_GLB_ALARMN (3185L) +#define MAC100_LINK_SUMMARY_LH_ABS (3186L) +#define MAC100_LINK_SUMMARY_LH_GLB_ALARMN (3187L) +#define MAC100_LINK_SUMMARY_LH_LOCAL_FAULT (3188L) +#define MAC100_LINK_SUMMARY_LH_REMOTE_FAULT (3189L) +#define MAC100_LINK_SUMMARY_LH_RX_LOS (3190L) +#define MAC100_LINK_SUMMARY_LINK_DOWN_CNT (3191L) +#define MAC100_LINK_SUMMARY_LL_PHY_LINK_STATE (3192L) +#define MAC100_LINK_SUMMARY_LOCAL_FAULT (3193L) +#define MAC100_LINK_SUMMARY_NT_PHY_LINK_STATE (3194L) +#define MAC100_LINK_SUMMARY_REMOTE_FAULT (3195L) +#define MAC100_LINK_SUMMARY_RX_LOS (3196L) +#define MAC100_MAC_STAT_BYTE (3197L) +#define MAC100_MAC_STAT_BYTE_CNT (3198L) +#define MAC100_MAC_STAT_CRC (3199L) +#define MAC100_MAC_STAT_CRC_CNT (3200L) +#define MAC100_MAC_STAT_CV (3201L) +#define MAC100_MAC_STAT_CV_CNT (3202L) +#define MAC100_MAC_STAT_FC (3203L) +#define MAC100_MAC_STAT_FC_CNT (3204L) +#define MAC100_MAC_STAT_FRAME (3205L) +#define MAC100_MAC_STAT_FRAME_CNT (3206L) +#define MAC100_MAC_STAT_MICRO_DROP (3207L) +#define MAC100_MAC_STAT_MICRO_DROP_CNT (3208L) +#define MAC100_MAC_STAT_PAUSE (3209L) +#define MAC100_MAC_STAT_PAUSE_CNT (3210L) +#define MAC100_MAC_STAT_RATE_DROP (3211L) +#define MAC100_MAC_STAT_RATE_DROP_CNT (3212L) +#define MAC100_MAC_STAT_TRUNC (3213L) +#define MAC100_MAC_STAT_TRUNC_CNT (3214L) +#define MAC100_MDS_CEN_VAL (3215L) +#define MAC100_MDS_CEN_VAL_VAL (3216L) +#define MAC100_MDS_CONF (3217L) +#define MAC100_MDS_CONF_CENTER_REC_ENA (3218L) +#define MAC100_MDS_CONF_CLR_STAT (3219L) +#define MAC100_MDS_CONF_ENA_TS_MOD (3220L) +#define MAC100_MDS_CONF_REC_ENA (3221L) +#define MAC100_MDS_CONF_TIME_MODE (3222L) +#define MAC100_MDS_DATA (3223L) +#define MAC100_MDS_DATA_DATA (3224L) +#define MAC100_MDS_FRAMES (3225L) +#define MAC100_MDS_FRAMES_CNT (3226L) +#define MAC100_MDS_MAX (3227L) +#define MAC100_MDS_MAX_MAX (3228L) +#define MAC100_MDS_MIN (3229L) +#define MAC100_MDS_MIN_MIN (3230L) +#define MAC100_MDS_STAT (3231L) +#define MAC100_MDS_STAT_CLR_BUSY (3232L) +#define MAC100_MDS_STAT_HIT_MAX (3233L) +#define MAC100_MDS_STAT_HIT_MIN (3234L) +#define MAC100_MDS_VAL_REC (3235L) +#define MAC100_MDS_VAL_REC_VALUE (3236L) +#define MAC100_MDS_VAL_REC_FRAME (3237L) +#define MAC100_MDS_VAL_REC_FRAME_VALUE (3238L) +#define MAC100_NT_PORT_CTRL (3239L) +#define MAC100_NT_PORT_CTRL_LED_MODE (3240L) +#define MAC100_RAM_MDS_ADDR (3241L) +#define MAC100_RAM_MDS_ADDR_ADR (3242L) +#define MAC100_RAM_MDS_ADDR_CLR_RAM (3243L) +#define MAC100_RAM_MDS_ADDR_RD_DONE (3244L) +#define MAC100_RAM_MDS_ADDR_RD_ENA (3245L) +#define MAC100_RAW_ADDR (3246L) +#define MAC100_RAW_ADDR_ADR (3247L) +#define MAC100_RAW_ADDR_RDENA (3248L) +#define MAC100_RAW_ADDR_RD_DONE (3249L) +#define MAC100_RAW_CTRL (3250L) +#define MAC100_RAW_CTRL_OVERWR_LM (3251L) +#define MAC100_RAW_CTRL_RESTART (3252L) +#define MAC100_RAW_CTRL_TG_ACT (3253L) +#define MAC100_RAW_CTRL_TG_ENA (3254L) +#define MAC100_RAW_CTRL_WRAP (3255L) +#define MAC100_RAW_DATA (3256L) +#define MAC100_RAW_DATA_RAW_DATA (3257L) +#define MAC100_RAW_REPETITION (3258L) +#define MAC100_RAW_REPETITION_CNT (3259L) +#define MAC100_RX_CONFIG (3260L) +#define MAC100_RX_CONFIG_DESCRAMB (3261L) +#define MAC100_RX_CONFIG_HADP_RUN_MODE (3262L) +#define MAC100_RX_CONFIG_HOST_CLR_CNT (3263L) +#define MAC100_RX_CONFIG_MAC_CLR_CNT (3264L) +#define MAC100_RX_CONFIG_MIN_RX_FRAME (3265L) +#define MAC100_RX_CONFIG_NT_DEBOUNCE_LATENCY (3266L) +#define MAC100_RX_CONFIG_NT_FORCE_LINK_DOWN (3267L) +#define MAC100_RX_CONFIG_NT_LINKUP_LATENCY (3268L) +#define MAC100_RX_CONFIG_RST_BLK_ERR (3269L) +#define MAC100_RX_CONFIG_RX_MAC_EN (3270L) +#define MAC100_RX_CONFIG_TS_EOP (3271L) +#define MAC100_RX_CONFIG_TXRX_LOOP (3272L) +#define MAC100_RX_CONFIG2 (3273L) +#define MAC100_RX_CONFIG2_NT_MOD_ABS_MASK_INT (3274L) +#define MAC100_RX_CONFIG2_NT_MOD_ABS_MASK_LINK (3275L) +#define MAC100_RX_CONFIG2_NT_MOD_ABS_MASK_RST (3276L) +#define MAC100_RX_CONFIG2_NT_RXLOS_MASK_INT (3277L) +#define MAC100_RX_CONFIG2_NT_RXLOS_MASK_LINK (3278L) +#define MAC100_RX_CONFIG2_NT_RXLOS_MASK_RST (3279L) +#define MAC100_RX_STATUS (3280L) +#define MAC100_RX_STATUS_CORE_MODE (3281L) +#define MAC100_RX_STATUS_LOCAL_FAULT (3282L) +#define MAC100_RX_STATUS_REMOTE_FAULT (3283L) +#define MAC100_RX_STATUS_RXTX_OVERFLOW (3284L) +#define MAC100_RX_STATUS_VERSION (3285L) +#define MAC100_TFG_ADDR (3286L) +#define MAC100_TFG_ADDR_ADR (3287L) +#define MAC100_TFG_ADDR_RDENA (3288L) +#define MAC100_TFG_ADDR_RD_DONE (3289L) +#define MAC100_TFG_CTRL (3290L) +#define MAC100_TFG_CTRL_ID_ENA (3291L) +#define MAC100_TFG_CTRL_ID_POS (3292L) +#define MAC100_TFG_CTRL_RESTART (3293L) +#define MAC100_TFG_CTRL_TG_ACT (3294L) +#define MAC100_TFG_CTRL_TG_ENA (3295L) +#define MAC100_TFG_CTRL_TIME_MODE (3296L) +#define MAC100_TFG_CTRL_WRAP (3297L) +#define MAC100_TFG_DATA (3298L) +#define MAC100_TFG_DATA_GAP (3299L) +#define MAC100_TFG_DATA_ID (3300L) +#define MAC100_TFG_DATA_LENGTH (3301L) +#define MAC100_TFG_FRAME_HDR (3302L) +#define MAC100_TFG_FRAME_HDR_HDR (3303L) +#define MAC100_TFG_REPETITION (3304L) +#define MAC100_TFG_REPETITION_CNT (3305L) +#define MAC100_TX_CONFIG (3306L) +#define MAC100_TX_CONFIG_CLR_STICKY (3307L) +#define MAC100_TX_CONFIG_CRC_ERR_INS (3308L) +#define MAC100_TX_CONFIG_HADP_LOOP (3309L) +#define MAC100_TX_CONFIG_HOST_TX_ENA (3310L) +#define MAC100_TX_CONFIG_MAC_LOOP (3311L) +#define MAC100_TX_CONFIG_PCS_BIP_ERR (3312L) +#define MAC100_TX_CONFIG_PCS_DIS_BIP_INS (3313L) +#define MAC100_TX_CONFIG_PCS_IDLE (3314L) +#define MAC100_TX_CONFIG_PCS_IDLE_DIS (3315L) +#define MAC100_TX_CONFIG_PCS_LOCAL_FAULT (3316L) +#define MAC100_TX_CONFIG_PCS_LOCAL_FAULT_DIS (3317L) +#define MAC100_TX_CONFIG_PCS_REMOTE_FAULT (3318L) +#define MAC100_TX_CONFIG_PCS_REMOTE_FAULT_DIS (3319L) +#define MAC100_TX_CONFIG_PCS_SCRAMB_ENA (3320L) +#define MAC100_TX_CONFIG_PCS_SCRAMB_ERR (3321L) +#define MAC100_TX_CONFIG_TIME_OFFSET_TX (3322L) +#define MAC100_TX_CONFIG_TS_EOP (3323L) +#define MAC100_TX_STATUS (3324L) +#define MAC100_TX_STATUS_PCS_ERR (3325L) +#define MAC100_TX_STATUS_TX_HADP_ST (3326L) +#define MAC100_TX_STATUS_TX_MAC_ST (3327L) +#define MAC100_TX_STATUS_UNDER_FLOW (3328L) +#define MAC100_UPD_RX_COUNTERS (3329L) +#define MAC100_UPD_RX_COUNTERS_TRIGGER (3330L) +/* MAC10G */ +#define MAC10G_CFG (3331L) +#define MAC10G_CFG_MIN_RX_FRAME (3332L) +#define MAC10G_CFG_RX_ENA (3333L) +#define MAC10G_CFG_RX_EOP_TS (3334L) +#define MAC10G_CFG_RX_PAUSE_ENA (3335L) +#define MAC10G_CFG_STR_ENA (3336L) +#define MAC10G_CFG_TX_ENA (3337L) +#define MAC10G_CFG_TX_PAUSE_ENA (3338L) +#define MAC10G_MA_LO (3339L) +#define MAC10G_MA_LO_MA_LO (3340L) +#define MAC10G_MA_UP (3341L) +#define MAC10G_MA_UP_MA_UP (3342L) +/* MAC1G */ +#define MAC1G_CFG (3343L) +#define MAC1G_CFG_MIN_RX_FRAME (3344L) +#define MAC1G_CFG_RX_ENA (3345L) +#define MAC1G_CFG_RX_EOP_TS (3346L) +#define MAC1G_CFG_RX_PAUSE_ENA (3347L) +#define MAC1G_CFG_SPEED (3348L) +#define MAC1G_CFG_STR_ENA (3349L) +#define MAC1G_CFG_TX_ENA (3350L) +#define MAC1G_CFG_TX_PAUSE_ENA (3351L) +#define MAC1G_MA_LO (3352L) +#define MAC1G_MA_LO_MA_LO (3353L) +#define MAC1G_MA_UP (3354L) +#define MAC1G_MA_UP_MA_UP (3355L) +/* MAC_PCS */ +#define MAC_PCS_BAD_CODE (3366L) +#define MAC_PCS_BAD_CODE_CODE_ERR (3367L) +#define MAC_PCS_BIP_ERR (3368L) +#define MAC_PCS_BIP_ERR_BIP_ERR (3369L) +#define MAC_PCS_BLOCK_LOCK (3370L) +#define MAC_PCS_BLOCK_LOCK_LOCK (3371L) +#define MAC_PCS_BLOCK_LOCK_CHG (3372L) +#define MAC_PCS_BLOCK_LOCK_CHG_LOCK_CHG (3373L) +#define MAC_PCS_CLKRX_FRQ (3374L) +#define MAC_PCS_CLKRX_FRQ_RX_FREQ (3375L) +#define MAC_PCS_CLKTX_FRQ (3376L) +#define MAC_PCS_CLKTX_FRQ_TX_FREQ (3377L) +#define MAC_PCS_DEBOUNCE_CTRL (3378L) +#define MAC_PCS_DEBOUNCE_CTRL_NT_DEBOUNCE_LATENCY (3379L) +#define MAC_PCS_DEBOUNCE_CTRL_NT_FORCE_LINK_DOWN (3380L) +#define MAC_PCS_DEBOUNCE_CTRL_NT_LINKUP_LATENCY (3381L) +#define MAC_PCS_DEBOUNCE_CTRL_NT_PORT_CTRL (3382L) +#define MAC_PCS_DRP_CONFIG (3383L) +#define MAC_PCS_DRP_CONFIG_DRP_ADR (3384L) +#define MAC_PCS_DRP_CONFIG_DRP_DI (3385L) +#define MAC_PCS_DRP_CONFIG_DRP_EN (3386L) +#define MAC_PCS_DRP_CONFIG_DRP_MOD_ADR (3387L) +#define MAC_PCS_DRP_CONFIG_DRP_WREN (3388L) +#define MAC_PCS_DRP_CTRL (3389L) +#define MAC_PCS_DRP_CTRL_ADR (3390L) +#define MAC_PCS_DRP_CTRL_DATA (3391L) +#define MAC_PCS_DRP_CTRL_DBG_BUSY (3392L) +#define MAC_PCS_DRP_CTRL_DONE (3393L) +#define MAC_PCS_DRP_CTRL_MOD_ADR (3394L) +#define MAC_PCS_DRP_CTRL_WREN (3395L) +#define MAC_PCS_DRP_DATA (3396L) +#define MAC_PCS_DRP_DATA_DRP_DO (3397L) +#define MAC_PCS_DRP_DATA_DRP_RDY (3398L) +#define MAC_PCS_FEC_CTRL (3399L) +#define MAC_PCS_FEC_CTRL_RS_FEC_CTRL_IN (3400L) +#define MAC_PCS_FEC_CW_CNT (3401L) +#define MAC_PCS_FEC_CW_CNT_CW_CNT (3402L) +#define MAC_PCS_FEC_ERR_CNT_0 (3403L) +#define MAC_PCS_FEC_ERR_CNT_0_ERR_CNT (3404L) +#define MAC_PCS_FEC_ERR_CNT_1 (3405L) +#define MAC_PCS_FEC_ERR_CNT_1_ERR_CNT (3406L) +#define MAC_PCS_FEC_ERR_CNT_2 (3407L) +#define MAC_PCS_FEC_ERR_CNT_2_ERR_CNT (3408L) +#define MAC_PCS_FEC_ERR_CNT_3 (3409L) +#define MAC_PCS_FEC_ERR_CNT_3_ERR_CNT (3410L) +#define MAC_PCS_FEC_LANE_DLY_0 (3411L) +#define MAC_PCS_FEC_LANE_DLY_0_DLY (3412L) +#define MAC_PCS_FEC_LANE_DLY_1 (3413L) +#define MAC_PCS_FEC_LANE_DLY_1_DLY (3414L) +#define MAC_PCS_FEC_LANE_DLY_2 (3415L) +#define MAC_PCS_FEC_LANE_DLY_2_DLY (3416L) +#define MAC_PCS_FEC_LANE_DLY_3 (3417L) +#define MAC_PCS_FEC_LANE_DLY_3_DLY (3418L) +#define MAC_PCS_FEC_LANE_MAP (3419L) +#define MAC_PCS_FEC_LANE_MAP_MAPPING (3420L) +#define MAC_PCS_FEC_STAT (3421L) +#define MAC_PCS_FEC_STAT_AM_LOCK (3422L) +#define MAC_PCS_FEC_STAT_AM_LOCK_0 (3423L) +#define MAC_PCS_FEC_STAT_AM_LOCK_1 (3424L) +#define MAC_PCS_FEC_STAT_AM_LOCK_2 (3425L) +#define MAC_PCS_FEC_STAT_AM_LOCK_3 (3426L) +#define MAC_PCS_FEC_STAT_BLOCK_LOCK (3427L) +#define MAC_PCS_FEC_STAT_BYPASS (3428L) +#define MAC_PCS_FEC_STAT_FEC_LANE_ALGN (3429L) +#define MAC_PCS_FEC_STAT_HI_SER (3430L) +#define MAC_PCS_FEC_STAT_PCS_LANE_ALGN (3431L) +#define MAC_PCS_FEC_STAT_VALID (3432L) +#define MAC_PCS_FEC_UCW_CNT (3433L) +#define MAC_PCS_FEC_UCW_CNT_UCW_CNT (3434L) +#define MAC_PCS_FRAMING_ERR (3435L) +#define MAC_PCS_FRAMING_ERR_FRAMING_ERR (3436L) +#define MAC_PCS_GTY_CTL (3437L) +#define MAC_PCS_GTY_CTL_CDR_HOLD_0 (3438L) +#define MAC_PCS_GTY_CTL_CDR_HOLD_1 (3439L) +#define MAC_PCS_GTY_CTL_CDR_HOLD_2 (3440L) +#define MAC_PCS_GTY_CTL_CDR_HOLD_3 (3441L) +#define MAC_PCS_GTY_CTL_RX (3442L) +#define MAC_PCS_GTY_CTL_RX_CDR_HOLD_0 (3443L) +#define MAC_PCS_GTY_CTL_RX_CDR_HOLD_1 (3444L) +#define MAC_PCS_GTY_CTL_RX_CDR_HOLD_2 (3445L) +#define MAC_PCS_GTY_CTL_RX_CDR_HOLD_3 (3446L) +#define MAC_PCS_GTY_CTL_RX_EQUA_RST_0 (3447L) +#define MAC_PCS_GTY_CTL_RX_EQUA_RST_1 (3448L) +#define MAC_PCS_GTY_CTL_RX_EQUA_RST_2 (3449L) +#define MAC_PCS_GTY_CTL_RX_EQUA_RST_3 (3450L) +#define MAC_PCS_GTY_CTL_RX_LPM_EN_0 (3451L) +#define MAC_PCS_GTY_CTL_RX_LPM_EN_1 (3452L) +#define MAC_PCS_GTY_CTL_RX_LPM_EN_2 (3453L) +#define MAC_PCS_GTY_CTL_RX_LPM_EN_3 (3454L) +#define MAC_PCS_GTY_CTL_RX_POLARITY_0 (3455L) +#define MAC_PCS_GTY_CTL_RX_POLARITY_1 (3456L) +#define MAC_PCS_GTY_CTL_RX_POLARITY_2 (3457L) +#define MAC_PCS_GTY_CTL_RX_POLARITY_3 (3458L) +#define MAC_PCS_GTY_CTL_RX_RATE_0 (3459L) +#define MAC_PCS_GTY_CTL_RX_RATE_1 (3460L) +#define MAC_PCS_GTY_CTL_RX_RATE_2 (3461L) +#define MAC_PCS_GTY_CTL_RX_RATE_3 (3462L) +#define MAC_PCS_GTY_CTL_TX (3463L) +#define MAC_PCS_GTY_CTL_TX_INHIBIT_0 (3464L) +#define MAC_PCS_GTY_CTL_TX_INHIBIT_1 (3465L) +#define MAC_PCS_GTY_CTL_TX_INHIBIT_2 (3466L) +#define MAC_PCS_GTY_CTL_TX_INHIBIT_3 (3467L) +#define MAC_PCS_GTY_CTL_TX_POLARITY_0 (3468L) +#define MAC_PCS_GTY_CTL_TX_POLARITY_1 (3469L) +#define MAC_PCS_GTY_CTL_TX_POLARITY_2 (3470L) +#define MAC_PCS_GTY_CTL_TX_POLARITY_3 (3471L) +#define MAC_PCS_GTY_DIFF_CTL (3472L) +#define MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_0 (3473L) +#define MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_1 (3474L) +#define MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_2 (3475L) +#define MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_3 (3476L) +#define MAC_PCS_GTY_LOOP (3477L) +#define MAC_PCS_GTY_LOOP_GT_LOOP_0 (3478L) +#define MAC_PCS_GTY_LOOP_GT_LOOP_1 (3479L) +#define MAC_PCS_GTY_LOOP_GT_LOOP_2 (3480L) +#define MAC_PCS_GTY_LOOP_GT_LOOP_3 (3481L) +#define MAC_PCS_GTY_POST_CURSOR (3482L) +#define MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_0 (3483L) +#define MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_1 (3484L) +#define MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_2 (3485L) +#define MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_3 (3486L) +#define MAC_PCS_GTY_PRBS_SEL (3487L) +#define MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_0 (3488L) +#define MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_1 (3489L) +#define MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_2 (3490L) +#define MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_3 (3491L) +#define MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_0 (3492L) +#define MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_1 (3493L) +#define MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_2 (3494L) +#define MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_3 (3495L) +#define MAC_PCS_GTY_PRE_CURSOR (3496L) +#define MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_0 (3497L) +#define MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_1 (3498L) +#define MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_2 (3499L) +#define MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_3 (3500L) +#define MAC_PCS_GTY_RX_BUF_STAT (3501L) +#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_0 (3502L) +#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_1 (3503L) +#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_2 (3504L) +#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_3 (3505L) +#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_0 (3506L) +#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_1 (3507L) +#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_2 (3508L) +#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_3 (3509L) +#define MAC_PCS_GTY_SCAN_CTL (3510L) +#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_0 (3511L) +#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_1 (3512L) +#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_2 (3513L) +#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_3 (3514L) +#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_0 (3515L) +#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_1 (3516L) +#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_2 (3517L) +#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_3 (3518L) +#define MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_0 (3519L) +#define MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_1 (3520L) +#define MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_2 (3521L) +#define MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_3 (3522L) +#define MAC_PCS_GTY_SCAN_CTL_PRBS_RST_0 (3523L) +#define MAC_PCS_GTY_SCAN_CTL_PRBS_RST_1 (3524L) +#define MAC_PCS_GTY_SCAN_CTL_PRBS_RST_2 (3525L) +#define MAC_PCS_GTY_SCAN_CTL_PRBS_RST_3 (3526L) +#define MAC_PCS_GTY_SCAN_STAT (3527L) +#define MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_0 (3528L) +#define MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_1 (3529L) +#define MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_2 (3530L) +#define MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_3 (3531L) +#define MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_0 (3532L) +#define MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_1 (3533L) +#define MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_2 (3534L) +#define MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_3 (3535L) +#define MAC_PCS_GTY_STAT (3536L) +#define MAC_PCS_GTY_STAT_RX_RST_DONE_0 (3537L) +#define MAC_PCS_GTY_STAT_RX_RST_DONE_1 (3538L) +#define MAC_PCS_GTY_STAT_RX_RST_DONE_2 (3539L) +#define MAC_PCS_GTY_STAT_RX_RST_DONE_3 (3540L) +#define MAC_PCS_GTY_STAT_TX_BUF_STAT_0 (3541L) +#define MAC_PCS_GTY_STAT_TX_BUF_STAT_1 (3542L) +#define MAC_PCS_GTY_STAT_TX_BUF_STAT_2 (3543L) +#define MAC_PCS_GTY_STAT_TX_BUF_STAT_3 (3544L) +#define MAC_PCS_GTY_STAT_TX_RST_DONE_0 (3545L) +#define MAC_PCS_GTY_STAT_TX_RST_DONE_1 (3546L) +#define MAC_PCS_GTY_STAT_TX_RST_DONE_2 (3547L) +#define MAC_PCS_GTY_STAT_TX_RST_DONE_3 (3548L) +#define MAC_PCS_LANE_ALIGNER_FILL (3549L) +#define MAC_PCS_LANE_ALIGNER_FILL_FILL (3550L) +#define MAC_PCS_LINK_SUMMARY (3551L) +#define MAC_PCS_LINK_SUMMARY_ABS (3552L) +#define MAC_PCS_LINK_SUMMARY_LH_ABS (3553L) +#define MAC_PCS_LINK_SUMMARY_LH_LOCAL_FAULT (3554L) +#define MAC_PCS_LINK_SUMMARY_LH_REMOTE_FAULT (3555L) +#define MAC_PCS_LINK_SUMMARY_LINK_DOWN_CNT (3556L) +#define MAC_PCS_LINK_SUMMARY_LL_PHY_LINK_STATE (3557L) +#define MAC_PCS_LINK_SUMMARY_LOCAL_FAULT (3558L) +#define MAC_PCS_LINK_SUMMARY_NIM_INTERR (3559L) +#define MAC_PCS_LINK_SUMMARY_NT_PHY_LINK_STATE (3560L) +#define MAC_PCS_LINK_SUMMARY_REMOTE_FAULT (3561L) +#define MAC_PCS_LINK_SUMMARY_RESERVED (3562L) +#define MAC_PCS_MAC_PCS_CONFIG (3563L) +#define MAC_PCS_MAC_PCS_CONFIG_RX_CORE_RST (3564L) +#define MAC_PCS_MAC_PCS_CONFIG_RX_ENABLE (3565L) +#define MAC_PCS_MAC_PCS_CONFIG_RX_FORCE_RESYNC (3566L) +#define MAC_PCS_MAC_PCS_CONFIG_RX_PATH_RST (3567L) +#define MAC_PCS_MAC_PCS_CONFIG_RX_TEST_PATTERN (3568L) +#define MAC_PCS_MAC_PCS_CONFIG_TX_CORE_RST (3569L) +#define MAC_PCS_MAC_PCS_CONFIG_TX_ENABLE (3570L) +#define MAC_PCS_MAC_PCS_CONFIG_TX_FCS_REMOVE (3571L) +#define MAC_PCS_MAC_PCS_CONFIG_TX_PATH_RST (3572L) +#define MAC_PCS_MAC_PCS_CONFIG_TX_SEND_IDLE (3573L) +#define MAC_PCS_MAC_PCS_CONFIG_TX_SEND_RFI (3574L) +#define MAC_PCS_MAC_PCS_CONFIG_TX_TEST_PATTERN (3575L) +#define MAC_PCS_MAX_PKT_LEN (3576L) +#define MAC_PCS_MAX_PKT_LEN_MAX_LEN (3577L) +#define MAC_PCS_MF_ERR (3578L) +#define MAC_PCS_MF_ERR_MF_ERR (3579L) +#define MAC_PCS_MF_LEN_ERR (3580L) +#define MAC_PCS_MF_LEN_ERR_MF_LEN_ERR (3581L) +#define MAC_PCS_MF_REPEAT_ERR (3582L) +#define MAC_PCS_MF_REPEAT_ERR_MF_REPEAT_ERR (3583L) +#define MAC_PCS_PHYMAC_MISC (3584L) +#define MAC_PCS_PHYMAC_MISC_TS_EOP (3585L) +#define MAC_PCS_PHYMAC_MISC_TX_MUX_STATE (3586L) +#define MAC_PCS_PHYMAC_MISC_TX_SEL_HOST (3587L) +#define MAC_PCS_PHYMAC_MISC_TX_SEL_RX_LOOP (3588L) +#define MAC_PCS_PHYMAC_MISC_TX_SEL_TFG (3589L) +#define MAC_PCS_PHY_STAT (3590L) +#define MAC_PCS_PHY_STAT_ALARM (3591L) +#define MAC_PCS_PHY_STAT_MOD_PRS (3592L) +#define MAC_PCS_PHY_STAT_RX_LOS (3593L) +#define MAC_PCS_STAT_PCS_RX (3594L) +#define MAC_PCS_STAT_PCS_RX_ALIGNED (3595L) +#define MAC_PCS_STAT_PCS_RX_ALIGNED_ERR (3596L) +#define MAC_PCS_STAT_PCS_RX_GOT_SIGNAL_OS (3597L) +#define MAC_PCS_STAT_PCS_RX_HI_BER (3598L) +#define MAC_PCS_STAT_PCS_RX_INTERNAL_LOCAL_FAULT (3599L) +#define MAC_PCS_STAT_PCS_RX_LOCAL_FAULT (3600L) +#define MAC_PCS_STAT_PCS_RX_MISALIGNED (3601L) +#define MAC_PCS_STAT_PCS_RX_RECEIVED_LOCAL_FAULT (3602L) +#define MAC_PCS_STAT_PCS_RX_REMOTE_FAULT (3603L) +#define MAC_PCS_STAT_PCS_RX_STATUS (3604L) +#define MAC_PCS_STAT_PCS_RX_LATCH (3605L) +#define MAC_PCS_STAT_PCS_RX_LATCH_ALIGNED (3606L) +#define MAC_PCS_STAT_PCS_RX_LATCH_ALIGNED_ERR (3607L) +#define MAC_PCS_STAT_PCS_RX_LATCH_GOT_SIGNAL_OS (3608L) +#define MAC_PCS_STAT_PCS_RX_LATCH_HI_BER (3609L) +#define MAC_PCS_STAT_PCS_RX_LATCH_INTERNAL_LOCAL_FAULT (3610L) +#define MAC_PCS_STAT_PCS_RX_LATCH_LOCAL_FAULT (3611L) +#define MAC_PCS_STAT_PCS_RX_LATCH_MISALIGNED (3612L) +#define MAC_PCS_STAT_PCS_RX_LATCH_RECEIVED_LOCAL_FAULT (3613L) +#define MAC_PCS_STAT_PCS_RX_LATCH_REMOTE_FAULT (3614L) +#define MAC_PCS_STAT_PCS_RX_LATCH_STATUS (3615L) +#define MAC_PCS_STAT_PCS_TX (3616L) +#define MAC_PCS_STAT_PCS_TX_LOCAL_FAULT (3617L) +#define MAC_PCS_STAT_PCS_TX_LOCAL_FAULT_CHANGED (3618L) +#define MAC_PCS_STAT_PCS_TX_PTP_FIFO_READ_ERROR (3619L) +#define MAC_PCS_STAT_PCS_TX_PTP_FIFO_READ_ERROR_CHANGED (3620L) +#define MAC_PCS_STAT_PCS_TX_PTP_FIFO_WRITE_ERROR (3621L) +#define MAC_PCS_STAT_PCS_TX_PTP_FIFO_WRITE_ERROR_CHANGED (3622L) +#define MAC_PCS_STAT_PCS_TX_TX_OVFOUT (3623L) +#define MAC_PCS_STAT_PCS_TX_TX_OVFOUT_CHANGED (3624L) +#define MAC_PCS_STAT_PCS_TX_TX_UNFOUT (3625L) +#define MAC_PCS_STAT_PCS_TX_TX_UNFOUT_CHANGED (3626L) +#define MAC_PCS_SYNCED (3627L) +#define MAC_PCS_SYNCED_SYNC (3628L) +#define MAC_PCS_SYNCED_ERR (3629L) +#define MAC_PCS_SYNCED_ERR_SYNC_ERROR (3630L) +#define MAC_PCS_TEST_ERR (3631L) +#define MAC_PCS_TEST_ERR_CODE_ERR (3632L) +#define MAC_PCS_TIMESTAMP_COMP (3633L) +#define MAC_PCS_TIMESTAMP_COMP_RX_DLY (3634L) +#define MAC_PCS_TIMESTAMP_COMP_TX_DLY (3635L) +#define MAC_PCS_VL_DEMUXED (3636L) +#define MAC_PCS_VL_DEMUXED_LOCK (3637L) +#define MAC_PCS_VL_DEMUXED_CHG (3638L) +#define MAC_PCS_VL_DEMUXED_CHG_LOCK_CHG (3639L) +#define MAC_PCS_VL_NUMBER (3640L) +#define MAC_PCS_VL_NUMBER_VL_NUMBER (3641L) +/* MAC_PCS_XXV */ +#define MAC_PCS_XXV_ANEG_1G_CONFIG_0 (3642L) +#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_ASMDIR (3643L) +#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_BYPASS (3644L) +#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_ENABLE (3645L) +#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_PAUSE (3646L) +#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_RESTART (3647L) +#define MAC_PCS_XXV_ANEG_1G_CONFIG_1 (3648L) +#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_ASMDIR (3649L) +#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_BYPASS (3650L) +#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_ENABLE (3651L) +#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_PAUSE (3652L) +#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_RESTART (3653L) +#define MAC_PCS_XXV_ANEG_1G_STA_0 (3654L) +#define MAC_PCS_XXV_ANEG_1G_STA_0_COMPLETE (3655L) +#define MAC_PCS_XXV_ANEG_1G_STA_0_LP_ANEG_ABLE (3656L) +#define MAC_PCS_XXV_ANEG_1G_STA_0_LP_ASM (3657L) +#define MAC_PCS_XXV_ANEG_1G_STA_0_LP_PAUSE (3658L) +#define MAC_PCS_XXV_ANEG_1G_STA_0_LP_RF (3659L) +#define MAC_PCS_XXV_ANEG_1G_STA_1 (3660L) +#define MAC_PCS_XXV_ANEG_1G_STA_1_COMPLETE (3661L) +#define MAC_PCS_XXV_ANEG_1G_STA_1_LP_ANEG_ABLE (3662L) +#define MAC_PCS_XXV_ANEG_1G_STA_1_LP_ASM (3663L) +#define MAC_PCS_XXV_ANEG_1G_STA_1_LP_PAUSE (3664L) +#define MAC_PCS_XXV_ANEG_1G_STA_1_LP_RF (3665L) +#define MAC_PCS_XXV_ANEG_ABILITY_0 (3666L) +#define MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR (3667L) +#define MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR1 (3668L) +#define MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR_S (3669L) +#define MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR (3670L) +#define MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR1 (3671L) +#define MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR_S (3672L) +#define MAC_PCS_XXV_ANEG_ABILITY_1 (3673L) +#define MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR (3674L) +#define MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR1 (3675L) +#define MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR_S (3676L) +#define MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR (3677L) +#define MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR1 (3678L) +#define MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR_S (3679L) +#define MAC_PCS_XXV_ANEG_ABILITY_2 (3680L) +#define MAC_PCS_XXV_ANEG_ABILITY_2_BASE25G_CR (3681L) +#define MAC_PCS_XXV_ANEG_ABILITY_2_BASE25G_CR1 (3682L) +#define MAC_PCS_XXV_ANEG_ABILITY_2_BASE25G_CR_S (3683L) +#define MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR (3684L) +#define MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR1 (3685L) +#define MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR_S (3686L) +#define MAC_PCS_XXV_ANEG_ABILITY_3 (3687L) +#define MAC_PCS_XXV_ANEG_ABILITY_3_BASE25G_CR (3688L) +#define MAC_PCS_XXV_ANEG_ABILITY_3_BASE25G_CR1 (3689L) +#define MAC_PCS_XXV_ANEG_ABILITY_3_BASE25G_CR_S (3690L) +#define MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR (3691L) +#define MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR1 (3692L) +#define MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR_S (3693L) +#define MAC_PCS_XXV_ANEG_CONFIG_0 (3694L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_ASMDIR (3695L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_BYPASS (3696L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_ENABLE (3697L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST (3698L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST_10G (3699L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_ABILITY (3700L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_REQUEST (3701L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_HIDE_FEC74 (3702L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_NONCE_SEED (3703L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_PAUSE (3704L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_PSEUDO (3705L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_REMOTE_FAULT (3706L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_RESTART (3707L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_RS_FEC_REQUEST (3708L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_SW_FEC_OVERWRITE (3709L) +#define MAC_PCS_XXV_ANEG_CONFIG_0_SW_SPEED_OVERWRITE (3710L) +#define MAC_PCS_XXV_ANEG_CONFIG_1 (3711L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_ASMDIR (3712L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_BYPASS (3713L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_ENABLE (3714L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST (3715L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST_10G (3716L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_ABILITY (3717L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_REQUEST (3718L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_HIDE_FEC74 (3719L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_NONCE_SEED (3720L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_PAUSE (3721L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_PSEUDO (3722L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_REMOTE_FAULT (3723L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_RESTART (3724L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_RS_FEC_REQUEST (3725L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_SW_FEC_OVERWRITE (3726L) +#define MAC_PCS_XXV_ANEG_CONFIG_1_SW_SPEED_OVERWRITE (3727L) +#define MAC_PCS_XXV_ANEG_CONFIG_2 (3728L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_ASMDIR (3729L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_BYPASS (3730L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_ENABLE (3731L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST (3732L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST_10G (3733L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_ABILITY (3734L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_REQUEST (3735L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_HIDE_FEC74 (3736L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_NONCE_SEED (3737L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_PAUSE (3738L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_PSEUDO (3739L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_REMOTE_FAULT (3740L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_RESTART (3741L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_RS_FEC_REQUEST (3742L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_SW_FEC_OVERWRITE (3743L) +#define MAC_PCS_XXV_ANEG_CONFIG_2_SW_SPEED_OVERWRITE (3744L) +#define MAC_PCS_XXV_ANEG_CONFIG_3 (3745L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_ASMDIR (3746L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_BYPASS (3747L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_ENABLE (3748L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST (3749L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST_10G (3750L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_ABILITY (3751L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_REQUEST (3752L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_HIDE_FEC74 (3753L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_NONCE_SEED (3754L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_PAUSE (3755L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_PSEUDO (3756L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_REMOTE_FAULT (3757L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_RESTART (3758L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_RS_FEC_REQUEST (3759L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_SW_FEC_OVERWRITE (3760L) +#define MAC_PCS_XXV_ANEG_CONFIG_3_SW_SPEED_OVERWRITE (3761L) +#define MAC_PCS_XXV_ANEG_DEBUG_0 (3762L) +#define MAC_PCS_XXV_ANEG_DEBUG_0_ANEG_END (3763L) +#define MAC_PCS_XXV_ANEG_DEBUG_0_ANEG_STARTED (3764L) +#define MAC_PCS_XXV_ANEG_DEBUG_0_CDR_HOLD (3765L) +#define MAC_PCS_XXV_ANEG_DEBUG_0_LT_END (3766L) +#define MAC_PCS_XXV_ANEG_DEBUG_0_LT_STARTED (3767L) +#define MAC_PCS_XXV_ANEG_DEBUG_1 (3768L) +#define MAC_PCS_XXV_ANEG_DEBUG_1_ANEG_END (3769L) +#define MAC_PCS_XXV_ANEG_DEBUG_1_ANEG_STARTED (3770L) +#define MAC_PCS_XXV_ANEG_DEBUG_1_CDR_HOLD (3771L) +#define MAC_PCS_XXV_ANEG_DEBUG_1_LT_END (3772L) +#define MAC_PCS_XXV_ANEG_DEBUG_1_LT_STARTED (3773L) +#define MAC_PCS_XXV_ANEG_DEBUG_2 (3774L) +#define MAC_PCS_XXV_ANEG_DEBUG_2_ANEG_END (3775L) +#define MAC_PCS_XXV_ANEG_DEBUG_2_ANEG_STARTED (3776L) +#define MAC_PCS_XXV_ANEG_DEBUG_2_CDR_HOLD (3777L) +#define MAC_PCS_XXV_ANEG_DEBUG_2_LT_END (3778L) +#define MAC_PCS_XXV_ANEG_DEBUG_2_LT_STARTED (3779L) +#define MAC_PCS_XXV_ANEG_DEBUG_3 (3780L) +#define MAC_PCS_XXV_ANEG_DEBUG_3_ANEG_END (3781L) +#define MAC_PCS_XXV_ANEG_DEBUG_3_ANEG_STARTED (3782L) +#define MAC_PCS_XXV_ANEG_DEBUG_3_CDR_HOLD (3783L) +#define MAC_PCS_XXV_ANEG_DEBUG_3_LT_END (3784L) +#define MAC_PCS_XXV_ANEG_DEBUG_3_LT_STARTED (3785L) +#define MAC_PCS_XXV_ANEG_LINK_STA_0 (3786L) +#define MAC_PCS_XXV_ANEG_LINK_STA_0_LINK_CR (3787L) +#define MAC_PCS_XXV_ANEG_LINK_STA_0_LINK_CR1 (3788L) +#define MAC_PCS_XXV_ANEG_LINK_STA_0_LINK_CR_S (3789L) +#define MAC_PCS_XXV_ANEG_LINK_STA_1 (3790L) +#define MAC_PCS_XXV_ANEG_LINK_STA_1_LINK_CR (3791L) +#define MAC_PCS_XXV_ANEG_LINK_STA_1_LINK_CR1 (3792L) +#define MAC_PCS_XXV_ANEG_LINK_STA_1_LINK_CR_S (3793L) +#define MAC_PCS_XXV_ANEG_LINK_STA_2 (3794L) +#define MAC_PCS_XXV_ANEG_LINK_STA_2_LINK_CR (3795L) +#define MAC_PCS_XXV_ANEG_LINK_STA_2_LINK_CR1 (3796L) +#define MAC_PCS_XXV_ANEG_LINK_STA_2_LINK_CR_S (3797L) +#define MAC_PCS_XXV_ANEG_LINK_STA_3 (3798L) +#define MAC_PCS_XXV_ANEG_LINK_STA_3_LINK_CR (3799L) +#define MAC_PCS_XXV_ANEG_LINK_STA_3_LINK_CR1 (3800L) +#define MAC_PCS_XXV_ANEG_LINK_STA_3_LINK_CR_S (3801L) +#define MAC_PCS_XXV_ANEG_LP_ABILITIES_0 (3802L) +#define MAC_PCS_XXV_ANEG_LP_ABILITIES_0_LP_25GBASE_CR (3803L) +#define MAC_PCS_XXV_ANEG_LP_ABILITIES_0_LP_25GBASE_CR_S (3804L) +#define MAC_PCS_XXV_ANEG_LP_ABILITIES_1 (3805L) +#define MAC_PCS_XXV_ANEG_LP_ABILITIES_1_LP_25GBASE_CR (3806L) +#define MAC_PCS_XXV_ANEG_LP_ABILITIES_1_LP_25GBASE_CR_S (3807L) +#define MAC_PCS_XXV_ANEG_LP_ABILITIES_2 (3808L) +#define MAC_PCS_XXV_ANEG_LP_ABILITIES_2_LP_25GBASE_CR (3809L) +#define MAC_PCS_XXV_ANEG_LP_ABILITIES_2_LP_25GBASE_CR_S (3810L) +#define MAC_PCS_XXV_ANEG_LP_ABILITIES_3 (3811L) +#define MAC_PCS_XXV_ANEG_LP_ABILITIES_3_LP_25GBASE_CR (3812L) +#define MAC_PCS_XXV_ANEG_LP_ABILITIES_3_LP_25GBASE_CR_S (3813L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0 (3814L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_C_FEC74_ABILITY (3815L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_C_FEC74_REQUEST (3816L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_C_FEC91_ABILITY (3817L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_C_FEC91_REQUEST (3818L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_LP_25GBASE_CR1 (3819L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_LP_EX_ABILITY_VALID (3820L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1 (3821L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_C_FEC74_ABILITY (3822L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_C_FEC74_REQUEST (3823L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_C_FEC91_ABILITY (3824L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_C_FEC91_REQUEST (3825L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_LP_25GBASE_CR1 (3826L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_LP_EX_ABILITY_VALID (3827L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2 (3828L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_C_FEC74_ABILITY (3829L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_C_FEC74_REQUEST (3830L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_C_FEC91_ABILITY (3831L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_C_FEC91_REQUEST (3832L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_LP_25GBASE_CR1 (3833L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_LP_EX_ABILITY_VALID (3834L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3 (3835L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_C_FEC74_ABILITY (3836L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_C_FEC74_REQUEST (3837L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_C_FEC91_ABILITY (3838L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_C_FEC91_REQUEST (3839L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_LP_25GBASE_CR1 (3840L) +#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_LP_EX_ABILITY_VALID (3841L) +#define MAC_PCS_XXV_ANEG_LP_STA_0 (3842L) +#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_ABILITY_VALID (3843L) +#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_ANEG_ABLE (3844L) +#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_ASM (3845L) +#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_FEC74_REQ (3846L) +#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_PAUSE (3847L) +#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_RF (3848L) +#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_RS_FEC_REQ (3849L) +#define MAC_PCS_XXV_ANEG_LP_STA_1 (3850L) +#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_ABILITY_VALID (3851L) +#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_ANEG_ABLE (3852L) +#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_ASM (3853L) +#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_FEC74_REQ (3854L) +#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_PAUSE (3855L) +#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_RF (3856L) +#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_RS_FEC_REQ (3857L) +#define MAC_PCS_XXV_ANEG_LP_STA_2 (3858L) +#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_ABILITY_VALID (3859L) +#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_ANEG_ABLE (3860L) +#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_ASM (3861L) +#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_FEC74_REQ (3862L) +#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_PAUSE (3863L) +#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_RF (3864L) +#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_RS_FEC_REQ (3865L) +#define MAC_PCS_XXV_ANEG_LP_STA_3 (3866L) +#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_ABILITY_VALID (3867L) +#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_ANEG_ABLE (3868L) +#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_ASM (3869L) +#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_FEC74_REQ (3870L) +#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_PAUSE (3871L) +#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_RF (3872L) +#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_RS_FEC_REQ (3873L) +#define MAC_PCS_XXV_ANEG_STA_0 (3874L) +#define MAC_PCS_XXV_ANEG_STA_0_COMPLETE (3875L) +#define MAC_PCS_XXV_ANEG_STA_0_FEC74_EN (3876L) +#define MAC_PCS_XXV_ANEG_STA_0_PAR_D_FAULT (3877L) +#define MAC_PCS_XXV_ANEG_STA_0_RS_FEC_EN (3878L) +#define MAC_PCS_XXV_ANEG_STA_0_RX_PAUSE_EN (3879L) +#define MAC_PCS_XXV_ANEG_STA_0_TX_PAUSE_EN (3880L) +#define MAC_PCS_XXV_ANEG_STA_1 (3881L) +#define MAC_PCS_XXV_ANEG_STA_1_COMPLETE (3882L) +#define MAC_PCS_XXV_ANEG_STA_1_FEC74_EN (3883L) +#define MAC_PCS_XXV_ANEG_STA_1_PAR_D_FAULT (3884L) +#define MAC_PCS_XXV_ANEG_STA_1_RS_FEC_EN (3885L) +#define MAC_PCS_XXV_ANEG_STA_1_RX_PAUSE_EN (3886L) +#define MAC_PCS_XXV_ANEG_STA_1_TX_PAUSE_EN (3887L) +#define MAC_PCS_XXV_ANEG_STA_2 (3888L) +#define MAC_PCS_XXV_ANEG_STA_2_COMPLETE (3889L) +#define MAC_PCS_XXV_ANEG_STA_2_FEC74_EN (3890L) +#define MAC_PCS_XXV_ANEG_STA_2_PAR_D_FAULT (3891L) +#define MAC_PCS_XXV_ANEG_STA_2_RS_FEC_EN (3892L) +#define MAC_PCS_XXV_ANEG_STA_2_RX_PAUSE_EN (3893L) +#define MAC_PCS_XXV_ANEG_STA_2_TX_PAUSE_EN (3894L) +#define MAC_PCS_XXV_ANEG_STA_3 (3895L) +#define MAC_PCS_XXV_ANEG_STA_3_COMPLETE (3896L) +#define MAC_PCS_XXV_ANEG_STA_3_FEC74_EN (3897L) +#define MAC_PCS_XXV_ANEG_STA_3_PAR_D_FAULT (3898L) +#define MAC_PCS_XXV_ANEG_STA_3_RS_FEC_EN (3899L) +#define MAC_PCS_XXV_ANEG_STA_3_RX_PAUSE_EN (3900L) +#define MAC_PCS_XXV_ANEG_STA_3_TX_PAUSE_EN (3901L) +#define MAC_PCS_XXV_CLK_REF_ACTIVITY (3902L) +#define MAC_PCS_XXV_CLK_REF_ACTIVITY_COUNT (3903L) +#define MAC_PCS_XXV_CORE_CONF_0 (3904L) +#define MAC_PCS_XXV_CORE_CONF_0_ENHANCED_TS (3905L) +#define MAC_PCS_XXV_CORE_CONF_0_INLINE_MODE (3906L) +#define MAC_PCS_XXV_CORE_CONF_0_LINE_LOOPBACK (3907L) +#define MAC_PCS_XXV_CORE_CONF_0_RX_ENABLE (3908L) +#define MAC_PCS_XXV_CORE_CONF_0_RX_FORCE_RESYNC (3909L) +#define MAC_PCS_XXV_CORE_CONF_0_TS_AT_EOP (3910L) +#define MAC_PCS_XXV_CORE_CONF_0_TX_ENABLE (3911L) +#define MAC_PCS_XXV_CORE_CONF_0_TX_IGN_FCS (3912L) +#define MAC_PCS_XXV_CORE_CONF_0_TX_INS_FCS (3913L) +#define MAC_PCS_XXV_CORE_CONF_0_TX_SEND_IDLE (3914L) +#define MAC_PCS_XXV_CORE_CONF_0_TX_SEND_LFI (3915L) +#define MAC_PCS_XXV_CORE_CONF_0_TX_SEND_RFI (3916L) +#define MAC_PCS_XXV_CORE_CONF_1 (3917L) +#define MAC_PCS_XXV_CORE_CONF_1_ENHANCED_TS (3918L) +#define MAC_PCS_XXV_CORE_CONF_1_INLINE_MODE (3919L) +#define MAC_PCS_XXV_CORE_CONF_1_LINE_LOOPBACK (3920L) +#define MAC_PCS_XXV_CORE_CONF_1_RX_ENABLE (3921L) +#define MAC_PCS_XXV_CORE_CONF_1_RX_FORCE_RESYNC (3922L) +#define MAC_PCS_XXV_CORE_CONF_1_TS_AT_EOP (3923L) +#define MAC_PCS_XXV_CORE_CONF_1_TX_ENABLE (3924L) +#define MAC_PCS_XXV_CORE_CONF_1_TX_IGN_FCS (3925L) +#define MAC_PCS_XXV_CORE_CONF_1_TX_INS_FCS (3926L) +#define MAC_PCS_XXV_CORE_CONF_1_TX_SEND_IDLE (3927L) +#define MAC_PCS_XXV_CORE_CONF_1_TX_SEND_LFI (3928L) +#define MAC_PCS_XXV_CORE_CONF_1_TX_SEND_RFI (3929L) +#define MAC_PCS_XXV_CORE_CONF_2 (3930L) +#define MAC_PCS_XXV_CORE_CONF_2_ENHANCED_TS (3931L) +#define MAC_PCS_XXV_CORE_CONF_2_INLINE_MODE (3932L) +#define MAC_PCS_XXV_CORE_CONF_2_LINE_LOOPBACK (3933L) +#define MAC_PCS_XXV_CORE_CONF_2_RX_ENABLE (3934L) +#define MAC_PCS_XXV_CORE_CONF_2_RX_FORCE_RESYNC (3935L) +#define MAC_PCS_XXV_CORE_CONF_2_TS_AT_EOP (3936L) +#define MAC_PCS_XXV_CORE_CONF_2_TX_ENABLE (3937L) +#define MAC_PCS_XXV_CORE_CONF_2_TX_IGN_FCS (3938L) +#define MAC_PCS_XXV_CORE_CONF_2_TX_INS_FCS (3939L) +#define MAC_PCS_XXV_CORE_CONF_2_TX_SEND_IDLE (3940L) +#define MAC_PCS_XXV_CORE_CONF_2_TX_SEND_LFI (3941L) +#define MAC_PCS_XXV_CORE_CONF_2_TX_SEND_RFI (3942L) +#define MAC_PCS_XXV_CORE_CONF_3 (3943L) +#define MAC_PCS_XXV_CORE_CONF_3_ENHANCED_TS (3944L) +#define MAC_PCS_XXV_CORE_CONF_3_INLINE_MODE (3945L) +#define MAC_PCS_XXV_CORE_CONF_3_LINE_LOOPBACK (3946L) +#define MAC_PCS_XXV_CORE_CONF_3_RX_ENABLE (3947L) +#define MAC_PCS_XXV_CORE_CONF_3_RX_FORCE_RESYNC (3948L) +#define MAC_PCS_XXV_CORE_CONF_3_TS_AT_EOP (3949L) +#define MAC_PCS_XXV_CORE_CONF_3_TX_ENABLE (3950L) +#define MAC_PCS_XXV_CORE_CONF_3_TX_IGN_FCS (3951L) +#define MAC_PCS_XXV_CORE_CONF_3_TX_INS_FCS (3952L) +#define MAC_PCS_XXV_CORE_CONF_3_TX_SEND_IDLE (3953L) +#define MAC_PCS_XXV_CORE_CONF_3_TX_SEND_LFI (3954L) +#define MAC_PCS_XXV_CORE_CONF_3_TX_SEND_RFI (3955L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_0 (3956L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_DEBOUNCE_LATENCY (3957L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_FORCE_LINK_DOWN (3958L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_LINKUP_LATENCY (3959L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_PORT_CTRL (3960L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_1 (3961L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_DEBOUNCE_LATENCY (3962L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_FORCE_LINK_DOWN (3963L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_LINKUP_LATENCY (3964L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_PORT_CTRL (3965L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_2 (3966L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_DEBOUNCE_LATENCY (3967L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_FORCE_LINK_DOWN (3968L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_LINKUP_LATENCY (3969L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_PORT_CTRL (3970L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_3 (3971L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_DEBOUNCE_LATENCY (3972L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_FORCE_LINK_DOWN (3973L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_LINKUP_LATENCY (3974L) +#define MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_PORT_CTRL (3975L) +#define MAC_PCS_XXV_FEC74_CCW_CNT_0 (3976L) +#define MAC_PCS_XXV_FEC74_CCW_CNT_0_FEC74_CCW_CNT (3977L) +#define MAC_PCS_XXV_FEC74_CCW_CNT_1 (3978L) +#define MAC_PCS_XXV_FEC74_CCW_CNT_1_FEC74_CCW_CNT (3979L) +#define MAC_PCS_XXV_FEC74_CCW_CNT_2 (3980L) +#define MAC_PCS_XXV_FEC74_CCW_CNT_2_FEC74_CCW_CNT (3981L) +#define MAC_PCS_XXV_FEC74_CCW_CNT_3 (3982L) +#define MAC_PCS_XXV_FEC74_CCW_CNT_3_FEC74_CCW_CNT (3983L) +#define MAC_PCS_XXV_FEC74_CONFIG_0 (3984L) +#define MAC_PCS_XXV_FEC74_CONFIG_0_FEC74_ERRORS_TO_PCS (3985L) +#define MAC_PCS_XXV_FEC74_CONFIG_0_RX_FEC74_ENABLE (3986L) +#define MAC_PCS_XXV_FEC74_CONFIG_0_TX_FEC74_ENABLE (3987L) +#define MAC_PCS_XXV_FEC74_CONFIG_1 (3988L) +#define MAC_PCS_XXV_FEC74_CONFIG_1_FEC74_ERRORS_TO_PCS (3989L) +#define MAC_PCS_XXV_FEC74_CONFIG_1_RX_FEC74_ENABLE (3990L) +#define MAC_PCS_XXV_FEC74_CONFIG_1_TX_FEC74_ENABLE (3991L) +#define MAC_PCS_XXV_FEC74_CONFIG_2 (3992L) +#define MAC_PCS_XXV_FEC74_CONFIG_2_FEC74_ERRORS_TO_PCS (3993L) +#define MAC_PCS_XXV_FEC74_CONFIG_2_RX_FEC74_ENABLE (3994L) +#define MAC_PCS_XXV_FEC74_CONFIG_2_TX_FEC74_ENABLE (3995L) +#define MAC_PCS_XXV_FEC74_CONFIG_3 (3996L) +#define MAC_PCS_XXV_FEC74_CONFIG_3_FEC74_ERRORS_TO_PCS (3997L) +#define MAC_PCS_XXV_FEC74_CONFIG_3_RX_FEC74_ENABLE (3998L) +#define MAC_PCS_XXV_FEC74_CONFIG_3_TX_FEC74_ENABLE (3999L) +#define MAC_PCS_XXV_FEC74_UCW_CNT_0 (4000L) +#define MAC_PCS_XXV_FEC74_UCW_CNT_0_FEC74_UCW_CNT (4001L) +#define MAC_PCS_XXV_FEC74_UCW_CNT_1 (4002L) +#define MAC_PCS_XXV_FEC74_UCW_CNT_1_FEC74_UCW_CNT (4003L) +#define MAC_PCS_XXV_FEC74_UCW_CNT_2 (4004L) +#define MAC_PCS_XXV_FEC74_UCW_CNT_2_FEC74_UCW_CNT (4005L) +#define MAC_PCS_XXV_FEC74_UCW_CNT_3 (4006L) +#define MAC_PCS_XXV_FEC74_UCW_CNT_3_FEC74_UCW_CNT (4007L) +#define MAC_PCS_XXV_GTY_CTL_RX_0 (4008L) +#define MAC_PCS_XXV_GTY_CTL_RX_0_CDR_HOLD (4009L) +#define MAC_PCS_XXV_GTY_CTL_RX_0_EQUA_RST (4010L) +#define MAC_PCS_XXV_GTY_CTL_RX_0_LPM_EN (4011L) +#define MAC_PCS_XXV_GTY_CTL_RX_0_POLARITY (4012L) +#define MAC_PCS_XXV_GTY_CTL_RX_0_RATE (4013L) +#define MAC_PCS_XXV_GTY_CTL_RX_1 (4014L) +#define MAC_PCS_XXV_GTY_CTL_RX_1_CDR_HOLD (4015L) +#define MAC_PCS_XXV_GTY_CTL_RX_1_EQUA_RST (4016L) +#define MAC_PCS_XXV_GTY_CTL_RX_1_LPM_EN (4017L) +#define MAC_PCS_XXV_GTY_CTL_RX_1_POLARITY (4018L) +#define MAC_PCS_XXV_GTY_CTL_RX_1_RATE (4019L) +#define MAC_PCS_XXV_GTY_CTL_RX_2 (4020L) +#define MAC_PCS_XXV_GTY_CTL_RX_2_CDR_HOLD (4021L) +#define MAC_PCS_XXV_GTY_CTL_RX_2_EQUA_RST (4022L) +#define MAC_PCS_XXV_GTY_CTL_RX_2_LPM_EN (4023L) +#define MAC_PCS_XXV_GTY_CTL_RX_2_POLARITY (4024L) +#define MAC_PCS_XXV_GTY_CTL_RX_2_RATE (4025L) +#define MAC_PCS_XXV_GTY_CTL_RX_3 (4026L) +#define MAC_PCS_XXV_GTY_CTL_RX_3_CDR_HOLD (4027L) +#define MAC_PCS_XXV_GTY_CTL_RX_3_EQUA_RST (4028L) +#define MAC_PCS_XXV_GTY_CTL_RX_3_LPM_EN (4029L) +#define MAC_PCS_XXV_GTY_CTL_RX_3_POLARITY (4030L) +#define MAC_PCS_XXV_GTY_CTL_RX_3_RATE (4031L) +#define MAC_PCS_XXV_GTY_CTL_TX_0 (4032L) +#define MAC_PCS_XXV_GTY_CTL_TX_0_INHIBIT (4033L) +#define MAC_PCS_XXV_GTY_CTL_TX_0_POLARITY (4034L) +#define MAC_PCS_XXV_GTY_CTL_TX_1 (4035L) +#define MAC_PCS_XXV_GTY_CTL_TX_1_INHIBIT (4036L) +#define MAC_PCS_XXV_GTY_CTL_TX_1_POLARITY (4037L) +#define MAC_PCS_XXV_GTY_CTL_TX_2 (4038L) +#define MAC_PCS_XXV_GTY_CTL_TX_2_INHIBIT (4039L) +#define MAC_PCS_XXV_GTY_CTL_TX_2_POLARITY (4040L) +#define MAC_PCS_XXV_GTY_CTL_TX_3 (4041L) +#define MAC_PCS_XXV_GTY_CTL_TX_3_INHIBIT (4042L) +#define MAC_PCS_XXV_GTY_CTL_TX_3_POLARITY (4043L) +#define MAC_PCS_XXV_GTY_DIFF_CTL_0 (4044L) +#define MAC_PCS_XXV_GTY_DIFF_CTL_0_TX_DIFF_CTL (4045L) +#define MAC_PCS_XXV_GTY_DIFF_CTL_0_TX_DIFF_CTL_ADJUSTED (4046L) +#define MAC_PCS_XXV_GTY_DIFF_CTL_1 (4047L) +#define MAC_PCS_XXV_GTY_DIFF_CTL_1_TX_DIFF_CTL (4048L) +#define MAC_PCS_XXV_GTY_DIFF_CTL_1_TX_DIFF_CTL_ADJUSTED (4049L) +#define MAC_PCS_XXV_GTY_DIFF_CTL_2 (4050L) +#define MAC_PCS_XXV_GTY_DIFF_CTL_2_TX_DIFF_CTL (4051L) +#define MAC_PCS_XXV_GTY_DIFF_CTL_2_TX_DIFF_CTL_ADJUSTED (4052L) +#define MAC_PCS_XXV_GTY_DIFF_CTL_3 (4053L) +#define MAC_PCS_XXV_GTY_DIFF_CTL_3_TX_DIFF_CTL (4054L) +#define MAC_PCS_XXV_GTY_DIFF_CTL_3_TX_DIFF_CTL_ADJUSTED (4055L) +#define MAC_PCS_XXV_GTY_LOOP_0 (4056L) +#define MAC_PCS_XXV_GTY_LOOP_0_GT_LOOP (4057L) +#define MAC_PCS_XXV_GTY_LOOP_1 (4058L) +#define MAC_PCS_XXV_GTY_LOOP_1_GT_LOOP (4059L) +#define MAC_PCS_XXV_GTY_LOOP_2 (4060L) +#define MAC_PCS_XXV_GTY_LOOP_2_GT_LOOP (4061L) +#define MAC_PCS_XXV_GTY_LOOP_3 (4062L) +#define MAC_PCS_XXV_GTY_LOOP_3_GT_LOOP (4063L) +#define MAC_PCS_XXV_GTY_MAIN_CTL_0 (4064L) +#define MAC_PCS_XXV_GTY_MAIN_CTL_0_TX_MAIN_CTL (4065L) +#define MAC_PCS_XXV_GTY_MAIN_CTL_1 (4066L) +#define MAC_PCS_XXV_GTY_MAIN_CTL_1_TX_MAIN_CTL (4067L) +#define MAC_PCS_XXV_GTY_MAIN_CTL_2 (4068L) +#define MAC_PCS_XXV_GTY_MAIN_CTL_2_TX_MAIN_CTL (4069L) +#define MAC_PCS_XXV_GTY_MAIN_CTL_3 (4070L) +#define MAC_PCS_XXV_GTY_MAIN_CTL_3_TX_MAIN_CTL (4071L) +#define MAC_PCS_XXV_GTY_POST_CURSOR_0 (4072L) +#define MAC_PCS_XXV_GTY_POST_CURSOR_0_TX_POST_CSR (4073L) +#define MAC_PCS_XXV_GTY_POST_CURSOR_0_TX_POST_CSR_ADJUSTED (4074L) +#define MAC_PCS_XXV_GTY_POST_CURSOR_1 (4075L) +#define MAC_PCS_XXV_GTY_POST_CURSOR_1_TX_POST_CSR (4076L) +#define MAC_PCS_XXV_GTY_POST_CURSOR_1_TX_POST_CSR_ADJUSTED (4077L) +#define MAC_PCS_XXV_GTY_POST_CURSOR_2 (4078L) +#define MAC_PCS_XXV_GTY_POST_CURSOR_2_TX_POST_CSR (4079L) +#define MAC_PCS_XXV_GTY_POST_CURSOR_2_TX_POST_CSR_ADJUSTED (4080L) +#define MAC_PCS_XXV_GTY_POST_CURSOR_3 (4081L) +#define MAC_PCS_XXV_GTY_POST_CURSOR_3_TX_POST_CSR (4082L) +#define MAC_PCS_XXV_GTY_POST_CURSOR_3_TX_POST_CSR_ADJUSTED (4083L) +#define MAC_PCS_XXV_GTY_PRBS_0 (4084L) +#define MAC_PCS_XXV_GTY_PRBS_0_PRBS_ERR (4085L) +#define MAC_PCS_XXV_GTY_PRBS_0_PRBS_ERR_INS (4086L) +#define MAC_PCS_XXV_GTY_PRBS_0_PRBS_RST (4087L) +#define MAC_PCS_XXV_GTY_PRBS_0_RX_PRBS_SEL (4088L) +#define MAC_PCS_XXV_GTY_PRBS_0_TX_PRBS_SEL (4089L) +#define MAC_PCS_XXV_GTY_PRBS_1 (4090L) +#define MAC_PCS_XXV_GTY_PRBS_1_PRBS_ERR (4091L) +#define MAC_PCS_XXV_GTY_PRBS_1_PRBS_ERR_INS (4092L) +#define MAC_PCS_XXV_GTY_PRBS_1_PRBS_RST (4093L) +#define MAC_PCS_XXV_GTY_PRBS_1_RX_PRBS_SEL (4094L) +#define MAC_PCS_XXV_GTY_PRBS_1_TX_PRBS_SEL (4095L) +#define MAC_PCS_XXV_GTY_PRBS_2 (4096L) +#define MAC_PCS_XXV_GTY_PRBS_2_PRBS_ERR (4097L) +#define MAC_PCS_XXV_GTY_PRBS_2_PRBS_ERR_INS (4098L) +#define MAC_PCS_XXV_GTY_PRBS_2_PRBS_RST (4099L) +#define MAC_PCS_XXV_GTY_PRBS_2_RX_PRBS_SEL (4100L) +#define MAC_PCS_XXV_GTY_PRBS_2_TX_PRBS_SEL (4101L) +#define MAC_PCS_XXV_GTY_PRBS_3 (4102L) +#define MAC_PCS_XXV_GTY_PRBS_3_PRBS_ERR (4103L) +#define MAC_PCS_XXV_GTY_PRBS_3_PRBS_ERR_INS (4104L) +#define MAC_PCS_XXV_GTY_PRBS_3_PRBS_RST (4105L) +#define MAC_PCS_XXV_GTY_PRBS_3_RX_PRBS_SEL (4106L) +#define MAC_PCS_XXV_GTY_PRBS_3_TX_PRBS_SEL (4107L) +#define MAC_PCS_XXV_GTY_PRBS_CNT_0 (4108L) +#define MAC_PCS_XXV_GTY_PRBS_CNT_0_COUNT (4109L) +#define MAC_PCS_XXV_GTY_PRBS_CNT_1 (4110L) +#define MAC_PCS_XXV_GTY_PRBS_CNT_1_COUNT (4111L) +#define MAC_PCS_XXV_GTY_PRBS_CNT_2 (4112L) +#define MAC_PCS_XXV_GTY_PRBS_CNT_2_COUNT (4113L) +#define MAC_PCS_XXV_GTY_PRBS_CNT_3 (4114L) +#define MAC_PCS_XXV_GTY_PRBS_CNT_3_COUNT (4115L) +#define MAC_PCS_XXV_GTY_PRE_CURSOR_0 (4116L) +#define MAC_PCS_XXV_GTY_PRE_CURSOR_0_TX_PRE_CSR (4117L) +#define MAC_PCS_XXV_GTY_PRE_CURSOR_0_TX_PRE_CSR_ADJUSTED (4118L) +#define MAC_PCS_XXV_GTY_PRE_CURSOR_1 (4119L) +#define MAC_PCS_XXV_GTY_PRE_CURSOR_1_TX_PRE_CSR (4120L) +#define MAC_PCS_XXV_GTY_PRE_CURSOR_1_TX_PRE_CSR_ADJUSTED (4121L) +#define MAC_PCS_XXV_GTY_PRE_CURSOR_2 (4122L) +#define MAC_PCS_XXV_GTY_PRE_CURSOR_2_TX_PRE_CSR (4123L) +#define MAC_PCS_XXV_GTY_PRE_CURSOR_2_TX_PRE_CSR_ADJUSTED (4124L) +#define MAC_PCS_XXV_GTY_PRE_CURSOR_3 (4125L) +#define MAC_PCS_XXV_GTY_PRE_CURSOR_3_TX_PRE_CSR (4126L) +#define MAC_PCS_XXV_GTY_PRE_CURSOR_3_TX_PRE_CSR_ADJUSTED (4127L) +#define MAC_PCS_XXV_GTY_STATUS_0 (4128L) +#define MAC_PCS_XXV_GTY_STATUS_0_GT_POWERGOOD (4129L) +#define MAC_PCS_XXV_GTY_STATUS_0_GT_RXBUFSTATUS (4130L) +#define MAC_PCS_XXV_GTY_STATUS_0_GT_STARTOFSEQ (4131L) +#define MAC_PCS_XXV_GTY_STATUS_0_GT_TXBUFSTATUS (4132L) +#define MAC_PCS_XXV_GTY_STATUS_1 (4133L) +#define MAC_PCS_XXV_GTY_STATUS_1_GT_POWERGOOD (4134L) +#define MAC_PCS_XXV_GTY_STATUS_1_GT_RXBUFSTATUS (4135L) +#define MAC_PCS_XXV_GTY_STATUS_1_GT_STARTOFSEQ (4136L) +#define MAC_PCS_XXV_GTY_STATUS_1_GT_TXBUFSTATUS (4137L) +#define MAC_PCS_XXV_GTY_STATUS_2 (4138L) +#define MAC_PCS_XXV_GTY_STATUS_2_GT_POWERGOOD (4139L) +#define MAC_PCS_XXV_GTY_STATUS_2_GT_RXBUFSTATUS (4140L) +#define MAC_PCS_XXV_GTY_STATUS_2_GT_STARTOFSEQ (4141L) +#define MAC_PCS_XXV_GTY_STATUS_2_GT_TXBUFSTATUS (4142L) +#define MAC_PCS_XXV_GTY_STATUS_3 (4143L) +#define MAC_PCS_XXV_GTY_STATUS_3_GT_POWERGOOD (4144L) +#define MAC_PCS_XXV_GTY_STATUS_3_GT_RXBUFSTATUS (4145L) +#define MAC_PCS_XXV_GTY_STATUS_3_GT_STARTOFSEQ (4146L) +#define MAC_PCS_XXV_GTY_STATUS_3_GT_TXBUFSTATUS (4147L) +#define MAC_PCS_XXV_LATENCY_0 (4148L) +#define MAC_PCS_XXV_LATENCY_0_RX_LATENCY_MEAS (4149L) +#define MAC_PCS_XXV_LATENCY_1 (4150L) +#define MAC_PCS_XXV_LATENCY_1_RX_LATENCY_MEAS (4151L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0 (4152L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_DEC_MAIN (4153L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_DEC_POST (4154L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_DEC_PRE (4155L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_INC_MAIN (4156L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_INC_POST (4157L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_INC_PRE (4158L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_INIT (4159L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_PRESET (4160L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1 (4161L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_DEC_MAIN (4162L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_DEC_POST (4163L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_DEC_PRE (4164L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_INC_MAIN (4165L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_INC_POST (4166L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_INC_PRE (4167L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_INIT (4168L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_PRESET (4169L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2 (4170L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_DEC_MAIN (4171L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_DEC_POST (4172L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_DEC_PRE (4173L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_INC_MAIN (4174L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_INC_POST (4175L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_INC_PRE (4176L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_INIT (4177L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_PRESET (4178L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3 (4179L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_DEC_MAIN (4180L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_DEC_POST (4181L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_DEC_PRE (4182L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_INC_MAIN (4183L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_INC_POST (4184L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_INC_PRE (4185L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_INIT (4186L) +#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_PRESET (4187L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_0 (4188L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_0_MAIN_STA (4189L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_0_POST_STA (4190L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_0_PRE_STA (4191L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_1 (4192L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_1_MAIN_STA (4193L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_1_POST_STA (4194L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_1_PRE_STA (4195L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_2 (4196L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_2_MAIN_STA (4197L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_2_POST_STA (4198L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_2_PRE_STA (4199L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_3 (4200L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_3_MAIN_STA (4201L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_3_POST_STA (4202L) +#define MAC_PCS_XXV_LE_LT_STA_SEND_3_PRE_STA (4203L) +#define MAC_PCS_XXV_LINK_SPEED_0 (4204L) +#define MAC_PCS_XXV_LINK_SPEED_0_10G (4205L) +#define MAC_PCS_XXV_LINK_SPEED_0_SPEED (4206L) +#define MAC_PCS_XXV_LINK_SPEED_0_TOGGLE (4207L) +#define MAC_PCS_XXV_LINK_SPEED_1 (4208L) +#define MAC_PCS_XXV_LINK_SPEED_1_10G (4209L) +#define MAC_PCS_XXV_LINK_SPEED_1_SPEED (4210L) +#define MAC_PCS_XXV_LINK_SPEED_1_TOGGLE (4211L) +#define MAC_PCS_XXV_LINK_SPEED_2 (4212L) +#define MAC_PCS_XXV_LINK_SPEED_2_10G (4213L) +#define MAC_PCS_XXV_LINK_SPEED_2_SPEED (4214L) +#define MAC_PCS_XXV_LINK_SPEED_2_TOGGLE (4215L) +#define MAC_PCS_XXV_LINK_SPEED_3 (4216L) +#define MAC_PCS_XXV_LINK_SPEED_3_10G (4217L) +#define MAC_PCS_XXV_LINK_SPEED_3_SPEED (4218L) +#define MAC_PCS_XXV_LINK_SPEED_3_TOGGLE (4219L) +#define MAC_PCS_XXV_LINK_SUMMARY_0 (4220L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_ABS (4221L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_ANEG_COMPLETE (4222L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_ANEG_CONSORTIUM_MISMATCH (4223L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_INTERNAL_LOCAL_FAULT (4224L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_ABS (4225L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_INTERNAL_LOCAL_FAULT (4226L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_LOCAL_FAULT (4227L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RECEIVED_LOCAL_FAULT (4228L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_REMOTE_FAULT (4229L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_FEC74_LOCK_ERROR (4230L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_HIGH_BIT_ERROR_RATE (4231L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_PCS_VALID_CTRL_CODE (4232L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_RSFEC_HI_SER (4233L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_TX_LOCAL_FAULT (4234L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_TX_UNDERRUN (4235L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LINK_DOWN_CNT (4236L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_PHY_LINK_STATE (4237L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_BLOCK_LOCK (4238L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_FEC74_LOCK (4239L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_RSFEC_LANE_ALIGNMENT (4240L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_TX_RSFEC_LANE_ALIGNMENT (4241L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_LT_DONE (4242L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_NIM_INTERR (4243L) +#define MAC_PCS_XXV_LINK_SUMMARY_0_NT_PHY_LINK_STATE (4244L) +#define MAC_PCS_XXV_LINK_SUMMARY_1 (4245L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_ABS (4246L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_ANEG_COMPLETE (4247L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_ANEG_CONSORTIUM_MISMATCH (4248L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_INTERNAL_LOCAL_FAULT (4249L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_ABS (4250L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_INTERNAL_LOCAL_FAULT (4251L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_LOCAL_FAULT (4252L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RECEIVED_LOCAL_FAULT (4253L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_REMOTE_FAULT (4254L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_FEC74_LOCK_ERROR (4255L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_HIGH_BIT_ERROR_RATE (4256L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_PCS_VALID_CTRL_CODE (4257L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_RSFEC_HI_SER (4258L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_TX_LOCAL_FAULT (4259L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_TX_UNDERRUN (4260L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LINK_DOWN_CNT (4261L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_PHY_LINK_STATE (4262L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_BLOCK_LOCK (4263L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_FEC74_LOCK (4264L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_RSFEC_LANE_ALIGNMENT (4265L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_TX_RSFEC_LANE_ALIGNMENT (4266L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_LT_DONE (4267L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_NIM_INTERR (4268L) +#define MAC_PCS_XXV_LINK_SUMMARY_1_NT_PHY_LINK_STATE (4269L) +#define MAC_PCS_XXV_LINK_SUMMARY_2 (4270L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_ABS (4271L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_ANEG_COMPLETE (4272L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_ANEG_CONSORTIUM_MISMATCH (4273L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_INTERNAL_LOCAL_FAULT (4274L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_ABS (4275L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_INTERNAL_LOCAL_FAULT (4276L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_LOCAL_FAULT (4277L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RECEIVED_LOCAL_FAULT (4278L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_REMOTE_FAULT (4279L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_FEC74_LOCK_ERROR (4280L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_HIGH_BIT_ERROR_RATE (4281L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_PCS_VALID_CTRL_CODE (4282L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_RSFEC_HI_SER (4283L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_TX_LOCAL_FAULT (4284L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_TX_UNDERRUN (4285L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LINK_DOWN_CNT (4286L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_PHY_LINK_STATE (4287L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_BLOCK_LOCK (4288L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_FEC74_LOCK (4289L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_RSFEC_LANE_ALIGNMENT (4290L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_TX_RSFEC_LANE_ALIGNMENT (4291L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_LT_DONE (4292L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_NIM_INTERR (4293L) +#define MAC_PCS_XXV_LINK_SUMMARY_2_NT_PHY_LINK_STATE (4294L) +#define MAC_PCS_XXV_LINK_SUMMARY_3 (4295L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_ABS (4296L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_ANEG_COMPLETE (4297L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_ANEG_CONSORTIUM_MISMATCH (4298L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_INTERNAL_LOCAL_FAULT (4299L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_ABS (4300L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_INTERNAL_LOCAL_FAULT (4301L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_LOCAL_FAULT (4302L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RECEIVED_LOCAL_FAULT (4303L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_REMOTE_FAULT (4304L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_FEC74_LOCK_ERROR (4305L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_HIGH_BIT_ERROR_RATE (4306L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_PCS_VALID_CTRL_CODE (4307L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_RSFEC_HI_SER (4308L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_TX_LOCAL_FAULT (4309L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_TX_UNDERRUN (4310L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LINK_DOWN_CNT (4311L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_PHY_LINK_STATE (4312L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_BLOCK_LOCK (4313L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_FEC74_LOCK (4314L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_RSFEC_LANE_ALIGNMENT (4315L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_TX_RSFEC_LANE_ALIGNMENT (4316L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_LT_DONE (4317L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_NIM_INTERR (4318L) +#define MAC_PCS_XXV_LINK_SUMMARY_3_NT_PHY_LINK_STATE (4319L) +#define MAC_PCS_XXV_LT_CONF_0 (4320L) +#define MAC_PCS_XXV_LT_CONF_0_ENABLE (4321L) +#define MAC_PCS_XXV_LT_CONF_0_RESTART (4322L) +#define MAC_PCS_XXV_LT_CONF_0_SEED (4323L) +#define MAC_PCS_XXV_LT_CONF_1 (4324L) +#define MAC_PCS_XXV_LT_CONF_1_ENABLE (4325L) +#define MAC_PCS_XXV_LT_CONF_1_RESTART (4326L) +#define MAC_PCS_XXV_LT_CONF_1_SEED (4327L) +#define MAC_PCS_XXV_LT_CONF_2 (4328L) +#define MAC_PCS_XXV_LT_CONF_2_ENABLE (4329L) +#define MAC_PCS_XXV_LT_CONF_2_RESTART (4330L) +#define MAC_PCS_XXV_LT_CONF_2_SEED (4331L) +#define MAC_PCS_XXV_LT_CONF_3 (4332L) +#define MAC_PCS_XXV_LT_CONF_3_ENABLE (4333L) +#define MAC_PCS_XXV_LT_CONF_3_RESTART (4334L) +#define MAC_PCS_XXV_LT_CONF_3_SEED (4335L) +#define MAC_PCS_XXV_LT_STA_0 (4336L) +#define MAC_PCS_XXV_LT_STA_0_DONE (4337L) +#define MAC_PCS_XXV_LT_STA_0_FAIL (4338L) +#define MAC_PCS_XXV_LT_STA_0_LOCK (4339L) +#define MAC_PCS_XXV_LT_STA_0_TRAIN (4340L) +#define MAC_PCS_XXV_LT_STA_1 (4341L) +#define MAC_PCS_XXV_LT_STA_1_DONE (4342L) +#define MAC_PCS_XXV_LT_STA_1_FAIL (4343L) +#define MAC_PCS_XXV_LT_STA_1_LOCK (4344L) +#define MAC_PCS_XXV_LT_STA_1_TRAIN (4345L) +#define MAC_PCS_XXV_LT_STA_2 (4346L) +#define MAC_PCS_XXV_LT_STA_2_DONE (4347L) +#define MAC_PCS_XXV_LT_STA_2_FAIL (4348L) +#define MAC_PCS_XXV_LT_STA_2_LOCK (4349L) +#define MAC_PCS_XXV_LT_STA_2_TRAIN (4350L) +#define MAC_PCS_XXV_LT_STA_3 (4351L) +#define MAC_PCS_XXV_LT_STA_3_DONE (4352L) +#define MAC_PCS_XXV_LT_STA_3_FAIL (4353L) +#define MAC_PCS_XXV_LT_STA_3_LOCK (4354L) +#define MAC_PCS_XXV_LT_STA_3_TRAIN (4355L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_0 (4356L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_0_ATTRIB (4357L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_0_NEXT (4358L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_0_PREV (4359L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_1 (4360L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_1_ATTRIB (4361L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_1_NEXT (4362L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_1_PREV (4363L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_2 (4364L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_2_ATTRIB (4365L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_2_NEXT (4366L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_2_PREV (4367L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_3 (4368L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_3_ATTRIB (4369L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_3_NEXT (4370L) +#define MAC_PCS_XXV_LT_TABLE_READBACK_3_PREV (4371L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0 (4372L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_ATTRIB (4373L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_NEXT (4374L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_PREV (4375L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_SEL (4376L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_TABLE_ADDR (4377L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_UPDATE (4378L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1 (4379L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_ATTRIB (4380L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_NEXT (4381L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_PREV (4382L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_SEL (4383L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_TABLE_ADDR (4384L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_UPDATE (4385L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2 (4386L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_ATTRIB (4387L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_NEXT (4388L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_PREV (4389L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_SEL (4390L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_TABLE_ADDR (4391L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_UPDATE (4392L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3 (4393L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_ATTRIB (4394L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_NEXT (4395L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_PREV (4396L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_SEL (4397L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_TABLE_ADDR (4398L) +#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_UPDATE (4399L) +#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_0 (4400L) +#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_0_RX_MAX_LENGTH (4401L) +#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_1 (4402L) +#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_1_RX_MAX_LENGTH (4403L) +#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_2 (4404L) +#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_2_RX_MAX_LENGTH (4405L) +#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_3 (4406L) +#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_3_RX_MAX_LENGTH (4407L) +#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_0 (4408L) +#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_0_MIN_RX_FRAME (4409L) +#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_0_RX_MIN_LENGTH (4410L) +#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_1 (4411L) +#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_1_MIN_RX_FRAME (4412L) +#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_1_RX_MIN_LENGTH (4413L) +#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_2 (4414L) +#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_2_MIN_RX_FRAME (4415L) +#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_2_RX_MIN_LENGTH (4416L) +#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_3 (4417L) +#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_3_MIN_RX_FRAME (4418L) +#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_3_RX_MIN_LENGTH (4419L) +#define MAC_PCS_XXV_MAX_PKT_LEN_0 (4420L) +#define MAC_PCS_XXV_MAX_PKT_LEN_0_MAX_LEN (4421L) +#define MAC_PCS_XXV_MAX_PKT_LEN_1 (4422L) +#define MAC_PCS_XXV_MAX_PKT_LEN_1_MAX_LEN (4423L) +#define MAC_PCS_XXV_MAX_PKT_LEN_2 (4424L) +#define MAC_PCS_XXV_MAX_PKT_LEN_2_MAX_LEN (4425L) +#define MAC_PCS_XXV_MAX_PKT_LEN_3 (4426L) +#define MAC_PCS_XXV_MAX_PKT_LEN_3_MAX_LEN (4427L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0 (4428L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_ADJ_MAIN (4429L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_ADJ_POST (4430L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_ADJ_PRE (4431L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_ENABLE (4432L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_INIT (4433L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_PRESET (4434L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_RX_READY (4435L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1 (4436L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_ADJ_MAIN (4437L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_ADJ_POST (4438L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_ADJ_PRE (4439L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_ENABLE (4440L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_INIT (4441L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_PRESET (4442L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_RX_READY (4443L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2 (4444L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_ADJ_MAIN (4445L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_ADJ_POST (4446L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_ADJ_PRE (4447L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_ENABLE (4448L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_INIT (4449L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_PRESET (4450L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_RX_READY (4451L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3 (4452L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_ADJ_MAIN (4453L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_ADJ_POST (4454L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_ADJ_PRE (4455L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_ENABLE (4456L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_INIT (4457L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_PRESET (4458L) +#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_RX_READY (4459L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_0 (4460L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_0_MAIN_STA (4461L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_0_POST_STA (4462L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_0_PRE_STA (4463L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_1 (4464L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_1_MAIN_STA (4465L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_1_POST_STA (4466L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_1_PRE_STA (4467L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_2 (4468L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_2_MAIN_STA (4469L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_2_POST_STA (4470L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_2_PRE_STA (4471L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_3 (4472L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_3_MAIN_STA (4473L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_3_POST_STA (4474L) +#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_3_PRE_STA (4475L) +#define MAC_PCS_XXV_RST_0 (4476L) +#define MAC_PCS_XXV_RST_0_MAC_PCS (4477L) +#define MAC_PCS_XXV_RST_1 (4478L) +#define MAC_PCS_XXV_RST_1_MAC_PCS (4479L) +#define MAC_PCS_XXV_RST_2 (4480L) +#define MAC_PCS_XXV_RST_2_MAC_PCS (4481L) +#define MAC_PCS_XXV_RST_3 (4482L) +#define MAC_PCS_XXV_RST_3_MAC_PCS (4483L) +#define MAC_PCS_XXV_RS_FEC_CCW_CNT_0 (4484L) +#define MAC_PCS_XXV_RS_FEC_CCW_CNT_0_RS_FEC_CCW_CNT (4485L) +#define MAC_PCS_XXV_RS_FEC_CCW_CNT_1 (4486L) +#define MAC_PCS_XXV_RS_FEC_CCW_CNT_1_RS_FEC_CCW_CNT (4487L) +#define MAC_PCS_XXV_RS_FEC_CCW_CNT_2 (4488L) +#define MAC_PCS_XXV_RS_FEC_CCW_CNT_2_RS_FEC_CCW_CNT (4489L) +#define MAC_PCS_XXV_RS_FEC_CCW_CNT_3 (4490L) +#define MAC_PCS_XXV_RS_FEC_CCW_CNT_3_RS_FEC_CCW_CNT (4491L) +#define MAC_PCS_XXV_RS_FEC_CONF_0 (4492L) +#define MAC_PCS_XXV_RS_FEC_CONF_0_CONSORTIUM (4493L) +#define MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_CORRECTION (4494L) +#define MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_ENABLE (4495L) +#define MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_IEEE_ERROR_INDICATION (4496L) +#define MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_INDICATION (4497L) +#define MAC_PCS_XXV_RS_FEC_CONF_1 (4498L) +#define MAC_PCS_XXV_RS_FEC_CONF_1_CONSORTIUM (4499L) +#define MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_CORRECTION (4500L) +#define MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_ENABLE (4501L) +#define MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_IEEE_ERROR_INDICATION (4502L) +#define MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_INDICATION (4503L) +#define MAC_PCS_XXV_RS_FEC_CONF_2 (4504L) +#define MAC_PCS_XXV_RS_FEC_CONF_2_CONSORTIUM (4505L) +#define MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_CORRECTION (4506L) +#define MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_ENABLE (4507L) +#define MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_IEEE_ERROR_INDICATION (4508L) +#define MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_INDICATION (4509L) +#define MAC_PCS_XXV_RS_FEC_CONF_3 (4510L) +#define MAC_PCS_XXV_RS_FEC_CONF_3_CONSORTIUM (4511L) +#define MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_CORRECTION (4512L) +#define MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_ENABLE (4513L) +#define MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_IEEE_ERROR_INDICATION (4514L) +#define MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_INDICATION (4515L) +#define MAC_PCS_XXV_RS_FEC_ERR_CNT_0 (4516L) +#define MAC_PCS_XXV_RS_FEC_ERR_CNT_0_RS_FEC_ERR_CNT (4517L) +#define MAC_PCS_XXV_RS_FEC_ERR_CNT_1 (4518L) +#define MAC_PCS_XXV_RS_FEC_ERR_CNT_1_RS_FEC_ERR_CNT (4519L) +#define MAC_PCS_XXV_RS_FEC_ERR_CNT_2 (4520L) +#define MAC_PCS_XXV_RS_FEC_ERR_CNT_2_RS_FEC_ERR_CNT (4521L) +#define MAC_PCS_XXV_RS_FEC_ERR_CNT_3 (4522L) +#define MAC_PCS_XXV_RS_FEC_ERR_CNT_3_RS_FEC_ERR_CNT (4523L) +#define MAC_PCS_XXV_RS_FEC_UCW_CNT_0 (4524L) +#define MAC_PCS_XXV_RS_FEC_UCW_CNT_0_RS_FEC_UCW_CNT (4525L) +#define MAC_PCS_XXV_RS_FEC_UCW_CNT_1 (4526L) +#define MAC_PCS_XXV_RS_FEC_UCW_CNT_1_RS_FEC_UCW_CNT (4527L) +#define MAC_PCS_XXV_RS_FEC_UCW_CNT_2 (4528L) +#define MAC_PCS_XXV_RS_FEC_UCW_CNT_2_RS_FEC_UCW_CNT (4529L) +#define MAC_PCS_XXV_RS_FEC_UCW_CNT_3 (4530L) +#define MAC_PCS_XXV_RS_FEC_UCW_CNT_3_RS_FEC_UCW_CNT (4531L) +#define MAC_PCS_XXV_RX_BAD_FCS_0 (4532L) +#define MAC_PCS_XXV_RX_BAD_FCS_0_COUNT (4533L) +#define MAC_PCS_XXV_RX_BAD_FCS_1 (4534L) +#define MAC_PCS_XXV_RX_BAD_FCS_1_COUNT (4535L) +#define MAC_PCS_XXV_RX_BAD_FCS_2 (4536L) +#define MAC_PCS_XXV_RX_BAD_FCS_2_COUNT (4537L) +#define MAC_PCS_XXV_RX_BAD_FCS_3 (4538L) +#define MAC_PCS_XXV_RX_BAD_FCS_3_COUNT (4539L) +#define MAC_PCS_XXV_RX_FRAMING_ERROR_0 (4540L) +#define MAC_PCS_XXV_RX_FRAMING_ERROR_0_COUNT (4541L) +#define MAC_PCS_XXV_RX_FRAMING_ERROR_1 (4542L) +#define MAC_PCS_XXV_RX_FRAMING_ERROR_1_COUNT (4543L) +#define MAC_PCS_XXV_RX_FRAMING_ERROR_2 (4544L) +#define MAC_PCS_XXV_RX_FRAMING_ERROR_2_COUNT (4545L) +#define MAC_PCS_XXV_RX_FRAMING_ERROR_3 (4546L) +#define MAC_PCS_XXV_RX_FRAMING_ERROR_3_COUNT (4547L) +#define MAC_PCS_XXV_RX_GOOD_BYTES_0 (4548L) +#define MAC_PCS_XXV_RX_GOOD_BYTES_0_COUNT (4549L) +#define MAC_PCS_XXV_RX_GOOD_BYTES_1 (4550L) +#define MAC_PCS_XXV_RX_GOOD_BYTES_1_COUNT (4551L) +#define MAC_PCS_XXV_RX_GOOD_BYTES_2 (4552L) +#define MAC_PCS_XXV_RX_GOOD_BYTES_2_COUNT (4553L) +#define MAC_PCS_XXV_RX_GOOD_BYTES_3 (4554L) +#define MAC_PCS_XXV_RX_GOOD_BYTES_3_COUNT (4555L) +#define MAC_PCS_XXV_RX_GOOD_PACKETS_0 (4556L) +#define MAC_PCS_XXV_RX_GOOD_PACKETS_0_COUNT (4557L) +#define MAC_PCS_XXV_RX_GOOD_PACKETS_1 (4558L) +#define MAC_PCS_XXV_RX_GOOD_PACKETS_1_COUNT (4559L) +#define MAC_PCS_XXV_RX_GOOD_PACKETS_2 (4560L) +#define MAC_PCS_XXV_RX_GOOD_PACKETS_2_COUNT (4561L) +#define MAC_PCS_XXV_RX_GOOD_PACKETS_3 (4562L) +#define MAC_PCS_XXV_RX_GOOD_PACKETS_3_COUNT (4563L) +#define MAC_PCS_XXV_RX_LATENCY_0 (4564L) +#define MAC_PCS_XXV_RX_LATENCY_0_LATENCY (4565L) +#define MAC_PCS_XXV_RX_LATENCY_1 (4566L) +#define MAC_PCS_XXV_RX_LATENCY_1_LATENCY (4567L) +#define MAC_PCS_XXV_RX_TOTAL_BYTES_0 (4568L) +#define MAC_PCS_XXV_RX_TOTAL_BYTES_0_COUNT (4569L) +#define MAC_PCS_XXV_RX_TOTAL_BYTES_1 (4570L) +#define MAC_PCS_XXV_RX_TOTAL_BYTES_1_COUNT (4571L) +#define MAC_PCS_XXV_RX_TOTAL_BYTES_2 (4572L) +#define MAC_PCS_XXV_RX_TOTAL_BYTES_2_COUNT (4573L) +#define MAC_PCS_XXV_RX_TOTAL_BYTES_3 (4574L) +#define MAC_PCS_XXV_RX_TOTAL_BYTES_3_COUNT (4575L) +#define MAC_PCS_XXV_RX_TOTAL_PACKETS_0 (4576L) +#define MAC_PCS_XXV_RX_TOTAL_PACKETS_0_COUNT (4577L) +#define MAC_PCS_XXV_RX_TOTAL_PACKETS_1 (4578L) +#define MAC_PCS_XXV_RX_TOTAL_PACKETS_1_COUNT (4579L) +#define MAC_PCS_XXV_RX_TOTAL_PACKETS_2 (4580L) +#define MAC_PCS_XXV_RX_TOTAL_PACKETS_2_COUNT (4581L) +#define MAC_PCS_XXV_RX_TOTAL_PACKETS_3 (4582L) +#define MAC_PCS_XXV_RX_TOTAL_PACKETS_3_COUNT (4583L) +#define MAC_PCS_XXV_SUB_RST_0 (4584L) +#define MAC_PCS_XXV_SUB_RST_0_AN_LT (4585L) +#define MAC_PCS_XXV_SUB_RST_0_QPLL (4586L) +#define MAC_PCS_XXV_SUB_RST_0_RX_BUF (4587L) +#define MAC_PCS_XXV_SUB_RST_0_RX_GT_DATA (4588L) +#define MAC_PCS_XXV_SUB_RST_0_RX_MAC_PCS (4589L) +#define MAC_PCS_XXV_SUB_RST_0_RX_PCS (4590L) +#define MAC_PCS_XXV_SUB_RST_0_RX_PMA (4591L) +#define MAC_PCS_XXV_SUB_RST_0_SPEED_CTRL (4592L) +#define MAC_PCS_XXV_SUB_RST_0_TX_GT_DATA (4593L) +#define MAC_PCS_XXV_SUB_RST_0_TX_MAC_PCS (4594L) +#define MAC_PCS_XXV_SUB_RST_0_TX_PCS (4595L) +#define MAC_PCS_XXV_SUB_RST_0_TX_PMA (4596L) +#define MAC_PCS_XXV_SUB_RST_1 (4597L) +#define MAC_PCS_XXV_SUB_RST_1_AN_LT (4598L) +#define MAC_PCS_XXV_SUB_RST_1_QPLL (4599L) +#define MAC_PCS_XXV_SUB_RST_1_RX_BUF (4600L) +#define MAC_PCS_XXV_SUB_RST_1_RX_GT_DATA (4601L) +#define MAC_PCS_XXV_SUB_RST_1_RX_MAC_PCS (4602L) +#define MAC_PCS_XXV_SUB_RST_1_RX_PCS (4603L) +#define MAC_PCS_XXV_SUB_RST_1_RX_PMA (4604L) +#define MAC_PCS_XXV_SUB_RST_1_SPEED_CTRL (4605L) +#define MAC_PCS_XXV_SUB_RST_1_TX_GT_DATA (4606L) +#define MAC_PCS_XXV_SUB_RST_1_TX_MAC_PCS (4607L) +#define MAC_PCS_XXV_SUB_RST_1_TX_PCS (4608L) +#define MAC_PCS_XXV_SUB_RST_1_TX_PMA (4609L) +#define MAC_PCS_XXV_SUB_RST_2 (4610L) +#define MAC_PCS_XXV_SUB_RST_2_AN_LT (4611L) +#define MAC_PCS_XXV_SUB_RST_2_QPLL (4612L) +#define MAC_PCS_XXV_SUB_RST_2_RX_BUF (4613L) +#define MAC_PCS_XXV_SUB_RST_2_RX_GT_DATA (4614L) +#define MAC_PCS_XXV_SUB_RST_2_RX_MAC_PCS (4615L) +#define MAC_PCS_XXV_SUB_RST_2_RX_PCS (4616L) +#define MAC_PCS_XXV_SUB_RST_2_RX_PMA (4617L) +#define MAC_PCS_XXV_SUB_RST_2_SPEED_CTRL (4618L) +#define MAC_PCS_XXV_SUB_RST_2_TX_GT_DATA (4619L) +#define MAC_PCS_XXV_SUB_RST_2_TX_MAC_PCS (4620L) +#define MAC_PCS_XXV_SUB_RST_2_TX_PCS (4621L) +#define MAC_PCS_XXV_SUB_RST_2_TX_PMA (4622L) +#define MAC_PCS_XXV_SUB_RST_3 (4623L) +#define MAC_PCS_XXV_SUB_RST_3_AN_LT (4624L) +#define MAC_PCS_XXV_SUB_RST_3_QPLL (4625L) +#define MAC_PCS_XXV_SUB_RST_3_RX_BUF (4626L) +#define MAC_PCS_XXV_SUB_RST_3_RX_GT_DATA (4627L) +#define MAC_PCS_XXV_SUB_RST_3_RX_MAC_PCS (4628L) +#define MAC_PCS_XXV_SUB_RST_3_RX_PCS (4629L) +#define MAC_PCS_XXV_SUB_RST_3_RX_PMA (4630L) +#define MAC_PCS_XXV_SUB_RST_3_SPEED_CTRL (4631L) +#define MAC_PCS_XXV_SUB_RST_3_TX_GT_DATA (4632L) +#define MAC_PCS_XXV_SUB_RST_3_TX_MAC_PCS (4633L) +#define MAC_PCS_XXV_SUB_RST_3_TX_PCS (4634L) +#define MAC_PCS_XXV_SUB_RST_3_TX_PMA (4635L) +#define MAC_PCS_XXV_SUB_RST_STATUS_0 (4636L) +#define MAC_PCS_XXV_SUB_RST_STATUS_0_QPLL_LOCK (4637L) +#define MAC_PCS_XXV_SUB_RST_STATUS_0_USER_RX_RST (4638L) +#define MAC_PCS_XXV_SUB_RST_STATUS_0_USER_TX_RST (4639L) +#define MAC_PCS_XXV_SUB_RST_STATUS_1 (4640L) +#define MAC_PCS_XXV_SUB_RST_STATUS_1_QPLL_LOCK (4641L) +#define MAC_PCS_XXV_SUB_RST_STATUS_1_USER_RX_RST (4642L) +#define MAC_PCS_XXV_SUB_RST_STATUS_1_USER_TX_RST (4643L) +#define MAC_PCS_XXV_SUB_RST_STATUS_2 (4644L) +#define MAC_PCS_XXV_SUB_RST_STATUS_2_QPLL_LOCK (4645L) +#define MAC_PCS_XXV_SUB_RST_STATUS_2_USER_RX_RST (4646L) +#define MAC_PCS_XXV_SUB_RST_STATUS_2_USER_TX_RST (4647L) +#define MAC_PCS_XXV_SUB_RST_STATUS_3 (4648L) +#define MAC_PCS_XXV_SUB_RST_STATUS_3_QPLL_LOCK (4649L) +#define MAC_PCS_XXV_SUB_RST_STATUS_3_USER_RX_RST (4650L) +#define MAC_PCS_XXV_SUB_RST_STATUS_3_USER_TX_RST (4651L) +#define MAC_PCS_XXV_TIMESTAMP_COMP_0 (4652L) +#define MAC_PCS_XXV_TIMESTAMP_COMP_0_RX_DLY (4653L) +#define MAC_PCS_XXV_TIMESTAMP_COMP_0_TX_DLY (4654L) +#define MAC_PCS_XXV_TIMESTAMP_COMP_1 (4655L) +#define MAC_PCS_XXV_TIMESTAMP_COMP_1_RX_DLY (4656L) +#define MAC_PCS_XXV_TIMESTAMP_COMP_1_TX_DLY (4657L) +#define MAC_PCS_XXV_TIMESTAMP_COMP_2 (4658L) +#define MAC_PCS_XXV_TIMESTAMP_COMP_2_RX_DLY (4659L) +#define MAC_PCS_XXV_TIMESTAMP_COMP_2_TX_DLY (4660L) +#define MAC_PCS_XXV_TIMESTAMP_COMP_3 (4661L) +#define MAC_PCS_XXV_TIMESTAMP_COMP_3_RX_DLY (4662L) +#define MAC_PCS_XXV_TIMESTAMP_COMP_3_TX_DLY (4663L) +#define MAC_PCS_XXV_TX_BAD_FCS_0 (4664L) +#define MAC_PCS_XXV_TX_BAD_FCS_0_COUNT (4665L) +#define MAC_PCS_XXV_TX_BAD_FCS_1 (4666L) +#define MAC_PCS_XXV_TX_BAD_FCS_1_COUNT (4667L) +#define MAC_PCS_XXV_TX_BAD_FCS_2 (4668L) +#define MAC_PCS_XXV_TX_BAD_FCS_2_COUNT (4669L) +#define MAC_PCS_XXV_TX_BAD_FCS_3 (4670L) +#define MAC_PCS_XXV_TX_BAD_FCS_3_COUNT (4671L) +#define MAC_PCS_XXV_TX_FRAME_ERROR_0 (4672L) +#define MAC_PCS_XXV_TX_FRAME_ERROR_0_COUNT (4673L) +#define MAC_PCS_XXV_TX_FRAME_ERROR_1 (4674L) +#define MAC_PCS_XXV_TX_FRAME_ERROR_1_COUNT (4675L) +#define MAC_PCS_XXV_TX_FRAME_ERROR_2 (4676L) +#define MAC_PCS_XXV_TX_FRAME_ERROR_2_COUNT (4677L) +#define MAC_PCS_XXV_TX_FRAME_ERROR_3 (4678L) +#define MAC_PCS_XXV_TX_FRAME_ERROR_3_COUNT (4679L) +#define MAC_PCS_XXV_TX_GOOD_BYTES_0 (4680L) +#define MAC_PCS_XXV_TX_GOOD_BYTES_0_COUNT (4681L) +#define MAC_PCS_XXV_TX_GOOD_BYTES_1 (4682L) +#define MAC_PCS_XXV_TX_GOOD_BYTES_1_COUNT (4683L) +#define MAC_PCS_XXV_TX_GOOD_BYTES_2 (4684L) +#define MAC_PCS_XXV_TX_GOOD_BYTES_2_COUNT (4685L) +#define MAC_PCS_XXV_TX_GOOD_BYTES_3 (4686L) +#define MAC_PCS_XXV_TX_GOOD_BYTES_3_COUNT (4687L) +#define MAC_PCS_XXV_TX_GOOD_PACKETS_0 (4688L) +#define MAC_PCS_XXV_TX_GOOD_PACKETS_0_COUNT (4689L) +#define MAC_PCS_XXV_TX_GOOD_PACKETS_1 (4690L) +#define MAC_PCS_XXV_TX_GOOD_PACKETS_1_COUNT (4691L) +#define MAC_PCS_XXV_TX_GOOD_PACKETS_2 (4692L) +#define MAC_PCS_XXV_TX_GOOD_PACKETS_2_COUNT (4693L) +#define MAC_PCS_XXV_TX_GOOD_PACKETS_3 (4694L) +#define MAC_PCS_XXV_TX_GOOD_PACKETS_3_COUNT (4695L) +#define MAC_PCS_XXV_TX_TOTAL_BYTES_0 (4696L) +#define MAC_PCS_XXV_TX_TOTAL_BYTES_0_COUNT (4697L) +#define MAC_PCS_XXV_TX_TOTAL_BYTES_1 (4698L) +#define MAC_PCS_XXV_TX_TOTAL_BYTES_1_COUNT (4699L) +#define MAC_PCS_XXV_TX_TOTAL_BYTES_2 (4700L) +#define MAC_PCS_XXV_TX_TOTAL_BYTES_2_COUNT (4701L) +#define MAC_PCS_XXV_TX_TOTAL_BYTES_3 (4702L) +#define MAC_PCS_XXV_TX_TOTAL_BYTES_3_COUNT (4703L) +#define MAC_PCS_XXV_TX_TOTAL_PACKETS_0 (4704L) +#define MAC_PCS_XXV_TX_TOTAL_PACKETS_0_COUNT (4705L) +#define MAC_PCS_XXV_TX_TOTAL_PACKETS_1 (4706L) +#define MAC_PCS_XXV_TX_TOTAL_PACKETS_1_COUNT (4707L) +#define MAC_PCS_XXV_TX_TOTAL_PACKETS_2 (4708L) +#define MAC_PCS_XXV_TX_TOTAL_PACKETS_2_COUNT (4709L) +#define MAC_PCS_XXV_TX_TOTAL_PACKETS_3 (4710L) +#define MAC_PCS_XXV_TX_TOTAL_PACKETS_3_COUNT (4711L) +/* MAC_RX */ +#define MAC_RX_BAD_FCS (4712L) +#define MAC_RX_BAD_FCS_COUNT (4713L) +#define MAC_RX_BAD_PREAMBLE (4714L) +#define MAC_RX_BAD_PREAMBLE_COUNT (4715L) +#define MAC_RX_BAD_SFD (4716L) +#define MAC_RX_BAD_SFD_COUNT (4717L) +#define MAC_RX_BROADCAST (4718L) +#define MAC_RX_BROADCAST_COUNT (4719L) +#define MAC_RX_FRAGMENT (4720L) +#define MAC_RX_FRAGMENT_COUNT (4721L) +#define MAC_RX_INRANGEERR (4722L) +#define MAC_RX_INRANGEERR_COUNT (4723L) +#define MAC_RX_JABBER (4724L) +#define MAC_RX_JABBER_COUNT (4725L) +#define MAC_RX_MULTICAST (4726L) +#define MAC_RX_MULTICAST_COUNT (4727L) +#define MAC_RX_OVERSIZE (4728L) +#define MAC_RX_OVERSIZE_COUNT (4729L) +#define MAC_RX_PACKET_1024_1518_BYTES (4730L) +#define MAC_RX_PACKET_1024_1518_BYTES_COUNT (4731L) +#define MAC_RX_PACKET_128_255_BYTES (4732L) +#define MAC_RX_PACKET_128_255_BYTES_COUNT (4733L) +#define MAC_RX_PACKET_1519_1522_BYTES (4734L) +#define MAC_RX_PACKET_1519_1522_BYTES_COUNT (4735L) +#define MAC_RX_PACKET_1523_1548_BYTES (4736L) +#define MAC_RX_PACKET_1523_1548_BYTES_COUNT (4737L) +#define MAC_RX_PACKET_1549_2047_BYTES (4738L) +#define MAC_RX_PACKET_1549_2047_BYTES_COUNT (4739L) +#define MAC_RX_PACKET_2048_4095_BYTES (4740L) +#define MAC_RX_PACKET_2048_4095_BYTES_COUNT (4741L) +#define MAC_RX_PACKET_256_511_BYTES (4742L) +#define MAC_RX_PACKET_256_511_BYTES_COUNT (4743L) +#define MAC_RX_PACKET_4096_8191_BYTES (4744L) +#define MAC_RX_PACKET_4096_8191_BYTES_COUNT (4745L) +#define MAC_RX_PACKET_512_1023_BYTES (4746L) +#define MAC_RX_PACKET_512_1023_BYTES_COUNT (4747L) +#define MAC_RX_PACKET_64_BYTES (4748L) +#define MAC_RX_PACKET_64_BYTES_COUNT (4749L) +#define MAC_RX_PACKET_65_127_BYTES (4750L) +#define MAC_RX_PACKET_65_127_BYTES_COUNT (4751L) +#define MAC_RX_PACKET_8192_9215_BYTES (4752L) +#define MAC_RX_PACKET_8192_9215_BYTES_COUNT (4753L) +#define MAC_RX_PACKET_BAD_FCS (4754L) +#define MAC_RX_PACKET_BAD_FCS_COUNT (4755L) +#define MAC_RX_PACKET_LARGE (4756L) +#define MAC_RX_PACKET_LARGE_COUNT (4757L) +#define MAC_RX_PACKET_SMALL (4758L) +#define MAC_RX_PACKET_SMALL_COUNT (4759L) +#define MAC_RX_STOMPED_FCS (4760L) +#define MAC_RX_STOMPED_FCS_COUNT (4761L) +#define MAC_RX_TOOLONG (4762L) +#define MAC_RX_TOOLONG_COUNT (4763L) +#define MAC_RX_TOTAL_BYTES (4764L) +#define MAC_RX_TOTAL_BYTES_COUNT (4765L) +#define MAC_RX_TOTAL_GOOD_BYTES (4766L) +#define MAC_RX_TOTAL_GOOD_BYTES_COUNT (4767L) +#define MAC_RX_TOTAL_GOOD_PACKETS (4768L) +#define MAC_RX_TOTAL_GOOD_PACKETS_COUNT (4769L) +#define MAC_RX_TOTAL_PACKETS (4770L) +#define MAC_RX_TOTAL_PACKETS_COUNT (4771L) +#define MAC_RX_TRUNCATED (4772L) +#define MAC_RX_TRUNCATED_COUNT (4773L) +#define MAC_RX_UNDERSIZE (4774L) +#define MAC_RX_UNDERSIZE_COUNT (4775L) +#define MAC_RX_UNICAST (4776L) +#define MAC_RX_UNICAST_COUNT (4777L) +#define MAC_RX_VLAN (4778L) +#define MAC_RX_VLAN_COUNT (4779L) +/* MAC_TFG */ +#define MAC_TFG_TFG_ADDR (4780L) +#define MAC_TFG_TFG_ADDR_ADR (4781L) +#define MAC_TFG_TFG_ADDR_RDENA (4782L) +#define MAC_TFG_TFG_ADDR_RD_DONE (4783L) +#define MAC_TFG_TFG_CTRL (4784L) +#define MAC_TFG_TFG_CTRL_ID_ENA (4785L) +#define MAC_TFG_TFG_CTRL_ID_POS (4786L) +#define MAC_TFG_TFG_CTRL_RESTART (4787L) +#define MAC_TFG_TFG_CTRL_TG_ACT (4788L) +#define MAC_TFG_TFG_CTRL_TG_ENA (4789L) +#define MAC_TFG_TFG_CTRL_TIME_MODE (4790L) +#define MAC_TFG_TFG_CTRL_WRAP (4791L) +#define MAC_TFG_TFG_DATA (4792L) +#define MAC_TFG_TFG_DATA_GAP (4793L) +#define MAC_TFG_TFG_DATA_ID (4794L) +#define MAC_TFG_TFG_DATA_LENGTH (4795L) +#define MAC_TFG_TFG_FRAME_HDR (4796L) +#define MAC_TFG_TFG_FRAME_HDR_HDR (4797L) +#define MAC_TFG_TFG_REPETITION (4798L) +#define MAC_TFG_TFG_REPETITION_CNT (4799L) +/* MAC_TX */ +#define MAC_TX_BAD_FCS (4800L) +#define MAC_TX_BAD_FCS_COUNT (4801L) +#define MAC_TX_BROADCAST (4802L) +#define MAC_TX_BROADCAST_COUNT (4803L) +#define MAC_TX_FRAME_ERRORS (4804L) +#define MAC_TX_FRAME_ERRORS_COUNT (4805L) +#define MAC_TX_MULTICAST (4806L) +#define MAC_TX_MULTICAST_COUNT (4807L) +#define MAC_TX_PACKET_1024_1518_BYTES (4808L) +#define MAC_TX_PACKET_1024_1518_BYTES_COUNT (4809L) +#define MAC_TX_PACKET_128_255_BYTES (4810L) +#define MAC_TX_PACKET_128_255_BYTES_COUNT (4811L) +#define MAC_TX_PACKET_1519_1522_BYTES (4812L) +#define MAC_TX_PACKET_1519_1522_BYTES_COUNT (4813L) +#define MAC_TX_PACKET_1523_1548_BYTES (4814L) +#define MAC_TX_PACKET_1523_1548_BYTES_COUNT (4815L) +#define MAC_TX_PACKET_1549_2047_BYTES (4816L) +#define MAC_TX_PACKET_1549_2047_BYTES_COUNT (4817L) +#define MAC_TX_PACKET_2048_4095_BYTES (4818L) +#define MAC_TX_PACKET_2048_4095_BYTES_COUNT (4819L) +#define MAC_TX_PACKET_256_511_BYTES (4820L) +#define MAC_TX_PACKET_256_511_BYTES_COUNT (4821L) +#define MAC_TX_PACKET_4096_8191_BYTES (4822L) +#define MAC_TX_PACKET_4096_8191_BYTES_COUNT (4823L) +#define MAC_TX_PACKET_512_1023_BYTES (4824L) +#define MAC_TX_PACKET_512_1023_BYTES_COUNT (4825L) +#define MAC_TX_PACKET_64_BYTES (4826L) +#define MAC_TX_PACKET_64_BYTES_COUNT (4827L) +#define MAC_TX_PACKET_65_127_BYTES (4828L) +#define MAC_TX_PACKET_65_127_BYTES_COUNT (4829L) +#define MAC_TX_PACKET_8192_9215_BYTES (4830L) +#define MAC_TX_PACKET_8192_9215_BYTES_COUNT (4831L) +#define MAC_TX_PACKET_LARGE (4832L) +#define MAC_TX_PACKET_LARGE_COUNT (4833L) +#define MAC_TX_PACKET_SMALL (4834L) +#define MAC_TX_PACKET_SMALL_COUNT (4835L) +#define MAC_TX_TOTAL_BYTES (4836L) +#define MAC_TX_TOTAL_BYTES_COUNT (4837L) +#define MAC_TX_TOTAL_GOOD_BYTES (4838L) +#define MAC_TX_TOTAL_GOOD_BYTES_COUNT (4839L) +#define MAC_TX_TOTAL_GOOD_PACKETS (4840L) +#define MAC_TX_TOTAL_GOOD_PACKETS_COUNT (4841L) +#define MAC_TX_TOTAL_PACKETS (4842L) +#define MAC_TX_TOTAL_PACKETS_COUNT (4843L) +#define MAC_TX_UNICAST (4844L) +#define MAC_TX_UNICAST_COUNT (4845L) +#define MAC_TX_VLAN (4846L) +#define MAC_TX_VLAN_COUNT (4847L) +/* MCU */ +#define MCU_CSR (4848L) +#define MCU_CSR_HALT (4849L) +#define MCU_CSR_PAUSE (4850L) +#define MCU_CSR_RESET (4851L) +#define MCU_CSR_RESET_MCU (4852L) +#define MCU_DRAM_CTRL (4853L) +#define MCU_DRAM_CTRL_ADR (4854L) +#define MCU_DRAM_CTRL_CNT (4855L) +#define MCU_DRAM_RD_DATA (4856L) +#define MCU_DRAM_RD_DATA_DATA (4857L) +#define MCU_DRAM_WR_DATA (4858L) +#define MCU_DRAM_WR_DATA_DATA (4859L) +#define MCU_IRAM_CTRL (4860L) +#define MCU_IRAM_CTRL_ADR (4861L) +#define MCU_IRAM_CTRL_CNT (4862L) +#define MCU_IRAM_DATA (4863L) +#define MCU_IRAM_DATA_DATA (4864L) +/* MDG */ +#define MDG_BSO_CTRL (4865L) +#define MDG_BSO_CTRL_ADR (4866L) +#define MDG_BSO_CTRL_CNT (4867L) +#define MDG_BSO_DATA (4868L) +#define MDG_BSO_DATA_OFFSET (4869L) +#define MDG_CONTROL (4870L) +#define MDG_CONTROL_AE (4871L) +#define MDG_CONTROL_AS (4872L) +#define MDG_CONTROL_CE (4873L) +#define MDG_CONTROL_EN (4874L) +#define MDG_DBG_EGS_FC0 (4875L) +#define MDG_DBG_EGS_FC0_BLOCKED (4876L) +#define MDG_DBG_EGS_FC1 (4877L) +#define MDG_DBG_EGS_FC1_BLOCKED (4878L) +#define MDG_DBG_EGS_FC2 (4879L) +#define MDG_DBG_EGS_FC2_BLOCKED (4880L) +#define MDG_DBG_EGS_FC3 (4881L) +#define MDG_DBG_EGS_FC3_BLOCKED (4882L) +#define MDG_DBG_HBM (4883L) +#define MDG_DBG_HBM_ADR (4884L) +#define MDG_DBG_HBM_MAIN (4885L) +#define MDG_DBG_HBM_MAP (4886L) +#define MDG_DBG_HBM_META (4887L) +#define MDG_DBG_HBM_VALID (4888L) +#define MDG_DBG_IGS_FC0 (4889L) +#define MDG_DBG_IGS_FC0_BLOCKED (4890L) +#define MDG_DBG_IGS_FC1 (4891L) +#define MDG_DBG_IGS_FC1_BLOCKED (4892L) +#define MDG_DBG_IGS_FC2 (4893L) +#define MDG_DBG_IGS_FC2_BLOCKED (4894L) +#define MDG_DBG_IGS_FC3 (4895L) +#define MDG_DBG_IGS_FC3_BLOCKED (4896L) +#define MDG_HBM_CTRL (4897L) +#define MDG_HBM_CTRL_ADR (4898L) +#define MDG_HBM_CTRL_CNT (4899L) +#define MDG_HBM_DATA (4900L) +#define MDG_HBM_DATA_MAIN (4901L) +#define MDG_HBM_DATA_MAP (4902L) +#define MDG_HBM_DATA_META (4903L) +#define MDG_HBS_CTRL (4904L) +#define MDG_HBS_CTRL_ADR (4905L) +#define MDG_HBS_CTRL_CNT (4906L) +#define MDG_HBS_DATA (4907L) +#define MDG_HBS_DATA_SIZE (4908L) +#define MDG_MAX_BYTES (4909L) +#define MDG_MAX_BYTES_MAX (4910L) +#define MDG_MAX_PACKETS (4911L) +#define MDG_MAX_PACKETS_MAX (4912L) +#define MDG_TIMEOUT (4913L) +#define MDG_TIMEOUT_T (4914L) +/* MSK */ +#define MSK_RCP_CTRL (4980L) +#define MSK_RCP_CTRL_ADR (4981L) +#define MSK_RCP_CTRL_CNT (4982L) +#define MSK_RCP_DATA (4983L) +#define MSK_RCP_DATA_MASK_DYN0 (4984L) +#define MSK_RCP_DATA_MASK_DYN1 (4985L) +#define MSK_RCP_DATA_MASK_DYN2 (4986L) +#define MSK_RCP_DATA_MASK_DYN3 (4987L) +#define MSK_RCP_DATA_MASK_EN0 (4988L) +#define MSK_RCP_DATA_MASK_EN1 (4989L) +#define MSK_RCP_DATA_MASK_EN2 (4990L) +#define MSK_RCP_DATA_MASK_EN3 (4991L) +#define MSK_RCP_DATA_MASK_LEN0 (4992L) +#define MSK_RCP_DATA_MASK_LEN1 (4993L) +#define MSK_RCP_DATA_MASK_LEN2 (4994L) +#define MSK_RCP_DATA_MASK_LEN3 (4995L) +#define MSK_RCP_DATA_MASK_OFS0 (4996L) +#define MSK_RCP_DATA_MASK_OFS1 (4997L) +#define MSK_RCP_DATA_MASK_OFS2 (4998L) +#define MSK_RCP_DATA_MASK_OFS3 (4999L) +/* NIF */ +#define NIF_CTRL (5000L) +#define NIF_CTRL_GT_PWDN (5001L) +#define NIF_CTRL_GT_SEL (5002L) +#define NIF_CTRL_LOOPBACK (5003L) +#define NIF_CTRL_PMA_INIT (5004L) +#define NIF_CTRL_PRBS_ERR (5005L) +#define NIF_CTRL_PRBS_RST (5006L) +#define NIF_CTRL_PRBS_SEL (5007L) +#define NIF_CTRL_QPLL_SEL (5008L) +#define NIF_CTRL_RST (5009L) +#define NIF_CTRL_TX_INHIBIT (5010L) +#define NIF_DRP_IF (5011L) +#define NIF_DRP_IF_ADR (5012L) +#define NIF_DRP_IF_DATA (5013L) +#define NIF_DRP_IF_DBG_BUSY (5014L) +#define NIF_DRP_IF_DONE (5015L) +#define NIF_DRP_IF_WREN (5016L) +#define NIF_ERROR (5017L) +#define NIF_ERROR_HARD_ERR (5018L) +#define NIF_ERROR_SOFT_ERR (5019L) +#define NIF_ERROR_SOFT_ERR_CNT (5020L) +#define NIF_GTH_TX_TUNING (5021L) +#define NIF_GTH_TX_TUNING_DIFF_CTRL (5022L) +#define NIF_GTH_TX_TUNING_POST_CURSOR (5023L) +#define NIF_GTH_TX_TUNING_PRE_CURSOR (5024L) +#define NIF_HARD_ERROR_CNT (5025L) +#define NIF_HARD_ERROR_CNT_UNCORRECTABLE_ERRORS (5026L) +#define NIF_STATUS (5027L) +#define NIF_STATUS_CH_UP (5028L) +#define NIF_STATUS_EP0_0_UP (5029L) +#define NIF_STATUS_EP0_1_UP (5030L) +#define NIF_STATUS_EP0_2_UP (5031L) +#define NIF_STATUS_EP0_3_UP (5032L) +#define NIF_STATUS_EP1_0_UP (5033L) +#define NIF_STATUS_EP1_1_UP (5034L) +#define NIF_STATUS_EP1_2_UP (5035L) +#define NIF_STATUS_EP1_3_UP (5036L) +#define NIF_STATUS_EP1_4_UP (5037L) +#define NIF_STATUS_EP1_5_UP (5038L) +#define NIF_STATUS_EP3_0_UP (5039L) +#define NIF_STATUS_EP3_1_UP (5040L) +#define NIF_STATUS_EP3_2_UP (5041L) +#define NIF_STATUS_EP3_3_UP (5042L) +#define NIF_STATUS_MMCM_ULCK (5043L) +#define NIF_STATUS_PLL_LCK (5044L) +#define NIF_STATUS_QPLLOUT_LCK (5045L) +#define NIF_STATUS_QPLLOUT_REF_LOST (5046L) +#define NIF_STATUS_QPLL_LCK (5047L) +#define NIF_STATUS_RXRST_DONE (5048L) +#define NIF_STATUS_TXRST_DONE (5049L) +#define NIF_STATUS_STICK (5050L) +#define NIF_STATUS_STICK_CH_DOWN (5051L) +#define NIF_STATUS_STICK_LN_DOWN (5052L) +#define NIF_STATUS_STICK_MMCM_ULCK (5053L) +#define NIF_STATUS_STICK_PLL_ULCK (5054L) +#define NIF_USER_REG (5055L) +#define NIF_USER_REG_MASTER (5056L) +#define NIF_USER_REG_RST (5057L) +#define NIF_USER_REG_SLAVE (5058L) +#define NIF_USER_REG_STAT (5059L) +#define NIF_USER_REG_STAT_LL (5060L) +/* PCIE3 */ +#define PCIE3_BUILD_SEED (5228L) +#define PCIE3_BUILD_SEED_BUILD_SEED (5229L) +#define PCIE3_BUILD_TIME (5230L) +#define PCIE3_BUILD_TIME_TIME (5231L) +#define PCIE3_CONFIG (5232L) +#define PCIE3_CONFIG_EXT_TAG (5233L) +#define PCIE3_CONFIG_MAX_READ (5234L) +#define PCIE3_CONFIG_MAX_TLP (5235L) +#define PCIE3_CONTROL (5236L) +#define PCIE3_CONTROL_RD_ATTR (5237L) +#define PCIE3_CONTROL_WRAW (5238L) +#define PCIE3_CONTROL_WR_ATTR (5239L) +#define PCIE3_CORESPEED (5240L) +#define PCIE3_CORESPEED_CORESPEED (5241L) +#define PCIE3_CORESPEED_DDR3SPEED (5242L) +#define PCIE3_DRP_COMMON (5243L) +#define PCIE3_DRP_COMMON_DRP_ADDR (5244L) +#define PCIE3_DRP_COMMON_DRP_RDY (5245L) +#define PCIE3_DRP_COMMON_GTH_SEL (5246L) +#define PCIE3_DRP_COMMON_WR (5247L) +#define PCIE3_DRP_DATE (5248L) +#define PCIE3_DRP_DATE_DRP_DATA (5249L) +#define PCIE3_EP_TO_RP_ERR (5250L) +#define PCIE3_EP_TO_RP_ERR_ERR_COR (5251L) +#define PCIE3_EP_TO_RP_ERR_ERR_FATAL (5252L) +#define PCIE3_EP_TO_RP_ERR_ERR_NONFATAL (5253L) +#define PCIE3_INT_CLR (5254L) +#define PCIE3_INT_CLR_AVR (5255L) +#define PCIE3_INT_CLR_FHM (5256L) +#define PCIE3_INT_CLR_INT_0 (5257L) +#define PCIE3_INT_CLR_INT_1 (5258L) +#define PCIE3_INT_CLR_INT_10 (5259L) +#define PCIE3_INT_CLR_INT_11 (5260L) +#define PCIE3_INT_CLR_INT_12 (5261L) +#define PCIE3_INT_CLR_INT_13 (5262L) +#define PCIE3_INT_CLR_INT_14 (5263L) +#define PCIE3_INT_CLR_INT_15 (5264L) +#define PCIE3_INT_CLR_INT_16 (5265L) +#define PCIE3_INT_CLR_INT_17 (5266L) +#define PCIE3_INT_CLR_INT_18 (5267L) +#define PCIE3_INT_CLR_INT_19 (5268L) +#define PCIE3_INT_CLR_INT_2 (5269L) +#define PCIE3_INT_CLR_INT_20 (5270L) +#define PCIE3_INT_CLR_INT_21 (5271L) +#define PCIE3_INT_CLR_INT_22 (5272L) +#define PCIE3_INT_CLR_INT_23 (5273L) +#define PCIE3_INT_CLR_INT_24 (5274L) +#define PCIE3_INT_CLR_INT_25 (5275L) +#define PCIE3_INT_CLR_INT_26 (5276L) +#define PCIE3_INT_CLR_INT_27 (5277L) +#define PCIE3_INT_CLR_INT_28 (5278L) +#define PCIE3_INT_CLR_INT_29 (5279L) +#define PCIE3_INT_CLR_INT_3 (5280L) +#define PCIE3_INT_CLR_INT_30 (5281L) +#define PCIE3_INT_CLR_INT_31 (5282L) +#define PCIE3_INT_CLR_INT_4 (5283L) +#define PCIE3_INT_CLR_INT_5 (5284L) +#define PCIE3_INT_CLR_INT_6 (5285L) +#define PCIE3_INT_CLR_INT_7 (5286L) +#define PCIE3_INT_CLR_INT_8 (5287L) +#define PCIE3_INT_CLR_INT_9 (5288L) +#define PCIE3_INT_CLR_PORT (5289L) +#define PCIE3_INT_CLR_PPS (5290L) +#define PCIE3_INT_CLR_QSPI (5291L) +#define PCIE3_INT_CLR_SPIM (5292L) +#define PCIE3_INT_CLR_SPIS (5293L) +#define PCIE3_INT_CLR_STA (5294L) +#define PCIE3_INT_CLR_TIMER (5295L) +#define PCIE3_INT_FORC (5296L) +#define PCIE3_INT_FORC_AVR (5297L) +#define PCIE3_INT_FORC_FHM (5298L) +#define PCIE3_INT_FORC_INT_0 (5299L) +#define PCIE3_INT_FORC_INT_1 (5300L) +#define PCIE3_INT_FORC_INT_10 (5301L) +#define PCIE3_INT_FORC_INT_11 (5302L) +#define PCIE3_INT_FORC_INT_12 (5303L) +#define PCIE3_INT_FORC_INT_13 (5304L) +#define PCIE3_INT_FORC_INT_14 (5305L) +#define PCIE3_INT_FORC_INT_15 (5306L) +#define PCIE3_INT_FORC_INT_16 (5307L) +#define PCIE3_INT_FORC_INT_17 (5308L) +#define PCIE3_INT_FORC_INT_18 (5309L) +#define PCIE3_INT_FORC_INT_19 (5310L) +#define PCIE3_INT_FORC_INT_2 (5311L) +#define PCIE3_INT_FORC_INT_20 (5312L) +#define PCIE3_INT_FORC_INT_21 (5313L) +#define PCIE3_INT_FORC_INT_22 (5314L) +#define PCIE3_INT_FORC_INT_23 (5315L) +#define PCIE3_INT_FORC_INT_24 (5316L) +#define PCIE3_INT_FORC_INT_25 (5317L) +#define PCIE3_INT_FORC_INT_26 (5318L) +#define PCIE3_INT_FORC_INT_27 (5319L) +#define PCIE3_INT_FORC_INT_28 (5320L) +#define PCIE3_INT_FORC_INT_29 (5321L) +#define PCIE3_INT_FORC_INT_3 (5322L) +#define PCIE3_INT_FORC_INT_30 (5323L) +#define PCIE3_INT_FORC_INT_31 (5324L) +#define PCIE3_INT_FORC_INT_4 (5325L) +#define PCIE3_INT_FORC_INT_5 (5326L) +#define PCIE3_INT_FORC_INT_6 (5327L) +#define PCIE3_INT_FORC_INT_7 (5328L) +#define PCIE3_INT_FORC_INT_8 (5329L) +#define PCIE3_INT_FORC_INT_9 (5330L) +#define PCIE3_INT_FORC_PORT (5331L) +#define PCIE3_INT_FORC_PPS (5332L) +#define PCIE3_INT_FORC_QSPI (5333L) +#define PCIE3_INT_FORC_SPIM (5334L) +#define PCIE3_INT_FORC_SPIS (5335L) +#define PCIE3_INT_FORC_STA (5336L) +#define PCIE3_INT_FORC_TIMER (5337L) +#define PCIE3_INT_MASK (5338L) +#define PCIE3_INT_MASK_AVR (5339L) +#define PCIE3_INT_MASK_FHM (5340L) +#define PCIE3_INT_MASK_IIC0 (5341L) +#define PCIE3_INT_MASK_IIC1 (5342L) +#define PCIE3_INT_MASK_IIC2 (5343L) +#define PCIE3_INT_MASK_IIC3 (5344L) +#define PCIE3_INT_MASK_IIC4 (5345L) +#define PCIE3_INT_MASK_IIC5 (5346L) +#define PCIE3_INT_MASK_INT_0 (5347L) +#define PCIE3_INT_MASK_INT_1 (5348L) +#define PCIE3_INT_MASK_INT_10 (5349L) +#define PCIE3_INT_MASK_INT_11 (5350L) +#define PCIE3_INT_MASK_INT_12 (5351L) +#define PCIE3_INT_MASK_INT_13 (5352L) +#define PCIE3_INT_MASK_INT_14 (5353L) +#define PCIE3_INT_MASK_INT_15 (5354L) +#define PCIE3_INT_MASK_INT_16 (5355L) +#define PCIE3_INT_MASK_INT_17 (5356L) +#define PCIE3_INT_MASK_INT_18 (5357L) +#define PCIE3_INT_MASK_INT_19 (5358L) +#define PCIE3_INT_MASK_INT_2 (5359L) +#define PCIE3_INT_MASK_INT_20 (5360L) +#define PCIE3_INT_MASK_INT_21 (5361L) +#define PCIE3_INT_MASK_INT_22 (5362L) +#define PCIE3_INT_MASK_INT_23 (5363L) +#define PCIE3_INT_MASK_INT_24 (5364L) +#define PCIE3_INT_MASK_INT_25 (5365L) +#define PCIE3_INT_MASK_INT_26 (5366L) +#define PCIE3_INT_MASK_INT_27 (5367L) +#define PCIE3_INT_MASK_INT_28 (5368L) +#define PCIE3_INT_MASK_INT_29 (5369L) +#define PCIE3_INT_MASK_INT_3 (5370L) +#define PCIE3_INT_MASK_INT_30 (5371L) +#define PCIE3_INT_MASK_INT_31 (5372L) +#define PCIE3_INT_MASK_INT_4 (5373L) +#define PCIE3_INT_MASK_INT_5 (5374L) +#define PCIE3_INT_MASK_INT_6 (5375L) +#define PCIE3_INT_MASK_INT_7 (5376L) +#define PCIE3_INT_MASK_INT_8 (5377L) +#define PCIE3_INT_MASK_INT_9 (5378L) +#define PCIE3_INT_MASK_PORT (5379L) +#define PCIE3_INT_MASK_PPS (5380L) +#define PCIE3_INT_MASK_QSPI (5381L) +#define PCIE3_INT_MASK_SPIM (5382L) +#define PCIE3_INT_MASK_SPIS (5383L) +#define PCIE3_INT_MASK_STA (5384L) +#define PCIE3_INT_MASK_TIMER (5385L) +#define PCIE3_LAT_CTRL (5386L) +#define PCIE3_LAT_CTRL_CLEAR_RAM (5387L) +#define PCIE3_LAT_CTRL_ENABLE (5388L) +#define PCIE3_LAT_CTRL_PRESCAL (5389L) +#define PCIE3_LAT_CTRL_RAM_VLD (5390L) +#define PCIE3_LAT_CTRL_READ_RAM (5391L) +#define PCIE3_LAT_CTRL_STATUS (5392L) +#define PCIE3_LAT_MAX (5393L) +#define PCIE3_LAT_MAX_MAX (5394L) +#define PCIE3_LAT_RAMADR (5395L) +#define PCIE3_LAT_RAMADR_ADR (5396L) +#define PCIE3_LAT_RAMDATA (5397L) +#define PCIE3_LAT_RAMDATA_DATA (5398L) +#define PCIE3_LINK_STATUS (5399L) +#define PCIE3_LINK_STATUS_CLEAR (5400L) +#define PCIE3_LINK_STATUS_RETRAIN_CNT (5401L) +#define PCIE3_MARKADR_LSB (5402L) +#define PCIE3_MARKADR_LSB_ADR (5403L) +#define PCIE3_MARKADR_MSB (5404L) +#define PCIE3_MARKADR_MSB_ADR (5405L) +#define PCIE3_PB_INTERVAL (5406L) +#define PCIE3_PB_INTERVAL_INTERVAL (5407L) +#define PCIE3_PB_MAX_RD (5408L) +#define PCIE3_PB_MAX_RD_PB (5409L) +#define PCIE3_PB_MAX_WR (5410L) +#define PCIE3_PB_MAX_WR_PB (5411L) +#define PCIE3_PCIE_CTRL (5412L) +#define PCIE3_PCIE_CTRL_EXT_TAG_ENA (5413L) +#define PCIE3_PCI_ENDPOINT (5414L) +#define PCIE3_PCI_ENDPOINT_DMA_EP0_ALLOW_MASK (5415L) +#define PCIE3_PCI_ENDPOINT_DMA_EP1_ALLOW_MASK (5416L) +#define PCIE3_PCI_ENDPOINT_GET_MSG (5417L) +#define PCIE3_PCI_ENDPOINT_IF_ID (5418L) +#define PCIE3_PCI_ENDPOINT_SEND_MSG (5419L) +#define PCIE3_PCI_TEST0 (5420L) +#define PCIE3_PCI_TEST0_DATA (5421L) +#define PCIE3_PCI_TEST1 (5422L) +#define PCIE3_PCI_TEST1_DATA (5423L) +#define PCIE3_PCI_TEST2 (5424L) +#define PCIE3_PCI_TEST2_DATA (5425L) +#define PCIE3_PCI_TEST3 (5426L) +#define PCIE3_PCI_TEST3_DATA (5427L) +#define PCIE3_PROD_ID_EX (5428L) +#define PCIE3_PROD_ID_EX_LAYOUT (5429L) +#define PCIE3_PROD_ID_EX_LAYOUT_VERSION (5430L) +#define PCIE3_PROD_ID_EX_RESERVED (5431L) +#define PCIE3_PROD_ID_LSB (5432L) +#define PCIE3_PROD_ID_LSB_GROUP_ID (5433L) +#define PCIE3_PROD_ID_LSB_REV_ID (5434L) +#define PCIE3_PROD_ID_LSB_VER_ID (5435L) +#define PCIE3_PROD_ID_MSB (5436L) +#define PCIE3_PROD_ID_MSB_BUILD_NO (5437L) +#define PCIE3_PROD_ID_MSB_PATCH_NO (5438L) +#define PCIE3_PROD_ID_MSB_TYPE_ID (5439L) +#define PCIE3_RESET_CTRL (5440L) +#define PCIE3_RESET_CTRL_MASK (5441L) +#define PCIE3_RP_TO_EP_ERR (5442L) +#define PCIE3_RP_TO_EP_ERR_ERR_COR (5443L) +#define PCIE3_RP_TO_EP_ERR_ERR_FATAL (5444L) +#define PCIE3_RP_TO_EP_ERR_ERR_NONFATAL (5445L) +#define PCIE3_SAMPLE_TIME (5446L) +#define PCIE3_SAMPLE_TIME_SAMPLE_TIME (5447L) +#define PCIE3_STATUS (5448L) +#define PCIE3_STATUS_RD_ERR (5449L) +#define PCIE3_STATUS_TAGS_IN_USE (5450L) +#define PCIE3_STATUS_WR_ERR (5451L) +#define PCIE3_STATUS0 (5452L) +#define PCIE3_STATUS0_TAGS_IN_USE (5453L) +#define PCIE3_STATUS0_UR_ADDR (5454L) +#define PCIE3_STATUS0_UR_DWORD (5455L) +#define PCIE3_STATUS0_UR_FBE (5456L) +#define PCIE3_STATUS0_UR_FMT (5457L) +#define PCIE3_STATUS0_UR_LBE (5458L) +#define PCIE3_STATUS0_UR_REG (5459L) +#define PCIE3_STAT_CTRL (5460L) +#define PCIE3_STAT_CTRL_STAT_ENA (5461L) +#define PCIE3_STAT_CTRL_STAT_REQ (5462L) +#define PCIE3_STAT_REFCLK (5463L) +#define PCIE3_STAT_REFCLK_REFCLK250 (5464L) +#define PCIE3_STAT_RQ_RDY (5465L) +#define PCIE3_STAT_RQ_RDY_COUNTER (5466L) +#define PCIE3_STAT_RQ_VLD (5467L) +#define PCIE3_STAT_RQ_VLD_COUNTER (5468L) +#define PCIE3_STAT_RX (5469L) +#define PCIE3_STAT_RX_COUNTER (5470L) +#define PCIE3_STAT_TX (5471L) +#define PCIE3_STAT_TX_COUNTER (5472L) +#define PCIE3_TEST0 (5473L) +#define PCIE3_TEST0_DATA (5474L) +#define PCIE3_TEST1 (5475L) +#define PCIE3_TEST1_DATA (5476L) +#define PCIE3_TEST2_DATA (5477L) +#define PCIE3_TEST3_DATA (5478L) +#define PCIE3_UUID0 (5479L) +#define PCIE3_UUID0_UUID0 (5480L) +#define PCIE3_UUID1 (5481L) +#define PCIE3_UUID1_UUID1 (5482L) +#define PCIE3_UUID2 (5483L) +#define PCIE3_UUID2_UUID2 (5484L) +#define PCIE3_UUID3 (5485L) +#define PCIE3_UUID3_UUID3 (5486L) +/* PCI_RD_TG */ +#define PCI_RD_TG_TG_CTRL (5487L) +#define PCI_RD_TG_TG_CTRL_TG_RD_RDY (5488L) +#define PCI_RD_TG_TG_RDADDR (5489L) +#define PCI_RD_TG_TG_RDADDR_RAM_ADDR (5490L) +#define PCI_RD_TG_TG_RDDATA0 (5491L) +#define PCI_RD_TG_TG_RDDATA0_PHYS_ADDR_LOW (5492L) +#define PCI_RD_TG_TG_RDDATA1 (5493L) +#define PCI_RD_TG_TG_RDDATA1_PHYS_ADDR_HIGH (5494L) +#define PCI_RD_TG_TG_RDDATA2 (5495L) +#define PCI_RD_TG_TG_RDDATA2_REQ_HID (5496L) +#define PCI_RD_TG_TG_RDDATA2_REQ_SIZE (5497L) +#define PCI_RD_TG_TG_RDDATA2_WAIT (5498L) +#define PCI_RD_TG_TG_RDDATA2_WRAP (5499L) +#define PCI_RD_TG_TG_RD_RUN (5500L) +#define PCI_RD_TG_TG_RD_RUN_RD_ITERATION (5501L) +/* PCI_TA */ +#define PCI_TA_CONTROL (5502L) +#define PCI_TA_CONTROL_ENABLE (5503L) +#define PCI_TA_LENGTH_ERROR (5504L) +#define PCI_TA_LENGTH_ERROR_AMOUNT (5505L) +#define PCI_TA_PACKET_BAD (5506L) +#define PCI_TA_PACKET_BAD_AMOUNT (5507L) +#define PCI_TA_PACKET_GOOD (5508L) +#define PCI_TA_PACKET_GOOD_AMOUNT (5509L) +#define PCI_TA_PAYLOAD_ERROR (5510L) +#define PCI_TA_PAYLOAD_ERROR_AMOUNT (5511L) +/* PCI_WR_TG */ +#define PCI_WR_TG_TG_CTRL (5512L) +#define PCI_WR_TG_TG_CTRL_TG_WR_RDY (5513L) +#define PCI_WR_TG_TG_SEQ (5514L) +#define PCI_WR_TG_TG_SEQ_SEQUENCE (5515L) +#define PCI_WR_TG_TG_WRADDR (5516L) +#define PCI_WR_TG_TG_WRADDR_RAM_ADDR (5517L) +#define PCI_WR_TG_TG_WRDATA0 (5518L) +#define PCI_WR_TG_TG_WRDATA0_PHYS_ADDR_LOW (5519L) +#define PCI_WR_TG_TG_WRDATA1 (5520L) +#define PCI_WR_TG_TG_WRDATA1_PHYS_ADDR_HIGH (5521L) +#define PCI_WR_TG_TG_WRDATA2 (5522L) +#define PCI_WR_TG_TG_WRDATA2_INC_MODE (5523L) +#define PCI_WR_TG_TG_WRDATA2_REQ_HID (5524L) +#define PCI_WR_TG_TG_WRDATA2_REQ_SIZE (5525L) +#define PCI_WR_TG_TG_WRDATA2_WAIT (5526L) +#define PCI_WR_TG_TG_WRDATA2_WRAP (5527L) +#define PCI_WR_TG_TG_WR_RUN (5528L) +#define PCI_WR_TG_TG_WR_RUN_WR_ITERATION (5529L) +/* PCM_NT100A01_01 */ +#define PCM_NT100A01_01_CTRL (5530L) +#define PCM_NT100A01_01_CTRL_PTP_CLKSEL (5531L) +#define PCM_NT100A01_01_CTRL_REC_MMCM_RST (5532L) +#define PCM_NT100A01_01_CTRL_TS_CLKSEL (5533L) +#define PCM_NT100A01_01_CTRL_TS_MMCM_RST (5534L) +#define PCM_NT100A01_01_GPIO_I (5535L) +#define PCM_NT100A01_01_GPIO_I_SI5328_C2B (5536L) +#define PCM_NT100A01_01_GPIO_I_SI5328_CS_CA (5537L) +#define PCM_NT100A01_01_GPIO_I_SI5328_INT_C1B (5538L) +#define PCM_NT100A01_01_GPIO_I_SI5328_LOL (5539L) +#define PCM_NT100A01_01_GPIO_O (5540L) +#define PCM_NT100A01_01_GPIO_O_SI5328_CS_CA (5541L) +#define PCM_NT100A01_01_GPIO_O_SI5328_RST_B (5542L) +#define PCM_NT100A01_01_GPIO_T (5543L) +#define PCM_NT100A01_01_GPIO_T_SI5328_CS_CA (5544L) +#define PCM_NT100A01_01_LATCH (5545L) +#define PCM_NT100A01_01_LATCH_REC_MMCM_LOCKED (5546L) +#define PCM_NT100A01_01_LATCH_TCXO_MMCM_LOCKED (5547L) +#define PCM_NT100A01_01_LATCH_TS_MMCM_LOCKED (5548L) +#define PCM_NT100A01_01_STAT (5549L) +#define PCM_NT100A01_01_STAT_REC_MMCM_LOCKED (5550L) +#define PCM_NT100A01_01_STAT_TCXO_MMCM_LOCKED (5551L) +#define PCM_NT100A01_01_STAT_TS_MMCM_LOCKED (5552L) +/* PCM_NT50B01_01 */ +#define PCM_NT50B01_01_CTRL (5553L) +#define PCM_NT50B01_01_CTRL_TS_CLKSEL (5554L) +#define PCM_NT50B01_01_CTRL_TS_MMCM_RST (5555L) +#define PCM_NT50B01_01_LATCH (5556L) +#define PCM_NT50B01_01_LATCH_TS_MMCM_LOCKED (5557L) +#define PCM_NT50B01_01_STAT (5558L) +#define PCM_NT50B01_01_STAT_TS_MMCM_LOCKED (5559L) +/* PCS */ +#define PCS_BER_COUNT (5560L) +#define PCS_BER_COUNT_CNT (5561L) +#define PCS_BIP_COUNT (5562L) +#define PCS_BIP_COUNT_CNT (5563L) +#define PCS_BLOCK_LOCK (5564L) +#define PCS_BLOCK_LOCK_LOCK (5565L) +#define PCS_BLOCK_LOCK_LATCH (5566L) +#define PCS_BLOCK_LOCK_LATCH_LATCH_LOCK (5567L) +#define PCS_BLOCK_LOCK_ST (5568L) +#define PCS_BLOCK_LOCK_ST_LATCH_STATE (5569L) +#define PCS_DDR3_STATUS (5570L) +#define PCS_DDR3_STATUS_CALIB_DONE (5571L) +#define PCS_DRP_CONFIG (5572L) +#define PCS_DRP_CONFIG_DRP_ADR (5573L) +#define PCS_DRP_CONFIG_DRP_DI (5574L) +#define PCS_DRP_CONFIG_DRP_EN (5575L) +#define PCS_DRP_CONFIG_DRP_WREN (5576L) +#define PCS_DRP_DATA (5577L) +#define PCS_DRP_DATA_DRP_DO (5578L) +#define PCS_DRP_DATA_DRP_RDY (5579L) +#define PCS_FSM_DONE (5580L) +#define PCS_FSM_DONE_RX_RST_DONE (5581L) +#define PCS_FSM_DONE_TX_RST_DONE (5582L) +#define PCS_GTH_CONFIG (5583L) +#define PCS_GTH_CONFIG_EYE_SCAN_RST (5584L) +#define PCS_GTH_CONFIG_EYE_SCAN_TRIG (5585L) +#define PCS_GTH_CONFIG_GT_LOOP (5586L) +#define PCS_GTH_CONFIG_GT_LPM_EN (5587L) +#define PCS_GTH_CONFIG_GT_MRST (5588L) +#define PCS_GTH_CONFIG_GT_RX_RST (5589L) +#define PCS_GTH_CONFIG_GT_SOFT_RST (5590L) +#define PCS_GTH_CONFIG_GT_TX_RST (5591L) +#define PCS_GTH_CONFIG_RX_MONITOR_SEL (5592L) +#define PCS_GTH_CONFIG_RX_PCS_RST (5593L) +#define PCS_GTH_CONFIG_RX_USER_RDY (5594L) +#define PCS_GTH_CONFIG_TX_PCS_RST (5595L) +#define PCS_GTH_CONFIG_TX_USER_RDYU (5596L) +#define PCS_GTH_CONTROL (5597L) +#define PCS_GTH_CONTROL_CPLL_LOCK (5598L) +#define PCS_GTH_CONTROL_CPLL_REFCLK_LOST (5599L) +#define PCS_GTH_CONTROL_RX_BUF_RST (5600L) +#define PCS_GTH_TX_TUNING (5601L) +#define PCS_GTH_TX_TUNING_DIFF_CTRL (5602L) +#define PCS_GTH_TX_TUNING_POST_CURSOR (5603L) +#define PCS_GTH_TX_TUNING_PRE_CURSOR (5604L) +#define PCS_LANE_LOCK (5605L) +#define PCS_LANE_LOCK_LOCK (5606L) +#define PCS_LANE_LOCK_LATCH (5607L) +#define PCS_LANE_LOCK_LATCH_LATCH_LOCK (5608L) +#define PCS_LANE_LOCK_ST (5609L) +#define PCS_LANE_LOCK_ST_LATCH_STATE (5610L) +#define PCS_LANE_MAPPING (5611L) +#define PCS_LANE_MAPPING_LANE (5612L) +#define PCS_LANE_OFFSET (5613L) +#define PCS_LANE_OFFSET_DIFF (5614L) +#define PCS_PCS_CONFIG (5615L) +#define PCS_PCS_CONFIG_BER_RST (5616L) +#define PCS_PCS_CONFIG_BIP_RST (5617L) +#define PCS_PCS_CONFIG_LANE_ADDR (5618L) +#define PCS_PCS_CONFIG_LANE_BLOCK_CLR (5619L) +#define PCS_PCS_CONFIG_TIME_OFFSET_RX (5620L) +#define PCS_PCS_CONFIG_TXRX_LOOP (5621L) +#define PCS_PCS_STATUS (5622L) +#define PCS_PCS_STATUS_ALIGN (5623L) +#define PCS_PCS_STATUS_DELAY_ERR (5624L) +#define PCS_PCS_STATUS_FIFO_DELAY (5625L) +#define PCS_PCS_STATUS_HI_BER (5626L) +#define PCS_POLARITY (5627L) +#define PCS_POLARITY_RX_POL (5628L) +#define PCS_POLARITY_TX_POL (5629L) +/* PCS100 */ +#define PCS100_BER_COUNT (5630L) +#define PCS100_BER_COUNT_CNT (5631L) +#define PCS100_BIP_COUNT (5632L) +#define PCS100_BIP_COUNT_CNT (5633L) +#define PCS100_BLOCK_LOCK (5634L) +#define PCS100_BLOCK_LOCK_LOCK (5635L) +#define PCS100_BLOCK_LOCK_LATCH (5636L) +#define PCS100_BLOCK_LOCK_LATCH_LATCH_LOCK (5637L) +#define PCS100_BLOCK_LOCK_ST (5638L) +#define PCS100_BLOCK_LOCK_ST_LATCH_STATE (5639L) +#define PCS100_DDR3_STATUS (5640L) +#define PCS100_DDR3_STATUS_CALIB_DONE (5641L) +#define PCS100_DRP_CONFIG (5642L) +#define PCS100_DRP_CONFIG_DRP_ADR (5643L) +#define PCS100_DRP_CONFIG_DRP_DI (5644L) +#define PCS100_DRP_CONFIG_DRP_EN (5645L) +#define PCS100_DRP_CONFIG_DRP_WREN (5646L) +#define PCS100_DRP_DATA (5647L) +#define PCS100_DRP_DATA_DRP_DO (5648L) +#define PCS100_DRP_DATA_DRP_RDY (5649L) +#define PCS100_FSM_DONE (5650L) +#define PCS100_FSM_DONE_RX_RST_DONE (5651L) +#define PCS100_FSM_DONE_TX_RST_DONE (5652L) +#define PCS100_GTH_CONFIG (5653L) +#define PCS100_GTH_CONFIG_EYE_SCAN_RST (5654L) +#define PCS100_GTH_CONFIG_EYE_SCAN_TRIG (5655L) +#define PCS100_GTH_CONFIG_GT_LOOP (5656L) +#define PCS100_GTH_CONFIG_GT_MRST (5657L) +#define PCS100_GTH_CONFIG_GT_RX_RST (5658L) +#define PCS100_GTH_CONFIG_GT_SOFT_RST (5659L) +#define PCS100_GTH_CONFIG_GT_TX_RST (5660L) +#define PCS100_GTH_CONFIG_RX_MONITOR_SEL (5661L) +#define PCS100_GTH_CONFIG_RX_PCS_RST (5662L) +#define PCS100_GTH_CONFIG_RX_USER_RDY (5663L) +#define PCS100_GTH_CONFIG_TX_PCS_RST (5664L) +#define PCS100_GTH_CONFIG_TX_USER_RDYU (5665L) +#define PCS100_GTH_CONTROL (5666L) +#define PCS100_GTH_CONTROL_CPLL_LOCK (5667L) +#define PCS100_GTH_CONTROL_CPLL_REFCLK_LOST (5668L) +#define PCS100_GTH_CONTROL_QPLL_LOCK (5669L) +#define PCS100_GTH_CONTROL_QPLL_REFCLK_LOST (5670L) +#define PCS100_GTH_CONTROL_RX_BUF_RST (5671L) +#define PCS100_GTH_TX_TUNING (5672L) +#define PCS100_GTH_TX_TUNING_DIFF_CTRL (5673L) +#define PCS100_GTH_TX_TUNING_POST_CURSOR (5674L) +#define PCS100_GTH_TX_TUNING_PRE_CURSOR (5675L) +#define PCS100_LANE_LOCK (5676L) +#define PCS100_LANE_LOCK_LOCK (5677L) +#define PCS100_LANE_LOCK_LATCH (5678L) +#define PCS100_LANE_LOCK_LATCH_LATCH_LOCK (5679L) +#define PCS100_LANE_LOCK_ST (5680L) +#define PCS100_LANE_LOCK_ST_LATCH_STATE (5681L) +#define PCS100_LANE_MAPPING (5682L) +#define PCS100_LANE_MAPPING_LANE (5683L) +#define PCS100_LANE_OFFSET (5684L) +#define PCS100_LANE_OFFSET_DIFF (5685L) +#define PCS100_PCS_CONFIG (5686L) +#define PCS100_PCS_CONFIG_BER_RST (5687L) +#define PCS100_PCS_CONFIG_BIP_RST (5688L) +#define PCS100_PCS_CONFIG_LANE_ADDR (5689L) +#define PCS100_PCS_CONFIG_LANE_BLOCK_CLR (5690L) +#define PCS100_PCS_CONFIG_TIME_OFFSET_RX (5691L) +#define PCS100_PCS_CONFIG_TXRX_LOOP (5692L) +#define PCS100_PCS_STATUS (5693L) +#define PCS100_PCS_STATUS_ALIGN (5694L) +#define PCS100_PCS_STATUS_DELAY_ERR (5695L) +#define PCS100_PCS_STATUS_FIFO_DELAY (5696L) +#define PCS100_PCS_STATUS_HI_BER (5697L) +/* PDB */ +#define PDB_CONFIG (5698L) +#define PDB_CONFIG_PORT_OFS (5699L) +#define PDB_CONFIG_TS_FORMAT (5700L) +#define PDB_RCP_CTRL (5701L) +#define PDB_RCP_CTRL_ADR (5702L) +#define PDB_RCP_CTRL_CNT (5703L) +#define PDB_RCP_DATA (5704L) +#define PDB_RCP_DATA_ALIGN (5705L) +#define PDB_RCP_DATA_CRC_OVERWRITE (5706L) +#define PDB_RCP_DATA_DESCRIPTOR (5707L) +#define PDB_RCP_DATA_DESC_LEN (5708L) +#define PDB_RCP_DATA_DUPLICATE_BIT (5709L) +#define PDB_RCP_DATA_DUPLICATE_EN (5710L) +#define PDB_RCP_DATA_IP_PROT_TNL (5711L) +#define PDB_RCP_DATA_OFS0_DYN (5712L) +#define PDB_RCP_DATA_OFS0_REL (5713L) +#define PDB_RCP_DATA_OFS1_DYN (5714L) +#define PDB_RCP_DATA_OFS1_REL (5715L) +#define PDB_RCP_DATA_OFS2_DYN (5716L) +#define PDB_RCP_DATA_OFS2_REL (5717L) +#define PDB_RCP_DATA_PCAP_KEEP_FCS (5718L) +#define PDB_RCP_DATA_PPC_HSH (5719L) +#define PDB_RCP_DATA_TX_IGNORE (5720L) +#define PDB_RCP_DATA_TX_NOW (5721L) +#define PDB_RCP_DATA_TX_PORT (5722L) +/* PDI */ +#define PDI_CR (5723L) +#define PDI_CR_EN (5724L) +#define PDI_CR_PARITY (5725L) +#define PDI_CR_RST (5726L) +#define PDI_CR_RXRST (5727L) +#define PDI_CR_STOP (5728L) +#define PDI_CR_TXRST (5729L) +#define PDI_DRR (5730L) +#define PDI_DRR_DRR (5731L) +#define PDI_DTR (5732L) +#define PDI_DTR_DTR (5733L) +#define PDI_PRE (5734L) +#define PDI_PRE_PRE (5735L) +#define PDI_SR (5736L) +#define PDI_SR_DISABLE_BUSY (5737L) +#define PDI_SR_DONE (5738L) +#define PDI_SR_ENABLE_BUSY (5739L) +#define PDI_SR_FRAME_ERR (5740L) +#define PDI_SR_OVERRUN_ERR (5741L) +#define PDI_SR_PARITY_ERR (5742L) +#define PDI_SR_RXLVL (5743L) +#define PDI_SR_RX_BUSY (5744L) +#define PDI_SR_TXLVL (5745L) +#define PDI_SR_TX_BUSY (5746L) +#define PDI_SRR (5747L) +#define PDI_SRR_RST (5748L) +/* PHY10G */ +#define PHY10G_CORE_CONF (5749L) +#define PHY10G_CORE_CONF_CLEAR_PCS_LINK_FAULTS (5750L) +#define PHY10G_CORE_CONF_CLEAR_PCS_STATUS2 (5751L) +#define PHY10G_CORE_CONF_CLEAR_PMA_PMD_LINK_FAULTS (5752L) +#define PHY10G_CORE_CONF_CLEAR_TEST_PATT_ERR_COUNT (5753L) +#define PHY10G_CORE_CONF_DATA_PATT_SEL (5754L) +#define PHY10G_CORE_CONF_GLOBAL_TX_DISABLE (5755L) +#define PHY10G_CORE_CONF_NT_FORCE_LINK_DOWN (5756L) +#define PHY10G_CORE_CONF_NT_LINKUP_LATENCY (5757L) +#define PHY10G_CORE_CONF_PCS_LOOPBACK (5758L) +#define PHY10G_CORE_CONF_PCS_RESET (5759L) +#define PHY10G_CORE_CONF_PMA_LOOPBACK (5760L) +#define PHY10G_CORE_CONF_PMA_RESET (5761L) +#define PHY10G_CORE_CONF_PMD_TX_DISABLE (5762L) +#define PHY10G_CORE_CONF_PRBS31_RX_EN (5763L) +#define PHY10G_CORE_CONF_PRBS31_TX_EN (5764L) +#define PHY10G_CORE_CONF_RX_TEST_PATT_EN (5765L) +#define PHY10G_CORE_CONF_SET_PCS_LINK_STATUS (5766L) +#define PHY10G_CORE_CONF_SET_PMA_LINK_STATUS (5767L) +#define PHY10G_CORE_CONF_TEST_PATT_SEL (5768L) +#define PHY10G_CORE_CONF_TX_TEST_PATT_EN (5769L) +#define PHY10G_CORE_STAT (5770L) +#define PHY10G_CORE_STAT_NT_LINK_STATE (5771L) +#define PHY10G_CORE_STAT_PCS_BER_COUNT (5772L) +#define PHY10G_CORE_STAT_PCS_BLOCK_LOCK (5773L) +#define PHY10G_CORE_STAT_PCS_ERR_BLOCK_COUNT (5774L) +#define PHY10G_CORE_STAT_PCS_HIBER (5775L) +#define PHY10G_CORE_STAT_PCS_RESET (5776L) +#define PHY10G_CORE_STAT_PCS_RX_FAULT (5777L) +#define PHY10G_CORE_STAT_PCS_RX_HIBER_LH (5778L) +#define PHY10G_CORE_STAT_PCS_RX_LINK_STATUS (5779L) +#define PHY10G_CORE_STAT_PCS_RX_LOCKED (5780L) +#define PHY10G_CORE_STAT_PCS_RX_LOCKED_LL (5781L) +#define PHY10G_CORE_STAT_PCS_TEST_PATT_ERR_COUNT (5782L) +#define PHY10G_CORE_STAT_PCS_TX_FAULT (5783L) +#define PHY10G_CORE_STAT_PMA_PMD_LINK_STAT (5784L) +#define PHY10G_CORE_STAT_PMA_PMD_RX_FAULT (5785L) +#define PHY10G_CORE_STAT_PMA_PMD_TX_FAULT (5786L) +#define PHY10G_CORE_STAT_PMA_RESET (5787L) +#define PHY10G_CORE_STAT_RX_SIG_DET (5788L) +#define PHY10G_CORE_STAT_TENG_PCS_RX_LINK_STATUS (5789L) +#define PHY10G_CTRL (5790L) +#define PHY10G_CTRL_FORCE_LINK_DOWN (5791L) +#define PHY10G_CTRL_HOST_LOOPBACK (5792L) +#define PHY10G_CTRL_LINE_LOOPBACK (5793L) +#define PHY10G_CTRL_LINKUP_LATENCY (5794L) +#define PHY10G_CTRL_SOFT_RESET (5795L) +#define PHY10G_GPIO (5796L) +#define PHY10G_GPIO_ABS (5797L) +#define PHY10G_GPIO_LED_MODE (5798L) +#define PHY10G_GPIO_LED_MODE_NIM (5799L) +#define PHY10G_GPIO_LED_MODE_PHY (5800L) +#define PHY10G_GPIO_PWR_EN (5801L) +#define PHY10G_GPIO_RX_LOS (5802L) +#define PHY10G_GPIO_TX_FAULT (5803L) +#define PHY10G_GT_CTRL (5804L) +#define PHY10G_GT_CTRL_EYESCANRESET (5805L) +#define PHY10G_GT_CTRL_EYESCANTRIGGER (5806L) +#define PHY10G_GT_CTRL_RXCDRHOLD (5807L) +#define PHY10G_GT_CTRL_RXDFELPMRESET (5808L) +#define PHY10G_GT_CTRL_RXLPMEN (5809L) +#define PHY10G_GT_CTRL_RXPMARESET (5810L) +#define PHY10G_GT_CTRL_RXPRBSENABLE (5811L) +#define PHY10G_GT_CTRL_RXRATE (5812L) +#define PHY10G_GT_CTRL_TXDIFFCTRL (5813L) +#define PHY10G_GT_CTRL_TXPCSRESET (5814L) +#define PHY10G_GT_CTRL_TXPMARESET (5815L) +#define PHY10G_GT_CTRL_TXPOSTCURSOR (5816L) +#define PHY10G_GT_CTRL_TXPRBSENABLE (5817L) +#define PHY10G_GT_CTRL_TXPRBSFORCEERR (5818L) +#define PHY10G_GT_CTRL_TXPRECURSOR (5819L) +#define PHY10G_GT_STAT (5820L) +#define PHY10G_GT_STAT_DMONITOROUT (5821L) +#define PHY10G_GT_STAT_EYESCANDATAERROR (5822L) +#define PHY10G_GT_STAT_RXBUFSTATUS (5823L) +#define PHY10G_GT_STAT_RXPMARESETDONE (5824L) +#define PHY10G_GT_STAT_RXPRBSERR (5825L) +#define PHY10G_GT_STAT_RXPRBSLOCKED (5826L) +#define PHY10G_GT_STAT_RXRESETDONE (5827L) +#define PHY10G_GT_STAT_TXBUFSTATUS (5828L) +#define PHY10G_GT_STAT_TXRESETDONE (5829L) +#define PHY10G_GT_STAT2 (5830L) +#define PHY10G_GT_STAT2_DMONITOR (5831L) +#define PHY10G_GT_STAT2_RXPRBSCNT (5832L) +#define PHY10G_INT (5833L) +#define PHY10G_INT_EN (5834L) +#define PHY10G_INT_MAX_PACE (5835L) +#define PHY10G_LINK_SUMMARY (5836L) +#define PHY10G_LINK_SUMMARY_ABS (5837L) +#define PHY10G_LINK_SUMMARY_CORE_STATUS (5838L) +#define PHY10G_LINK_SUMMARY_LINK_DOWN_CNT (5839L) +#define PHY10G_LINK_SUMMARY_NT_LINK_STATE (5840L) +#define PHY10G_LINK_SUMMARY_RES (5841L) +#define PHY10G_TS_COMP (5842L) +#define PHY10G_TS_COMP_RX (5843L) +/* PHY3S10G */ +#define PHY3S10G_ANEG_ADV_3S (5844L) +#define PHY3S10G_ANEG_ADV_3S_DUPLEX (5845L) +#define PHY3S10G_ANEG_ADV_3S_PAUSE (5846L) +#define PHY3S10G_ANEG_ADV_3S_REMOTE_FAULT (5847L) +#define PHY3S10G_CORE_CONF_10G (5848L) +#define PHY3S10G_CORE_CONF_10G_CLEAR_PCS_LINK_FAULTS (5849L) +#define PHY3S10G_CORE_CONF_10G_CLEAR_PCS_STATUS2 (5850L) +#define PHY3S10G_CORE_CONF_10G_CLEAR_PMA_PMD_LINK_FAULTS (5851L) +#define PHY3S10G_CORE_CONF_10G_PCS_LOOPBACK (5852L) +#define PHY3S10G_CORE_CONF_10G_PCS_RESET (5853L) +#define PHY3S10G_CORE_CONF_10G_PMA_LOOPBACK (5854L) +#define PHY3S10G_CORE_CONF_10G_PMA_RESET (5855L) +#define PHY3S10G_CORE_CONF_10G_SET_PCS_LINK_STATUS (5856L) +#define PHY3S10G_CORE_CONF_10G_SET_PMA_LINK_STATUS (5857L) +#define PHY3S10G_CORE_CONF_3S (5858L) +#define PHY3S10G_CORE_CONF_3S_ANEG_BYPASS_EN (5859L) +#define PHY3S10G_CORE_CONF_3S_ANEG_EN (5860L) +#define PHY3S10G_CORE_CONF_3S_ANEG_RESTART (5861L) +#define PHY3S10G_CORE_CONF_3S_BASEX_OR_SGMII (5862L) +#define PHY3S10G_CORE_CONF_3S_LINK_TIMER_BASEX (5863L) +#define PHY3S10G_CORE_CONF_3S_LOOPBACK_CTRL (5864L) +#define PHY3S10G_CORE_CONF_3S_POWER_DOWN (5865L) +#define PHY3S10G_CORE_CONF_3S_SPEED (5866L) +#define PHY3S10G_CORE_CONF_3S_UNIDIRECT_EN (5867L) +#define PHY3S10G_CORE_STAT_10G (5868L) +#define PHY3S10G_CORE_STAT_10G_NT_LINK_STATE (5869L) +#define PHY3S10G_CORE_STAT_10G_PCS_BER_COUNT (5870L) +#define PHY3S10G_CORE_STAT_10G_PCS_BLOCK_LOCK (5871L) +#define PHY3S10G_CORE_STAT_10G_PCS_ERR_BLOCK_COUNT (5872L) +#define PHY3S10G_CORE_STAT_10G_PCS_HIBER (5873L) +#define PHY3S10G_CORE_STAT_10G_PCS_RX_HIBER_LH (5874L) +#define PHY3S10G_CORE_STAT_10G_PCS_RX_LINK_STATUS (5875L) +#define PHY3S10G_CORE_STAT_10G_PCS_RX_LOCKED (5876L) +#define PHY3S10G_CORE_STAT_10G_PCS_RX_LOCKED_LL (5877L) +#define PHY3S10G_CORE_STAT_10G_PMA_PMD_LINK_STAT (5878L) +#define PHY3S10G_CORE_STAT_10G_RX_SIG_DET (5879L) +#define PHY3S10G_CORE_STAT_10G_TENG_PCS_RX_LINK_STATUS (5880L) +#define PHY3S10G_CORE_STAT_3S (5881L) +#define PHY3S10G_CORE_STAT_3S_ANEG_COMPLETE (5882L) +#define PHY3S10G_CORE_STAT_3S_DUPLEX_MODE (5883L) +#define PHY3S10G_CORE_STAT_3S_LINK_STATUS (5884L) +#define PHY3S10G_CORE_STAT_3S_LINK_SYNC (5885L) +#define PHY3S10G_CORE_STAT_3S_NT_LINK_STATE (5886L) +#define PHY3S10G_CORE_STAT_3S_PAUSE (5887L) +#define PHY3S10G_CORE_STAT_3S_PHY_LINK_STAT (5888L) +#define PHY3S10G_CORE_STAT_3S_REM_FAULT_ENC (5889L) +#define PHY3S10G_CORE_STAT_3S_RESERVED (5890L) +#define PHY3S10G_CORE_STAT_3S_RUDI_C (5891L) +#define PHY3S10G_CORE_STAT_3S_RUDI_I (5892L) +#define PHY3S10G_CORE_STAT_3S_RUDI_INVALID (5893L) +#define PHY3S10G_CORE_STAT_3S_RXDISPERR (5894L) +#define PHY3S10G_CORE_STAT_3S_RXNOTINTABLE (5895L) +#define PHY3S10G_CORE_STAT_3S_SPEED (5896L) +#define PHY3S10G_CTRL (5897L) +#define PHY3S10G_CTRL_FORCE_LINK_DOWN (5898L) +#define PHY3S10G_CTRL_HOST_LOOPBACK_10G (5899L) +#define PHY3S10G_CTRL_HOST_LOOPBACK_3S (5900L) +#define PHY3S10G_CTRL_LINE_LOOPBACK_10G (5901L) +#define PHY3S10G_CTRL_LINE_LOOPBACK_3S (5902L) +#define PHY3S10G_CTRL_LINKUP_LATENCY (5903L) +#define PHY3S10G_CTRL_PHY_CHANGE_FSM_DONE (5904L) +#define PHY3S10G_CTRL_PHY_SEL (5905L) +#define PHY3S10G_CTRL_SOFT_RESET (5906L) +#define PHY3S10G_GPIO (5907L) +#define PHY3S10G_GPIO_ABS (5908L) +#define PHY3S10G_GPIO_LED_MODE (5909L) +#define PHY3S10G_GPIO_RATE_SEL (5910L) +#define PHY3S10G_GPIO_RX_LOS (5911L) +#define PHY3S10G_GPIO_TX_DISABLE (5912L) +#define PHY3S10G_GPIO_TX_FAULT (5913L) +#define PHY3S10G_GT_CR (5914L) +#define PHY3S10G_GT_CR_EYESCANRESET (5915L) +#define PHY3S10G_GT_CR_EYESCANTRIGGER (5916L) +#define PHY3S10G_GT_CR_LOOPBACK (5917L) +#define PHY3S10G_GT_CR_RXCDRHOLD (5918L) +#define PHY3S10G_GT_CR_RXDFELPMRESET (5919L) +#define PHY3S10G_GT_CR_RXLPMEN (5920L) +#define PHY3S10G_GT_CR_RXPMARESET (5921L) +#define PHY3S10G_GT_CR_RXPRBSCNTRESET (5922L) +#define PHY3S10G_GT_CR_RXPRBSSEL (5923L) +#define PHY3S10G_GT_CR_TXDIFFCTRL (5924L) +#define PHY3S10G_GT_CR_TXPMARESET (5925L) +#define PHY3S10G_GT_CR_TXPOSTCURSOR (5926L) +#define PHY3S10G_GT_CR_TXPRBSFORCEERR (5927L) +#define PHY3S10G_GT_CR_TXPRBSSEL (5928L) +#define PHY3S10G_GT_CR_TXPRECURSOR (5929L) +#define PHY3S10G_GT_SR (5930L) +#define PHY3S10G_GT_SR_EYESCANDATAERROR (5931L) +#define PHY3S10G_GT_SR_RXBUFSTATUS (5932L) +#define PHY3S10G_GT_SR_RXPMARESETDONE (5933L) +#define PHY3S10G_GT_SR_RXPRBSERR (5934L) +#define PHY3S10G_GT_SR_RXRESETDONE (5935L) +#define PHY3S10G_GT_SR_TXBUFSTATUS (5936L) +#define PHY3S10G_GT_SR_TXRESETDONE (5937L) +#define PHY3S10G_INT (5938L) +#define PHY3S10G_INT_EN (5939L) +#define PHY3S10G_INT_MAX_PACE (5940L) +#define PHY3S10G_LINK_SUMMARY (5941L) +#define PHY3S10G_LINK_SUMMARY_ABS (5942L) +#define PHY3S10G_LINK_SUMMARY_ANEG_BYPASS (5943L) +#define PHY3S10G_LINK_SUMMARY_LINK_DOWN_CNT (5944L) +#define PHY3S10G_LINK_SUMMARY_NT_LINK_STATE (5945L) +#define PHY3S10G_TS_COMP (5946L) +#define PHY3S10G_TS_COMP_RX (5947L) +#define PHY3S10G_TS_COMP_RX_10G (5948L) +#define PHY3S10G_TS_COMP_RX_3S (5949L) +/* PM */ +#define PM_CTRL (5950L) +#define PM_CTRL_SW_CLEAN_DONE (5951L) +#define PM_DEBUG_RP (5952L) +#define PM_DEBUG_RP_RP (5953L) +#define PM_DEBUG_RP_SETUP (5954L) +#define PM_DEBUG_RP_SETUP_HB (5955L) +#define PM_DEBUG_RX_BLOCK (5956L) +#define PM_DEBUG_RX_BLOCK_MASK (5957L) +#define PM_HB_SIZE_RX_MEM_CTRL (5958L) +#define PM_HB_SIZE_RX_MEM_CTRL_A (5959L) +#define PM_HB_SIZE_RX_MEM_CTRL_CNT (5960L) +#define PM_HB_SIZE_RX_MEM_DATA (5961L) +#define PM_HB_SIZE_RX_MEM_DATA_SIZE (5962L) +#define PM_HB_SIZE_RX_THRESHOLD (5963L) +#define PM_HB_SIZE_RX_THRESHOLD_D (5964L) +#define PM_HB_SIZE_TX_THRESHOLD (5965L) +#define PM_HB_SIZE_TX_THRESHOLD_D (5966L) +#define PM_PBI_MEM_CTRL (5967L) +#define PM_PBI_MEM_CTRL_A (5968L) +#define PM_PBI_MEM_CTRL_CNT (5969L) +#define PM_PBI_MEM_DATA (5970L) +#define PM_PBI_MEM_DATA_PHYADDR (5971L) +#define PM_PBI_MEM_DATA_SIZE (5972L) +#define PM_POINTER_BANKS (5973L) +#define PM_POINTER_BANKS_D (5974L) +#define PM_RXTX_FAST_MEM_CTRL (5975L) +#define PM_RXTX_FAST_MEM_CTRL_A (5976L) +#define PM_RXTX_FAST_MEM_CTRL_CNT (5977L) +#define PM_RXTX_FAST_MEM_DATA (5978L) +#define PM_RXTX_FAST_MEM_DATA_BANK (5979L) +#define PM_RXTX_FAST_MEM_DATA_ENTRY (5980L) +#define PM_RXTX_FAST_MEM_DATA_HOST_BUFFER (5981L) +#define PM_RXTX_FAST_MEM_DATA_RX_TX (5982L) +#define PM_RXTX_FAST_MEM_DATA_VLD (5983L) +#define PM_RXTX_SLOW_MEM_CTRL (5984L) +#define PM_RXTX_SLOW_MEM_CTRL_A (5985L) +#define PM_RXTX_SLOW_MEM_CTRL_CNT (5986L) +#define PM_RXTX_SLOW_MEM_DATA (5987L) +#define PM_RXTX_SLOW_MEM_DATA_BANK (5988L) +#define PM_RXTX_SLOW_MEM_DATA_ENTRY (5989L) +#define PM_RXTX_SLOW_MEM_DATA_HOST_BUFFER (5990L) +#define PM_RXTX_SLOW_MEM_DATA_RX_TX (5991L) +#define PM_RXTX_SLOW_MEM_DATA_VLD (5992L) +#define PM_RXWP_MEM_CTRL (5993L) +#define PM_RXWP_MEM_CTRL_A (5994L) +#define PM_RXWP_MEM_CTRL_CNT (5995L) +#define PM_RXWP_MEM_DATA (5996L) +#define PM_RXWP_MEM_DATA_BANK (5997L) +#define PM_RXWP_MEM_DATA_ENTRY (5998L) +#define PM_RXWP_MEM_DATA_HOST_BUFFER (5999L) +#define PM_RXWP_MEM_DATA_VLD (6000L) +#define PM_RX_BLOCKED_STATUS (6001L) +#define PM_RX_BLOCKED_STATUS_D (6002L) +#define PM_RX_BLOCKED_STATUS_HI (6003L) +#define PM_RX_BLOCKED_STATUS_HI_D (6004L) +#define PM_RX_OVERFLOW_STATUS (6005L) +#define PM_RX_OVERFLOW_STATUS_D (6006L) +#define PM_RX_READER (6007L) +#define PM_RX_READER_MASK (6008L) +#define PM_RX_TX_FAST_POINTER_BLOCK_INTERVAL (6009L) +#define PM_RX_TX_FAST_POINTER_BLOCK_INTERVAL_D (6010L) +#define PM_RX_TX_SLOW_POINTER_BLOCK_INTERVAL (6011L) +#define PM_RX_TX_SLOW_POINTER_BLOCK_INTERVAL_D (6012L) +#define PM_RX_WRITE_POINTER_BLOCK_INTERVAL (6013L) +#define PM_RX_WRITE_POINTER_BLOCK_INTERVAL_D (6014L) +#define PM_TXRP_MEM_CTRL (6015L) +#define PM_TXRP_MEM_CTRL_A (6016L) +#define PM_TXRP_MEM_CTRL_CNT (6017L) +#define PM_TXRP_MEM_DATA (6018L) +#define PM_TXRP_MEM_DATA_BANK (6019L) +#define PM_TXRP_MEM_DATA_ENTRY (6020L) +#define PM_TXRP_MEM_DATA_HOST_BUFFER (6021L) +#define PM_TXRP_MEM_DATA_VLD (6022L) +#define PM_TX_READ_POINTER_BLOCK_INTERVAL (6023L) +#define PM_TX_READ_POINTER_BLOCK_INTERVAL_D (6024L) +/* PRM_NT100A01_01 */ +#define PRM_NT100A01_01_POWER (6025L) +#define PRM_NT100A01_01_POWER_PU_NSEB (6026L) +#define PRM_NT100A01_01_POWER_PU_PHY (6027L) +#define PRM_NT100A01_01_RST (6028L) +#define PRM_NT100A01_01_RST_PERIPH (6029L) +#define PRM_NT100A01_01_RST_PLATFORM (6030L) +/* PRM_NT50B01_01 */ +#define PRM_NT50B01_01_POWER (6031L) +#define PRM_NT50B01_01_POWER_PU_NSEB (6032L) +#define PRM_NT50B01_01_POWER_PU_PHY (6033L) +#define PRM_NT50B01_01_RST (6034L) +#define PRM_NT50B01_01_RST_PERIPH (6035L) +#define PRM_NT50B01_01_RST_PLATFORM (6036L) +/* PTP1588 */ +#define PTP1588_CONF (6037L) +#define PTP1588_CONF_MII_RX_TX_LOOP (6038L) +#define PTP1588_CONF_MII_TX_RX_LOOP (6039L) +#define PTP1588_CONF_PHY_RST (6040L) +#define PTP1588_CONF_PHY_RST1 (6041L) +#define PTP1588_CONF_PHY_RST2 (6042L) +#define PTP1588_CONF_PTP_CTRL_LOCAL (6043L) +#define PTP1588_CONF_PTP_RX_CTRL (6044L) +#define PTP1588_CONF_PTP_TX_CTRL (6045L) +#define PTP1588_CONF_PTP_TX_CTRL_OS (6046L) +#define PTP1588_CONF_RX_IGNORE_DEST_ADDR (6047L) +#define PTP1588_CONF_TG_CMD (6048L) +#define PTP1588_CONF_TG_MODE (6049L) +#define PTP1588_CONF_TSM_MI_ACK (6050L) +#define PTP1588_CONF_TSM_MI_BUSY (6051L) +#define PTP1588_CONF_TSM_MI_ENA (6052L) +#define PTP1588_CONF_TSM_MI_REQ (6053L) +#define PTP1588_CONF_TX_IFG (6054L) +#define PTP1588_CONF_TX_IGNORE_DEST_ADDR (6055L) +#define PTP1588_CTRL (6056L) +#define PTP1588_CTRL_CLK_ENABLE (6057L) +#define PTP1588_CTRL_MII_RX_TX_LOOP (6058L) +#define PTP1588_CTRL_MII_TX_RX_LOOP (6059L) +#define PTP1588_CTRL_PRESENT (6060L) +#define PTP1588_CTRL_RESET_N (6061L) +#define PTP1588_CTRL_TS_MI_ACK (6062L) +#define PTP1588_CTRL_TS_MI_BUSY (6063L) +#define PTP1588_CTRL_TS_MI_ENA (6064L) +#define PTP1588_CTRL_TS_MI_REQ (6065L) +#define PTP1588_CTRL_TX_IFG (6066L) +#define PTP1588_GP_DATA (6067L) +#define PTP1588_GP_DATA_GPIO (6068L) +#define PTP1588_GP_DATA_PWRDOWN_INTN (6069L) +#define PTP1588_GP_DATA_TIMESYNC_CON (6070L) +#define PTP1588_GP_DATA_LH (6071L) +#define PTP1588_GP_DATA_LH_GPIO (6072L) +#define PTP1588_GP_DATA_LH_PWRDOWN_INTN (6073L) +#define PTP1588_GP_DATA_LH_TIMESYNC_CON (6074L) +#define PTP1588_GP_DATA_LL (6075L) +#define PTP1588_GP_DATA_LL_GPIO (6076L) +#define PTP1588_GP_DATA_LL_PWRDOWN_INTN (6077L) +#define PTP1588_GP_DATA_LL_TIMESYNC_CON (6078L) +#define PTP1588_GP_OE (6079L) +#define PTP1588_GP_OE_GPIO (6080L) +#define PTP1588_GP_OE_PWRDOWN_INTN (6081L) +#define PTP1588_GP_OE_TIMESYNC_CON (6082L) +#define PTP1588_MAC_HOST_ADDR (6083L) +#define PTP1588_MAC_HOST_ADDR_ADDR (6084L) +#define PTP1588_MAC_HOST_ADDR_MDIO_ACCESS (6085L) +#define PTP1588_MAC_HOST_ADDR_OPCODE (6086L) +#define PTP1588_MAC_HOST_ADDR_RDY (6087L) +#define PTP1588_MAC_HOST_DATA_LSB (6088L) +#define PTP1588_MAC_HOST_DATA_LSB_DATA (6089L) +#define PTP1588_MAC_HOST_DATA_MSB (6090L) +#define PTP1588_MAC_HOST_DATA_MSB_DATA (6091L) +#define PTP1588_MAC_INBAND_STAT (6092L) +#define PTP1588_MAC_INBAND_STAT_DUPLEX (6093L) +#define PTP1588_MAC_INBAND_STAT_LINK (6094L) +#define PTP1588_MAC_INBAND_STAT_SPEED (6095L) +#define PTP1588_MAC_MI_CONF (6096L) +#define PTP1588_MAC_MI_CONF_ACCESS_TYPE (6097L) +#define PTP1588_MAC_MI_CONF_ADDRESS (6098L) +#define PTP1588_MAC_MI_CONF_RDY (6099L) +#define PTP1588_MAC_MI_DATA (6100L) +#define PTP1588_MAC_MI_DATA_DATA (6101L) +#define PTP1588_RX_HOST_ADR_LSB (6102L) +#define PTP1588_RX_HOST_ADR_LSB_LSB (6103L) +#define PTP1588_RX_HOST_ADR_MSB (6104L) +#define PTP1588_RX_HOST_ADR_MSB_MSB (6105L) +#define PTP1588_RX_HOST_CONF (6106L) +#define PTP1588_RX_HOST_CONF_ENA (6107L) +#define PTP1588_RX_HOST_CONF_RDPTR (6108L) +#define PTP1588_RX_HOST_CONF_REDUCED (6109L) +#define PTP1588_RX_HOST_CTRL (6110L) +#define PTP1588_RX_HOST_CTRL_ENA (6111L) +#define PTP1588_RX_HOST_CTRL_RDPTR (6112L) +#define PTP1588_RX_HOST_CTRL_REDUCED (6113L) +#define PTP1588_STAT (6114L) +#define PTP1588_STAT_DATA (6115L) +#define PTP1588_STAT_CONF (6116L) +#define PTP1588_STAT_CONF_INDEX (6117L) +#define PTP1588_STAT_CONF_LOCK (6118L) +#define PTP1588_STAT_CTRL (6119L) +#define PTP1588_STAT_CTRL_INDEX (6120L) +#define PTP1588_STAT_CTRL_LOCK (6121L) +#define PTP1588_TX_FIRST_DAT (6122L) +#define PTP1588_TX_FIRST_DAT_DAT (6123L) +#define PTP1588_TX_LAST1_DAT (6124L) +#define PTP1588_TX_LAST1_DAT_DAT (6125L) +#define PTP1588_TX_LAST2_DAT (6126L) +#define PTP1588_TX_LAST2_DAT_DAT (6127L) +#define PTP1588_TX_LAST3_DAT (6128L) +#define PTP1588_TX_LAST3_DAT_DAT (6129L) +#define PTP1588_TX_LAST4_DAT (6130L) +#define PTP1588_TX_LAST4_DAT_DAT (6131L) +#define PTP1588_TX_MID_DAT (6132L) +#define PTP1588_TX_MID_DAT_DAT (6133L) +#define PTP1588_TX_PACKET_STATE (6134L) +#define PTP1588_TX_PACKET_STATE_MSG_TYPE (6135L) +#define PTP1588_TX_PACKET_STATE_PCK_TYPE (6136L) +#define PTP1588_TX_PACKET_STATE_SEQ_ID (6137L) +#define PTP1588_TX_PACKET_STATE_TEST_MARGIN (6138L) +#define PTP1588_TX_PACKET_STATE_VALID (6139L) +#define PTP1588_TX_STATUS (6140L) +#define PTP1588_TX_STATUS_DB_ERR (6141L) +#define PTP1588_TX_STATUS_DB_FULL (6142L) +#define PTP1588_TX_STATUS_FIFO_STATUS (6143L) +#define PTP1588_TX_STATUS_RDY (6144L) +#define PTP1588_TX_STATUS_TG_ENA (6145L) +#define PTP1588_TX_STATUS_TG_MODE (6146L) +#define PTP1588_TX_TIMESTAMP_NS (6147L) +#define PTP1588_TX_TIMESTAMP_NS_TIMESTAMP (6148L) +#define PTP1588_TX_TIMESTAMP_SEC (6149L) +#define PTP1588_TX_TIMESTAMP_SEC_TIMESTAMP (6150L) +/* QM */ +#define QM_BLOCK_SIZE (6151L) +#define QM_BLOCK_SIZE_CELLS (6152L) +#define QM_CTRL (6153L) +#define QM_CTRL_ACTIVE_QUEUES (6154L) +#define QM_CTRL_ACTIVE_QUEUES_QPI_BYPASS (6155L) +#define QM_CTRL_ENABLE (6156L) +#define QM_CTRL_PRIORITY_SCHEME (6157L) +#define QM_DEBUG_BLOCK_SIZE (6158L) +#define QM_DEBUG_BLOCK_SIZE_CELLS (6159L) +#define QM_DEBUG_CRC (6160L) +#define QM_DEBUG_CRC_FORCE_ERROR (6161L) +#define QM_DEBUG_SDRAM_SIZE (6162L) +#define QM_DEBUG_SDRAM_SIZE_MASK (6163L) +#define QM_GROUP_LIMIT_MEM_CTRL (6164L) +#define QM_GROUP_LIMIT_MEM_CTRL_A (6165L) +#define QM_GROUP_LIMIT_MEM_CTRL_CNT (6166L) +#define QM_GROUP_LIMIT_MEM_DATA (6167L) +#define QM_GROUP_LIMIT_MEM_DATA_LIMIT (6168L) +#define QM_GROUP_MAPPING_MEM_CTRL (6169L) +#define QM_GROUP_MAPPING_MEM_CTRL_A (6170L) +#define QM_GROUP_MAPPING_MEM_CTRL_CNT (6171L) +#define QM_GROUP_MAPPING_MEM_DATA (6172L) +#define QM_GROUP_MAPPING_MEM_DATA_GROUP0 (6173L) +#define QM_GROUP_MAPPING_MEM_DATA_GROUP1 (6174L) +#define QM_GROUP_MAPPING_MEM_DATA_GROUP2 (6175L) +#define QM_PRIO_LEVELS_MEM_CTRL (6176L) +#define QM_PRIO_LEVELS_MEM_CTRL_A (6177L) +#define QM_PRIO_LEVELS_MEM_CTRL_CNT (6178L) +#define QM_PRIO_LEVELS_MEM_DATA (6179L) +#define QM_PRIO_LEVELS_MEM_DATA_PRIO (6180L) +#define QM_QUEUE_LIMIT_MEM_CTRL (6181L) +#define QM_QUEUE_LIMIT_MEM_CTRL_A (6182L) +#define QM_QUEUE_LIMIT_MEM_CTRL_CNT (6183L) +#define QM_QUEUE_LIMIT_MEM_DATA (6184L) +#define QM_QUEUE_LIMIT_MEM_DATA_LIMIT (6185L) +#define QM_STATUS_BLOCKED (6186L) +#define QM_STATUS_BLOCKED_D (6187L) +#define QM_STATUS_BLOCKED_HI (6188L) +#define QM_STATUS_BLOCKED_HI_D (6189L) +#define QM_STATUS_BLOCKING (6190L) +#define QM_STATUS_BLOCKING_D (6191L) +#define QM_STATUS_BLOCKING_HI (6192L) +#define QM_STATUS_BLOCKING_HI_D (6193L) +#define QM_STATUS_CRC_ERROR (6194L) +#define QM_STATUS_CRC_ERROR_CNT (6195L) +#define QM_STATUS_EMPTY (6196L) +#define QM_STATUS_EMPTY_D (6197L) +#define QM_STATUS_EMPTY_HI (6198L) +#define QM_STATUS_EMPTY_HI_D (6199L) +#define QM_STATUS_FLUSH_DROP (6200L) +#define QM_STATUS_FLUSH_DROP_CNT (6201L) +#define QM_STATUS_SDRAM_BLOCK_MAX_USAGE (6202L) +#define QM_STATUS_SDRAM_BLOCK_MAX_USAGE_D (6203L) +#define QM_STATUS_SDRAM_BLOCK_USAGE (6204L) +#define QM_STATUS_SDRAM_BLOCK_USAGE_D (6205L) +#define QM_STATUS_SDRAM_CELL_MAX_USAGE (6206L) +#define QM_STATUS_SDRAM_CELL_MAX_USAGE_D (6207L) +#define QM_STATUS_SDRAM_CELL_USAGE (6208L) +#define QM_STATUS_SDRAM_CELL_USAGE_D (6209L) +/* QSL */ +#define QSL_LTX_CTRL (6210L) +#define QSL_LTX_CTRL_ADR (6211L) +#define QSL_LTX_CTRL_CNT (6212L) +#define QSL_LTX_DATA (6213L) +#define QSL_LTX_DATA_LR (6214L) +#define QSL_LTX_DATA_TSA (6215L) +#define QSL_LTX_DATA_TX_PORT (6216L) +#define QSL_QEN_CTRL (6217L) +#define QSL_QEN_CTRL_ADR (6218L) +#define QSL_QEN_CTRL_CNT (6219L) +#define QSL_QEN_DATA (6220L) +#define QSL_QEN_DATA_EN (6221L) +#define QSL_QST_CTRL (6222L) +#define QSL_QST_CTRL_ADR (6223L) +#define QSL_QST_CTRL_CNT (6224L) +#define QSL_QST_DATA (6225L) +#define QSL_QST_DATA_EN (6226L) +#define QSL_QST_DATA_LRE (6227L) +#define QSL_QST_DATA_QEN (6228L) +#define QSL_QST_DATA_QUEUE (6229L) +#define QSL_QST_DATA_TCI (6230L) +#define QSL_QST_DATA_TX_PORT (6231L) +#define QSL_QST_DATA_VEN (6232L) +#define QSL_RCP_CTRL (6233L) +#define QSL_RCP_CTRL_ADR (6234L) +#define QSL_RCP_CTRL_CNT (6235L) +#define QSL_RCP_DATA (6236L) +#define QSL_RCP_DATA_CAO (6237L) +#define QSL_RCP_DATA_DISCARD (6238L) +#define QSL_RCP_DATA_DROP (6239L) +#define QSL_RCP_DATA_LR (6240L) +#define QSL_RCP_DATA_TBL_HI (6241L) +#define QSL_RCP_DATA_TBL_IDX (6242L) +#define QSL_RCP_DATA_TBL_LO (6243L) +#define QSL_RCP_DATA_TBL_MSK (6244L) +#define QSL_RCP_DATA_TSA (6245L) +#define QSL_RCP_DATA_VLI (6246L) +#define QSL_UNMQ_CTRL (6247L) +#define QSL_UNMQ_CTRL_ADR (6248L) +#define QSL_UNMQ_CTRL_CNT (6249L) +#define QSL_UNMQ_DATA (6250L) +#define QSL_UNMQ_DATA_DEST_QUEUE (6251L) +#define QSL_UNMQ_DATA_EN (6252L) +/* QSPI */ +#define QSPI_CR (6253L) +#define QSPI_CR_CPHA (6254L) +#define QSPI_CR_CPOL (6255L) +#define QSPI_CR_LOOP (6256L) +#define QSPI_CR_LSBF (6257L) +#define QSPI_CR_MSSAE (6258L) +#define QSPI_CR_MST (6259L) +#define QSPI_CR_MTI (6260L) +#define QSPI_CR_RXFIFO_RST (6261L) +#define QSPI_CR_SPE (6262L) +#define QSPI_CR_TXFIFO_RST (6263L) +#define QSPI_DGIE (6264L) +#define QSPI_DGIE_GIE (6265L) +#define QSPI_DRR (6266L) +#define QSPI_DRR_DATA_VAL (6267L) +#define QSPI_DTR (6268L) +#define QSPI_DTR_DATA_VAL (6269L) +#define QSPI_IER (6270L) +#define QSPI_IER_CMD_ERR (6271L) +#define QSPI_IER_CPOL_CPHA_ERR (6272L) +#define QSPI_IER_DRR_FULL (6273L) +#define QSPI_IER_DRR_NEMPTY (6274L) +#define QSPI_IER_DRR_OR (6275L) +#define QSPI_IER_DTR_EMPTY (6276L) +#define QSPI_IER_DTR_UR (6277L) +#define QSPI_IER_LOOP_ERR (6278L) +#define QSPI_IER_MODF (6279L) +#define QSPI_IER_MSB_ERR (6280L) +#define QSPI_IER_SLV_ERR (6281L) +#define QSPI_IER_SLV_MODF (6282L) +#define QSPI_IER_SLV_MS (6283L) +#define QSPI_IER_TXFIFO_HEMPTY (6284L) +#define QSPI_ISR (6285L) +#define QSPI_ISR_CMD_ERR (6286L) +#define QSPI_ISR_CPOL_CPHA_ERR (6287L) +#define QSPI_ISR_DRR_FULL (6288L) +#define QSPI_ISR_DRR_NEMPTY (6289L) +#define QSPI_ISR_DRR_OR (6290L) +#define QSPI_ISR_DTR_EMPTY (6291L) +#define QSPI_ISR_DTR_UR (6292L) +#define QSPI_ISR_LOOP_ERR (6293L) +#define QSPI_ISR_MODF (6294L) +#define QSPI_ISR_MSB_ERR (6295L) +#define QSPI_ISR_SLV_ERR (6296L) +#define QSPI_ISR_SLV_MODF (6297L) +#define QSPI_ISR_SLV_MS (6298L) +#define QSPI_ISR_TXFIFO_HEMPTY (6299L) +#define QSPI_RX_FIFO_OCY (6300L) +#define QSPI_RX_FIFO_OCY_OCY_VAL (6301L) +#define QSPI_SR (6302L) +#define QSPI_SR_CMD_ERR (6303L) +#define QSPI_SR_CPOL_CPHA_ERR (6304L) +#define QSPI_SR_LOOP_ERR (6305L) +#define QSPI_SR_MODF (6306L) +#define QSPI_SR_MSB_ERR (6307L) +#define QSPI_SR_RXEMPTY (6308L) +#define QSPI_SR_RXFULL (6309L) +#define QSPI_SR_SLVMS (6310L) +#define QSPI_SR_SLV_ERR (6311L) +#define QSPI_SR_TXEMPTY (6312L) +#define QSPI_SR_TXFULL (6313L) +#define QSPI_SRR (6314L) +#define QSPI_SRR_RST (6315L) +#define QSPI_SSR (6316L) +#define QSPI_SSR_SEL_SLV (6317L) +#define QSPI_TX_FIFO_OCY (6318L) +#define QSPI_TX_FIFO_OCY_OCY_VAL (6319L) +/* R2DRP */ +#define R2DRP_CTRL (6320L) +#define R2DRP_CTRL_ADR (6321L) +#define R2DRP_CTRL_DATA (6322L) +#define R2DRP_CTRL_DBG_BUSY (6323L) +#define R2DRP_CTRL_DONE (6324L) +#define R2DRP_CTRL_RES (6325L) +#define R2DRP_CTRL_WREN (6326L) +/* RAC */ +#define RAC_DBG_CTRL (6327L) +#define RAC_DBG_CTRL_C (6328L) +#define RAC_DBG_DATA (6329L) +#define RAC_DBG_DATA_D (6330L) +#define RAC_DUMMY0 (6331L) +#define RAC_DUMMY1 (6332L) +#define RAC_DUMMY2 (6333L) +#define RAC_NDM_REGISTER (6334L) +#define RAC_NDM_REGISTER_NDM (6335L) +#define RAC_NMB_DATA (6336L) +#define RAC_NMB_DATA_NMB_DATA (6337L) +#define RAC_NMB_RD_ADR (6338L) +#define RAC_NMB_RD_ADR_ADR (6339L) +#define RAC_NMB_RD_ADR_RES (6340L) +#define RAC_NMB_STATUS (6341L) +#define RAC_NMB_STATUS_BUS_TIMEOUT (6342L) +#define RAC_NMB_STATUS_NMB_READY (6343L) +#define RAC_NMB_WR_ADR (6344L) +#define RAC_NMB_WR_ADR_ADR (6345L) +#define RAC_NMB_WR_ADR_RES (6346L) +#define RAC_RAB_BUF_FREE (6347L) +#define RAC_RAB_BUF_FREE_IB_FREE (6348L) +#define RAC_RAB_BUF_FREE_IB_OVF (6349L) +#define RAC_RAB_BUF_FREE_OB_FREE (6350L) +#define RAC_RAB_BUF_FREE_OB_OVF (6351L) +#define RAC_RAB_BUF_FREE_TIMEOUT (6352L) +#define RAC_RAB_BUF_USED (6353L) +#define RAC_RAB_BUF_USED_FLUSH (6354L) +#define RAC_RAB_BUF_USED_IB_USED (6355L) +#define RAC_RAB_BUF_USED_OB_USED (6356L) +#define RAC_RAB_DMA_IB_HI (6357L) +#define RAC_RAB_DMA_IB_HI_PHYADDR (6358L) +#define RAC_RAB_DMA_IB_LO (6359L) +#define RAC_RAB_DMA_IB_LO_PHYADDR (6360L) +#define RAC_RAB_DMA_IB_RD (6361L) +#define RAC_RAB_DMA_IB_RD_PTR (6362L) +#define RAC_RAB_DMA_IB_WR (6363L) +#define RAC_RAB_DMA_IB_WR_PTR (6364L) +#define RAC_RAB_DMA_OB_HI (6365L) +#define RAC_RAB_DMA_OB_HI_PHYADDR (6366L) +#define RAC_RAB_DMA_OB_LO (6367L) +#define RAC_RAB_DMA_OB_LO_PHYADDR (6368L) +#define RAC_RAB_DMA_OB_WR (6369L) +#define RAC_RAB_DMA_OB_WR_PTR (6370L) +#define RAC_RAB_IB_DATA (6371L) +#define RAC_RAB_IB_DATA_D (6372L) +#define RAC_RAB_INIT (6373L) +#define RAC_RAB_INIT_RAB (6374L) +#define RAC_RAB_OB_DATA (6375L) +#define RAC_RAB_OB_DATA_D (6376L) +/* RBH */ +#define RBH_CTRL (6377L) +#define RBH_CTRL_ENABLE_METADATA_HB (6378L) +#define RBH_CTRL_ENABLE_PM (6379L) +#define RBH_CTRL_ENABLE_QHM (6380L) +#define RBH_CTRL_HB_MAX (6381L) +#define RBH_CTRL_HB_SEGMENT_SIZE (6382L) +#define RBH_CTRL_RESERVED (6383L) +#define RBH_CTRL_RESET_CREDITS_QHM (6384L) +#define RBH_DEB_REG1 (6385L) +#define RBH_DEB_REG1_VALUE (6386L) +#define RBH_DEB_REG2 (6387L) +#define RBH_DEB_REG2_VALUE (6388L) +#define RBH_DEB_REG3 (6389L) +#define RBH_DEB_REG3_VALUE (6390L) +#define RBH_FLUSH_ADR_HI (6391L) +#define RBH_FLUSH_ADR_HI_VALUE (6392L) +#define RBH_FLUSH_ADR_LO (6393L) +#define RBH_FLUSH_ADR_LO_VALUE (6394L) +#define RBH_HOST_BUF_SIZE_MEM_CTRL (6395L) +#define RBH_HOST_BUF_SIZE_MEM_CTRL_A (6396L) +#define RBH_HOST_BUF_SIZE_MEM_CTRL_CNT (6397L) +#define RBH_HOST_BUF_SIZE_MEM_DATA (6398L) +#define RBH_HOST_BUF_SIZE_MEM_DATA_HB_SEGMENT_CNT (6399L) +#define RBH_STATUS (6400L) +#define RBH_STATUS_BUFFER_EMPTY (6401L) +#define RBH_STATUS_DWA_DATAFIFO_EMPTY (6402L) +#define RBH_STATUS_PWA_DATAFIFO_EMPTY (6403L) +#define RBH_WP_SET_MEM_CTRL (6404L) +#define RBH_WP_SET_MEM_CTRL_A (6405L) +#define RBH_WP_SET_MEM_CTRL_CNT (6406L) +#define RBH_WP_SET_MEM_DATA (6407L) +#define RBH_WP_SET_MEM_DATA_WP (6408L) +/* RFD */ +#define RFD_CTRL (6409L) +#define RFD_CTRL_CFP (6410L) +#define RFD_CTRL_ISL (6411L) +#define RFD_CTRL_PWMCW (6412L) +#define RFD_MAX_FRAME_SIZE (6413L) +#define RFD_MAX_FRAME_SIZE_MAX (6414L) +#define RFD_TNL_VLAN (6415L) +#define RFD_TNL_VLAN_TPID0 (6416L) +#define RFD_TNL_VLAN_TPID1 (6417L) +#define RFD_VLAN (6418L) +#define RFD_VLAN_TPID0 (6419L) +#define RFD_VLAN_TPID1 (6420L) +#define RFD_VXLAN (6421L) +#define RFD_VXLAN_DP0 (6422L) +#define RFD_VXLAN_DP1 (6423L) +/* RMC */ +#define RMC_CTRL (6424L) +#define RMC_CTRL_BLOCK_KEEPA (6425L) +#define RMC_CTRL_BLOCK_MAC_PORT (6426L) +#define RMC_CTRL_BLOCK_RPP_SLICE (6427L) +#define RMC_CTRL_BLOCK_STATT (6428L) +#define RMC_CTRL_LAG_PHY_ODD_EVEN (6429L) +#define RMC_DBG (6430L) +#define RMC_DBG_MERGE (6431L) +#define RMC_MAC_IF (6432L) +#define RMC_MAC_IF_ERR (6433L) +#define RMC_STATUS (6434L) +#define RMC_STATUS_DESCR_FIFO_OF (6435L) +#define RMC_STATUS_SF_RAM_OF (6436L) +/* RNTC */ +#define RNTC_CTRL (6437L) +#define RNTC_CTRL_RNTC_ENA (6438L) +#define RNTC_STAT (6439L) +#define RNTC_STAT_EMPTY (6440L) +#define RNTC_TX_DATA (6441L) +#define RNTC_TX_DATA_D (6442L) +/* ROA */ +#define ROA_CONFIG (6443L) +#define ROA_CONFIG_FWD_CELLBUILDER_PCKS (6444L) +#define ROA_CONFIG_FWD_NON_NORMAL_PCKS (6445L) +#define ROA_CONFIG_FWD_NORMAL_PCKS (6446L) +#define ROA_CONFIG_FWD_RECIRCULATE (6447L) +#define ROA_CONFIG_FWD_TXPORT0 (6448L) +#define ROA_CONFIG_FWD_TXPORT1 (6449L) +#define ROA_IGS (6450L) +#define ROA_IGS_BYTE (6451L) +#define ROA_IGS_BYTE_DROP (6452L) +#define ROA_IGS_PKT (6453L) +#define ROA_IGS_PKT_DROP (6454L) +#define ROA_LAGCFG_CTRL (6455L) +#define ROA_LAGCFG_CTRL_ADR (6456L) +#define ROA_LAGCFG_CTRL_CNT (6457L) +#define ROA_LAGCFG_DATA (6458L) +#define ROA_LAGCFG_DATA_TXPHY_PORT (6459L) +#define ROA_RCC (6460L) +#define ROA_RCC_BYTE (6461L) +#define ROA_RCC_BYTE_DROP (6462L) +#define ROA_RCC_PKT (6463L) +#define ROA_RCC_PKT_DROP (6464L) +#define ROA_TUNCFG_CTRL (6465L) +#define ROA_TUNCFG_CTRL_ADR (6466L) +#define ROA_TUNCFG_CTRL_CNT (6467L) +#define ROA_TUNCFG_DATA (6468L) +#define ROA_TUNCFG_DATA_PUSH_TUNNEL (6469L) +#define ROA_TUNCFG_DATA_RECIRCULATE (6470L) +#define ROA_TUNCFG_DATA_RECIRC_BYPASS (6471L) +#define ROA_TUNCFG_DATA_RECIRC_PORT (6472L) +#define ROA_TUNCFG_DATA_TUN_IPCS_PRECALC (6473L) +#define ROA_TUNCFG_DATA_TUN_IPCS_UPD (6474L) +#define ROA_TUNCFG_DATA_TUN_IPTL_PRECALC (6475L) +#define ROA_TUNCFG_DATA_TUN_IPTL_UPD (6476L) +#define ROA_TUNCFG_DATA_TUN_IP_TYPE (6477L) +#define ROA_TUNCFG_DATA_TUN_LEN (6478L) +#define ROA_TUNCFG_DATA_TUN_TYPE (6479L) +#define ROA_TUNCFG_DATA_TUN_VLAN (6480L) +#define ROA_TUNCFG_DATA_TUN_VXLAN_UDP_LEN_UPD (6481L) +#define ROA_TUNCFG_DATA_TX_LAG_IX (6482L) +#define ROA_TUNHDR_CTRL (6483L) +#define ROA_TUNHDR_CTRL_ADR (6484L) +#define ROA_TUNHDR_CTRL_CNT (6485L) +#define ROA_TUNHDR_DATA (6486L) +#define ROA_TUNHDR_DATA_TUNNEL_HDR (6487L) +/* RPL */ +#define RPL_EXT_CTRL (6488L) +#define RPL_EXT_CTRL_ADR (6489L) +#define RPL_EXT_CTRL_CNT (6490L) +#define RPL_EXT_DATA (6491L) +#define RPL_EXT_DATA_RPL_PTR (6492L) +#define RPL_RCP_CTRL (6493L) +#define RPL_RCP_CTRL_ADR (6494L) +#define RPL_RCP_CTRL_CNT (6495L) +#define RPL_RCP_DATA (6496L) +#define RPL_RCP_DATA_DYN (6497L) +#define RPL_RCP_DATA_EXT_PRIO (6498L) +#define RPL_RCP_DATA_LEN (6499L) +#define RPL_RCP_DATA_OFS (6500L) +#define RPL_RCP_DATA_RPL_PTR (6501L) +#define RPL_RPL_CTRL (6502L) +#define RPL_RPL_CTRL_ADR (6503L) +#define RPL_RPL_CTRL_CNT (6504L) +#define RPL_RPL_DATA (6505L) +#define RPL_RPL_DATA_VALUE (6506L) +/* RPP_LR */ +#define RPP_LR_IFR_RCP_CTRL (6507L) +#define RPP_LR_IFR_RCP_CTRL_ADR (6508L) +#define RPP_LR_IFR_RCP_CTRL_CNT (6509L) +#define RPP_LR_IFR_RCP_DATA (6510L) +#define RPP_LR_IFR_RCP_DATA_EN (6511L) +#define RPP_LR_IFR_RCP_DATA_MTU (6512L) +#define RPP_LR_RCP_CTRL (6513L) +#define RPP_LR_RCP_CTRL_ADR (6514L) +#define RPP_LR_RCP_CTRL_CNT (6515L) +#define RPP_LR_RCP_DATA (6516L) +#define RPP_LR_RCP_DATA_EXP (6517L) +/* RST7000 */ +#define RST7000_RST (6518L) +#define RST7000_RST_SYS (6519L) +/* RST7001 */ +#define RST7001_RST (6520L) +#define RST7001_RST_SYS (6521L) +/* RST9500 */ +#define RST9500_CTRL (6598L) +#define RST9500_CTRL_PTP_MMCM_CLKSEL (6599L) +#define RST9500_CTRL_TS_CLKSEL (6600L) +#define RST9500_CTRL_TS_CLKSEL_OVERRIDE (6601L) +#define RST9500_RST (6602L) +#define RST9500_RST_DDR3 (6603L) +#define RST9500_RST_DDR3_IDLY_MMCM (6604L) +#define RST9500_RST_PERIPH (6605L) +#define RST9500_RST_PHY10G_QPLL (6606L) +#define RST9500_RST_PHY3S10G (6607L) +#define RST9500_RST_PHY3S_MMCM (6608L) +#define RST9500_RST_PTP (6609L) +#define RST9500_RST_PTP_MMCM (6610L) +#define RST9500_RST_RPP (6611L) +#define RST9500_RST_SDC (6612L) +#define RST9500_RST_SI5326 (6613L) +#define RST9500_RST_SYS (6614L) +#define RST9500_RST_TS (6615L) +#define RST9500_RST_TS_MMCM (6616L) +#define RST9500_RST_STAT (6617L) +#define RST9500_RST_STAT_PCS_RESET_BY_SERDES (6618L) +#define RST9500_STAT (6619L) +#define RST9500_STAT_DDR3_IDLY_MMCM_LOCKED (6620L) +#define RST9500_STAT_DDR3_MMCM_LOCKED (6621L) +#define RST9500_STAT_DDR3_PLL_LOCKED (6622L) +#define RST9500_STAT_PHY10G_QPLL_LOCK_0_1 (6623L) +#define RST9500_STAT_PHY10G_QPLL_LOCK_2_3 (6624L) +#define RST9500_STAT_PHY3S_MMCM_LOCKED (6625L) +#define RST9500_STAT_PTP_MMCM_LOCKED (6626L) +#define RST9500_STAT_SYNCE_MAIN_CLK_LOS (6627L) +#define RST9500_STAT_SYS_MMCM_LOCKED (6628L) +#define RST9500_STAT_TS_MMCM_LOCKED (6629L) +#define RST9500_STICKY (6630L) +#define RST9500_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6631L) +#define RST9500_STICKY_DDR3_MMCM_UNLOCKED (6632L) +#define RST9500_STICKY_DDR3_PLL_UNLOCKED (6633L) +#define RST9500_STICKY_PHY10G_QPLL_UNLOCK_0_1 (6634L) +#define RST9500_STICKY_PHY10G_QPLL_UNLOCK_2_3 (6635L) +#define RST9500_STICKY_PHY3S_MMCM_UNLOCKED (6636L) +#define RST9500_STICKY_PTP_MMCM_UNLOCKED (6637L) +#define RST9500_STICKY_TS_MMCM_UNLOCKED (6638L) +/* RST9501 */ +#define RST9501_CTRL (6639L) +#define RST9501_CTRL_PTP_MMCM_CLKSEL (6640L) +#define RST9501_CTRL_TS_CLKSEL (6641L) +#define RST9501_CTRL_TS_CLKSEL_OVERRIDE (6642L) +#define RST9501_RST (6643L) +#define RST9501_RST_DDR3 (6644L) +#define RST9501_RST_DDR3_IDLY_MMCM (6645L) +#define RST9501_RST_PERIPH (6646L) +#define RST9501_RST_PHY10G_QPLL (6647L) +#define RST9501_RST_PHY3S10G (6648L) +#define RST9501_RST_PHY3S_MMCM (6649L) +#define RST9501_RST_PTP (6650L) +#define RST9501_RST_PTP_MMCM (6651L) +#define RST9501_RST_RPP (6652L) +#define RST9501_RST_SDC (6653L) +#define RST9501_RST_SI5326 (6654L) +#define RST9501_RST_SYS (6655L) +#define RST9501_RST_TS (6656L) +#define RST9501_RST_TS_MMCM (6657L) +#define RST9501_RST_STAT (6658L) +#define RST9501_RST_STAT_PCS_RESET_BY_SERDES (6659L) +#define RST9501_STAT (6660L) +#define RST9501_STAT_DDR3_IDLY_MMCM_LOCKED (6661L) +#define RST9501_STAT_DDR3_MMCM_LOCKED (6662L) +#define RST9501_STAT_DDR3_PLL_LOCKED (6663L) +#define RST9501_STAT_PHY10G_QPLL_LOCK_0_1 (6664L) +#define RST9501_STAT_PHY10G_QPLL_LOCK_2_3 (6665L) +#define RST9501_STAT_PHY3S_MMCM_LOCKED (6666L) +#define RST9501_STAT_PTP_MMCM_LOCKED (6667L) +#define RST9501_STAT_SYNCE_MAIN_CLK_LOS (6668L) +#define RST9501_STAT_SYS_MMCM_LOCKED (6669L) +#define RST9501_STAT_TS_MMCM_LOCKED (6670L) +#define RST9501_STICKY (6671L) +#define RST9501_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6672L) +#define RST9501_STICKY_DDR3_MMCM_UNLOCKED (6673L) +#define RST9501_STICKY_DDR3_PLL_UNLOCKED (6674L) +#define RST9501_STICKY_PHY10G_QPLL_UNLOCK_0_1 (6675L) +#define RST9501_STICKY_PHY10G_QPLL_UNLOCK_2_3 (6676L) +#define RST9501_STICKY_PHY3S_MMCM_UNLOCKED (6677L) +#define RST9501_STICKY_PTP_MMCM_UNLOCKED (6678L) +#define RST9501_STICKY_TS_MMCM_UNLOCKED (6679L) +/* RST9502 */ +#define RST9502_CTRL (6680L) +#define RST9502_CTRL_PTP_MMCM_CLKSEL (6681L) +#define RST9502_CTRL_TS_CLKSEL (6682L) +#define RST9502_CTRL_TS_CLKSEL_OVERRIDE (6683L) +#define RST9502_RST (6684L) +#define RST9502_RST_DDR3 (6685L) +#define RST9502_RST_DDR3_IDLY_MMCM (6686L) +#define RST9502_RST_NSEB (6687L) +#define RST9502_RST_PERIPH (6688L) +#define RST9502_RST_PHY10G_QPLL (6689L) +#define RST9502_RST_PHY3S10G (6690L) +#define RST9502_RST_PHY3S_MMCM (6691L) +#define RST9502_RST_PTP (6692L) +#define RST9502_RST_PTP_MMCM (6693L) +#define RST9502_RST_RPP (6694L) +#define RST9502_RST_SDC (6695L) +#define RST9502_RST_SI5326 (6696L) +#define RST9502_RST_SYS (6697L) +#define RST9502_RST_TS (6698L) +#define RST9502_RST_TS_MMCM (6699L) +#define RST9502_RST_STAT (6700L) +#define RST9502_RST_STAT_PCS_RESET_BY_SERDES (6701L) +#define RST9502_STAT (6702L) +#define RST9502_STAT_DDR3_IDLY_MMCM_LOCKED (6703L) +#define RST9502_STAT_DDR3_MMCM_LOCKED (6704L) +#define RST9502_STAT_DDR3_PLL_LOCKED (6705L) +#define RST9502_STAT_PHY10G_QPLL_LOCK_0_1 (6706L) +#define RST9502_STAT_PHY10G_QPLL_LOCK_2_3 (6707L) +#define RST9502_STAT_PHY3S_MMCM_LOCKED (6708L) +#define RST9502_STAT_PTP_MMCM_LOCKED (6709L) +#define RST9502_STAT_SYNCE_MAIN_CLK_LOS (6710L) +#define RST9502_STAT_SYS_MMCM_LOCKED (6711L) +#define RST9502_STAT_TS_MMCM_LOCKED (6712L) +#define RST9502_STICKY (6713L) +#define RST9502_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6714L) +#define RST9502_STICKY_DDR3_MMCM_UNLOCKED (6715L) +#define RST9502_STICKY_DDR3_PLL_UNLOCKED (6716L) +#define RST9502_STICKY_PHY10G_QPLL_UNLOCK_0_1 (6717L) +#define RST9502_STICKY_PHY10G_QPLL_UNLOCK_2_3 (6718L) +#define RST9502_STICKY_PHY3S_MMCM_UNLOCKED (6719L) +#define RST9502_STICKY_PTP_MMCM_UNLOCKED (6720L) +#define RST9502_STICKY_TS_MMCM_UNLOCKED (6721L) +/* RST9503 */ +#define RST9503_CTRL (6722L) +#define RST9503_CTRL_PTP_MMCM_CLKSEL (6723L) +#define RST9503_CTRL_TS_CLKSEL (6724L) +#define RST9503_CTRL_TS_CLKSEL_OVERRIDE (6725L) +#define RST9503_PORT_CLK_SEL (6726L) +#define RST9503_PORT_CLK_SEL_PORT0 (6727L) +#define RST9503_PORT_CLK_SEL_PORT1 (6728L) +#define RST9503_RST (6729L) +#define RST9503_RST_DDR3 (6730L) +#define RST9503_RST_DDR3_IDLY_MMCM (6731L) +#define RST9503_RST_MAC_RX (6732L) +#define RST9503_RST_MAC_RX_MMCM (6733L) +#define RST9503_RST_MAC_TX (6734L) +#define RST9503_RST_NSEB (6735L) +#define RST9503_RST_PCS_RX (6736L) +#define RST9503_RST_PERIPH (6737L) +#define RST9503_RST_PHY40G (6738L) +#define RST9503_RST_PTP (6739L) +#define RST9503_RST_PTP_MMCM (6740L) +#define RST9503_RST_RPP (6741L) +#define RST9503_RST_SDC (6742L) +#define RST9503_RST_SERDES_RX (6743L) +#define RST9503_RST_SERDES_TX (6744L) +#define RST9503_RST_SI5326 (6745L) +#define RST9503_RST_SYS (6746L) +#define RST9503_RST_TS (6747L) +#define RST9503_RST_TS_MMCM (6748L) +#define RST9503_RST_STAT (6749L) +#define RST9503_RST_STAT_PCS_RESET_BY_SERDES (6750L) +#define RST9503_STAT (6751L) +#define RST9503_STAT_DDR3_IDLY_MMCM_LOCKED (6752L) +#define RST9503_STAT_DDR3_MMCM_LOCKED (6753L) +#define RST9503_STAT_DDR3_PLL_LOCKED (6754L) +#define RST9503_STAT_MAC_RX_MMCM_LOCKED (6755L) +#define RST9503_STAT_PTP_MMCM_LOCKED (6756L) +#define RST9503_STAT_SYNCE_MAIN_CLK_LOS (6757L) +#define RST9503_STAT_SYS_MMCM_LOCKED (6758L) +#define RST9503_STAT_TS_MMCM_LOCKED (6759L) +#define RST9503_STICKY (6760L) +#define RST9503_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6761L) +#define RST9503_STICKY_DDR3_MMCM_UNLOCKED (6762L) +#define RST9503_STICKY_DDR3_PLL_UNLOCKED (6763L) +#define RST9503_STICKY_MAC_RX_MMCM_UNLOCKED (6764L) +#define RST9503_STICKY_PTP_MMCM_UNLOCKED (6765L) +#define RST9503_STICKY_TS_MMCM_UNLOCKED (6766L) +/* RST9504 */ +#define RST9504_CTRL (6767L) +#define RST9504_CTRL_PTP_MMCM_CLKSEL (6768L) +#define RST9504_CTRL_TS_CLKSEL (6769L) +#define RST9504_CTRL_TS_CLKSEL_OVERRIDE (6770L) +#define RST9504_RST (6771L) +#define RST9504_RST_DDR3 (6772L) +#define RST9504_RST_DDR3_IDLY_MMCM (6773L) +#define RST9504_RST_MAC_RX (6774L) +#define RST9504_RST_MAC_RX_MMCM (6775L) +#define RST9504_RST_MAC_TX (6776L) +#define RST9504_RST_NSEB (6777L) +#define RST9504_RST_PCS_RX (6778L) +#define RST9504_RST_PERIPH (6779L) +#define RST9504_RST_PHY100G (6780L) +#define RST9504_RST_PTP (6781L) +#define RST9504_RST_PTP_MMCM (6782L) +#define RST9504_RST_RPP (6783L) +#define RST9504_RST_SDC (6784L) +#define RST9504_RST_SERDES_RX (6785L) +#define RST9504_RST_SERDES_TX (6786L) +#define RST9504_RST_SI5326 (6787L) +#define RST9504_RST_SYS (6788L) +#define RST9504_RST_TS (6789L) +#define RST9504_RST_TS_MMCM (6790L) +#define RST9504_RST_STAT (6791L) +#define RST9504_RST_STAT_PCS_RESET_BY_SERDES (6792L) +#define RST9504_STAT (6793L) +#define RST9504_STAT_DDR3_IDLY_MMCM_LOCKED (6794L) +#define RST9504_STAT_DDR3_MMCM_LOCKED (6795L) +#define RST9504_STAT_DDR3_PLL_LOCKED (6796L) +#define RST9504_STAT_MAC_RX_MMCM_LOCKED (6797L) +#define RST9504_STAT_PTP_MMCM_LOCKED (6798L) +#define RST9504_STAT_SYNCE_MAIN_CLK_LOS (6799L) +#define RST9504_STAT_SYS_MMCM_LOCKED (6800L) +#define RST9504_STAT_TS_MMCM_LOCKED (6801L) +#define RST9504_STICKY (6802L) +#define RST9504_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6803L) +#define RST9504_STICKY_DDR3_MMCM_UNLOCKED (6804L) +#define RST9504_STICKY_DDR3_PLL_UNLOCKED (6805L) +#define RST9504_STICKY_MAC_RX_MMCM_UNLOCKED (6806L) +#define RST9504_STICKY_PTP_MMCM_UNLOCKED (6807L) +#define RST9504_STICKY_TS_MMCM_UNLOCKED (6808L) +/* RST9505 */ +#define RST9505_CTRL (6809L) +#define RST9505_CTRL_PTP_MMCM_CLKSEL (6810L) +#define RST9505_CTRL_TS_CLKSEL (6811L) +#define RST9505_CTRL_TS_CLKSEL_OVERRIDE (6812L) +#define RST9505_RST (6813L) +#define RST9505_RST_DDR3 (6814L) +#define RST9505_RST_DDR3_IDLY_MMCM (6815L) +#define RST9505_RST_MAC_RX (6816L) +#define RST9505_RST_MAC_RX_MMCM (6817L) +#define RST9505_RST_MAC_TX (6818L) +#define RST9505_RST_NSEB (6819L) +#define RST9505_RST_PCS_RX (6820L) +#define RST9505_RST_PERIPH (6821L) +#define RST9505_RST_PHY100G (6822L) +#define RST9505_RST_PTP (6823L) +#define RST9505_RST_PTP_MMCM (6824L) +#define RST9505_RST_RPP (6825L) +#define RST9505_RST_SDC (6826L) +#define RST9505_RST_SERDES_RX (6827L) +#define RST9505_RST_SERDES_TX (6828L) +#define RST9505_RST_SI5326 (6829L) +#define RST9505_RST_SYS (6830L) +#define RST9505_RST_TS (6831L) +#define RST9505_RST_TS_MMCM (6832L) +#define RST9505_RST_STAT (6833L) +#define RST9505_RST_STAT_PCS_RESET_BY_SERDES (6834L) +#define RST9505_STAT (6835L) +#define RST9505_STAT_DDR3_IDLY_MMCM_LOCKED (6836L) +#define RST9505_STAT_DDR3_MMCM_LOCKED (6837L) +#define RST9505_STAT_DDR3_PLL_LOCKED (6838L) +#define RST9505_STAT_MAC_RX_MMCM_LOCKED (6839L) +#define RST9505_STAT_PTP_MMCM_LOCKED (6840L) +#define RST9505_STAT_SYNCE_MAIN_CLK_LOS (6841L) +#define RST9505_STAT_SYS_MMCM_LOCKED (6842L) +#define RST9505_STAT_TS_MMCM_LOCKED (6843L) +#define RST9505_STICKY (6844L) +#define RST9505_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6845L) +#define RST9505_STICKY_DDR3_MMCM_UNLOCKED (6846L) +#define RST9505_STICKY_DDR3_PLL_UNLOCKED (6847L) +#define RST9505_STICKY_MAC_RX_MMCM_UNLOCKED (6848L) +#define RST9505_STICKY_PTP_MMCM_UNLOCKED (6849L) +#define RST9505_STICKY_TS_MMCM_UNLOCKED (6850L) +/* RST9506 */ +/* RST9507 */ +/* RST9508 */ +#define RST9508_CTRL (6851L) +#define RST9508_CTRL_PTP_MMCM_CLKSEL (6852L) +#define RST9508_CTRL_TS_CLKSEL (6853L) +#define RST9508_CTRL_TS_CLKSEL_OVERRIDE (6854L) +#define RST9508_CTRL_TS_CLKSEL_REF (6855L) +#define RST9508_POWER (6856L) +#define RST9508_POWER_PU_NSEB (6857L) +#define RST9508_POWER_PU_PHY (6858L) +#define RST9508_RST (6859L) +#define RST9508_RST_CORE_MMCM (6860L) +#define RST9508_RST_DDR4 (6861L) +#define RST9508_RST_MAC_RX (6862L) +#define RST9508_RST_PERIPH (6863L) +#define RST9508_RST_PHY (6864L) +#define RST9508_RST_PTP (6865L) +#define RST9508_RST_PTP_MMCM (6866L) +#define RST9508_RST_RPP (6867L) +#define RST9508_RST_SDC (6868L) +#define RST9508_RST_SYS (6869L) +#define RST9508_RST_SYS_MMCM (6870L) +#define RST9508_RST_TMC (6871L) +#define RST9508_RST_TS (6872L) +#define RST9508_RST_TSM_REF_MMCM (6873L) +#define RST9508_RST_TS_MMCM (6874L) +#define RST9508_STAT (6875L) +#define RST9508_STAT_CORE_MMCM_LOCKED (6876L) +#define RST9508_STAT_DDR4_MMCM_LOCKED (6877L) +#define RST9508_STAT_DDR4_PLL_LOCKED (6878L) +#define RST9508_STAT_PCI_SYS_MMCM_LOCKED (6879L) +#define RST9508_STAT_PTP_MMCM_LOCKED (6880L) +#define RST9508_STAT_SYS_MMCM_LOCKED (6881L) +#define RST9508_STAT_TSM_REF_MMCM_LOCKED (6882L) +#define RST9508_STAT_TS_MMCM_LOCKED (6883L) +#define RST9508_STICKY (6884L) +#define RST9508_STICKY_CORE_MMCM_UNLOCKED (6885L) +#define RST9508_STICKY_DDR4_MMCM_UNLOCKED (6886L) +#define RST9508_STICKY_DDR4_PLL_UNLOCKED (6887L) +#define RST9508_STICKY_PCI_SYS_MMCM_UNLOCKED (6888L) +#define RST9508_STICKY_PTP_MMCM_UNLOCKED (6889L) +#define RST9508_STICKY_SYS_MMCM_UNLOCKED (6890L) +#define RST9508_STICKY_TSM_REF_MMCM_UNLOCKED (6891L) +#define RST9508_STICKY_TS_MMCM_UNLOCKED (6892L) +/* RST9509 */ +/* RST9510 */ +/* RST9512 */ +#define RST9512_CTRL (6893L) +#define RST9512_CTRL_PTP_MMCM_CLKSEL (6894L) +#define RST9512_CTRL_TS_CLKSEL (6895L) +#define RST9512_CTRL_TS_CLKSEL_OVERRIDE (6896L) +#define RST9512_CTRL_TS_CLKSEL_REF (6897L) +#define RST9512_POWER (6898L) +#define RST9512_POWER_PU_NSEB (6899L) +#define RST9512_POWER_PU_PHY (6900L) +#define RST9512_RST (6901L) +#define RST9512_RST_CORE_MMCM (6902L) +#define RST9512_RST_DDR4 (6903L) +#define RST9512_RST_MAC_RX (6904L) +#define RST9512_RST_MAC_TX (6905L) +#define RST9512_RST_PCS_RX (6906L) +#define RST9512_RST_PERIPH (6907L) +#define RST9512_RST_PHY (6908L) +#define RST9512_RST_PTP (6909L) +#define RST9512_RST_PTP_MMCM (6910L) +#define RST9512_RST_RPP (6911L) +#define RST9512_RST_SDC (6912L) +#define RST9512_RST_SERDES_RX (6913L) +#define RST9512_RST_SERDES_RX_DATAPATH (6914L) +#define RST9512_RST_SERDES_TX (6915L) +#define RST9512_RST_SYS (6916L) +#define RST9512_RST_SYS_MMCM (6917L) +#define RST9512_RST_TS (6918L) +#define RST9512_RST_TSM_REF_MMCM (6919L) +#define RST9512_RST_TS_MMCM (6920L) +#define RST9512_STAT (6921L) +#define RST9512_STAT_CORE_MMCM_LOCKED (6922L) +#define RST9512_STAT_DDR4_MMCM_LOCKED (6923L) +#define RST9512_STAT_DDR4_PLL_LOCKED (6924L) +#define RST9512_STAT_PCI_SYS_MMCM_LOCKED (6925L) +#define RST9512_STAT_PTP_MMCM_LOCKED (6926L) +#define RST9512_STAT_SYS_MMCM_LOCKED (6927L) +#define RST9512_STAT_TSM_REF_MMCM_LOCKED (6928L) +#define RST9512_STAT_TS_MMCM_LOCKED (6929L) +#define RST9512_STICKY (6930L) +#define RST9512_STICKY_CORE_MMCM_UNLOCKED (6931L) +#define RST9512_STICKY_DDR4_MMCM_UNLOCKED (6932L) +#define RST9512_STICKY_DDR4_PLL_UNLOCKED (6933L) +#define RST9512_STICKY_PCI_SYS_MMCM_UNLOCKED (6934L) +#define RST9512_STICKY_PTP_MMCM_UNLOCKED (6935L) +#define RST9512_STICKY_SYS_MMCM_UNLOCKED (6936L) +#define RST9512_STICKY_TSM_REF_MMCM_UNLOCKED (6937L) +#define RST9512_STICKY_TS_MMCM_UNLOCKED (6938L) +/* RST9513 */ +/* RST9515 */ +#define RST9515_CTRL (6939L) +#define RST9515_CTRL_PTP_MMCM_CLKSEL (6940L) +#define RST9515_CTRL_TS_CLKSEL (6941L) +#define RST9515_CTRL_TS_CLKSEL_OVERRIDE (6942L) +#define RST9515_CTRL_TS_CLKSEL_REF (6943L) +#define RST9515_POWER (6944L) +#define RST9515_POWER_PU_NSEB (6945L) +#define RST9515_POWER_PU_PHY (6946L) +#define RST9515_RST (6947L) +#define RST9515_RST_CORE_MMCM (6948L) +#define RST9515_RST_DDR4 (6949L) +#define RST9515_RST_MAC_RX (6950L) +#define RST9515_RST_PERIPH (6951L) +#define RST9515_RST_PHY (6952L) +#define RST9515_RST_PTP (6953L) +#define RST9515_RST_PTP_MMCM (6954L) +#define RST9515_RST_RPP (6955L) +#define RST9515_RST_SDC (6956L) +#define RST9515_RST_SYS (6957L) +#define RST9515_RST_SYS_MMCM (6958L) +#define RST9515_RST_TMC (6959L) +#define RST9515_RST_TS (6960L) +#define RST9515_RST_TSM_REF_MMCM (6961L) +#define RST9515_RST_TS_MMCM (6962L) +#define RST9515_STAT (6963L) +#define RST9515_STAT_CORE_MMCM_LOCKED (6964L) +#define RST9515_STAT_DDR4_MMCM_LOCKED (6965L) +#define RST9515_STAT_DDR4_PLL_LOCKED (6966L) +#define RST9515_STAT_PCI_SYS_MMCM_LOCKED (6967L) +#define RST9515_STAT_PTP_MMCM_LOCKED (6968L) +#define RST9515_STAT_SYS_MMCM_LOCKED (6969L) +#define RST9515_STAT_TSM_REF_MMCM_LOCKED (6970L) +#define RST9515_STAT_TS_MMCM_LOCKED (6971L) +#define RST9515_STICKY (6972L) +#define RST9515_STICKY_CORE_MMCM_UNLOCKED (6973L) +#define RST9515_STICKY_DDR4_MMCM_UNLOCKED (6974L) +#define RST9515_STICKY_DDR4_PLL_UNLOCKED (6975L) +#define RST9515_STICKY_PCI_SYS_MMCM_UNLOCKED (6976L) +#define RST9515_STICKY_PTP_MMCM_UNLOCKED (6977L) +#define RST9515_STICKY_SYS_MMCM_UNLOCKED (6978L) +#define RST9515_STICKY_TSM_REF_MMCM_UNLOCKED (6979L) +#define RST9515_STICKY_TS_MMCM_UNLOCKED (6980L) +/* RST9516 */ +#define RST9516_CTRL (6981L) +#define RST9516_CTRL_PTP_MMCM_CLKSEL (6982L) +#define RST9516_CTRL_TS_CLKSEL (6983L) +#define RST9516_CTRL_TS_CLKSEL_OVERRIDE (6984L) +#define RST9516_CTRL_TS_CLKSEL_REF (6985L) +#define RST9516_POWER (6986L) +#define RST9516_POWER_PU_NSEB (6987L) +#define RST9516_POWER_PU_PHY (6988L) +#define RST9516_RST (6989L) +#define RST9516_RST_CORE_MMCM (6990L) +#define RST9516_RST_DDR4 (6991L) +#define RST9516_RST_MAC_RX (6992L) +#define RST9516_RST_PCS_RX (6993L) +#define RST9516_RST_PERIPH (6994L) +#define RST9516_RST_PHY (6995L) +#define RST9516_RST_PTP (6996L) +#define RST9516_RST_PTP_MMCM (6997L) +#define RST9516_RST_RPP (6998L) +#define RST9516_RST_SDC (6999L) +#define RST9516_RST_SERDES_RX (7000L) +#define RST9516_RST_SERDES_TX (7001L) +#define RST9516_RST_SYS (7002L) +#define RST9516_RST_SYS_MMCM (7003L) +#define RST9516_RST_TMC (7004L) +#define RST9516_RST_TS (7005L) +#define RST9516_RST_TSM_REF_MMCM (7006L) +#define RST9516_RST_TS_MMCM (7007L) +#define RST9516_STAT (7008L) +#define RST9516_STAT_CORE_MMCM_LOCKED (7009L) +#define RST9516_STAT_DDR4_MMCM_LOCKED (7010L) +#define RST9516_STAT_DDR4_PLL_LOCKED (7011L) +#define RST9516_STAT_PCI_SYS_MMCM_LOCKED (7012L) +#define RST9516_STAT_PTP_MMCM_LOCKED (7013L) +#define RST9516_STAT_SYS_MMCM_LOCKED (7014L) +#define RST9516_STAT_TSM_REF_MMCM_LOCKED (7015L) +#define RST9516_STAT_TS_MMCM_LOCKED (7016L) +#define RST9516_STICKY (7017L) +#define RST9516_STICKY_CORE_MMCM_UNLOCKED (7018L) +#define RST9516_STICKY_DDR4_MMCM_UNLOCKED (7019L) +#define RST9516_STICKY_DDR4_PLL_UNLOCKED (7020L) +#define RST9516_STICKY_PCI_SYS_MMCM_UNLOCKED (7021L) +#define RST9516_STICKY_PTP_MMCM_UNLOCKED (7022L) +#define RST9516_STICKY_SYS_MMCM_UNLOCKED (7023L) +#define RST9516_STICKY_TSM_REF_MMCM_UNLOCKED (7024L) +#define RST9516_STICKY_TS_MMCM_UNLOCKED (7025L) +/* RST9517 */ +#define RST9517_CTRL (7026L) +#define RST9517_CTRL_PTP_MMCM_CLKSEL (7027L) +#define RST9517_CTRL_TS_CLKSEL (7028L) +#define RST9517_CTRL_TS_CLKSEL_OVERRIDE (7029L) +#define RST9517_RST (7030L) +#define RST9517_RST_DDR3 (7031L) +#define RST9517_RST_DDR3_IDLY_MMCM (7032L) +#define RST9517_RST_NSEB (7033L) +#define RST9517_RST_PERIPH (7034L) +#define RST9517_RST_PHY10G_QPLL (7035L) +#define RST9517_RST_PHY3S10G (7036L) +#define RST9517_RST_PHY3S_MMCM (7037L) +#define RST9517_RST_PTP (7038L) +#define RST9517_RST_PTP_MMCM (7039L) +#define RST9517_RST_RPP (7040L) +#define RST9517_RST_SDC (7041L) +#define RST9517_RST_SI5326 (7042L) +#define RST9517_RST_SYS (7043L) +#define RST9517_RST_TS (7044L) +#define RST9517_RST_TS_MMCM (7045L) +#define RST9517_RST_STAT (7046L) +#define RST9517_RST_STAT_PCS_RESET_BY_SERDES (7047L) +#define RST9517_STAT (7048L) +#define RST9517_STAT_DDR3_IDLY_MMCM_LOCKED (7049L) +#define RST9517_STAT_DDR3_MMCM_LOCKED (7050L) +#define RST9517_STAT_DDR3_PLL_LOCKED (7051L) +#define RST9517_STAT_PHY10G_QPLL_LOCK_0_1 (7052L) +#define RST9517_STAT_PHY10G_QPLL_LOCK_2_3 (7053L) +#define RST9517_STAT_PHY3S_MMCM_LOCKED (7054L) +#define RST9517_STAT_PTP_MMCM_LOCKED (7055L) +#define RST9517_STAT_SYNCE_MAIN_CLK_LOS (7056L) +#define RST9517_STAT_SYS_MMCM_LOCKED (7057L) +#define RST9517_STAT_TS_MMCM_LOCKED (7058L) +#define RST9517_STICKY (7059L) +#define RST9517_STICKY_DDR3_IDLY_MMCM_UNLOCKED (7060L) +#define RST9517_STICKY_DDR3_MMCM_UNLOCKED (7061L) +#define RST9517_STICKY_DDR3_PLL_UNLOCKED (7062L) +#define RST9517_STICKY_PHY10G_QPLL_UNLOCK_0_1 (7063L) +#define RST9517_STICKY_PHY10G_QPLL_UNLOCK_2_3 (7064L) +#define RST9517_STICKY_PHY3S_MMCM_UNLOCKED (7065L) +#define RST9517_STICKY_PTP_MMCM_UNLOCKED (7066L) +#define RST9517_STICKY_TS_MMCM_UNLOCKED (7067L) +/* RST9519 */ +#define RST9519_CTRL (7068L) +#define RST9519_CTRL_PTP_MMCM_CLKSEL (7069L) +#define RST9519_CTRL_TS_CLKSEL (7070L) +#define RST9519_CTRL_TS_CLKSEL_OVERRIDE (7071L) +#define RST9519_RST (7072L) +#define RST9519_RST_DDR3 (7073L) +#define RST9519_RST_DDR3_IDLY_MMCM (7074L) +#define RST9519_RST_PERIPH (7075L) +#define RST9519_RST_PHY10G (7076L) +#define RST9519_RST_PHY10G_QPLL (7077L) +#define RST9519_RST_PTP (7078L) +#define RST9519_RST_PTP_MMCM (7079L) +#define RST9519_RST_RPP (7080L) +#define RST9519_RST_SDC (7081L) +#define RST9519_RST_SI5326 (7082L) +#define RST9519_RST_SYS (7083L) +#define RST9519_RST_TS (7084L) +#define RST9519_RST_TS_MMCM (7085L) +#define RST9519_RST_STAT (7086L) +#define RST9519_RST_STAT_PCS_RESET_BY_SERDES (7087L) +#define RST9519_STAT (7088L) +#define RST9519_STAT_DDR3_IDLY_MMCM_LOCKED (7089L) +#define RST9519_STAT_DDR3_MMCM_LOCKED (7090L) +#define RST9519_STAT_DDR3_PLL_LOCKED (7091L) +#define RST9519_STAT_PHY10G_QPLL_LOCK (7092L) +#define RST9519_STAT_PTP_MMCM_LOCKED (7093L) +#define RST9519_STAT_SYNCE_MAIN_CLK_LOS (7094L) +#define RST9519_STAT_SYS_MMCM_LOCKED (7095L) +#define RST9519_STAT_TS_MMCM_LOCKED (7096L) +#define RST9519_STICKY (7097L) +#define RST9519_STICKY_DDR3_IDLY_MMCM_UNLOCKED (7098L) +#define RST9519_STICKY_DDR3_MMCM_UNLOCKED (7099L) +#define RST9519_STICKY_DDR3_PLL_UNLOCKED (7100L) +#define RST9519_STICKY_PHY10G_QPLL_UNLOCK (7101L) +#define RST9519_STICKY_PTP_MMCM_UNLOCKED (7102L) +#define RST9519_STICKY_TS_MMCM_UNLOCKED (7103L) +/* RST9520 */ +/* RST9521 */ +#define RST9521_CTRL (7104L) +#define RST9521_CTRL_PTP_MMCM_CLKSEL (7105L) +#define RST9521_CTRL_TS_CLKSEL (7106L) +#define RST9521_CTRL_TS_CLKSEL_OVERRIDE (7107L) +#define RST9521_POWER (7108L) +#define RST9521_POWER_PU_NSEB (7109L) +#define RST9521_POWER_PU_PHY (7110L) +#define RST9521_RST (7111L) +#define RST9521_RST_CORE_MMCM (7112L) +#define RST9521_RST_DDR4 (7113L) +#define RST9521_RST_MAC_RX (7114L) +#define RST9521_RST_PERIPH (7115L) +#define RST9521_RST_PHY (7116L) +#define RST9521_RST_PTP (7117L) +#define RST9521_RST_PTP_MMCM (7118L) +#define RST9521_RST_RPP (7119L) +#define RST9521_RST_SDC (7120L) +#define RST9521_RST_SYS (7121L) +#define RST9521_RST_SYS_MMCM (7122L) +#define RST9521_RST_TMC (7123L) +#define RST9521_RST_TS (7124L) +#define RST9521_RST_TSM_REF_MMCM (7125L) +#define RST9521_RST_TS_MMCM (7126L) +#define RST9521_STAT (7127L) +#define RST9521_STAT_CORE_MMCM_LOCKED (7128L) +#define RST9521_STAT_DDR4_MMCM_LOCKED (7129L) +#define RST9521_STAT_DDR4_PLL_LOCKED (7130L) +#define RST9521_STAT_PTP_MMCM_LOCKED (7131L) +#define RST9521_STAT_SYS_MMCM_LOCKED (7132L) +#define RST9521_STAT_TS_MMCM_LOCKED (7133L) +#define RST9521_STICKY (7134L) +#define RST9521_STICKY_CORE_MMCM_UNLOCKED (7135L) +#define RST9521_STICKY_DDR4_MMCM_UNLOCKED (7136L) +#define RST9521_STICKY_DDR4_PLL_UNLOCKED (7137L) +#define RST9521_STICKY_PTP_MMCM_UNLOCKED (7138L) +#define RST9521_STICKY_SYS_MMCM_UNLOCKED (7139L) +#define RST9521_STICKY_TS_MMCM_UNLOCKED (7140L) +/* RST9522 */ +#define RST9522_CTRL (7141L) +#define RST9522_CTRL_PTP_MMCM_CLKSEL (7142L) +#define RST9522_CTRL_TS_CLKSEL (7143L) +#define RST9522_CTRL_TS_CLKSEL_OVERRIDE (7144L) +#define RST9522_CTRL_TS_CLKSEL_REF (7145L) +#define RST9522_POWER (7146L) +#define RST9522_POWER_PU_NSEB (7147L) +#define RST9522_POWER_PU_PHY (7148L) +#define RST9522_RST (7149L) +#define RST9522_RST_CORE_MMCM (7150L) +#define RST9522_RST_DDR4 (7151L) +#define RST9522_RST_PERIPH (7152L) +#define RST9522_RST_PHY10G (7153L) +#define RST9522_RST_PHY10G_QPLL (7154L) +#define RST9522_RST_PTP (7155L) +#define RST9522_RST_PTP_MMCM (7156L) +#define RST9522_RST_RPP (7157L) +#define RST9522_RST_SDC (7158L) +#define RST9522_RST_SYS (7159L) +#define RST9522_RST_SYS_MMCM (7160L) +#define RST9522_RST_TS (7161L) +#define RST9522_RST_TSM_REF_MMCM (7162L) +#define RST9522_RST_TS_MMCM (7163L) +#define RST9522_STAT (7164L) +#define RST9522_STAT_CORE_MMCM_LOCKED (7165L) +#define RST9522_STAT_DDR4_MMCM_LOCKED (7166L) +#define RST9522_STAT_DDR4_PLL_LOCKED (7167L) +#define RST9522_STAT_PCI_SYS_MMCM_LOCKED (7168L) +#define RST9522_STAT_PHY10G_QPLL_LOCKED (7169L) +#define RST9522_STAT_PTP_MMCM_LOCKED (7170L) +#define RST9522_STAT_SYS_MMCM_LOCKED (7171L) +#define RST9522_STAT_TSM_REF_MMCM_LOCKED (7172L) +#define RST9522_STAT_TS_MMCM_LOCKED (7173L) +#define RST9522_STICKY (7174L) +#define RST9522_STICKY_CORE_MMCM_UNLOCKED (7175L) +#define RST9522_STICKY_DDR4_MMCM_UNLOCKED (7176L) +#define RST9522_STICKY_DDR4_PLL_UNLOCKED (7177L) +#define RST9522_STICKY_PCI_SYS_MMCM_UNLOCKED (7178L) +#define RST9522_STICKY_PHY10G_QPLL_UNLOCKED (7179L) +#define RST9522_STICKY_PTP_MMCM_UNLOCKED (7180L) +#define RST9522_STICKY_SYS_MMCM_UNLOCKED (7181L) +#define RST9522_STICKY_TSM_REF_MMCM_UNLOCKED (7182L) +#define RST9522_STICKY_TS_MMCM_UNLOCKED (7183L) +/* RST9523 */ +/* RST9524 */ +#define RST9524_CTRL (7184L) +#define RST9524_CTRL_PTP_MMCM_CLKSEL (7185L) +#define RST9524_CTRL_TS_CLKSEL (7186L) +#define RST9524_CTRL_TS_CLKSEL_OVERRIDE (7187L) +#define RST9524_POWER (7188L) +#define RST9524_POWER_PU_NSEB (7189L) +#define RST9524_POWER_PU_PHY (7190L) +#define RST9524_RST (7191L) +#define RST9524_RST_CORE_MMCM (7192L) +#define RST9524_RST_DDR4 (7193L) +#define RST9524_RST_MAC_RX (7194L) +#define RST9524_RST_PERIPH (7195L) +#define RST9524_RST_PHY (7196L) +#define RST9524_RST_PTP (7197L) +#define RST9524_RST_PTP_MMCM (7198L) +#define RST9524_RST_RPP (7199L) +#define RST9524_RST_SDC (7200L) +#define RST9524_RST_SYS (7201L) +#define RST9524_RST_SYS_MMCM (7202L) +#define RST9524_RST_TMC (7203L) +#define RST9524_RST_TS (7204L) +#define RST9524_RST_TS_MMCM (7205L) +#define RST9524_STAT (7206L) +#define RST9524_STAT_CORE_MMCM_LOCKED (7207L) +#define RST9524_STAT_DDR4_MMCM_LOCKED (7208L) +#define RST9524_STAT_DDR4_PLL_LOCKED (7209L) +#define RST9524_STAT_PTP_MMCM_LOCKED (7210L) +#define RST9524_STAT_SYS_MMCM_LOCKED (7211L) +#define RST9524_STAT_TS_MMCM_LOCKED (7212L) +#define RST9524_STICKY (7213L) +#define RST9524_STICKY_CORE_MMCM_UNLOCKED (7214L) +#define RST9524_STICKY_DDR4_MMCM_UNLOCKED (7215L) +#define RST9524_STICKY_DDR4_PLL_UNLOCKED (7216L) +#define RST9524_STICKY_PTP_MMCM_UNLOCKED (7217L) +#define RST9524_STICKY_SYS_MMCM_UNLOCKED (7218L) +#define RST9524_STICKY_TS_MMCM_UNLOCKED (7219L) +/* RST9525 */ +#define RST9525_CTRL (7220L) +#define RST9525_CTRL_PTP_MMCM_CLKSEL (7221L) +#define RST9525_CTRL_TS_CLKSEL (7222L) +#define RST9525_CTRL_TS_CLKSEL_OVERRIDE (7223L) +#define RST9525_CTRL_TS_CLKSEL_REF (7224L) +#define RST9525_POWER (7225L) +#define RST9525_POWER_PU_NSEB (7226L) +#define RST9525_POWER_PU_PHY (7227L) +#define RST9525_RST (7228L) +#define RST9525_RST_CORE_MMCM (7229L) +#define RST9525_RST_DDR4 (7230L) +#define RST9525_RST_MAC_RX (7231L) +#define RST9525_RST_MAC_TX (7232L) +#define RST9525_RST_PCS_RX (7233L) +#define RST9525_RST_PERIPH (7234L) +#define RST9525_RST_PHY (7235L) +#define RST9525_RST_PTP (7236L) +#define RST9525_RST_PTP_MMCM (7237L) +#define RST9525_RST_RPP (7238L) +#define RST9525_RST_SDC (7239L) +#define RST9525_RST_SERDES_RX (7240L) +#define RST9525_RST_SERDES_RX_DATAPATH (7241L) +#define RST9525_RST_SERDES_TX (7242L) +#define RST9525_RST_SYS (7243L) +#define RST9525_RST_SYS_MMCM (7244L) +#define RST9525_RST_TS (7245L) +#define RST9525_RST_TSM_REF_MMCM (7246L) +#define RST9525_RST_TS_MMCM (7247L) +#define RST9525_STAT (7248L) +#define RST9525_STAT_CORE_MMCM_LOCKED (7249L) +#define RST9525_STAT_DDR4_MMCM_LOCKED (7250L) +#define RST9525_STAT_DDR4_PLL_LOCKED (7251L) +#define RST9525_STAT_PCI_SYS_MMCM_LOCKED (7252L) +#define RST9525_STAT_PTP_MMCM_LOCKED (7253L) +#define RST9525_STAT_SYS_MMCM_LOCKED (7254L) +#define RST9525_STAT_TSM_REF_MMCM_LOCKED (7255L) +#define RST9525_STAT_TS_MMCM_LOCKED (7256L) +#define RST9525_STICKY (7257L) +#define RST9525_STICKY_CORE_MMCM_UNLOCKED (7258L) +#define RST9525_STICKY_DDR4_MMCM_UNLOCKED (7259L) +#define RST9525_STICKY_DDR4_PLL_UNLOCKED (7260L) +#define RST9525_STICKY_PCI_SYS_MMCM_UNLOCKED (7261L) +#define RST9525_STICKY_PTP_MMCM_UNLOCKED (7262L) +#define RST9525_STICKY_SYS_MMCM_UNLOCKED (7263L) +#define RST9525_STICKY_TSM_REF_MMCM_UNLOCKED (7264L) +#define RST9525_STICKY_TS_MMCM_UNLOCKED (7265L) +/* RST9526 */ +#define RST9526_CTRL (7266L) +#define RST9526_CTRL_PTP_MMCM_CLKSEL (7267L) +#define RST9526_CTRL_TS_CLKSEL (7268L) +#define RST9526_CTRL_TS_CLKSEL_OVERRIDE (7269L) +#define RST9526_POWER (7270L) +#define RST9526_POWER_PU_NSEB (7271L) +#define RST9526_POWER_PU_PHY (7272L) +#define RST9526_RST (7273L) +#define RST9526_RST_CORE_MMCM (7274L) +#define RST9526_RST_DDR4 (7275L) +#define RST9526_RST_MAC_RX (7276L) +#define RST9526_RST_MAC_TX (7277L) +#define RST9526_RST_PCS_RX (7278L) +#define RST9526_RST_PERIPH (7279L) +#define RST9526_RST_PHY (7280L) +#define RST9526_RST_PTP (7281L) +#define RST9526_RST_PTP_MMCM (7282L) +#define RST9526_RST_RPP (7283L) +#define RST9526_RST_SDC (7284L) +#define RST9526_RST_SERDES_RX (7285L) +#define RST9526_RST_SERDES_RX_DATAPATH (7286L) +#define RST9526_RST_SERDES_TX (7287L) +#define RST9526_RST_SYS (7288L) +#define RST9526_RST_SYS_MMCM (7289L) +#define RST9526_RST_TMC (7290L) +#define RST9526_RST_TS (7291L) +#define RST9526_RST_TS_MMCM (7292L) +#define RST9526_STAT (7293L) +#define RST9526_STAT_CORE_MMCM_LOCKED (7294L) +#define RST9526_STAT_DDR4_MMCM_LOCKED (7295L) +#define RST9526_STAT_DDR4_PLL_LOCKED (7296L) +#define RST9526_STAT_PTP_MMCM_LOCKED (7297L) +#define RST9526_STAT_SYS_MMCM_LOCKED (7298L) +#define RST9526_STAT_TS_MMCM_LOCKED (7299L) +#define RST9526_STICKY (7300L) +#define RST9526_STICKY_CORE_MMCM_UNLOCKED (7301L) +#define RST9526_STICKY_DDR4_MMCM_UNLOCKED (7302L) +#define RST9526_STICKY_DDR4_PLL_UNLOCKED (7303L) +#define RST9526_STICKY_PTP_MMCM_UNLOCKED (7304L) +#define RST9526_STICKY_SYS_MMCM_UNLOCKED (7305L) +#define RST9526_STICKY_TS_MMCM_UNLOCKED (7306L) +/* RST9527 */ +#define RST9527_CTRL (7307L) +#define RST9527_CTRL_PTP_MMCM_CLKSEL (7308L) +#define RST9527_CTRL_TS_CLKSEL (7309L) +#define RST9527_CTRL_TS_CLKSEL_OVERRIDE (7310L) +#define RST9527_POWER (7311L) +#define RST9527_POWER_PU_NSEB (7312L) +#define RST9527_POWER_PU_PHY (7313L) +#define RST9527_RST (7314L) +#define RST9527_RST_CORE_MMCM (7315L) +#define RST9527_RST_DDR4 (7316L) +#define RST9527_RST_MAC_RX (7317L) +#define RST9527_RST_MAC_TX (7318L) +#define RST9527_RST_PCS_RX (7319L) +#define RST9527_RST_PERIPH (7320L) +#define RST9527_RST_PHY (7321L) +#define RST9527_RST_PTP (7322L) +#define RST9527_RST_PTP_MMCM (7323L) +#define RST9527_RST_RPP (7324L) +#define RST9527_RST_SDC (7325L) +#define RST9527_RST_SERDES_RX (7326L) +#define RST9527_RST_SERDES_RX_DATAPATH (7327L) +#define RST9527_RST_SERDES_TX (7328L) +#define RST9527_RST_SYS (7329L) +#define RST9527_RST_SYS_MMCM (7330L) +#define RST9527_RST_TMC (7331L) +#define RST9527_RST_TS (7332L) +#define RST9527_RST_TS_MMCM (7333L) +#define RST9527_STAT (7334L) +#define RST9527_STAT_CORE_MMCM_LOCKED (7335L) +#define RST9527_STAT_DDR4_MMCM_LOCKED (7336L) +#define RST9527_STAT_DDR4_PLL_LOCKED (7337L) +#define RST9527_STAT_PTP_MMCM_LOCKED (7338L) +#define RST9527_STAT_SYS_MMCM_LOCKED (7339L) +#define RST9527_STAT_TS_MMCM_LOCKED (7340L) +#define RST9527_STICKY (7341L) +#define RST9527_STICKY_CORE_MMCM_UNLOCKED (7342L) +#define RST9527_STICKY_DDR4_MMCM_UNLOCKED (7343L) +#define RST9527_STICKY_DDR4_PLL_UNLOCKED (7344L) +#define RST9527_STICKY_PTP_MMCM_UNLOCKED (7345L) +#define RST9527_STICKY_SYS_MMCM_UNLOCKED (7346L) +#define RST9527_STICKY_TS_MMCM_UNLOCKED (7347L) +/* RST9528 */ +/* RST9529 */ +#define RST9529_CTRL (7348L) +#define RST9529_CTRL_PTP_MMCM_CLKSEL (7349L) +#define RST9529_CTRL_TS_CLKSEL (7350L) +#define RST9529_CTRL_TS_CLKSEL_OVERRIDE (7351L) +#define RST9529_CTRL_TS_CLKSEL_REF (7352L) +#define RST9529_POWER (7353L) +#define RST9529_POWER_PU_NSEB (7354L) +#define RST9529_POWER_PU_PHY (7355L) +#define RST9529_RST (7356L) +#define RST9529_RST_CORE_MMCM (7357L) +#define RST9529_RST_DDR4 (7358L) +#define RST9529_RST_PERIPH (7359L) +#define RST9529_RST_PHY (7360L) +#define RST9529_RST_PTP (7361L) +#define RST9529_RST_PTP_MMCM (7362L) +#define RST9529_RST_RPP (7363L) +#define RST9529_RST_SDC (7364L) +#define RST9529_RST_SYS (7365L) +#define RST9529_RST_SYS_MMCM (7366L) +#define RST9529_RST_TS (7367L) +#define RST9529_RST_TSM_REF_MMCM (7368L) +#define RST9529_RST_TS_MMCM (7369L) +#define RST9529_STAT (7370L) +#define RST9529_STAT_CORE_MMCM_LOCKED (7371L) +#define RST9529_STAT_DDR4_MMCM_LOCKED (7372L) +#define RST9529_STAT_DDR4_PLL_LOCKED (7373L) +#define RST9529_STAT_PCI_SYS_MMCM_LOCKED (7374L) +#define RST9529_STAT_PTP_MMCM_LOCKED (7375L) +#define RST9529_STAT_SYS_MMCM_LOCKED (7376L) +#define RST9529_STAT_TSM_REF_MMCM_LOCKED (7377L) +#define RST9529_STAT_TS_MMCM_LOCKED (7378L) +#define RST9529_STICKY (7379L) +#define RST9529_STICKY_CORE_MMCM_UNLOCKED (7380L) +#define RST9529_STICKY_DDR4_MMCM_UNLOCKED (7381L) +#define RST9529_STICKY_DDR4_PLL_UNLOCKED (7382L) +#define RST9529_STICKY_PCI_SYS_MMCM_UNLOCKED (7383L) +#define RST9529_STICKY_PTP_MMCM_UNLOCKED (7384L) +#define RST9529_STICKY_SYS_MMCM_UNLOCKED (7385L) +#define RST9529_STICKY_TSM_REF_MMCM_UNLOCKED (7386L) +#define RST9529_STICKY_TS_MMCM_UNLOCKED (7387L) +/* RST9530 */ +#define RST9530_CTRL (7388L) +#define RST9530_CTRL_PTP_MMCM_CLKSEL (7389L) +#define RST9530_CTRL_TS_CLKSEL (7390L) +#define RST9530_CTRL_TS_CLKSEL_OVERRIDE (7391L) +#define RST9530_CTRL_TS_CLKSEL_REF (7392L) +#define RST9530_POWER (7393L) +#define RST9530_POWER_PU_NSEB (7394L) +#define RST9530_POWER_PU_PHY (7395L) +#define RST9530_RST (7396L) +#define RST9530_RST_CORE_MMCM (7397L) +#define RST9530_RST_DDR4 (7398L) +#define RST9530_RST_NFV_OVS (7399L) +#define RST9530_RST_PERIPH (7400L) +#define RST9530_RST_PHY (7401L) +#define RST9530_RST_PTP (7402L) +#define RST9530_RST_PTP_MMCM (7403L) +#define RST9530_RST_RPP (7404L) +#define RST9530_RST_SDC (7405L) +#define RST9530_RST_SYS (7406L) +#define RST9530_RST_SYS_MMCM (7407L) +#define RST9530_RST_TMC (7408L) +#define RST9530_RST_TS (7409L) +#define RST9530_RST_TSM_REF_MMCM (7410L) +#define RST9530_RST_TS_MMCM (7411L) +#define RST9530_STAT (7412L) +#define RST9530_STAT_CORE_MMCM_LOCKED (7413L) +#define RST9530_STAT_DDR4_MMCM_LOCKED (7414L) +#define RST9530_STAT_DDR4_PLL_LOCKED (7415L) +#define RST9530_STAT_PTP_MMCM_LOCKED (7416L) +#define RST9530_STAT_SYS_MMCM_LOCKED (7417L) +#define RST9530_STAT_TSM_REF_MMCM_LOCKED (7418L) +#define RST9530_STAT_TS_MMCM_LOCKED (7419L) +#define RST9530_STICKY (7420L) +#define RST9530_STICKY_CORE_MMCM_UNLOCKED (7421L) +#define RST9530_STICKY_DDR4_MMCM_UNLOCKED (7422L) +#define RST9530_STICKY_DDR4_PLL_UNLOCKED (7423L) +#define RST9530_STICKY_PCI_SYS_MMCM_UNLOCKED (7424L) +#define RST9530_STICKY_PTP_MMCM_UNLOCKED (7425L) +#define RST9530_STICKY_SYS_MMCM_UNLOCKED (7426L) +#define RST9530_STICKY_TSM_REF_MMCM_UNLOCKED (7427L) +#define RST9530_STICKY_TS_MMCM_UNLOCKED (7428L) +/* RST9531 */ +#define RST9531_CTRL (7429L) +#define RST9531_CTRL_PTP_MMCM_CLKSEL (7430L) +#define RST9531_CTRL_TS_CLKSEL (7431L) +#define RST9531_CTRL_TS_CLKSEL_OVERRIDE (7432L) +#define RST9531_CTRL_TS_CLKSEL_REF (7433L) +#define RST9531_POWER (7434L) +#define RST9531_POWER_PU_NSEB (7435L) +#define RST9531_POWER_PU_PHY (7436L) +#define RST9531_RST (7437L) +#define RST9531_RST_CORE_MMCM (7438L) +#define RST9531_RST_DDR4 (7439L) +#define RST9531_RST_PERIPH (7440L) +#define RST9531_RST_PHY (7441L) +#define RST9531_RST_PTP (7442L) +#define RST9531_RST_PTP_MMCM (7443L) +#define RST9531_RST_RPP (7444L) +#define RST9531_RST_SDC (7445L) +#define RST9531_RST_SYS (7446L) +#define RST9531_RST_SYS_MMCM (7447L) +#define RST9531_RST_TS (7448L) +#define RST9531_RST_TSM_REF_MMCM (7449L) +#define RST9531_RST_TS_MMCM (7450L) +#define RST9531_STAT (7451L) +#define RST9531_STAT_CORE_MMCM_LOCKED (7452L) +#define RST9531_STAT_DDR4_MMCM_LOCKED (7453L) +#define RST9531_STAT_DDR4_PLL_LOCKED (7454L) +#define RST9531_STAT_PCI_SYS_MMCM_LOCKED (7455L) +#define RST9531_STAT_PTP_MMCM_LOCKED (7456L) +#define RST9531_STAT_SYS_MMCM_LOCKED (7457L) +#define RST9531_STAT_TSM_REF_MMCM_LOCKED (7458L) +#define RST9531_STAT_TS_MMCM_LOCKED (7459L) +#define RST9531_STICKY (7460L) +#define RST9531_STICKY_CORE_MMCM_UNLOCKED (7461L) +#define RST9531_STICKY_DDR4_MMCM_UNLOCKED (7462L) +#define RST9531_STICKY_DDR4_PLL_UNLOCKED (7463L) +#define RST9531_STICKY_PCI_SYS_MMCM_UNLOCKED (7464L) +#define RST9531_STICKY_PTP_MMCM_UNLOCKED (7465L) +#define RST9531_STICKY_SYS_MMCM_UNLOCKED (7466L) +#define RST9531_STICKY_TSM_REF_MMCM_UNLOCKED (7467L) +#define RST9531_STICKY_TS_MMCM_UNLOCKED (7468L) +/* RST9532 */ +#define RST9532_CTRL (7469L) +#define RST9532_CTRL_PTP_MMCM_CLKSEL (7470L) +#define RST9532_CTRL_TS_CLKSEL (7471L) +#define RST9532_CTRL_TS_CLKSEL_OVERRIDE (7472L) +#define RST9532_POWER (7473L) +#define RST9532_POWER_PU_NSEB (7474L) +#define RST9532_POWER_PU_PHY (7475L) +#define RST9532_RST (7476L) +#define RST9532_RST_CORE_MMCM (7477L) +#define RST9532_RST_DDR4 (7478L) +#define RST9532_RST_PERIPH (7479L) +#define RST9532_RST_PHY (7480L) +#define RST9532_RST_PTP (7481L) +#define RST9532_RST_PTP_MMCM (7482L) +#define RST9532_RST_RPP (7483L) +#define RST9532_RST_SDC (7484L) +#define RST9532_RST_SYS (7485L) +#define RST9532_RST_SYS_MMCM (7486L) +#define RST9532_RST_TMC (7487L) +#define RST9532_RST_TS (7488L) +#define RST9532_RST_TS_MMCM (7489L) +#define RST9532_STAT (7490L) +#define RST9532_STAT_CORE_MMCM_LOCKED (7491L) +#define RST9532_STAT_DDR4_MMCM_LOCKED (7492L) +#define RST9532_STAT_DDR4_PLL_LOCKED (7493L) +#define RST9532_STAT_PTP_MMCM_LOCKED (7494L) +#define RST9532_STAT_SYS_MMCM_LOCKED (7495L) +#define RST9532_STAT_TS_MMCM_LOCKED (7496L) +#define RST9532_STICKY (7497L) +#define RST9532_STICKY_CORE_MMCM_UNLOCKED (7498L) +#define RST9532_STICKY_DDR4_MMCM_UNLOCKED (7499L) +#define RST9532_STICKY_DDR4_PLL_UNLOCKED (7500L) +#define RST9532_STICKY_PTP_MMCM_UNLOCKED (7501L) +#define RST9532_STICKY_SYS_MMCM_UNLOCKED (7502L) +#define RST9532_STICKY_TS_MMCM_UNLOCKED (7503L) +/* RST9533 */ +#define RST9533_CTRL (7504L) +#define RST9533_CTRL_PTP_MMCM_CLKSEL (7505L) +#define RST9533_CTRL_TS_CLKSEL (7506L) +#define RST9533_CTRL_TS_CLKSEL_OVERRIDE (7507L) +#define RST9533_POWER (7508L) +#define RST9533_POWER_PU_NSEB (7509L) +#define RST9533_POWER_PU_PHY (7510L) +#define RST9533_RST (7511L) +#define RST9533_RST_CORE_MMCM (7512L) +#define RST9533_RST_DDR4 (7513L) +#define RST9533_RST_PERIPH (7514L) +#define RST9533_RST_PHY (7515L) +#define RST9533_RST_PTP (7516L) +#define RST9533_RST_PTP_MMCM (7517L) +#define RST9533_RST_RPP (7518L) +#define RST9533_RST_SDC (7519L) +#define RST9533_RST_SYS (7520L) +#define RST9533_RST_SYS_MMCM (7521L) +#define RST9533_RST_TMC (7522L) +#define RST9533_RST_TS (7523L) +#define RST9533_RST_TS_MMCM (7524L) +#define RST9533_STAT (7525L) +#define RST9533_STAT_CORE_MMCM_LOCKED (7526L) +#define RST9533_STAT_DDR4_MMCM_LOCKED (7527L) +#define RST9533_STAT_DDR4_PLL_LOCKED (7528L) +#define RST9533_STAT_PTP_MMCM_LOCKED (7529L) +#define RST9533_STAT_SYS_MMCM_LOCKED (7530L) +#define RST9533_STAT_TS_MMCM_LOCKED (7531L) +#define RST9533_STICKY (7532L) +#define RST9533_STICKY_CORE_MMCM_UNLOCKED (7533L) +#define RST9533_STICKY_DDR4_MMCM_UNLOCKED (7534L) +#define RST9533_STICKY_DDR4_PLL_UNLOCKED (7535L) +#define RST9533_STICKY_PTP_MMCM_UNLOCKED (7536L) +#define RST9533_STICKY_SYS_MMCM_UNLOCKED (7537L) +#define RST9533_STICKY_TS_MMCM_UNLOCKED (7538L) +/* RST9534 */ +#define RST9534_CTRL (7539L) +#define RST9534_CTRL_PTP_MMCM_CLKSEL (7540L) +#define RST9534_CTRL_TS_CLKSEL (7541L) +#define RST9534_CTRL_TS_CLKSEL_OVERRIDE (7542L) +#define RST9534_POWER (7543L) +#define RST9534_POWER_PU_NSEB (7544L) +#define RST9534_POWER_PU_PHY (7545L) +#define RST9534_RST (7546L) +#define RST9534_RST_CORE_MMCM (7547L) +#define RST9534_RST_DDR4 (7548L) +#define RST9534_RST_PERIPH (7549L) +#define RST9534_RST_PHY (7550L) +#define RST9534_RST_PTP (7551L) +#define RST9534_RST_PTP_MMCM (7552L) +#define RST9534_RST_RPP (7553L) +#define RST9534_RST_SDC (7554L) +#define RST9534_RST_SYS (7555L) +#define RST9534_RST_SYS_MMCM (7556L) +#define RST9534_RST_TMC (7557L) +#define RST9534_RST_TS (7558L) +#define RST9534_RST_TS_MMCM (7559L) +#define RST9534_STAT (7560L) +#define RST9534_STAT_CORE_MMCM_LOCKED (7561L) +#define RST9534_STAT_DDR4_MMCM_LOCKED (7562L) +#define RST9534_STAT_DDR4_PLL_LOCKED (7563L) +#define RST9534_STAT_PTP_MMCM_LOCKED (7564L) +#define RST9534_STAT_SYS_MMCM_LOCKED (7565L) +#define RST9534_STAT_TS_MMCM_LOCKED (7566L) +#define RST9534_STICKY (7567L) +#define RST9534_STICKY_CORE_MMCM_UNLOCKED (7568L) +#define RST9534_STICKY_DDR4_MMCM_UNLOCKED (7569L) +#define RST9534_STICKY_DDR4_PLL_UNLOCKED (7570L) +#define RST9534_STICKY_PTP_MMCM_UNLOCKED (7571L) +#define RST9534_STICKY_SYS_MMCM_UNLOCKED (7572L) +#define RST9534_STICKY_TS_MMCM_UNLOCKED (7573L) +/* RST9535 */ +#define RST9535_CTRL (7574L) +#define RST9535_CTRL_PTP_MMCM_CLKSEL (7575L) +#define RST9535_CTRL_TS_CLKSEL (7576L) +#define RST9535_CTRL_TS_CLKSEL_OVERRIDE (7577L) +#define RST9535_POWER (7578L) +#define RST9535_POWER_PU_NSEB (7579L) +#define RST9535_POWER_PU_PHY (7580L) +#define RST9535_RST (7581L) +#define RST9535_RST_CORE_MMCM (7582L) +#define RST9535_RST_DDR4 (7583L) +#define RST9535_RST_MAC_RX (7584L) +#define RST9535_RST_MAC_TX (7585L) +#define RST9535_RST_PCS_RX (7586L) +#define RST9535_RST_PERIPH (7587L) +#define RST9535_RST_PHY (7588L) +#define RST9535_RST_PTP (7589L) +#define RST9535_RST_PTP_MMCM (7590L) +#define RST9535_RST_RPP (7591L) +#define RST9535_RST_SDC (7592L) +#define RST9535_RST_SERDES_RX (7593L) +#define RST9535_RST_SERDES_RX_DATAPATH (7594L) +#define RST9535_RST_SERDES_TX (7595L) +#define RST9535_RST_SYS (7596L) +#define RST9535_RST_SYS_MMCM (7597L) +#define RST9535_RST_TMC (7598L) +#define RST9535_RST_TS (7599L) +#define RST9535_RST_TS_MMCM (7600L) +#define RST9535_STAT (7601L) +#define RST9535_STAT_CORE_MMCM_LOCKED (7602L) +#define RST9535_STAT_DDR4_MMCM_LOCKED (7603L) +#define RST9535_STAT_DDR4_PLL_LOCKED (7604L) +#define RST9535_STAT_PTP_MMCM_LOCKED (7605L) +#define RST9535_STAT_SYS_MMCM_LOCKED (7606L) +#define RST9535_STAT_TS_MMCM_LOCKED (7607L) +#define RST9535_STICKY (7608L) +#define RST9535_STICKY_CORE_MMCM_UNLOCKED (7609L) +#define RST9535_STICKY_DDR4_MMCM_UNLOCKED (7610L) +#define RST9535_STICKY_DDR4_PLL_UNLOCKED (7611L) +#define RST9535_STICKY_PTP_MMCM_UNLOCKED (7612L) +#define RST9535_STICKY_SYS_MMCM_UNLOCKED (7613L) +#define RST9535_STICKY_TS_MMCM_UNLOCKED (7614L) +/* RST9536 */ +#define RST9536_CTRL (7615L) +#define RST9536_CTRL_PTP_MMCM_CLKSEL (7616L) +#define RST9536_CTRL_TS_CLKSEL (7617L) +#define RST9536_CTRL_TS_CLKSEL_OVERRIDE (7618L) +#define RST9536_POWER (7619L) +#define RST9536_POWER_PU_NSEB (7620L) +#define RST9536_POWER_PU_PHY (7621L) +#define RST9536_RST (7622L) +#define RST9536_RST_CORE_MMCM (7623L) +#define RST9536_RST_DDR4 (7624L) +#define RST9536_RST_MAC_RX (7625L) +#define RST9536_RST_PERIPH (7626L) +#define RST9536_RST_PHY (7627L) +#define RST9536_RST_PTP (7628L) +#define RST9536_RST_PTP_MMCM (7629L) +#define RST9536_RST_RPP (7630L) +#define RST9536_RST_SDC (7631L) +#define RST9536_RST_SYS (7632L) +#define RST9536_RST_SYS_MMCM (7633L) +#define RST9536_RST_TMC (7634L) +#define RST9536_RST_TS (7635L) +#define RST9536_RST_TS_MMCM (7636L) +#define RST9536_STAT (7637L) +#define RST9536_STAT_CORE_MMCM_LOCKED (7638L) +#define RST9536_STAT_DDR4_MMCM_LOCKED (7639L) +#define RST9536_STAT_DDR4_PLL_LOCKED (7640L) +#define RST9536_STAT_PTP_MMCM_LOCKED (7641L) +#define RST9536_STAT_SYS_MMCM_LOCKED (7642L) +#define RST9536_STAT_TS_MMCM_LOCKED (7643L) +#define RST9536_STICKY (7644L) +#define RST9536_STICKY_CORE_MMCM_UNLOCKED (7645L) +#define RST9536_STICKY_DDR4_MMCM_UNLOCKED (7646L) +#define RST9536_STICKY_DDR4_PLL_UNLOCKED (7647L) +#define RST9536_STICKY_PTP_MMCM_UNLOCKED (7648L) +#define RST9536_STICKY_SYS_MMCM_UNLOCKED (7649L) +#define RST9536_STICKY_TS_MMCM_UNLOCKED (7650L) +/* RST9537 */ +#define RST9537_CTRL (7651L) +#define RST9537_CTRL_PTP_MMCM_CLKSEL (7652L) +#define RST9537_CTRL_TS_CLKSEL (7653L) +#define RST9537_CTRL_TS_CLKSEL_OVERRIDE (7654L) +#define RST9537_RST (7655L) +#define RST9537_RST_DDR3 (7656L) +#define RST9537_RST_DDR3_IDLY_MMCM (7657L) +#define RST9537_RST_NSEB (7658L) +#define RST9537_RST_PERIPH (7659L) +#define RST9537_RST_PHY10G_QPLL (7660L) +#define RST9537_RST_PHY3S10G (7661L) +#define RST9537_RST_PHY3S_MMCM (7662L) +#define RST9537_RST_PTP (7663L) +#define RST9537_RST_PTP_MMCM (7664L) +#define RST9537_RST_RPP (7665L) +#define RST9537_RST_SDC (7666L) +#define RST9537_RST_SI5326 (7667L) +#define RST9537_RST_SYS (7668L) +#define RST9537_RST_TS (7669L) +#define RST9537_RST_TS_MMCM (7670L) +#define RST9537_RST_STAT (7671L) +#define RST9537_RST_STAT_PCS_RESET_BY_SERDES (7672L) +#define RST9537_STAT (7673L) +#define RST9537_STAT_DDR3_IDLY_MMCM_LOCKED (7674L) +#define RST9537_STAT_DDR3_MMCM_LOCKED (7675L) +#define RST9537_STAT_DDR3_PLL_LOCKED (7676L) +#define RST9537_STAT_PHY10G_QPLL_LOCK_0_1 (7677L) +#define RST9537_STAT_PHY10G_QPLL_LOCK_2_3 (7678L) +#define RST9537_STAT_PHY3S_MMCM_LOCKED (7679L) +#define RST9537_STAT_PTP_MMCM_LOCKED (7680L) +#define RST9537_STAT_SYNCE_MAIN_CLK_LOS (7681L) +#define RST9537_STAT_SYS_MMCM_LOCKED (7682L) +#define RST9537_STAT_TS_MMCM_LOCKED (7683L) +#define RST9537_STICKY (7684L) +#define RST9537_STICKY_DDR3_IDLY_MMCM_UNLOCKED (7685L) +#define RST9537_STICKY_DDR3_MMCM_UNLOCKED (7686L) +#define RST9537_STICKY_DDR3_PLL_UNLOCKED (7687L) +#define RST9537_STICKY_PHY10G_QPLL_UNLOCK_0_1 (7688L) +#define RST9537_STICKY_PHY10G_QPLL_UNLOCK_2_3 (7689L) +#define RST9537_STICKY_PHY3S_MMCM_UNLOCKED (7690L) +#define RST9537_STICKY_PTP_MMCM_UNLOCKED (7691L) +#define RST9537_STICKY_TS_MMCM_UNLOCKED (7692L) +/* RST9538 */ +#define RST9538_CTRL (7693L) +#define RST9538_CTRL_PTP_MMCM_CLKSEL (7694L) +#define RST9538_CTRL_TS_CLKSEL (7695L) +#define RST9538_CTRL_TS_CLKSEL_OVERRIDE (7696L) +#define RST9538_RST (7697L) +#define RST9538_RST_DDR3 (7698L) +#define RST9538_RST_DDR3_IDLY_MMCM (7699L) +#define RST9538_RST_NSEB (7700L) +#define RST9538_RST_PERIPH (7701L) +#define RST9538_RST_PHY10G_QPLL (7702L) +#define RST9538_RST_PHY3S10G (7703L) +#define RST9538_RST_PHY3S_MMCM (7704L) +#define RST9538_RST_PTP (7705L) +#define RST9538_RST_PTP_MMCM (7706L) +#define RST9538_RST_RPP (7707L) +#define RST9538_RST_SDC (7708L) +#define RST9538_RST_SI5326 (7709L) +#define RST9538_RST_SYS (7710L) +#define RST9538_RST_TS (7711L) +#define RST9538_RST_TS_MMCM (7712L) +#define RST9538_RST_STAT (7713L) +#define RST9538_RST_STAT_PCS_RESET_BY_SERDES (7714L) +#define RST9538_STAT (7715L) +#define RST9538_STAT_DDR3_IDLY_MMCM_LOCKED (7716L) +#define RST9538_STAT_DDR3_MMCM_LOCKED (7717L) +#define RST9538_STAT_DDR3_PLL_LOCKED (7718L) +#define RST9538_STAT_PHY10G_QPLL_LOCK_0_1 (7719L) +#define RST9538_STAT_PHY10G_QPLL_LOCK_2_3 (7720L) +#define RST9538_STAT_PHY3S_MMCM_LOCKED (7721L) +#define RST9538_STAT_PTP_MMCM_LOCKED (7722L) +#define RST9538_STAT_SYNCE_MAIN_CLK_LOS (7723L) +#define RST9538_STAT_SYS_MMCM_LOCKED (7724L) +#define RST9538_STAT_TS_MMCM_LOCKED (7725L) +#define RST9538_STICKY (7726L) +#define RST9538_STICKY_DDR3_IDLY_MMCM_UNLOCKED (7727L) +#define RST9538_STICKY_DDR3_MMCM_UNLOCKED (7728L) +#define RST9538_STICKY_DDR3_PLL_UNLOCKED (7729L) +#define RST9538_STICKY_PHY10G_QPLL_UNLOCK_0_1 (7730L) +#define RST9538_STICKY_PHY10G_QPLL_UNLOCK_2_3 (7731L) +#define RST9538_STICKY_PHY3S_MMCM_UNLOCKED (7732L) +#define RST9538_STICKY_PTP_MMCM_UNLOCKED (7733L) +#define RST9538_STICKY_TS_MMCM_UNLOCKED (7734L) +/* RST9539 */ +#define RST9539_CTRL (7735L) +#define RST9539_CTRL_PTP_MMCM_CLKSEL (7736L) +#define RST9539_CTRL_TS_CLKSEL (7737L) +#define RST9539_CTRL_TS_CLKSEL_OVERRIDE (7738L) +#define RST9539_POWER (7739L) +#define RST9539_POWER_PU_NSEB (7740L) +#define RST9539_POWER_PU_PHY (7741L) +#define RST9539_RST (7742L) +#define RST9539_RST_CORE_MMCM (7743L) +#define RST9539_RST_DDR4 (7744L) +#define RST9539_RST_PERIPH (7745L) +#define RST9539_RST_PHY (7746L) +#define RST9539_RST_PTP (7747L) +#define RST9539_RST_PTP_MMCM (7748L) +#define RST9539_RST_RPP (7749L) +#define RST9539_RST_SDC (7750L) +#define RST9539_RST_SYS (7751L) +#define RST9539_RST_SYS_MMCM (7752L) +#define RST9539_RST_TMC (7753L) +#define RST9539_RST_TS (7754L) +#define RST9539_RST_TS_MMCM (7755L) +#define RST9539_STAT (7756L) +#define RST9539_STAT_CORE_MMCM_LOCKED (7757L) +#define RST9539_STAT_DDR4_MMCM_LOCKED (7758L) +#define RST9539_STAT_DDR4_PLL_LOCKED (7759L) +#define RST9539_STAT_PTP_MMCM_LOCKED (7760L) +#define RST9539_STAT_SYS_MMCM_LOCKED (7761L) +#define RST9539_STAT_TS_MMCM_LOCKED (7762L) +#define RST9539_STICKY (7763L) +#define RST9539_STICKY_CORE_MMCM_UNLOCKED (7764L) +#define RST9539_STICKY_DDR4_MMCM_UNLOCKED (7765L) +#define RST9539_STICKY_DDR4_PLL_UNLOCKED (7766L) +#define RST9539_STICKY_PTP_MMCM_UNLOCKED (7767L) +#define RST9539_STICKY_SYS_MMCM_UNLOCKED (7768L) +#define RST9539_STICKY_TS_MMCM_UNLOCKED (7769L) +/* RST9540 */ +#define RST9540_CTRL (7770L) +#define RST9540_CTRL_PTP_MMCM_CLKSEL (7771L) +#define RST9540_CTRL_TS_CLKSEL (7772L) +#define RST9540_CTRL_TS_CLKSEL_OVERRIDE (7773L) +#define RST9540_POWER (7774L) +#define RST9540_POWER_PU_NSEB (7775L) +#define RST9540_POWER_PU_PHY (7776L) +#define RST9540_RST (7777L) +#define RST9540_RST_CORE_MMCM (7778L) +#define RST9540_RST_DDR4 (7779L) +#define RST9540_RST_MAC_RX (7780L) +#define RST9540_RST_MAC_TX (7781L) +#define RST9540_RST_PCS_RX (7782L) +#define RST9540_RST_PERIPH (7783L) +#define RST9540_RST_PHY (7784L) +#define RST9540_RST_PTP (7785L) +#define RST9540_RST_PTP_MMCM (7786L) +#define RST9540_RST_RPP (7787L) +#define RST9540_RST_SDC (7788L) +#define RST9540_RST_SERDES_RX (7789L) +#define RST9540_RST_SERDES_RX_DATAPATH (7790L) +#define RST9540_RST_SERDES_TX (7791L) +#define RST9540_RST_SYS (7792L) +#define RST9540_RST_SYS_MMCM (7793L) +#define RST9540_RST_TMC (7794L) +#define RST9540_RST_TS (7795L) +#define RST9540_RST_TS_MMCM (7796L) +#define RST9540_STAT (7797L) +#define RST9540_STAT_CORE_MMCM_LOCKED (7798L) +#define RST9540_STAT_DDR4_MMCM_LOCKED (7799L) +#define RST9540_STAT_DDR4_PLL_LOCKED (7800L) +#define RST9540_STAT_PTP_MMCM_LOCKED (7801L) +#define RST9540_STAT_SYS_MMCM_LOCKED (7802L) +#define RST9540_STAT_TS_MMCM_LOCKED (7803L) +#define RST9540_STICKY (7804L) +#define RST9540_STICKY_CORE_MMCM_UNLOCKED (7805L) +#define RST9540_STICKY_DDR4_MMCM_UNLOCKED (7806L) +#define RST9540_STICKY_DDR4_PLL_UNLOCKED (7807L) +#define RST9540_STICKY_PTP_MMCM_UNLOCKED (7808L) +#define RST9540_STICKY_SYS_MMCM_UNLOCKED (7809L) +#define RST9540_STICKY_TS_MMCM_UNLOCKED (7810L) +/* RST9541 */ +#define RST9541_LATCH (7811L) +#define RST9541_LATCH_DDR4_CALIB_COMPLETE (7812L) +#define RST9541_LATCH_PHY_RDY (7813L) +#define RST9541_POWER (7814L) +#define RST9541_POWER_PU_PHY (7815L) +#define RST9541_RST (7816L) +#define RST9541_RST_DDR4 (7817L) +#define RST9541_RST_PERIPH (7818L) +#define RST9541_RST_PHY (7819L) +#define RST9541_RST_POWER (7820L) +#define RST9541_RST_SYS (7821L) +#define RST9541_STAT (7822L) +#define RST9541_STAT_DDR4_CALIB_COMPLETE (7823L) +#define RST9541_STAT_PHY_RDY (7824L) +/* RST9542 */ +#define RST9542_LATCH (7825L) +#define RST9542_LATCH_DDR4_CALIB_COMPLETE (7826L) +#define RST9542_LATCH_PHY_RDY (7827L) +#define RST9542_POWER (7828L) +#define RST9542_POWER_PU_PHY (7829L) +#define RST9542_RST (7830L) +#define RST9542_RST_DDR4 (7831L) +#define RST9542_RST_PERIPH (7832L) +#define RST9542_RST_PHY (7833L) +#define RST9542_RST_SYS (7834L) +#define RST9542_STAT (7835L) +#define RST9542_STAT_DDR4_CALIB_COMPLETE (7836L) +#define RST9542_STAT_PHY_RDY (7837L) +/* RST9543 */ +#define RST9543_CTRL (7838L) +#define RST9543_CTRL_PTP_MMCM_CLKSEL (7839L) +#define RST9543_CTRL_TS_CLKSEL (7840L) +#define RST9543_CTRL_TS_CLKSEL_OVERRIDE (7841L) +#define RST9543_POWER (7842L) +#define RST9543_POWER_PU_NSEB (7843L) +#define RST9543_POWER_PU_PHY (7844L) +#define RST9543_RST (7845L) +#define RST9543_RST_CORE_MMCM (7846L) +#define RST9543_RST_DDR4 (7847L) +#define RST9543_RST_MAC_RX (7848L) +#define RST9543_RST_PERIPH (7849L) +#define RST9543_RST_PHY (7850L) +#define RST9543_RST_PTP (7851L) +#define RST9543_RST_PTP_MMCM (7852L) +#define RST9543_RST_RPP (7853L) +#define RST9543_RST_SDC (7854L) +#define RST9543_RST_SYS (7855L) +#define RST9543_RST_SYS_MMCM (7856L) +#define RST9543_RST_TMC (7857L) +#define RST9543_RST_TS (7858L) +#define RST9543_RST_TS_MMCM (7859L) +#define RST9543_STAT (7860L) +#define RST9543_STAT_CORE_MMCM_LOCKED (7861L) +#define RST9543_STAT_DDR4_MMCM_LOCKED (7862L) +#define RST9543_STAT_DDR4_PLL_LOCKED (7863L) +#define RST9543_STAT_PTP_MMCM_LOCKED (7864L) +#define RST9543_STAT_SYS_MMCM_LOCKED (7865L) +#define RST9543_STAT_TS_MMCM_LOCKED (7866L) +#define RST9543_STICKY (7867L) +#define RST9543_STICKY_CORE_MMCM_UNLOCKED (7868L) +#define RST9543_STICKY_DDR4_MMCM_UNLOCKED (7869L) +#define RST9543_STICKY_DDR4_PLL_UNLOCKED (7870L) +#define RST9543_STICKY_PTP_MMCM_UNLOCKED (7871L) +#define RST9543_STICKY_SYS_MMCM_UNLOCKED (7872L) +#define RST9543_STICKY_TS_MMCM_UNLOCKED (7873L) +/* RST9544 */ +#define RST9544_CTRL (7874L) +#define RST9544_CTRL_PTP_MMCM_CLKSEL (7875L) +#define RST9544_CTRL_TS_CLKSEL (7876L) +#define RST9544_CTRL_TS_CLKSEL_OVERRIDE (7877L) +#define RST9544_CTRL_TS_CLKSEL_REF (7878L) +#define RST9544_POWER (7879L) +#define RST9544_POWER_PU_NSEB (7880L) +#define RST9544_POWER_PU_PHY (7881L) +#define RST9544_RST (7882L) +#define RST9544_RST_CORE_MMCM (7883L) +#define RST9544_RST_DDR4 (7884L) +#define RST9544_RST_NFV_OVS (7885L) +#define RST9544_RST_PERIPH (7886L) +#define RST9544_RST_PHY (7887L) +#define RST9544_RST_PTP (7888L) +#define RST9544_RST_PTP_MMCM (7889L) +#define RST9544_RST_RPP (7890L) +#define RST9544_RST_SDC (7891L) +#define RST9544_RST_SYS (7892L) +#define RST9544_RST_SYS_MMCM (7893L) +#define RST9544_RST_TMC (7894L) +#define RST9544_RST_TS (7895L) +#define RST9544_RST_TSM_REF_MMCM (7896L) +#define RST9544_RST_TS_MMCM (7897L) +#define RST9544_STAT (7898L) +#define RST9544_STAT_CORE_MMCM_LOCKED (7899L) +#define RST9544_STAT_DDR4_MMCM_LOCKED (7900L) +#define RST9544_STAT_DDR4_PLL_LOCKED (7901L) +#define RST9544_STAT_PTP_MMCM_LOCKED (7902L) +#define RST9544_STAT_SYS_MMCM_LOCKED (7903L) +#define RST9544_STAT_TSM_REF_MMCM_LOCKED (7904L) +#define RST9544_STAT_TS_MMCM_LOCKED (7905L) +#define RST9544_STICKY (7906L) +#define RST9544_STICKY_CORE_MMCM_UNLOCKED (7907L) +#define RST9544_STICKY_DDR4_MMCM_UNLOCKED (7908L) +#define RST9544_STICKY_DDR4_PLL_UNLOCKED (7909L) +#define RST9544_STICKY_PCI_SYS_MMCM_UNLOCKED (7910L) +#define RST9544_STICKY_PTP_MMCM_UNLOCKED (7911L) +#define RST9544_STICKY_SYS_MMCM_UNLOCKED (7912L) +#define RST9544_STICKY_TSM_REF_MMCM_UNLOCKED (7913L) +#define RST9544_STICKY_TS_MMCM_UNLOCKED (7914L) +/* RST9545 */ +#define RST9545_CTRL (7915L) +#define RST9545_CTRL_PTP_MMCM_CLKSEL (7916L) +#define RST9545_CTRL_TS_CLKSEL (7917L) +#define RST9545_CTRL_TS_CLKSEL_OVERRIDE (7918L) +#define RST9545_POWER (7919L) +#define RST9545_POWER_PU_NSEB (7920L) +#define RST9545_POWER_PU_PHY (7921L) +#define RST9545_RST (7922L) +#define RST9545_RST_CORE_MMCM (7923L) +#define RST9545_RST_DDR4 (7924L) +#define RST9545_RST_PERIPH (7925L) +#define RST9545_RST_PHY (7926L) +#define RST9545_RST_PTP (7927L) +#define RST9545_RST_PTP_MMCM (7928L) +#define RST9545_RST_RPP (7929L) +#define RST9545_RST_SDC (7930L) +#define RST9545_RST_SYS (7931L) +#define RST9545_RST_SYS_MMCM (7932L) +#define RST9545_RST_TMC (7933L) +#define RST9545_RST_TS (7934L) +#define RST9545_RST_TS_MMCM (7935L) +#define RST9545_STAT (7936L) +#define RST9545_STAT_CORE_MMCM_LOCKED (7937L) +#define RST9545_STAT_DDR4_MMCM_LOCKED (7938L) +#define RST9545_STAT_DDR4_PLL_LOCKED (7939L) +#define RST9545_STAT_PTP_MMCM_LOCKED (7940L) +#define RST9545_STAT_SYS_MMCM_LOCKED (7941L) +#define RST9545_STAT_TS_MMCM_LOCKED (7942L) +#define RST9545_STICKY (7943L) +#define RST9545_STICKY_CORE_MMCM_UNLOCKED (7944L) +#define RST9545_STICKY_DDR4_MMCM_UNLOCKED (7945L) +#define RST9545_STICKY_DDR4_PLL_UNLOCKED (7946L) +#define RST9545_STICKY_PTP_MMCM_UNLOCKED (7947L) +#define RST9545_STICKY_SYS_MMCM_UNLOCKED (7948L) +#define RST9545_STICKY_TS_MMCM_UNLOCKED (7949L) +/* RST9546 */ +#define RST9546_CTRL (7950L) +#define RST9546_CTRL_PTP_MMCM_CLKSEL (7951L) +#define RST9546_CTRL_TS_CLKSEL (7952L) +#define RST9546_CTRL_TS_CLKSEL_OVERRIDE (7953L) +#define RST9546_POWER (7954L) +#define RST9546_POWER_PU_NSEB (7955L) +#define RST9546_POWER_PU_PHY (7956L) +#define RST9546_RST (7957L) +#define RST9546_RST_CORE_MMCM (7958L) +#define RST9546_RST_DDR4 (7959L) +#define RST9546_RST_MAC_RX (7960L) +#define RST9546_RST_MAC_TX (7961L) +#define RST9546_RST_PCS_RX (7962L) +#define RST9546_RST_PERIPH (7963L) +#define RST9546_RST_PHY (7964L) +#define RST9546_RST_PTP (7965L) +#define RST9546_RST_PTP_MMCM (7966L) +#define RST9546_RST_RPP (7967L) +#define RST9546_RST_SDC (7968L) +#define RST9546_RST_SERDES_RX (7969L) +#define RST9546_RST_SERDES_RX_DATAPATH (7970L) +#define RST9546_RST_SERDES_TX (7971L) +#define RST9546_RST_SYS (7972L) +#define RST9546_RST_SYS_MMCM (7973L) +#define RST9546_RST_TMC (7974L) +#define RST9546_RST_TS (7975L) +#define RST9546_RST_TS_MMCM (7976L) +#define RST9546_STAT (7977L) +#define RST9546_STAT_CORE_MMCM_LOCKED (7978L) +#define RST9546_STAT_DDR4_MMCM_LOCKED (7979L) +#define RST9546_STAT_DDR4_PLL_LOCKED (7980L) +#define RST9546_STAT_PTP_MMCM_LOCKED (7981L) +#define RST9546_STAT_SYS_MMCM_LOCKED (7982L) +#define RST9546_STAT_TS_MMCM_LOCKED (7983L) +#define RST9546_STICKY (7984L) +#define RST9546_STICKY_CORE_MMCM_UNLOCKED (7985L) +#define RST9546_STICKY_DDR4_MMCM_UNLOCKED (7986L) +#define RST9546_STICKY_DDR4_PLL_UNLOCKED (7987L) +#define RST9546_STICKY_PTP_MMCM_UNLOCKED (7988L) +#define RST9546_STICKY_SYS_MMCM_UNLOCKED (7989L) +#define RST9546_STICKY_TS_MMCM_UNLOCKED (7990L) +/* RST9547 */ +#define RST9547_LATCH (7991L) +#define RST9547_LATCH_DDR4_CALIB_COMPLETE (7992L) +#define RST9547_LATCH_PHY_RDY (7993L) +#define RST9547_POWER (7994L) +#define RST9547_POWER_PU_PHY (7995L) +#define RST9547_RST (7996L) +#define RST9547_RST_DDR4 (7997L) +#define RST9547_RST_PERIPH (7998L) +#define RST9547_RST_PHY (7999L) +#define RST9547_RST_SYS (8000L) +#define RST9547_STAT (8001L) +#define RST9547_STAT_DDR4_CALIB_COMPLETE (8002L) +#define RST9547_STAT_PHY_RDY (8003L) +/* RST9548 */ +#define RST9548_CTRL (8004L) +#define RST9548_CTRL_PTP_MMCM_CLKSEL (8005L) +#define RST9548_CTRL_TS_CLKSEL (8006L) +#define RST9548_CTRL_TS_CLKSEL_OVERRIDE (8007L) +#define RST9548_POWER (8008L) +#define RST9548_POWER_PU_NSEB (8009L) +#define RST9548_POWER_PU_PHY (8010L) +#define RST9548_RST (8011L) +#define RST9548_RST_CORE_MMCM (8012L) +#define RST9548_RST_DDR4 (8013L) +#define RST9548_RST_PERIPH (8014L) +#define RST9548_RST_PHY (8015L) +#define RST9548_RST_PTP (8016L) +#define RST9548_RST_PTP_MMCM (8017L) +#define RST9548_RST_RPP (8018L) +#define RST9548_RST_SDC (8019L) +#define RST9548_RST_SYS (8020L) +#define RST9548_RST_SYS_MMCM (8021L) +#define RST9548_RST_TMC (8022L) +#define RST9548_RST_TS (8023L) +#define RST9548_RST_TS_MMCM (8024L) +#define RST9548_STAT (8025L) +#define RST9548_STAT_CORE_MMCM_LOCKED (8026L) +#define RST9548_STAT_DDR4_MMCM_LOCKED (8027L) +#define RST9548_STAT_DDR4_PLL_LOCKED (8028L) +#define RST9548_STAT_PTP_MMCM_LOCKED (8029L) +#define RST9548_STAT_SYS_MMCM_LOCKED (8030L) +#define RST9548_STAT_TS_MMCM_LOCKED (8031L) +#define RST9548_STICKY (8032L) +#define RST9548_STICKY_CORE_MMCM_UNLOCKED (8033L) +#define RST9548_STICKY_DDR4_MMCM_UNLOCKED (8034L) +#define RST9548_STICKY_DDR4_PLL_UNLOCKED (8035L) +#define RST9548_STICKY_PTP_MMCM_UNLOCKED (8036L) +#define RST9548_STICKY_SYS_MMCM_UNLOCKED (8037L) +#define RST9548_STICKY_TS_MMCM_UNLOCKED (8038L) +/* RST9549 */ +#define RST9549_CTRL (8039L) +#define RST9549_CTRL_PTP_MMCM_CLKSEL (8040L) +#define RST9549_CTRL_TS_CLKSEL (8041L) +#define RST9549_CTRL_TS_CLKSEL_OVERRIDE (8042L) +#define RST9549_POWER (8043L) +#define RST9549_POWER_PU_NSEB (8044L) +#define RST9549_POWER_PU_PHY (8045L) +#define RST9549_RST (8046L) +#define RST9549_RST_CORE_MMCM (8047L) +#define RST9549_RST_DDR4 (8048L) +#define RST9549_RST_PERIPH (8049L) +#define RST9549_RST_PHY (8050L) +#define RST9549_RST_PTP (8051L) +#define RST9549_RST_PTP_MMCM (8052L) +#define RST9549_RST_RPP (8053L) +#define RST9549_RST_SDC (8054L) +#define RST9549_RST_SYS (8055L) +#define RST9549_RST_SYS_MMCM (8056L) +#define RST9549_RST_TMC (8057L) +#define RST9549_RST_TS (8058L) +#define RST9549_RST_TS_MMCM (8059L) +#define RST9549_STAT (8060L) +#define RST9549_STAT_CORE_MMCM_LOCKED (8061L) +#define RST9549_STAT_DDR4_MMCM_LOCKED (8062L) +#define RST9549_STAT_DDR4_PLL_LOCKED (8063L) +#define RST9549_STAT_PTP_MMCM_LOCKED (8064L) +#define RST9549_STAT_SYS_MMCM_LOCKED (8065L) +#define RST9549_STAT_TS_MMCM_LOCKED (8066L) +#define RST9549_STICKY (8067L) +#define RST9549_STICKY_CORE_MMCM_UNLOCKED (8068L) +#define RST9549_STICKY_DDR4_MMCM_UNLOCKED (8069L) +#define RST9549_STICKY_DDR4_PLL_UNLOCKED (8070L) +#define RST9549_STICKY_PTP_MMCM_UNLOCKED (8071L) +#define RST9549_STICKY_SYS_MMCM_UNLOCKED (8072L) +#define RST9549_STICKY_TS_MMCM_UNLOCKED (8073L) +/* RST9553 */ +#define RST9553_LATCH (8074L) +#define RST9553_LATCH_DDR4_CALIB_COMPLETE (8075L) +#define RST9553_LATCH_PHY_RDY (8076L) +#define RST9553_RST (8077L) +#define RST9553_RST_DDR4 (8078L) +#define RST9553_RST_PHY (8079L) +#define RST9553_RST_SYS (8080L) +#define RST9553_STAT (8081L) +#define RST9553_STAT_DDR4_CALIB_COMPLETE (8082L) +#define RST9553_STAT_PHY_RDY (8083L) +/* RST9555 */ +#define RST9555_CTRL (8094L) +#define RST9555_CTRL_PTP_MMCM_CLKSEL (8095L) +#define RST9555_CTRL_TS_CLKSEL (8096L) +#define RST9555_CTRL_TS_CLKSEL_OVERRIDE (8097L) +#define RST9555_POWER (8098L) +#define RST9555_POWER_PU_NSEB (8099L) +#define RST9555_POWER_PU_PHY (8100L) +#define RST9555_RST (8101L) +#define RST9555_RST_CORE_MMCM (8102L) +#define RST9555_RST_DDR4 (8103L) +#define RST9555_RST_PERIPH (8104L) +#define RST9555_RST_PHY (8105L) +#define RST9555_RST_PTP (8106L) +#define RST9555_RST_PTP_MMCM (8107L) +#define RST9555_RST_RPP (8108L) +#define RST9555_RST_SDC (8109L) +#define RST9555_RST_SYS (8110L) +#define RST9555_RST_SYS_MMCM (8111L) +#define RST9555_RST_TMC (8112L) +#define RST9555_RST_TS (8113L) +#define RST9555_RST_TS_MMCM (8114L) +#define RST9555_STAT (8115L) +#define RST9555_STAT_CORE_MMCM_LOCKED (8116L) +#define RST9555_STAT_DDR4_MMCM_LOCKED (8117L) +#define RST9555_STAT_DDR4_PLL_LOCKED (8118L) +#define RST9555_STAT_PTP_MMCM_LOCKED (8119L) +#define RST9555_STAT_SYS_MMCM_LOCKED (8120L) +#define RST9555_STAT_TS_MMCM_LOCKED (8121L) +#define RST9555_STICKY (8122L) +#define RST9555_STICKY_CORE_MMCM_UNLOCKED (8123L) +#define RST9555_STICKY_DDR4_MMCM_UNLOCKED (8124L) +#define RST9555_STICKY_DDR4_PLL_UNLOCKED (8125L) +#define RST9555_STICKY_PTP_MMCM_UNLOCKED (8126L) +#define RST9555_STICKY_SYS_MMCM_UNLOCKED (8127L) +#define RST9555_STICKY_TS_MMCM_UNLOCKED (8128L) +/* RST9559 */ +#define RST9559_LATCH (8129L) +#define RST9559_LATCH_DDR4_CALIB_COMPLETE (8130L) +#define RST9559_LATCH_PHY_RDY (8131L) +#define RST9559_RST (8132L) +#define RST9559_RST_DDR4 (8133L) +#define RST9559_RST_PHY (8134L) +#define RST9559_RST_SYS (8135L) +#define RST9559_STAT (8136L) +#define RST9559_STAT_DDR4_CALIB_COMPLETE (8137L) +#define RST9559_STAT_PHY_RDY (8138L) +/* RST9563 */ +#define RST9563_CTRL (8159L) +#define RST9563_CTRL_PTP_MMCM_CLKSEL (8160L) +#define RST9563_CTRL_TS_CLKSEL (8161L) +#define RST9563_CTRL_TS_CLKSEL_OVERRIDE (8162L) +#define RST9563_POWER (8163L) +#define RST9563_POWER_PU_NSEB (8164L) +#define RST9563_POWER_PU_PHY (8165L) +#define RST9563_RST (8166L) +#define RST9563_RST_CORE_MMCM (8167L) +#define RST9563_RST_DDR4 (8168L) +#define RST9563_RST_MAC_RX (8169L) +#define RST9563_RST_PERIPH (8170L) +#define RST9563_RST_PHY (8171L) +#define RST9563_RST_PTP (8172L) +#define RST9563_RST_PTP_MMCM (8173L) +#define RST9563_RST_RPP (8174L) +#define RST9563_RST_SDC (8175L) +#define RST9563_RST_SYS (8176L) +#define RST9563_RST_SYS_MMCM (8177L) +#define RST9563_RST_TMC (8178L) +#define RST9563_RST_TS (8179L) +#define RST9563_RST_TSM_REF_MMCM (8180L) +#define RST9563_RST_TS_MMCM (8181L) +#define RST9563_STAT (8182L) +#define RST9563_STAT_CORE_MMCM_LOCKED (8183L) +#define RST9563_STAT_DDR4_MMCM_LOCKED (8184L) +#define RST9563_STAT_DDR4_PLL_LOCKED (8185L) +#define RST9563_STAT_PTP_MMCM_LOCKED (8186L) +#define RST9563_STAT_SYS_MMCM_LOCKED (8187L) +#define RST9563_STAT_TS_MMCM_LOCKED (8188L) +#define RST9563_STICKY (8189L) +#define RST9563_STICKY_CORE_MMCM_UNLOCKED (8190L) +#define RST9563_STICKY_DDR4_MMCM_UNLOCKED (8191L) +#define RST9563_STICKY_DDR4_PLL_UNLOCKED (8192L) +#define RST9563_STICKY_PTP_MMCM_UNLOCKED (8193L) +#define RST9563_STICKY_SYS_MMCM_UNLOCKED (8194L) +#define RST9563_STICKY_TS_MMCM_UNLOCKED (8195L) +/* RTD */ +#define RTD_CTRL (8196L) +#define RTD_CTRL_ENABLE_RTD (8197L) +#define RTD_CTRL_ENABLE_TX_FLUSH (8198L) +#define RTD_CTRL_ENABLE_TX_MACPHY (8199L) +#define RTD_CTRL_RDPTR_UPDATE_TIMER (8200L) +#define RTD_CTRL_RESERVED (8201L) +#define RTD_CTRL_TX_SPEED (8202L) +#define RTD_DEB_REG1 (8203L) +#define RTD_DEB_REG1_VALUE (8204L) +#define RTD_DEB_REG2 (8205L) +#define RTD_DEB_REG2_VALUE (8206L) +#define RTD_DEB_REG3 (8207L) +#define RTD_DEB_REG3_VALUE (8208L) +#define RTD_HOSTBUFFER_ADR_HI (8209L) +#define RTD_HOSTBUFFER_ADR_HI_VALUE (8210L) +#define RTD_HOSTBUFFER_ADR_LO (8211L) +#define RTD_HOSTBUFFER_ADR_LO_VALUE (8212L) +#define RTD_RDPTR_ADR_HI (8213L) +#define RTD_RDPTR_ADR_HI_VALUE (8214L) +#define RTD_RDPTR_ADR_LO (8215L) +#define RTD_RDPTR_ADR_LO_VALUE (8216L) +#define RTD_STATUS (8217L) +#define RTD_STATUS_HB_EMPTY (8218L) +#define RTD_STATUS_LHF_EMPTY (8219L) +#define RTD_STATUS_UNPACKER_STATUS (8220L) +#define RTD_WRPTR (8221L) +#define RTD_WRPTR_VALUE (8222L) +/* RTD_HMP */ +#define RTD_HMP_CTRL (8223L) +#define RTD_HMP_CTRL_ENABLE_HMP_0 (8224L) +#define RTD_HMP_CTRL_ENABLE_HMP_1 (8225L) +#define RTD_HMP_CTRL_ENABLE_HMP_2 (8226L) +#define RTD_HMP_CTRL_ENABLE_HMP_3 (8227L) +#define RTD_HMP_CTRL_WRPTR_POLL_TIMER (8228L) +#define RTD_HMP_DEB_REG1 (8229L) +#define RTD_HMP_DEB_REG1_VALUE (8230L) +#define RTD_HMP_DEB_REG2 (8231L) +#define RTD_HMP_DEB_REG2_VALUE (8232L) +#define RTD_HMP_DEB_REG3 (8233L) +#define RTD_HMP_DEB_REG3_VALUE (8234L) +#define RTD_HMP_STATUS (8235L) +#define RTD_HMP_STATUS_HMP_ACTIVE (8236L) +#define RTD_HMP_WRPTR_ADR_HI (8237L) +#define RTD_HMP_WRPTR_ADR_HI_VALUE (8238L) +#define RTD_HMP_WRPTR_ADR_LO (8239L) +#define RTD_HMP_WRPTR_ADR_LO_VALUE (8240L) +/* RTX */ +#define RTX_CTRL (8241L) +#define RTX_CTRL_PORT (8242L) +#define RTX_CTRL_SIZE (8243L) +#define RTX_STATUS (8244L) +#define RTX_STATUS_AF (8245L) +#define RTX_STATUS_BUSY (8246L) +#define RTX_TXF_CTRL (8247L) +#define RTX_TXF_CTRL_CNT (8248L) +#define RTX_TXF_DATA (8249L) +#define RTX_TXF_DATA_PAYLOAD (8250L) +#define RXAUI_DEBUG (8268L) +#define RXAUI_DEBUG_MGT_CV_0 (8269L) +#define RXAUI_DEBUG_MGT_CV_1 (8270L) +#define RXAUI_DEBUG_MGT_CV_2 (8271L) +#define RXAUI_DEBUG_MGT_CV_3 (8272L) +#define RXAUI_DEBUG_MGT_CV_4 (8273L) +#define RXAUI_DEBUG_MGT_CV_5 (8274L) +#define RXAUI_DEBUG_MGT_CV_6 (8275L) +#define RXAUI_DEBUG_MGT_CV_7 (8276L) +#define RXAUI_DEBUG_MGT_RXLOCK_0 (8277L) +#define RXAUI_DEBUG_MGT_RXLOCK_1 (8278L) +#define RXAUI_DEBUG_MGT_RX_RESET (8279L) +#define RXAUI_DEBUG_MGT_TX_RESET (8280L) +#define RXAUI_DEBUG_MMCM1_LOCKED (8281L) +#define RXAUI_DRP_AD (8282L) +#define RXAUI_DRP_AD_ADDRESS (8283L) +#define RXAUI_DRP_AD_DFEEYEDACMON (8284L) +#define RXAUI_DRP_AD_GTX_NO (8285L) +#define RXAUI_DRP_AD_READY (8286L) +#define RXAUI_DRP_AD_RESERVED3 (8287L) +#define RXAUI_DRP_AD_RESERVED4 (8288L) +#define RXAUI_DRP_DA (8289L) +#define RXAUI_DRP_DA_DATA (8290L) +#define RXAUI_GTX_CONFIG (8291L) +#define RXAUI_GTX_CONFIG_LOOPBACK (8292L) +#define RXAUI_GTX_CONFIG_LOOPBACKMUX (8293L) +#define RXAUI_GTX_CONFIG_PRBSCNTRESET (8294L) +#define RXAUI_GTX_CONFIG_RESERVED6 (8295L) +#define RXAUI_GTX_CONFIG_RESERVED7 (8296L) +#define RXAUI_GTX_CONFIG_RXENPRBSTST (8297L) +#define RXAUI_GTX_CONFIG_RXEQMIX (8298L) +#define RXAUI_GTX_CONFIG_TXDIFFCTRL (8299L) +#define RXAUI_GTX_CONFIG_TXENPRBSTST (8300L) +#define RXAUI_GTX_CONFIG_TXPOSTEMPHAS (8301L) +#define RXAUI_GTX_CONFIG_TXPRBSFORCEE (8302L) +#define RXAUI_GTX_CONFIG_TXPREEMPHASI (8303L) +#define RXAUI_GTX_STAT (8304L) +#define RXAUI_GTX_STAT_RESERVED10 (8305L) +#define RXAUI_GTX_STAT_RESERVED11 (8306L) +#define RXAUI_GTX_STAT_RESERVED12 (8307L) +#define RXAUI_GTX_STAT_RESERVED13 (8308L) +#define RXAUI_GTX_STAT_RESERVED8 (8309L) +#define RXAUI_GTX_STAT_RESERVED9 (8310L) +#define RXAUI_GTX_STAT_RXBUFSTATUS0 (8311L) +#define RXAUI_GTX_STAT_RXBUFSTATUS1 (8312L) +#define RXAUI_GTX_STAT_RXBYTEISAL_0 (8313L) +#define RXAUI_GTX_STAT_RXBYTEISAL_1 (8314L) +#define RXAUI_GTX_STAT_RXBYTEREAL_0 (8315L) +#define RXAUI_GTX_STAT_RXBYTEREAL_1 (8316L) +#define RXAUI_GTX_STAT_RXCHANREAL_0 (8317L) +#define RXAUI_GTX_STAT_RXCHANREAL_1 (8318L) +#define RXAUI_GTX_STAT_RXCOMMADET_0 (8319L) +#define RXAUI_GTX_STAT_RXCOMMADET_1 (8320L) +#define RXAUI_GTX_STAT_RXPRBSERR_0 (8321L) +#define RXAUI_GTX_STAT_RXPRBSERR_1 (8322L) +/* SDC */ +#define SDC_CELL_CNT (8612L) +#define SDC_CELL_CNT_CELL_CNT (8613L) +#define SDC_CELL_CNT_PERIOD (8614L) +#define SDC_CELL_CNT_PERIOD_CELL_CNT_PERIOD (8615L) +#define SDC_CTRL (8616L) +#define SDC_CTRL_INIT (8617L) +#define SDC_CTRL_RESET_POINTERS (8618L) +#define SDC_CTRL_RUN_TEST (8619L) +#define SDC_CTRL_STOP_CLIENT (8620L) +#define SDC_CTRL_TEST_EN (8621L) +#define SDC_FILL_LVL (8622L) +#define SDC_FILL_LVL_FILL_LVL (8623L) +#define SDC_MAX_FILL_LVL (8624L) +#define SDC_MAX_FILL_LVL_MAX_FILL_LVL (8625L) +#define SDC_STAT (8626L) +#define SDC_STAT_CALIB (8627L) +#define SDC_STAT_CELL_CNT_STOPPED (8628L) +#define SDC_STAT_ERR_FOUND (8629L) +#define SDC_STAT_INIT_DONE (8630L) +#define SDC_STAT_MMCM_LOCK (8631L) +#define SDC_STAT_PLL_LOCK (8632L) +#define SDC_STAT_RESETTING (8633L) +/* SLC */ +#define SLC_RCP_CTRL (8681L) +#define SLC_RCP_CTRL_ADR (8682L) +#define SLC_RCP_CTRL_CNT (8683L) +#define SLC_RCP_DATA (8684L) +#define SLC_RCP_DATA_PCAP (8685L) +#define SLC_RCP_DATA_TAIL_DYN (8686L) +#define SLC_RCP_DATA_TAIL_OFS (8687L) +#define SLC_RCP_DATA_TAIL_SLC_EN (8688L) +/* SLC_LR */ +/* SMM */ +#define SMM_CTRL (8770L) +#define SMM_CTRL_ENABLE (8771L) +#define SMM_READY_STATUS (8772L) +#define SMM_READY_STATUS_D (8773L) +#define SMM_SEG_INVLD_STICKY_STATUS (8774L) +#define SMM_SEG_INVLD_STICKY_STATUS_D (8775L) +#define SMM_SEG_MEM_CTRL (8776L) +#define SMM_SEG_MEM_CTRL_A (8777L) +#define SMM_SEG_MEM_CTRL_CNT (8778L) +#define SMM_SEG_MEM_DATA (8779L) +#define SMM_SEG_MEM_DATA_PHYADDR (8780L) +#define SMM_SEG_MEM_DATA_SIZE (8781L) +#define SMM_START_SEG_MEM_CTRL (8782L) +#define SMM_START_SEG_MEM_CTRL_A (8783L) +#define SMM_START_SEG_MEM_CTRL_CNT (8784L) +#define SMM_START_SEG_MEM_DATA (8785L) +#define SMM_START_SEG_MEM_DATA_SEG (8786L) +/* SPIM */ +#define SPIM_CFG (8793L) +#define SPIM_CFG_PRE (8794L) +#define SPIM_CMD (8795L) +#define SPIM_CMD_ADDR (8796L) +#define SPIM_CMD_CMD (8797L) +#define SPIM_CMD_DATA (8798L) +#define SPIM_CONF0 (8799L) +#define SPIM_CONF0_BYTE_PACE (8800L) +#define SPIM_CONF0_MIRROR_EN (8801L) +#define SPIM_CONF0_MSB_FIRST (8802L) +#define SPIM_CONF0_PRESCAL_CLK (8803L) +#define SPIM_CONF0_RESTART (8804L) +#define SPIM_CONF0_RST (8805L) +#define SPIM_CONF0_SYNC_MON_EN (8806L) +#define SPIM_CONF1 (8807L) +#define SPIM_CONF1_MIRROR_PACE (8808L) +#define SPIM_CONF1_MIRROR_SCAN (8809L) +#define SPIM_CONF1_SYNCTIMEOUT (8810L) +#define SPIM_CONF2 (8811L) +#define SPIM_CONF2_MIRROR_PRESC (8812L) +#define SPIM_CONF2_OPCODE_RD (8813L) +#define SPIM_CONF2_OPCODE_WR (8814L) +#define SPIM_CONF3 (8815L) +#define SPIM_CONF3_MIRROR_RDADR (8816L) +#define SPIM_CONF3_MIRROR_WRADR (8817L) +#define SPIM_CR (8818L) +#define SPIM_CR_EN (8819L) +#define SPIM_CR_LOOP (8820L) +#define SPIM_CR_RXRST (8821L) +#define SPIM_CR_TXRST (8822L) +#define SPIM_DRR (8823L) +#define SPIM_DRR_DRR (8824L) +#define SPIM_DTR (8825L) +#define SPIM_DTR_DTR (8826L) +#define SPIM_REPLY (8827L) +#define SPIM_REPLY_RDDATA (8828L) +#define SPIM_SR (8829L) +#define SPIM_SR_DONE (8830L) +#define SPIM_SR_RXEMPTY (8831L) +#define SPIM_SR_RXFULL (8832L) +#define SPIM_SR_RXLVL (8833L) +#define SPIM_SR_TXEMPTY (8834L) +#define SPIM_SR_TXFULL (8835L) +#define SPIM_SR_TXLVL (8836L) +#define SPIM_SRR (8837L) +#define SPIM_SRR_RST (8838L) +#define SPIM_STATUS (8839L) +#define SPIM_STATUS_CMDPENDING (8840L) +#define SPIM_STATUS_RESERVED (8841L) +#define SPIM_STATUS_RESYNCDETECT (8842L) +#define SPIM_STATUS_RESYNCING (8843L) +/* SPIS */ +#define SPIS_CR (8844L) +#define SPIS_CR_DEBUG (8845L) +#define SPIS_CR_EN (8846L) +#define SPIS_CR_LOOP (8847L) +#define SPIS_CR_RXRST (8848L) +#define SPIS_CR_TXRST (8849L) +#define SPIS_DRR (8850L) +#define SPIS_DRR_DRR (8851L) +#define SPIS_DTR (8852L) +#define SPIS_DTR_DTR (8853L) +#define SPIS_RAM_CTRL (8854L) +#define SPIS_RAM_CTRL_ADR (8855L) +#define SPIS_RAM_CTRL_CNT (8856L) +#define SPIS_RAM_DATA (8857L) +#define SPIS_RAM_DATA_DATA (8858L) +#define SPIS_SR (8859L) +#define SPIS_SR_DONE (8860L) +#define SPIS_SR_FRAME_ERR (8861L) +#define SPIS_SR_READ_ERR (8862L) +#define SPIS_SR_RXEMPTY (8863L) +#define SPIS_SR_RXFULL (8864L) +#define SPIS_SR_RXLVL (8865L) +#define SPIS_SR_TXEMPTY (8866L) +#define SPIS_SR_TXFULL (8867L) +#define SPIS_SR_TXLVL (8868L) +#define SPIS_SR_WRITE_ERR (8869L) +#define SPIS_SRR (8870L) +#define SPIS_SRR_RST (8871L) +/* STA */ +#define STA_BYTE (8872L) +#define STA_BYTE_CNT (8873L) +#define STA_CFG (8874L) +#define STA_CFG_CNT_CLEAR (8875L) +#define STA_CFG_CNT_FRZ (8876L) +#define STA_CFG_DMA_ENA (8877L) +#define STA_CFG_TX_DISABLE (8878L) +#define STA_CV_ERR (8879L) +#define STA_CV_ERR_CNT (8880L) +#define STA_FCS_ERR (8881L) +#define STA_FCS_ERR_CNT (8882L) +#define STA_HOST_ADR_LSB (8883L) +#define STA_HOST_ADR_LSB_LSB (8884L) +#define STA_HOST_ADR_MSB (8885L) +#define STA_HOST_ADR_MSB_MSB (8886L) +#define STA_PCKT (8887L) +#define STA_PCKT_CNT (8888L) +#define STA_STATUS (8889L) +#define STA_STATUS_STAT_TOGGLE_MISSED (8890L) +/* TBH */ +#define TBH_CTRL (9103L) +#define TBH_CTRL_DISABLE_LR_LB (9104L) +#define TBH_CTRL_ENABLE (9105L) +#define TBH_CTRL_PORT (9106L) +#define TBH_CTRL_PORT_AUS (9107L) +#define TBH_CTRL_SEGMENT (9108L) +#define TBH_CTRL_SEGMENT_SIZE (9109L) +#define TBH_DBG_DLN_ERR (9110L) +#define TBH_DBG_DLN_ERR_E (9111L) +#define TBH_DBG_DLN_ERR_HB (9112L) +#define TBH_DBG_ILLEGAL_RANGE (9113L) +#define TBH_DBG_ILLEGAL_RANGE_E (9114L) +#define TBH_DBG_ILLEGAL_RANGE_HB (9115L) +#define TBH_DBG_MAX_PCI_QUIET (9116L) +#define TBH_DBG_MAX_PCI_QUIET_CYCLES (9117L) +#define TBH_DISABLE (9118L) +#define TBH_DISABLE_DISABLE (9119L) +#define TBH_DISABLE_HB (9120L) +#define TBH_HB_DSC_MEM_CTRL (9121L) +#define TBH_HB_DSC_MEM_CTRL_ADR (9122L) +#define TBH_HB_DSC_MEM_CTRL_CNT (9123L) +#define TBH_HB_DSC_MEM_DATA (9124L) +#define TBH_HB_DSC_MEM_DATA_DT (9125L) +#define TBH_HB_DSC_MEM_DATA_FCS (9126L) +#define TBH_HB_DSC_MEM_DATA_FCS_CTL_POS (9127L) +#define TBH_HB_DSC_MEM_DATA_FCS_CTL_USE (9128L) +#define TBH_HB_DSC_MEM_DATA_IG_POS (9129L) +#define TBH_HB_DSC_MEM_DATA_IG_USE (9130L) +#define TBH_HB_DSC_MEM_DATA_OCS_CMD_POS (9131L) +#define TBH_HB_DSC_MEM_DATA_OCS_CMD_USE (9132L) +#define TBH_HB_DSC_MEM_DATA_OFS0_POS (9133L) +#define TBH_HB_DSC_MEM_DATA_OFS0_USE (9134L) +#define TBH_HB_DSC_MEM_DATA_OFS1_POS (9135L) +#define TBH_HB_DSC_MEM_DATA_OFS1_USE (9136L) +#define TBH_HB_DSC_MEM_DATA_OFS2_POS (9137L) +#define TBH_HB_DSC_MEM_DATA_OFS2_USE (9138L) +#define TBH_HB_DSC_MEM_DATA_PFD (9139L) +#define TBH_HB_DSC_MEM_DATA_PORT (9140L) +#define TBH_HB_DSC_MEM_DATA_PORT_MASK (9141L) +#define TBH_HB_DSC_MEM_DATA_PORT_POS (9142L) +#define TBH_HB_DSC_MEM_DATA_SET_CLOCK_POS (9143L) +#define TBH_HB_DSC_MEM_DATA_SET_CLOCK_USE (9144L) +#define TBH_HB_DSC_MEM_DATA_SW_TFD_TYPE_POS (9145L) +#define TBH_HB_DSC_MEM_DATA_SW_TFD_TYPE_USE (9146L) +#define TBH_HB_DSC_MEM_DATA_TS_APPEND (9147L) +#define TBH_HB_DSC_MEM_DATA_TS_FMT (9148L) +#define TBH_HB_DSC_MEM_DATA_TS_INJECT_POS (9149L) +#define TBH_HB_DSC_MEM_DATA_TS_INJECT_USE (9150L) +#define TBH_HB_DSC_MEM_DATA_TX_NOW_POS (9151L) +#define TBH_HB_DSC_MEM_DATA_TX_NOW_USE (9152L) +#define TBH_HB_DSC_MEM_DATA_TX_ON_TS (9153L) +#define TBH_HB_DSC_MEM_DATA_WL_USE (9154L) +#define TBH_HB_INFO_MEM_CTRL (9155L) +#define TBH_HB_INFO_MEM_CTRL_A (9156L) +#define TBH_HB_INFO_MEM_CTRL_CNT (9157L) +#define TBH_HB_INFO_MEM_DATA (9158L) +#define TBH_HB_INFO_MEM_DATA_SIZE (9159L) +#define TBH_HB_PORTS_MEM_CTRL (9160L) +#define TBH_HB_PORTS_MEM_CTRL_A (9161L) +#define TBH_HB_PORTS_MEM_CTRL_CNT (9162L) +#define TBH_HB_PORTS_MEM_DATA (9163L) +#define TBH_HB_PORTS_MEM_DATA_MAPPING (9164L) +#define TBH_PORT_MAPPING (9165L) +#define TBH_PORT_MAPPING_P0 (9166L) +#define TBH_PORT_MAPPING_P1 (9167L) +#define TBH_PORT_MAPPING_P2 (9168L) +#define TBH_PORT_MAPPING_P3 (9169L) +#define TBH_PORT_MAPPING_P4 (9170L) +#define TBH_PORT_MAPPING_P5 (9171L) +#define TBH_PORT_MAPPING_P6 (9172L) +#define TBH_PORT_MAPPING_P7 (9173L) +#define TBH_SET_RD_POINTER (9174L) +#define TBH_SET_RD_POINTER_HB (9175L) +#define TBH_SET_RD_POINTER_OFFSET (9176L) +#define TBH_STATUS (9177L) +#define TBH_STATUS_STOPPED (9178L) +/* TEMPMON */ +#define TEMPMON_ALARMS (9179L) +#define TEMPMON_ALARMS_OT (9180L) +#define TEMPMON_ALARMS_OT_OVERWR (9181L) +#define TEMPMON_ALARMS_OT_OVERWRVAL (9182L) +#define TEMPMON_ALARMS_TEMP (9183L) +#define TEMPMON_STAT (9184L) +#define TEMPMON_STAT_TEMP (9185L) +/* TINT */ +#define TINT_CTRL (9186L) +#define TINT_CTRL_INTERVAL (9187L) +#define TINT_STATUS (9188L) +#define TINT_STATUS_DELAYED (9189L) +#define TINT_STATUS_SKIPPED (9190L) +/* TMC */ +#define TMC_PORT_RPL (9191L) +#define TMC_PORT_RPL_P0 (9192L) +#define TMC_PORT_RPL_P1 (9193L) +#define TMC_PORT_RPL_P2 (9194L) +#define TMC_PORT_RPL_P3 (9195L) +#define TMC_PORT_RPL_P4 (9196L) +#define TMC_PORT_RPL_P5 (9197L) +#define TMC_PORT_RPL_P6 (9198L) +#define TMC_PORT_RPL_P7 (9199L) +/* TSM */ +#define TSM_ADJ_FINE_N (9200L) +#define TSM_ADJ_FINE_N_2DY (9201L) +#define TSM_ADJ_FINE_N_2DY2DX (9202L) +#define TSM_ADJ_FINE_P (9203L) +#define TSM_ADJ_FINE_P_2DY (9204L) +#define TSM_ADJ_FINE_P_2DY2DX (9205L) +#define TSM_ADJ_LIMIT_HI (9206L) +#define TSM_ADJ_LIMIT_HI_LIMIT (9207L) +#define TSM_ADJ_LIMIT_LO (9208L) +#define TSM_ADJ_LIMIT_LO_LIMIT (9209L) +#define TSM_BASIC_2DY (9210L) +#define TSM_BASIC_2DY_2DY (9211L) +#define TSM_BASIC_2DY2DX (9212L) +#define TSM_BASIC_2DY2DX_2DY2DX (9213L) +#define TSM_CON0_CONFIG (9214L) +#define TSM_CON0_CONFIG_BLIND (9215L) +#define TSM_CON0_CONFIG_DC_SRC (9216L) +#define TSM_CON0_CONFIG_PORT (9217L) +#define TSM_CON0_CONFIG_PPSIN_2_5V (9218L) +#define TSM_CON0_CONFIG_SAMPLE_EDGE (9219L) +#define TSM_CON0_INTERFACE (9220L) +#define TSM_CON0_INTERFACE_EX_TERM (9221L) +#define TSM_CON0_INTERFACE_IN_REF_PWM (9222L) +#define TSM_CON0_INTERFACE_PWM_ENA (9223L) +#define TSM_CON0_INTERFACE_RESERVED (9224L) +#define TSM_CON0_INTERFACE_VTERM_PWM (9225L) +#define TSM_CON0_SAMPLE_HI (9226L) +#define TSM_CON0_SAMPLE_HI_SEC (9227L) +#define TSM_CON0_SAMPLE_LO (9228L) +#define TSM_CON0_SAMPLE_LO_NS (9229L) +#define TSM_CON1_CONFIG (9230L) +#define TSM_CON1_CONFIG_BLIND (9231L) +#define TSM_CON1_CONFIG_DC_SRC (9232L) +#define TSM_CON1_CONFIG_PORT (9233L) +#define TSM_CON1_CONFIG_PPSIN_2_5V (9234L) +#define TSM_CON1_CONFIG_SAMPLE_EDGE (9235L) +#define TSM_CON1_SAMPLE_HI (9236L) +#define TSM_CON1_SAMPLE_HI_SEC (9237L) +#define TSM_CON1_SAMPLE_LO (9238L) +#define TSM_CON1_SAMPLE_LO_NS (9239L) +#define TSM_CON2_CONFIG (9240L) +#define TSM_CON2_CONFIG_BLIND (9241L) +#define TSM_CON2_CONFIG_DC_SRC (9242L) +#define TSM_CON2_CONFIG_PORT (9243L) +#define TSM_CON2_CONFIG_PPSIN_2_5V (9244L) +#define TSM_CON2_CONFIG_SAMPLE_EDGE (9245L) +#define TSM_CON2_SAMPLE_HI (9246L) +#define TSM_CON2_SAMPLE_HI_SEC (9247L) +#define TSM_CON2_SAMPLE_LO (9248L) +#define TSM_CON2_SAMPLE_LO_NS (9249L) +#define TSM_CON3_CONFIG (9250L) +#define TSM_CON3_CONFIG_BLIND (9251L) +#define TSM_CON3_CONFIG_PORT (9252L) +#define TSM_CON3_CONFIG_SAMPLE_EDGE (9253L) +#define TSM_CON3_SAMPLE_HI (9254L) +#define TSM_CON3_SAMPLE_HI_SEC (9255L) +#define TSM_CON3_SAMPLE_LO (9256L) +#define TSM_CON3_SAMPLE_LO_NS (9257L) +#define TSM_CON4_CONFIG (9258L) +#define TSM_CON4_CONFIG_BLIND (9259L) +#define TSM_CON4_CONFIG_PORT (9260L) +#define TSM_CON4_CONFIG_SAMPLE_EDGE (9261L) +#define TSM_CON4_SAMPLE_HI (9262L) +#define TSM_CON4_SAMPLE_HI_SEC (9263L) +#define TSM_CON4_SAMPLE_LO (9264L) +#define TSM_CON4_SAMPLE_LO_NS (9265L) +#define TSM_CON5_CONFIG (9266L) +#define TSM_CON5_CONFIG_BLIND (9267L) +#define TSM_CON5_CONFIG_PORT (9268L) +#define TSM_CON5_CONFIG_SAMPLE_EDGE (9269L) +#define TSM_CON5_SAMPLE_HI (9270L) +#define TSM_CON5_SAMPLE_HI_SEC (9271L) +#define TSM_CON5_SAMPLE_LO (9272L) +#define TSM_CON5_SAMPLE_LO_TIME (9273L) +#define TSM_CON6_CONFIG (9274L) +#define TSM_CON6_CONFIG_BLIND (9275L) +#define TSM_CON6_CONFIG_PORT (9276L) +#define TSM_CON6_CONFIG_SAMPLE_EDGE (9277L) +#define TSM_CON6_SAMPLE_HI (9278L) +#define TSM_CON6_SAMPLE_HI_SEC (9279L) +#define TSM_CON6_SAMPLE_LO (9280L) +#define TSM_CON6_SAMPLE_LO_NS (9281L) +#define TSM_CON7_HOST_SAMPLE_HI (9282L) +#define TSM_CON7_HOST_SAMPLE_HI_SEC (9283L) +#define TSM_CON7_HOST_SAMPLE_LO (9284L) +#define TSM_CON7_HOST_SAMPLE_LO_NS (9285L) +#define TSM_CONFIG (9286L) +#define TSM_CONFIG_NTTS_SRC (9287L) +#define TSM_CONFIG_NTTS_SYNC (9288L) +#define TSM_CONFIG_TIMESET_EDGE (9289L) +#define TSM_CONFIG_TIMESET_SRC (9290L) +#define TSM_CONFIG_TIMESET_UP (9291L) +#define TSM_CONFIG_TS_FORMAT (9292L) +#define TSM_CTRL (9293L) +#define TSM_CTRL_DCEN_CON0 (9294L) +#define TSM_CTRL_DCEN_CON1 (9295L) +#define TSM_CTRL_DCEN_CON2 (9296L) +#define TSM_CTRL_FORMAT (9297L) +#define TSM_CTRL_HIGH_SAMPLE (9298L) +#define TSM_CTRL_LED_CON0 (9299L) +#define TSM_CTRL_LED_CON1 (9300L) +#define TSM_CTRL_LED_CON2 (9301L) +#define TSM_CTRL_MASTER_STAT (9302L) +#define TSM_CTRL_OEN_CON0 (9303L) +#define TSM_CTRL_OEN_CON1 (9304L) +#define TSM_CTRL_OEN_CON2 (9305L) +#define TSM_CTRL_PPSEN (9306L) +#define TSM_CTRL_PPS_NEGEDGE (9307L) +#define TSM_CTRL_PPS_TIME_UP (9308L) +#define TSM_CTRL_PTP_TIME_UP (9309L) +#define TSM_CTRL_RESERVED (9310L) +#define TSM_CTRL_SEL_EXTSRC (9311L) +#define TSM_CTRL_SYNEN (9312L) +#define TSM_CTRL_TS_CON0 (9313L) +#define TSM_CTRL_TS_CON1 (9314L) +#define TSM_CTRL_TS_CON2 (9315L) +#define TSM_EXT_STAT (9316L) +#define TSM_EXT_STAT_STAT (9317L) +#define TSM_EXT_TIME_HI (9318L) +#define TSM_EXT_TIME_HI_TIME (9319L) +#define TSM_EXT_TIME_LO (9320L) +#define TSM_EXT_TIME_LO_TIME (9321L) +#define TSM_INTERFACE (9322L) +#define TSM_INTERFACE_EX_TERM (9323L) +#define TSM_INTERFACE_IN_REF_PWM (9324L) +#define TSM_INTERFACE_PWM_ENA (9325L) +#define TSM_INTERFACE_RESERVED (9326L) +#define TSM_INTERFACE_VTERM_PWM (9327L) +#define TSM_INT_CONFIG (9328L) +#define TSM_INT_CONFIG_AUTO_DISABLE (9329L) +#define TSM_INT_CONFIG_MASK (9330L) +#define TSM_INT_STAT (9331L) +#define TSM_INT_STAT_CAUSE (9332L) +#define TSM_INT_STAT_ENABLE (9333L) +#define TSM_INT_TIME_HI (9334L) +#define TSM_INT_TIME_HI_TIME (9335L) +#define TSM_INT_TIME_LO (9336L) +#define TSM_INT_TIME_LO_TIME (9337L) +#define TSM_LED (9338L) +#define TSM_LED_LED0_BG_COLOR (9339L) +#define TSM_LED_LED0_COLOR (9340L) +#define TSM_LED_LED0_MODE (9341L) +#define TSM_LED_LED0_SRC (9342L) +#define TSM_LED_LED1_BG_COLOR (9343L) +#define TSM_LED_LED1_COLOR (9344L) +#define TSM_LED_LED1_MODE (9345L) +#define TSM_LED_LED1_SRC (9346L) +#define TSM_LED_LED2_BG_COLOR (9347L) +#define TSM_LED_LED2_COLOR (9348L) +#define TSM_LED_LED2_MODE (9349L) +#define TSM_LED_LED2_SRC (9350L) +#define TSM_NTTS_CONFIG (9351L) +#define TSM_NTTS_CONFIG_AUTO_HARDSET (9352L) +#define TSM_NTTS_CONFIG_EXT_CLK_ADJ (9353L) +#define TSM_NTTS_CONFIG_HIGH_SAMPLE (9354L) +#define TSM_NTTS_CONFIG_TS_SRC_FORMAT (9355L) +#define TSM_NTTS_CTRL (9356L) +#define TSM_NTTS_CTRL_NTTS_CMD (9357L) +#define TSM_NTTS_DATA_HI (9358L) +#define TSM_NTTS_DATA_HI_DATA (9359L) +#define TSM_NTTS_DATA_LO (9360L) +#define TSM_NTTS_DATA_LO_DATA (9361L) +#define TSM_NTTS_EXT_STAT (9362L) +#define TSM_NTTS_EXT_STAT_MASTER_ID (9363L) +#define TSM_NTTS_EXT_STAT_MASTER_REV (9364L) +#define TSM_NTTS_EXT_STAT_MASTER_STAT (9365L) +#define TSM_NTTS_LIMIT_HI (9366L) +#define TSM_NTTS_LIMIT_HI_SEC (9367L) +#define TSM_NTTS_LIMIT_LO (9368L) +#define TSM_NTTS_LIMIT_LO_NS (9369L) +#define TSM_NTTS_OFFSET (9370L) +#define TSM_NTTS_OFFSET_NS (9371L) +#define TSM_NTTS_SAMPLE_HI (9372L) +#define TSM_NTTS_SAMPLE_HI_SEC (9373L) +#define TSM_NTTS_SAMPLE_LO (9374L) +#define TSM_NTTS_SAMPLE_LO_NS (9375L) +#define TSM_NTTS_STAT (9376L) +#define TSM_NTTS_STAT_NTTS_VALID (9377L) +#define TSM_NTTS_STAT_SIGNAL_LOST (9378L) +#define TSM_NTTS_STAT_SYNC_LOST (9379L) +#define TSM_NTTS_TS_T0_HI (9380L) +#define TSM_NTTS_TS_T0_HI_TIME (9381L) +#define TSM_NTTS_TS_T0_LO (9382L) +#define TSM_NTTS_TS_T0_LO_TIME (9383L) +#define TSM_NTTS_TS_T0_OFFSET (9384L) +#define TSM_NTTS_TS_T0_OFFSET_COUNT (9385L) +#define TSM_OFFSET_HI (9386L) +#define TSM_OFFSET_HI_OFFSET (9387L) +#define TSM_OFFSET_LO (9388L) +#define TSM_OFFSET_LO_OFFSET (9389L) +#define TSM_PB_CTRL (9390L) +#define TSM_PB_CTRL_INSTMEM_WR (9391L) +#define TSM_PB_CTRL_RESET (9392L) +#define TSM_PB_CTRL_RST (9393L) +#define TSM_PB_INSTMEM (9394L) +#define TSM_PB_INSTMEM_ADDR (9395L) +#define TSM_PB_INSTMEM_DATA (9396L) +#define TSM_PB_INSTMEM_MEM_ADDR (9397L) +#define TSM_PB_INSTMEM_MEM_DATA (9398L) +#define TSM_PI_CTRL_I (9399L) +#define TSM_PI_CTRL_I_VAL (9400L) +#define TSM_PI_CTRL_KI (9401L) +#define TSM_PI_CTRL_KI_GAIN (9402L) +#define TSM_PI_CTRL_KP (9403L) +#define TSM_PI_CTRL_KP_GAIN (9404L) +#define TSM_PI_CTRL_SHL (9405L) +#define TSM_PI_CTRL_SHL_VAL (9406L) +#define TSM_RSYNC_COUNT (9407L) +#define TSM_RSYNC_COUNT_COUNT (9408L) +#define TSM_STAT (9409L) +#define TSM_STAT_EXT_SRC_OK (9410L) +#define TSM_STAT_HARD_SYNC (9411L) +#define TSM_STAT_INSYNC (9412L) +#define TSM_STAT_LINK_ACTIVE (9413L) +#define TSM_STAT_LINK_CON0 (9414L) +#define TSM_STAT_LINK_CON1 (9415L) +#define TSM_STAT_LINK_CON2 (9416L) +#define TSM_STAT_LINK_CON3 (9417L) +#define TSM_STAT_LINK_CON4 (9418L) +#define TSM_STAT_LINK_CON5 (9419L) +#define TSM_STAT_NTTS_INSYNC (9420L) +#define TSM_STAT_PTP_MI_PRESENT (9421L) +#define TSM_TIMER_CTRL (9422L) +#define TSM_TIMER_CTRL_TIMER_EN_T0 (9423L) +#define TSM_TIMER_CTRL_TIMER_EN_T1 (9424L) +#define TSM_TIMER_CTRL_TRIGGER_SEL (9425L) +#define TSM_TIMER_D_T0 (9426L) +#define TSM_TIMER_D_T0_MAX_COUNT (9427L) +#define TSM_TIMER_T0 (9428L) +#define TSM_TIMER_T0_MAX_COUNT (9429L) +#define TSM_TIMER_T1 (9430L) +#define TSM_TIMER_T1_MAX_COUNT (9431L) +#define TSM_TIMESTAMP_HI (9432L) +#define TSM_TIMESTAMP_HI_TIME (9433L) +#define TSM_TIMESTAMP_LO (9434L) +#define TSM_TIMESTAMP_LO_TIME (9435L) +#define TSM_TIME_HARDSET_HI (9436L) +#define TSM_TIME_HARDSET_HI_TIME (9437L) +#define TSM_TIME_HARDSET_LO (9438L) +#define TSM_TIME_HARDSET_LO_TIME (9439L) +#define TSM_TIME_HI (9440L) +#define TSM_TIME_HI_SEC (9441L) +#define TSM_TIME_HI_TIME (9442L) +#define TSM_TIME_LO (9443L) +#define TSM_TIME_LO_NS (9444L) +#define TSM_TIME_RATE_ADJ (9445L) +#define TSM_TIME_RATE_ADJ_FRACTION (9446L) +#define TSM_TS_HI (9447L) +#define TSM_TS_HI_TIME (9448L) +#define TSM_TS_LO (9449L) +#define TSM_TS_LO_TIME (9450L) +#define TSM_TS_OFFSET (9451L) +#define TSM_TS_OFFSET_NS (9452L) +#define TSM_TS_STAT (9453L) +#define TSM_TS_STAT_OVERRUN (9454L) +#define TSM_TS_STAT_SAMPLES (9455L) +#define TSM_TS_STAT_HI_OFFSET (9456L) +#define TSM_TS_STAT_HI_OFFSET_NS (9457L) +#define TSM_TS_STAT_LO_OFFSET (9458L) +#define TSM_TS_STAT_LO_OFFSET_NS (9459L) +#define TSM_TS_STAT_TAR_HI (9460L) +#define TSM_TS_STAT_TAR_HI_SEC (9461L) +#define TSM_TS_STAT_TAR_LO (9462L) +#define TSM_TS_STAT_TAR_LO_NS (9463L) +#define TSM_TS_STAT_X (9464L) +#define TSM_TS_STAT_X_NS (9465L) +#define TSM_TS_STAT_X2_HI (9466L) +#define TSM_TS_STAT_X2_HI_NS (9467L) +#define TSM_TS_STAT_X2_LO (9468L) +#define TSM_TS_STAT_X2_LO_NS (9469L) +#define TSM_UTC_OFFSET (9470L) +#define TSM_UTC_OFFSET_SEC (9471L) + +#endif /* _NTHW_FPGA_REGISTERS_DEFS_ */ From patchwork Mon Aug 21 13:54:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mykola Kostenok X-Patchwork-Id: 130582 X-Patchwork-Delegate: thomas@monjalon.net 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 387B8430C1; Mon, 21 Aug 2023 15:55:27 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C1A6943255; Mon, 21 Aug 2023 15:54:46 +0200 (CEST) Received: from egress-ip4b.ess.de.barracuda.com (egress-ip4b.ess.de.barracuda.com [18.185.115.208]) by mails.dpdk.org (Postfix) with ESMTP id 7949D43249 for ; Mon, 21 Aug 2023 15:54:43 +0200 (CEST) Received: from EUR03-AM7-obe.outbound.protection.outlook.com (mail-am7eur03lp2237.outbound.protection.outlook.com [104.47.51.237]) by mx-outbound23-196.eu-central-1b.ess.aws.cudaops.com (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 21 Aug 2023 13:54:41 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=NLh+/bQ1tWO2IKmXBT0PQH3C5as9n5HWMMV1f8fWSFd4qm63G70Db9zWATxp3rC2amfz1uKfqKlCvrXQZBCTIz+ZT+b83Mx1YMOClT97pNcs0CqqN4s/1C6w2QdWTeBn+EZXg4+3zQaScYwWesb+HuIQrFBk8YZcj/BDB1NdTQGqRv0VYuNZwwH0fqYTwf8sz69kfH9qQuniPQ/PcethMWTdHHqOyK3sZbEiwxV8GdIZrp2MUlv/rze17rqay4Qv+ciidIhZBcYoQvgb6TQg/5M/odBG5OLzfHV15GPsIXBtpETyiCT3O8iZ2odU/SSZGLaLTmWPf7j4rIF+nuvElw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=dkHDgrGmYYIulIXUWvlg1endX+IU3wS6WMRsLeiJEhI=; b=jgRgbvviyMmecfR4cizR1rb/nqBsjS09kKuxPP1bDP6gIl4xC4mLET68O8IUCKNW23CxxagEy1AUxvbadVQdaRtzUKWvAhxtdlrkyQppS/TH+ab9/rd67lVAxpegY224btMRFnTwihkKUcvH+7OUqT9yHLbK/bhCVxBaSBWSyokTdVMOcrvsmJZpJJrNnSgRkGSlLcTuqkwCLxEeXQ+3fmYIiHJLSv9LXRXWfoSUM7npmFPdTg0Zns3qgeYMbzhwudsZ1u6IGlAYGK+v3YcpVtCoqRqpMvFiUObYpWh8NZp9KGdgUqmly0Xk6oKpW9mcC8FyASEpSrEN3risJoRMeA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=fail (sender ip is 178.72.21.4) smtp.rcpttodomain=dpdk.org smtp.mailfrom=napatech.com; dmarc=fail (p=none sp=none pct=100) action=none header.from=napatech.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=napatech.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=dkHDgrGmYYIulIXUWvlg1endX+IU3wS6WMRsLeiJEhI=; b=mD2bIsGUFeSlwWwva0cHMvyGpdYTVpJNmqkOGy4KfH8tzysRKqFsakiF3u97IyHAk/bd2LkePJ4fTVdvcFi8qshaWcyyRrf7oaKzmfZeqFI5JjPyyOBsCRWUCGWY48G4YpVOl/s/7LWoCQW9RA3WwsgmqLyYedKApiEvez3IWbk= Received: from DB8PR04CA0029.eurprd04.prod.outlook.com (2603:10a6:10:110::39) by DB9P190MB1481.EURP190.PROD.OUTLOOK.COM (2603:10a6:10:243::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.20; Mon, 21 Aug 2023 13:54:28 +0000 Received: from DU2PEPF0001E9C5.eurprd03.prod.outlook.com (2603:10a6:10:110:cafe::85) by DB8PR04CA0029.outlook.office365.com (2603:10a6:10:110::39) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.20 via Frontend Transport; Mon, 21 Aug 2023 13:54:28 +0000 X-MS-Exchange-Authentication-Results: spf=fail (sender IP is 178.72.21.4) smtp.mailfrom=napatech.com; dkim=none (message not signed) header.d=none;dmarc=fail action=none header.from=napatech.com; Received-SPF: Fail (protection.outlook.com: domain of napatech.com does not designate 178.72.21.4 as permitted sender) receiver=protection.outlook.com; client-ip=178.72.21.4; helo=localhost.localdomain.com; Received: from localhost.localdomain.com (178.72.21.4) by DU2PEPF0001E9C5.mail.protection.outlook.com (10.167.8.74) with Microsoft SMTP Server id 15.20.6699.14 via Frontend Transport; Mon, 21 Aug 2023 13:54:27 +0000 From: Mykola Kostenok To: dev@dpdk.org, mko-plv@napatech.com Cc: ckm@napatech.com Subject: [PATCH v6 2/8] net/ntnic: adds core registers and fpga functionality Date: Mon, 21 Aug 2023 15:54:20 +0200 Message-Id: <20230821135426.1478754-2-mko-plv@napatech.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20230821135426.1478754-1-mko-plv@napatech.com> References: <20230816132552.2483752-1-mko-plv@napatech.com> <20230821135426.1478754-1-mko-plv@napatech.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU2PEPF0001E9C5:EE_|DB9P190MB1481:EE_ X-MS-Office365-Filtering-Correlation-Id: 26b36a5e-f5c1-42ca-aeb3-08dba24e22fe X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: GMXVHbBws5Np/elBokzLpLnV9qcQEldKgAwLRP/03pFkIfCgrlrQq0RMxXzKeFZHVC/3sPbLY8tj4tEsNntZAp1kRm5Hlbws1Jd8BxvcnK89qgdfxFCYdkxli9I87MH3TtWJYqx23wMWunYZKzx/+vt+6T1O0N0KHF7Aj6E31lgSJBTXfM9GmaUoa4ef7r1WLtgIrxr4pZpZEUkJIvmgVzY8BvNOS50CeIVc07k35pz2WLWU7lhzg70FEAi3o57lso88LWO5rTnHJECbo1U04WOvoPP3C5Wv1TL/OCO7b6CGsitVUFupjDX/I59kepUhjPsomIDHeEgp5d45BEIT8NdPMgtcr+uufbwfYb4HCTyNvF1PQidNnrexPjNQb/m+kYCrQEAF/0c/Fr07TKTvYs1RF214cnMsMjPlahLWOgSuE2dVPJ+vudydDj83JxBBgF030N7ciR+N8+YSM+7HKjsfEpG2ud1ylp/rx4IeISquX4xdRCKyE7SGSzVS3xrEiAZ99Zd0YCXxUVFf+1ZfQ1bd/C+o3zjIEqpCcY0bZ3Zp8LW2Jv97+S2Rq3TKY2+VG/QGXAFBoCs/gXXVlebxDhR282Zfv75UDiFQC6W+zeTlkWHOgp02DzJt0c9991GChR9OLNxZN/0F6CY+2Xw4oFB/jKnkbvy8vWgOhDkakzxNQMbpYscAFxkJRIAosIL56K+B9xyS6vGH73+F/dc4PCloS86J5IbN80EYF+DuV/En5WKtCIr+9psengcXxKjRiqMbf4VLkN8wgxtAANG1VAg7Xl2KI/KgyiRIC/MGIJ4= X-Forefront-Antispam-Report: CIP:178.72.21.4; CTRY:DK; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:localhost.localdomain.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230031)(6069001)(346002)(39840400004)(376002)(136003)(396003)(82310400011)(451199024)(186009)(1800799009)(36840700001)(46966006)(118246002)(15974865002)(2906002)(30864003)(40480700001)(6506007)(6486002)(83380400001)(5660300002)(336012)(26005)(34020700004)(86362001)(36860700001)(47076005)(8676002)(2616005)(8936002)(956004)(107886003)(4326008)(70206006)(316002)(6512007)(70586007)(36736006)(9316004)(478600001)(356005)(81166007)(19627235002)(6666004)(36756003)(41300700001)(1076003)(21314003)(36900700001)(559001)(579004); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: Tj+iOE7yc/gIUGnlHIIS8ona7GMf7caN+Wy/+sBSU+92RkDkM8JyLe9z1Rvmo/E7aEYrdRb1jnBwIlLWSexvwsKsYF3wHQpLFIjLTWy0bu9D97FxwhApEJx3uX9S8Jti02Y/EMdpJpU0a9z9fFJMMu0kYumk6fyYJ7QkdM7EGKM4+AROxvs4zUPA0d3lzl25JKVe0uFuHqF8PL8DvkBPUQfQ1vwI1+7qNCCiV+da6swvErZ14fjn7dBBg2HW2TV0uSdDjJMMRAfQCxojHeImtBgnpjb6hiyEhg9ZBh3JosMfiHVtDuWoDiT0YtX6tTA8fCbbGvcoYrXSAboriVUxaE0hsEpOco3DpTebaxnLOaTWjbQUwtGj2n7jG4eBqaulo7cQp54ehFEn6/y79tmexCgJAflJ+0LlAkISV4SIURLwpdB6qk0zrXa1uBoWZsJLvtZvyQJZ6Sz1D0lB4jAL8DHbp/t21f9sjyqhowhMW40cKcn+CPt1fwC0tySYkhuYZvBRXgTjBm30c2HXWgzBl3MoQzpkUJM/Urh0kgZOb3GUBJLY/J4CYf+8Ox38TfS3ByU0XRn0gWjvmlHUNw9utNbL2bGDcDMoOlBBgqq8c26naF44MJnfxRpUlZDTBHgU6wYfV0RbfSpun90I1ZjtHZU9ZTFOjIdPFNJeslDkoP46Mz+LRfauV2d/FWK5RLrDPRMAb02v99m0VGAiKVJyIIF3hh7U/k5rYToNhQHICIL3SJDd13Kd4SebUMua9mWJIieopuFEPd6A0FMrcKIdBD6UeqDqmdBE3I6Jpo1qnpU= X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Aug 2023 13:54:27.9603 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 26b36a5e-f5c1-42ca-aeb3-08dba24e22fe X-MS-Exchange-CrossTenant-Id: c4540d0b-728a-4233-9da5-9ea30c7ec3ed X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=c4540d0b-728a-4233-9da5-9ea30c7ec3ed; Ip=[178.72.21.4]; Helo=[localhost.localdomain.com] X-MS-Exchange-CrossTenant-AuthSource: DU2PEPF0001E9C5.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9P190MB1481 X-BESS-ID: 1692626081-306084-12530-16951-1 X-BESS-VER: 2019.1_20230817.1828 X-BESS-Apparent-Source-IP: 104.47.51.237 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKVqaGhqaWZkB2BlDY1DQx1dgyzc Ii1cLSyMjY0iApydw4xdIsydDQMM0o0VCpNhYA5sucpEMAAAA= X-BESS-Outbound-Spam-Score: 0.00 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.250291 [from cloudscan14-148.eu-central-1a.ess.aws.cudaops.com] Rule breakdown below pts rule name description ---- ---------------------- -------------------------------- 0.00 LARGE_BODY_SHORTCUT META: X-BESS-Outbound-Spam-Status: SCORE=0.00 using account:ESS113687 scores of KILL_LEVEL=7.0 tests=LARGE_BODY_SHORTCUT X-BESS-BRTS-Status: 1 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 From: Christian Koue Muf Includes functionality to reset, initialize, program, and collect stats for the NTNIC FPGA. Signed-off-by: Christian Koue Muf Reviewed-by: Mykola Kostenok --- v2: * Fixed WARNING:TYPO_SPELLING * Fix compilation for Fedora38 v3: * Fixed WARNING:TYPO_SPELLING * Fix compilation for Fedora38 --- drivers/net/ntnic/include/nthw_bus.h | 10 + drivers/net/ntnic/meson.build | 32 + .../net/ntnic/nthw/core/nthw_clock_profiles.c | 9 + .../net/ntnic/nthw/core/nthw_clock_profiles.h | 39 + drivers/net/ntnic/nthw/core/nthw_core.h | 31 + drivers/net/ntnic/nthw/core/nthw_fpga.c | 914 +++++++++ drivers/net/ntnic/nthw/core/nthw_fpga.h | 47 + .../net/ntnic/nthw/core/nthw_fpga_nt200a0x.c | 46 + .../net/ntnic/nthw/core/nthw_fpga_nt200a0x.h | 14 + drivers/net/ntnic/nthw/core/nthw_fpga_rst.c | 10 + drivers/net/ntnic/nthw/core/nthw_fpga_rst.h | 17 + .../net/ntnic/nthw/core/nthw_fpga_rst9563.c | 241 +++ .../ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c | 674 +++++++ .../ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h | 89 + drivers/net/ntnic/nthw/core/nthw_gpio_phy.c | 271 +++ drivers/net/ntnic/nthw/core/nthw_gpio_phy.h | 57 + drivers/net/ntnic/nthw/core/nthw_hif.c | 342 ++++ drivers/net/ntnic/nthw/core/nthw_hif.h | 156 ++ drivers/net/ntnic/nthw/core/nthw_iic.c | 570 ++++++ drivers/net/ntnic/nthw/core/nthw_iic.h | 101 + drivers/net/ntnic/nthw/core/nthw_mac_pcs.c | 1034 ++++++++++ drivers/net/ntnic/nthw/core/nthw_mac_pcs.h | 261 +++ .../net/ntnic/nthw/core/nthw_mac_pcs_xxv.c | 1631 ++++++++++++++++ .../net/ntnic/nthw/core/nthw_mac_pcs_xxv.h | 291 +++ drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c | 121 ++ drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h | 51 + drivers/net/ntnic/nthw/core/nthw_pci_ta.c | 99 + drivers/net/ntnic/nthw/core/nthw_pci_ta.h | 40 + drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c | 127 ++ drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h | 55 + drivers/net/ntnic/nthw/core/nthw_pcie3.c | 274 +++ drivers/net/ntnic/nthw/core/nthw_pcie3.h | 100 + drivers/net/ntnic/nthw/core/nthw_sdc.c | 177 ++ drivers/net/ntnic/nthw/core/nthw_sdc.h | 43 + drivers/net/ntnic/nthw/core/nthw_si5340.c | 206 ++ drivers/net/ntnic/nthw/core/nthw_si5340.h | 34 + drivers/net/ntnic/nthw/core/nthw_spi_v3.c | 380 ++++ drivers/net/ntnic/nthw/core/nthw_spi_v3.h | 106 ++ drivers/net/ntnic/nthw/core/nthw_spim.c | 117 ++ drivers/net/ntnic/nthw/core/nthw_spim.h | 52 + drivers/net/ntnic/nthw/core/nthw_spis.c | 147 ++ drivers/net/ntnic/nthw/core/nthw_spis.h | 63 + drivers/net/ntnic/nthw/core/nthw_tsm.c | 179 ++ drivers/net/ntnic/nthw/core/nthw_tsm.h | 53 + drivers/net/ntnic/nthw/nthw_dbs.c | 1301 +++++++++++++ drivers/net/ntnic/nthw/nthw_dbs.h | 313 +++ drivers/net/ntnic/nthw/nthw_drv.h | 82 + drivers/net/ntnic/nthw/nthw_epp.c | 335 ++++ drivers/net/ntnic/nthw/nthw_epp.h | 99 + drivers/net/ntnic/nthw/nthw_fpga_model.c | 1677 +++++++++++++++++ drivers/net/ntnic/nthw/nthw_fpga_model.h | 308 +++ drivers/net/ntnic/nthw/nthw_helper.h | 21 + drivers/net/ntnic/nthw/nthw_platform.c | 35 + drivers/net/ntnic/nthw/nthw_platform_drv.h | 42 + drivers/net/ntnic/nthw/nthw_profile.h | 15 + drivers/net/ntnic/nthw/nthw_rac.c | 976 ++++++++++ drivers/net/ntnic/nthw/nthw_rac.h | 161 ++ drivers/net/ntnic/nthw/nthw_register.h | 2 + drivers/net/ntnic/nthw/nthw_stat.c | 266 +++ drivers/net/ntnic/nthw/nthw_stat.h | 72 + drivers/net/ntnic/ntlog/include/ntlog.h | 162 ++ drivers/net/ntnic/ntlog/ntlog.c | 115 ++ drivers/net/ntnic/ntutil/include/nt_util.h | 71 + drivers/net/ntnic/ntutil/nt_util.c | 77 + 64 files changed, 15441 insertions(+) create mode 100644 drivers/net/ntnic/include/nthw_bus.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_clock_profiles.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_clock_profiles.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_core.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_gpio_phy.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_gpio_phy.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_hif.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_hif.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_iic.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_iic.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_ta.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_ta.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcie3.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcie3.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_sdc.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_sdc.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_si5340.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_si5340.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_spi_v3.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_spi_v3.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_spim.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_spim.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_spis.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_spis.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_tsm.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_tsm.h create mode 100644 drivers/net/ntnic/nthw/nthw_dbs.c create mode 100644 drivers/net/ntnic/nthw/nthw_dbs.h create mode 100644 drivers/net/ntnic/nthw/nthw_drv.h create mode 100644 drivers/net/ntnic/nthw/nthw_epp.c create mode 100644 drivers/net/ntnic/nthw/nthw_epp.h create mode 100644 drivers/net/ntnic/nthw/nthw_fpga_model.c create mode 100644 drivers/net/ntnic/nthw/nthw_fpga_model.h create mode 100644 drivers/net/ntnic/nthw/nthw_helper.h create mode 100644 drivers/net/ntnic/nthw/nthw_platform.c create mode 100644 drivers/net/ntnic/nthw/nthw_platform_drv.h create mode 100644 drivers/net/ntnic/nthw/nthw_profile.h create mode 100644 drivers/net/ntnic/nthw/nthw_rac.c create mode 100644 drivers/net/ntnic/nthw/nthw_rac.h create mode 100644 drivers/net/ntnic/nthw/nthw_stat.c create mode 100644 drivers/net/ntnic/nthw/nthw_stat.h create mode 100644 drivers/net/ntnic/ntlog/include/ntlog.h create mode 100644 drivers/net/ntnic/ntlog/ntlog.c create mode 100644 drivers/net/ntnic/ntutil/include/nt_util.h create mode 100644 drivers/net/ntnic/ntutil/nt_util.c diff --git a/drivers/net/ntnic/include/nthw_bus.h b/drivers/net/ntnic/include/nthw_bus.h new file mode 100644 index 0000000000..975cc95e78 --- /dev/null +++ b/drivers/net/ntnic/include/nthw_bus.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_BUS_H__ +#define __NTHW_BUS_H__ + +typedef uint8_t rab_bus_id_t; + +#endif /* __NTHW_BUS_H__ */ diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build index 0e2c2d38cc..6f48af601f 100644 --- a/drivers/net/ntnic/meson.build +++ b/drivers/net/ntnic/meson.build @@ -17,13 +17,45 @@ endif includes = [ include_directories('.'), include_directories('include'), + include_directories('ntlog/include'), + include_directories('ntutil/include'), include_directories('nthw'), + include_directories('nthw/core'), include_directories('nthw/supported'), ] # all sources sources = files( + 'nthw/core/nthw_clock_profiles.c', + 'nthw/core/nthw_fpga.c', + 'nthw/core/nthw_fpga_nt200a0x.c', + 'nthw/core/nthw_fpga_rst.c', + 'nthw/core/nthw_fpga_rst9563.c', + 'nthw/core/nthw_fpga_rst_nt200a0x.c', + 'nthw/core/nthw_gpio_phy.c', + 'nthw/core/nthw_hif.c', + 'nthw/core/nthw_iic.c', + 'nthw/core/nthw_mac_pcs.c', + 'nthw/core/nthw_mac_pcs_xxv.c', + 'nthw/core/nthw_pci_rd_tg.c', + 'nthw/core/nthw_pci_ta.c', + 'nthw/core/nthw_pci_wr_tg.c', + 'nthw/core/nthw_pcie3.c', + 'nthw/core/nthw_sdc.c', + 'nthw/core/nthw_si5340.c', + 'nthw/core/nthw_spi_v3.c', + 'nthw/core/nthw_spim.c', + 'nthw/core/nthw_spis.c', + 'nthw/core/nthw_tsm.c', + 'nthw/nthw_fpga_model.c', + 'nthw/nthw_dbs.c', + 'nthw/nthw_epp.c', + 'nthw/nthw_platform.c', + 'nthw/nthw_rac.c', + 'nthw/nthw_stat.c', 'nthw/supported/nthw_fpga_9563_055_024_0000.c', + 'ntlog/ntlog.c', + 'ntutil/nt_util.c', ) if is_variable('default_cflags') diff --git a/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c new file mode 100644 index 0000000000..efdcc222a8 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nthw_clock_profiles.h" + +/* Clock profile for NT200A02 2x40G, 2x100G */ +const int n_data_si5340_nt200a02_u23_v5; +const clk_profile_data_fmt2_t *p_data_si5340_nt200a02_u23_v5; diff --git a/drivers/net/ntnic/nthw/core/nthw_clock_profiles.h b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.h new file mode 100644 index 0000000000..4252f69e92 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_CLOCK_PROFILES_H__ +#define __NTHW_CLOCK_PROFILES_H__ + +#include + +#include "nthw_helper.h" + +#define clk_profile_size_error_msg "size test failed" + +typedef struct { + unsigned char reg_addr; + unsigned char reg_val; + unsigned char reg_mask; +} clk_profile_data_fmt0_t; + +typedef struct { + uint16_t reg_addr; + uint8_t reg_val; +} clk_profile_data_fmt1_t; + +typedef struct { + unsigned int reg_addr; + unsigned char reg_val; +} clk_profile_data_fmt2_t; + +typedef enum { + CLK_PROFILE_DATA_FMT_0, + CLK_PROFILE_DATA_FMT_1, + CLK_PROFILE_DATA_FMT_2 +} clk_profile_data_fmt_t; + +extern const int n_data_si5340_nt200a02_u23_v5; +extern const clk_profile_data_fmt2_t *p_data_si5340_nt200a02_u23_v5; + +#endif /* __NTHW_CLOCK_PROFILES_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_core.h b/drivers/net/ntnic/nthw/core/nthw_core.h new file mode 100644 index 0000000000..798a95d5cf --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_core.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_CORE_H__ +#define __NTHW_CORE_H__ + +#include "nthw_helper.h" + +#include "nthw_platform_drv.h" +#include "nthw_fpga_model.h" +#include "nthw_hif.h" +#include "nthw_pcie3.h" +#include "nthw_pci_rd_tg.h" +#include "nthw_pci_wr_tg.h" +#include "nthw_pci_ta.h" +#include "nthw_iic.h" + +#include "nthw_gpio_phy.h" +#include "nthw_mac_pcs.h" +#include "nthw_mac_pcs_xxv.h" +#include "nthw_sdc.h" + +#include "nthw_spim.h" +#include "nthw_spis.h" + +#include "nthw_tsm.h" + +#include "nthw_si5340.h" + +#endif /* __NTHW_CORE_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga.c b/drivers/net/ntnic/nthw/core/nthw_fpga.c new file mode 100644 index 0000000000..646d45b7eb --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_fpga.c @@ -0,0 +1,914 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_fpga.h" +#include "nthw_fpga_instances.h" + +#include "nthw_spi_v3.h" + +#include + +int nthw_fpga_get_param_info(struct fpga_info_s *p_fpga_info, nt_fpga_t *p_fpga) +{ + const int n_nims = fpga_get_product_param(p_fpga, NT_NIMS, -1); + const int n_phy_ports = fpga_get_product_param(p_fpga, NT_PHY_PORTS, -1); + const int n_phy_quads = fpga_get_product_param(p_fpga, NT_PHY_QUADS, -1); + const int n_rx_ports = fpga_get_product_param(p_fpga, NT_RX_PORTS, -1); + const int n_tx_ports = fpga_get_product_param(p_fpga, NT_TX_PORTS, -1); + + p_fpga_info->n_nims = n_nims; + p_fpga_info->n_phy_ports = n_phy_ports; + p_fpga_info->n_phy_quads = n_phy_quads; + p_fpga_info->n_rx_ports = n_rx_ports; + p_fpga_info->n_tx_ports = n_tx_ports; + p_fpga_info->profile = FPGA_INFO_PROFILE_UNKNOWN; + + /* Check for VSWITCH FPGA */ + if (fpga_get_product_param(p_fpga, NT_NFV_OVS_PRODUCT, 0) != 0) + p_fpga_info->profile = FPGA_INFO_PROFILE_VSWITCH; + /* Check for VSWITCH FPGA - legacy */ + else if (fpga_get_product_param(p_fpga, NT_IOA_PRESENT, 0) != 0) + p_fpga_info->profile = FPGA_INFO_PROFILE_VSWITCH; + + else if (fpga_get_product_param(p_fpga, NT_QM_PRESENT, 0) != 0) + p_fpga_info->profile = FPGA_INFO_PROFILE_CAPTURE; + + else + p_fpga_info->profile = FPGA_INFO_PROFILE_INLINE; + + return 0; +} + +int nthw_fpga_iic_read_byte(nt_fpga_t *p_fpga, const int n_instance_no, + const uint8_t n_dev_addr, const uint8_t n_reg_addr) +{ + nthw_iic_t nthw_iic; + uint8_t val = 0; + + if (nthw_iic_init(&nthw_iic, p_fpga, n_instance_no, 8) != 0) + return -1; + + if (nthw_iic_readbyte(&nthw_iic, n_dev_addr, n_reg_addr, 1, &val) == 0) + return val; + + else + return -1; +} + +int nthw_fpga_iic_write_byte(nt_fpga_t *p_fpga, const int n_instance_no, + const uint8_t n_dev_addr, const uint8_t n_reg_addr, + uint8_t val) +{ + nthw_iic_t nthw_iic; + + if (nthw_iic_init(&nthw_iic, p_fpga, n_instance_no, 8) != 0) + return -1; + + if (nthw_iic_writebyte(&nthw_iic, n_dev_addr, n_reg_addr, 1, &val) != 0) + return -1; + + return 0; +} + +int nthw_fpga_iic_scan(nt_fpga_t *p_fpga, const int n_instance_no_begin, + const int n_instance_no_end) +{ + int i; + + assert(n_instance_no_begin <= n_instance_no_end); + + for (i = n_instance_no_begin; i <= n_instance_no_end; i++) { + nthw_iic_t *p_nthw_iic = nthw_iic_new(); + + if (p_nthw_iic) { + const int rc = nthw_iic_init(p_nthw_iic, p_fpga, i, 8); + + if (rc == 0) { + nthw_iic_set_retry_params(p_nthw_iic, -1, 100, 100, + 3, 3); + nthw_iic_scan(p_nthw_iic); + } + nthw_iic_delete(p_nthw_iic); + p_nthw_iic = NULL; + } + } + return 0; +} + +int nthw_fpga_silabs_detect(nt_fpga_t *p_fpga, const int n_instance_no, + const int n_dev_addr, const int n_page_reg_addr) +{ + const char *const p_adapter_id_str _unused = + p_fpga->p_fpga_info->mp_adapter_id_str; + uint64_t ident = -1; + int res = -1; + + nthw_iic_t *p_nthw_iic = nthw_iic_new(); + + if (p_nthw_iic) { + uint8_t data; + uint8_t a_silabs_ident[8]; + + nthw_iic_init(p_nthw_iic, p_fpga, n_instance_no, 8); + + data = 0; + /* switch to page 0 */ + nthw_iic_write_data(p_nthw_iic, (uint8_t)n_dev_addr, + (uint8_t)n_page_reg_addr, 1, &data); + res = nthw_iic_read_data(p_nthw_iic, (uint8_t)n_dev_addr, 0x00, + sizeof(a_silabs_ident), a_silabs_ident); + if (res == 0) { + int i; + + for (i = 0; i < (int)sizeof(a_silabs_ident); i++) { + ident <<= 8; + ident |= a_silabs_ident[i]; + } + } + nthw_iic_delete(p_nthw_iic); + p_nthw_iic = NULL; + + /* Conclude SiLabs part */ + if (res == 0) { + if (a_silabs_ident[3] == 0x53) { + if (a_silabs_ident[2] == 0x40) + res = 5340; + else if (a_silabs_ident[2] == 0x41) + res = 5341; + } else if (a_silabs_ident[2] == 38) { + res = 5338; + } else { + res = -1; + } + } + } + + NT_LOG(DBG, NTHW, "%s: %016" PRIX64 ": %d\n", p_adapter_id_str, ident, + res); + return res; +} + +/* + * Calculate CRC-16-CCITT of passed data + * CRC-16-CCITT ^16 + ^12 + ^5 + 1 (0x1021) (X.25, HDLC, XMODEM, Bluetooth, + * SD, many others; known as CRC-CCITT) + */ +static uint16_t crc16(uint8_t *buffer, size_t length) +{ + uint16_t seed = 0; + + while (length--) { + seed = (uint16_t)(seed >> 8 | seed << 8); + seed = (uint16_t)(seed ^ *buffer++); + seed = (uint16_t)(seed ^ (seed & 0xff) >> 4); + seed = (uint16_t)(seed ^ seed << 8 << 4); + seed = (uint16_t)(seed ^ (seed & 0xff) << 4 << 1); + } + return seed; +} + +int nthw_fpga_avr_probe(nt_fpga_t *p_fpga, const int n_instance_no) +{ + struct fpga_info_s *p_fpga_info = p_fpga->p_fpga_info; + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + nthw_spi_v3_t *p_avr_spi; + int res = -1; + + p_avr_spi = nthw_spi_v3_new(); + if (p_avr_spi) { + struct avr_vpd_info_s { + /* avr info */ + uint32_t n_avr_spi_version; + uint8_t n_avr_fw_ver_major; + uint8_t n_avr_fw_ver_minor; + uint8_t n_avr_fw_ver_micro; + uint8_t a_avr_fw_ver_str[50]; + uint8_t a_avr_fw_plat_id_str[20]; + + /* vpdEeprom_t */ + uint8_t psu_hw_version; + uint8_t vpd_pn[GEN2_PN_SIZE]; + uint8_t vpd_pba[GEN2_PBA_SIZE]; + uint8_t vpd_sn[GEN2_SN_SIZE]; + uint8_t vpd_board_name[GEN2_BNAME_SIZE]; + uint8_t vpd_platform_section[GEN2_PLATFORM_SIZE]; + + /* BoardInfo_t aka vpd_platform_section: */ + uint32_t product_family; /* uint8_t 1: capture, 2: Inline, 3: analysis */ + uint32_t feature_mask; /* Bit 0: OC192 capable */ + uint32_t invfeature_mask; + uint8_t no_of_macs; + uint8_t mac_address[6]; + uint16_t custom_id; + uint8_t user_id[8]; + /* + * Reserved NT operations to monitor the reprogram count of userId with + * vpduser + */ + uint16_t user_id_erase_write_count; + + /* + * AVR_OP_SYSINFO: struct version_sysinfo_request_container + * Which version of the sysinfo container to retrieve. Set to zero to fetch + * latest. offset zero of latest always contain an uint8_t version info + */ + uint8_t sysinfo_container_version; + + /* AVR_OP_SYSINFO: struct AvrLibcVersion */ + uint32_t sysinfo_avr_libc_version; /* The constant __AVR_LIBC_VERSION__ */ + + /* AVR_OP_SYSINFO: struct AvrLibcSignature */ + uint8_t sysinfo_signature_0; /* The constant SIGNATURE_0 */ + uint8_t sysinfo_signature_1; /* The constant SIGNATURE_1 */ + uint8_t sysinfo_signature_2; /* The constant SIGNATURE_2 */ + + /* AVR_OP_SYSINFO: struct AvrOs */ + uint8_t sysinfo_spi_version; /* SPI command layer version */ + /* + * Hardware revision. Locked to eeprom address zero. Is also available via + * VPD read opcode (prior to v1.4b, this is required) + */ + uint8_t sysinfo_hw_revision; + /* + * Number of ticks/second (Note: Be aware this may become zero if timer + * module is rewritten to a tickles system!) + */ + uint8_t sysinfo_ticks_per_second; + uint32_t sysinfo_uptime; /* Uptime in seconds since last AVR reset */ + uint8_t sysinfo_osccal; /* OSCCAL value */ + + /* + * Meta data concluded/calculated from req/reply + */ + bool b_feature_mask_valid; + bool b_crc16_valid; + uint16_t n_crc16_stored; + uint16_t n_crc16_calced; + uint64_t n_mac_val; + }; + + struct avr_vpd_info_s avr_vpd_info; + struct tx_rx_buf tx_buf; + struct tx_rx_buf rx_buf; + char rx_data[MAX_AVR_CONTAINER_SIZE]; + uint32_t u32; + + memset(&avr_vpd_info, 0, sizeof(avr_vpd_info)); + + nthw_spi_v3_init(p_avr_spi, p_fpga, n_instance_no); + + /* AVR_OP_SPI_VERSION */ + tx_buf.size = 0; + tx_buf.p_buf = NULL; + rx_buf.size = sizeof(u32); + rx_buf.p_buf = &u32; + u32 = 0; + res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SPI_VERSION, &tx_buf, + &rx_buf); + avr_vpd_info.n_avr_spi_version = u32; + NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.n_avr_spi_version); + + /* AVR_OP_VERSION */ + tx_buf.size = 0; + tx_buf.p_buf = NULL; + rx_buf.size = sizeof(rx_data); + rx_buf.p_buf = &rx_data; + res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_VERSION, &tx_buf, + &rx_buf); + + avr_vpd_info.n_avr_fw_ver_major = rx_data[0]; + avr_vpd_info.n_avr_fw_ver_minor = rx_data[1]; + avr_vpd_info.n_avr_fw_ver_micro = rx_data[2]; + NT_LOG(DBG, NTHW, "%s: AVR%d: FW_VER: %c.%c.%c\n", + p_adapter_id_str, n_instance_no, avr_vpd_info.n_avr_fw_ver_major, + avr_vpd_info.n_avr_fw_ver_minor, + avr_vpd_info.n_avr_fw_ver_micro); + + memcpy(avr_vpd_info.a_avr_fw_ver_str, &rx_data[0 + 3], + sizeof(avr_vpd_info.a_avr_fw_ver_str)); + NT_LOG(DBG, NTHW, "%s: AVR%d: FW_VER_STR: '%.*s'\n", + p_adapter_id_str, n_instance_no, + (int)sizeof(avr_vpd_info.a_avr_fw_ver_str), + avr_vpd_info.a_avr_fw_ver_str); + + memcpy(avr_vpd_info.a_avr_fw_plat_id_str, &rx_data[0 + 3 + 50], + sizeof(avr_vpd_info.a_avr_fw_plat_id_str)); + NT_LOG(DBG, NTHW, "%s: AVR%d: FW_HW_ID_STR: '%.*s'\n", + p_adapter_id_str, n_instance_no, + (int)sizeof(avr_vpd_info.a_avr_fw_plat_id_str), + avr_vpd_info.a_avr_fw_plat_id_str); + + rte_strscpy(p_fpga_info->nthw_hw_info.hw_plat_id_str, + (char *)avr_vpd_info.a_avr_fw_plat_id_str, + sizeof(p_fpga_info->nthw_hw_info.hw_plat_id_str)); + p_fpga_info->nthw_hw_info.hw_plat_id_str + [sizeof(p_fpga_info->nthw_hw_info.hw_plat_id_str) - 1] = + 0; + + /* AVR_OP_SYSINFO_2 */ + tx_buf.size = 0; + tx_buf.p_buf = NULL; + rx_buf.size = sizeof(rx_data); + rx_buf.p_buf = &rx_data; + res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SYSINFO_2, &tx_buf, + &rx_buf); + if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 && + rx_buf.size >= 16) { + if (rx_buf.size != 16) { + NT_LOG(WRN, NTHW, + "%s: AVR%d: SYSINFO2: reply is larger than expected: %04X %04X\n", + p_adapter_id_str, n_instance_no, rx_buf.size, + 16); + } else { + NT_LOG(DBG, NTHW, + "%s: AVR%d: SYSINFO2: OK: res=%d sz=%d\n", + p_adapter_id_str, n_instance_no, res, + rx_buf.size); + } + + avr_vpd_info.sysinfo_container_version = rx_data[0]; + NT_LOG(DBG, NTHW, "%s: AVR%d: SYSINFO_REQ_VER: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_container_version); + + memcpy(&avr_vpd_info.sysinfo_avr_libc_version, + &rx_data[0 + 1], + sizeof(avr_vpd_info.sysinfo_avr_libc_version)); + NT_LOG(DBG, NTHW, "%s: AVR%d: LIBC_VER: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_avr_libc_version); + + avr_vpd_info.sysinfo_signature_0 = rx_data[5]; + avr_vpd_info.sysinfo_signature_1 = rx_data[6]; + avr_vpd_info.sysinfo_signature_2 = rx_data[7]; + NT_LOG(DBG, NTHW, + "%s: AVR%d: SIGNATURE: %02x%02x%02x\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_signature_0, + avr_vpd_info.sysinfo_signature_1, + avr_vpd_info.sysinfo_signature_2); + + avr_vpd_info.sysinfo_spi_version = rx_data[8]; + NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_spi_version); + + avr_vpd_info.sysinfo_hw_revision = rx_data[9]; + NT_LOG(DBG, NTHW, "%s: AVR%d: HW_REV: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_hw_revision); + + avr_vpd_info.sysinfo_ticks_per_second = rx_data[10]; + NT_LOG(DBG, NTHW, "%s: AVR%d: TICKS_PER_SEC: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_ticks_per_second); + + memcpy(&avr_vpd_info.sysinfo_uptime, &rx_data[11], + sizeof(avr_vpd_info.sysinfo_uptime)); + NT_LOG(DBG, NTHW, "%s: AVR%d: UPTIME: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_uptime); + + avr_vpd_info.sysinfo_osccal = rx_data[15]; + NT_LOG(DBG, NTHW, "%s: AVR%d: OSCCAL: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_osccal); + + { + bool b_spi_ver_match _unused = + (avr_vpd_info.n_avr_spi_version == + avr_vpd_info.sysinfo_spi_version); + NT_LOG(DBG, NTHW, + "%s: AVR%d: SPI_VER_TST: %s (%d %d)\n", + p_adapter_id_str, n_instance_no, + (b_spi_ver_match ? "OK" : "MISMATCH"), + avr_vpd_info.n_avr_spi_version, + avr_vpd_info.sysinfo_spi_version); + } + /* SYSINFO2: if response: only populate hw_id not hw_id_emulated */ + p_fpga_info->nthw_hw_info.hw_id = + avr_vpd_info.sysinfo_hw_revision; + } else { + /* AVR_OP_SYSINFO */ + tx_buf.size = 0; + tx_buf.p_buf = NULL; + rx_buf.size = sizeof(rx_data); + rx_buf.p_buf = &rx_data; + res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SYSINFO, + &tx_buf, &rx_buf); + if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 && + rx_buf.size >= 16) { + if (rx_buf.size != 16) { + NT_LOG(WRN, NTHW, + "%s: AVR%d: SYSINFO: reply is larger than expected: %04X %04X\n", + p_adapter_id_str, n_instance_no, + rx_buf.size, 16); + } else { + NT_LOG(DBG, NTHW, + "%s: AVR%d: SYSINFO: OK: res=%d sz=%d\n", + p_adapter_id_str, n_instance_no, res, + rx_buf.size); + } + + avr_vpd_info.sysinfo_container_version = + rx_data[0]; + NT_LOG(DBG, NTHW, + "%s: AVR%d: SYSINFO_REQ_VER: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_container_version); + + memcpy(&avr_vpd_info.sysinfo_avr_libc_version, + &rx_data[0 + 1], + sizeof(avr_vpd_info + .sysinfo_avr_libc_version)); + NT_LOG(DBG, NTHW, "%s: AVR%d: LIBC_VER: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_avr_libc_version); + + avr_vpd_info.sysinfo_signature_0 = rx_data[5]; + avr_vpd_info.sysinfo_signature_1 = rx_data[6]; + avr_vpd_info.sysinfo_signature_2 = rx_data[7]; + NT_LOG(DBG, NTHW, + "%s: AVR%d: SIGNATURE: %02x%02x%02x\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_signature_0, + avr_vpd_info.sysinfo_signature_1, + avr_vpd_info.sysinfo_signature_2); + + avr_vpd_info.sysinfo_spi_version = rx_data[8]; + NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_spi_version); + + avr_vpd_info.sysinfo_hw_revision = rx_data[9]; + NT_LOG(DBG, NTHW, "%s: AVR%d: HW_REV: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_hw_revision); + NT_LOG(INF, NTHW, "%s: AVR%d: HW_REV: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_hw_revision); + + avr_vpd_info.sysinfo_ticks_per_second = + rx_data[10]; + NT_LOG(DBG, NTHW, + "%s: AVR%d: TICKS_PER_SEC: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_ticks_per_second); + + memcpy(&avr_vpd_info.sysinfo_uptime, + &rx_data[11], + sizeof(avr_vpd_info.sysinfo_uptime)); + NT_LOG(DBG, NTHW, "%s: AVR%d: UPTIME: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_uptime); + + avr_vpd_info.sysinfo_osccal = rx_data[15]; + NT_LOG(DBG, NTHW, "%s: AVR%d: OSCCAL: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_osccal); + + { + bool b_spi_ver_match _unused = + (avr_vpd_info.n_avr_spi_version == + avr_vpd_info + .sysinfo_spi_version); + NT_LOG(DBG, NTHW, + "%s: AVR%d: SPI_VER_TST: %s (%d %d)\n", + p_adapter_id_str, n_instance_no, + (b_spi_ver_match ? "OK" : + "MISMATCH"), + avr_vpd_info.n_avr_spi_version, + avr_vpd_info.sysinfo_spi_version); + } + + p_fpga_info->nthw_hw_info.hw_id = + avr_vpd_info.sysinfo_hw_revision; + p_fpga_info->nthw_hw_info.hw_id_emulated = + avr_vpd_info.sysinfo_hw_revision; + } else { + NT_LOG(ERR, NTHW, + "%s: AVR%d: SYSINFO: NA: res=%d sz=%d\n", + p_adapter_id_str, n_instance_no, res, + rx_buf.size); + } + } + + /* AVR_OP_VPD_READ */ + tx_buf.size = 0; + tx_buf.p_buf = NULL; + rx_buf.size = sizeof(rx_data); + rx_buf.p_buf = &rx_data; + res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_VPD_READ, &tx_buf, + &rx_buf); + if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 && + rx_buf.size >= GEN2_VPD_SIZE_TOTAL) { + avr_vpd_info.n_crc16_calced = + crc16(rx_buf.p_buf, rx_buf.size - 2); + memcpy(&avr_vpd_info.n_crc16_stored, + &rx_data[rx_buf.size - 2], + sizeof(avr_vpd_info.n_crc16_stored)); + NT_LOG(DBG, NTHW, "%s: AVR%d: VPD_CRC: %04X %04X\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.n_crc16_stored, + avr_vpd_info.n_crc16_calced); + + avr_vpd_info.b_crc16_valid = (avr_vpd_info.n_crc16_stored == + avr_vpd_info.n_crc16_calced); + NT_LOG(DBG, NTHW, "%s: AVR%d: CRC_TST: %s\n", + p_adapter_id_str, n_instance_no, + (avr_vpd_info.b_crc16_valid ? "OK" : "ERROR")); + + if (avr_vpd_info.b_crc16_valid) { + memcpy(&avr_vpd_info.psu_hw_version, &rx_data[0], + sizeof(avr_vpd_info.psu_hw_version)); + NT_LOG(DBG, NTHW, "%s: AVR%d: PSU_HW_VER: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.psu_hw_version); + + memcpy(&avr_vpd_info.vpd_pn, &rx_data[0 + 1], + sizeof(avr_vpd_info.vpd_pn)); + NT_LOG(DBG, NTHW, "%s: AVR%d: PN: '%.*s'\n", + p_adapter_id_str, n_instance_no, GEN2_PN_SIZE, + avr_vpd_info.vpd_pn); + + memcpy(&avr_vpd_info.vpd_pba, + &rx_data[0 + 1 + GEN2_PN_SIZE], + sizeof(avr_vpd_info.vpd_pba)); + NT_LOG(DBG, NTHW, "%s: AVR%d: PBA: '%.*s'\n", + p_adapter_id_str, n_instance_no, + GEN2_PBA_SIZE, avr_vpd_info.vpd_pba); + + memcpy(&avr_vpd_info.vpd_sn, + &rx_data[0 + 1 + GEN2_PN_SIZE + + GEN2_PBA_SIZE], + sizeof(avr_vpd_info.vpd_sn)); + NT_LOG(DBG, NTHW, "%s: AVR%d: SN: '%.*s'\n", + p_adapter_id_str, n_instance_no, GEN2_SN_SIZE, + avr_vpd_info.vpd_sn); + + memcpy(&avr_vpd_info.vpd_board_name, + &rx_data[0 + 1 + GEN2_PN_SIZE + + GEN2_PBA_SIZE + GEN2_SN_SIZE], + sizeof(avr_vpd_info.vpd_board_name)); + NT_LOG(DBG, NTHW, "%s: AVR%d: BN: '%.*s'\n", + p_adapter_id_str, n_instance_no, + GEN2_BNAME_SIZE, + avr_vpd_info.vpd_board_name); + + { + uint32_t u1; + union mac_u { + uint8_t a_u8[8]; + uint16_t a_u16[4]; + uint32_t a_u32[2]; + uint64_t a_u64[1]; + } mac; + + /* vpd_platform_section */ + uint8_t *p_vpd_board_info = + (uint8_t *)(&rx_data[1 + + GEN2_PN_SIZE + + GEN2_PBA_SIZE + + GEN2_SN_SIZE + + GEN2_BNAME_SIZE]); + memcpy(&avr_vpd_info.product_family, + &p_vpd_board_info[0], + sizeof(avr_vpd_info + .product_family)); + NT_LOG(DBG, NTHW, + "%s: AVR%d: PROD_FAM: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.product_family); + + memcpy(&avr_vpd_info.feature_mask, + &p_vpd_board_info[0 + 4], + sizeof(avr_vpd_info.feature_mask)); + NT_LOG(DBG, NTHW, + "%s: AVR%d: FMSK_VAL: 0x%08X\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.feature_mask); + + memcpy(&avr_vpd_info.invfeature_mask, + &p_vpd_board_info[0 + 4 + 4], + sizeof(avr_vpd_info + .invfeature_mask)); + NT_LOG(DBG, NTHW, + "%s: AVR%d: FMSK_INV: 0x%08X\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.invfeature_mask); + + avr_vpd_info.b_feature_mask_valid = + (avr_vpd_info.feature_mask == + ~avr_vpd_info.invfeature_mask); + NT_LOG(DBG, NTHW, + "%s: AVR%d: FMSK_TST: %s\n", + p_adapter_id_str, n_instance_no, + (avr_vpd_info.b_feature_mask_valid ? + "OK" : + "ERROR")); + + memcpy(&avr_vpd_info.no_of_macs, + &p_vpd_board_info[0 + 4 + 4 + 4], + sizeof(avr_vpd_info.no_of_macs)); + NT_LOG(DBG, NTHW, + "%s: AVR%d: NUM_MACS: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.no_of_macs); + + memcpy(&avr_vpd_info.mac_address, + &p_vpd_board_info[0 + 4 + 4 + 4 + 1], + sizeof(avr_vpd_info.mac_address)); + NT_LOG(DBG, NTHW, + "%s: AVR%d: MAC_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.mac_address[0], + avr_vpd_info.mac_address[1], + avr_vpd_info.mac_address[2], + avr_vpd_info.mac_address[3], + avr_vpd_info.mac_address[4], + avr_vpd_info.mac_address[5]); + + mac.a_u64[0] = 0; + memcpy(&mac.a_u8[2], + &avr_vpd_info.mac_address, + sizeof(avr_vpd_info.mac_address)); + u1 = ntohl(mac.a_u32[0]); + if (u1 != mac.a_u32[0]) { + const uint32_t u0 = ntohl(mac.a_u32[1]); + mac.a_u32[0] = u0; + mac.a_u32[1] = u1; + } + avr_vpd_info.n_mac_val = mac.a_u64[0]; + NT_LOG(DBG, NTHW, + "%s: AVR%d: MAC_U64: %012" PRIX64 + "\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.n_mac_val); + } + } + p_fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_count = + avr_vpd_info.no_of_macs; + p_fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_value = + avr_vpd_info.n_mac_val; + memcpy(p_fpga_info->nthw_hw_info.vpd_info.ma_mac_addr_octets, + avr_vpd_info.mac_address, + ARRAY_SIZE(p_fpga_info->nthw_hw_info.vpd_info + .ma_mac_addr_octets)); + } else { + NT_LOG(ERR, NTHW, "%s:%u: res=%d\n", __func__, __LINE__, + res); + NT_LOG(ERR, NTHW, + "%s: AVR%d: SYSINFO2: NA: res=%d sz=%d\n", + p_adapter_id_str, n_instance_no, res, rx_buf.size); + } + } + + return res; +} + +/* + * NT50B01, NT200A02, NT200A01-HWbuild2 + */ +int nthw_fpga_si5340_clock_synth_init_fmt2(nt_fpga_t *p_fpga, + const uint8_t n_iic_addr, + const clk_profile_data_fmt2_t *p_clk_profile, + const int n_clk_profile_rec_cnt) +{ + int res; + nthw_iic_t *p_nthw_iic = nthw_iic_new(); + nthw_si5340_t *p_nthw_si5340 = nthw_si5340_new(); + + assert(p_nthw_iic); + assert(p_nthw_si5340); + nthw_iic_init(p_nthw_iic, p_fpga, 0, 8); /* I2C cycle time 125Mhz ~ 8ns */ + + nthw_si5340_init(p_nthw_si5340, p_nthw_iic, + n_iic_addr); /* Si5340_U23_I2c_Addr_7bit */ + res = nthw_si5340_config_fmt2(p_nthw_si5340, p_clk_profile, + n_clk_profile_rec_cnt); + nthw_si5340_delete(p_nthw_si5340); + p_nthw_si5340 = NULL; + + return res; +} + +int nthw_fpga_init(struct fpga_info_s *p_fpga_info) +{ + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + + nthw_hif_t *p_nthw_hif = NULL; + nthw_pcie3_t *p_nthw_pcie3 = NULL; + nthw_rac_t *p_nthw_rac = NULL; + nthw_tsm_t *p_nthw_tsm = NULL; + + uint64_t n_fpga_ident = 0; + nt_fpga_mgr_t *p_fpga_mgr = NULL; + nt_fpga_t *p_fpga = NULL; + + char s_fpga_prod_ver_rev_str[32] = { 0 }; + + int res = 0; + + assert(p_fpga_info); + + { + int n_fpga_type_id, n_fpga_prod_id, n_fpga_ver_id, n_fpga_rev_id; + uint64_t n_fpga_ident; + uint32_t n_fpga_ident_low, n_fpga_ident_high, n_fpga_build_time; + + nthw_rac_reg_read32(p_fpga_info, 0x0, &n_fpga_ident_low); + nthw_rac_reg_read32(p_fpga_info, 0x8, &n_fpga_ident_high); + nthw_rac_reg_read32(p_fpga_info, 0x10, &n_fpga_build_time); + + n_fpga_ident = (((uint64_t)n_fpga_ident_high << 32) | n_fpga_ident_low); + n_fpga_type_id = FPGAID_TO_PRODUCTTYPE(n_fpga_ident); + n_fpga_prod_id = FPGAID_TO_PRODUCTCODE(n_fpga_ident); + n_fpga_ver_id = FPGAID_TO_VERSIONCODE(n_fpga_ident); + n_fpga_rev_id = FPGAID_TO_REVISIONCODE(n_fpga_ident); + + p_fpga_info->n_fpga_ident = n_fpga_ident; + p_fpga_info->n_fpga_type_id = n_fpga_type_id; + p_fpga_info->n_fpga_prod_id = n_fpga_prod_id; + p_fpga_info->n_fpga_ver_id = n_fpga_ver_id; + p_fpga_info->n_fpga_rev_id = n_fpga_rev_id; + p_fpga_info->n_fpga_build_time = n_fpga_build_time; + + snprintf(s_fpga_prod_ver_rev_str, sizeof(s_fpga_prod_ver_rev_str), + "%04d-%04d-%02d-%02d", n_fpga_type_id, n_fpga_prod_id, + n_fpga_ver_id, n_fpga_rev_id); + + NT_LOG(INF, NTHW, "%s: FPGA %s (%" PRIX64 ") [%08X]\n", + p_adapter_id_str, s_fpga_prod_ver_rev_str, n_fpga_ident, + n_fpga_build_time); + } + + n_fpga_ident = p_fpga_info->n_fpga_ident; + + p_fpga_mgr = fpga_mgr_new(); + fpga_mgr_init(p_fpga_mgr); + fpga_mgr_log_dump(p_fpga_mgr); + p_fpga = fpga_mgr_query_fpga(p_fpga_mgr, n_fpga_ident, p_fpga_info); + p_fpga_info->mp_fpga = p_fpga; + if (p_fpga == NULL) { + NT_LOG(ERR, NTHW, "%s: Unsupported FPGA: %s (%08X)\n", + p_adapter_id_str, s_fpga_prod_ver_rev_str, + p_fpga_info->n_fpga_build_time); + return -1; + } + + if (p_fpga_mgr) { + fpga_mgr_delete(p_fpga_mgr); + p_fpga_mgr = NULL; + } + + /* Read Fpga param info */ + nthw_fpga_get_param_info(p_fpga_info, p_fpga); + + /* debug: report params */ + NT_LOG(DBG, NTHW, "%s: NT_NIMS=%d\n", p_adapter_id_str, p_fpga_info->n_nims); + NT_LOG(DBG, NTHW, "%s: NT_PHY_PORTS=%d\n", p_adapter_id_str, + p_fpga_info->n_phy_ports); + NT_LOG(DBG, NTHW, "%s: NT_PHY_QUADS=%d\n", p_adapter_id_str, + p_fpga_info->n_phy_quads); + NT_LOG(DBG, NTHW, "%s: NT_RX_PORTS=%d\n", p_adapter_id_str, + p_fpga_info->n_rx_ports); + NT_LOG(DBG, NTHW, "%s: NT_TX_PORTS=%d\n", p_adapter_id_str, + p_fpga_info->n_tx_ports); + NT_LOG(DBG, NTHW, "%s: nProfile=%d\n", p_adapter_id_str, + (int)p_fpga_info->profile); + + p_nthw_rac = nthw_rac_new(); + if (p_nthw_rac == NULL) { + NT_LOG(ERR, NTHW, + "%s: Unsupported FPGA: RAC is not found: %s (%08X)\n", + p_adapter_id_str, s_fpga_prod_ver_rev_str, + p_fpga_info->n_fpga_build_time); + return -1; + } + + nthw_rac_init(p_nthw_rac, p_fpga, p_fpga_info); + nthw_rac_rab_flush(p_nthw_rac); + p_fpga_info->mp_nthw_rac = p_nthw_rac; + + /* special case: values below 0x100 will disable debug on RAC communication */ + { + const int n_fpga_initial_debug_mode = p_fpga_info->n_fpga_debug_mode; + + fpga_set_debug_mode(p_fpga, n_fpga_initial_debug_mode); + } + + switch (p_fpga_info->n_nthw_adapter_id) { + case NT_HW_ADAPTER_ID_NT200A01: /* fallthrough */ + case NT_HW_ADAPTER_ID_NT200A02: + res = nthw_fpga_nt200a0x_init(p_fpga_info); + break; + default: + NT_LOG(ERR, NTHW, "%s: Unsupported HW product id: %d\n", + p_adapter_id_str, p_fpga_info->n_nthw_adapter_id); + res = -1; + break; + } + + if (res) { + NT_LOG(ERR, NTHW, "%s: status: 0x%08X\n", p_adapter_id_str, res); + return res; + } + + res = nthw_pcie3_init(NULL, p_fpga, 0); /* Probe for module */ + if (res == 0) { + p_nthw_pcie3 = nthw_pcie3_new(); + if (p_nthw_pcie3) { + res = nthw_pcie3_init(p_nthw_pcie3, p_fpga, 0); + if (res == 0) { + NT_LOG(DBG, NTHW, "%s: Pcie3 module found\n", + p_adapter_id_str); + nthw_pcie3_trigger_sample_time(p_nthw_pcie3); + } else { + nthw_pcie3_delete(p_nthw_pcie3); + p_nthw_pcie3 = NULL; + } + } + p_fpga_info->mp_nthw_pcie3 = p_nthw_pcie3; + } + + if (p_nthw_pcie3 == NULL) { + p_nthw_hif = nthw_hif_new(); + if (p_nthw_hif) { + res = nthw_hif_init(p_nthw_hif, p_fpga, 0); + if (res == 0) { + NT_LOG(DBG, NTHW, "%s: Hif module found\n", + p_adapter_id_str); + nthw_hif_trigger_sample_time(p_nthw_hif); + } else { + nthw_hif_delete(p_nthw_hif); + p_nthw_hif = NULL; + } + } + } + p_fpga_info->mp_nthw_hif = p_nthw_hif; + + p_nthw_tsm = nthw_tsm_new(); + if (p_nthw_tsm) { + nthw_tsm_init(p_nthw_tsm, p_fpga, 0); + + nthw_tsm_set_config_ts_format(p_nthw_tsm, + 1); /* 1 = TSM: TS format native */ + + /* Timer T0 - stat toggle timer */ + nthw_tsm_set_timer_t0_enable(p_nthw_tsm, false); + nthw_tsm_set_timer_t0_max_count(p_nthw_tsm, 50 * 1000 * 1000); /* ns */ + nthw_tsm_set_timer_t0_enable(p_nthw_tsm, true); + + /* Timer T1 - keep alive timer */ + nthw_tsm_set_timer_t1_enable(p_nthw_tsm, false); + nthw_tsm_set_timer_t1_max_count(p_nthw_tsm, + 100 * 1000 * 1000); /* ns */ + nthw_tsm_set_timer_t1_enable(p_nthw_tsm, true); + } + p_fpga_info->mp_nthw_tsm = p_nthw_tsm; + + /* TSM sample triggering: test validation... */ +#if defined(DEBUG) && (1) + { + uint64_t n_time, n_ts; + int i; + + for (i = 0; i < 4; i++) { + if (p_nthw_hif) + nthw_hif_trigger_sample_time(p_nthw_hif); + + else if (p_nthw_pcie3) + nthw_pcie3_trigger_sample_time(p_nthw_pcie3); + nthw_tsm_get_time(p_nthw_tsm, &n_time); + nthw_tsm_get_ts(p_nthw_tsm, &n_ts); + + NT_LOG(DBG, NTHW, + "%s: TSM time: %016" PRIX64 " %016" PRIX64 "\n", + p_adapter_id_str, n_time, n_ts); + + NT_OS_WAIT_USEC(1000); + } + } +#endif + + return res; +} + +int nthw_fpga_shutdown(struct fpga_info_s *p_fpga_info) +{ + int res = -1; + + if (p_fpga_info) { + if (p_fpga_info && p_fpga_info->mp_nthw_rac) + res = nthw_rac_rab_reset(p_fpga_info->mp_nthw_rac); + } + + return res; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga.h b/drivers/net/ntnic/nthw/core/nthw_fpga.h new file mode 100644 index 0000000000..336d81f337 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_fpga.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_FPGA_H__ +#define __NTHW_FPGA_H__ + +#include "nthw_drv.h" + +#include "nthw_fpga_model.h" + +#include "nthw_rac.h" +#include "nthw_iic.h" + +#include "nthw_stat.h" + +#include "nthw_fpga_rst.h" + +#include "nthw_fpga_nt200a0x.h" + +#include "nthw_dbs.h" + +int nthw_fpga_init(struct fpga_info_s *p_fpga_info); +int nthw_fpga_shutdown(struct fpga_info_s *p_fpga_info); + +int nthw_fpga_get_param_info(struct fpga_info_s *p_fpga_info, nt_fpga_t *p_fpga); + +int nthw_fpga_avr_probe(nt_fpga_t *p_fpga, const int n_instance_no); + +int nthw_fpga_iic_scan(nt_fpga_t *p_fpga, const int n_instance_no_begin, + const int n_instance_no_end); + +int nthw_fpga_iic_read_byte(nt_fpga_t *p_fpga, const int n_instance_no, + const uint8_t n_dev_addr, const uint8_t n_reg_addr); +int nthw_fpga_iic_write_byte(nt_fpga_t *p_fpga, const int n_instance_no, + const uint8_t n_dev_addr, const uint8_t n_reg_addr, + uint8_t val); + +int nthw_fpga_silabs_detect(nt_fpga_t *p_fpga, const int n_instance_no, + const int n_dev_addr, const int n_page_reg_addr); + +int nthw_fpga_si5340_clock_synth_init_fmt2(nt_fpga_t *p_fpga, + const uint8_t n_iic_addr, + const clk_profile_data_fmt2_t *p_clk_profile, + const int n_clk_profile_rec_cnt); + +#endif /* __NTHW_FPGA_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c new file mode 100644 index 0000000000..70338fdfd7 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_fpga.h" +#include "nthw_fpga_nt200a0x.h" + +int nthw_fpga_nt200a0x_init(struct fpga_info_s *p_fpga_info) +{ + assert(p_fpga_info); + + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + struct nthw_fpga_rst_nt200a0x rst; + int res = -1; + + /* reset common */ + res = nthw_fpga_rst_nt200a0x_init(p_fpga_info, &rst); + if (res) { + NT_LOG(ERR, NTHW, "%s: %s: loc=%u: FPGA=%04d res=%d\n", + p_adapter_id_str, __func__, __LINE__, + p_fpga_info->n_fpga_prod_id, res); + return res; + } + + /* reset specific */ + switch (p_fpga_info->n_fpga_prod_id) { + case 9563: + res = nthw_fpga_rst9563_init(p_fpga_info, &rst); + break; + default: + NT_LOG(ERR, NTHW, "%s: Unsupported FPGA product: %04d\n", + p_adapter_id_str, p_fpga_info->n_fpga_prod_id); + res = -1; + break; + } + if (res) { + NT_LOG(ERR, NTHW, "%s: %s: loc=%u: FPGA=%04d res=%d\n", + p_adapter_id_str, __func__, __LINE__, + p_fpga_info->n_fpga_prod_id, res); + return res; + } + + return res; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h new file mode 100644 index 0000000000..ff324bee39 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_FPGA_NT200A0X_H__ +#define __NTHW_FPGA_NT200A0X_H__ + +int nthw_fpga_nt200a0x_init(struct fpga_info_s *p_fpga_info); + +/* NT200A02: 9563 */ +int nthw_fpga_rst9563_init(struct fpga_info_s *p_fpga_info, + struct nthw_fpga_rst_nt200a0x *const p); + +#endif /* __NTHW_FPGA_NT200A0X_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c new file mode 100644 index 0000000000..66c148bab2 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_fpga.h" +#include "nthw_fpga_nt200a0x.h" + +#include "nthw_fpga_rst.h" diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst.h b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.h new file mode 100644 index 0000000000..2099c4b677 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_FPGA_RST_H__ +#define __NTHW_FPGA_RST_H__ + +#include "nthw_drv.h" + +#include "nthw_fpga_model.h" + +#include "nthw_rac.h" +#include "nthw_iic.h" + +#include "nthw_fpga_rst_nt200a0x.h" + +#endif /* __NTHW_FPGA_RST_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c b/drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c new file mode 100644 index 0000000000..077b043c60 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c @@ -0,0 +1,241 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" +#include "nthw_fpga.h" + +#include "nthw_clock_profiles.h" + +static int nthw_fpga_rst9563_setup(nt_fpga_t *p_fpga, + struct nthw_fpga_rst_nt200a0x *const p) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + const int n_fpga_product_id = p_fpga->m_product_id; + const int n_fpga_version = p_fpga->m_fpga_version; + const int n_fpga_revision = p_fpga->m_fpga_revision; + + nt_module_t *p_mod_rst; + nt_register_t *p_curr_reg; + + assert(p); + p->mn_fpga_product_id = n_fpga_product_id; + p->mn_fpga_version = n_fpga_version; + p->mn_fpga_revision = n_fpga_revision; + + NT_LOG(DBG, NTHW, "%s: %s: FPGA reset setup: FPGA %04d-%02d-%02d\n", + p_adapter_id_str, __func__, n_fpga_product_id, n_fpga_version, + n_fpga_revision); + + p_mod_rst = fpga_query_module(p_fpga, MOD_RST9563, 0); + if (p_mod_rst == NULL) { + NT_LOG(ERR, NTHW, "%s: RST %d: no such instance\n", + p_adapter_id_str, 0); + return -1; + } + + p_mod_rst = fpga_query_module(p_fpga, MOD_RST9563, 0); + if (p_mod_rst == NULL) { + NT_LOG(ERR, NTHW, "%s: RST %d: no such instance\n", + p_adapter_id_str, 0); + return -1; + } + + /* RST register field pointers */ + p_curr_reg = module_get_register(p_mod_rst, RST9563_RST); + p->mp_fld_rst_sys = register_get_field(p_curr_reg, RST9563_RST_SYS); + p->mp_fld_rst_sys_mmcm = register_get_field(p_curr_reg, RST9563_RST_SYS_MMCM); + p->mp_fld_rst_core_mmcm = + register_get_field(p_curr_reg, RST9563_RST_CORE_MMCM); + p->mp_fld_rst_rpp = register_get_field(p_curr_reg, RST9563_RST_RPP); + p->mp_fld_rst_ddr4 = register_get_field(p_curr_reg, RST9563_RST_DDR4); + p->mp_fld_rst_sdc = register_get_field(p_curr_reg, RST9563_RST_SDC); + p->mp_fld_rst_phy = register_get_field(p_curr_reg, RST9563_RST_PHY); + p->mp_fld_rst_serdes_rx = NULL; /* Field not present on 9563 */ + p->mp_fld_rst_serdes_tx = NULL; /* Field not present on 9563 */ + p->mp_fld_rst_serdes_rx_datapath = NULL; /* Field not present on 9563 */ + p->mp_fld_rst_pcs_rx = NULL; /* Field not present on 9563 */ + p->mp_fld_rst_mac_rx = register_get_field(p_curr_reg, RST9563_RST_MAC_RX); + p->mp_fld_rst_mac_tx = NULL; + p->mp_fld_rst_ptp = register_get_field(p_curr_reg, RST9563_RST_PTP); + p->mp_fld_rst_ptp = register_get_field(p_curr_reg, RST9563_RST_PTP); + p->mp_fld_rst_ts = register_get_field(p_curr_reg, RST9563_RST_TS); + p->mp_fld_rst_ptp_mmcm = register_get_field(p_curr_reg, RST9563_RST_PTP_MMCM); + p->mp_fld_rst_ts_mmcm = register_get_field(p_curr_reg, RST9563_RST_TS_MMCM); + /* referenced in separate function */ + p->mp_fld_rst_periph = register_get_field(p_curr_reg, RST9563_RST_PERIPH); + p->mp_fld_rst_tsm_ref_mmcm = + register_query_field(p_curr_reg, RST9563_RST_TSM_REF_MMCM); + p->mp_fld_rst_tmc = register_query_field(p_curr_reg, RST9563_RST_TMC); + + if (!p->mp_fld_rst_tsm_ref_mmcm) { + NT_LOG(DBG, NTHW, "%s: No RST9563_RST_TSM_REF_MMCM found\n", + p_adapter_id_str); + } + if (!p->mp_fld_rst_tmc) { + NT_LOG(DBG, NTHW, "%s: No RST9563_RST_TMC found\n", + p_adapter_id_str); + } + register_update(p_curr_reg); + + /* CTRL register field pointers */ + p_curr_reg = module_get_register(p_mod_rst, RST9563_CTRL); + p->mp_fld_ctrl_ts_clk_sel_override = + register_get_field(p_curr_reg, RST9563_CTRL_TS_CLKSEL_OVERRIDE); + /* Field not present on 9563 */ + p->mp_fld_ctrl_ts_clk_sel = + register_get_field(p_curr_reg, RST9563_CTRL_TS_CLKSEL); + p->mp_fld_ctrl_ts_clk_sel_ref = NULL; /* Field not present on 9563 */ + p->mp_fld_ctrl_ptp_mmcm_clk_sel = + register_get_field(p_curr_reg, RST9563_CTRL_PTP_MMCM_CLKSEL); + register_update(p_curr_reg); + + /* STAT register field pointers */ + p_curr_reg = module_get_register(p_mod_rst, RST9563_STAT); + p->mp_fld_stat_ddr4_mmcm_locked = + register_get_field(p_curr_reg, RST9563_STAT_DDR4_MMCM_LOCKED); + p->mp_fld_stat_sys_mmcm_locked = + register_get_field(p_curr_reg, RST9563_STAT_SYS_MMCM_LOCKED); + p->mp_fld_stat_core_mmcm_locked = + register_get_field(p_curr_reg, RST9563_STAT_CORE_MMCM_LOCKED); + p->mp_fld_stat_ddr4_pll_locked = + register_get_field(p_curr_reg, RST9563_STAT_DDR4_PLL_LOCKED); + p->mp_fld_stat_ptp_mmcm_locked = + register_get_field(p_curr_reg, RST9563_STAT_PTP_MMCM_LOCKED); + p->mp_fld_stat_ts_mmcm_locked = + register_get_field(p_curr_reg, RST9563_STAT_TS_MMCM_LOCKED); + p->mp_fld_stat_tsm_ref_mmcm_locked = NULL; /* Field not present on 9563 */ + + if (!p->mp_fld_stat_tsm_ref_mmcm_locked) { + NT_LOG(DBG, NTHW, + "%s: No RST9563_STAT_TSM_REF_MMCM_LOCKED found\n", + p_adapter_id_str); + } + register_update(p_curr_reg); + + /* STICKY register field pointers */ + p_curr_reg = module_get_register(p_mod_rst, RST9563_STICKY); + p->mp_fld_sticky_ptp_mmcm_unlocked = + register_get_field(p_curr_reg, RST9563_STICKY_PTP_MMCM_UNLOCKED); + p->mp_fld_sticky_ts_mmcm_unlocked = + register_get_field(p_curr_reg, RST9563_STICKY_TS_MMCM_UNLOCKED); + p->mp_fld_sticky_ddr4_mmcm_unlocked = + register_get_field(p_curr_reg, RST9563_STICKY_DDR4_MMCM_UNLOCKED); + p->mp_fld_sticky_ddr4_pll_unlocked = + register_get_field(p_curr_reg, RST9563_STICKY_DDR4_PLL_UNLOCKED); + p->mp_fld_sticky_core_mmcm_unlocked = + register_get_field(p_curr_reg, RST9563_STICKY_CORE_MMCM_UNLOCKED); + p->mp_fld_sticky_pci_sys_mmcm_unlocked = NULL; /* Field not present on 9563 */ + p->mp_fld_sticky_tsm_ref_mmcm_unlocked = NULL; /* Field not present on 9563 */ + + if (!p->mp_fld_sticky_tsm_ref_mmcm_unlocked) { + NT_LOG(DBG, NTHW, + "%s: No RST9563_STICKY_TSM_REF_MMCM_UNLOCKED found\n", + p_adapter_id_str); + } + register_update(p_curr_reg); + + /* POWER register field pointers */ + p_curr_reg = module_get_register(p_mod_rst, RST9563_POWER); + p->mp_fld_power_pu_phy = register_get_field(p_curr_reg, RST9563_POWER_PU_PHY); + p->mp_fld_power_pu_nseb = + register_get_field(p_curr_reg, RST9563_POWER_PU_NSEB); + register_update(p_curr_reg); + + return 0; +} + +static int nthw_fpga_rst9563_periph_reset(nt_fpga_t *p_fpga) +{ + const char *const _unused p_adapter_id_str = + p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod_rst = fpga_query_module(p_fpga, MOD_RST9563, 0); + + if (p_mod_rst) { + nt_register_t *p_reg_rst; + nt_field_t *p_fld_rst_periph; + + NT_LOG(DBG, NTHW, "%s: PERIPH RST\n", p_adapter_id_str); + p_reg_rst = module_get_register(p_mod_rst, RST9563_RST); + p_fld_rst_periph = register_get_field(p_reg_rst, RST9563_RST_PERIPH); + field_set_flush(p_fld_rst_periph); + field_clr_flush(p_fld_rst_periph); + } else { + return -1; + } + return 0; +} + +static int +nthw_fpga_rst9563_clock_synth_init(nt_fpga_t *p_fpga, + const int n_si_labs_clock_synth_model, + const uint8_t n_si_labs_clock_synth_i2c_addr) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + const int n_fpga_product_id = p_fpga->m_product_id; + int res; + + if (n_si_labs_clock_synth_model == 5340) { + res = nthw_fpga_si5340_clock_synth_init_fmt2(p_fpga, + n_si_labs_clock_synth_i2c_addr, + p_data_si5340_nt200a02_u23_v5, + n_data_si5340_nt200a02_u23_v5); + } else { + NT_LOG(ERR, NTHW, + "%s: Fpga %d: Unsupported clock synth model (%d)\n", + p_adapter_id_str, n_fpga_product_id, n_si_labs_clock_synth_model); + res = -1; + } + return res; +} + +int nthw_fpga_rst9563_init(struct fpga_info_s *p_fpga_info, + struct nthw_fpga_rst_nt200a0x *p_rst) +{ + assert(p_fpga_info); + assert(p_rst); + + const char *const _unused p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + int res = -1; + int n_si_labs_clock_synth_model; + uint8_t n_si_labs_clock_synth_i2c_addr; + nt_fpga_t *p_fpga = NULL; + + p_fpga = p_fpga_info->mp_fpga; + n_si_labs_clock_synth_model = p_rst->mn_si_labs_clock_synth_model; + n_si_labs_clock_synth_i2c_addr = p_rst->mn_si_labs_clock_synth_i2c_addr; + + res = nthw_fpga_rst9563_periph_reset(p_fpga); + if (res) { + NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str, + res, __func__, __LINE__); + return res; + } + + res = nthw_fpga_rst9563_clock_synth_init(p_fpga, n_si_labs_clock_synth_model, + n_si_labs_clock_synth_i2c_addr); + if (res) { + NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str, + res, __func__, __LINE__); + return res; + } + + res = nthw_fpga_rst9563_setup(p_fpga, p_rst); + if (res) { + NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str, + res, __func__, __LINE__); + return res; + } + + res = nthw_fpga_rst_nt200a0x_reset(p_fpga, p_rst); + if (res) { + NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str, + res, __func__, __LINE__); + return res; + } + + return res; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c new file mode 100644 index 0000000000..ae63fefb09 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c @@ -0,0 +1,674 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" +#include "nthw_fpga.h" + +static const uint8_t si5338_u23_i2c_addr_7bit = 0x70; +static const uint8_t si5340_u23_i2c_addr_7bit = 0x74; + +/* + * Wait until DDR4 PLL LOCKED + */ +static int nthw_fpga_rst_nt200a0x_wait_ddr4_pll_locked(nt_fpga_t *p_fpga, + const struct nthw_fpga_rst_nt200a0x *p) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + uint32_t locked; + uint32_t retrycount = 5; + uint32_t timeout = 50000; /* initial timeout must be set to 5 sec. */ + /* 14: wait until DDR4 PLL LOCKED */ + NT_LOG(DBG, NTHW, "%s: Waiting for DDR4 PLL to lock\n", p_adapter_id_str); + /* + * The following retry count gives a total timeout of 1 * 5 + 5 * 8 = 45sec + * It has been observed that at least 21sec can be necessary + */ + while (true) { + int locked = field_wait_set_any32(p->mp_fld_stat_ddr4_pll_locked, + timeout, 100); + if (locked == 0) + break; + NT_LOG(DBG, NTHW, + "%s: Waiting for DDR4 PLL to lock - timeout\n", + p_adapter_id_str); + if (retrycount <= 0) { + NT_LOG(ERR, NTHW, + "%s: Waiting for DDR4 PLL to lock failed (%d)\n", + p_adapter_id_str, locked); + break; + } + field_set_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */ + field_clr_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */ + retrycount--; + timeout = + 80000; /* Increase timeout for second attempt to 8 sec. */ + } + + NT_LOG(DBG, NTHW, "%s: Waiting for DDR4 MMCM to lock\n", p_adapter_id_str); + locked = field_wait_set_any32(p->mp_fld_stat_ddr4_mmcm_locked, -1, -1); + if (locked != 0) { + NT_LOG(ERR, NTHW, + "%s: Waiting for DDR4 MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + return -1; + } + + if ((true) && p->mp_fld_stat_tsm_ref_mmcm_locked) { + NT_LOG(DBG, NTHW, "%s: Waiting for TSM REF MMCM to lock\n", + p_adapter_id_str); + locked = field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked, -1, + -1); + if (locked != 0) { + NT_LOG(ERR, NTHW, + "%s: Waiting for TSM REF MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + return -1; + } + } + + /* 10: Clear all MMCM/PLL lock sticky bits before testing them */ + NT_LOG(DBG, NTHW, "%s: Clear sticky MMCM unlock bits\n", p_adapter_id_str); + field_update_register(p->mp_fld_sticky_ptp_mmcm_unlocked); + /* Clear all sticky bits */ + field_set_flush(p->mp_fld_sticky_ptp_mmcm_unlocked); + field_set_flush(p->mp_fld_sticky_ts_mmcm_unlocked); + field_set_flush(p->mp_fld_sticky_ddr4_mmcm_unlocked); + field_set_flush(p->mp_fld_sticky_ddr4_pll_unlocked); + field_set_flush(p->mp_fld_sticky_core_mmcm_unlocked); + if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked) + field_set_flush(p->mp_fld_sticky_tsm_ref_mmcm_unlocked); + if (p->mp_fld_sticky_pci_sys_mmcm_unlocked) + field_set_flush(p->mp_fld_sticky_pci_sys_mmcm_unlocked); + + /* 11: Ensure sticky bits are not unlocked except PTP MMCM and TS MMCM */ + if (field_get_updated(p->mp_fld_sticky_ddr4_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, + "%s: get_sticky_ddr4_mmcm_unlocked() returned true\n", + p_adapter_id_str); + } + + if (field_get_updated(p->mp_fld_sticky_ddr4_pll_unlocked)) { + NT_LOG(ERR, NTHW, + "%s: get_sticky_ddr4_pll_unlocked() returned true\n", + p_adapter_id_str); + } + + return 0; +} + +/* + * Wait for SDRAM controller has been calibrated - On some adapters we have seen + * calibration time of 2.3 seconds + */ +static int +nthw_fpga_rst_nt200a0x_wait_sdc_calibrated(nt_fpga_t *p_fpga, + const struct nthw_fpga_rst_nt200a0x *p) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nthw_sdc_t *p_nthw_sdc = NULL; + const int n_retry_cnt_max = 5; + int n_retry_cnt; + int res; + + res = nthw_sdc_init(NULL, p_fpga, 0); /* probe for module */ + if (res == 0) { + p_nthw_sdc = nthw_sdc_new(); + if (p_nthw_sdc) { + res = nthw_sdc_init(p_nthw_sdc, p_fpga, 0); + if (res) { + NT_LOG(ERR, NTHW, + "%s: SDC init failed: res=%d [%s:%d]\n", + p_adapter_id_str, res, __func__, __LINE__); + nthw_sdc_delete(p_nthw_sdc); + p_nthw_sdc = NULL; + return -1; + } + } else { + nthw_sdc_delete(p_nthw_sdc); + p_nthw_sdc = NULL; + } + } else { + NT_LOG(DBG, NTHW, "%s: No SDC found\n", p_adapter_id_str); + } + n_retry_cnt = 0; + res = -1; + while ((res != 0) && (n_retry_cnt <= n_retry_cnt_max)) { + /* wait until DDR4 PLL LOCKED */ + res = nthw_fpga_rst_nt200a0x_wait_ddr4_pll_locked(p_fpga, p); + if (res == 0) { + if (p_nthw_sdc) { + /* + * Wait for SDRAM controller has been calibrated + * On some adapters we have seen calibration time of 2.3 seconds + */ + NT_LOG(DBG, NTHW, + "%s: Waiting for SDRAM to calibrate\n", + p_adapter_id_str); + res = nthw_sdc_wait_states(p_nthw_sdc, 10000, 1000); + { + uint64_t n_result_mask; + + int n_state_code _unused = + nthw_sdc_get_states(p_nthw_sdc, + &n_result_mask); + NT_LOG(DBG, NTHW, + "%s: SDRAM state=0x%08lX state_code=%d retry=%d code=%d\n", + p_adapter_id_str, n_result_mask, + n_state_code, n_retry_cnt, res); + } + if (res == 0) + break; + } + + if (n_retry_cnt >= n_retry_cnt_max) { + uint64_t n_result_mask; + int n_state_code _unused = nthw_sdc_get_states(p_nthw_sdc, + &n_result_mask); + + NT_LOG(DBG, NTHW, + "%s: SDRAM state=0x%08lX state_code=%d retry=%d code=%d\n", + p_adapter_id_str, n_result_mask, n_state_code, + n_retry_cnt, res); + if (res != 0) { + NT_LOG(ERR, NTHW, + "%s: Timeout waiting for SDRAM controller calibration\n", + p_adapter_id_str); + } + } + } + + /* + * SDRAM controller is not calibrated with DDR4 ram blocks: + * reset DDR and perform calibration retry + */ + field_set_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */ + NT_OS_WAIT_USEC(100); + field_clr_flush(p->mp_fld_rst_ddr4); + + n_retry_cnt++; + } + nthw_sdc_delete(p_nthw_sdc); + + return res; +} + +int nthw_fpga_rst_nt200a0x_reset(nt_fpga_t *p_fpga, + const struct nthw_fpga_rst_nt200a0x *p) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + const fpga_info_t *const p_fpga_info = p_fpga->p_fpga_info; + + const int n_fpga_product_id = p->mn_fpga_product_id; + const int n_fpga_version = p->mn_fpga_version; + const int n_fpga_revision = p->mn_fpga_revision; + const int n_nthw_adapter_id = p_fpga_info->n_nthw_adapter_id; + const bool b_is_nt200a01 = (n_nthw_adapter_id == NT_HW_ADAPTER_ID_NT200A01); + const int n_hw_id = p_fpga_info->nthw_hw_info.hw_id; + const uint8_t index = 0; + int locked; + int res = -1; + + NT_LOG(DBG, NTHW, + "%s: %s: FPGA reset sequence: FPGA %04d-%02d-%02d @ HWId%d\n", + p_adapter_id_str, __func__, n_fpga_product_id, n_fpga_version, + n_fpga_revision, n_hw_id); + assert(n_fpga_product_id == p_fpga->m_product_id); + + /* + * Reset all domains / modules except peripherals + * Set default reset values to ensure that all modules are reset correctly + * no matter if nic has been powercycled or ntservice has been reloaded + */ + + /* + * Reset to defaults + * 1: Reset all domains + */ + NT_LOG(DBG, NTHW, "%s: RST defaults\n", p_adapter_id_str); + + field_update_register(p->mp_fld_rst_sys); + field_set_flush(p->mp_fld_rst_sys); + if (p->mp_fld_rst_tmc) + field_set_flush(p->mp_fld_rst_tmc); + field_set_flush(p->mp_fld_rst_rpp); + field_set_flush(p->mp_fld_rst_ddr4); /* 0x07 3 banks */ + field_set_flush(p->mp_fld_rst_sdc); + + /* Reset port 0 and 1 in the following registers: */ + field_set_flush(p->mp_fld_rst_phy); /* 0x03 2 ports */ + if (p->mp_fld_rst_mac_rx) + field_set_flush(p->mp_fld_rst_mac_rx); /* 0x03 2 ports */ + + if (p->mp_fld_rst_mac_tx) + field_set_flush(p->mp_fld_rst_mac_tx); /* 0x03 2 ports */ + + if (p->mp_fld_rst_pcs_rx) + field_set_flush(p->mp_fld_rst_pcs_rx); /* 0x03 2 ports */ + + if (p->mp_fld_rst_serdes_rx) + field_set_flush(p->mp_fld_rst_serdes_rx); /* 0x03 2 ports */ + + if (p->mp_fld_rst_serdes_rx_datapath) { + field_set_flush(p->mp_fld_rst_serdes_rx_datapath); + field_clr_flush(p->mp_fld_rst_serdes_rx); + } + if (p->mp_fld_rst_serdes_tx) + field_set_flush(p->mp_fld_rst_serdes_tx); + + field_set_flush(p->mp_fld_rst_ptp); + field_set_flush(p->mp_fld_rst_ts); + field_set_flush(p->mp_fld_rst_sys_mmcm); + field_set_flush(p->mp_fld_rst_core_mmcm); + field_set_flush(p->mp_fld_rst_ptp_mmcm); + field_set_flush(p->mp_fld_rst_ts_mmcm); + + if ((true) && p->mp_fld_rst_tsm_ref_mmcm) + field_set_flush(p->mp_fld_rst_tsm_ref_mmcm); + + /* Write all changes to register */ + field_flush_register(p->mp_fld_rst_sys); + + if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */ + if (p->mp_fld_rst_tsm_ref_mmcm) { + field_update_register(p->mp_fld_rst_tsm_ref_mmcm); + field_set_flush(p->mp_fld_rst_tsm_ref_mmcm); + } + } + + /* + * 2: Force use of 50 MHz reference clock for timesync; + * NOTE: From 9508-05-18 this is a 20 MHz clock + */ + NT_LOG(DBG, NTHW, "%s: Setting TS CLK SEL OVERRIDE\n", p_adapter_id_str); + field_update_register(p->mp_fld_ctrl_ts_clk_sel_override); + field_set_flush(p->mp_fld_ctrl_ts_clk_sel_override); + + NT_LOG(DBG, NTHW, "%s: Setting TS CLK SEL\n", p_adapter_id_str); + field_update_register(p->mp_fld_ctrl_ts_clk_sel); + field_set_flush(p->mp_fld_ctrl_ts_clk_sel); + + if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */ + NT_LOG(DBG, NTHW, "%s: _selecting 20MHz TS CLK SEL REF\n", + p_adapter_id_str); + if (p->mp_fld_ctrl_ts_clk_sel_ref) { + field_update_register(p->mp_fld_ctrl_ts_clk_sel_ref); + field_clr_flush(p->mp_fld_ctrl_ts_clk_sel_ref); + } + } + + /* 4: De-assert sys reset, CORE and SYS MMCM resets */ + NT_LOG(DBG, NTHW, "%s: De-asserting SYS, CORE and SYS MMCM resets\n", + p_adapter_id_str); + field_update_register(p->mp_fld_rst_sys); + field_clr_flush(p->mp_fld_rst_sys); + field_clr_flush(p->mp_fld_rst_sys_mmcm); + field_clr_flush(p->mp_fld_rst_core_mmcm); + + /* 5: wait until CORE MMCM and SYS MMCM are LOCKED */ + NT_LOG(DBG, NTHW, "%s: Waiting for SYS MMCM to lock\n", p_adapter_id_str); + locked = field_wait_set_any32(p->mp_fld_stat_sys_mmcm_locked, -1, -1); + if (locked != 0) { + NT_LOG(ERR, NTHW, + "%s: Waiting for SYS MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + } + + NT_LOG(DBG, NTHW, "%s: Waiting for CORE MMCM to lock\n", p_adapter_id_str); + locked = field_wait_set_any32(p->mp_fld_stat_core_mmcm_locked, -1, -1); + if (locked != 0) { + NT_LOG(ERR, NTHW, + "%s: Waiting for CORE MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + } + + /* RAC RAB bus "flip/flip" reset second stage - new impl (ref RMT#37020) */ + /* RAC/RAB init - SYS/CORE MMCM is locked - pull the remaining RAB buses out of reset */ + { + nthw_rac_t *p_nthw_rac = p_fpga_info->mp_nthw_rac; + + NT_LOG(DBG, NTHW, "%s: De-asserting remaining RAB buses\n", + p_adapter_id_str); + nthw_rac_rab_init(p_nthw_rac, 0); + } + + if ((true) && p->mp_fld_rst_tsm_ref_mmcm) { + NT_LOG(DBG, NTHW, "%s: De-asserting TSM REF MMCM\n", + p_adapter_id_str); + field_clr_flush(p->mp_fld_rst_tsm_ref_mmcm); + if (p->mp_fld_stat_tsm_ref_mmcm_locked) { + NT_LOG(DBG, NTHW, + "%s: Waiting for TSM REF MMCM to lock\n", + p_adapter_id_str); + locked = field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked, + -1, -1); + if (locked != 0) { + NT_LOG(ERR, NTHW, + "%s: Waiting for TSM REF MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + } + } + } + + /* + * 5.2: Having ensured CORE MMCM and SYS MMCM are LOCKED, + * we need to select the alternative 20 MHz reference clock, + * the external TSM reference clock + * on NT200A01 - build 2 HW only (see SSF00024 p.32) + */ + if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */ + NT_LOG(DBG, NTHW, "%s: Setting TS CLK SEL REF\n", + p_adapter_id_str); + if (p->mp_fld_ctrl_ts_clk_sel_ref) + field_set_flush(p->mp_fld_ctrl_ts_clk_sel_ref); + if (p->mp_fld_rst_tsm_ref_mmcm) { + NT_LOG(DBG, NTHW, "%s: De-asserting TSM REF MMCM\n", + p_adapter_id_str); + field_clr_flush(p->mp_fld_rst_tsm_ref_mmcm); + } + NT_LOG(DBG, NTHW, "%s: Waiting for TSM REF MMCM to lock\n", + p_adapter_id_str); + if (p->mp_fld_stat_tsm_ref_mmcm_locked) { + locked = field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked, + -1, -1); + if (locked != 0) { + NT_LOG(ERR, NTHW, + "%s: Waiting for TSM REF MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + } + } + } + + NT_LOG(DBG, NTHW, "%s: De-asserting all PHY resets\n", p_adapter_id_str); + field_update_register(p->mp_fld_rst_phy); + field_clr_flush(p->mp_fld_rst_phy); + + /* MAC_PCS_XXV 10G/25G: 9530 / 9544 */ + if (n_fpga_product_id == 9530 || n_fpga_product_id == 9544) { + { + /* Based on nt200e3_2_ptp.cpp My25GbPhy::resetRx */ + nthw_mac_pcs_xxv_t *p_nthw_mac_pcs_xxv0 = nthw_mac_pcs_xxv_new(); + + assert(p_nthw_mac_pcs_xxv0); + nthw_mac_pcs_xxv_init(p_nthw_mac_pcs_xxv0, p_fpga, 0, 1); + + nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv0, true, + index); + NT_OS_WAIT_USEC(1000); + + nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv0, false, + index); + NT_OS_WAIT_USEC(1000); + + nthw_mac_pcs_xxv_delete(p_nthw_mac_pcs_xxv0); + } + + { + /* Based on nt200e3_2_ptp.cpp My25GbPhy::resetRx */ + nthw_mac_pcs_xxv_t *p_nthw_mac_pcs_xxv1 = nthw_mac_pcs_xxv_new(); + + assert(p_nthw_mac_pcs_xxv1); + nthw_mac_pcs_xxv_init(p_nthw_mac_pcs_xxv1, p_fpga, 1, 1); + + nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv1, true, + index); + NT_OS_WAIT_USEC(1000); + + nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv1, false, + index); + NT_OS_WAIT_USEC(1000); + + nthw_mac_pcs_xxv_delete(p_nthw_mac_pcs_xxv1); + } + NT_OS_WAIT_USEC(3000); + } + + /* + * 8: De-assert reset for remaining domains/modules resets except + * TS, PTP, PTP_MMCM and TS_MMCM + */ + NT_LOG(DBG, NTHW, "%s: De-asserting TMC RST\n", p_adapter_id_str); + if (p->mp_fld_rst_tmc) { + field_update_register(p->mp_fld_rst_tmc); + field_clr_flush(p->mp_fld_rst_tmc); + } + + NT_LOG(DBG, NTHW, "%s: De-asserting RPP RST\n", p_adapter_id_str); + field_update_register(p->mp_fld_rst_rpp); + field_clr_flush(p->mp_fld_rst_rpp); + + NT_LOG(DBG, NTHW, "%s: De-asserting DDR4 RST\n", p_adapter_id_str); + field_update_register(p->mp_fld_rst_ddr4); + field_clr_flush(p->mp_fld_rst_ddr4); + + NT_LOG(DBG, NTHW, "%s: De-asserting SDC RST\n", p_adapter_id_str); + field_update_register(p->mp_fld_rst_sdc); + field_clr_flush(p->mp_fld_rst_sdc); + + /* NOTE: 9522 implements PHY10G_QPLL reset and lock at this stage in mac_rx_rst() */ + NT_LOG(DBG, NTHW, "%s: De-asserting MAC RX RST\n", p_adapter_id_str); + if (p->mp_fld_rst_mac_rx) { + field_update_register(p->mp_fld_rst_mac_rx); + field_clr_flush(p->mp_fld_rst_mac_rx); + } + + /* await until DDR4 PLL LOCKED and SDRAM controller has been calibrated */ + res = nthw_fpga_rst_nt200a0x_wait_sdc_calibrated(p_fpga, p); + if (res) { + NT_LOG(ERR, NTHW, + "%s: nthw_fpga_rst_nt200a0x_wait_sdc_calibrated() returned true\n", + p_adapter_id_str); + return -1; + } + + if (field_get_updated(p->mp_fld_sticky_core_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, + "%s: get_sticky_core_mmcm_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + + if (p->mp_fld_sticky_pci_sys_mmcm_unlocked && + field_get_updated(p->mp_fld_sticky_pci_sys_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, + "%s: get_sticky_pci_sys_mmcm_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + + if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */ + if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked && + field_get_updated(p->mp_fld_sticky_tsm_ref_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, + "%s: get_sticky_tsm_ref_mmcm_unlocked returned true\n", + p_adapter_id_str); + return -1; + } + } + + /* + * Timesync/PTP reset sequence + * De-assert TS_MMCM reset + */ + NT_LOG(DBG, NTHW, "%s: De-asserting TS MMCM RST\n", p_adapter_id_str); + field_clr_flush(p->mp_fld_rst_ts_mmcm); + + /* Wait until TS_MMCM LOCKED (NT_RAB0_REG_P9508_RST9508_STAT_TS_MMCM_LOCKED=1); */ + NT_LOG(DBG, NTHW, "%s: Waiting for TS MMCM to lock\n", p_adapter_id_str); + locked = field_wait_set_any32(p->mp_fld_stat_ts_mmcm_locked, -1, -1); + if (locked != 0) { + NT_LOG(ERR, NTHW, + "%s: Waiting for TS MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + } + + NT_LOG(DBG, NTHW, "%s: Calling clear_sticky_mmcm_unlock_bits()\n", + p_adapter_id_str); + field_update_register(p->mp_fld_sticky_ptp_mmcm_unlocked); + /* Clear all sticky bits */ + field_set_flush(p->mp_fld_sticky_ptp_mmcm_unlocked); + field_set_flush(p->mp_fld_sticky_ts_mmcm_unlocked); + field_set_flush(p->mp_fld_sticky_ddr4_mmcm_unlocked); + field_set_flush(p->mp_fld_sticky_ddr4_pll_unlocked); + field_set_flush(p->mp_fld_sticky_core_mmcm_unlocked); + if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked) + field_set_flush(p->mp_fld_sticky_tsm_ref_mmcm_unlocked); + if (p->mp_fld_sticky_pci_sys_mmcm_unlocked) + field_set_flush(p->mp_fld_sticky_pci_sys_mmcm_unlocked); + + /* De-assert TS reset bit */ + NT_LOG(DBG, NTHW, "%s: De-asserting TS RST\n", p_adapter_id_str); + field_clr_flush(p->mp_fld_rst_ts); + + if (field_get_updated(p->mp_fld_sticky_ts_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, + "%s: get_sticky_ts_mmcm_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + + if (field_get_updated(p->mp_fld_sticky_ddr4_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, + "%s: get_sticky_ddr4_mmcm_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + + if (field_get_updated(p->mp_fld_sticky_ddr4_pll_unlocked)) { + NT_LOG(ERR, NTHW, + "%s: get_sticky_ddr4_pll_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + + if (field_get_updated(p->mp_fld_sticky_core_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, + "%s: get_sticky_core_mmcm_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + + if (p->mp_fld_sticky_pci_sys_mmcm_unlocked && + field_get_updated(p->mp_fld_sticky_pci_sys_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, + "%s: get_sticky_pci_sys_mmcm_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + + if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */ + if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked && + field_get_updated(p->mp_fld_sticky_tsm_ref_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, + "%s: get_sticky_tsm_ref_mmcm_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + } + + if (false) { + /* Deassert PTP_MMCM */ + NT_LOG(DBG, NTHW, "%s: De-asserting PTP MMCM RST\n", + p_adapter_id_str); + field_clr_flush(p->mp_fld_rst_ptp_mmcm); + + if ((b_is_nt200a01 && n_fpga_version >= 9) || !b_is_nt200a01) { + /* Wait until PTP_MMCM LOCKED */ + NT_LOG(DBG, NTHW, "%s: Waiting for PTP MMCM to lock\n", + p_adapter_id_str); + locked = field_wait_set_any32(p->mp_fld_stat_ptp_mmcm_locked, + -1, -1); + if (locked != 0) { + NT_LOG(ERR, NTHW, + "%s: Waiting for PTP MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + } + } + + /* Switch PTP MMCM sel to use ptp clk */ + NT_LOG(DBG, NTHW, "%s: Setting PTP MMCM CLK SEL\n", + p_adapter_id_str); + field_set_flush(p->mp_fld_ctrl_ptp_mmcm_clk_sel); + + /* Wait until TS_MMCM LOCKED (NT_RAB0_REG_P9508_RST9508_STAT_TS_MMCM_LOCKED=1); */ + NT_LOG(DBG, NTHW, "%s: Waiting for TS MMCM to re-lock\n", + p_adapter_id_str); + locked = field_wait_set_any32(p->mp_fld_stat_ts_mmcm_locked, -1, -1); + if (locked != 0) { + NT_LOG(ERR, NTHW, + "%s: Waiting for TS MMCM to re-lock failed (%d)\n", + p_adapter_id_str, locked); + } + } + + NT_LOG(DBG, NTHW, "%s: De-asserting PTP RST\n", p_adapter_id_str); + field_clr_flush(p->mp_fld_rst_ptp); + + /* POWER staging introduced in 9508-05-09 and always for 9512 */ + if (n_fpga_product_id == 9508 && n_fpga_version <= 5 && + n_fpga_revision <= 8) { + NT_LOG(DBG, NTHW, "%s: No power staging\n", p_adapter_id_str); + } else { + NT_LOG(DBG, NTHW, "%s: Staging power\n", p_adapter_id_str); + field_set_flush(p->mp_fld_power_pu_phy); /* PHY power up */ + field_clr_flush(p->mp_fld_power_pu_nseb); /* NSEB power down */ + } + + NT_LOG(DBG, NTHW, "%s: %s: END\n", p_adapter_id_str, __func__); + + return 0; +} + +int nthw_fpga_rst_nt200a0x_init(struct fpga_info_s *p_fpga_info, + struct nthw_fpga_rst_nt200a0x *p_rst) +{ + assert(p_fpga_info); + + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + int res = -1; + int n_si_labs_clock_synth_model = -1; + uint8_t n_si_labs_clock_synth_i2c_addr = 0; + nt_fpga_t *p_fpga = NULL; + + p_fpga = p_fpga_info->mp_fpga; + + NT_LOG(DBG, NTHW, "%s: %s: RAB init/reset\n", p_adapter_id_str, __func__); + nthw_rac_rab_reset(p_fpga_info->mp_nthw_rac); + nthw_rac_rab_setup(p_fpga_info->mp_nthw_rac); + + res = nthw_fpga_avr_probe(p_fpga, 0); + + res = nthw_fpga_iic_scan(p_fpga, 0, 0); + res = nthw_fpga_iic_scan(p_fpga, 2, 3); + + /* + * Detect clock synth model + * check for NT200A02/NT200A01 HW-build2 - most commonly seen + */ + n_si_labs_clock_synth_i2c_addr = si5340_u23_i2c_addr_7bit; + n_si_labs_clock_synth_model = + nthw_fpga_silabs_detect(p_fpga, 0, n_si_labs_clock_synth_i2c_addr, 1); + if (n_si_labs_clock_synth_model == -1) { + /* check for old NT200A01 HW-build1 */ + n_si_labs_clock_synth_i2c_addr = si5338_u23_i2c_addr_7bit; + n_si_labs_clock_synth_model = + nthw_fpga_silabs_detect(p_fpga, 0, + n_si_labs_clock_synth_i2c_addr, 255); + if (n_si_labs_clock_synth_model == -1) { + NT_LOG(ERR, NTHW, + "%s: Failed to detect clock synth model (%d)\n", + p_adapter_id_str, n_si_labs_clock_synth_model); + return -1; + } + } + p_rst->mn_si_labs_clock_synth_model = n_si_labs_clock_synth_model; + p_rst->mn_si_labs_clock_synth_i2c_addr = n_si_labs_clock_synth_i2c_addr; + p_rst->mn_hw_id = p_fpga_info->nthw_hw_info.hw_id; + NT_LOG(DBG, NTHW, "%s: %s: Si%04d @ 0x%02x\n", p_adapter_id_str, __func__, + p_rst->mn_si_labs_clock_synth_model, p_rst->mn_si_labs_clock_synth_i2c_addr); + + return res; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h new file mode 100644 index 0000000000..1f192f5ecc --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_FPGA_RST_NT200A0X_H__ +#define __NTHW_FPGA_RST_NT200A0X_H__ + +#include "nthw_drv.h" +#include "nthw_fpga_model.h" + +struct nthw_fpga_rst_nt200a0x { + int mn_fpga_product_id; + int mn_fpga_version; + int mn_fpga_revision; + + int mn_hw_id; + + int mn_si_labs_clock_synth_model; + uint8_t mn_si_labs_clock_synth_i2c_addr; + + nt_field_t *mp_fld_rst_sys; + nt_field_t *mp_fld_rst_sys_mmcm; + nt_field_t *mp_fld_rst_core_mmcm; + nt_field_t *mp_fld_rst_rpp; + nt_field_t *mp_fld_rst_ddr4; + nt_field_t *mp_fld_rst_sdc; + nt_field_t *mp_fld_rst_phy; + nt_field_t *mp_fld_rst_serdes_rx; + nt_field_t *mp_fld_rst_serdes_tx; + nt_field_t *mp_fld_rst_serdes_rx_datapath; + nt_field_t *mp_fld_rst_pcs_rx; + nt_field_t *mp_fld_rst_mac_rx; + nt_field_t *mp_fld_rst_mac_tx; + nt_field_t *mp_fld_rst_ptp; + nt_field_t *mp_fld_rst_ts; + nt_field_t *mp_fld_rst_ptp_mmcm; + nt_field_t *mp_fld_rst_ts_mmcm; + nt_field_t *mp_fld_rst_periph; + nt_field_t *mp_fld_rst_tsm_ref_mmcm; + nt_field_t *mp_fld_rst_tmc; + + /* CTRL register field pointers */ + nt_field_t *mp_fld_ctrl_ts_clk_sel_override; + nt_field_t *mp_fld_ctrl_ts_clk_sel; + nt_field_t *mp_fld_ctrl_ts_clk_sel_ref; + nt_field_t *mp_fld_ctrl_ptp_mmcm_clk_sel; + + /* STAT register field pointers */ + nt_field_t *mp_fld_stat_ddr4_mmcm_locked; + nt_field_t *mp_fld_stat_sys_mmcm_locked; + nt_field_t *mp_fld_stat_core_mmcm_locked; + nt_field_t *mp_fld_stat_ddr4_pll_locked; + nt_field_t *mp_fld_stat_ptp_mmcm_locked; + nt_field_t *mp_fld_stat_ts_mmcm_locked; + nt_field_t *mp_fld_stat_tsm_ref_mmcm_locked; + + /* STICKY register field pointers */ + nt_field_t *mp_fld_sticky_ptp_mmcm_unlocked; + nt_field_t *mp_fld_sticky_ts_mmcm_unlocked; + nt_field_t *mp_fld_sticky_ddr4_mmcm_unlocked; + nt_field_t *mp_fld_sticky_ddr4_pll_unlocked; + nt_field_t *mp_fld_sticky_core_mmcm_unlocked; + nt_field_t *mp_fld_sticky_pci_sys_mmcm_unlocked; + nt_field_t *mp_fld_sticky_tsm_ref_mmcm_unlocked; + + /* POWER register field pointers */ + nt_field_t *mp_fld_power_pu_phy; + nt_field_t *mp_fld_power_pu_nseb; + /* */ + + void (*reset_serdes_rx)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no, + uint32_t rst); + void (*pcs_rx_rst)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no, + uint32_t rst); + void (*get_serdes_rx_rst)(struct nthw_fpga_rst_nt200a0x *p, + uint32_t intf_no, uint32_t *p_set); + void (*get_pcs_rx_rst)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no, + uint32_t *p_set); + bool (*is_rst_serdes_rx_datapath_implemented)(struct nthw_fpga_rst_nt200a0x *p); +}; + +typedef struct nthw_fpga_rst_nt200a0x nthw_fpga_rst_nt200a0x_t; + +int nthw_fpga_rst_nt200a0x_init(struct fpga_info_s *p_fpga_info, + struct nthw_fpga_rst_nt200a0x *p_rst); +int nthw_fpga_rst_nt200a0x_reset(nt_fpga_t *p_fpga, + const struct nthw_fpga_rst_nt200a0x *p); + +#endif /* __NTHW_FPGA_RST_NT200A0X_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_gpio_phy.c b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.c new file mode 100644 index 0000000000..9b536726d0 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.c @@ -0,0 +1,271 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_gpio_phy.h" + +nthw_gpio_phy_t *nthw_gpio_phy_new(void) +{ + nthw_gpio_phy_t *p = malloc(sizeof(nthw_gpio_phy_t)); + + if (p) + memset(p, 0, sizeof(nthw_gpio_phy_t)); + return p; +} + +void nthw_gpio_phy_delete(nthw_gpio_phy_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_gpio_phy_t)); + free(p); + } +} + +int nthw_gpio_phy_init(nthw_gpio_phy_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_GPIO_PHY, n_instance); + + if (p == NULL) + return (p_mod == NULL ? -1 : 0); + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: GPIO_PHY %d: no such instance\n", + p_fpga->p_fpga_info->mp_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_gpio_phy = p_mod; + + /* Registers */ + p->mp_reg_config = module_get_register(p->mp_mod_gpio_phy, GPIO_PHY_CFG); + p->mp_reg_gpio = module_get_register(p->mp_mod_gpio_phy, GPIO_PHY_GPIO); + + /* PORT-0, config fields */ + p->mpa_fields[0].cfg_fld_lp_mode = + register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_LPMODE); + p->mpa_fields[0].cfg_int = + register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_INT_B); + p->mpa_fields[0].cfg_reset = + register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_RESET_B); + p->mpa_fields[0].cfg_mod_prs = + register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_MODPRS_B); + + /* PORT-0, Non-mandatory fields (queryField) */ + p->mpa_fields[0].cfg_pll_int = + register_query_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_PLL_INTR); + p->mpa_fields[0].cfg_port_rxlos = + register_query_field(p->mp_reg_config, GPIO_PHY_CFG_E_PORT0_RXLOS); + + /* PORT-1, config fields */ + p->mpa_fields[1].cfg_fld_lp_mode = + register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_LPMODE); + p->mpa_fields[1].cfg_int = + register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_INT_B); + p->mpa_fields[1].cfg_reset = + register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_RESET_B); + p->mpa_fields[1].cfg_mod_prs = + register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_MODPRS_B); + + /* PORT-1, Non-mandatory fields (queryField) */ + p->mpa_fields[1].cfg_pll_int = + register_query_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_PLL_INTR); + p->mpa_fields[1].cfg_port_rxlos = + register_query_field(p->mp_reg_config, GPIO_PHY_CFG_E_PORT1_RXLOS); + + /* PORT-0, gpio fields */ + p->mpa_fields[0].gpio_fld_lp_mode = + register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_LPMODE); + p->mpa_fields[0].gpio_int = + register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_INT_B); + p->mpa_fields[0].gpio_reset = + register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_RESET_B); + p->mpa_fields[0].gpio_mod_prs = + register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_MODPRS_B); + + /* PORT-0, Non-mandatory fields (queryField) */ + p->mpa_fields[0].gpio_pll_int = + register_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_PLL_INTR); + p->mpa_fields[0].gpio_port_rxlos = + register_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_E_PORT0_RXLOS); + + /* PORT-1, gpio fields */ + p->mpa_fields[1].gpio_fld_lp_mode = + register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_LPMODE); + p->mpa_fields[1].gpio_int = + register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_INT_B); + p->mpa_fields[1].gpio_reset = + register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_RESET_B); + p->mpa_fields[1].gpio_mod_prs = + register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_MODPRS_B); + + /* PORT-1, Non-mandatory fields (queryField) */ + p->mpa_fields[1].gpio_pll_int = + register_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_PLL_INTR); + p->mpa_fields[1].gpio_port_rxlos = + register_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_E_PORT1_RXLOS); + + register_update(p->mp_reg_config); + + return 0; +} + +bool nthw_gpio_phy_is_low_power_enabled(nthw_gpio_phy_t *p, uint8_t if_no) +{ + if (if_no >= ARRAY_SIZE(p->mpa_fields)) { + assert(false); + return false; + } + + if (field_get_updated(p->mpa_fields[if_no].gpio_fld_lp_mode)) + return true; + + else + return false; +} + +bool nthw_gpio_phy_is_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no) +{ + if (if_no >= ARRAY_SIZE(p->mpa_fields)) { + assert(false); + return false; + } + + /* NOTE: This is a negated GPIO PIN "INT_B" */ + if (field_get_updated(p->mpa_fields[if_no].gpio_int)) + return false; + + else + return true; +} + +bool nthw_gpio_phy_is_reset(nthw_gpio_phy_t *p, uint8_t if_no) +{ + if (if_no >= ARRAY_SIZE(p->mpa_fields)) { + assert(false); + return false; + } + + /* NOTE: This is a negated GPIO PIN "RESET_B" */ + if (field_get_updated(p->mpa_fields[if_no].gpio_reset)) + return false; + + else + return true; +} + +bool nthw_gpio_phy_is_module_present(nthw_gpio_phy_t *p, uint8_t if_no) +{ + if (if_no >= ARRAY_SIZE(p->mpa_fields)) { + assert(false); + return false; + } + + /* NOTE: This is a negated GPIO PIN "MODPRS_B" */ + return field_get_updated(p->mpa_fields[if_no].gpio_mod_prs) == 0U ? true : + false; +} + +bool nthw_gpio_phy_is_pll_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no) +{ + if (if_no >= ARRAY_SIZE(p->mpa_fields)) { + assert(false); + return false; + } + + /* NOTE: This is a normal GPIO PIN "PLL_INTR" */ + if (p->mpa_fields[if_no].gpio_pll_int) { + if (field_get_updated(p->mpa_fields[if_no].gpio_pll_int)) + return true; + + else + return false; + } else { + /* this HW doesn't support "PLL_INTR" (INTR from SyncE jitter attenuater) */ + return false; + } +} + +bool nthw_gpio_phy_is_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no) +{ + if (if_no >= ARRAY_SIZE(p->mpa_fields)) { + assert(false); + return false; + } + + if (p->mpa_fields[if_no].gpio_port_rxlos) { + if (field_get_updated(p->mpa_fields[if_no].gpio_port_rxlos)) + return true; + else + return false; + } else { + return false; + } +} + +void nthw_gpio_phy_set_low_power(nthw_gpio_phy_t *p, uint8_t if_no, bool enable) +{ + if (if_no >= ARRAY_SIZE(p->mpa_fields)) { + assert(false); + return; + } + + if (enable) + field_set_flush(p->mpa_fields[if_no].gpio_fld_lp_mode); + + else + field_clr_flush(p->mpa_fields[if_no].gpio_fld_lp_mode); + field_clr_flush(p->mpa_fields[if_no].cfg_fld_lp_mode); /* enable output */ +} + +void nthw_gpio_phy_set_reset(nthw_gpio_phy_t *p, uint8_t if_no, bool enable) +{ + if (if_no >= ARRAY_SIZE(p->mpa_fields)) { + assert(false); + return; + } + + if (enable) + field_clr_flush(p->mpa_fields[if_no].gpio_reset); + + else + field_set_flush(p->mpa_fields[if_no].gpio_reset); + field_clr_flush(p->mpa_fields[if_no].cfg_reset); /* enable output */ +} + +void nthw_gpio_phy_set_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no, bool enable) +{ + if (if_no >= ARRAY_SIZE(p->mpa_fields)) { + assert(false); + return; + } + + if (p->mpa_fields[if_no].gpio_port_rxlos) { + if (enable) + field_set_flush(p->mpa_fields[if_no].gpio_port_rxlos); + + else + field_clr_flush(p->mpa_fields[if_no].gpio_port_rxlos); + } +} + +void nthw_gpio_phy_set_cfg_default_values(nthw_gpio_phy_t *p, uint8_t if_no) +{ + if (if_no >= ARRAY_SIZE(p->mpa_fields)) { + assert(false); + return; + } + + field_set_flush(p->mpa_fields[if_no].cfg_fld_lp_mode); /* enable input */ + field_set_flush(p->mpa_fields[if_no].cfg_int); /* enable input */ + field_set_flush(p->mpa_fields[if_no].cfg_reset); /* enable input */ + field_set_flush(p->mpa_fields[if_no].cfg_mod_prs); /* enable input */ + if (p->mpa_fields[if_no].cfg_port_rxlos) + field_clr_flush(p->mpa_fields[if_no].cfg_port_rxlos); /* enable output */ +} diff --git a/drivers/net/ntnic/nthw/core/nthw_gpio_phy.h b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.h new file mode 100644 index 0000000000..1c6185150c --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NTHW_GPIO_PHY_H_ +#define NTHW_GPIO_PHY_H_ + +#define GPIO_PHY_INTERFACES (2) + +typedef struct { + nt_field_t *cfg_fld_lp_mode; /* Cfg Low Power Mode */ + nt_field_t *cfg_int; /* Cfg Port Interrupt */ + nt_field_t *cfg_reset; /* Cfg Reset */ + nt_field_t *cfg_mod_prs; /* Cfg Module Present */ + nt_field_t *cfg_pll_int; /* Cfg PLL Interrupt */ + nt_field_t *cfg_port_rxlos; /* Emulate Cfg Port RXLOS */ + + nt_field_t *gpio_fld_lp_mode; /* Gpio Low Power Mode */ + nt_field_t *gpio_int; /* Gpio Port Interrupt */ + nt_field_t *gpio_reset; /* Gpio Reset */ + nt_field_t *gpio_mod_prs; /* Gpio Module Present */ + nt_field_t *gpio_pll_int; /* Gpio PLL Interrupt */ + nt_field_t *gpio_port_rxlos; /* Emulate Gpio Port RXLOS */ +} gpio_phy_fields_t; + +struct nthw_gpio_phy { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_gpio_phy; + int mn_instance; + + /* Registers */ + nt_register_t *mp_reg_config; + nt_register_t *mp_reg_gpio; + + /* Fields */ + gpio_phy_fields_t mpa_fields[GPIO_PHY_INTERFACES]; +}; + +typedef struct nthw_gpio_phy nthw_gpio_phy_t; +typedef struct nthw_gpio_phy nthw_gpio_phy; + +nthw_gpio_phy_t *nthw_gpio_phy_new(void); +void nthw_gpio_phy_delete(nthw_gpio_phy_t *p); +int nthw_gpio_phy_init(nthw_gpio_phy_t *p, nt_fpga_t *p_fpga, int n_instance); + +bool nthw_gpio_phy_is_low_power_enabled(nthw_gpio_phy_t *p, uint8_t if_no); +bool nthw_gpio_phy_is_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no); +bool nthw_gpio_phy_is_reset(nthw_gpio_phy_t *p, uint8_t if_no); +bool nthw_gpio_phy_is_module_present(nthw_gpio_phy_t *p, uint8_t if_no); +bool nthw_gpio_phy_is_pll_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no); +bool nthw_gpio_phy_is_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no); +void nthw_gpio_phy_set_low_power(nthw_gpio_phy_t *p, uint8_t if_no, bool enable); +void nthw_gpio_phy_set_reset(nthw_gpio_phy_t *p, uint8_t if_no, bool enable); +void nthw_gpio_phy_set_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no, bool enable); +void nthw_gpio_phy_set_cfg_default_values(nthw_gpio_phy_t *p, uint8_t if_no); + +#endif /* NTHW_GPIO_PHY_H_ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_hif.c b/drivers/net/ntnic/nthw/core/nthw_hif.c new file mode 100644 index 0000000000..7b7a919108 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_hif.c @@ -0,0 +1,342 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nt_util.h" +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_hif.h" + +nthw_hif_t *nthw_hif_new(void) +{ + nthw_hif_t *p = malloc(sizeof(nthw_hif_t)); + + if (p) + memset(p, 0, sizeof(nthw_hif_t)); + return p; +} + +void nthw_hif_delete(nthw_hif_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_hif_t)); + free(p); + } +} + +int nthw_hif_init(nthw_hif_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str _unused = + p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *mod = fpga_query_module(p_fpga, MOD_HIF, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: HIF %d: no such instance\n", + p_fpga->p_fpga_info->mp_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_hif = mod; + + /* default for (Xilinx-based) products until august 2022: (1e6/4000 = 250 MHz) */ + p->mn_fpga_param_hif_per_ps = + fpga_get_product_param(p->mp_fpga, NT_HIF_PER_PS, 4000); + p->mn_fpga_hif_ref_clk_freq = + (uint32_t)(1000000000000ULL / + (unsigned int)p->mn_fpga_param_hif_per_ps); + + p->mp_reg_prod_id_lsb = module_get_register(p->mp_mod_hif, HIF_PROD_ID_LSB); + p->mp_fld_prod_id_lsb_rev_id = + register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_REV_ID); + p->mp_fld_prod_id_lsb_ver_id = + register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_VER_ID); + p->mp_fld_prod_id_lsb_group_id = + register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_GROUP_ID); + + p->mp_reg_prod_id_msb = module_get_register(p->mp_mod_hif, HIF_PROD_ID_MSB); + p->mp_fld_prod_id_msb_type_id = + register_get_field(p->mp_reg_prod_id_msb, HIF_PROD_ID_MSB_TYPE_ID); + p->mp_fld_prod_id_msb_build_no = + register_get_field(p->mp_reg_prod_id_msb, HIF_PROD_ID_MSB_BUILD_NO); + + p->mp_reg_build_time = module_get_register(p->mp_mod_hif, HIF_BUILD_TIME); + p->mp_fld_build_time = + register_get_field(p->mp_reg_build_time, HIF_BUILD_TIME_TIME); + + p->mn_fpga_id_prod = field_get_updated(p->mp_fld_prod_id_lsb_group_id); + p->mn_fpga_id_ver = field_get_updated(p->mp_fld_prod_id_lsb_ver_id); + p->mn_fpga_id_rev = field_get_updated(p->mp_fld_prod_id_lsb_rev_id); + p->mn_fpga_id_build_no = field_get_updated(p->mp_fld_prod_id_msb_build_no); + p->mn_fpga_id_item = field_get_updated(p->mp_fld_prod_id_msb_type_id); + + NT_LOG(DBG, NTHW, "%s: HIF %d: %s: %d-%d-%d-%d-%d\n", p_adapter_id_str, + p->mn_instance, __func__, p->mn_fpga_id_item, p->mn_fpga_id_prod, + p->mn_fpga_id_ver, p->mn_fpga_id_rev, p->mn_fpga_id_build_no); + NT_LOG(DBG, NTHW, + "%s: HIF %d: %s: HIF ref clock: %d Hz (%d ticks/ps)\n", + p_adapter_id_str, p->mn_instance, __func__, p->mn_fpga_hif_ref_clk_freq, + p->mn_fpga_param_hif_per_ps); + + p->mp_reg_build_seed = NULL; /* Reg/Fld not present on HIF */ + if (p->mp_reg_build_seed) + p->mp_fld_build_seed = NULL; /* Reg/Fld not present on HIF */ + else + p->mp_fld_build_seed = NULL; + + p->mp_reg_core_speed = NULL; /* Reg/Fld not present on HIF */ + if (p->mp_reg_core_speed) { + p->mp_fld_core_speed = NULL; /* Reg/Fld not present on HIF */ + p->mp_fld_ddr3_speed = NULL; /* Reg/Fld not present on HIF */ + } else { + p->mp_reg_core_speed = NULL; + p->mp_fld_core_speed = NULL; + p->mp_fld_ddr3_speed = NULL; + } + + /* Optional registers since: 2018-04-25 */ + p->mp_reg_int_mask = NULL; /* Reg/Fld not present on HIF */ + p->mp_reg_int_clr = NULL; /* Reg/Fld not present on HIF */ + p->mp_reg_int_force = NULL; /* Reg/Fld not present on HIF */ + + p->mp_fld_int_mask_timer = NULL; + p->mp_fld_int_clr_timer = NULL; + p->mp_fld_int_force_timer = NULL; + + p->mp_fld_int_mask_port = NULL; + p->mp_fld_int_clr_port = NULL; + p->mp_fld_int_force_port = NULL; + + p->mp_fld_int_mask_pps = NULL; + p->mp_fld_int_clr_pps = NULL; + p->mp_fld_int_force_pps = NULL; + + p->mp_reg_stat_ctrl = module_get_register(p->mp_mod_hif, HIF_STAT_CTRL); + p->mp_fld_stat_ctrl_ena = + register_get_field(p->mp_reg_stat_ctrl, HIF_STAT_CTRL_STAT_ENA); + p->mp_fld_stat_ctrl_req = + register_get_field(p->mp_reg_stat_ctrl, HIF_STAT_CTRL_STAT_REQ); + + p->mp_reg_stat_rx = module_get_register(p->mp_mod_hif, HIF_STAT_RX); + p->mp_fld_stat_rx_counter = + register_get_field(p->mp_reg_stat_rx, HIF_STAT_RX_COUNTER); + + p->mp_reg_stat_tx = module_get_register(p->mp_mod_hif, HIF_STAT_TX); + p->mp_fld_stat_tx_counter = + register_get_field(p->mp_reg_stat_tx, HIF_STAT_TX_COUNTER); + + p->mp_reg_stat_ref_clk = module_get_register(p->mp_mod_hif, HIF_STAT_REFCLK); + p->mp_fld_stat_ref_clk_ref_clk = register_get_field(p->mp_reg_stat_ref_clk, + HIF_STAT_REFCLK_REFCLK250); + + p->mp_reg_status = module_query_register(p->mp_mod_hif, HIF_STATUS); + if (p->mp_reg_status) { + p->mp_fld_status_tags_in_use = + register_query_field(p->mp_reg_status, HIF_STATUS_TAGS_IN_USE); + p->mp_fld_status_wr_err = + register_query_field(p->mp_reg_status, HIF_STATUS_WR_ERR); + p->mp_fld_status_rd_err = + register_query_field(p->mp_reg_status, HIF_STATUS_RD_ERR); + } else { + p->mp_reg_status = module_query_register(p->mp_mod_hif, HIF_STATUS); + p->mp_fld_status_tags_in_use = + register_query_field(p->mp_reg_status, HIF_STATUS_TAGS_IN_USE); + p->mp_fld_status_wr_err = NULL; + p->mp_fld_status_rd_err = NULL; + } + + p->mp_reg_pci_test0 = module_get_register(p->mp_mod_hif, HIF_TEST0); + p->mp_fld_pci_test0 = register_get_field(p->mp_reg_pci_test0, HIF_TEST0_DATA); + + p->mp_reg_pci_test1 = module_get_register(p->mp_mod_hif, HIF_TEST1); + p->mp_fld_pci_test1 = register_get_field(p->mp_reg_pci_test1, HIF_TEST1_DATA); + + /* Required to run TSM */ + p->mp_reg_sample_time = module_get_register(p->mp_mod_hif, HIF_SAMPLE_TIME); + if (p->mp_reg_sample_time) { + p->mp_fld_sample_time = + register_get_field(p->mp_reg_sample_time, HIF_SAMPLE_TIME_SAMPLE_TIME); + } else { + p->mp_fld_sample_time = NULL; + } + + /* We need to optimize PCIe3 TLP-size read-request and extended tag usage */ + { + p->mp_reg_config = module_query_register(p->mp_mod_hif, HIF_CONFIG); + if (p->mp_reg_config) { + p->mp_fld_max_tlp = + register_get_field(p->mp_reg_config, HIF_CONFIG_MAX_TLP); + p->mp_fld_max_read = + register_get_field(p->mp_reg_config, HIF_CONFIG_MAX_READ); + p->mp_fld_ext_tag = + register_get_field(p->mp_reg_config, HIF_CONFIG_EXT_TAG); + } else { + p->mp_fld_max_tlp = NULL; + p->mp_fld_max_read = NULL; + p->mp_fld_ext_tag = NULL; + } + } + + return 0; +} + +int nthw_hif_setup_config(nthw_hif_t *p) +{ + const char *const p_adapter_id_str _unused = + p->mp_fpga->p_fpga_info->mp_adapter_id_str; + + /* + * We need to optimize PCIe3 read-request and extended tag usage + * original check: HW_ADAPTER_ID_NT200A02 HW_ADAPTER_ID_NT100A01 HW_ADAPTER_ID_NT50B01 + */ + if (p->mp_fpga->p_fpga_info->n_nthw_adapter_id != NT_HW_ADAPTER_ID_NT40E3) { + if (p->mp_fld_max_read) { + /* + * NOTE: On Pandion DELL server, this param was negotiated to 4096 + * (index=5), but the server crashed. For now we need to limit this value to + * 512 (index=2) + */ + const uint32_t n_max_read_req_size = + field_get_updated(p->mp_fld_max_read); + if (n_max_read_req_size > 2) { + field_set_val_flush32(p->mp_fld_max_read, 2); + NT_LOG(INF, NTHW, + "%s: %s: PCIe: MaxReadReqsize %d - changed to 2 (512B)\n", + p_adapter_id_str, __func__, + n_max_read_req_size); + } + } + + if (p->mp_fld_ext_tag) + field_set_val_flush32(p->mp_fld_ext_tag, 1); + + if (p->mp_fld_max_tlp && p->mp_fld_max_read && p->mp_fld_ext_tag) { + NT_LOG(INF, NTHW, + "%s: %s: PCIe config: MaxTlp = %d, MaxReadReqsize = %d, ExtTagEna = %d\n", + p_adapter_id_str, __func__, + field_get_updated(p->mp_fld_max_tlp), + field_get_updated(p->mp_fld_max_read), + field_get_updated(p->mp_fld_ext_tag)); + } + } + return 0; +} + +int nthw_hif_trigger_sample_time(nthw_hif_t *p) +{ + field_set_val_flush32(p->mp_fld_sample_time, 0xfee1dead); + + return 0; +} + +int nthw_hif_get_stat(nthw_hif_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt, + uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size, + uint32_t *p_tg_ref_freq, uint64_t *p_tags_in_use, + uint64_t *p_rd_err, uint64_t *p_wr_err) +{ + *p_rx_cnt = field_get_updated(p->mp_fld_stat_rx_counter); + *p_tx_cnt = field_get_updated(p->mp_fld_stat_tx_counter); + + *p_ref_clk_cnt = field_get_updated(p->mp_fld_stat_ref_clk_ref_clk); + + *p_tg_unit_size = NTHW_TG_CNT_SIZE; + *p_tg_ref_freq = p->mn_fpga_hif_ref_clk_freq; + + *p_tags_in_use = (p->mp_fld_status_tags_in_use ? + field_get_updated(p->mp_fld_status_tags_in_use) : + 0); + + *p_rd_err = (p->mp_fld_status_rd_err ? field_get_updated(p->mp_fld_status_rd_err) : + 0); + *p_wr_err = (p->mp_fld_status_wr_err ? field_get_updated(p->mp_fld_status_wr_err) : + 0); + + return 0; +} + +int nthw_hif_get_stat_rate(nthw_hif_t *p, uint64_t *p_pci_rx_rate, + uint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt, + uint64_t *p_tags_in_use, uint64_t *p_rd_err_cnt, + uint64_t *p_wr_err_cnt) +{ + uint32_t rx_cnt, tx_cnt, ref_clk_cnt, tg_unit_size, tg_ref_freq; + uint64_t n_tags_in_use, n_rd_err, n_wr_err; + + nthw_hif_get_stat(p, &rx_cnt, &tx_cnt, &ref_clk_cnt, &tg_unit_size, &tg_ref_freq, + &n_tags_in_use, &n_rd_err, &n_wr_err); + + *p_tags_in_use = n_tags_in_use; + if (n_rd_err) + (*p_rd_err_cnt)++; + if (n_wr_err) + (*p_wr_err_cnt)++; + + if (ref_clk_cnt) { + uint64_t rx_rate; + uint64_t tx_rate; + + *p_ref_clk_cnt = ref_clk_cnt; + + rx_rate = ((uint64_t)rx_cnt * tg_unit_size * tg_ref_freq) / + (uint64_t)ref_clk_cnt; + *p_pci_rx_rate = rx_rate; + + tx_rate = ((uint64_t)tx_cnt * tg_unit_size * tg_ref_freq) / + (uint64_t)ref_clk_cnt; + *p_pci_tx_rate = tx_rate; + } else { + *p_pci_rx_rate = 0; + *p_pci_tx_rate = 0; + *p_ref_clk_cnt = 0; + } + + return 0; +} + +int nthw_hif_stat_req_enable(nthw_hif_t *p) +{ + field_set_all(p->mp_fld_stat_ctrl_ena); + field_set_all(p->mp_fld_stat_ctrl_req); + field_flush_register(p->mp_fld_stat_ctrl_req); + return 0; +} + +int nthw_hif_stat_req_disable(nthw_hif_t *p) +{ + field_clr_all(p->mp_fld_stat_ctrl_ena); + field_set_all(p->mp_fld_stat_ctrl_req); + field_flush_register(p->mp_fld_stat_ctrl_req); + return 0; +} + +int nthw_hif_stat_sample(nthw_hif_t *p, uint64_t *p_rx_rate, uint64_t *p_tx_rate, + uint64_t *p_ref_clk_cnt, uint64_t *p_tags_in_use, + uint64_t *p_rd_err_cnt, uint64_t *p_wr_err_cnt) +{ + nthw_hif_stat_req_enable(p); + NT_OS_WAIT_USEC(100000); + nthw_hif_stat_req_disable(p); + nthw_hif_get_stat_rate(p, p_rx_rate, p_tx_rate, p_ref_clk_cnt, p_tags_in_use, + p_rd_err_cnt, p_wr_err_cnt); + + return 0; +} + +int nthw_hif_end_point_counters_sample(nthw_hif_t *p, + struct nthw_hif_end_point_counters *epc) +{ + assert(epc); + + /* Get stat rate and maintain rx/tx min/max */ + nthw_hif_get_stat_rate(p, &epc->cur_tx, &epc->cur_rx, &epc->n_ref_clk_cnt, + &epc->n_tags_in_use, &epc->n_rd_err, &epc->n_wr_err); + + return 0; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_hif.h b/drivers/net/ntnic/nthw/core/nthw_hif.h new file mode 100644 index 0000000000..2701e222b3 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_hif.h @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_HIF_H__ +#define __NTHW_HIF_H__ + +#define NTHW_TG_CNT_SIZE (4ULL) + +struct nthw_hif { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_hif; + int mn_instance; + + nt_register_t *mp_reg_prod_id_lsb; + nt_field_t *mp_fld_prod_id_lsb_rev_id; + nt_field_t *mp_fld_prod_id_lsb_ver_id; + nt_field_t *mp_fld_prod_id_lsb_group_id; + + nt_register_t *mp_reg_prod_id_msb; + nt_field_t *mp_fld_prod_id_msb_type_id; + nt_field_t *mp_fld_prod_id_msb_build_no; + + nt_register_t *mp_reg_build_time; + nt_field_t *mp_fld_build_time; + + nt_register_t *mp_reg_build_seed; + nt_field_t *mp_fld_build_seed; + + nt_register_t *mp_reg_core_speed; + nt_field_t *mp_fld_core_speed; + nt_field_t *mp_fld_ddr3_speed; + + nt_register_t *mp_reg_int_mask; + nt_field_t *mp_fld_int_mask_timer; + nt_field_t *mp_fld_int_mask_port; + nt_field_t *mp_fld_int_mask_pps; + + nt_register_t *mp_reg_int_clr; + nt_field_t *mp_fld_int_clr_timer; + nt_field_t *mp_fld_int_clr_port; + nt_field_t *mp_fld_int_clr_pps; + + nt_register_t *mp_reg_int_force; + nt_field_t *mp_fld_int_force_timer; + nt_field_t *mp_fld_int_force_port; + nt_field_t *mp_fld_int_force_pps; + + nt_register_t *mp_reg_sample_time; + nt_field_t *mp_fld_sample_time; + + nt_register_t *mp_reg_status; + nt_field_t *mp_fld_status_tags_in_use; + nt_field_t *mp_fld_status_wr_err; + nt_field_t *mp_fld_status_rd_err; + + nt_register_t *mp_reg_stat_ctrl; + nt_field_t *mp_fld_stat_ctrl_ena; + nt_field_t *mp_fld_stat_ctrl_req; + + nt_register_t *mp_reg_stat_rx; + nt_field_t *mp_fld_stat_rx_counter; + + nt_register_t *mp_reg_stat_tx; + nt_field_t *mp_fld_stat_tx_counter; + + nt_register_t *mp_reg_stat_ref_clk; + nt_field_t *mp_fld_stat_ref_clk_ref_clk; + + nt_register_t *mp_reg_pci_test0; + nt_field_t *mp_fld_pci_test0; + + nt_register_t *mp_reg_pci_test1; + nt_field_t *mp_fld_pci_test1; + + nt_register_t *mp_reg_pci_test2; + nt_field_t *mp_fld_pci_test2; + + nt_register_t *mp_reg_pci_test3; + nt_field_t *mp_fld_pci_test3; + + nt_register_t *mp_reg_config; + nt_field_t *mp_fld_max_tlp; + nt_field_t *mp_fld_max_read; + nt_field_t *mp_fld_ext_tag; + + int mn_fpga_id_item; + int mn_fpga_id_prod; + int mn_fpga_id_ver; + int mn_fpga_id_rev; + int mn_fpga_id_build_no; + + int mn_fpga_param_hif_per_ps; + uint32_t mn_fpga_hif_ref_clk_freq; +}; + +typedef struct nthw_hif nthw_hif_t; +typedef struct nthw_hif nthw_hif; + +struct nthw_hif_end_point_err_counters { + uint32_t n_err_correctable, n_err_non_fatal, n_err_fatal; +}; + +struct nthw_hif_end_point_counters { + int n_numa_node; + + int n_tg_direction; + int n_tg_pkt_size; + int n_tg_num_pkts; + int n_tg_delay; + + uint64_t cur_rx, cur_tx; + uint64_t cur_pci_nt_util, cur_pci_xil_util; + uint64_t n_ref_clk_cnt; + + uint64_t n_tags_in_use; + uint64_t n_rd_err; + uint64_t n_wr_err; + + struct nthw_hif_end_point_err_counters s_rc_ep_pre, s_rc_ep_post, s_rc_ep_delta; + struct nthw_hif_end_point_err_counters s_ep_rc_pre, s_ep_rc_post, s_ep_rc_delta; + + int bo_error; +}; + +struct nthw_hif_end_points { + struct nthw_hif_end_point_counters pri, sla; +}; + +nthw_hif_t *nthw_hif_new(void); +void nthw_hif_delete(nthw_hif_t *p); +int nthw_hif_init(nthw_hif_t *p, nt_fpga_t *p_fpga, int n_instance); + +int nthw_hif_setup_config(nthw_hif_t *p); + +int nthw_hif_trigger_sample_time(nthw_hif_t *p); + +int nthw_hif_stat_req_enable(nthw_hif_t *p); +int nthw_hif_stat_req_disable(nthw_hif_t *p); +int nthw_hif_stat_sample(nthw_hif_t *p, uint64_t *p_rx_rate, uint64_t *p_tx_rate, + uint64_t *p_ref_clk_cnt, uint64_t *p_tags_in_use, + uint64_t *p_rd_err_cnt, uint64_t *p_wr_err_cnt); + +int nthw_hif_get_stat(nthw_hif_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt, + uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size, + uint32_t *p_tg_ref_freq, uint64_t *p_tags_in_use, + uint64_t *p_rd_err, uint64_t *p_wr_err); +int nthw_hif_get_stat_rate(nthw_hif_t *p, uint64_t *p_pci_rx_rate, + uint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt, + uint64_t *p_tags_in_use, uint64_t *p_rd_err_cnt, + uint64_t *p_wr_err_cnt); + +int nthw_hif_end_point_counters_sample(nthw_hif_t *p, + struct nthw_hif_end_point_counters *epc); + +#endif /* __NTHW_HIF_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_iic.c b/drivers/net/ntnic/nthw/core/nthw_iic.c new file mode 100644 index 0000000000..14aee221ce --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_iic.c @@ -0,0 +1,570 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nt_util.h" +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_iic.h" + +#define I2C_TRANSMIT_WR (0x00) +#define I2C_TRANSMIT_RD (0x01) + +#define I2C_WAIT_US(x) NT_OS_WAIT_USEC(x) + +/* + * Minimum timing values for I2C for a Marvel 88E11111 Phy. + * This Phy is used in many Trispeed NIMs. + * In order to access this Phy, the I2C clock speed is needed to be set to 100KHz. + */ +static const uint32_t susta = 4700; /* ns */ +static const uint32_t susto = 4000; /* ns */ +static const uint32_t hdsta = 4000; /* ns */ +static const uint32_t sudat = 250; /* ns */ +static const uint32_t buf = 4700; /* ns */ +static const uint32_t high = 4000; /* ns */ +static const uint32_t low = 4700; /* ns */ +static const uint32_t hddat = 300; /* ns */ + +static int nthw_iic_reg_control_txfifo_reset(nthw_iic_t *p) +{ + field_update_register(p->mp_fld_cr_txfifo_reset); + + field_set_all(p->mp_fld_cr_txfifo_reset); + field_flush_register(p->mp_fld_cr_txfifo_reset); + + field_clr_all(p->mp_fld_cr_txfifo_reset); + field_flush_register(p->mp_fld_cr_txfifo_reset); + + return 0; +} + +static int nthw_iic_reg_tx_fifo_write(nthw_iic_t *p, uint32_t data, bool start, + bool stop) +{ + if (start) + field_set_all(p->mp_fld_tx_fifo_start); + + else + field_clr_all(p->mp_fld_tx_fifo_start); + + if (stop) + field_set_all(p->mp_fld_tx_fifo_stop); + + else + field_clr_all(p->mp_fld_tx_fifo_stop); + + field_set_val32(p->mp_fld_tx_fifo_txdata, data); + + register_flush(p->mp_reg_tx_fifo, 1); + + return 0; +} + +static int nthw_iic_reg_read_i2c_rx_fifo(nthw_iic_t *p, uint8_t *p_data) +{ + assert(p_data); + + *p_data = (uint8_t)field_get_updated(p->mp_fld_rx_fifo_rxdata); + + return 0; +} + +static int nthw_iic_reg_softr(nthw_iic_t *p) +{ + field_update_register(p->mp_fld_cr_en); + field_set_val_flush32(p->mp_fld_softr_rkey, 0x0A); + + return 0; +} + +static int nthw_iic_reg_enable(nthw_iic_t *p) +{ + field_update_register(p->mp_fld_cr_en); + field_set_flush(p->mp_fld_cr_en); + + return 0; +} + +static int nthw_iic_reg_busbusy(nthw_iic_t *p, bool *pb_flag) +{ + assert(pb_flag); + + *pb_flag = field_get_updated(p->mp_fld_sr_bb) ? true : false; + + return 0; +} + +static int nthw_iic_reg_rxfifo_empty(nthw_iic_t *p, bool *pb_flag) +{ + assert(pb_flag); + + *pb_flag = field_get_updated(p->mp_fld_sr_rxfifo_empty) ? true : false; + + return 0; +} + +/* + * nIicCycleTime is the I2C clock cycle time in ns ie 125MHz = 8ns + */ +static int nthw_iic_reg_set_timing(nthw_iic_t *p, uint32_t n_iic_cycle_time) +{ + uint32_t val; + + val = susta / n_iic_cycle_time; + field_set_val_flush(p->mp_fld_tsusta, &val, 1); + + val = susto / n_iic_cycle_time; + field_set_val_flush(p->mp_fld_tsusto, &val, 1); + + val = hdsta / n_iic_cycle_time; + field_set_val_flush(p->mp_fld_thdsta, &val, 1); + + val = sudat / n_iic_cycle_time; + field_set_val_flush(p->mp_fld_tsudat, &val, 1); + + val = buf / n_iic_cycle_time; + field_set_val_flush(p->mp_fld_tbuf, &val, 1); + + val = high / n_iic_cycle_time; + field_set_val_flush(p->mp_fld_thigh, &val, 1); + + val = low / n_iic_cycle_time; + field_set_val_flush(p->mp_fld_tlow, &val, 1); + + val = hddat / n_iic_cycle_time; + field_set_val_flush(p->mp_fld_thddat, &val, 1); + + return 0; +} + +nthw_iic_t *nthw_iic_new(void) +{ + nthw_iic_t *p = malloc(sizeof(nthw_iic_t)); + + if (p) + memset(p, 0, sizeof(nthw_iic_t)); + return p; +} + +int nthw_iic_init(nthw_iic_t *p, nt_fpga_t *p_fpga, int n_iic_instance, + uint32_t n_iic_cycle_time) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *mod = fpga_query_module(p_fpga, MOD_IIC, n_iic_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: I2C %d: no such instance\n", + p_adapter_id_str, n_iic_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_iic_instance = n_iic_instance; + + p->mn_iic_cycle_time = n_iic_cycle_time; + + nthw_iic_set_retry_params(p, -1, -1, -1, -1, -1); + + p->mp_mod_iic = mod; + + /* I2C is a primary communication channel - turn off debug by default */ + module_set_debug_mode(p->mp_mod_iic, 0x00); + + p->mp_reg_tsusta = module_get_register(p->mp_mod_iic, IIC_TSUSTA); + p->mp_fld_tsusta = + register_get_field(p->mp_reg_tsusta, IIC_TSUSTA_TSUSTA_VAL); + + p->mp_reg_tsusto = module_get_register(p->mp_mod_iic, IIC_TSUSTO); + p->mp_fld_tsusto = + register_get_field(p->mp_reg_tsusto, IIC_TSUSTO_TSUSTO_VAL); + + p->mp_reg_thdsta = module_get_register(p->mp_mod_iic, IIC_THDSTA); + p->mp_fld_thdsta = + register_get_field(p->mp_reg_thdsta, IIC_THDSTA_THDSTA_VAL); + + p->mp_reg_tsudat = module_get_register(p->mp_mod_iic, IIC_TSUDAT); + p->mp_fld_tsudat = + register_get_field(p->mp_reg_tsudat, IIC_TSUDAT_TSUDAT_VAL); + + p->mp_reg_tbuf = module_get_register(p->mp_mod_iic, IIC_TBUF); + p->mp_fld_tbuf = register_get_field(p->mp_reg_tbuf, IIC_TBUF_TBUF_VAL); + + p->mp_reg_thigh = module_get_register(p->mp_mod_iic, IIC_THIGH); + p->mp_fld_thigh = register_get_field(p->mp_reg_thigh, IIC_THIGH_THIGH_VAL); + + p->mp_reg_tlow = module_get_register(p->mp_mod_iic, IIC_TLOW); + p->mp_fld_tlow = register_get_field(p->mp_reg_tlow, IIC_TLOW_TLOW_VAL); + + p->mp_reg_thddat = module_get_register(p->mp_mod_iic, IIC_THDDAT); + p->mp_fld_thddat = + register_get_field(p->mp_reg_thddat, IIC_THDDAT_THDDAT_VAL); + + p->mp_reg_cr = module_get_register(p->mp_mod_iic, IIC_CR); + p->mp_fld_cr_en = register_get_field(p->mp_reg_cr, IIC_CR_EN); + p->mp_fld_cr_msms = register_get_field(p->mp_reg_cr, IIC_CR_MSMS); + p->mp_fld_cr_txfifo_reset = + register_get_field(p->mp_reg_cr, IIC_CR_TXFIFO_RESET); + p->mp_fld_cr_txak = register_get_field(p->mp_reg_cr, IIC_CR_TXAK); + + p->mp_reg_sr = module_get_register(p->mp_mod_iic, IIC_SR); + p->mp_fld_sr_bb = register_get_field(p->mp_reg_sr, IIC_SR_BB); + p->mp_fld_sr_rxfifo_full = + register_get_field(p->mp_reg_sr, IIC_SR_RXFIFO_FULL); + p->mp_fld_sr_rxfifo_empty = + register_get_field(p->mp_reg_sr, IIC_SR_RXFIFO_EMPTY); + p->mp_fld_sr_txfifo_full = + register_get_field(p->mp_reg_sr, IIC_SR_TXFIFO_FULL); + p->mp_fld_sr_txfifo_empty = + register_get_field(p->mp_reg_sr, IIC_SR_TXFIFO_EMPTY); + + p->mp_reg_tx_fifo = module_get_register(p->mp_mod_iic, IIC_TX_FIFO); + p->mp_fld_tx_fifo_txdata = + register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_TXDATA); + p->mp_fld_tx_fifo_start = + register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_START); + p->mp_fld_tx_fifo_stop = + register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_STOP); + + p->mp_reg_rx_fifo_pirq = + module_get_register(p->mp_mod_iic, IIC_RX_FIFO_PIRQ); + p->mp_fld_rx_fifo_pirq_cmp_val = + register_get_field(p->mp_reg_rx_fifo_pirq, IIC_RX_FIFO_PIRQ_CMP_VAL); + + p->mp_reg_rx_fifo = module_get_register(p->mp_mod_iic, IIC_RX_FIFO); + p->mp_fld_rx_fifo_rxdata = + register_get_field(p->mp_reg_rx_fifo, IIC_RX_FIFO_RXDATA); + + p->mp_reg_softr = module_get_register(p->mp_mod_iic, IIC_SOFTR); + p->mp_fld_softr_rkey = register_get_field(p->mp_reg_softr, IIC_SOFTR_RKEY); + + /* + * Initialize I2C controller by applying soft reset and enable the controller + */ + nthw_iic_reg_softr(p); + /* Enable the controller */ + nthw_iic_reg_enable(p); + + /* Setup controller timing */ + if (p->mn_iic_cycle_time) { + NT_LOG(DBG, NTHW, "%s: I2C%d: cycletime=%d\n", p_adapter_id_str, + p->mn_iic_instance, p->mn_iic_cycle_time); + nthw_iic_reg_set_timing(p, p->mn_iic_cycle_time); + } + + /* Reset TX fifo - must be after enable */ + nthw_iic_reg_control_txfifo_reset(p); + nthw_iic_reg_tx_fifo_write(p, 0, 0, 0); + + return 0; +} + +void nthw_iic_delete(nthw_iic_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_iic_t)); + free(p); + } +} + +int nthw_iic_set_retry_params(nthw_iic_t *p, const int n_poll_delay, + const int n_bus_ready_retry, const int n_data_ready_retry, + const int n_read_data_retry, const int n_write_data_retry) +{ + p->mn_poll_delay = n_poll_delay >= 0 ? n_poll_delay : 10; + + p->mn_bus_ready_retry = n_bus_ready_retry >= 0 ? n_bus_ready_retry : 1000; + p->mn_data_ready_retry = n_data_ready_retry >= 0 ? n_data_ready_retry : 1000; + + p->mn_read_data_retry = n_read_data_retry >= 0 ? n_read_data_retry : 10; + p->mn_write_data_retry = n_write_data_retry >= 0 ? n_write_data_retry : 10; + + return 0; +} + +int nthw_iic_read_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr, + uint8_t data_len, void *p_void) +{ + const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str; + const int n_debug_mode = module_get_debug_mode(p->mp_mod_iic); + + uint8_t *pb = (uint8_t *)p_void; + int retry = (p->mn_read_data_retry >= 0 ? p->mn_read_data_retry : 10); + + if (n_debug_mode == 0xff) { + NT_LOG(DBG, NTHW, "%s: adr=0x%2.2x, reg=%d, len=%d\n", + p_adapter_id_str, dev_addr, reg_addr, data_len); + } + + while (nthw_iic_readbyte(p, dev_addr, reg_addr, data_len, pb) != 0) { + retry--; + if (retry <= 0) { + NT_LOG(ERR, NTHW, + "%s: I2C%d: Read retry exhausted (dev_addr=%d reg_addr=%d)\n", + p_adapter_id_str, p->mn_iic_instance, dev_addr, + reg_addr); + return -1; + } +#if defined(DEBUG) + NT_LOG(DBG, NTHW, + "%s: I2C%d: Read retry=%d (dev_addr=%d reg_addr=%d)\n", + p_adapter_id_str, p->mn_iic_instance, retry, dev_addr, + reg_addr); +#endif + } + + if (n_debug_mode == 0xff) { + NT_LOG(DBG, NTHW, + "%s: adr=0x%2.2x, reg=%d, len=%d, retries remaining: %d\n", + p_adapter_id_str, dev_addr, reg_addr, data_len, retry); + } + + return 0; +} + +int nthw_iic_readbyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr, + uint8_t data_len, uint8_t *p_byte) +{ + const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str; + + uint32_t value; + uint32_t i; + + if (nthw_iic_bus_ready(p)) { + /* Reset TX fifo */ + nthw_iic_reg_control_txfifo_reset(p); + + /* Write device address to TX_FIFO and set start bit!! */ + value = (dev_addr << 1) | I2C_TRANSMIT_WR; + nthw_iic_reg_tx_fifo_write(p, value, 1, 0); + + /* Write reg_addr to TX FIFO */ + nthw_iic_reg_tx_fifo_write(p, reg_addr, 0, 1); + + if (!nthw_iic_bus_ready(p)) { + NT_LOG(ERR, NTHW, "%s: error: (%s:%u)\n", p_adapter_id_str, + __func__, __LINE__); + return -1; + } + + /* Write device address + RD bit to TX_FIFO and set start bit!! */ + value = (dev_addr << 1) | I2C_TRANSMIT_RD; + nthw_iic_reg_tx_fifo_write(p, value, 1, 0); + + /* Write DataLen to TX_FIFO and set stop bit!! */ + nthw_iic_reg_tx_fifo_write(p, data_len, 0, 1); + + for (i = 0; i < data_len; i++) { + /* Wait for RX FIFO not empty */ + if (!nthw_iic_data_ready(p)) + return -1; + + /* Read DataLen bytes from RX_FIFO */ + nthw_iic_reg_read_i2c_rx_fifo(p, p_byte); + p_byte++; + } + + return 0; + + } else { + NT_LOG(ERR, NTHW, "%s: error: (%s:%u)\n", p_adapter_id_str, + __func__, __LINE__); + return -1; + } + return 0; +} + +int nthw_iic_write_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr, + uint8_t data_len, void *p_void) +{ + const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str; + int retry = (p->mn_write_data_retry >= 0 ? p->mn_write_data_retry : 10); + uint8_t *pb = (uint8_t *)p_void; + + while (nthw_iic_writebyte(p, dev_addr, reg_addr, data_len, pb) != 0) { + retry--; + if (retry <= 0) { + NT_LOG(ERR, NTHW, + "%s: I2C%d: Write retry exhausted (dev_addr=%d reg_addr=%d)\n", + p_adapter_id_str, p->mn_iic_instance, dev_addr, + reg_addr); + return -1; + } +#if defined(DEBUG) + NT_LOG(DBG, NTHW, + "%s: I2C%d: Write retry=%d (dev_addr=%d reg_addr=%d)\n", + p_adapter_id_str, p->mn_iic_instance, retry, dev_addr, + reg_addr); +#endif + } + + return 0; +} + +int nthw_iic_writebyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr, + uint8_t data_len, uint8_t *p_byte) +{ + const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str; + uint32_t value; + int count; + int i; + + if (data_len == 0) + return -1; + + count = data_len - 1; + if (nthw_iic_bus_ready(p)) { + /* Reset TX fifo */ + nthw_iic_reg_control_txfifo_reset(p); + + /* Write device address to TX_FIFO and set start bit!! */ + value = (dev_addr << 1) | I2C_TRANSMIT_WR; + nthw_iic_reg_tx_fifo_write(p, value, 1, 0); + + /* Write reg_addr to TX FIFO */ + nthw_iic_reg_tx_fifo_write(p, reg_addr, 0, 0); + + for (i = 0; i < count; i++) { + /* Write data byte to TX fifo and set stop bit */ + nthw_iic_reg_tx_fifo_write(p, *p_byte, 0, 0); + p_byte++; + } + + /* Write data byte to TX fifo and set stop bit */ + nthw_iic_reg_tx_fifo_write(p, *p_byte, 0, 1); + + if (!nthw_iic_bus_ready(p)) { + NT_LOG(WRN, NTHW, "%s: warn: !busReady (%s:%u)\n", + p_adapter_id_str, __func__, __LINE__); + while (true) { + if (nthw_iic_bus_ready(p)) { + NT_LOG(DBG, NTHW, + "%s: info: busReady (%s:%u)\n", + p_adapter_id_str, __func__, + __LINE__); + break; + } + } + } + + return 0; + + } else { + NT_LOG(WRN, NTHW, "%s: (%s:%u)\n", p_adapter_id_str, __func__, + __LINE__); + return -1; + } +} + +/* + * Support function for read/write functions below. Waits for bus ready. + */ +bool nthw_iic_bus_ready(nthw_iic_t *p) +{ + int count = (p->mn_bus_ready_retry >= 0 ? p->mn_bus_ready_retry : 1000); + bool b_bus_busy = true; + + while (true) { + nthw_iic_reg_busbusy(p, &b_bus_busy); + if (!b_bus_busy) + break; + + count--; + if (count <= 0) /* Test for timeout */ + break; + + if (p->mn_poll_delay != 0) + I2C_WAIT_US(p->mn_poll_delay); + } + + if (count == 0) + return false; + + return true; +} + +/* + * Support function for read function. Waits for data ready. + */ +bool nthw_iic_data_ready(nthw_iic_t *p) +{ + int count = (p->mn_data_ready_retry >= 0 ? p->mn_data_ready_retry : 1000); + bool b_rx_fifo_empty = true; + + while (true) { + nthw_iic_reg_rxfifo_empty(p, &b_rx_fifo_empty); + if (!b_rx_fifo_empty) + break; + + count--; + if (count <= 0) /* Test for timeout */ + break; + + if (p->mn_poll_delay != 0) + I2C_WAIT_US(p->mn_poll_delay); + } + + if (count == 0) + return false; + + return true; +} + +int nthw_iic_scan_dev_addr(nthw_iic_t *p, int n_dev_addr, int n_reg_addr) +{ + const char *const p_adapter_id_str _unused = + p->mp_fpga->p_fpga_info->mp_adapter_id_str; + int res; + uint8_t data_val = -1; + + res = nthw_iic_readbyte(p, (uint8_t)n_dev_addr, (uint8_t)n_reg_addr, 1, + &data_val); + if (res == 0) { + NT_LOG(DBG, NTHW, + "%s: I2C%d: devaddr=0x%02X (%03d) regaddr=%02X val=%02X (%03d) res=%d\n", + p_adapter_id_str, p->mn_iic_instance, n_dev_addr, n_dev_addr, + n_reg_addr, data_val, data_val, res); + } + return res; +} + +int nthw_iic_scan_find_dev(nthw_iic_t *p, int n_dev_addr_start, bool b_increate) +{ + const char *const p_adapter_id_str _unused = + p->mp_fpga->p_fpga_info->mp_adapter_id_str; + + int res = 0; + int i = 0; + + if (b_increate) { + for (i = n_dev_addr_start; i < 128; i++) { + res = nthw_iic_scan_dev_addr(p, i, 0x00); + if (res == 0) + break; + } + } else { + for (i = n_dev_addr_start; i >= 0; i--) { + res = nthw_iic_scan_dev_addr(p, i, 0x00); + if (res == 0) + break; + } + } + NT_LOG(DBG, NTHW, "%s: I2C%d: FOUND: %d\n", p_adapter_id_str, + p->mn_iic_instance, i); + return (res == 0 ? i : -1); +} + +int nthw_iic_scan(nthw_iic_t *p) +{ + int i; + + for (i = 0; i < 128; i++) + (void)nthw_iic_scan_dev_addr(p, i, 0x00); + return 0; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_iic.h b/drivers/net/ntnic/nthw/core/nthw_iic.h new file mode 100644 index 0000000000..e3bd313c88 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_iic.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_IIC_H__ +#define __NTHW_IIC_H__ + +#include "nthw_fpga_model.h" + +struct nthw_iic { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_iic; + int mn_iic_instance; + + uint32_t mn_iic_cycle_time; + int mn_poll_delay; + int mn_bus_ready_retry; + int mn_data_ready_retry; + int mn_read_data_retry; + int mn_write_data_retry; + + nt_register_t *mp_reg_tsusta; + nt_field_t *mp_fld_tsusta; + + nt_register_t *mp_reg_tsusto; + nt_field_t *mp_fld_tsusto; + + nt_register_t *mp_reg_thdsta; + nt_field_t *mp_fld_thdsta; + + nt_register_t *mp_reg_tsudat; + nt_field_t *mp_fld_tsudat; + + nt_register_t *mp_reg_tbuf; + nt_field_t *mp_fld_tbuf; + + nt_register_t *mp_reg_thigh; + nt_field_t *mp_fld_thigh; + + nt_register_t *mp_reg_tlow; + nt_field_t *mp_fld_tlow; + + nt_register_t *mp_reg_thddat; + nt_field_t *mp_fld_thddat; + + nt_register_t *mp_reg_cr; + nt_field_t *mp_fld_cr_en; + nt_field_t *mp_fld_cr_msms; + nt_field_t *mp_fld_cr_txfifo_reset; + nt_field_t *mp_fld_cr_txak; + + nt_register_t *mp_reg_sr; + nt_field_t *mp_fld_sr_bb; + nt_field_t *mp_fld_sr_rxfifo_full; + nt_field_t *mp_fld_sr_rxfifo_empty; + nt_field_t *mp_fld_sr_txfifo_full; + nt_field_t *mp_fld_sr_txfifo_empty; + + nt_register_t *mp_reg_tx_fifo; + nt_field_t *mp_fld_tx_fifo_txdata; + nt_field_t *mp_fld_tx_fifo_start; + nt_field_t *mp_fld_tx_fifo_stop; + + nt_register_t *mp_reg_rx_fifo_pirq; + nt_field_t *mp_fld_rx_fifo_pirq_cmp_val; + + nt_register_t *mp_reg_rx_fifo; + nt_field_t *mp_fld_rx_fifo_rxdata; + + nt_register_t *mp_reg_softr; + nt_field_t *mp_fld_softr_rkey; +}; + +typedef struct nthw_iic nthw_iic_t; +typedef struct nthw_iic nthw_iic; + +nthw_iic_t *nthw_iic_new(void); +int nthw_iic_init(nthw_iic_t *p, nt_fpga_t *p_fpga, int n_iic_instance, + uint32_t n_iic_cycle_time); +void nthw_iic_delete(nthw_iic_t *p); + +int nthw_iic_set_retry_params(nthw_iic_t *p, const int n_poll_delay, + const int n_bus_ready_retry, const int n_data_ready_retry, + const int n_read_data_retry, const int n_write_data_retry); + +int nthw_iic_read_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr, + uint8_t data_len, void *p_void); +int nthw_iic_readbyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr, + uint8_t data_len, uint8_t *p_byte); +int nthw_iic_write_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr, + uint8_t data_len, void *p_void); +int nthw_iic_writebyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr, + uint8_t data_len, uint8_t *p_byte); +bool nthw_iic_bus_ready(nthw_iic_t *p); +bool nthw_iic_data_ready(nthw_iic_t *p); + +int nthw_iic_scan(nthw_iic_t *p); +int nthw_iic_scan_dev_addr(nthw_iic_t *p, int n_dev_addr, int n_reg_addr); +int nthw_iic_scan_find_dev(nthw_iic_t *p, int n_dev_addr_start, bool b_increate); + +#endif /* __NTHW_IIC_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c new file mode 100644 index 0000000000..448caf1fd5 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c @@ -0,0 +1,1034 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nt_util.h" +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_mac_pcs.h" + +#define NTHW_MAC_PCS_LANES (20) + +static const uint8_t c_pcs_lanes = NTHW_MAC_PCS_LANES; +static const uint8_t c_mac_pcs_receiver_mode_dfe _unused; + +nthw_mac_pcs_t *nthw_mac_pcs_new(void) +{ + nthw_mac_pcs_t *p = malloc(sizeof(nthw_mac_pcs_t)); + + if (p) + memset(p, 0, sizeof(nthw_mac_pcs_t)); + return p; +} + +void nthw_mac_pcs_delete(nthw_mac_pcs_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_mac_pcs_t)); + free(p); + } +} + +/* + * Parameters: + * p != NULL: init struct pointed to by p + * p == NULL: check fpga module(s) presence (but no struct to init) + * + * Return value: + * <0: if p == NULL then fpga module(s) is/are not present. + * if p != NULL then fpga module(s) is/are not present, struct undefined + * ==0: if p == NULL then fpga module(s) is/are present (no struct to init) + * : if p != NULL then fpga module(s) is/are present and struct initialized + */ +int nthw_mac_pcs_init(nthw_mac_pcs_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + nt_module_t *mod = fpga_query_module(p_fpga, MOD_MAC_PCS, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: MAC_PCS %d: no such instance\n", + p_fpga->p_fpga_info->mp_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_mac_pcs = mod; + + assert(n_instance >= 0 && n_instance <= 255); + nthw_mac_pcs_set_port_no(p, (uint8_t)n_instance); + + { + nt_register_t *p_reg_block_lock, *p_reg_stat_pcs_rx, + *p_reg_stat_pcs_rx_latch; + nt_register_t *p_reg_vl_demuxed, *p_reg_gty_stat, *p_reg_pcs_config, + *p_reg_phymac_misc; + const int product_id = fpga_get_product_id(p_fpga); + + p_reg_block_lock = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_BLOCK_LOCK); + p->mp_reg_block_lock = p_reg_block_lock; + p->mp_fld_block_lock_lock = + register_get_field(p_reg_block_lock, MAC_PCS_BLOCK_LOCK_LOCK); + + p_reg_stat_pcs_rx = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_STAT_PCS_RX); + p->mp_reg_stat_pcs_rx = p_reg_stat_pcs_rx; + p->mp_fld_stat_pcs_rx_status = + register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_STATUS); + p->mp_fld_stat_pcs_rx_aligned = + register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_ALIGNED); + p->mp_fld_stat_pcs_rx_aligned_err = + register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_ALIGNED_ERR); + p->mp_fld_stat_pcs_rx_misaligned = + register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_MISALIGNED); + p->mp_fld_stat_pcs_rx_internal_local_fault = + register_get_field(p_reg_stat_pcs_rx, + MAC_PCS_STAT_PCS_RX_INTERNAL_LOCAL_FAULT); + p->mp_fld_stat_pcs_rx_received_local_fault = + register_get_field(p_reg_stat_pcs_rx, + MAC_PCS_STAT_PCS_RX_RECEIVED_LOCAL_FAULT); + p->mp_fld_stat_pcs_rx_local_fault = + register_get_field(p_reg_stat_pcs_rx, + MAC_PCS_STAT_PCS_RX_LOCAL_FAULT); + p->mp_fld_stat_pcs_rx_remote_fault = + register_get_field(p_reg_stat_pcs_rx, + MAC_PCS_STAT_PCS_RX_REMOTE_FAULT); + p->mp_fld_stat_pcs_rx_hi_ber = + register_get_field(p_reg_stat_pcs_rx, + MAC_PCS_STAT_PCS_RX_HI_BER); + + p_reg_stat_pcs_rx_latch = + module_get_register(p->mp_mod_mac_pcs, + MAC_PCS_STAT_PCS_RX_LATCH); + p->mp_reg_stat_pcs_rx_latch = p_reg_stat_pcs_rx_latch; + p->mp_fld_stat_pcs_rx_latch_status = + register_get_field(p_reg_stat_pcs_rx_latch, + MAC_PCS_STAT_PCS_RX_LATCH_STATUS); + + p_reg_vl_demuxed = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_VL_DEMUXED); + p->mp_fld_vl_demuxed_lock = + register_get_field(p_reg_vl_demuxed, MAC_PCS_VL_DEMUXED_LOCK); + + p_reg_gty_stat = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_STAT); + p->mp_fld_gty_stat_tx_rst_done0 = + register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_0); + p->mp_fld_gty_stat_tx_rst_done1 = + register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_1); + p->mp_fld_gty_stat_tx_rst_done2 = + register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_2); + p->mp_fld_gty_stat_tx_rst_done3 = + register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_3); + p->mp_fld_gty_stat_rx_rst_done0 = + register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_0); + p->mp_fld_gty_stat_rx_rst_done1 = + register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_1); + p->mp_fld_gty_stat_rx_rst_done2 = + register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_2); + p->mp_fld_gty_stat_rx_rst_done3 = + register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_3); + + p->m_fld_block_lock_lock_mask = 0; + p->m_fld_vl_demuxed_lock_mask = 0; + p->m_fld_gty_stat_tx_rst_done_mask = 0; + p->m_fld_gty_stat_rx_rst_done_mask = 0; + + if (product_id == 9563) { + /* NT200A01_2X100 implements 20 virtual lanes */ + p->m_fld_block_lock_lock_mask = (1 << 20) - 1; + /* NT200A01_2X100 implements 20 virtual lanes */ + p->m_fld_vl_demuxed_lock_mask = (1 << 20) - 1; + p->m_fld_gty_stat_tx_rst_done_mask = + 1; /* NT200A01_2X100 implements 4 GTY */ + p->m_fld_gty_stat_rx_rst_done_mask = + 1; /* NT200A01_2X100 implements 4 GTY */ + } else { + /* Remember to add new productIds */ + assert(0); + } + + p_reg_pcs_config = module_get_register(p->mp_mod_mac_pcs, + MAC_PCS_MAC_PCS_CONFIG); + p->mp_fld_pcs_config_tx_path_rst = + register_get_field(p_reg_pcs_config, MAC_PCS_MAC_PCS_CONFIG_TX_PATH_RST); + p->mp_fld_pcs_config_rx_path_rst = + register_get_field(p_reg_pcs_config, MAC_PCS_MAC_PCS_CONFIG_RX_PATH_RST); + p->mp_fld_pcs_config_rx_enable = + register_get_field(p_reg_pcs_config, MAC_PCS_MAC_PCS_CONFIG_RX_ENABLE); + p->mp_fld_pcs_config_rx_force_resync = + register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_RX_FORCE_RESYNC); + p->mp_fld_pcs_config_rx_test_pattern = + register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_RX_TEST_PATTERN); + p->mp_fld_pcs_config_tx_enable = + register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_TX_ENABLE); + p->mp_fld_pcs_config_tx_send_idle = + register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_TX_SEND_IDLE); + p->mp_fld_pcs_config_tx_send_rfi = + register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_TX_SEND_RFI); + p->mp_fld_pcs_config_tx_test_pattern = + register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_TX_TEST_PATTERN); + + p->mp_reg_gty_loop = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_LOOP); + p->mp_fld_gty_loop_gt_loop0 = + register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_0); + p->mp_fld_gty_loop_gt_loop1 = + register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_1); + p->mp_fld_gty_loop_gt_loop2 = + register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_2); + p->mp_fld_gty_loop_gt_loop3 = + register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_3); + + p_reg_phymac_misc = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_PHYMAC_MISC); + p->mp_reg_phymac_misc = p_reg_phymac_misc; + p->mp_fld_phymac_misc_tx_sel_host = + register_get_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TX_SEL_HOST); + p->mp_fld_phymac_misc_tx_sel_tfg = + register_get_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TX_SEL_TFG); + p->mp_fld_phymac_misc_tx_sel_rx_loop = + register_get_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TX_SEL_RX_LOOP); + + /* SOP or EOP TIMESTAMP */ + p->mp_fld_phymac_misc_ts_eop = + register_query_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TS_EOP); + + p->mp_reg_link_summary = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_LINK_SUMMARY); + p->mp_fld_link_summary_abs = + register_get_field(p->mp_reg_link_summary, MAC_PCS_LINK_SUMMARY_ABS); + p->mp_fld_link_summary_nt_phy_link_state = + register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_NT_PHY_LINK_STATE); + p->mp_fld_link_summary_lh_abs = + register_get_field(p->mp_reg_link_summary, MAC_PCS_LINK_SUMMARY_LH_ABS); + p->mp_fld_link_summary_ll_nt_phy_link_state = + register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_LL_PHY_LINK_STATE); + p->mp_fld_link_summary_link_down_cnt = + register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_LINK_DOWN_CNT); + p->mp_fld_link_summary_nim_interr = + register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_NIM_INTERR); + p->mp_fld_link_summary_lh_local_fault = + register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_LH_LOCAL_FAULT); + p->mp_fld_link_summary_lh_remote_fault = + register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_LH_REMOTE_FAULT); + p->mp_fld_link_summary_local_fault = + register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_LOCAL_FAULT); + p->mp_fld_link_summary_remote_fault = + register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_REMOTE_FAULT); + + p->mp_reg_bip_err = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_BIP_ERR); + p->mp_fld_reg_bip_err_bip_err = + register_get_field(p->mp_reg_bip_err, MAC_PCS_BIP_ERR_BIP_ERR); + + p->mp_reg_fec_ctrl = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_CTRL); + p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in = + register_get_field(p->mp_reg_fec_ctrl, MAC_PCS_FEC_CTRL_RS_FEC_CTRL_IN); + + p->mp_reg_fec_stat = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_STAT); + p->mp_field_fec_stat_bypass = + register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_BYPASS); + p->mp_field_fec_stat_valid = + register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_VALID); + p->mp_field_fec_stat_am_lock0 = + register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_0); + p->mp_field_fec_stat_am_lock1 = + register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_1); + p->mp_field_fec_stat_am_lock2 = + register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_2); + p->mp_field_fec_stat_am_lock3 = + register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_3); + p->mp_field_fec_stat_fec_lane_algn = + register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_FEC_LANE_ALGN); + + p->mp_reg_fec_cw_cnt = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_CW_CNT); + p->mp_field_fec_cw_cnt_cw_cnt = + register_get_field(p->mp_reg_fec_cw_cnt, MAC_PCS_FEC_CW_CNT_CW_CNT); + + p->mp_reg_fec_ucw_cnt = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_UCW_CNT); + p->mp_field_fec_ucw_cnt_ucw_cnt = + register_get_field(p->mp_reg_fec_ucw_cnt, MAC_PCS_FEC_UCW_CNT_UCW_CNT); + + /* GTY_RX_BUF_STAT */ +#ifdef RXBUFSTAT + p->mp_reg_gty_rx_buf_stat = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_RX_BUF_STAT); + p->mp_field_gty_rx_buf_stat_rx_buf_stat0 = + register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_0); + p->mp_field_gty_rx_buf_stat_rx_buf_stat1 = + register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_1); + p->mp_field_gty_rx_buf_stat_rx_buf_stat2 = + register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_2); + p->mp_field_gty_rx_buf_stat_rx_buf_stat3 = + register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_3); + p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed0 = + register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_0); + p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed1 = + register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_1); + p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed2 = + register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_2); + p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed3 = + register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_3); +#endif + + /* GTY_PRE_CURSOR */ + p->mp_reg_gty_pre_cursor = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_PRE_CURSOR); + p->mp_field_gty_pre_cursor_tx_pre_csr0 = + register_get_field(p->mp_reg_gty_pre_cursor, + MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_0); + p->mp_field_gty_pre_cursor_tx_pre_csr1 = + register_get_field(p->mp_reg_gty_pre_cursor, + MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_1); + p->mp_field_gty_pre_cursor_tx_pre_csr2 = + register_get_field(p->mp_reg_gty_pre_cursor, + MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_2); + p->mp_field_gty_pre_cursor_tx_pre_csr3 = + register_get_field(p->mp_reg_gty_pre_cursor, + MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_3); + + /* GTY_DIFF_CTL */ + p->mp_reg_gty_diff_ctl = + module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_DIFF_CTL); + p->mp_field_gty_gty_diff_ctl_tx_diff_ctl0 = + register_get_field(p->mp_reg_gty_diff_ctl, + MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_0); + p->mp_field_gty_gty_diff_ctl_tx_diff_ctl1 = + register_get_field(p->mp_reg_gty_diff_ctl, + MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_1); + p->mp_field_gty_gty_diff_ctl_tx_diff_ctl2 = + register_get_field(p->mp_reg_gty_diff_ctl, + MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_2); + p->mp_field_gty_gty_diff_ctl_tx_diff_ctl3 = + register_get_field(p->mp_reg_gty_diff_ctl, + MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_3); + + /* GTY_POST_CURSOR */ + p->mp_reg_gty_post_cursor = + module_get_register(p->mp_mod_mac_pcs, + MAC_PCS_GTY_POST_CURSOR); + p->mp_field_gty_post_cursor_tx_post_csr0 = + register_get_field(p->mp_reg_gty_post_cursor, + MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_0); + p->mp_field_gty_post_cursor_tx_post_csr1 = + register_get_field(p->mp_reg_gty_post_cursor, + MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_1); + p->mp_field_gty_post_cursor_tx_post_csr2 = + register_get_field(p->mp_reg_gty_post_cursor, + MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_2); + p->mp_field_gty_post_cursor_tx_post_csr3 = + register_get_field(p->mp_reg_gty_post_cursor, + MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_3); + + /* GTY_CTL */ + p->mp_reg_gty_ctl = + module_query_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_CTL); + if (p->mp_reg_gty_ctl) { + p->mp_field_gty_ctl_tx_pol0 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_TX_POLARITY_0); + p->mp_field_gty_ctl_tx_pol1 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_TX_POLARITY_1); + p->mp_field_gty_ctl_tx_pol2 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_TX_POLARITY_2); + p->mp_field_gty_ctl_tx_pol3 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_TX_POLARITY_3); + } else { + p->mp_reg_gty_ctl = + module_get_register(p->mp_mod_mac_pcs, + MAC_PCS_GTY_CTL_RX); + p->mp_reg_gty_ctl_tx = + module_get_register(p->mp_mod_mac_pcs, + MAC_PCS_GTY_CTL_TX); + p->mp_field_gty_ctl_tx_pol0 = + register_get_field(p->mp_reg_gty_ctl_tx, + MAC_PCS_GTY_CTL_TX_POLARITY_0); + p->mp_field_gty_ctl_tx_pol1 = + register_get_field(p->mp_reg_gty_ctl_tx, + MAC_PCS_GTY_CTL_TX_POLARITY_1); + p->mp_field_gty_ctl_tx_pol2 = + register_get_field(p->mp_reg_gty_ctl_tx, + MAC_PCS_GTY_CTL_TX_POLARITY_2); + p->mp_field_gty_ctl_tx_pol3 = + register_get_field(p->mp_reg_gty_ctl_tx, + MAC_PCS_GTY_CTL_TX_POLARITY_3); + } + p->mp_field_gty_ctl_rx_pol0 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_RX_POLARITY_0); + p->mp_field_gty_ctl_rx_pol1 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_RX_POLARITY_1); + p->mp_field_gty_ctl_rx_pol2 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_RX_POLARITY_2); + p->mp_field_gty_ctl_rx_pol3 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_RX_POLARITY_3); + p->mp_field_gty_ctl_rx_lpm_en0 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_RX_LPM_EN_0); + p->mp_field_gty_ctl_rx_lpm_en1 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_RX_LPM_EN_1); + p->mp_field_gty_ctl_rx_lpm_en2 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_RX_LPM_EN_2); + p->mp_field_gty_ctl_rx_lpm_en3 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_RX_LPM_EN_3); + p->mp_field_gty_ctl_rx_equa_rst0 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_RX_EQUA_RST_0); + p->mp_field_gty_ctl_rx_equa_rst1 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_RX_EQUA_RST_1); + p->mp_field_gty_ctl_rx_equa_rst2 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_RX_EQUA_RST_2); + p->mp_field_gty_ctl_rx_equa_rst3 = + register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_RX_EQUA_RST_3); + + /* DEBOUNCE_CTRL */ + p->mp_reg_debounce_ctrl = + module_get_register(p->mp_mod_mac_pcs, + MAC_PCS_DEBOUNCE_CTRL); + p->mp_field_debounce_ctrl_nt_port_ctrl = + register_get_field(p->mp_reg_debounce_ctrl, + MAC_PCS_DEBOUNCE_CTRL_NT_PORT_CTRL); + + p->mp_reg_time_stamp_comp = + module_query_register(p->mp_mod_mac_pcs, + MAC_PCS_TIMESTAMP_COMP); + if (p->mp_reg_time_stamp_comp) { + /* TIMESTAMP_COMP */ + p->mp_field_time_stamp_comp_rx_dly = + register_get_field(p->mp_reg_time_stamp_comp, + MAC_PCS_TIMESTAMP_COMP_RX_DLY); + p->mp_field_time_stamp_comp_tx_dly = + register_get_field(p->mp_reg_time_stamp_comp, + MAC_PCS_TIMESTAMP_COMP_TX_DLY); + } + } + return 0; +} + +/* wrapper - for ease of use */ +void nthw_mac_pcs_tx_host_enable(nthw_mac_pcs_t *p, bool enable) +{ + nthw_mac_pcs_set_tx_sel_host(p, enable); + nthw_mac_pcs_set_tx_sel_tfg(p, !enable); +} + +void nthw_mac_pcs_set_rx_enable(nthw_mac_pcs_t *p, bool enable) +{ + field_get_updated(p->mp_fld_pcs_config_rx_enable); + if (enable) + field_set_flush(p->mp_fld_pcs_config_rx_enable); + + else + field_clr_flush(p->mp_fld_pcs_config_rx_enable); +} + +void nthw_mac_pcs_set_tx_enable(nthw_mac_pcs_t *p, bool enable) +{ + field_get_updated(p->mp_fld_pcs_config_tx_enable); + if (enable) + field_set_flush(p->mp_fld_pcs_config_tx_enable); + + else + field_clr_flush(p->mp_fld_pcs_config_tx_enable); +} + +void nthw_mac_pcs_set_tx_sel_host(nthw_mac_pcs_t *p, bool enable) +{ + field_get_updated(p->mp_fld_phymac_misc_tx_sel_host); + if (enable) + field_set_flush(p->mp_fld_phymac_misc_tx_sel_host); + + else + field_clr_flush(p->mp_fld_phymac_misc_tx_sel_host); +} + +void nthw_mac_pcs_set_tx_sel_tfg(nthw_mac_pcs_t *p, bool enable) +{ + field_get_updated(p->mp_fld_phymac_misc_tx_sel_tfg); + if (enable) + field_set_flush(p->mp_fld_phymac_misc_tx_sel_tfg); + + else + field_clr_flush(p->mp_fld_phymac_misc_tx_sel_tfg); +} + +void nthw_mac_pcs_set_ts_eop(nthw_mac_pcs_t *p, bool enable) +{ + if (p->mp_fld_phymac_misc_ts_eop) { + field_get_updated(p->mp_fld_phymac_misc_ts_eop); + if (enable) + field_set_flush(p->mp_fld_phymac_misc_ts_eop); + + else + field_clr_flush(p->mp_fld_phymac_misc_ts_eop); + } +} + +bool nthw_mac_pcs_is_block_and_lane_lock_locked(nthw_mac_pcs_t *p) +{ + uint32_t block_lock; + uint32_t lane_lock; + + block_lock = field_get_updated(p->mp_fld_block_lock_lock) & + p->m_fld_block_lock_lock_mask; + lane_lock = field_get_updated(p->mp_fld_vl_demuxed_lock) & + p->m_fld_vl_demuxed_lock_mask; + if (block_lock == p->m_fld_block_lock_lock_mask && + lane_lock == p->m_fld_vl_demuxed_lock_mask) + return true; + + return false; +} + +void nthw_mac_pcs_tx_path_rst(nthw_mac_pcs_t *p, bool enable) +{ + field_get_updated(p->mp_fld_pcs_config_tx_path_rst); + if (enable) + field_set_flush(p->mp_fld_pcs_config_tx_path_rst); + + else + field_clr_flush(p->mp_fld_pcs_config_tx_path_rst); +} + +void nthw_mac_pcs_rx_path_rst(nthw_mac_pcs_t *p, bool enable) +{ + field_get_updated(p->mp_fld_pcs_config_rx_path_rst); + if (enable) + field_set_flush(p->mp_fld_pcs_config_rx_path_rst); + + else + field_clr_flush(p->mp_fld_pcs_config_rx_path_rst); +} + +bool nthw_mac_pcs_is_rx_path_rst(nthw_mac_pcs_t *p) +{ + return field_get_updated(p->mp_fld_pcs_config_rx_path_rst); +} + +void nthw_mac_pcs_tx_send_rfi(nthw_mac_pcs_t *p, bool enable) +{ + field_get_updated(p->mp_fld_pcs_config_tx_send_rfi); + if (enable) + field_set_flush(p->mp_fld_pcs_config_tx_send_rfi); + + else + field_clr_flush(p->mp_fld_pcs_config_tx_send_rfi); +} + +void nthw_mac_pcs_rx_force_resync(nthw_mac_pcs_t *p, bool enable) +{ + field_get_updated(p->mp_fld_pcs_config_rx_force_resync); + if (enable) + field_set_flush(p->mp_fld_pcs_config_rx_force_resync); + + else + field_clr_flush(p->mp_fld_pcs_config_rx_force_resync); +} + +bool nthw_mac_pcs_is_gt_fsm_rx_reset_done(nthw_mac_pcs_t *p) +{ + if ((field_get_updated(p->mp_fld_gty_stat_rx_rst_done0) & + p->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask && + (field_get_updated(p->mp_fld_gty_stat_rx_rst_done1) & + p->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask && + (field_get_updated(p->mp_fld_gty_stat_rx_rst_done2) & + p->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask && + (field_get_updated(p->mp_fld_gty_stat_rx_rst_done3) & + p->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask) + return true; + + else + return false; +} + +bool nthw_mac_pcs_is_gt_fsm_tx_reset_done(nthw_mac_pcs_t *p) +{ + if ((field_get_updated(p->mp_fld_gty_stat_tx_rst_done0) & + p->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask && + (field_get_updated(p->mp_fld_gty_stat_tx_rst_done1) & + p->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask && + (field_get_updated(p->mp_fld_gty_stat_tx_rst_done2) & + p->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask && + (field_get_updated(p->mp_fld_gty_stat_tx_rst_done3) & + p->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask) + return true; + + else + return false; +} + +void nthw_mac_pcs_set_host_loopback(nthw_mac_pcs_t *p, bool enable) +{ + register_update(p->mp_reg_gty_loop); + if (enable) { + field_set_val32(p->mp_fld_gty_loop_gt_loop0, 2); + field_set_val32(p->mp_fld_gty_loop_gt_loop1, 2); + field_set_val32(p->mp_fld_gty_loop_gt_loop2, 2); + field_set_val32(p->mp_fld_gty_loop_gt_loop3, 2); + } else { + field_set_val32(p->mp_fld_gty_loop_gt_loop0, 0); + field_set_val32(p->mp_fld_gty_loop_gt_loop1, 0); + field_set_val32(p->mp_fld_gty_loop_gt_loop2, 0); + field_set_val32(p->mp_fld_gty_loop_gt_loop3, 0); + } + register_flush(p->mp_reg_gty_loop, 1); +} + +void nthw_mac_pcs_set_line_loopback(nthw_mac_pcs_t *p, bool enable) +{ + register_update(p->mp_reg_gty_loop); + if (enable) { + field_set_val32(p->mp_fld_gty_loop_gt_loop0, 4); + field_set_val32(p->mp_fld_gty_loop_gt_loop1, 4); + field_set_val32(p->mp_fld_gty_loop_gt_loop2, 4); + field_set_val32(p->mp_fld_gty_loop_gt_loop3, 4); + } else { + field_set_val32(p->mp_fld_gty_loop_gt_loop0, 0); + field_set_val32(p->mp_fld_gty_loop_gt_loop1, 0); + field_set_val32(p->mp_fld_gty_loop_gt_loop2, 0); + field_set_val32(p->mp_fld_gty_loop_gt_loop3, 0); + } + register_flush(p->mp_reg_gty_loop, 1); +} + +void nthw_mac_pcs_reset_bip_counters(nthw_mac_pcs_t *p) +{ + uint32_t lane_bit_errors[NTHW_MAC_PCS_LANES]; + + register_update(p->mp_reg_bip_err); + field_get_val(p->mp_fld_reg_bip_err_bip_err, (uint32_t *)lane_bit_errors, + ARRAY_SIZE(lane_bit_errors)); + +#if defined(DEBUG) + { + uint8_t lane; + + for (lane = 0; lane < c_pcs_lanes; lane++) { + if (lane_bit_errors[lane]) { + NT_LOG(DBG, NTHW, + "Port %u: pcsLane %2u: BIP8 errors: %u\n", + p->m_port_no, lane, lane_bit_errors[lane]); + } + } + } +#else + (void)c_pcs_lanes; /* unused - kill warning */ +#endif +} + +void nthw_mac_pcs_get_status(nthw_mac_pcs_t *p, uint8_t *status) +{ + *status = field_get_updated(p->mp_fld_stat_pcs_rx_status) & 0x01; +} + +bool nthw_mac_pcs_get_hi_ber(nthw_mac_pcs_t *p) +{ + return field_get_updated(p->mp_fld_stat_pcs_rx_hi_ber); +} + +void nthw_mac_pcs_get_link_summary(nthw_mac_pcs_t *p, uint32_t *p_abs, + uint32_t *p_nt_phy_link_state, uint32_t *p_lh_abs, + uint32_t *p_ll_nt_phy_link_state, + uint32_t *p_link_down_cnt, uint32_t *p_nim_interr, + uint32_t *p_lh_local_fault, + uint32_t *p_lh_remote_fault, uint32_t *p_local_fault, + uint32_t *p_remote_fault) +{ + register_update(p->mp_reg_link_summary); + if (p_abs) + *p_abs = field_get_val32(p->mp_fld_link_summary_abs); + if (p_nt_phy_link_state) { + *p_nt_phy_link_state = + field_get_val32(p->mp_fld_link_summary_nt_phy_link_state); + } + if (p_lh_abs) + *p_lh_abs = field_get_val32(p->mp_fld_link_summary_lh_abs); + if (p_ll_nt_phy_link_state) { + *p_ll_nt_phy_link_state = + field_get_val32(p->mp_fld_link_summary_ll_nt_phy_link_state); + } + if (p_link_down_cnt) + *p_link_down_cnt = field_get_val32(p->mp_fld_link_summary_link_down_cnt); + if (p_nim_interr) + *p_nim_interr = field_get_val32(p->mp_fld_link_summary_nim_interr); + if (p_lh_local_fault) { + *p_lh_local_fault = + field_get_val32(p->mp_fld_link_summary_lh_local_fault); + } + if (p_lh_remote_fault) { + *p_lh_remote_fault = + field_get_val32(p->mp_fld_link_summary_lh_remote_fault); + } + if (p_local_fault) + *p_local_fault = field_get_val32(p->mp_fld_link_summary_local_fault); + if (p_remote_fault) + *p_remote_fault = field_get_val32(p->mp_fld_link_summary_remote_fault); +} + +/* + * Returns true if the lane/block lock bits indicate that a reset is required. + * This is the case if Block/Lane lock is not all zero but not all set either. + */ +bool nthw_mac_pcs_reset_required(nthw_mac_pcs_t *p) +{ + uint32_t block_lock = nthw_mac_pcs_get_fld_block_lock_lock(p); + uint32_t lane_lock = nthw_mac_pcs_get_fld_lane_lock_lock(p); + uint32_t block_lock_mask = nthw_mac_pcs_get_fld_block_lock_lock_mask(p); + uint32_t lane_lock_mask = nthw_mac_pcs_get_fld_lane_lock_lock_mask(p); + + return ((block_lock != 0) && (block_lock != block_lock_mask)) || + ((lane_lock != 0) && (lane_lock != lane_lock_mask)); +} + +void nthw_mac_pcs_set_fec(nthw_mac_pcs_t *p, bool enable) +{ + NT_LOG(DBG, NTHW, "Port %u: Set FEC: %u\n", p->m_port_no, enable); + + field_get_updated(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in); + if (enable) { + field_set_val_flush32(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in, 0); + } else { + field_set_val_flush32(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in, + (1 << 5) - 1); + } + + /* Both Rx and Tx must be reset for new FEC state to become active */ + nthw_mac_pcs_rx_path_rst(p, true); + nthw_mac_pcs_tx_path_rst(p, true); + NT_OS_WAIT_USEC(10000); /* 10ms */ + + nthw_mac_pcs_rx_path_rst(p, false); + nthw_mac_pcs_tx_path_rst(p, false); + NT_OS_WAIT_USEC(10000); /* 10ms */ + +#ifdef DEBUG + if (enable) { + NT_LOG(DBG, NTHW, "Port %u: FEC valid: %u\n", p->m_port_no, + field_get_updated(p->mp_field_fec_stat_valid)); + } else { + NT_LOG(DBG, NTHW, "Port %u: FEC bypass: %u\n", p->m_port_no, + field_get_updated(p->mp_field_fec_stat_bypass)); + } +#endif +} + +bool nthw_mac_pcs_get_fec_bypass(nthw_mac_pcs_t *p) +{ + return field_get_updated(p->mp_field_fec_stat_bypass); +} + +bool nthw_mac_pcs_get_fec_valid(nthw_mac_pcs_t *p) +{ + return field_get_updated(p->mp_field_fec_stat_valid); +} + +bool nthw_mac_pcs_get_fec_aligned(nthw_mac_pcs_t *p) +{ + return field_get_updated(p->mp_field_fec_stat_fec_lane_algn); +} + +bool nthw_mac_pcs_get_fec_stat_any_am_locked(nthw_mac_pcs_t *p) +{ + register_update(p->mp_reg_fec_stat); + if ((field_get_val32(p->mp_field_fec_stat_am_lock0)) || + (field_get_val32(p->mp_field_fec_stat_am_lock1)) || + (field_get_val32(p->mp_field_fec_stat_am_lock2)) || + (field_get_val32(p->mp_field_fec_stat_am_lock3))) + return true; + return false; +} + +bool nthw_mac_pcs_get_fec_stat_all_am_locked(nthw_mac_pcs_t *p) +{ + register_update(p->mp_reg_fec_stat); + if ((field_get_val32(p->mp_field_fec_stat_am_lock0)) && + (field_get_val32(p->mp_field_fec_stat_am_lock1)) && + (field_get_val32(p->mp_field_fec_stat_am_lock2)) && + (field_get_val32(p->mp_field_fec_stat_am_lock3))) + return true; + return false; +} + +void nthw_mac_pcs_dump_fec_stat_fields(nthw_mac_pcs_t *p) +{ + register_update(p->mp_reg_fec_stat); + NT_LOG(DBG, NTHW, + "Port %u: FEC_STAT VALID: %u, AM_LOCK_0: %u, AM_LOCK_1: %u, AM_LOCK_2: %u, AM_LOCK_0: %u, FEC_LANE_ALGN: %u\n", + p->m_port_no, field_get_val32(p->mp_field_fec_stat_valid), + field_get_val32(p->mp_field_fec_stat_am_lock0), + field_get_val32(p->mp_field_fec_stat_am_lock1), + field_get_val32(p->mp_field_fec_stat_am_lock2), + field_get_val32(p->mp_field_fec_stat_am_lock3), + field_get_val32(p->mp_field_fec_stat_fec_lane_algn)); +} + +void nthw_mac_pcs_reset_fec_counters(nthw_mac_pcs_t *p) +{ + register_update(p->mp_reg_fec_cw_cnt); + register_update(p->mp_reg_fec_ucw_cnt); + + if (field_get_val32(p->mp_field_fec_cw_cnt_cw_cnt)) { + NT_LOG(DBG, NTHW, "Port %u: FEC_CW_CNT: %u\n", p->m_port_no, + field_get_val32(p->mp_field_fec_cw_cnt_cw_cnt)); + } + if (field_get_val32(p->mp_field_fec_ucw_cnt_ucw_cnt)) { + NT_LOG(DBG, NTHW, "Port %u: FEC_UCW_CNT: %u\n", p->m_port_no, + field_get_val32(p->mp_field_fec_ucw_cnt_ucw_cnt)); + } +} + +bool nthw_mac_pcs_get_gty_rx_buf_stat_error(nthw_mac_pcs_t *p) +{ + register_update(p->mp_reg_gty_rx_buf_stat); + + if (field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed0) || + field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed1) || + field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed2) || + field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed3)) { + if (field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat0) || + field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat1) || + field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat2) || + field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat3)) { + NT_LOG(DBG, NTHW, + "Port %u: GTY RX_BUF_STAT_0: %u, RX_BUF_STAT_1: %u, RX_BUF_STAT_2: %u, RX_BUF_STAT_3: %u\n", + p->m_port_no, + field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat0), + field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat1), + field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat2), + field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat3)); + + return true; + } + } + return false; +} + +void nthw_mac_pcs_set_gty_tx_tuning(nthw_mac_pcs_t *p, uint8_t lane, uint8_t tx_pre_csr, + uint8_t tx_diff_ctl, uint8_t tx_post_csr) +{ + /* GTY_PRE_CURSOR */ + register_update(p->mp_reg_gty_pre_cursor); + switch (lane) { + case 0: + field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr0, + tx_pre_csr & 0x1F); + break; + case 1: + field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr1, + tx_pre_csr & 0x1F); + break; + case 2: + field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr2, + tx_pre_csr & 0x1F); + break; + case 3: + field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr3, + tx_pre_csr & 0x1F); + break; + } + + /* GTY_DIFF_CTL */ + register_update(p->mp_reg_gty_diff_ctl); + switch (lane) { + case 0: + field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl0, + tx_diff_ctl & 0x1F); + break; + case 1: + field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl1, + tx_diff_ctl & 0x1F); + break; + case 2: + field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl2, + tx_diff_ctl & 0x1F); + break; + case 3: + field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl3, + tx_diff_ctl & 0x1F); + break; + } + + /* GTY_POST_CURSOR */ + register_update(p->mp_reg_gty_post_cursor); + switch (lane) { + case 0: + field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr0, + tx_post_csr & 0x1F); + break; + case 1: + field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr1, + tx_post_csr & 0x1F); + break; + case 2: + field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr2, + tx_post_csr & 0x1F); + break; + case 3: + field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr3, + tx_post_csr & 0x1F); + break; + } + + NT_LOG(DBG, NTHW, + "Port %u, lane %u: GTY txPreCsr: %d, txDiffCtl: %d, txPostCsr: %d\n", + p->m_port_no, lane, tx_pre_csr, tx_diff_ctl, tx_post_csr); +} + +/* + * Set receiver equalization mode + * 0: enable DFE + * mode 1: enable LPM + * + * See UltraScale Architecture GTY Transceivers www.xilinx.com page 181, + * UG578 (v1.1) November 24, 2015 + */ +void nthw_mac_pcs_set_receiver_equalization_mode(nthw_mac_pcs_t *p, uint8_t mode) +{ + register_update(p->mp_reg_gty_ctl); + field_set_val32(p->mp_field_gty_ctl_rx_lpm_en0, mode & 0x1); + field_set_val32(p->mp_field_gty_ctl_rx_lpm_en1, mode & 0x1); + field_set_val32(p->mp_field_gty_ctl_rx_lpm_en2, mode & 0x1); + field_set_val_flush32(p->mp_field_gty_ctl_rx_lpm_en3, mode & 0x1); + + /* Toggle reset */ + field_set_val32(p->mp_field_gty_ctl_rx_equa_rst0, 1); + field_set_val32(p->mp_field_gty_ctl_rx_equa_rst1, 1); + field_set_val32(p->mp_field_gty_ctl_rx_equa_rst2, 1); + field_set_val_flush32(p->mp_field_gty_ctl_rx_equa_rst3, 1); + + NT_OS_WAIT_USEC(1000); /* 1ms */ + + field_set_val32(p->mp_field_gty_ctl_rx_equa_rst0, 0); + field_set_val32(p->mp_field_gty_ctl_rx_equa_rst1, 0); + field_set_val32(p->mp_field_gty_ctl_rx_equa_rst2, 0); + field_set_val_flush32(p->mp_field_gty_ctl_rx_equa_rst3, 0); + + NT_LOG(DBG, NTHW, "Port %u: GTY receiver mode: %s\n", p->m_port_no, + (mode == c_mac_pcs_receiver_mode_dfe ? "DFE" : "LPM")); +} + +void nthw_mac_pcs_swap_gty_tx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap) +{ + register_update(p->mp_reg_gty_ctl); + switch (lane) { + case 0: + field_set_val_flush32(p->mp_field_gty_ctl_tx_pol0, swap); + break; + case 1: + field_set_val_flush32(p->mp_field_gty_ctl_tx_pol1, swap); + break; + case 2: + field_set_val_flush32(p->mp_field_gty_ctl_tx_pol2, swap); + break; + case 3: + field_set_val_flush32(p->mp_field_gty_ctl_tx_pol3, swap); + break; + } + NT_LOG(DBG, NTHW, "Port %u: set GTY Tx lane (%d) polarity: %d\n", + p->m_port_no, lane, swap); +} + +void nthw_mac_pcs_swap_gty_rx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap) +{ + register_update(p->mp_reg_gty_ctl); + switch (lane) { + case 0: + field_set_val_flush32(p->mp_field_gty_ctl_rx_pol0, swap); + break; + case 1: + field_set_val_flush32(p->mp_field_gty_ctl_rx_pol1, swap); + break; + case 2: + field_set_val_flush32(p->mp_field_gty_ctl_rx_pol2, swap); + break; + case 3: + field_set_val_flush32(p->mp_field_gty_ctl_rx_pol3, swap); + break; + } + NT_LOG(DBG, NTHW, "Port %u: set GTY Rx lane (%d) polarity: %d\n", + p->m_port_no, lane, swap); +} + +void nthw_mac_pcs_set_led_mode(nthw_mac_pcs_t *p, uint8_t mode) +{ + field_get_updated(p->mp_field_debounce_ctrl_nt_port_ctrl); + field_set_val_flush32(p->mp_field_debounce_ctrl_nt_port_ctrl, mode); +} + +void nthw_mac_pcs_set_timestamp_comp_rx(nthw_mac_pcs_t *p, uint16_t rx_dly) +{ + if (p->mp_field_time_stamp_comp_rx_dly) { + field_get_updated(p->mp_field_time_stamp_comp_rx_dly); + field_set_val_flush32(p->mp_field_time_stamp_comp_rx_dly, rx_dly); + } +} + +void nthw_mac_pcs_set_port_no(nthw_mac_pcs_t *p, uint8_t port_no) +{ + p->m_port_no = port_no; +} + +uint32_t nthw_mac_pcs_get_fld_block_lock_lock(nthw_mac_pcs_t *p) +{ + return field_get_updated(p->mp_fld_block_lock_lock); +} + +uint32_t nthw_mac_pcs_get_fld_block_lock_lock_mask(nthw_mac_pcs_t *p) +{ + return p->m_fld_block_lock_lock_mask; +} + +uint32_t nthw_mac_pcs_get_fld_lane_lock_lock(nthw_mac_pcs_t *p) +{ + return field_get_updated(p->mp_fld_vl_demuxed_lock); +} + +uint32_t nthw_mac_pcs_get_fld_lane_lock_lock_mask(nthw_mac_pcs_t *p) +{ + return p->m_fld_vl_demuxed_lock_mask; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs.h b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.h new file mode 100644 index 0000000000..08197f8b9e --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.h @@ -0,0 +1,261 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NTHW_MAC_PCS_H_ +#define NTHW_MAC_PCS_H_ + +enum nthw_mac_pcs_led_mode_e { + NTHW_MAC_PCS_LED_AUTO = 0x00, + NTHW_MAC_PCS_LED_ON = 0x01, + NTHW_MAC_PCS_LED_OFF = 0x02, + NTHW_MAC_PCS_LED_PORTID = 0x03, +}; + +#define nthw_mac_pcs_receiver_mode_dfe (0) +#define nthw_mac_pcs_receiver_mode_lpm (1) + +struct nthw_mac_pcs { + uint8_t m_port_no; + + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_mac_pcs; + int mn_instance; + + /* Block lock status */ + nt_field_t *mp_fld_block_lock_lock; + uint32_t m_fld_block_lock_lock_mask; + + /* Lane lock status */ + nt_field_t *mp_fld_vl_demuxed_lock; + uint32_t m_fld_vl_demuxed_lock_mask; + + /* GTY_STAT */ + nt_field_t *mp_fld_gty_stat_rx_rst_done0; + nt_field_t *mp_fld_gty_stat_rx_rst_done1; + nt_field_t *mp_fld_gty_stat_rx_rst_done2; + nt_field_t *mp_fld_gty_stat_rx_rst_done3; + nt_field_t *mp_fld_gty_stat_tx_rst_done0; + nt_field_t *mp_fld_gty_stat_tx_rst_done1; + nt_field_t *mp_fld_gty_stat_tx_rst_done2; + nt_field_t *mp_fld_gty_stat_tx_rst_done3; + uint32_t m_fld_gty_stat_rx_rst_done_mask; + uint32_t m_fld_gty_stat_tx_rst_done_mask; + + /* GTY_LOOP */ + nt_register_t *mp_reg_gty_loop; + nt_field_t *mp_fld_gty_loop_gt_loop0; + nt_field_t *mp_fld_gty_loop_gt_loop1; + nt_field_t *mp_fld_gty_loop_gt_loop2; + nt_field_t *mp_fld_gty_loop_gt_loop3; + + /* MAC_PCS_CONFIG */ + nt_field_t *mp_fld_pcs_config_tx_path_rst; + nt_field_t *mp_fld_pcs_config_rx_path_rst; + nt_field_t *mp_fld_pcs_config_rx_enable; + nt_field_t *mp_fld_pcs_config_rx_force_resync; + nt_field_t *mp_fld_pcs_config_rx_test_pattern; + nt_field_t *mp_fld_pcs_config_tx_enable; + nt_field_t *mp_fld_pcs_config_tx_send_idle; + nt_field_t *mp_fld_pcs_config_tx_send_rfi; + nt_field_t *mp_fld_pcs_config_tx_test_pattern; + + /* STAT PCS */ + nt_field_t *mp_fld_stat_pcs_rx_status; + nt_field_t *mp_fld_stat_pcs_rx_aligned; + nt_field_t *mp_fld_stat_pcs_rx_aligned_err; + nt_field_t *mp_fld_stat_pcs_rx_misaligned; + nt_field_t *mp_fld_stat_pcs_rx_internal_local_fault; + nt_field_t *mp_fld_stat_pcs_rx_received_local_fault; + nt_field_t *mp_fld_stat_pcs_rx_local_fault; + nt_field_t *mp_fld_stat_pcs_rx_remote_fault; + nt_field_t *mp_fld_stat_pcs_rx_hi_ber; + + /* STAT_PCS_RX_LATCH */ + nt_field_t *mp_fld_stat_pcs_rx_latch_status; + + /* PHYMAC_MISC */ + nt_field_t *mp_fld_phymac_misc_tx_sel_host; + nt_field_t *mp_fld_phymac_misc_tx_sel_tfg; + nt_field_t *mp_fld_phymac_misc_tx_sel_rx_loop; + nt_field_t *mp_fld_phymac_misc_ts_eop; + + /* LINK_SUMMARY */ + nt_register_t *mp_reg_link_summary; + nt_field_t *mp_fld_link_summary_abs; + nt_field_t *mp_fld_link_summary_nt_phy_link_state; + nt_field_t *mp_fld_link_summary_lh_abs; + nt_field_t *mp_fld_link_summary_ll_nt_phy_link_state; + nt_field_t *mp_fld_link_summary_link_down_cnt; + nt_field_t *mp_fld_link_summary_nim_interr; + nt_field_t *mp_fld_link_summary_lh_local_fault; + nt_field_t *mp_fld_link_summary_lh_remote_fault; + nt_field_t *mp_fld_link_summary_local_fault; + nt_field_t *mp_fld_link_summary_remote_fault; + + /* BIP_ERR */ + nt_register_t *mp_reg_bip_err; + nt_field_t *mp_fld_reg_bip_err_bip_err; + + /* FEC_CTRL */ + nt_register_t *mp_reg_fec_ctrl; + nt_field_t *mp_field_fec_ctrl_reg_rs_fec_ctrl_in; + + /* FEC_STAT */ + nt_register_t *mp_reg_fec_stat; + nt_field_t *mp_field_fec_stat_bypass; + nt_field_t *mp_field_fec_stat_valid; + nt_field_t *mp_field_fec_stat_am_lock0; + nt_field_t *mp_field_fec_stat_am_lock1; + nt_field_t *mp_field_fec_stat_am_lock2; + nt_field_t *mp_field_fec_stat_am_lock3; + nt_field_t *mp_field_fec_stat_fec_lane_algn; + + /* FEC Corrected code word count */ + nt_register_t *mp_reg_fec_cw_cnt; + nt_field_t *mp_field_fec_cw_cnt_cw_cnt; + + /* FEC Uncorrected code word count */ + nt_register_t *mp_reg_fec_ucw_cnt; + nt_field_t *mp_field_fec_ucw_cnt_ucw_cnt; + + /* GTY_RX_BUF_STAT */ + nt_register_t *mp_reg_gty_rx_buf_stat; + nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat0; + nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat1; + nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat2; + nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat3; + nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed0; + nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed1; + nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed2; + nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed3; + + /* GTY_PRE_CURSOR */ + nt_register_t *mp_reg_gty_pre_cursor; + nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr0; + nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr1; + nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr2; + nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr3; + + /* GTY_DIFF_CTL */ + nt_register_t *mp_reg_gty_diff_ctl; + nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl0; + nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl1; + nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl2; + nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl3; + + /* GTY_POST_CURSOR */ + nt_register_t *mp_reg_gty_post_cursor; + nt_field_t *mp_field_gty_post_cursor_tx_post_csr0; + nt_field_t *mp_field_gty_post_cursor_tx_post_csr1; + nt_field_t *mp_field_gty_post_cursor_tx_post_csr2; + nt_field_t *mp_field_gty_post_cursor_tx_post_csr3; + + /* GTY_CTL */ + nt_register_t *mp_reg_gty_ctl; + nt_register_t *mp_reg_gty_ctl_tx; + nt_field_t *mp_field_gty_ctl_tx_pol0; + nt_field_t *mp_field_gty_ctl_tx_pol1; + nt_field_t *mp_field_gty_ctl_tx_pol2; + nt_field_t *mp_field_gty_ctl_tx_pol3; + nt_field_t *mp_field_gty_ctl_rx_pol0; + nt_field_t *mp_field_gty_ctl_rx_pol1; + nt_field_t *mp_field_gty_ctl_rx_pol2; + nt_field_t *mp_field_gty_ctl_rx_pol3; + nt_field_t *mp_field_gty_ctl_rx_lpm_en0; + nt_field_t *mp_field_gty_ctl_rx_lpm_en1; + nt_field_t *mp_field_gty_ctl_rx_lpm_en2; + nt_field_t *mp_field_gty_ctl_rx_lpm_en3; + nt_field_t *mp_field_gty_ctl_rx_equa_rst0; + nt_field_t *mp_field_gty_ctl_rx_equa_rst1; + nt_field_t *mp_field_gty_ctl_rx_equa_rst2; + nt_field_t *mp_field_gty_ctl_rx_equa_rst3; + + /* DEBOUNCE_CTRL */ + nt_register_t *mp_reg_debounce_ctrl; + nt_field_t *mp_field_debounce_ctrl_nt_port_ctrl; + + /* TIMESTAMP_COMP */ + nt_register_t *mp_reg_time_stamp_comp; + nt_field_t *mp_field_time_stamp_comp_rx_dly; + nt_field_t *mp_field_time_stamp_comp_tx_dly; + + /* STAT_PCS_RX */ + nt_register_t *mp_reg_stat_pcs_rx; + + /* STAT_PCS_RX */ + nt_register_t *mp_reg_stat_pcs_rx_latch; + + /* PHYMAC_MISC */ + nt_register_t *mp_reg_phymac_misc; + + /* BLOCK_LOCK */ + nt_register_t *mp_reg_block_lock; +}; + +typedef struct nthw_mac_pcs nthw_mac_pcs_t; +typedef struct nthw_mac_pcs nthw_mac_pcs; + +nthw_mac_pcs_t *nthw_mac_pcs_new(void); +int nthw_mac_pcs_init(nthw_mac_pcs_t *p, nt_fpga_t *p_fpga, int n_instance); +void nthw_mac_pcs_delete(nthw_mac_pcs_t *p); + +bool nthw_mac_pcs_is_block_and_lane_lock_locked(nthw_mac_pcs_t *p); +bool nthw_mac_pcs_is_gt_fsm_rx_reset_done(nthw_mac_pcs_t *p); +bool nthw_mac_pcs_is_gt_fsm_tx_reset_done(nthw_mac_pcs_t *p); +void nthw_mac_pcs_tx_path_rst(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_rx_path_rst(nthw_mac_pcs_t *p, bool enable); +bool nthw_mac_pcs_is_rx_path_rst(nthw_mac_pcs_t *p); +void nthw_mac_pcs_rx_force_resync(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_tx_send_rfi(nthw_mac_pcs_t *p, bool enable); +bool nthw_mac_pcs_is_dd_r3_calib_done(nthw_mac_pcs_t *p); +void nthw_mac_pcs_tx_host_enable(nthw_mac_pcs_t *p, + bool enable); /* wrapper - for ease of use */ +void nthw_mac_pcs_set_rx_enable(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_set_tx_enable(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_set_tx_sel_host(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_set_tx_sel_tfg(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_set_ts_eop(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_set_host_loopback(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_set_line_loopback(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_reset_bip_counters(nthw_mac_pcs_t *p); +void nthw_mac_pcs_get_status(nthw_mac_pcs_t *p, uint8_t *status); +bool nthw_mac_pcs_get_hi_ber(nthw_mac_pcs_t *p); + +void nthw_mac_pcs_get_link_summary1(nthw_mac_pcs_t *p, uint32_t *p_status, + uint32_t *p_status_latch, uint32_t *p_aligned, + uint32_t *p_local_fault, uint32_t *p_remote_fault); + +void nthw_mac_pcs_get_link_summary(nthw_mac_pcs_t *p, uint32_t *p_abs, + uint32_t *p_nt_phy_link_state, uint32_t *p_lh_abs, + uint32_t *p_ll_nt_phy_link_state, + uint32_t *p_link_down_cnt, uint32_t *p_nim_interr, + uint32_t *p_lh_local_fault, + uint32_t *p_lh_remote_fault, uint32_t *p_local_fault, + uint32_t *p_remote_fault); + +bool nthw_mac_pcs_reset_required(nthw_mac_pcs_t *p); +void nthw_mac_pcs_set_fec(nthw_mac_pcs_t *p, bool enable); +bool nthw_mac_pcs_get_fec_bypass(nthw_mac_pcs_t *p); +bool nthw_mac_pcs_get_fec_valid(nthw_mac_pcs_t *p); +bool nthw_mac_pcs_get_fec_aligned(nthw_mac_pcs_t *p); +bool nthw_mac_pcs_get_fec_stat_any_am_locked(nthw_mac_pcs_t *p); +bool nthw_mac_pcs_get_fec_stat_all_am_locked(nthw_mac_pcs_t *p); +void nthw_mac_pcs_dump_fec_stat_fields(nthw_mac_pcs_t *p); +void nthw_mac_pcs_reset_fec_counters(nthw_mac_pcs_t *p); +bool nthw_mac_pcs_get_gty_rx_buf_stat_error(nthw_mac_pcs_t *p); +void nthw_mac_pcs_set_gty_tx_tuning(nthw_mac_pcs_t *p, uint8_t lane, uint8_t tx_pre_csr, + uint8_t tx_diff_ctl, uint8_t tx_post_csr); +void nthw_mac_pcs_swap_gty_tx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap); +void nthw_mac_pcs_swap_gty_rx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap); +void nthw_mac_pcs_set_receiver_equalization_mode(nthw_mac_pcs_t *p, uint8_t mode); +void nthw_mac_pcs_set_led_mode(nthw_mac_pcs_t *p, uint8_t mode); +void nthw_mac_pcs_set_timestamp_comp_rx(nthw_mac_pcs_t *p, uint16_t rx_dly); +void nthw_mac_pcs_set_port_no(nthw_mac_pcs_t *p, uint8_t port_no); + +uint32_t nthw_mac_pcs_get_fld_block_lock_lock(nthw_mac_pcs_t *p); +uint32_t nthw_mac_pcs_get_fld_block_lock_lock_mask(nthw_mac_pcs_t *p); +uint32_t nthw_mac_pcs_get_fld_lane_lock_lock(nthw_mac_pcs_t *p); +uint32_t nthw_mac_pcs_get_fld_lane_lock_lock_mask(nthw_mac_pcs_t *p); + +#endif /* NTHW_MAC_PCS_H_ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c new file mode 100644 index 0000000000..d8e1f0de5d --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c @@ -0,0 +1,1631 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_mac_pcs_xxv.h" + +static void nthw_mac_pcs_xxv_field_set_or_clr_flush(const nt_field_t *f, bool set) +{ + if (f) { + field_get_updated(f); + if (set) + field_set_flush(f); + else + field_clr_flush(f); + } +} + +nthw_mac_pcs_xxv_t *nthw_mac_pcs_xxv_new(void) +{ + nthw_mac_pcs_xxv_t *p = malloc(sizeof(nthw_mac_pcs_xxv_t)); + + if (p) + memset(p, 0, sizeof(nthw_mac_pcs_xxv_t)); + return p; +} + +void nthw_mac_pcs_xxv_delete(nthw_mac_pcs_xxv_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_mac_pcs_xxv_t)); + free(p); + } +} + +uint8_t nthw_mac_pcs_xxv_get_port_no(const nthw_mac_pcs_xxv_t *p, uint8_t index) +{ + return index == 0 ? (uint8_t)p->mn_instance : index; +} + +void nthw_mac_pcs_xxv_set_port_no(nthw_mac_pcs_xxv_t *p, uint8_t port_no) +{ + p->m_port_no = port_no; +} + +void nthw_mac_pcs_xxv_get_link_summary(nthw_mac_pcs_xxv_t *p, + uint32_t *p_abs, uint32_t *p_nt_phy_link_state, + uint32_t *p_lh_abs, uint32_t *p_ll_nt_phy_link_state, uint32_t *p_link_down_cnt, + uint32_t *p_nim_interr, uint32_t *p_lh_local_fault, uint32_t *p_lh_remote_fault, + uint32_t *p_lh_internal_local_fault, uint32_t *p_lh_received_local_fault, + uint8_t index) +{ + struct nthw_mac_pcs_xxv__registers_fields *r = + &p->regs[index]; /* register and fields */ + + assert(p); + + register_update(r->mp_reg_link_summary); + if (p_abs) + *p_abs = field_get_val32(r->mp_fld_link_summary_abs); + if (p_nt_phy_link_state) { + *p_nt_phy_link_state = + field_get_val32(r->mp_fld_link_summary_nt_phy_link_state); + } + if (p_lh_abs) + *p_lh_abs = field_get_val32(r->mp_fld_link_summary_lh_abs); + if (p_ll_nt_phy_link_state) { + *p_ll_nt_phy_link_state = + field_get_val32(r->mp_fld_link_summary_ll_nt_phy_link_state); + } + if (p_link_down_cnt) + *p_link_down_cnt = field_get_val32(r->mp_fld_link_summary_link_down_cnt); + if (p_nim_interr) + *p_nim_interr = field_get_val32(r->mp_fld_link_summary_nim_interr); + if (p_lh_local_fault) { + *p_lh_local_fault = + field_get_val32(r->mp_fld_link_summary_lh_local_fault); + } + if (p_lh_remote_fault) { + *p_lh_remote_fault = + field_get_val32(r->mp_fld_link_summary_lh_remote_fault); + } + if (p_lh_internal_local_fault) { + *p_lh_internal_local_fault = + field_get_val32(r->mp_fld_link_summary_lh_internal_local_fault); + } + if (p_lh_received_local_fault) { + *p_lh_received_local_fault = + field_get_val32(r->mp_fld_link_summary_lh_received_local_fault); + } +} + +void nthw_mac_pcs_xxv_set_tx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_enable; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_rx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_core_conf_rx_enable; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_rx_force_resync(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_core_conf_rx_force_resync; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_reset_rx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_rx_gt_data; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_reset_tx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_tx_gt_data; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_reset_an_lt(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_an_lt; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_reset_speed_ctrl(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_speed_ctrl; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_send_rfi; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_tx_send_lfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_send_lfi; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_tx_send_lfi_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable_lfi, + bool enable_rfi, uint8_t index) +{ + register_update(p->regs[index].mp_reg_core_conf); + field_set_val32(p->regs[index].mp_fld_core_conf_tx_send_lfi, enable_lfi); + field_set_val32(p->regs[index].mp_fld_core_conf_tx_send_rfi, enable_rfi); + register_flush(p->regs[index].mp_reg_core_conf, 1); +} + +bool nthw_mac_pcs_xxv_is_dfe_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_rx_lpm_en; + + /* NOTE: DFE is enabled when LPM is disabled */ + return !field_get_updated(f); +} + +void nthw_mac_pcs_xxv_set_dfe(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index) +{ + const nt_field_t *f = p->regs[index].mp_fld_gty_ctl_rx_lpm_en; + const bool set_dfe = + !enable; /* NOTE: Enable DFE mode means setting LPM = 0 */ + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, set_dfe); + + /* Toggle GTY_CTL_RX->EQUA_RST to 1 and 0 to assert new LPM_EN setting */ + f = p->regs[index].mp_fld_gty_ctl_rx_equa_rst; + field_get_updated(f); + field_set_val_flush32(f, 1); /* Assert GTH SOFT RESET */ + field_get_updated(f); + field_set_val_flush32(f, 0); /* De-Assert GTH SOFT RESET */ + field_get_updated(f); +} + +void nthw_mac_pcs_xxv_set_rx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_rx_polarity; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_tx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_tx_polarity; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_tx_gty_inhibit(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_tx_inhibit; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_host_loopback(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_gty_loop_gt_loop; + + field_get_updated(f); + field_set_val_flush32(f, enable ? 2U : 0U); +} + +void nthw_mac_pcs_xxv_set_line_loopback(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_core_conf_line_loopback; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +bool nthw_mac_pcs_xxv_is_user_rx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index) +{ + return field_get_updated(p->regs[index].mp_fld_sub_rst_status_user_rx_rst); +} + +bool nthw_mac_pcs_xxv_is_user_tx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index) +{ + return field_get_updated(p->regs[index].mp_fld_sub_rst_status_user_tx_rst); +} + +/* + * QPLL lock signal. + * For cores capable of 10G only, there are only 1 QPLL. For cores capable of + * 10G/25G, there are 2 QPLLs. + */ +bool nthw_mac_pcs_xxv_is_qpll_lock(nthw_mac_pcs_xxv_t *p, uint8_t index) +{ + return (field_get_updated(p->regs[index].mp_fld_sub_rst_status_qpll_lock) == + 3); +} + +bool nthw_mac_pcs_xxv_is_sub_rst_ready(nthw_mac_pcs_xxv_t *p, uint8_t index) +{ + return (nthw_mac_pcs_xxv_is_qpll_lock(p, index) && + !nthw_mac_pcs_xxv_is_user_rx_rst(p, index) && + !nthw_mac_pcs_xxv_is_user_tx_rst(p, index)); +} + +bool nthw_mac_pcs_xxv_is_aneg_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index) +{ + return field_get_updated(p->regs[index].mp_fld_aneg_config_enable); +} + +void nthw_mac_pcs_xxv_set_tx_send_idle(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_send_idle; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_tx_ins_fcs(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_ins_fcs; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +bool nthw_mac_pcs_xxv_get_link_speed10_g(nthw_mac_pcs_xxv_t *p, uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_link_speed10_g; + + return field_get_updated(f) != 0; /* 0 = 25g, 1 = 10g */ +} + +void nthw_mac_pcs_xxv_set_link_speed10_g(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_link_speed10_g; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_link_speed_toggle(nthw_mac_pcs_xxv_t *p, uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_link_speed_toggle; + + field_get_updated(f); + field_set_flush(f); +} + +void nthw_mac_pcs_xxv_set_rs_fec_conf_rs_fec_enable(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_rs_fec_conf_rs_fec_enable; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_led_mode(nthw_mac_pcs_xxv_t *p, uint8_t mode, uint8_t index) +{ + const nt_field_t *const f = + p->regs[index].mp_field_debounce_ctrl_nt_port_ctrl; + + field_get_updated(f); + field_set_val_flush32(f, mode); +} + +void nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_rx_mac_pcs; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_tx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_tx_mac_pcs; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_reset_fec_counters(nthw_mac_pcs_xxv_t *p, uint8_t index) +{ + register_update(p->regs[index].mp_reg_rs_fec_ccw); + register_update(p->regs[index].mp_reg_rs_fec_ucw); + + if (field_get_val32(p->regs[index].mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt)) { + NT_LOG(DBG, NTHW, "Port %u: FEC_CW_CNT: %u", p->m_port_no, + field_get_val32(p->regs[index].mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt)); + } + if (field_get_val32(p->regs[index].mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt)) { + NT_LOG(DBG, NTHW, "Port %u: FEC_UCW_CNT: %u", p->m_port_no, + field_get_val32(p->regs[index].mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt)); + } +} + +void nthw_mac_pcs_xxv_set_timestamp_comp_rx(nthw_mac_pcs_xxv_t *p, uint16_t rx_dly, + uint8_t index) +{ + field_get_updated(p->regs[index].mp_field_timestamp_comp_rx_dly); + field_set_val_flush32(p->regs[index].mp_field_timestamp_comp_rx_dly, rx_dly); +} + +void nthw_mac_pcs_xxv_set_timestamp_comp_tx(nthw_mac_pcs_xxv_t *p, uint16_t tx_dly, + uint8_t index) +{ + field_get_updated(p->regs[index].mp_field_timestamp_comp_tx_dly); + field_set_val_flush32(p->regs[index].mp_field_timestamp_comp_tx_dly, tx_dly); +} + +void nthw_mac_pcs_xxv_set_ts_at_eop(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_core_conf_ts_at_eop; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_gty_diff(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index) +{ + field_get_updated(p->regs[index].mp_field_gty_gty_diff_ctl_tx_diff_ctl); + field_set_val_flush32(p->regs[index].mp_field_gty_gty_diff_ctl_tx_diff_ctl, + value); +} + +void nthw_mac_pcs_xxv_set_gty_pre(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index) +{ + field_get_updated(p->regs[index].mp_field_gty_pre_cursor_tx_pre_csr); + field_set_val_flush32(p->regs[index].mp_field_gty_pre_cursor_tx_pre_csr, value); +} + +void nthw_mac_pcs_xxv_set_gty_post(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index) +{ + field_get_updated(p->regs[index].mp_field_gty_post_cursor_tx_post_csr); + field_set_val_flush32(p->regs[index].mp_field_gty_post_cursor_tx_post_csr, + value); +} + +void nthw_mac_pcs_xxv_set_lt_conf_enable(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_lt_conf_enable; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_aneg_config_fec91_request(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_fec91_request; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_aneg_config_rs_fec_request(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_rs_fec_request; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_aneg_config_fec74_request(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_fec74_request; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_aneg_config_enable(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_enable; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_aneg_config_bypass(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index) +{ + const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_bypass; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +void nthw_mac_pcs_xxv_set_dac_mode(nthw_mac_pcs_xxv_t *p, uint8_t dac_mode, + uint8_t index) +{ + if (dac_mode == NTHW_MAC_PCS_XXV_DAC_OFF) { + nthw_mac_pcs_xxv_reset_an_lt(p, false, index); + nthw_mac_pcs_xxv_set_aneg_config_enable(p, false, index); + nthw_mac_pcs_xxv_set_aneg_config_bypass(p, true, index); + nthw_mac_pcs_xxv_set_lt_conf_enable(p, false, index); + nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(p, true, index); + nthw_mac_pcs_xxv_set_tx_mac_pcs_rst(p, true, index); + nthw_mac_pcs_xxv_reset_rx_gt_data(p, true, index); + nthw_mac_pcs_xxv_reset_tx_gt_data(p, true, index); + nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(p, false, index); + nthw_mac_pcs_xxv_set_tx_mac_pcs_rst(p, false, index); + nthw_mac_pcs_xxv_reset_rx_gt_data(p, false, index); + nthw_mac_pcs_xxv_reset_tx_gt_data(p, false, index); + + return; + } + assert(0); /* If you end up here you need to implement other DAC modes */ +} + +bool nthw_mac_pcs_xxv_get_ll_rx_fec74_lock(nthw_mac_pcs_xxv_t *p, uint8_t index) +{ + return field_get_updated(p->regs[index].mp_fld_link_summary_ll_rx_fec74_lock); +} + +bool nthw_mac_pcs_xxv_get_ll_rx_rsfec_lane_alignment(nthw_mac_pcs_xxv_t *p, uint8_t index) +{ + return field_get_updated(p->regs[index].mp_fld_link_summary_ll_rx_rsfec_lane_alignment); +} + +int nthw_mac_pcs_xxv_init(nthw_mac_pcs_xxv_t *p, nt_fpga_t *p_fpga, int n_instance, + int n_channels) +{ + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_MAC_PCS_XXV, n_instance); + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + const bool m_mac8x10_g = false; + nt_module_t *module = p_mod; + uint64_t n_module_version_packed64 = -1; + nt_register_t *r; + nt_register_t *(*get_register)(nt_module_t *, uint32_t) = + module_get_register; + nt_field_t *(*get_field)(const nt_register_t *, uint32_t) = + register_get_field; + nt_field_t *(*query_field)(const nt_register_t *, uint32_t) = + register_query_field; + struct nthw_mac_pcs_xxv__registers_fields *rf; + + if (p == NULL) + return (p_mod == NULL ? -1 : 0); + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, + "%s: MAC_PCS_XXV instance=%d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_mac_pcs_xxv = p_mod; + + memset(p->regs, 0, sizeof(p->regs)); + + n_module_version_packed64 = module_get_version_packed64(p->mp_mod_mac_pcs_xxv); + switch (n_module_version_packed64) { + case (0UL << 32) | 0UL: /* 0.0 */ + case (0UL << 32) | 1UL: /* 0.1 */ + case (0UL << 32) | 2UL: /* 0.2 */ + NT_LOG(DBG, NTHW, + "%s: MAC_PCS_XXV instance=%d: version=0x%08lX\n", + p_adapter_id_str, p->mn_instance, n_module_version_packed64); + break; + default: + NT_LOG(ERR, NTHW, + "%s: MAC_PCS_XXV instance=%d: version=0x%08lX: unsupported module version\n", + p_adapter_id_str, p->mn_instance, n_module_version_packed64); + return -1; + } + + assert(n_channels == 1 || n_channels == 2 || n_channels == 4); + + /* Register MAC_PCS_XXV_CORE_CONF_0 -- MAC_PCS_XXV_CORE_CONF_3 */ + if (n_channels < 4) { + /* Initialize regs/fields for sub-module/channel 0 */ + rf = &p->regs[0]; + r = get_register(module, MAC_PCS_XXV_CORE_CONF_0); + + rf->mp_reg_core_conf = r; + rf->mp_fld_core_conf_rx_enable = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_RX_ENABLE); + rf->mp_fld_core_conf_rx_force_resync = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_RX_FORCE_RESYNC); + rf->mp_fld_core_conf_tx_enable = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_ENABLE); + rf->mp_fld_core_conf_tx_ins_fcs = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_INS_FCS); + rf->mp_fld_core_conf_tx_ign_fcs = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_IGN_FCS); + rf->mp_fld_core_conf_tx_send_lfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_LFI); + rf->mp_fld_core_conf_tx_send_rfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_RFI); + rf->mp_fld_core_conf_tx_send_idle = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_IDLE); + rf->mp_fld_core_conf_inline_mode = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_INLINE_MODE); + rf->mp_fld_core_conf_line_loopback = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_LINE_LOOPBACK); + rf->mp_fld_core_conf_ts_at_eop = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_TS_AT_EOP); + } + + if (n_channels >= 2) { + /* Initialize regs/fields for sub-module/channel 1 */ + rf = &p->regs[1]; + r = get_register(module, MAC_PCS_XXV_CORE_CONF_1); + + rf->mp_reg_core_conf = r; + rf->mp_fld_core_conf_rx_enable = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_RX_ENABLE); + rf->mp_fld_core_conf_rx_force_resync = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_RX_FORCE_RESYNC); + rf->mp_fld_core_conf_tx_enable = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_ENABLE); + rf->mp_fld_core_conf_tx_ins_fcs = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_INS_FCS); + rf->mp_fld_core_conf_tx_ign_fcs = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_IGN_FCS); + rf->mp_fld_core_conf_tx_send_lfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_LFI); + rf->mp_fld_core_conf_tx_send_rfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_RFI); + rf->mp_fld_core_conf_tx_send_idle = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_IDLE); + rf->mp_fld_core_conf_inline_mode = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_INLINE_MODE); + rf->mp_fld_core_conf_line_loopback = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_LINE_LOOPBACK); + rf->mp_fld_core_conf_ts_at_eop = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_TS_AT_EOP); + } + + if (n_channels == 4) { + /* Initialize regs/fields for sub-module/channel 2 */ + rf = &p->regs[2]; + r = get_register(module, MAC_PCS_XXV_CORE_CONF_2); + + rf->mp_reg_core_conf = r; + rf->mp_fld_core_conf_rx_enable = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_RX_ENABLE); + rf->mp_fld_core_conf_rx_force_resync = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_RX_FORCE_RESYNC); + rf->mp_fld_core_conf_tx_enable = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_ENABLE); + rf->mp_fld_core_conf_tx_ins_fcs = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_INS_FCS); + rf->mp_fld_core_conf_tx_ign_fcs = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_IGN_FCS); + rf->mp_fld_core_conf_tx_send_lfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_LFI); + rf->mp_fld_core_conf_tx_send_rfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_RFI); + rf->mp_fld_core_conf_tx_send_idle = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_IDLE); + rf->mp_fld_core_conf_inline_mode = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_INLINE_MODE); + rf->mp_fld_core_conf_line_loopback = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_LINE_LOOPBACK); + rf->mp_fld_core_conf_ts_at_eop = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_TS_AT_EOP); + + /* Initialize regs/fields for sub-module/channel 3 */ + rf = &p->regs[3]; + r = get_register(module, MAC_PCS_XXV_CORE_CONF_3); + + rf->mp_reg_core_conf = r; + rf->mp_fld_core_conf_rx_enable = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_RX_ENABLE); + rf->mp_fld_core_conf_rx_force_resync = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_RX_FORCE_RESYNC); + rf->mp_fld_core_conf_tx_enable = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_ENABLE); + rf->mp_fld_core_conf_tx_ins_fcs = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_INS_FCS); + rf->mp_fld_core_conf_tx_ign_fcs = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_IGN_FCS); + rf->mp_fld_core_conf_tx_send_lfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_LFI); + rf->mp_fld_core_conf_tx_send_rfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_RFI); + rf->mp_fld_core_conf_tx_send_idle = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_IDLE); + rf->mp_fld_core_conf_inline_mode = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_INLINE_MODE); + rf->mp_fld_core_conf_line_loopback = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_LINE_LOOPBACK); + rf->mp_fld_core_conf_ts_at_eop = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_TS_AT_EOP); + } + + /* + * Registers MAC_PCS_XXV_ANEG_CONFIG_0 -- MAC_PCS_XXV_ANEG_CONFIG_3 + * and MAC_PCS_XXV_ANEG_ABILITY_0 -- MAC_PCS_XXV_ANEG_ABILITY_3 + * and MAC_PCS_XXV_LT_CONF_0 -- MAC_PCS_XXV_LT_CONF_3 + */ + if (!m_mac8x10_g && n_channels < 4) { + /* 2 x 10 25 G */ + /* ANEG_CONFIG */ + rf = &p->regs[0]; + + r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_0); + rf->mp_reg_aneg_config = r; + rf->mp_fld_aneg_config_enable = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_ENABLE); + rf->mp_fld_aneg_config_bypass = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_BYPASS); + rf->mp_fld_aneg_config_restart = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_RESTART); + rf->mp_fld_aneg_config_pseudo = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_PSEUDO); + rf->mp_fld_aneg_config_nonce_seed = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_NONCE_SEED); + rf->mp_fld_aneg_config_remote_fault = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_REMOTE_FAULT); + rf->mp_fld_aneg_config_pause = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_PAUSE); + rf->mp_fld_aneg_config_asmdir = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_ASMDIR); + rf->mp_fld_aneg_config_fec74_request10_g = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST_10G); + rf->mp_fld_aneg_config_hide_fec74 = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_HIDE_FEC74); + rf->mp_fld_aneg_config_fec74_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST); + rf->mp_fld_aneg_config_fec91_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_REQUEST); + rf->mp_fld_aneg_config_fec91_ability = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_ABILITY); + rf->mp_fld_aneg_config_rs_fec_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_RS_FEC_REQUEST); + rf->mp_fld_aneg_config_sw_fec_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_SW_FEC_OVERWRITE); + rf->mp_fld_aneg_config_sw_speed_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_SW_SPEED_OVERWRITE); + + /* ANEG_ABILITY */ + r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_0); + rf->mp_reg_aneg_ability = r; + + rf->mp_fld_aneg_ability25_g_base_cr = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR); + if (!rf->mp_fld_aneg_ability25_g_base_cr) { + rf->mp_fld_aneg_ability25_g_base_cr = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR); + } + + rf->mp_fld_aneg_ability25_g_base_crs = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR_S); + if (!rf->mp_fld_aneg_ability25_g_base_crs) { + rf->mp_fld_aneg_ability25_g_base_crs = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR_S); + } + + rf->mp_fld_aneg_ability25_g_base_cr1 = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR1); + if (!rf->mp_fld_aneg_ability25_g_base_cr1) { + rf->mp_fld_aneg_ability25_g_base_cr1 = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR1); + } + + /* LT_CONF */ + r = get_register(module, MAC_PCS_XXV_LT_CONF_0); + rf->mp_reg_lt_conf = r; + rf->mp_fld_lt_conf_enable = + get_field(r, MAC_PCS_XXV_LT_CONF_0_ENABLE); + rf->mp_fld_lt_conf_restart = + get_field(r, MAC_PCS_XXV_LT_CONF_0_RESTART); + rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_0_SEED); + } + + if (!m_mac8x10_g && n_channels >= 2) { + /* 2 x 10 25 G */ + /* ANEG_CONFIG */ + + /* Initialize regs/fields for sub-module/channel 1 */ + rf = &p->regs[1]; + + r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_1); + rf->mp_reg_aneg_config = r; + rf->mp_fld_aneg_config_enable = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_ENABLE); + rf->mp_fld_aneg_config_bypass = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_BYPASS); + rf->mp_fld_aneg_config_restart = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_RESTART); + rf->mp_fld_aneg_config_pseudo = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_PSEUDO); + rf->mp_fld_aneg_config_nonce_seed = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_NONCE_SEED); + rf->mp_fld_aneg_config_remote_fault = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_REMOTE_FAULT); + rf->mp_fld_aneg_config_pause = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_PAUSE); + rf->mp_fld_aneg_config_asmdir = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_ASMDIR); + rf->mp_fld_aneg_config_fec74_request10_g = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST_10G); + rf->mp_fld_aneg_config_hide_fec74 = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_HIDE_FEC74); + rf->mp_fld_aneg_config_fec74_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST); + rf->mp_fld_aneg_config_fec91_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_REQUEST); + rf->mp_fld_aneg_config_fec91_ability = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_ABILITY); + rf->mp_fld_aneg_config_rs_fec_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_RS_FEC_REQUEST); + rf->mp_fld_aneg_config_sw_fec_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_SW_FEC_OVERWRITE); + rf->mp_fld_aneg_config_sw_speed_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_SW_SPEED_OVERWRITE); + + /* ANEG_ABILITY */ + r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_1); + rf->mp_reg_aneg_ability = r; + + rf->mp_fld_aneg_ability25_g_base_cr = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR); + if (!rf->mp_fld_aneg_ability25_g_base_cr) { + rf->mp_fld_aneg_ability25_g_base_cr = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR); + } + + rf->mp_fld_aneg_ability25_g_base_crs = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR_S); + if (!rf->mp_fld_aneg_ability25_g_base_crs) { + rf->mp_fld_aneg_ability25_g_base_crs = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR_S); + } + + rf->mp_fld_aneg_ability25_g_base_cr1 = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR1); + if (!rf->mp_fld_aneg_ability25_g_base_cr1) { + rf->mp_fld_aneg_ability25_g_base_cr1 = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR1); + } + + /* LT_CONF */ + r = get_register(module, MAC_PCS_XXV_LT_CONF_1); + rf->mp_reg_lt_conf = r; + rf->mp_fld_lt_conf_enable = + get_field(r, MAC_PCS_XXV_LT_CONF_1_ENABLE); + rf->mp_fld_lt_conf_restart = + get_field(r, MAC_PCS_XXV_LT_CONF_1_RESTART); + rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_1_SEED); + } + + if (!m_mac8x10_g && n_channels == 4) { + /* Initialize regs/fields for sub-module/channel 2 */ + rf = &p->regs[2]; + + r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_2); + rf->mp_reg_aneg_config = r; + rf->mp_fld_aneg_config_enable = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_ENABLE); + rf->mp_fld_aneg_config_bypass = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_BYPASS); + rf->mp_fld_aneg_config_restart = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_RESTART); + rf->mp_fld_aneg_config_pseudo = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_PSEUDO); + rf->mp_fld_aneg_config_nonce_seed = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_NONCE_SEED); + rf->mp_fld_aneg_config_remote_fault = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_REMOTE_FAULT); + rf->mp_fld_aneg_config_pause = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_PAUSE); + rf->mp_fld_aneg_config_asmdir = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_ASMDIR); + rf->mp_fld_aneg_config_fec74_request10_g = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST_10G); + rf->mp_fld_aneg_config_hide_fec74 = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_HIDE_FEC74); + rf->mp_fld_aneg_config_fec74_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST); + rf->mp_fld_aneg_config_fec91_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_REQUEST); + rf->mp_fld_aneg_config_fec91_ability = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_ABILITY); + rf->mp_fld_aneg_config_rs_fec_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_RS_FEC_REQUEST); + rf->mp_fld_aneg_config_sw_fec_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_SW_FEC_OVERWRITE); + rf->mp_fld_aneg_config_sw_speed_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_SW_SPEED_OVERWRITE); + + /* ANEG_ABILITY */ + r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_2); + rf->mp_reg_aneg_ability = r; + rf->mp_fld_aneg_ability25_g_base_cr = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR); + rf->mp_fld_aneg_ability25_g_base_crs = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR_S); + rf->mp_fld_aneg_ability25_g_base_cr1 = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR1); + + /* LT_CONF */ + r = get_register(module, MAC_PCS_XXV_LT_CONF_2); + rf->mp_reg_lt_conf = r; + rf->mp_fld_lt_conf_enable = + get_field(r, MAC_PCS_XXV_LT_CONF_2_ENABLE); + rf->mp_fld_lt_conf_restart = + get_field(r, MAC_PCS_XXV_LT_CONF_2_RESTART); + rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_2_SEED); + + /* Initialize regs/fields for sub-module/channel 3 */ + rf = &p->regs[3]; + + r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_3); + rf->mp_reg_aneg_config = r; + rf->mp_fld_aneg_config_enable = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_ENABLE); + rf->mp_fld_aneg_config_bypass = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_BYPASS); + rf->mp_fld_aneg_config_restart = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_RESTART); + rf->mp_fld_aneg_config_pseudo = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_PSEUDO); + rf->mp_fld_aneg_config_nonce_seed = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_NONCE_SEED); + rf->mp_fld_aneg_config_remote_fault = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_REMOTE_FAULT); + rf->mp_fld_aneg_config_pause = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_PAUSE); + rf->mp_fld_aneg_config_asmdir = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_ASMDIR); + rf->mp_fld_aneg_config_fec74_request10_g = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST_10G); + rf->mp_fld_aneg_config_hide_fec74 = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_HIDE_FEC74); + rf->mp_fld_aneg_config_fec74_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST); + rf->mp_fld_aneg_config_fec91_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_REQUEST); + rf->mp_fld_aneg_config_fec91_ability = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_ABILITY); + rf->mp_fld_aneg_config_rs_fec_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_RS_FEC_REQUEST); + rf->mp_fld_aneg_config_sw_fec_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_SW_FEC_OVERWRITE); + rf->mp_fld_aneg_config_sw_speed_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_SW_SPEED_OVERWRITE); + + /* ANEG_ABILITY */ + r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_3); + rf->mp_reg_aneg_ability = r; + rf->mp_fld_aneg_ability25_g_base_cr = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR); + rf->mp_fld_aneg_ability25_g_base_crs = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR_S); + rf->mp_fld_aneg_ability25_g_base_cr1 = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR1); + + /* LT_CONF */ + r = get_register(module, MAC_PCS_XXV_LT_CONF_3); + rf->mp_reg_lt_conf = r; + rf->mp_fld_lt_conf_enable = + get_field(r, MAC_PCS_XXV_LT_CONF_3_ENABLE); + rf->mp_fld_lt_conf_restart = + get_field(r, MAC_PCS_XXV_LT_CONF_3_RESTART); + rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_3_SEED); + } + + /* + * Registers MAC_PCS_XXV_SUB_RST_0 -- MAC_PCS_XXV_SUB_RST_3 + * and MAC_PCS_XXV_SUB_RST_STATUS_0 -- MAC_PCS_XXV_SUB_RST_STATUS_3 + */ + if (n_channels < 4) { + /* Initialize regs/fields for sub-module/channel 0 */ + rf = &p->regs[0]; + r = get_register(module, MAC_PCS_XXV_SUB_RST_0); + + rf->mp_reg_sub_rst = r; + rf->mp_fld_sub_rst_rx_mac_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_MAC_PCS); + rf->mp_fld_sub_rst_tx_mac_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_MAC_PCS); + rf->mp_fld_sub_rst_rx_gt_data = + get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_GT_DATA); + rf->mp_fld_sub_rst_tx_gt_data = + get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_GT_DATA); + rf->mp_fld_sub_rst_rx_buf = + get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_BUF); + rf->mp_fld_sub_rst_rx_pma = + get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_PMA); + rf->mp_fld_sub_rst_tx_pma = + get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_PMA); + rf->mp_fld_sub_rst_rx_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_PCS); + rf->mp_fld_sub_rst_tx_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_PCS); + rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_0_AN_LT); + rf->mp_fld_sub_rst_speed_ctrl = + query_field(r, MAC_PCS_XXV_SUB_RST_0_SPEED_CTRL); + + r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_0); + rf->mp_reg_sub_rst_status = r; + rf->mp_fld_sub_rst_status_user_rx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_USER_RX_RST); + rf->mp_fld_sub_rst_status_user_tx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_USER_TX_RST); + rf->mp_fld_sub_rst_status_qpll_lock = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_QPLL_LOCK); + } + + if (n_channels >= 2) { + /* Initialize regs/fields for sub-module/channel 1 */ + rf = &p->regs[1]; + r = get_register(module, MAC_PCS_XXV_SUB_RST_1); + + rf->mp_reg_sub_rst = r; + rf->mp_fld_sub_rst_rx_mac_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_MAC_PCS); + rf->mp_fld_sub_rst_tx_mac_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_MAC_PCS); + rf->mp_fld_sub_rst_rx_gt_data = + get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_GT_DATA); + rf->mp_fld_sub_rst_tx_gt_data = + get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_GT_DATA); + rf->mp_fld_sub_rst_rx_buf = + get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_BUF); + rf->mp_fld_sub_rst_rx_pma = + get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_PMA); + rf->mp_fld_sub_rst_tx_pma = + get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_PMA); + rf->mp_fld_sub_rst_rx_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_PCS); + rf->mp_fld_sub_rst_tx_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_PCS); + rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_1_AN_LT); + rf->mp_fld_sub_rst_speed_ctrl = + query_field(r, MAC_PCS_XXV_SUB_RST_1_SPEED_CTRL); + + r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_1); + rf->mp_reg_sub_rst_status = r; + rf->mp_fld_sub_rst_status_user_rx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_USER_RX_RST); + rf->mp_fld_sub_rst_status_user_tx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_USER_TX_RST); + rf->mp_fld_sub_rst_status_qpll_lock = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_QPLL_LOCK); + } + + if (n_channels == 4) { + /* Initialize regs/fields for sub-module/channel 2 */ + rf = &p->regs[2]; + r = get_register(module, MAC_PCS_XXV_SUB_RST_2); + + rf->mp_reg_sub_rst = r; + rf->mp_fld_sub_rst_rx_mac_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_MAC_PCS); + rf->mp_fld_sub_rst_tx_mac_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_MAC_PCS); + rf->mp_fld_sub_rst_rx_gt_data = + get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_GT_DATA); + rf->mp_fld_sub_rst_tx_gt_data = + get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_GT_DATA); + rf->mp_fld_sub_rst_rx_buf = + get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_BUF); + rf->mp_fld_sub_rst_rx_pma = + get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_PMA); + rf->mp_fld_sub_rst_tx_pma = + get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_PMA); + rf->mp_fld_sub_rst_rx_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_PCS); + rf->mp_fld_sub_rst_tx_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_PCS); + rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_2_AN_LT); + rf->mp_fld_sub_rst_speed_ctrl = + query_field(r, MAC_PCS_XXV_SUB_RST_2_SPEED_CTRL); + + r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_2); + rf->mp_reg_sub_rst_status = r; + rf->mp_fld_sub_rst_status_user_rx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_USER_RX_RST); + rf->mp_fld_sub_rst_status_user_tx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_USER_TX_RST); + rf->mp_fld_sub_rst_status_qpll_lock = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_QPLL_LOCK); + + /* Initialize regs/fields for sub-module/channel 3 */ + rf = &p->regs[3]; + r = get_register(module, MAC_PCS_XXV_SUB_RST_3); + + rf->mp_reg_sub_rst = r; + rf->mp_fld_sub_rst_rx_mac_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_MAC_PCS); + rf->mp_fld_sub_rst_tx_mac_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_MAC_PCS); + rf->mp_fld_sub_rst_rx_gt_data = + get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_GT_DATA); + rf->mp_fld_sub_rst_tx_gt_data = + get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_GT_DATA); + rf->mp_fld_sub_rst_rx_buf = + get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_BUF); + rf->mp_fld_sub_rst_rx_pma = + get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_PMA); + rf->mp_fld_sub_rst_tx_pma = + get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_PMA); + rf->mp_fld_sub_rst_rx_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_PCS); + rf->mp_fld_sub_rst_tx_pcs = + get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_PCS); + rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_3_AN_LT); + rf->mp_fld_sub_rst_speed_ctrl = + query_field(r, MAC_PCS_XXV_SUB_RST_3_SPEED_CTRL); + + r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_3); + rf->mp_reg_sub_rst_status = r; + rf->mp_fld_sub_rst_status_user_rx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_USER_RX_RST); + rf->mp_fld_sub_rst_status_user_tx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_USER_TX_RST); + rf->mp_fld_sub_rst_status_qpll_lock = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_QPLL_LOCK); + } + + /* Registers MAC_PCS_XXV_LINK_SUMMARY_0 -- MAC_PCS_XXV_LINK_SUMMARY_3 */ + if (n_channels < 4) { + /* Initialize regs/fields for sub-module/channel 0 */ + rf = &p->regs[0]; + r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_0); + + rf->mp_reg_link_summary = r; + rf->mp_fld_link_summary_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_NT_PHY_LINK_STATE); + rf->mp_fld_link_summary_ll_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_PHY_LINK_STATE); + rf->mp_fld_link_summary_abs = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_ABS); + rf->mp_fld_link_summary_lh_abs = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_ABS); + rf->mp_fld_link_summary_link_down_cnt = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LINK_DOWN_CNT); + if (!m_mac8x10_g) { + rf->mp_fld_link_summary_ll_rx_fec74_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_FEC74_LOCK); + rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_RSFEC_HI_SER); + rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_TX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_PCS_VALID_CTRL_CODE); + } + rf->mp_fld_link_summary_ll_rx_block_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_BLOCK_LOCK); + rf->mp_fld_link_summary_lh_rx_high_bit_error_rate = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_HIGH_BIT_ERROR_RATE); + ; + rf->mp_fld_link_summary_lh_internal_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_INTERNAL_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_received_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RECEIVED_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_remote_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_REMOTE_FAULT); + rf->mp_fld_link_summary_nim_interr = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_NIM_INTERR); + } + + if (n_channels >= 2) { + /* Initialize regs/fields for sub-module/channel 1 */ + rf = &p->regs[1]; + r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_1); + + rf->mp_reg_link_summary = r; + rf->mp_fld_link_summary_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_NT_PHY_LINK_STATE); + rf->mp_fld_link_summary_ll_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_PHY_LINK_STATE); + rf->mp_fld_link_summary_abs = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_ABS); + rf->mp_fld_link_summary_lh_abs = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_ABS); + rf->mp_fld_link_summary_link_down_cnt = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LINK_DOWN_CNT); + if (!m_mac8x10_g) { + rf->mp_fld_link_summary_ll_rx_fec74_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_FEC74_LOCK); + rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_RSFEC_HI_SER); + rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_TX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_PCS_VALID_CTRL_CODE); + } + rf->mp_fld_link_summary_ll_rx_block_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_BLOCK_LOCK); + rf->mp_fld_link_summary_lh_rx_high_bit_error_rate = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_HIGH_BIT_ERROR_RATE); + ; + rf->mp_fld_link_summary_lh_internal_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_INTERNAL_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_received_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RECEIVED_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_remote_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_REMOTE_FAULT); + rf->mp_fld_link_summary_nim_interr = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_NIM_INTERR); + } + + if (n_channels == 4) { + /* Initialize regs/fields for sub-module/channel 2 */ + rf = &p->regs[2]; + r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_2); + + rf->mp_reg_link_summary = r; + rf->mp_fld_link_summary_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_NT_PHY_LINK_STATE); + rf->mp_fld_link_summary_ll_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_PHY_LINK_STATE); + rf->mp_fld_link_summary_abs = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_ABS); + rf->mp_fld_link_summary_lh_abs = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_ABS); + rf->mp_fld_link_summary_link_down_cnt = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LINK_DOWN_CNT); + if (!m_mac8x10_g) { + rf->mp_fld_link_summary_ll_rx_fec74_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_FEC74_LOCK); + rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_RSFEC_HI_SER); + rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_TX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_PCS_VALID_CTRL_CODE); + } + rf->mp_fld_link_summary_ll_rx_block_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_BLOCK_LOCK); + rf->mp_fld_link_summary_lh_rx_high_bit_error_rate = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_HIGH_BIT_ERROR_RATE); + ; + rf->mp_fld_link_summary_lh_internal_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_INTERNAL_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_received_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RECEIVED_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_remote_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_REMOTE_FAULT); + rf->mp_fld_link_summary_nim_interr = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_NIM_INTERR); + + /* Initialize regs/fields for sub-module/channel 3 */ + rf = &p->regs[3]; + r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_3); + + rf->mp_reg_link_summary = r; + rf->mp_fld_link_summary_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_NT_PHY_LINK_STATE); + rf->mp_fld_link_summary_ll_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_PHY_LINK_STATE); + rf->mp_fld_link_summary_abs = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_ABS); + rf->mp_fld_link_summary_lh_abs = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_ABS); + rf->mp_fld_link_summary_link_down_cnt = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LINK_DOWN_CNT); + if (!m_mac8x10_g) { + rf->mp_fld_link_summary_ll_rx_fec74_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_FEC74_LOCK); + rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_RSFEC_HI_SER); + rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_TX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_PCS_VALID_CTRL_CODE); + } + rf->mp_fld_link_summary_ll_rx_block_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_BLOCK_LOCK); + rf->mp_fld_link_summary_lh_rx_high_bit_error_rate = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_HIGH_BIT_ERROR_RATE); + ; + rf->mp_fld_link_summary_lh_internal_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_INTERNAL_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_received_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RECEIVED_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_remote_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_REMOTE_FAULT); + rf->mp_fld_link_summary_nim_interr = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_NIM_INTERR); + } + + /* + * Registers MAC_PCS_XXV_GTY_LOOP_0 -- MAC_PCS_XXV_GTY_LOOP_3 + * and MAC_PCS_XXV_GTY_CTL_RX_0 -- MAC_PCS_XXV_GTY_CTL_RX_3 + * and MAC_PCS_XXV_GTY_CTL_TX_0 -- MAC_PCS_XXV_GTY_CTL_TX_3 + * and MAC_PCS_XXV_LINK_SPEED_0 -- MAC_PCS_XXV_LINK_SPEED_3 + * and MAC_PCS_XXV_RS_FEC_CONF_0 -- MAC_PCS_XXV_RS_FEC_CONF_0 + */ + if (n_channels < 4) { + /* Initialize regs/fields for sub-module/channel 0 */ + rf = &p->regs[0]; + + r = get_register(module, MAC_PCS_XXV_GTY_LOOP_0); + rf->mp_reg_gty_loop = r; + rf->mp_fld_gty_loop_gt_loop = + get_field(r, MAC_PCS_XXV_GTY_LOOP_0_GT_LOOP); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_0); + rf->mp_reg_gty_ctl_rx = r; + rf->mp_fld_gty_ctl_rx_polarity = + get_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_POLARITY); + rf->mp_fld_gty_ctl_rx_lpm_en = + get_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_LPM_EN); + rf->mp_fld_gty_ctl_rx_equa_rst = + get_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_EQUA_RST); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_0); + rf->mp_fld_gty_ctl_tx_polarity = + get_field(r, MAC_PCS_XXV_GTY_CTL_TX_0_POLARITY); + rf->mp_fld_gty_ctl_tx_inhibit = + get_field(r, MAC_PCS_XXV_GTY_CTL_TX_0_INHIBIT); + + if (!m_mac8x10_g) { + r = get_register(module, MAC_PCS_XXV_LINK_SPEED_0); + rf->mp_reg_link_speed = + get_register(module, MAC_PCS_XXV_LINK_SPEED_0); + + rf->mp_fld_link_speed10_g = + query_field(r, MAC_PCS_XXV_LINK_SPEED_0_SPEED); + if (!rf->mp_fld_link_speed10_g) { + rf->mp_fld_link_speed10_g = + get_field(r, MAC_PCS_XXV_LINK_SPEED_0_10G); + } + + rf->mp_fld_link_speed_toggle = + get_field(r, MAC_PCS_XXV_LINK_SPEED_0_TOGGLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_0); + rf->mp_reg_rs_fec_conf = r; + rf->mp_fld_rs_fec_conf_rs_fec_enable = + get_field(r, MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_ENABLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_0); + rf->mp_reg_rs_fec_ccw = r; + rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_0_RS_FEC_CCW_CNT); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_0); + rf->mp_reg_rs_fec_ucw = r; + rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_0_RS_FEC_UCW_CNT); + } + } + + if (n_channels >= 2) { + /* Initialize regs/fields for sub-module/channel 1 */ + rf = &p->regs[1]; + + r = get_register(module, MAC_PCS_XXV_GTY_LOOP_1); + rf->mp_reg_gty_loop = r; + rf->mp_fld_gty_loop_gt_loop = + get_field(r, MAC_PCS_XXV_GTY_LOOP_1_GT_LOOP); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_1); + rf->mp_reg_gty_ctl_rx = r; + rf->mp_fld_gty_ctl_rx_polarity = + get_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_POLARITY); + rf->mp_fld_gty_ctl_rx_lpm_en = + get_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_LPM_EN); + rf->mp_fld_gty_ctl_rx_equa_rst = + get_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_EQUA_RST); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_1); + rf->mp_fld_gty_ctl_tx_polarity = + get_field(r, MAC_PCS_XXV_GTY_CTL_TX_1_POLARITY); + rf->mp_fld_gty_ctl_tx_inhibit = + get_field(r, MAC_PCS_XXV_GTY_CTL_TX_1_INHIBIT); + + if (!m_mac8x10_g) { + r = get_register(module, MAC_PCS_XXV_LINK_SPEED_1); + rf->mp_reg_link_speed = + get_register(module, MAC_PCS_XXV_LINK_SPEED_1); + + rf->mp_fld_link_speed10_g = + get_field(r, MAC_PCS_XXV_LINK_SPEED_1_SPEED); + if (!rf->mp_fld_link_speed10_g) { + rf->mp_fld_link_speed10_g = + get_field(r, MAC_PCS_XXV_LINK_SPEED_1_10G); + } + rf->mp_fld_link_speed_toggle = + get_field(r, MAC_PCS_XXV_LINK_SPEED_1_TOGGLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_1); + rf->mp_reg_rs_fec_conf = r; + rf->mp_fld_rs_fec_conf_rs_fec_enable = + get_field(r, MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_ENABLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_1); + rf->mp_reg_rs_fec_ccw = r; + rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_1_RS_FEC_CCW_CNT); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_1); + rf->mp_reg_rs_fec_ucw = r; + rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_1_RS_FEC_UCW_CNT); + } + } + + if (n_channels == 4) { + /* Initialize regs/fields for sub-module/channel 2 */ + rf = &p->regs[2]; + + r = get_register(module, MAC_PCS_XXV_GTY_LOOP_2); + rf->mp_reg_gty_loop = r; + rf->mp_fld_gty_loop_gt_loop = + get_field(r, MAC_PCS_XXV_GTY_LOOP_2_GT_LOOP); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_2); + rf->mp_reg_gty_ctl_rx = r; + rf->mp_fld_gty_ctl_rx_polarity = + get_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_POLARITY); + rf->mp_fld_gty_ctl_rx_lpm_en = + get_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_LPM_EN); + rf->mp_fld_gty_ctl_rx_equa_rst = + get_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_EQUA_RST); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_2); + rf->mp_fld_gty_ctl_tx_polarity = + get_field(r, MAC_PCS_XXV_GTY_CTL_TX_2_POLARITY); + rf->mp_fld_gty_ctl_tx_inhibit = + get_field(r, MAC_PCS_XXV_GTY_CTL_TX_2_INHIBIT); + + if (!m_mac8x10_g) { + r = get_register(module, MAC_PCS_XXV_LINK_SPEED_2); + rf->mp_reg_link_speed = + get_register(module, MAC_PCS_XXV_LINK_SPEED_2); + + rf->mp_fld_link_speed10_g = + get_field(r, MAC_PCS_XXV_LINK_SPEED_2_SPEED); + if (!rf->mp_fld_link_speed10_g) { + rf->mp_fld_link_speed10_g = + get_field(r, MAC_PCS_XXV_LINK_SPEED_2_10G); + } + + rf->mp_fld_link_speed_toggle = + get_field(r, MAC_PCS_XXV_LINK_SPEED_2_TOGGLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_2); + rf->mp_reg_rs_fec_conf = r; + rf->mp_fld_rs_fec_conf_rs_fec_enable = + get_field(r, MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_ENABLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_2); + rf->mp_reg_rs_fec_ccw = r; + rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_2_RS_FEC_CCW_CNT); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_2); + rf->mp_reg_rs_fec_ucw = r; + rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_2_RS_FEC_UCW_CNT); + } + + /* Initialize regs/fields for sub-module/channel 3 */ + rf = &p->regs[3]; + + r = get_register(module, MAC_PCS_XXV_GTY_LOOP_3); + rf->mp_reg_gty_loop = r; + rf->mp_fld_gty_loop_gt_loop = + get_field(r, MAC_PCS_XXV_GTY_LOOP_3_GT_LOOP); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_3); + rf->mp_reg_gty_ctl_rx = r; + rf->mp_fld_gty_ctl_rx_polarity = + get_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_POLARITY); + rf->mp_fld_gty_ctl_rx_lpm_en = + get_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_LPM_EN); + rf->mp_fld_gty_ctl_rx_equa_rst = + get_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_EQUA_RST); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_3); + rf->mp_fld_gty_ctl_tx_polarity = + get_field(r, MAC_PCS_XXV_GTY_CTL_TX_3_POLARITY); + rf->mp_fld_gty_ctl_tx_inhibit = + get_field(r, MAC_PCS_XXV_GTY_CTL_TX_3_INHIBIT); + + if (!m_mac8x10_g) { + r = get_register(module, MAC_PCS_XXV_LINK_SPEED_3); + rf->mp_reg_link_speed = + get_register(module, MAC_PCS_XXV_LINK_SPEED_3); + + rf->mp_fld_link_speed10_g = + get_field(r, MAC_PCS_XXV_LINK_SPEED_3_SPEED); + if (!rf->mp_fld_link_speed10_g) { + rf->mp_fld_link_speed10_g = + get_field(r, MAC_PCS_XXV_LINK_SPEED_3_10G); + } + rf->mp_fld_link_speed_toggle = + get_field(r, MAC_PCS_XXV_LINK_SPEED_3_TOGGLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_3); + rf->mp_reg_rs_fec_conf = r; + rf->mp_fld_rs_fec_conf_rs_fec_enable = + get_field(r, MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_ENABLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_3); + rf->mp_reg_rs_fec_ccw = r; + rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_3_RS_FEC_CCW_CNT); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_3); + rf->mp_reg_rs_fec_ucw = r; + rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_3_RS_FEC_UCW_CNT); + } + } + + /* + * Registers MAC_PCS_XXV_DEBOUNCE_CTRL_0 -- MAC_PCS_XXV_DEBOUNCE_CTRL_3 + * and MAC_PCS_XXV_TIMESTAMP_COMP_0 -- MAC_PCS_XXV_TIMESTAMP_COMP_3 + * and MAC_PCS_XXV_GTY_PRE_CURSOR_0 -- MAC_PCS_XXV_GTY_PRE_CURSOR_3 + * and MAC_PCS_XXV_GTY_DIFF_CTL_0 -- MAC_PCS_XXV_GTY_DIFF_CTL_0 + * and MAC_PCS_XXV_GTY_POST_CURSOR_0 -- MAC_PCS_XXV_GTY_POST_CURSOR_3 + */ + if (n_channels < 4) { + /* Initialize regs/fields for sub-module/channel 0 */ + rf = &p->regs[0]; + + r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_0); + + rf->mp_reg_debounce_ctrl = r; + rf->mp_field_debounce_ctrl_nt_port_ctrl = + get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_PORT_CTRL); + + r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_0); + rf->mp_reg_timestamp_comp = r; + rf->mp_field_timestamp_comp_rx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_0_RX_DLY); + rf->mp_field_timestamp_comp_tx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_0_TX_DLY); + + /* GTY_PRE_CURSOR */ + r = get_register(p->mp_mod_mac_pcs_xxv, + MAC_PCS_XXV_GTY_PRE_CURSOR_0); + rf->mp_reg_gty_pre_cursor = r; + rf->mp_field_gty_pre_cursor_tx_pre_csr = + get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_0_TX_PRE_CSR); + + /* GTY_DIFF_CTL */ + r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_0); + rf->mp_reg_gty_diff_ctl = r; + rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl = + get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_0_TX_DIFF_CTL); + + /* GTY_POST_CURSOR */ + r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_0); + rf->mp_reg_gty_post_cursor = r; + rf->mp_field_gty_post_cursor_tx_post_csr = + get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_0_TX_POST_CSR); + } + + if (n_channels >= 2) { + /* Initialize regs/fields for sub-module/channel 1 */ + rf = &p->regs[1]; + + r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_1); + + rf->mp_reg_debounce_ctrl = r; + rf->mp_field_debounce_ctrl_nt_port_ctrl = + get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_PORT_CTRL); + + r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_1); + rf->mp_reg_timestamp_comp = r; + rf->mp_field_timestamp_comp_rx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_1_RX_DLY); + rf->mp_field_timestamp_comp_tx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_1_TX_DLY); + + /* GTY_PRE_CURSOR */ + r = get_register(p->mp_mod_mac_pcs_xxv, + MAC_PCS_XXV_GTY_PRE_CURSOR_1); + rf->mp_reg_gty_pre_cursor = r; + rf->mp_field_gty_pre_cursor_tx_pre_csr = + get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_1_TX_PRE_CSR); + + /* GTY_DIFF_CTL */ + r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_1); + rf->mp_reg_gty_diff_ctl = r; + rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl = + get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_1_TX_DIFF_CTL); + + /* GTY_POST_CURSOR */ + r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_1); + rf->mp_reg_gty_post_cursor = r; + rf->mp_field_gty_post_cursor_tx_post_csr = + get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_1_TX_POST_CSR); + } + + if (n_channels == 4) { + /* Initialize regs/fields for sub-module/channel 2 */ + rf = &p->regs[2]; + + r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_2); + + rf->mp_reg_debounce_ctrl = r; + rf->mp_field_debounce_ctrl_nt_port_ctrl = + get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_PORT_CTRL); + + r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_2); + rf->mp_reg_timestamp_comp = r; + rf->mp_field_timestamp_comp_rx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_2_RX_DLY); + rf->mp_field_timestamp_comp_tx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_2_TX_DLY); + + /* GTY_PRE_CURSOR */ + r = get_register(p->mp_mod_mac_pcs_xxv, + MAC_PCS_XXV_GTY_PRE_CURSOR_2); + rf->mp_reg_gty_pre_cursor = r; + rf->mp_field_gty_pre_cursor_tx_pre_csr = + get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_2_TX_PRE_CSR); + + /* GTY_DIFF_CTL */ + r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_2); + rf->mp_reg_gty_diff_ctl = r; + rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl = + get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_2_TX_DIFF_CTL); + + /* GTY_POST_CURSOR */ + r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_2); + rf->mp_reg_gty_post_cursor = r; + rf->mp_field_gty_post_cursor_tx_post_csr = + get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_2_TX_POST_CSR); + + /* Initialize regs/fields for sub-module/channel 3 */ + rf = &p->regs[3]; + + r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_3); + + rf->mp_reg_debounce_ctrl = r; + rf->mp_field_debounce_ctrl_nt_port_ctrl = + get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_PORT_CTRL); + + r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_3); + rf->mp_reg_timestamp_comp = r; + rf->mp_field_timestamp_comp_rx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_3_RX_DLY); + rf->mp_field_timestamp_comp_tx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_3_TX_DLY); + + /* GTY_PRE_CURSOR */ + r = get_register(p->mp_mod_mac_pcs_xxv, + MAC_PCS_XXV_GTY_PRE_CURSOR_3); + rf->mp_reg_gty_pre_cursor = r; + rf->mp_field_gty_pre_cursor_tx_pre_csr = + get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_3_TX_PRE_CSR); + + /* GTY_DIFF_CTL */ + r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_3); + rf->mp_reg_gty_diff_ctl = r; + rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl = + get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_3_TX_DIFF_CTL); + + /* GTY_POST_CURSOR */ + r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_3); + rf->mp_reg_gty_post_cursor = r; + rf->mp_field_gty_post_cursor_tx_post_csr = + get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_3_TX_POST_CSR); + } + return 0; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h new file mode 100644 index 0000000000..5a38494f7e --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h @@ -0,0 +1,291 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NTHW_MAC_PCS_XXV_H_ +#define NTHW_MAC_PCS_XXV_H_ + +#include +#include +#include "nthw_fpga_model.h" + +enum nthw_mac_pcs_xxv_led_mode_e { + NTHW_MAC_PCS_XXV_LED_AUTO = 0x00, + NTHW_MAC_PCS_XXV_LED_ON = 0x01, + NTHW_MAC_PCS_XXV_LED_OFF = 0x02, + NTHW_MAC_PCS_XXV_LED_PORTID = 0x03, +}; + +enum nthw_mac_pcs_xxv_dac_mode_e { + NTHW_MAC_PCS_XXV_DAC_OFF = 0x00, + NTHW_MAC_PCS_XXV_DAC_CA_25G_N = 0x01, + NTHW_MAC_PCS_XXV_DAC_CA_25G_S = 0x02, + NTHW_MAC_PCS_XXV_DAC_CA_25G_L = 0x03, +}; + +struct nthw_mac_pcs_xxv { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_mac_pcs_xxv; + int mn_instance; + + uint8_t m_port_no; + +#define NTHW_MAC_PCS_XXV_NUM_ELEMS 4 + struct nthw_mac_pcs_xxv__registers_fields { + /* CORE_CONF */ + nt_register_t *mp_reg_core_conf; + nt_field_t *mp_fld_core_conf_rx_enable; + nt_field_t *mp_fld_core_conf_rx_force_resync; + nt_field_t *mp_fld_core_conf_tx_enable; + nt_field_t *mp_fld_core_conf_tx_ins_fcs; + nt_field_t *mp_fld_core_conf_tx_ign_fcs; + nt_field_t *mp_fld_core_conf_tx_send_lfi; + nt_field_t *mp_fld_core_conf_tx_send_rfi; + nt_field_t *mp_fld_core_conf_tx_send_idle; + nt_field_t *mp_fld_core_conf_inline_mode; + nt_field_t *mp_fld_core_conf_line_loopback; + nt_field_t *mp_fld_core_conf_ts_at_eop; + + /* ANEG_CONFIG */ + nt_register_t *mp_reg_aneg_config; + nt_field_t *mp_fld_aneg_config_enable; + nt_field_t *mp_fld_aneg_config_bypass; + nt_field_t *mp_fld_aneg_config_restart; + nt_field_t *mp_fld_aneg_config_pseudo; + nt_field_t *mp_fld_aneg_config_nonce_seed; + nt_field_t *mp_fld_aneg_config_remote_fault; + nt_field_t *mp_fld_aneg_config_pause; + nt_field_t *mp_fld_aneg_config_asmdir; + nt_field_t *mp_fld_aneg_config_fec74_request10_g; + nt_field_t *mp_fld_aneg_config_hide_fec74; + nt_field_t *mp_fld_aneg_config_fec74_request; + nt_field_t *mp_fld_aneg_config_fec91_request; + nt_field_t *mp_fld_aneg_config_fec91_ability; + nt_field_t *mp_fld_aneg_config_rs_fec_request; + nt_field_t *mp_fld_aneg_config_sw_fec_overwrite; + nt_field_t *mp_fld_aneg_config_sw_speed_overwrite; + + /* ANEG_ABILITY */ + nt_register_t *mp_reg_aneg_ability; + nt_field_t *mp_fld_aneg_ability25_g_base_cr; + nt_field_t *mp_fld_aneg_ability25_g_base_crs; + nt_field_t *mp_fld_aneg_ability25_g_base_cr1; + + /* LT_CONF */ + nt_register_t *mp_reg_lt_conf; + nt_field_t *mp_fld_lt_conf_enable; + nt_field_t *mp_fld_lt_conf_restart; + nt_field_t *mp_fld_lt_conf_seed; + + /* SUB_RST */ + nt_register_t *mp_reg_sub_rst; + nt_field_t *mp_fld_sub_rst_rx_mac_pcs; + nt_field_t *mp_fld_sub_rst_tx_mac_pcs; + nt_field_t *mp_fld_sub_rst_rx_gt_data; + nt_field_t *mp_fld_sub_rst_tx_gt_data; + nt_field_t *mp_fld_sub_rst_rx_buf; + nt_field_t *mp_fld_sub_rst_rx_pma; + nt_field_t *mp_fld_sub_rst_tx_pma; + nt_field_t *mp_fld_sub_rst_rx_pcs; + nt_field_t *mp_fld_sub_rst_tx_pcs; + nt_field_t *mp_fld_sub_rst_an_lt; + nt_field_t *mp_fld_sub_rst_speed_ctrl; + + /* SUB_RST_STATUS */ + nt_register_t *mp_reg_sub_rst_status; + nt_field_t *mp_fld_sub_rst_status_user_rx_rst; + nt_field_t *mp_fld_sub_rst_status_user_tx_rst; + nt_field_t *mp_fld_sub_rst_status_qpll_lock; + + /* LINK_SUMMARY */ + nt_register_t *mp_reg_link_summary; + nt_field_t *mp_fld_link_summary_nt_phy_link_state; + nt_field_t *mp_fld_link_summary_ll_nt_phy_link_state; + nt_field_t *mp_fld_link_summary_abs; + nt_field_t *mp_fld_link_summary_lh_abs; + nt_field_t *mp_fld_link_summary_link_down_cnt; + /* Begin 2 x 10/25 Gbps only fields: */ + nt_field_t *mp_fld_link_summary_ll_rx_fec74_lock; + nt_field_t *mp_fld_link_summary_lh_rx_rsfec_hi_ser; + nt_field_t *mp_fld_link_summary_ll_rx_rsfec_lane_alignment; + nt_field_t *mp_fld_link_summary_ll_tx_rsfec_lane_alignment; + nt_field_t *mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code; + /* End 2 x 10/25 Gbps only fields. */ + nt_field_t *mp_fld_link_summary_ll_rx_block_lock; + nt_field_t *mp_fld_link_summary_lh_rx_high_bit_error_rate; + nt_field_t *mp_fld_link_summary_lh_internal_local_fault; + nt_field_t *mp_fld_link_summary_lh_received_local_fault; + nt_field_t *mp_fld_link_summary_lh_local_fault; + nt_field_t *mp_fld_link_summary_lh_remote_fault; + nt_field_t *mp_fld_link_summary_lh_tx_local_fault; + nt_field_t *mp_fld_link_summary_nim_interr; + + /* GTY_LOOP */ + nt_register_t *mp_reg_gty_loop; + nt_field_t *mp_fld_gty_loop_gt_loop; + + /* GTY_CTL_RX */ + nt_register_t *mp_reg_gty_ctl_rx; + nt_field_t *mp_fld_gty_ctl_rx_polarity; + nt_field_t *mp_fld_gty_ctl_rx_lpm_en; + nt_field_t *mp_fld_gty_ctl_rx_equa_rst; + + /* GTY_CTL_TX */ + nt_register_t *mp_reg_gty_ctl_tx; + nt_field_t *mp_fld_gty_ctl_tx_polarity; + nt_field_t *mp_fld_gty_ctl_tx_inhibit; + + /* LINK_SPEED */ + nt_register_t *mp_reg_link_speed; + nt_field_t *mp_fld_link_speed10_g; + nt_field_t *mp_fld_link_speed_toggle; + + /* RS_FEC_CONF */ + nt_register_t *mp_reg_rs_fec_conf; + nt_field_t *mp_fld_rs_fec_conf_rs_fec_enable; + + /* DEBOUNCE_CTRL */ + nt_register_t *mp_reg_debounce_ctrl; + nt_field_t *mp_field_debounce_ctrl_nt_port_ctrl; + + /* FEC_CCW_CNT */ + nt_register_t *mp_reg_rs_fec_ccw; + nt_field_t *mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt; + + /* FEC_UCW_CNT */ + nt_register_t *mp_reg_rs_fec_ucw; + nt_field_t *mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt; + + /* TIMESTAMP_COMP */ + nt_register_t *mp_reg_timestamp_comp; + nt_field_t *mp_field_timestamp_comp_rx_dly; + nt_field_t *mp_field_timestamp_comp_tx_dly; + + /* GTY_PRE_CURSOR */ + nt_register_t *mp_reg_gty_pre_cursor; + nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr; + + /* GTY_DIFF_CTL */ + nt_register_t *mp_reg_gty_diff_ctl; + nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl; + + /* GTY_POST_CURSOR */ + nt_register_t *mp_reg_gty_post_cursor; + nt_field_t *mp_field_gty_post_cursor_tx_post_csr; + } regs[NTHW_MAC_PCS_XXV_NUM_ELEMS]; +}; + +typedef struct nthw_mac_pcs_xxv nthw_mac_pcs_xxv_t; +typedef struct nthw_mac_pcs_xxv nthw_mac_pcs_xxv; + +nthw_mac_pcs_xxv_t *nthw_mac_pcs_xxv_new(void); +void nthw_mac_pcs_xxv_delete(nthw_mac_pcs_xxv_t *p); +int nthw_mac_pcs_xxv_init(nthw_mac_pcs_xxv_t *p, nt_fpga_t *p_fpga, int n_instance, + int n_channels); + +void nthw_mac_pcs_xxv_get_link_summary(nthw_mac_pcs_xxv_t *p, + uint32_t *p_abs, uint32_t *p_nt_phy_link_state, + uint32_t *p_lh_abs, uint32_t *p_ll_nt_phy_link_state, uint32_t *p_link_down_cnt, + uint32_t *p_nim_interr, uint32_t *p_lh_local_fault, uint32_t *p_lh_remote_fault, + uint32_t *p_lh_internal_local_fault, uint32_t *p_lh_received_local_fault, + uint8_t index); + +uint8_t nthw_mac_pcs_xxv_get_port_no(const nthw_mac_pcs_xxv_t *p, uint8_t index); + +void nthw_mac_pcs_xxv_set_port_no(nthw_mac_pcs_xxv_t *p, uint8_t port_no); + +void nthw_mac_pcs_xxv_set_tx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index); +void nthw_mac_pcs_xxv_set_rx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index); +void nthw_mac_pcs_xxv_rx_force_resync(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); + +void nthw_mac_pcs_xxv_reset_rx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); +void nthw_mac_pcs_xxv_reset_tx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); + +void nthw_mac_pcs_xxv_reset_an_lt(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index); +void nthw_mac_pcs_xxv_reset_speed_ctrl(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); + +void nthw_mac_pcs_xxv_set_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index); +void nthw_mac_pcs_xxv_set_tx_send_lfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index); +void nthw_mac_pcs_xxv_set_tx_send_lfi_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable_lfi, + bool enable_rfi, uint8_t index); + +bool nthw_mac_pcs_xxv_is_dfe_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index); +void nthw_mac_pcs_xxv_set_dfe(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index); + +void nthw_mac_pcs_xxv_set_rx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); +void nthw_mac_pcs_xxv_set_tx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); + +void nthw_mac_pcs_xxv_set_tx_gty_inhibit(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); + +void nthw_mac_pcs_xxv_set_host_loopback(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); +void nthw_mac_pcs_xxv_set_line_loopback(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); + +bool nthw_mac_pcs_xxv_is_user_rx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index); +bool nthw_mac_pcs_xxv_is_user_tx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index); + +bool nthw_mac_pcs_xxv_is_qpll_lock(nthw_mac_pcs_xxv_t *p, uint8_t index); +bool nthw_mac_pcs_xxv_is_sub_rst_ready(nthw_mac_pcs_xxv_t *p, uint8_t index); +bool nthw_mac_pcs_xxv_is_aneg_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index); + +void nthw_mac_pcs_xxv_set_tx_send_idle(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); +void nthw_mac_pcs_xxv_set_tx_ins_fcs(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index); + +bool nthw_mac_pcs_xxv_get_link_speed10_g(nthw_mac_pcs_xxv_t *p, uint8_t index); +void nthw_mac_pcs_xxv_set_link_speed10_g(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); +void nthw_mac_pcs_xxv_set_link_speed_toggle(nthw_mac_pcs_xxv_t *p, uint8_t index); + +void nthw_mac_pcs_xxv_set_rs_fec_conf_rs_fec_enable(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); + +void nthw_mac_pcs_xxv_set_led_mode(nthw_mac_pcs_xxv_t *p, uint8_t mode, uint8_t index); + +void nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); +void nthw_mac_pcs_xxv_set_tx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); + +void nthw_mac_pcs_xxv_reset_fec_counters(nthw_mac_pcs_xxv_t *p, uint8_t index); + +void nthw_mac_pcs_xxv_set_gty_diff(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index); +void nthw_mac_pcs_xxv_set_gty_pre(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index); +void nthw_mac_pcs_xxv_set_gty_post(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index); + +void nthw_mac_pcs_xxv_set_ts_at_eop(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index); + +void nthw_mac_pcs_xxv_set_aneg_config_enable(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); +void nthw_mac_pcs_xxv_set_aneg_config_bypass(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); +void nthw_mac_pcs_xxv_set_lt_conf_enable(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); + +void nthw_mac_pcs_xxv_set_dac_mode(nthw_mac_pcs_xxv_t *p, uint8_t dac_mode, + uint8_t index); + +void nthw_mac_pcs_xxv_set_timestamp_comp_rx(nthw_mac_pcs_xxv_t *p, uint16_t rx_dly, + uint8_t index); +void nthw_mac_pcs_xxv_set_timestamp_comp_tx(nthw_mac_pcs_xxv_t *p, uint16_t tx_dly, + uint8_t index); + +void nthw_mac_pcs_xxv_set_aneg_config_fec91_request(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); +void nthw_mac_pcs_xxv_set_aneg_config_rs_fec_request(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); +void nthw_mac_pcs_xxv_set_aneg_config_fec74_request(nthw_mac_pcs_xxv_t *p, bool enable, + uint8_t index); + +bool nthw_mac_pcs_xxv_get_ll_rx_fec74_lock(nthw_mac_pcs_xxv_t *p, uint8_t index); +bool nthw_mac_pcs_xxv_get_ll_rx_rsfec_lane_alignment(nthw_mac_pcs_xxv_t *p, uint8_t index); + +#endif /* NTHW_MAC_PCS_XXV_H_ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c new file mode 100644 index 0000000000..92089d2fa3 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_pci_rd_tg.h" + +nthw_pci_rd_tg_t *nthw_pci_rd_tg_new(void) +{ + nthw_pci_rd_tg_t *p = malloc(sizeof(nthw_pci_rd_tg_t)); + + if (p) + memset(p, 0, sizeof(nthw_pci_rd_tg_t)); + return p; +} + +void nthw_pci_rd_tg_delete(nthw_pci_rd_tg_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_pci_rd_tg_t)); + free(p); + } +} + +int nthw_pci_rd_tg_init(nthw_pci_rd_tg_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + nt_module_t *mod = fpga_query_module(p_fpga, MOD_PCI_RD_TG, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: PCI_RD_TG %d: no such instance\n", + p_fpga->p_fpga_info->mp_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_pci_rd_tg = mod; + + p->mn_param_pci_ta_tg_present = + fpga_get_product_param(p_fpga, NT_PCI_TA_TG_PRESENT, 1); + + p->mp_reg_pci_rd_tg_rd_data0 = + module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDDATA0); + p->mp_fld_pci_rd_tg_phys_addr_low = + register_get_field(p->mp_reg_pci_rd_tg_rd_data0, + PCI_RD_TG_TG_RDDATA0_PHYS_ADDR_LOW); + + p->mp_reg_pci_rd_tg_rd_data1 = + module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDDATA1); + p->mp_fld_pci_rd_tg_phys_addr_high = + register_get_field(p->mp_reg_pci_rd_tg_rd_data1, + PCI_RD_TG_TG_RDDATA1_PHYS_ADDR_HIGH); + + p->mp_reg_pci_rd_tg_rd_data2 = + module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDDATA2); + p->mp_fld_pci_rd_tg_req_size = + register_get_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_REQ_SIZE); + p->mp_fld_pci_rd_tg_wait = + register_get_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_WAIT); + p->mp_fld_pci_rd_tg_wrap = + register_get_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_WRAP); + /* optional VF host id */ + p->mp_fld_pci_rd_tg_req_hid = + register_query_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_REQ_HID); + + p->mp_reg_pci_rd_tg_rd_addr = + module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDADDR); + p->mp_fld_pci_rd_tg_ram_addr = + register_get_field(p->mp_reg_pci_rd_tg_rd_addr, PCI_RD_TG_TG_RDADDR_RAM_ADDR); + + p->mp_reg_pci_rd_tg_rd_run = + module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RD_RUN); + p->mp_fld_pci_rd_tg_run_iteration = + register_get_field(p->mp_reg_pci_rd_tg_rd_run, PCI_RD_TG_TG_RD_RUN_RD_ITERATION); + + p->mp_reg_pci_rd_tg_rd_ctrl = + module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_CTRL); + p->mp_fld_pci_rd_tg_ctrl_rdy = + register_get_field(p->mp_reg_pci_rd_tg_rd_ctrl, PCI_RD_TG_TG_CTRL_TG_RD_RDY); + + return 0; +} + +void nthw_pci_rd_tg_set_phys_addr(nthw_pci_rd_tg_t *p, uint64_t n_phys_addr) +{ + field_set_val_flush32(p->mp_fld_pci_rd_tg_phys_addr_low, + (uint32_t)(n_phys_addr & ((1UL << 32) - 1))); + field_set_val_flush32(p->mp_fld_pci_rd_tg_phys_addr_high, + (uint32_t)((n_phys_addr >> 32) & ((1UL << 32) - 1))); +} + +void nthw_pci_rd_tg_set_ram_addr(nthw_pci_rd_tg_t *p, int n_ram_addr) +{ + field_set_val_flush32(p->mp_fld_pci_rd_tg_ram_addr, n_ram_addr); +} + +void nthw_pci_rd_tg_set_ram_data(nthw_pci_rd_tg_t *p, uint32_t req_size, bool wait, + bool wrap) +{ + field_set_val32(p->mp_fld_pci_rd_tg_req_size, req_size); + field_set_val32(p->mp_fld_pci_rd_tg_wait, wait); + field_set_val32(p->mp_fld_pci_rd_tg_wrap, wrap); + field_flush_register(p->mp_fld_pci_rd_tg_wrap); +} + +void nthw_pci_rd_tg_set_run(nthw_pci_rd_tg_t *p, int n_iterations) +{ + field_set_val_flush32(p->mp_fld_pci_rd_tg_run_iteration, n_iterations); +} + +uint32_t nthw_pci_rd_tg_get_ctrl_rdy(nthw_pci_rd_tg_t *p) +{ + return field_get_updated(p->mp_fld_pci_rd_tg_ctrl_rdy); +} diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h new file mode 100644 index 0000000000..b1c912f0f3 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_PCI_RD_TG_H__ +#define __NTHW_PCI_RD_TG_H__ + +struct nthw_pci_rd_tg { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_pci_rd_tg; + int mn_instance; + + int mn_param_pci_ta_tg_present; + + nt_register_t *mp_reg_pci_rd_tg_rd_data0; + nt_field_t *mp_fld_pci_rd_tg_phys_addr_low; + + nt_register_t *mp_reg_pci_rd_tg_rd_data1; + nt_field_t *mp_fld_pci_rd_tg_phys_addr_high; + + nt_register_t *mp_reg_pci_rd_tg_rd_data2; + nt_field_t *mp_fld_pci_rd_tg_req_size; + nt_field_t *mp_fld_pci_rd_tg_req_hid; + nt_field_t *mp_fld_pci_rd_tg_wait; + nt_field_t *mp_fld_pci_rd_tg_wrap; + + nt_register_t *mp_reg_pci_rd_tg_rd_addr; + nt_field_t *mp_fld_pci_rd_tg_ram_addr; + + nt_register_t *mp_reg_pci_rd_tg_rd_run; + nt_field_t *mp_fld_pci_rd_tg_run_iteration; + + nt_register_t *mp_reg_pci_rd_tg_rd_ctrl; + nt_field_t *mp_fld_pci_rd_tg_ctrl_rdy; +}; + +typedef struct nthw_pci_rd_tg nthw_pci_rd_tg_t; +typedef struct nthw_pci_rd_tg nthw_pci_rd_tg; + +nthw_pci_rd_tg_t *nthw_pci_rd_tg_new(void); +void nthw_pci_rd_tg_delete(nthw_pci_rd_tg_t *p); +int nthw_pci_rd_tg_init(nthw_pci_rd_tg_t *p, nt_fpga_t *p_fpga, int n_instance); + +void nthw_pci_rd_tg_set_phys_addr(nthw_pci_rd_tg_t *p, uint64_t n_phys_addr); +void nthw_pci_rd_tg_set_ram_addr(nthw_pci_rd_tg_t *p, int n_ram_addr); +void nthw_pci_rd_tg_set_ram_data(nthw_pci_rd_tg_t *p, uint32_t req_size, bool wait, + bool wrap); +void nthw_pci_rd_tg_set_run(nthw_pci_rd_tg_t *p, int n_iterations); +uint32_t nthw_pci_rd_tg_get_ctrl_rdy(nthw_pci_rd_tg_t *p); + +#endif /* __NTHW_PCI_RD_TG_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_ta.c b/drivers/net/ntnic/nthw/core/nthw_pci_ta.c new file mode 100644 index 0000000000..17e30a670d --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_pci_ta.c @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_pci_ta.h" + +nthw_pci_ta_t *nthw_pci_ta_new(void) +{ + nthw_pci_ta_t *p = malloc(sizeof(nthw_pci_ta_t)); + + if (p) + memset(p, 0, sizeof(nthw_pci_ta_t)); + return p; +} + +void nthw_pci_ta_delete(nthw_pci_ta_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_pci_ta_t)); + free(p); + } +} + +int nthw_pci_ta_init(nthw_pci_ta_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + nt_module_t *mod = fpga_query_module(p_fpga, MOD_PCI_TA, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: PCI_TA %d: no such instance\n", + p_fpga->p_fpga_info->mp_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_pci_ta = mod; + + p->mn_param_pci_ta_tg_present = + fpga_get_product_param(p_fpga, NT_PCI_TA_TG_PRESENT, 1); + + p->mp_reg_pci_ta_ctrl = module_get_register(p->mp_mod_pci_ta, PCI_TA_CONTROL); + p->mp_fld_pci_ta_ctrl_enable = + register_get_field(p->mp_reg_pci_ta_ctrl, PCI_TA_CONTROL_ENABLE); + + p->mp_reg_pci_ta_packet_good = + module_get_register(p->mp_mod_pci_ta, PCI_TA_PACKET_GOOD); + p->mp_fld_pci_ta_packet_good_amount = + register_get_field(p->mp_reg_pci_ta_packet_good, PCI_TA_PACKET_GOOD_AMOUNT); + + p->mp_reg_pci_ta_packet_bad = + module_get_register(p->mp_mod_pci_ta, PCI_TA_PACKET_BAD); + p->mp_fld_pci_ta_packet_bad_amount = + register_get_field(p->mp_reg_pci_ta_packet_bad, PCI_TA_PACKET_BAD_AMOUNT); + + p->mp_reg_pci_ta_length_error = + module_get_register(p->mp_mod_pci_ta, PCI_TA_LENGTH_ERROR); + p->mp_fld_pci_ta_length_error_amount = + register_get_field(p->mp_reg_pci_ta_length_error, PCI_TA_LENGTH_ERROR_AMOUNT); + + p->mp_reg_pci_ta_payload_error = + module_get_register(p->mp_mod_pci_ta, PCI_TA_PAYLOAD_ERROR); + p->mp_fld_pci_ta_payload_error_amount = + register_get_field(p->mp_reg_pci_ta_payload_error, PCI_TA_PAYLOAD_ERROR_AMOUNT); + + return 0; +} + +void nthw_pci_ta_set_control_enable(nthw_pci_ta_t *p, uint32_t val) +{ + field_set_val_flush32(p->mp_fld_pci_ta_ctrl_enable, val); +} + +void nthw_pci_ta_get_packet_good(nthw_pci_ta_t *p, uint32_t *val) +{ + *val = field_get_updated(p->mp_fld_pci_ta_packet_good_amount); +} + +void nthw_pci_ta_get_packet_bad(nthw_pci_ta_t *p, uint32_t *val) +{ + *val = field_get_updated(p->mp_fld_pci_ta_packet_bad_amount); +} + +void nthw_pci_ta_get_length_error(nthw_pci_ta_t *p, uint32_t *val) +{ + *val = field_get_updated(p->mp_fld_pci_ta_length_error_amount); +} + +void nthw_pci_ta_get_payload_error(nthw_pci_ta_t *p, uint32_t *val) +{ + *val = field_get_updated(p->mp_fld_pci_ta_payload_error_amount); +} diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_ta.h b/drivers/net/ntnic/nthw/core/nthw_pci_ta.h new file mode 100644 index 0000000000..7968cad9fa --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_pci_ta.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_PCI_TA_H__ +#define __NTHW_PCI_TA_H__ + +struct nthw_pci_ta { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_pci_ta; + int mn_instance; + + int mn_param_pci_ta_tg_present; + + nt_register_t *mp_reg_pci_ta_ctrl; + nt_field_t *mp_fld_pci_ta_ctrl_enable; + nt_register_t *mp_reg_pci_ta_packet_good; + nt_field_t *mp_fld_pci_ta_packet_good_amount; + nt_register_t *mp_reg_pci_ta_packet_bad; + nt_field_t *mp_fld_pci_ta_packet_bad_amount; + nt_register_t *mp_reg_pci_ta_length_error; + nt_field_t *mp_fld_pci_ta_length_error_amount; + nt_register_t *mp_reg_pci_ta_payload_error; + nt_field_t *mp_fld_pci_ta_payload_error_amount; +}; + +typedef struct nthw_pci_ta nthw_pci_ta_t; +typedef struct nthw_pci_ta nthw_pci_ta; + +nthw_pci_ta_t *nthw_pci_ta_new(void); +void nthw_pci_ta_delete(nthw_pci_ta_t *p); +int nthw_pci_ta_init(nthw_pci_ta_t *p, nt_fpga_t *p_fpga, int n_instance); + +void nthw_pci_ta_set_control_enable(nthw_pci_ta_t *p, uint32_t val); +void nthw_pci_ta_get_packet_good(nthw_pci_ta_t *p, uint32_t *val); +void nthw_pci_ta_get_packet_bad(nthw_pci_ta_t *p, uint32_t *val); +void nthw_pci_ta_get_length_error(nthw_pci_ta_t *p, uint32_t *val); +void nthw_pci_ta_get_payload_error(nthw_pci_ta_t *p, uint32_t *val); + +#endif /* __NTHW_PCI_TA_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c new file mode 100644 index 0000000000..f830a586b2 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_pci_wr_tg.h" + +nthw_pci_wr_tg_t *nthw_pci_wr_tg_new(void) +{ + nthw_pci_wr_tg_t *p = malloc(sizeof(nthw_pci_wr_tg_t)); + + if (p) + memset(p, 0, sizeof(nthw_pci_wr_tg_t)); + return p; +} + +void nthw_pci_wr_tg_delete(nthw_pci_wr_tg_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_pci_wr_tg_t)); + free(p); + } +} + +int nthw_pci_wr_tg_init(nthw_pci_wr_tg_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + nt_module_t *mod = fpga_query_module(p_fpga, MOD_PCI_WR_TG, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: PCI_WR_TG %d: no such instance\n", + p_fpga->p_fpga_info->mp_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_pci_wr_tg = mod; + + p->mn_param_pci_ta_tg_present = + fpga_get_product_param(p_fpga, NT_PCI_TA_TG_PRESENT, 1); + + p->mp_reg_pci_wr_tg_data0 = + module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRDATA0); + p->mp_fld_pci_wr_tg_phys_addr_low = + register_get_field(p->mp_reg_pci_wr_tg_data0, PCI_WR_TG_TG_WRDATA0_PHYS_ADDR_LOW); + + p->mp_reg_pci_wr_tg_data1 = + module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRDATA1); + p->mp_fld_pci_wr_tg_phys_addr_high = + register_get_field(p->mp_reg_pci_wr_tg_data1, PCI_WR_TG_TG_WRDATA1_PHYS_ADDR_HIGH); + + p->mp_reg_pci_wr_tg_data2 = + module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRDATA2); + p->mp_fld_pci_wr_tg_req_size = + register_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_REQ_SIZE); + p->mp_fld_pci_wr_tg_inc_mode = + register_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_INC_MODE); + p->mp_fld_pci_wr_tg_wait = + register_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_WAIT); + p->mp_fld_pci_wr_tg_wrap = + register_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_WRAP); + /* optional VF host id */ + p->mp_fld_pci_wr_tg_req_hid = + register_query_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_REQ_HID); + + p->mp_reg_pci_wr_tg_addr = + module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRADDR); + p->mp_fld_pci_wr_tg_ram_addr = + register_get_field(p->mp_reg_pci_wr_tg_addr, PCI_WR_TG_TG_WRADDR_RAM_ADDR); + + p->mp_reg_pci_wr_tg_run = + module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WR_RUN); + p->mp_fld_pci_wr_tg_run_iteration = + register_get_field(p->mp_reg_pci_wr_tg_run, PCI_WR_TG_TG_WR_RUN_WR_ITERATION); + + p->mp_reg_pci_wr_tg_ctrl = + module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_CTRL); + p->mp_fld_pci_wr_tg_ctrl_rdy = + register_get_field(p->mp_reg_pci_wr_tg_ctrl, PCI_WR_TG_TG_CTRL_TG_WR_RDY); + + p->mp_reg_pci_wr_tg_seq = + module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_SEQ); + p->mp_fld_pci_wr_tg_seq_sequence = + register_get_field(p->mp_reg_pci_wr_tg_seq, PCI_WR_TG_TG_SEQ_SEQUENCE); + + return 0; +} + +void nthw_pci_wr_tg_set_phys_addr(nthw_pci_wr_tg_t *p, uint64_t n_phys_addr) +{ + field_set_val_flush32(p->mp_fld_pci_wr_tg_phys_addr_low, + (uint32_t)(n_phys_addr & ((1UL << 32) - 1))); + field_set_val_flush32(p->mp_fld_pci_wr_tg_phys_addr_high, + (uint32_t)((n_phys_addr >> 32) & ((1UL << 32) - 1))); +} + +void nthw_pci_wr_tg_set_ram_addr(nthw_pci_wr_tg_t *p, int n_ram_addr) +{ + field_set_val_flush32(p->mp_fld_pci_wr_tg_ram_addr, n_ram_addr); +} + +void nthw_pci_wr_tg_set_ram_data(nthw_pci_wr_tg_t *p, uint32_t req_size, bool wait, + bool wrap, bool inc) +{ + field_set_val32(p->mp_fld_pci_wr_tg_req_size, req_size); + field_set_val32(p->mp_fld_pci_wr_tg_wait, wait); + field_set_val32(p->mp_fld_pci_wr_tg_wrap, wrap); + field_set_val32(p->mp_fld_pci_wr_tg_inc_mode, inc); + field_flush_register(p->mp_fld_pci_wr_tg_inc_mode); +} + +void nthw_pci_wr_tg_set_run(nthw_pci_wr_tg_t *p, int n_iterations) +{ + field_set_val_flush32(p->mp_fld_pci_wr_tg_run_iteration, n_iterations); +} + +uint32_t nthw_pci_wr_tg_get_ctrl_rdy(nthw_pci_wr_tg_t *p) +{ + return field_get_updated(p->mp_fld_pci_wr_tg_ctrl_rdy); +} diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h new file mode 100644 index 0000000000..535b39526e --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_PCI_WR_TG_H__ +#define __NTHW_PCI_WR_TG_H__ + +struct nthw_pci_wr_tg { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_pci_wr_tg; + int mn_instance; + + int mn_param_pci_ta_tg_present; + + nt_register_t *mp_reg_pci_wr_tg_data0; + nt_field_t *mp_fld_pci_wr_tg_phys_addr_low; + + nt_register_t *mp_reg_pci_wr_tg_data1; + nt_field_t *mp_fld_pci_wr_tg_phys_addr_high; + + nt_register_t *mp_reg_pci_wr_tg_data2; + nt_field_t *mp_fld_pci_wr_tg_req_size; + nt_field_t *mp_fld_pci_wr_tg_req_hid; + nt_field_t *mp_fld_pci_wr_tg_inc_mode; + nt_field_t *mp_fld_pci_wr_tg_wait; + nt_field_t *mp_fld_pci_wr_tg_wrap; + + nt_register_t *mp_reg_pci_wr_tg_addr; + nt_field_t *mp_fld_pci_wr_tg_ram_addr; + + nt_register_t *mp_reg_pci_wr_tg_run; + nt_field_t *mp_fld_pci_wr_tg_run_iteration; + + nt_register_t *mp_reg_pci_wr_tg_ctrl; + nt_field_t *mp_fld_pci_wr_tg_ctrl_rdy; + + nt_register_t *mp_reg_pci_wr_tg_seq; + nt_field_t *mp_fld_pci_wr_tg_seq_sequence; +}; + +typedef struct nthw_pci_wr_tg nthw_pci_wr_tg_t; +typedef struct nthw_pci_wr_tg nthw_pci_wr_tg; + +nthw_pci_wr_tg_t *nthw_pci_wr_tg_new(void); +void nthw_pci_wr_tg_delete(nthw_pci_wr_tg_t *p); +int nthw_pci_wr_tg_init(nthw_pci_wr_tg_t *p, nt_fpga_t *p_fpga, int n_instance); + +void nthw_pci_wr_tg_set_phys_addr(nthw_pci_wr_tg_t *p, uint64_t n_phys_addr); +void nthw_pci_wr_tg_set_ram_addr(nthw_pci_wr_tg_t *p, int n_ram_addr); +void nthw_pci_wr_tg_set_ram_data(nthw_pci_wr_tg_t *p, uint32_t req_size, bool wait, + bool wrap, bool inc); +void nthw_pci_wr_tg_set_run(nthw_pci_wr_tg_t *p, int n_iterations); +uint32_t nthw_pci_wr_tg_get_ctrl_rdy(nthw_pci_wr_tg_t *p); + +#endif /* __NTHW_PCI_WR_TG_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_pcie3.c b/drivers/net/ntnic/nthw/core/nthw_pcie3.c new file mode 100644 index 0000000000..07ad784695 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_pcie3.c @@ -0,0 +1,274 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_pcie3.h" + +#define NTHW_TG_REF_FREQ (250000000ULL) + +nthw_pcie3_t *nthw_pcie3_new(void) +{ + nthw_pcie3_t *p = malloc(sizeof(nthw_pcie3_t)); + + if (p) + memset(p, 0, sizeof(nthw_pcie3_t)); + return p; +} + +void nthw_pcie3_delete(nthw_pcie3_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_pcie3_t)); + free(p); + } +} + +int nthw_pcie3_init(nthw_pcie3_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + nt_module_t *mod = fpga_query_module(p_fpga, MOD_PCIE3, n_instance); + + if (p == NULL) + return (mod == NULL ? -1 : 0); + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: PCIE3 %d: no such instance\n", + p_fpga->p_fpga_info->mp_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_pcie3 = mod; + + /* PCIe3 */ + p->mp_reg_stat_ctrl = module_get_register(p->mp_mod_pcie3, PCIE3_STAT_CTRL); + p->mp_fld_stat_ctrl_ena = + register_get_field(p->mp_reg_stat_ctrl, PCIE3_STAT_CTRL_STAT_ENA); + p->mp_fld_stat_ctrl_req = + register_get_field(p->mp_reg_stat_ctrl, PCIE3_STAT_CTRL_STAT_REQ); + + p->mp_reg_stat_rx = module_get_register(p->mp_mod_pcie3, PCIE3_STAT_RX); + p->mp_fld_stat_rx_counter = + register_get_field(p->mp_reg_stat_rx, PCIE3_STAT_RX_COUNTER); + + p->mp_reg_stat_tx = module_get_register(p->mp_mod_pcie3, PCIE3_STAT_TX); + p->mp_fld_stat_tx_counter = + register_get_field(p->mp_reg_stat_tx, PCIE3_STAT_TX_COUNTER); + + p->mp_reg_stat_ref_clk = + module_get_register(p->mp_mod_pcie3, PCIE3_STAT_REFCLK); + p->mp_fld_stat_ref_clk_ref_clk = + register_get_field(p->mp_reg_stat_ref_clk, PCIE3_STAT_REFCLK_REFCLK250); + + p->mp_reg_stat_rq_rdy = + module_get_register(p->mp_mod_pcie3, PCIE3_STAT_RQ_RDY); + p->mp_fld_stat_rq_rdy_counter = + register_get_field(p->mp_reg_stat_rq_rdy, PCIE3_STAT_RQ_RDY_COUNTER); + + p->mp_reg_stat_rq_vld = + module_get_register(p->mp_mod_pcie3, PCIE3_STAT_RQ_VLD); + p->mp_fld_stat_rq_vld_counter = + register_get_field(p->mp_reg_stat_rq_vld, PCIE3_STAT_RQ_VLD_COUNTER); + + p->mp_reg_status0 = module_get_register(p->mp_mod_pcie3, PCIE3_STATUS0); + p->mp_fld_status0_tags_in_use = + register_get_field(p->mp_reg_status0, PCIE3_STATUS0_TAGS_IN_USE); + + p->mp_reg_rp_to_ep_err = + module_get_register(p->mp_mod_pcie3, PCIE3_RP_TO_EP_ERR); + p->mp_fld_rp_to_ep_err_cor = + register_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_COR); + p->mp_fld_rp_to_ep_err_non_fatal = + register_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_NONFATAL); + p->mp_fld_rp_to_ep_err_fatal = + register_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_FATAL); + + p->mp_reg_ep_to_rp_err = + module_get_register(p->mp_mod_pcie3, PCIE3_EP_TO_RP_ERR); + p->mp_fld_ep_to_rp_err_cor = register_get_field(p->mp_reg_ep_to_rp_err, + PCIE3_EP_TO_RP_ERR_ERR_COR); + p->mp_fld_ep_to_rp_err_non_fatal = + register_get_field(p->mp_reg_ep_to_rp_err, PCIE3_EP_TO_RP_ERR_ERR_NONFATAL); + p->mp_fld_ep_to_rp_err_fatal = + register_get_field(p->mp_reg_ep_to_rp_err, PCIE3_EP_TO_RP_ERR_ERR_FATAL); + + p->mp_reg_sample_time = + module_get_register(p->mp_mod_pcie3, PCIE3_SAMPLE_TIME); + p->mp_fld_sample_time = + register_get_field(p->mp_reg_sample_time, PCIE3_SAMPLE_TIME_SAMPLE_TIME); + + p->mp_reg_pci_end_point = + module_get_register(p->mp_mod_pcie3, PCIE3_PCI_ENDPOINT); + p->mp_fld_pci_end_point_if_id = + register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_IF_ID); + p->mp_fld_pci_end_point_send_msg = + register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_SEND_MSG); + p->mp_fld_pci_end_point_get_msg = + register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_GET_MSG); + p->mp_fld_pci_end_point_dmae_p0_allow_mask = + register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_DMA_EP0_ALLOW_MASK); + p->mp_fld_pci_end_point_dmae_p1_allow_mask = + register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_DMA_EP1_ALLOW_MASK); + if (p->mp_reg_pci_end_point) + register_update(p->mp_reg_pci_end_point); + + p->mp_reg_pci_test0 = module_get_register(p->mp_mod_pcie3, PCIE3_PCI_TEST0); + p->mp_fld_pci_test0 = + register_get_field(p->mp_reg_pci_test0, PCIE3_PCI_TEST0_DATA); + if (p->mp_reg_pci_test0) + register_update(p->mp_reg_pci_test0); + + p->mp_reg_pci_test1 = module_get_register(p->mp_mod_pcie3, PCIE3_PCI_TEST1); + p->mp_fld_pci_test1 = + register_get_field(p->mp_reg_pci_test1, PCIE3_PCI_TEST1_DATA); + if (p->mp_reg_pci_test1) + register_update(p->mp_reg_pci_test1); + + p->mp_reg_pci_e3_mark_adr_lsb = + module_get_register(p->mp_mod_pcie3, PCIE3_MARKADR_LSB); + p->mp_fld_pci_e3_mark_adr_lsb_adr = + register_get_field(p->mp_reg_pci_e3_mark_adr_lsb, PCIE3_MARKADR_LSB_ADR); + if (p->mp_reg_pci_e3_mark_adr_lsb) + register_update(p->mp_reg_pci_e3_mark_adr_lsb); + + p->mp_reg_pci_e3_mark_adr_msb = + module_get_register(p->mp_mod_pcie3, PCIE3_MARKADR_MSB); + p->mp_fld_pci_e3_mark_adr_msb_adr = + register_get_field(p->mp_reg_pci_e3_mark_adr_msb, PCIE3_MARKADR_MSB_ADR); + if (p->mp_reg_pci_e3_mark_adr_msb) + register_update(p->mp_reg_pci_e3_mark_adr_msb); + + /* Initial setup - disable markerscheme and bifurcation */ + if (p->mp_fld_pci_end_point_dmae_p0_allow_mask) + field_clr_flush(p->mp_fld_pci_end_point_dmae_p0_allow_mask); + + if (p->mp_fld_pci_end_point_dmae_p1_allow_mask) + field_clr_flush(p->mp_fld_pci_end_point_dmae_p1_allow_mask); + + if (p->mp_fld_pci_e3_mark_adr_lsb_adr) + field_set_val_flush32(p->mp_fld_pci_e3_mark_adr_lsb_adr, 0UL); + + if (p->mp_fld_pci_e3_mark_adr_msb_adr) + field_set_val_flush32(p->mp_fld_pci_e3_mark_adr_msb_adr, 0UL); + + if (p->mp_fld_pci_end_point_dmae_p0_allow_mask) + field_set_flush(p->mp_fld_pci_end_point_dmae_p0_allow_mask); + + if (p->mp_fld_pci_end_point_dmae_p1_allow_mask) + field_clr_flush(p->mp_fld_pci_end_point_dmae_p1_allow_mask); + return 0; +}; + +int nthw_pcie3_trigger_sample_time(nthw_pcie3_t *p) +{ + field_set_val_flush32(p->mp_fld_sample_time, 0xfee1dead); + + return 0; +} + +int nthw_pcie3_stat_req_enable(nthw_pcie3_t *p) +{ + field_set_all(p->mp_fld_stat_ctrl_ena); + field_set_all(p->mp_fld_stat_ctrl_req); + field_flush_register(p->mp_fld_stat_ctrl_req); + return 0; +} + +int nthw_pcie3_stat_req_disable(nthw_pcie3_t *p) +{ + field_clr_all(p->mp_fld_stat_ctrl_ena); + field_set_all(p->mp_fld_stat_ctrl_req); + field_flush_register(p->mp_fld_stat_ctrl_req); + return 0; +} + +int nthw_pcie3_get_stat(nthw_pcie3_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt, + uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size, + uint32_t *p_tg_ref_freq, uint32_t *p_tag_use_cnt, + uint32_t *p_rq_rdy_cnt, uint32_t *p_rq_vld_cnt) +{ + *p_rx_cnt = field_get_updated(p->mp_fld_stat_rx_counter); + *p_tx_cnt = field_get_updated(p->mp_fld_stat_tx_counter); + + *p_ref_clk_cnt = field_get_updated(p->mp_fld_stat_ref_clk_ref_clk); + + *p_tg_unit_size = NTHW_TG_CNT_SIZE; + *p_tg_ref_freq = NTHW_TG_REF_FREQ; + + *p_tag_use_cnt = field_get_updated(p->mp_fld_status0_tags_in_use); + + *p_rq_rdy_cnt = field_get_updated(p->mp_fld_stat_rq_rdy_counter); + *p_rq_vld_cnt = field_get_updated(p->mp_fld_stat_rq_vld_counter); + + return 0; +} + +int nthw_pcie3_get_stat_rate(nthw_pcie3_t *p, uint64_t *p_pci_rx_rate, + uint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt, + uint64_t *p_tag_use_cnt, uint64_t *p_pci_nt_bus_util, + uint64_t *p_pci_xil_bus_util) +{ + uint32_t rx_cnt, tx_cnt, ref_clk_cnt; + uint32_t tg_unit_size, tg_ref_freq; + uint32_t tag_use_cnt, rq_rdy_cnt, rq_vld_cnt; + + nthw_pcie3_get_stat(p, &rx_cnt, &tx_cnt, &ref_clk_cnt, &tg_unit_size, + &tg_ref_freq, &tag_use_cnt, &rq_rdy_cnt, &rq_vld_cnt); + + if (ref_clk_cnt) { + uint64_t nt_bus_util, xil_bus_util; + uint64_t rx_rate, tx_rate; + + rx_rate = ((uint64_t)rx_cnt * tg_unit_size * tg_ref_freq) / + (uint64_t)ref_clk_cnt; + *p_pci_rx_rate = rx_rate; + + tx_rate = ((uint64_t)tx_cnt * tg_unit_size * tg_ref_freq) / + (uint64_t)ref_clk_cnt; + *p_pci_tx_rate = tx_rate; + + *p_ref_clk_cnt = ref_clk_cnt; + + *p_tag_use_cnt = tag_use_cnt; + + nt_bus_util = + ((uint64_t)rq_vld_cnt * 1000000ULL) / (uint64_t)ref_clk_cnt; + *p_pci_nt_bus_util = nt_bus_util; + xil_bus_util = + ((uint64_t)rq_rdy_cnt * 1000000ULL) / (uint64_t)ref_clk_cnt; + *p_pci_xil_bus_util = xil_bus_util; + } else { + *p_ref_clk_cnt = 0; + *p_pci_nt_bus_util = 0; + *p_pci_xil_bus_util = 0; + } + + return 0; +} + +int nthw_pcie3_end_point_counters_sample_pre(nthw_pcie3_t *p, + struct nthw_hif_end_point_counters *epc) +{ + NT_LOG(DBG, NTHW, "%s:%u: empty function\n", __func__, __LINE__); + + (void)p; + (void)epc; + + return 0; +} + +int nthw_pcie3_end_point_counters_sample_post(nthw_pcie3_t *p, + struct nthw_hif_end_point_counters *epc) +{ + NT_LOG(DBG, NTHW, "%s:%u:\n", __func__, __LINE__); + assert(epc); + nthw_pcie3_get_stat_rate(p, &epc->cur_tx, &epc->cur_rx, &epc->n_ref_clk_cnt, + &epc->n_tags_in_use, &epc->cur_pci_nt_util, + &epc->cur_pci_xil_util); + return 0; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_pcie3.h b/drivers/net/ntnic/nthw/core/nthw_pcie3.h new file mode 100644 index 0000000000..beb79a9577 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_pcie3.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_PCIE3_H__ +#define __NTHW_PCIE3_H__ + +struct nthw_pcie3 { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_pcie3; + int mn_instance; + + nt_register_t *mp_reg_stat_ctrl; + nt_field_t *mp_fld_stat_ctrl_req; + nt_field_t *mp_fld_stat_ctrl_ena; + + nt_register_t *mp_reg_stat_rx; + nt_field_t *mp_fld_stat_rx_counter; + + nt_register_t *mp_reg_stat_tx; + nt_field_t *mp_fld_stat_tx_counter; + + nt_register_t *mp_reg_stat_rq_rdy; + nt_field_t *mp_fld_stat_rq_rdy_counter; + + nt_register_t *mp_reg_stat_rq_vld; + nt_field_t *mp_fld_stat_rq_vld_counter; + + nt_register_t *mp_reg_status0; + nt_field_t *mp_fld_status0_tags_in_use; + + nt_register_t *mp_reg_stat_ref_clk; + nt_field_t *mp_fld_stat_ref_clk_ref_clk; + + nt_register_t *mp_reg_rp_to_ep_err; + nt_field_t *mp_fld_rp_to_ep_err_cor; + nt_field_t *mp_fld_rp_to_ep_err_non_fatal; + nt_field_t *mp_fld_rp_to_ep_err_fatal; + + nt_register_t *mp_reg_ep_to_rp_err; + nt_field_t *mp_fld_ep_to_rp_err_cor; + nt_field_t *mp_fld_ep_to_rp_err_non_fatal; + nt_field_t *mp_fld_ep_to_rp_err_fatal; + + nt_register_t *mp_reg_sample_time; + nt_field_t *mp_fld_sample_time; + + nt_register_t *mp_reg_pci_end_point; + nt_field_t *mp_fld_pci_end_point_if_id; + nt_field_t *mp_fld_pci_end_point_send_msg; + nt_field_t *mp_fld_pci_end_point_get_msg; + nt_field_t *mp_fld_pci_end_point_dmae_p0_allow_mask; + nt_field_t *mp_fld_pci_end_point_dmae_p1_allow_mask; + + nt_register_t *mp_reg_pci_e3_mark_adr_lsb; + nt_field_t *mp_fld_pci_e3_mark_adr_lsb_adr; + + nt_register_t *mp_reg_pci_e3_mark_adr_msb; + nt_field_t *mp_fld_pci_e3_mark_adr_msb_adr; + + nt_register_t *mp_reg_pci_test0; + nt_field_t *mp_fld_pci_test0; + + nt_register_t *mp_reg_pci_test1; + nt_field_t *mp_fld_pci_test1; + + nt_register_t *mp_reg_pci_test2; + nt_field_t *mp_fld_pci_test2; + + nt_register_t *mp_reg_pci_test3; + nt_field_t *mp_fld_pci_test3; +}; + +typedef struct nthw_pcie3 nthw_pcie3_t; +typedef struct nthw_pcie3 nthw_pcie3; + +nthw_pcie3_t *nthw_pcie3_new(void); +void nthw_pcie3_delete(nthw_pcie3_t *p); +int nthw_pcie3_init(nthw_pcie3_t *p, nt_fpga_t *p_fpga, int n_instance); + +int nthw_pcie3_trigger_sample_time(nthw_pcie3_t *p); + +int nthw_pcie3_stat_req_enable(nthw_pcie3_t *p); +int nthw_pcie3_stat_req_disable(nthw_pcie3_t *p); + +int nthw_pcie3_get_stat(nthw_pcie3_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt, + uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size, + uint32_t *p_tg_ref_freq, uint32_t *p_tag_use_cnt, + uint32_t *p_rq_rdy_cnt, uint32_t *p_rq_vld_cnt); +int nthw_pcie3_get_stat_rate(nthw_pcie3_t *p, uint64_t *p_pci_rx_rate, + uint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt, + uint64_t *p_tag_use_cnt, uint64_t *p_pci_nt_bus_util, + uint64_t *p_pci_xil_bus_util); + +int nthw_pcie3_end_point_counters_sample_pre(nthw_pcie3_t *p, + struct nthw_hif_end_point_counters *epc); +int nthw_pcie3_end_point_counters_sample_post(nthw_pcie3_t *p, + struct nthw_hif_end_point_counters *epc); + +#endif /* __NTHW_PCIE3_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_sdc.c b/drivers/net/ntnic/nthw/core/nthw_sdc.c new file mode 100644 index 0000000000..0547b92c47 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_sdc.c @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_sdc.h" + +nthw_sdc_t *nthw_sdc_new(void) +{ + nthw_sdc_t *p = malloc(sizeof(nthw_sdc_t)); + + if (p) + memset(p, 0, sizeof(nthw_sdc_t)); + return p; +} + +void nthw_sdc_delete(nthw_sdc_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_sdc_t)); + free(p); + } +} + +int nthw_sdc_init(nthw_sdc_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *mod = fpga_query_module(p_fpga, MOD_SDC, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: SDC %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_sdc = mod; + + { + nt_register_t *p_reg; + + p_reg = module_get_register(p->mp_mod_sdc, SDC_CTRL); + p->mp_fld_ctrl_init = register_get_field(p_reg, SDC_CTRL_INIT); + p->mp_fld_ctrl_run_test = + register_get_field(p_reg, SDC_CTRL_RUN_TEST); + p->mp_fld_ctrl_stop_client = + register_get_field(p_reg, SDC_CTRL_STOP_CLIENT); + p->mp_fld_ctrl_test_enable = + register_get_field(p_reg, SDC_CTRL_TEST_EN); + + p_reg = module_get_register(p->mp_mod_sdc, SDC_STAT); + p->mp_fld_stat_calib = register_get_field(p_reg, SDC_STAT_CALIB); + p->mp_fld_stat_cell_cnt_stopped = + register_get_field(p_reg, SDC_STAT_CELL_CNT_STOPPED); + p->mp_fld_stat_err_found = + register_get_field(p_reg, SDC_STAT_ERR_FOUND); + p->mp_fld_stat_init_done = + register_get_field(p_reg, SDC_STAT_INIT_DONE); + p->mp_fld_stat_mmcm_lock = + register_get_field(p_reg, SDC_STAT_MMCM_LOCK); + p->mp_fld_stat_pll_lock = + register_get_field(p_reg, SDC_STAT_PLL_LOCK); + p->mp_fld_stat_resetting = + register_get_field(p_reg, SDC_STAT_RESETTING); + + p_reg = module_get_register(p->mp_mod_sdc, SDC_CELL_CNT); + p->mp_fld_cell_cnt = + register_get_field(p_reg, SDC_CELL_CNT_CELL_CNT); + + p_reg = module_get_register(p->mp_mod_sdc, SDC_CELL_CNT_PERIOD); + p->mp_fld_cell_cnt_period = + register_get_field(p_reg, SDC_CELL_CNT_PERIOD_CELL_CNT_PERIOD); + + p_reg = module_get_register(p->mp_mod_sdc, SDC_FILL_LVL); + p->mp_fld_fill_level = + register_get_field(p_reg, SDC_FILL_LVL_FILL_LVL); + + p_reg = module_get_register(p->mp_mod_sdc, SDC_MAX_FILL_LVL); + p->mp_fld_max_fill_level = + register_get_field(p_reg, SDC_MAX_FILL_LVL_MAX_FILL_LVL); + } + return 0; +} + +int nthw_sdc_get_states(nthw_sdc_t *p, uint64_t *pn_result_mask) +{ + int n_err_cnt = 0; + uint64_t n_mask = 0; + uint32_t val; + uint32_t val_mask; + int n_val_width; + + if (!p || !pn_result_mask) + return -1; + + val = field_get_updated(p->mp_fld_stat_calib); + n_val_width = field_get_bit_width(p->mp_fld_stat_calib); + val_mask = ((1 << n_val_width) - 1); + n_mask = (n_mask << n_val_width) | (val & val_mask); + if (val != val_mask) + n_err_cnt++; + + val = field_get_updated(p->mp_fld_stat_init_done); + n_val_width = field_get_bit_width(p->mp_fld_stat_init_done); + val_mask = ((1 << n_val_width) - 1); + n_mask = (n_mask << n_val_width) | (val & val_mask); + if (val != val_mask) + n_err_cnt++; + + val = field_get_updated(p->mp_fld_stat_mmcm_lock); + n_val_width = field_get_bit_width(p->mp_fld_stat_mmcm_lock); + val_mask = ((1 << n_val_width) - 1); + n_mask = (n_mask << n_val_width) | (val & val_mask); + if (val != val_mask) + n_err_cnt++; + + val = field_get_updated(p->mp_fld_stat_pll_lock); + n_val_width = field_get_bit_width(p->mp_fld_stat_pll_lock); + val_mask = ((1 << n_val_width) - 1); + n_mask = (n_mask << n_val_width) | (val & val_mask); + if (val != val_mask) + n_err_cnt++; + + val = field_get_updated(p->mp_fld_stat_resetting); + n_val_width = field_get_bit_width(p->mp_fld_stat_resetting); + val_mask = ((1 << n_val_width) - 1); + n_mask = (n_mask << n_val_width) | (val & val_mask); + if (val != 0) + n_err_cnt++; + + if (pn_result_mask) + *pn_result_mask = n_mask; + + return n_err_cnt; /* 0 = all ok */ +} + +int nthw_sdc_wait_states(nthw_sdc_t *p, const int n_poll_iterations, + const int n_poll_interval) +{ + int res; + int n_err_cnt = 0; + + res = field_wait_set_all32(p->mp_fld_stat_calib, n_poll_iterations, + n_poll_interval); + if (res) + n_err_cnt++; + + res = field_wait_set_all32(p->mp_fld_stat_init_done, n_poll_iterations, + n_poll_interval); + if (res) + n_err_cnt++; + + res = field_wait_set_all32(p->mp_fld_stat_mmcm_lock, n_poll_iterations, + n_poll_interval); + if (res) + n_err_cnt++; + + res = field_wait_set_all32(p->mp_fld_stat_pll_lock, n_poll_iterations, + n_poll_interval); + if (res) + n_err_cnt++; + + res = field_wait_clr_all32(p->mp_fld_stat_resetting, n_poll_iterations, + n_poll_interval); + if (res) + n_err_cnt++; + + return n_err_cnt; /* 0 = all ok */ +} diff --git a/drivers/net/ntnic/nthw/core/nthw_sdc.h b/drivers/net/ntnic/nthw/core/nthw_sdc.h new file mode 100644 index 0000000000..e6c08ffbc3 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_sdc.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_SDC_H__ +#define __NTHW_SDC_H__ + +struct nthw_sdc { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_sdc; + int mn_instance; + + nt_field_t *mp_fld_ctrl_init; + nt_field_t *mp_fld_ctrl_run_test; + nt_field_t *mp_fld_ctrl_stop_client; + nt_field_t *mp_fld_ctrl_test_enable; + + nt_field_t *mp_fld_stat_calib; + nt_field_t *mp_fld_stat_cell_cnt_stopped; + nt_field_t *mp_fld_stat_err_found; + nt_field_t *mp_fld_stat_init_done; + nt_field_t *mp_fld_stat_mmcm_lock; + nt_field_t *mp_fld_stat_pll_lock; + nt_field_t *mp_fld_stat_resetting; + + nt_field_t *mp_fld_cell_cnt; + nt_field_t *mp_fld_cell_cnt_period; + nt_field_t *mp_fld_fill_level; + nt_field_t *mp_fld_max_fill_level; +}; + +typedef struct nthw_sdc nthw_sdc_t; +typedef struct nthw_sdc nthw_sdc; + +nthw_sdc_t *nthw_sdc_new(void); +int nthw_sdc_init(nthw_sdc_t *p, nt_fpga_t *p_fpga, int n_instance); +void nthw_sdc_delete(nthw_sdc_t *p); + +int nthw_sdc_wait_states(nthw_sdc_t *p, const int n_poll_iterations, + const int n_poll_interval); +int nthw_sdc_get_states(nthw_sdc_t *p, uint64_t *pn_result_mask); + +#endif /* __NTHW_SDC_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_si5340.c b/drivers/net/ntnic/nthw/core/nthw_si5340.c new file mode 100644 index 0000000000..3337f1f9e3 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_si5340.c @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + * + * This file implements Si5340 clock synthesizer support. + * The implementation is generic and must be tailored to a specific use by the + * correct initialization data. + */ + +#include "nt_util.h" +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_si5340.h" + +#define SI5340_WAIT_US(x) NT_OS_WAIT_USEC(x) + +#define SI5340_LOG_DEBUG(...) NT_LOG(DBG, NTHW, __VA_ARGS__) +#define SI5340_LOG_INFO(...) NT_LOG(INF, NTHW, __VA_ARGS__) +#define SI5340_LOG_WARN(...) NT_LOG(WRN, NTHW, __VA_ARGS__) +#define SI5340_LOG_ERROR(...) NT_LOG(ERR, NTHW, __VA_ARGS__) + +#define SI5340_PAGE_REG_ADDR (0x01) + +nthw_si5340_t *nthw_si5340_new(void) +{ + nthw_si5340_t *p = malloc(sizeof(nthw_si5340_t)); + + if (p) + memset(p, 0, sizeof(nthw_si5340_t)); + return p; +} + +int nthw_si5340_init(nthw_si5340_t *p, nthw_iic_t *p_nthw_iic, uint8_t n_iic_addr) +{ + uint8_t data; + + p->mp_nthw_iic = p_nthw_iic; + p->mn_iic_addr = n_iic_addr; + p->mn_clk_cfg = -1; + + p->m_si5340_page = 0; + data = p->m_si5340_page; + nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr, SI5340_PAGE_REG_ADDR, 1, + &data); + + return 0; +} + +void nthw_si5340_delete(nthw_si5340_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_si5340_t)); + free(p); + } +} + +/* + * Read access (via I2C) to the clock synthesizer IC. The IC is located at I2C + * 7bit address 0x74 + */ +static uint8_t nthw_si5340_read(nthw_si5340_t *p, uint16_t reg_addr) +{ + const uint8_t offset_adr = (uint8_t)(reg_addr & 0xff); + uint8_t page = (uint8_t)((reg_addr >> 8) & 0xff); + uint8_t data; + + /* check if we are on the right page */ + if (page != p->m_si5340_page) { + nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr, + SI5340_PAGE_REG_ADDR, 1, &page); + p->m_si5340_page = page; + } + nthw_iic_read_data(p->mp_nthw_iic, p->mn_iic_addr, offset_adr, 1, &data); + return data; +} + +/* + * Write access (via I2C) to the clock synthesizer IC. The IC is located at I2C + * 7 bit address 0x74 + */ +static int nthw_si5340_write(nthw_si5340_t *p, uint16_t reg_addr, uint8_t data) +{ + const uint8_t offset_adr = (uint8_t)(reg_addr & 0xff); + uint8_t page = (uint8_t)((reg_addr >> 8) & 0xff); + + /* check if we are on the right page */ + if (page != p->m_si5340_page) { + nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr, + SI5340_PAGE_REG_ADDR, 1, &page); + p->m_si5340_page = page; + } + nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr, offset_adr, 1, &data); + + return 0; +} + +static int nthw_si5340_cfg(nthw_si5340_t *p, const void *p_data, int data_cnt, + clk_profile_data_fmt_t data_format) +{ + const char *const p_adapter_id_str = + p->mp_nthw_iic->mp_fpga->p_fpga_info->mp_adapter_id_str; + int i; + uint16_t addr; + uint8_t value; + uint8_t ctrl_value; + + NT_LOG(DBG, NTHW, "%s: %s: data_cnt = %d, dataFormat = %d\n", + p_adapter_id_str, __func__, data_cnt, data_format); + + for (i = 0; i < data_cnt; i++) { + if (data_format == CLK_PROFILE_DATA_FMT_1) { + addr = ((const clk_profile_data_fmt1_t *)p_data)->reg_addr; + value = ((const clk_profile_data_fmt1_t *)p_data)->reg_val; + p_data = ((const clk_profile_data_fmt1_t *)p_data) + 1; + } else if (data_format == CLK_PROFILE_DATA_FMT_2) { + addr = (uint16_t)(((const clk_profile_data_fmt2_t *)p_data) + ->reg_addr); + value = ((const clk_profile_data_fmt2_t *)p_data)->reg_val; + p_data = ((const clk_profile_data_fmt2_t *)p_data) + 1; + } else { + NT_LOG(ERR, NTHW, + "%s: Unhandled Si5340 data format (%d)\n", + p_adapter_id_str, data_format); + return -1; + } + + if (addr == 0x0006) { + /* Wait 300ms before continuing. See NT200E3-2-PTP_U23_Si5340_adr0_v2.h */ + NT_OS_WAIT_USEC(300000); + } + + nthw_si5340_write(p, addr, value); + + if (addr == 0x001C) { + /* skip readback for "soft reset" register */ + continue; + } + + ctrl_value = nthw_si5340_read(p, addr); + + if (ctrl_value != value) { + NT_LOG(ERR, NTHW, + "%s: Si5340 configuration readback check failed. (Addr = 0x%04X, Write = 0x%02X, Read = 0x%02X)\n", + p_adapter_id_str, addr, value, ctrl_value); + return -1; + } + } + return 0; +} + +int nthw_si5340_config(nthw_si5340_t *p, const void *p_data, int data_cnt, + clk_profile_data_fmt_t data_format) +{ + const char *const p_adapter_id_str = + p->mp_nthw_iic->mp_fpga->p_fpga_info->mp_adapter_id_str; + int i; + bool success = false; + uint8_t status, sticky; + uint8_t design_id[9]; + + (void)nthw_si5340_cfg(p, p_data, data_cnt, data_format); + + /* Check if DPLL is locked and SYS is calibrated */ + for (i = 0; i < 5; i++) { + status = nthw_si5340_read(p, 0x0c); + sticky = nthw_si5340_read(p, 0x11); + nthw_si5340_write(p, 0x11, 0x00); + + if (((status & 0x09) == 0x00) && ((sticky & 0x09) == 0x00)) { + success = true; + break; + } + NT_OS_WAIT_USEC(1000000); /* 1 sec */ + } + + if (!success) { + NT_LOG(ERR, NTHW, + "%s: Si5340 configuration failed. (Status = 0x%02X, Sticky = 0x%02X)\n", + p_adapter_id_str, status, sticky); + return -1; + } + + for (i = 0; i < (int)sizeof(design_id) - 1; i++) + design_id[i] = nthw_si5340_read(p, (uint16_t)(0x26B + i)); + design_id[sizeof(design_id) - 1] = 0; + + (void)design_id; /* Only used in debug mode */ + NT_LOG(DBG, NTHW, "%s: Si5340.DesignId = %s\n", p_adapter_id_str, + design_id); + + return 0; +} + +int nthw_si5340_config_fmt1(nthw_si5340_t *p, const clk_profile_data_fmt1_t *p_data, + const int data_cnt) +{ + return nthw_si5340_config(p, p_data, data_cnt, CLK_PROFILE_DATA_FMT_1); +} + +int nthw_si5340_config_fmt2(nthw_si5340_t *p, const clk_profile_data_fmt2_t *p_data, + const int data_cnt) +{ + return nthw_si5340_config(p, p_data, data_cnt, CLK_PROFILE_DATA_FMT_2); +} diff --git a/drivers/net/ntnic/nthw/core/nthw_si5340.h b/drivers/net/ntnic/nthw/core/nthw_si5340.h new file mode 100644 index 0000000000..f588b5b825 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_si5340.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_SI5340_H__ +#define __NTHW_SI5340_H__ + +#include "nthw_clock_profiles.h" + +#define SI5340_SUCCESS (0) +#define SI5340_FAILED (999) +#define SI5340_TIMEOUT (666) + +struct nthw_si5340 { + uint8_t mn_iic_addr; + nthw_iic_t *mp_nthw_iic; + int mn_clk_cfg; + uint8_t m_si5340_page; +}; + +typedef struct nthw_si5340 nthw_si5340_t; + +nthw_si5340_t *nthw_si5340_new(void); +int nthw_si5340_init(nthw_si5340_t *p, nthw_iic_t *p_nthw_iic, uint8_t n_iic_addr); +void nthw_si5340_delete(nthw_si5340_t *p); + +int nthw_si5340_config(nthw_si5340_t *p, const void *p_data, int data_cnt, + clk_profile_data_fmt_t data_format); +int nthw_si5340_config_fmt1(nthw_si5340_t *p, const clk_profile_data_fmt1_t *p_data, + const int data_cnt); +int nthw_si5340_config_fmt2(nthw_si5340_t *p, const clk_profile_data_fmt2_t *p_data, + const int data_cnt); + +#endif /* __NTHW_SI5338_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_spi_v3.c b/drivers/net/ntnic/nthw/core/nthw_spi_v3.c new file mode 100644 index 0000000000..454c9b73b8 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_spi_v3.c @@ -0,0 +1,380 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_fpga.h" + +#include "nthw_spi_v3.h" + +#include + +#undef SPI_V3_DEBUG_PRINT + +nthw_spi_v3_t *nthw_spi_v3_new(void) +{ + nthw_spi_v3_t *p = malloc(sizeof(nthw_spi_v3_t)); + + if (p) + memset(p, 0, sizeof(nthw_spi_v3_t)); + return p; +} + +void nthw_spi_v3_delete(nthw_spi_v3_t *p) +{ + if (p) { + if (p->mp_spim_mod) { + nthw_spim_delete(p->mp_spim_mod); + p->mp_spim_mod = NULL; + } + + if (p->mp_spis_mod) { + nthw_spis_delete(p->mp_spis_mod); + p->mp_spis_mod = NULL; + } + + memset(p, 0, sizeof(nthw_spi_v3_t)); + free(p); + } +} + +int nthw_spi_v3_set_timeout(nthw_spi_v3_t *p, int time_out) +{ + p->m_time_out = time_out; + return 0; +} + +int nthw_spi_v3_get_version(nthw_spi_v3_t *p) +{ + (void)p; + return 3; +} + +/* + * Wait until Tx data have been sent after they have been placed in the Tx FIFO. + */ +static int wait_for_tx_data_sent(nthw_spim_t *p_spim_mod, uint64_t time_out) +{ + int result; + bool empty; + uint64_t start_time; + uint64_t cur_time; + + start_time = NT_OS_GET_TIME_MONOTONIC_COUNTER(); + + while (true) { + NT_OS_WAIT_USEC(1000); /* Every 1ms */ + + result = nthw_spim_get_tx_fifo_empty(p_spim_mod, &empty); + if (result != 0) { + NT_LOG(WRN, NTHW, + "nthw_spim_get_tx_fifo_empty failed\n"); + return result; + } + + if (empty) + break; + + cur_time = NT_OS_GET_TIME_MONOTONIC_COUNTER(); + if ((cur_time - start_time) > time_out) { + NT_LOG(WRN, NTHW, "%s: Timed out\n", __func__); + return -1; + } + } + + return 0; +} + +/* + * Wait until Rx data have been received. + */ +static int wait_for_rx_data_ready(nthw_spis_t *p_spis_mod, uint64_t time_out) +{ + int result; + bool empty; + uint64_t start_time; + uint64_t cur_time; + + start_time = NT_OS_GET_TIME_MONOTONIC_COUNTER(); + + /* Wait for data to become ready in the Rx FIFO */ + while (true) { + NT_OS_WAIT_USEC(10000); /* Every 10ms */ + + result = nthw_spis_get_rx_fifo_empty(p_spis_mod, &empty); + if (result != 0) { + NT_LOG(WRN, NTHW, "nthw_spis_get_rx_empty failed\n"); + return result; + } + + if (!empty) + break; + + cur_time = NT_OS_GET_TIME_MONOTONIC_COUNTER(); + if ((cur_time - start_time) > time_out) { + NT_LOG(WRN, NTHW, "%s: Timed out\n", __func__); + return -1; + } + } + + return 0; +} + +#ifdef SPI_V3_DEBUG_PRINT +static void dump_hex(uint8_t *p_data, uint16_t count) +{ + int i; + int j = 0; + char tmp_str[128]; + + for (i = 0; i < count; i++) { + sprintf(&tmp_str[j * 3], "%02X ", *(p_data++)); + j++; + + if (j == 16 || (i == count - 1)) { + tmp_str[j * 3 - 1] = '\0'; + NT_LOG(DBG, NTHW, " %s\n", tmp_str); + j = 0; + } + } +} +#endif + +int nthw_spi_v3_init(nthw_spi_v3_t *p, nt_fpga_t *p_fpga, int n_instance_no) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + uint32_t result; + + p->mn_instance_no = n_instance_no; + + nthw_spi_v3_set_timeout(p, 1); + + /* Initialize SPIM module */ + p->mp_spim_mod = nthw_spim_new(); + + result = nthw_spim_init(p->mp_spim_mod, p_fpga, n_instance_no); + if (result != 0) { + NT_LOG(ERR, NTHW, "%s: nthw_spis_init failed: %d\n", + p_adapter_id_str, result); + } + + /* Initialize SPIS module */ + p->mp_spis_mod = nthw_spis_new(); + + result = nthw_spis_init(p->mp_spis_mod, p_fpga, n_instance_no); + if (result != 0) { + NT_LOG(ERR, NTHW, "%s: nthw_spim_init failed: %d\n", + p_adapter_id_str, result); + } + + /* Reset SPIM and SPIS modules */ + result = nthw_spim_reset(p->mp_spim_mod); + if (result != 0) { + NT_LOG(ERR, NTHW, "%s: nthw_spim_reset failed: %d\n", + p_adapter_id_str, result); + } + + result = nthw_spis_reset(p->mp_spis_mod); + if (result != 0) { + NT_LOG(ERR, NTHW, "%s: nthw_spis_reset failed: %d\n", + p_adapter_id_str, result); + } + + return result; +} + +/* + * Send Tx data using the SPIM module and receive any data using the SPIS module. + * The data are sent and received being wrapped into a SPI v3 container. + */ +int nthw_spi_v3_transfer(nthw_spi_v3_t *p, uint16_t opcode, + struct tx_rx_buf *tx_buf, struct tx_rx_buf *rx_buf) +{ + const uint16_t max_payload_rx_size = rx_buf->size; + int result = 0; + +#pragma pack(push, 1) + union { + uint32_t raw; + + struct { + uint16_t opcode; + uint16_t size; + }; + } spi_tx_hdr; + + union { + uint32_t raw; + + struct { + uint16_t error_code; + uint16_t size; + }; + } spi_rx_hdr; +#pragma pack(pop) + +#ifdef SPI_V3_DEBUG_PRINT + NT_LOG(DBG, NTHW, "%s: Started\n", __func__); +#endif + + /* Disable transmission from Tx FIFO */ + result = nthw_spim_enable(p->mp_spim_mod, false); + if (result != 0) { + NT_LOG(WRN, NTHW, "nthw_spim_enable failed\n"); + return result; + } + + /* Enable SPIS module */ + result = nthw_spis_enable(p->mp_spis_mod, true); + if (result != 0) { + NT_LOG(WRN, NTHW, "nthw_spis_enable failed\n"); + return result; + } + + /* Put data into Tx FIFO */ + spi_tx_hdr.opcode = opcode; + spi_tx_hdr.size = tx_buf->size; + +#ifdef SPI_V3_DEBUG_PRINT + NT_LOG(DBG, NTHW, "opcode=0x%04X tx_bufsize=0x%04X rx_bufsize=0x%04X\n", + opcode, tx_buf->size, rx_buf->size); + +#endif /* SPI_V3_DEBUG_PRINT */ + + result = nthw_spim_write_tx_fifo(p->mp_spim_mod, htonl(spi_tx_hdr.raw)); + if (result != 0) { + NT_LOG(WRN, NTHW, "nthw_spim_write_tx_fifo failed\n"); + return result; + } + + { + uint8_t *tx_data = (uint8_t *)tx_buf->p_buf; + uint16_t tx_size = tx_buf->size; + uint16_t count; + uint32_t value; + + while (tx_size > 0) { + if (tx_size > 4) { + count = 4; + } else { + count = tx_size; + value = 0; + } + + memcpy(&value, tx_data, count); + + result = nthw_spim_write_tx_fifo(p->mp_spim_mod, + htonl(value)); + if (result != 0) { + NT_LOG(WRN, NTHW, + "nthw_spim_write_tx_fifo failed\n"); + return result; + } + + tx_size = (uint16_t)(tx_size - count); + tx_data += count; + } + } + + /* Enable Tx FIFO */ + result = nthw_spim_enable(p->mp_spim_mod, true); + if (result != 0) { + NT_LOG(WRN, NTHW, "nthw_spim_enable failed\n"); + return result; + } + + result = wait_for_tx_data_sent(p->mp_spim_mod, p->m_time_out); + if (result != 0) + return result; + +#ifdef SPI_V3_DEBUG_PRINT + NT_LOG(DBG, NTHW, "%s: SPI header and payload data have been sent\n", + __func__); +#endif + + { + /* + * Start receiving data + * The first data to read is the header + */ + uint16_t rx_size = sizeof(spi_rx_hdr.raw); + uint8_t *rx_data = (uint8_t *)rx_buf->p_buf; + bool rx_hdr_read = false; + + rx_buf->size = 0; + + while (true) { + uint16_t count; + uint32_t value; + + if (!rx_hdr_read) { /* Read the header */ + result = wait_for_rx_data_ready(p->mp_spis_mod, + p->m_time_out); + if (result != 0) + return result; + + result = nthw_spis_read_rx_fifo(p->mp_spis_mod, + &spi_rx_hdr.raw); + if (result != 0) { + NT_LOG(WRN, NTHW, + "nthw_spis_read_rx_fifo failed\n"); + return result; + } + + spi_rx_hdr.raw = ntohl(spi_rx_hdr.raw); + rx_size = spi_rx_hdr.size; + rx_hdr_read = true; /* Next time read payload */ + +#ifdef SPI_V3_DEBUG_PRINT + NT_LOG(DBG, NTHW, + " spi_rx_hdr.error_code = 0x%04X, spi_rx_hdr.size = 0x%04X\n", + spi_rx_hdr.error_code, spi_rx_hdr.size); +#endif + + if (spi_rx_hdr.error_code != 0) { + result = -1; /* NT_ERROR_AVR_OPCODE_RETURNED_ERROR; */ + break; + } + + if (rx_size > max_payload_rx_size) { + result = 1; /* NT_ERROR_AVR_RX_BUFFER_TOO_SMALL; */ + break; + } + } else { /* Read the payload */ + count = (uint16_t)(rx_size < 4U ? rx_size : 4U); + + if (count == 0) + break; + + result = wait_for_rx_data_ready(p->mp_spis_mod, + p->m_time_out); + if (result != 0) + return result; + + result = nthw_spis_read_rx_fifo(p->mp_spis_mod, + &value); + if (result != 0) { + NT_LOG(WRN, NTHW, + "nthw_spis_read_rx_fifo failed\n"); + return result; + } + + value = ntohl(value); /* Convert to host endian */ + memcpy(rx_data, &value, count); + rx_buf->size = (uint16_t)(rx_buf->size + count); + rx_size = (uint16_t)(rx_size - count); + rx_data += count; + } + } + } + +#ifdef SPI_V3_DEBUG_PRINT + NT_LOG(DBG, NTHW, " RxData: %d\n", rx_buf->size); + dump_hex(rx_buf->p_buf, rx_buf->size); + NT_LOG(DBG, NTHW, "%s: Ended: %d\n", __func__, result); +#endif + + return result; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_spi_v3.h b/drivers/net/ntnic/nthw/core/nthw_spi_v3.h new file mode 100644 index 0000000000..c54379a273 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_spi_v3.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NT4GA_SPI_V3__ +#define __NT4GA_SPI_V3__ + +/* Must include v1.x series. The first v1.0a only had 248 bytes of storage. v2.0x have 255 */ +#define MAX_AVR_CONTAINER_SIZE (248) + +enum avr_opcodes { + AVR_OP_NOP = 0, /* v2 NOP command */ + /* version handlers */ + AVR_OP_VERSION = 1, + AVR_OP_SPI_VERSION = 2, /* v2.0+ command Get protocol version */ + AVR_OP_SYSINFO = 3, + /* Ping handlers */ + AVR_OP_PING = 4, + AVR_OP_PING_DELAY = 5, + /* i2c handlers */ + AVR_OP_I2C_READ = 9, + AVR_OP_I2C_WRITE = 10, + AVR_OP_I2C_RANDOM_READ = 11, + /* VPD handlers */ + AVR_OP_VPD_READ = 19, + AVR_OP_VPD_WRITE = 20, + /* SENSOR handlers */ + AVR_OP_SENSOR_FETCH = 28, + /* The following command are only relevant to V3 */ + AVR_OP_SENSOR_MON_CONTROL = 42, + AVR_OP_SENSOR_MON_SETUP = 43, + /* special version handler */ + AVR_OP_SYSINFO_2 = 62, +}; + +#define GEN2_AVR_IDENT_SIZE (20) +#define GEN2_AVR_VERSION_SIZE (50) + +#define GEN2_PN_SIZE (13) +#define GEN2_PBA_SIZE (16) +#define GEN2_SN_SIZE (10) +#define GEN2_BNAME_SIZE (14) +#define GEN2_PLATFORM_SIZE (72) +#define GEN2_VPD_SIZE_TOTAL \ + (1 + GEN2_PN_SIZE + GEN2_PBA_SIZE + GEN2_SN_SIZE + GEN2_BNAME_SIZE + \ + GEN2_PLATFORM_SIZE + 2) + +typedef struct vpd_eeprom_s { + uint8_t psu_hw_version; /* Hw revision - MUST NEVER ne overwritten. */ + /* Vital Product Data: P/N (13bytes ascii 0-9) */ + uint8_t vpd_pn[GEN2_PN_SIZE]; + /* Vital Product Data: PBA (16bytes ascii 0-9) */ + uint8_t vpd_pba[GEN2_PBA_SIZE]; + /* Vital Product Data: S/N (10bytes ascii 0-9) */ + uint8_t vpd_sn[GEN2_SN_SIZE]; + /* Vital Product Data: Board Name (10bytes ascii) (e.g. "ntmainb1e2" or "ntfront20b1") */ + uint8_t vpd_board_name[GEN2_BNAME_SIZE]; + /* + * Vital Product Data: Other (72bytes of MAC addresses or other stuff.. (gives up to 12 mac + * addresses) + */ + uint8_t vpd_platform_section[GEN2_PLATFORM_SIZE]; + /* CRC16 checksum of all of above. This field is not included in the checksum */ + uint16_t crc16; +} vpd_eeprom_t; + +typedef struct { + uint8_t psu_hw_revision; + char board_type[GEN2_BNAME_SIZE + 1]; + char product_id[GEN2_PN_SIZE + 1]; + char pba_id[GEN2_PBA_SIZE + 1]; + char serial_number[GEN2_SN_SIZE + 1]; + uint8_t product_family; + uint32_t feature_mask; + uint32_t invfeature_mask; + uint8_t no_of_macs; + uint8_t mac_address[6]; + uint16_t custom_id; + uint8_t user_id[8]; +} board_info_t; + +struct tx_rx_buf { + uint16_t size; + void *p_buf; +}; + +struct nthw__spi__v3 { + int m_time_out; + int mn_instance_no; + nthw_spim_t *mp_spim_mod; + nthw_spis_t *mp_spis_mod; +}; + +typedef struct nthw__spi__v3 nthw_spi_v3_t; +typedef struct nthw__spi__v3 nthw_spi_v3; + +nthw_spi_v3_t *nthw_spi_v3_new(void); +int nthw_spi_v3_init(nthw_spi_v3_t *p, nt_fpga_t *p_fpga, int n_instance_no); +void nthw_spi_v3_delete(nthw_spi_v3_t *p); + +int nthw_spi_v3_set_timeout(nthw_spi_v3_t *p, int time_out); +int nthw_spi_v3_get_version(nthw_spi_v3_t *p); +int nthw_spi_v3_transfer(nthw_spi_v3_t *p, uint16_t opcode, + struct tx_rx_buf *tx_buf, struct tx_rx_buf *rx_buf); + +#endif /* __NT4GA_SPI_V3__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_spim.c b/drivers/net/ntnic/nthw/core/nthw_spim.c new file mode 100644 index 0000000000..ece7db26e1 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_spim.c @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_spim.h" + +nthw_spim_t *nthw_spim_new(void) +{ + nthw_spim_t *p = malloc(sizeof(nthw_spim_t)); + + if (p) + memset(p, 0, sizeof(nthw_spim_t)); + return p; +} + +int nthw_spim_init(nthw_spim_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *mod = fpga_query_module(p_fpga, MOD_SPIM, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: SPIM %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_spim = mod; + + /* SPIM is a primary communication channel - turn off debug by default */ + module_set_debug_mode(p->mp_mod_spim, 0x00); + + p->mp_reg_srr = module_get_register(p->mp_mod_spim, SPIM_SRR); + p->mp_fld_srr_rst = register_get_field(p->mp_reg_srr, SPIM_SRR_RST); + + p->mp_reg_cr = module_get_register(p->mp_mod_spim, SPIM_CR); + p->mp_fld_cr_loop = register_get_field(p->mp_reg_cr, SPIM_CR_LOOP); + p->mp_fld_cr_en = register_get_field(p->mp_reg_cr, SPIM_CR_EN); + p->mp_fld_cr_txrst = register_get_field(p->mp_reg_cr, SPIM_CR_TXRST); + p->mp_fld_cr_rxrst = register_get_field(p->mp_reg_cr, SPIM_CR_RXRST); + + p->mp_reg_sr = module_get_register(p->mp_mod_spim, SPIM_SR); + p->mp_fld_sr_done = register_get_field(p->mp_reg_sr, SPIM_SR_DONE); + p->mp_fld_sr_txempty = register_get_field(p->mp_reg_sr, SPIM_SR_TXEMPTY); + p->mp_fld_sr_rxempty = register_get_field(p->mp_reg_sr, SPIM_SR_RXEMPTY); + p->mp_fld_sr_txfull = register_get_field(p->mp_reg_sr, SPIM_SR_TXFULL); + p->mp_fld_sr_rxfull = register_get_field(p->mp_reg_sr, SPIM_SR_RXFULL); + p->mp_fld_sr_txlvl = register_get_field(p->mp_reg_sr, SPIM_SR_TXLVL); + p->mp_fld_sr_rxlvl = register_get_field(p->mp_reg_sr, SPIM_SR_RXLVL); + + p->mp_reg_dtr = module_get_register(p->mp_mod_spim, SPIM_DTR); + p->mp_fld_dtr_dtr = register_get_field(p->mp_reg_dtr, SPIM_DTR_DTR); + + p->mp_reg_drr = module_get_register(p->mp_mod_spim, SPIM_DRR); + p->mp_fld_drr_drr = register_get_field(p->mp_reg_drr, SPIM_DRR_DRR); + + p->mp_reg_cfg = module_get_register(p->mp_mod_spim, SPIM_CFG); + p->mp_fld_cfg_pre = register_get_field(p->mp_reg_cfg, SPIM_CFG_PRE); + + return 0; +} + +void nthw_spim_delete(nthw_spim_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_spim_t)); + free(p); + } +} + +uint32_t nthw_spim_reset(nthw_spim_t *p) +{ + register_update(p->mp_reg_srr); + field_set_val32(p->mp_fld_srr_rst, + 0x0A); /* 0x0A hardcoded value - see doc */ + register_flush(p->mp_reg_srr, 1); + + return 0; +} + +uint32_t nthw_spim_enable(nthw_spim_t *p, bool b_enable) +{ + field_update_register(p->mp_fld_cr_en); + + if (b_enable) + field_set_all(p->mp_fld_cr_en); + + else + field_clr_all(p->mp_fld_cr_en); + field_flush_register(p->mp_fld_cr_en); + + return 0; +} + +uint32_t nthw_spim_write_tx_fifo(nthw_spim_t *p, uint32_t n_data) +{ + field_set_val_flush32(p->mp_fld_dtr_dtr, n_data); + return 0; +} + +uint32_t nthw_spim_get_tx_fifo_empty(nthw_spim_t *p, bool *pb_empty) +{ + assert(pb_empty); + + *pb_empty = field_get_updated(p->mp_fld_sr_txempty) ? true : false; + + return 0; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_spim.h b/drivers/net/ntnic/nthw/core/nthw_spim.h new file mode 100644 index 0000000000..713751e563 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_spim.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_SPIM_H__ +#define __NTHW_SPIM_H__ + +struct nthw_spim { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_spim; + int mn_instance; + + nt_register_t *mp_reg_srr; + nt_field_t *mp_fld_srr_rst; + + nt_register_t *mp_reg_cr; + nt_field_t *mp_fld_cr_loop; + nt_field_t *mp_fld_cr_en; + nt_field_t *mp_fld_cr_txrst; + nt_field_t *mp_fld_cr_rxrst; + + nt_register_t *mp_reg_sr; + nt_field_t *mp_fld_sr_done; + nt_field_t *mp_fld_sr_txempty; + nt_field_t *mp_fld_sr_rxempty; + nt_field_t *mp_fld_sr_txfull; + nt_field_t *mp_fld_sr_rxfull; + nt_field_t *mp_fld_sr_txlvl; + nt_field_t *mp_fld_sr_rxlvl; + + nt_register_t *mp_reg_dtr; + nt_field_t *mp_fld_dtr_dtr; + + nt_register_t *mp_reg_drr; + nt_field_t *mp_fld_drr_drr; + nt_register_t *mp_reg_cfg; + nt_field_t *mp_fld_cfg_pre; +}; + +typedef struct nthw_spim nthw_spim_t; +typedef struct nthw_spim nthw_spim; + +nthw_spim_t *nthw_spim_new(void); +int nthw_spim_init(nthw_spim_t *p, nt_fpga_t *p_fpga, int n_instance); +void nthw_spim_delete(nthw_spim_t *p); + +uint32_t nthw_spim_reset(nthw_spim_t *p); +uint32_t nthw_spim_enable(nthw_spim_t *p, bool b_enable); +uint32_t nthw_spim_get_tx_fifo_empty(nthw_spim_t *p, bool *pb_empty); +uint32_t nthw_spim_write_tx_fifo(nthw_spim_t *p, uint32_t n_data); + +#endif /* __NTHW_SPIM_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_spis.c b/drivers/net/ntnic/nthw/core/nthw_spis.c new file mode 100644 index 0000000000..8799584194 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_spis.c @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_spis.h" + +nthw_spis_t *nthw_spis_new(void) +{ + nthw_spis_t *p = malloc(sizeof(nthw_spis_t)); + + if (p) + memset(p, 0, sizeof(nthw_spis_t)); + return p; +} + +int nthw_spis_init(nthw_spis_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *mod = fpga_query_module(p_fpga, MOD_SPIS, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: SPIS %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_spis = mod; + + /* SPIS is a primary communication channel - turn off debug by default */ + module_set_debug_mode(p->mp_mod_spis, 0x00); + + p->mp_reg_srr = module_get_register(p->mp_mod_spis, SPIS_SRR); + p->mp_fld_srr_rst = register_get_field(p->mp_reg_srr, SPIS_SRR_RST); + + p->mp_reg_cr = module_get_register(p->mp_mod_spis, SPIS_CR); + p->mp_fld_cr_loop = register_get_field(p->mp_reg_cr, SPIS_CR_LOOP); + p->mp_fld_cr_en = register_get_field(p->mp_reg_cr, SPIS_CR_EN); + p->mp_fld_cr_txrst = register_get_field(p->mp_reg_cr, SPIS_CR_TXRST); + p->mp_fld_cr_rxrst = register_get_field(p->mp_reg_cr, SPIS_CR_RXRST); + p->mp_fld_cr_debug = register_get_field(p->mp_reg_cr, SPIS_CR_DEBUG); + + p->mp_reg_sr = module_get_register(p->mp_mod_spis, SPIS_SR); + p->mp_fld_sr_done = register_get_field(p->mp_reg_sr, SPIS_SR_DONE); + p->mp_fld_sr_txempty = register_get_field(p->mp_reg_sr, SPIS_SR_TXEMPTY); + p->mp_fld_sr_rxempty = register_get_field(p->mp_reg_sr, SPIS_SR_RXEMPTY); + p->mp_fld_sr_txfull = register_get_field(p->mp_reg_sr, SPIS_SR_TXFULL); + p->mp_fld_sr_rxfull = register_get_field(p->mp_reg_sr, SPIS_SR_RXFULL); + p->mp_fld_sr_txlvl = register_get_field(p->mp_reg_sr, SPIS_SR_TXLVL); + p->mp_fld_sr_rxlvl = register_get_field(p->mp_reg_sr, SPIS_SR_RXLVL); + p->mp_fld_sr_frame_err = + register_get_field(p->mp_reg_sr, SPIS_SR_FRAME_ERR); + p->mp_fld_sr_read_err = register_get_field(p->mp_reg_sr, SPIS_SR_READ_ERR); + p->mp_fld_sr_write_err = + register_get_field(p->mp_reg_sr, SPIS_SR_WRITE_ERR); + + p->mp_reg_dtr = module_get_register(p->mp_mod_spis, SPIS_DTR); + p->mp_fld_dtr_dtr = register_get_field(p->mp_reg_dtr, SPIS_DTR_DTR); + + p->mp_reg_drr = module_get_register(p->mp_mod_spis, SPIS_DRR); + p->mp_fld_drr_drr = register_get_field(p->mp_reg_drr, SPIS_DRR_DRR); + + p->mp_reg_ram_ctrl = module_get_register(p->mp_mod_spis, SPIS_RAM_CTRL); + p->mp_fld_ram_ctrl_adr = + register_get_field(p->mp_reg_ram_ctrl, SPIS_RAM_CTRL_ADR); + p->mp_fld_ram_ctrl_cnt = + register_get_field(p->mp_reg_ram_ctrl, SPIS_RAM_CTRL_CNT); + + p->mp_reg_ram_data = module_get_register(p->mp_mod_spis, SPIS_RAM_DATA); + p->mp_fld_ram_data_data = + register_get_field(p->mp_reg_ram_data, SPIS_RAM_DATA_DATA); + + return 0; +} + +void nthw_spis_delete(nthw_spis_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_spis_t)); + free(p); + } +} + +uint32_t nthw_spis_reset(nthw_spis_t *p) +{ + register_update(p->mp_reg_srr); + field_set_val32(p->mp_fld_srr_rst, + 0x0A); /* 0x0A hardcoded value - see doc */ + register_flush(p->mp_reg_srr, 1); + + return 0; +} + +uint32_t nthw_spis_enable(nthw_spis_t *p, bool b_enable) +{ + field_update_register(p->mp_fld_cr_en); + + if (b_enable) + field_set_all(p->mp_fld_cr_en); + + else + field_clr_all(p->mp_fld_cr_en); + field_flush_register(p->mp_fld_cr_en); + + return 0; +} + +uint32_t nthw_spis_get_rx_fifo_empty(nthw_spis_t *p, bool *pb_empty) +{ + assert(pb_empty); + + *pb_empty = field_get_updated(p->mp_fld_sr_rxempty) ? true : false; + + return 0; +} + +uint32_t nthw_spis_read_rx_fifo(nthw_spis_t *p, uint32_t *p_data) +{ + assert(p_data); + + *p_data = field_get_updated(p->mp_fld_drr_drr); + + return 0; +} + +uint32_t nthw_spis_read_sensor(nthw_spis_t *p, uint8_t n_result_idx, + uint32_t *p_sensor_result) +{ + assert(p_sensor_result); + + field_set_val32(p->mp_fld_ram_ctrl_adr, n_result_idx); + field_set_val32(p->mp_fld_ram_ctrl_cnt, 1); + register_flush(p->mp_reg_ram_ctrl, 1); + + *p_sensor_result = field_get_updated(p->mp_fld_ram_data_data); + + return 0; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_spis.h b/drivers/net/ntnic/nthw/core/nthw_spis.h new file mode 100644 index 0000000000..2ebe840c9e --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_spis.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_SPIS_H__ +#define __NTHW_SPIS_H__ + +struct nthw_spis { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_spis; + int mn_instance; + + nt_register_t *mp_reg_srr; + nt_field_t *mp_fld_srr_rst; + + nt_register_t *mp_reg_cr; + nt_field_t *mp_fld_cr_loop; + nt_field_t *mp_fld_cr_en; + nt_field_t *mp_fld_cr_txrst; + nt_field_t *mp_fld_cr_rxrst; + nt_field_t *mp_fld_cr_debug; + + nt_register_t *mp_reg_sr; + nt_field_t *mp_fld_sr_done; + nt_field_t *mp_fld_sr_txempty; + nt_field_t *mp_fld_sr_rxempty; + nt_field_t *mp_fld_sr_txfull; + nt_field_t *mp_fld_sr_rxfull; + nt_field_t *mp_fld_sr_txlvl; + nt_field_t *mp_fld_sr_rxlvl; + nt_field_t *mp_fld_sr_frame_err; + nt_field_t *mp_fld_sr_read_err; + nt_field_t *mp_fld_sr_write_err; + + nt_register_t *mp_reg_dtr; + nt_field_t *mp_fld_dtr_dtr; + + nt_register_t *mp_reg_drr; + nt_field_t *mp_fld_drr_drr; + + nt_register_t *mp_reg_ram_ctrl; + nt_field_t *mp_fld_ram_ctrl_adr; + nt_field_t *mp_fld_ram_ctrl_cnt; + + nt_register_t *mp_reg_ram_data; + nt_field_t *mp_fld_ram_data_data; +}; + +typedef struct nthw_spis nthw_spis_t; +typedef struct nthw_spis nthw_spis; + +nthw_spis_t *nthw_spis_new(void); +int nthw_spis_init(nthw_spis_t *p, nt_fpga_t *p_fpga, int n_instance); +void nthw_spis_delete(nthw_spis_t *p); + +uint32_t nthw_spis_reset(nthw_spis_t *p); +uint32_t nthw_spis_enable(nthw_spis_t *p, bool b_enable); +uint32_t nthw_spis_get_rx_fifo_empty(nthw_spis_t *p, bool *pb_empty); +uint32_t nthw_spis_read_rx_fifo(nthw_spis_t *p, uint32_t *p_data); +uint32_t nthw_spis_read_sensor(nthw_spis_t *p, uint8_t n_result_idx, + uint32_t *p_sensor_result); + +#endif /* __NTHW_SPIS_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_tsm.c b/drivers/net/ntnic/nthw/core/nthw_tsm.c new file mode 100644 index 0000000000..8ea4a4c440 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_tsm.c @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_tsm.h" + +nthw_tsm_t *nthw_tsm_new(void) +{ + nthw_tsm_t *p = malloc(sizeof(nthw_tsm_t)); + + if (p) + memset(p, 0, sizeof(nthw_tsm_t)); + return p; +} + +void nthw_tsm_delete(nthw_tsm_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_tsm_t)); + free(p); + } +} + +int nthw_tsm_init(nthw_tsm_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *mod = fpga_query_module(p_fpga, MOD_TSM, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: TSM %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_tsm = mod; + + { + nt_register_t *p_reg; + + p_reg = module_get_register(p->mp_mod_tsm, TSM_CONFIG); + p->mp_fld_config_ts_format = + register_get_field(p_reg, TSM_CONFIG_TS_FORMAT); + + p_reg = module_get_register(p->mp_mod_tsm, TSM_TIMER_CTRL); + p->mp_fld_timer_ctrl_timer_en_t0 = + register_get_field(p_reg, TSM_TIMER_CTRL_TIMER_EN_T0); + p->mp_fld_timer_ctrl_timer_en_t1 = + register_get_field(p_reg, TSM_TIMER_CTRL_TIMER_EN_T1); + + p_reg = module_get_register(p->mp_mod_tsm, TSM_TIMER_T0); + p->mp_fld_timer_timer_t0_max_count = + register_get_field(p_reg, TSM_TIMER_T0_MAX_COUNT); + + p_reg = module_get_register(p->mp_mod_tsm, TSM_TIMER_T1); + p->mp_fld_timer_timer_t1_max_count = + register_get_field(p_reg, TSM_TIMER_T1_MAX_COUNT); + + p_reg = module_get_register(p->mp_mod_tsm, TSM_TIME_LO); + p->mp_reg_time_lo = module_get_register(p->mp_mod_tsm, TSM_TIME_LO); + p->mp_fld_time_lo = register_get_field(p_reg, TSM_TIME_LO_NS); + + p_reg = module_get_register(p->mp_mod_tsm, TSM_TIME_HI); + p->mp_reg_time_hi = module_get_register(p->mp_mod_tsm, TSM_TIME_HI); + p->mp_fld_time_hi = register_get_field(p_reg, TSM_TIME_HI_SEC); + + p_reg = module_get_register(p->mp_mod_tsm, TSM_TS_LO); + p->mp_reg_ts_lo = module_get_register(p->mp_mod_tsm, TSM_TS_LO); + p->mp_fld_ts_lo = register_get_field(p_reg, TSM_TS_LO_TIME); + + p_reg = module_get_register(p->mp_mod_tsm, TSM_TS_HI); + p->mp_reg_ts_hi = module_get_register(p->mp_mod_tsm, TSM_TS_HI); + p->mp_fld_ts_hi = register_get_field(p_reg, TSM_TS_HI_TIME); + } + return 0; +} + +int nthw_tsm_get_ts(nthw_tsm_t *p, uint64_t *p_ts) +{ + uint32_t n_ts_lo, n_ts_hi; + uint64_t val; + + if (!p_ts) + return -1; + + n_ts_lo = field_get_updated(p->mp_fld_ts_lo); + n_ts_hi = field_get_updated(p->mp_fld_ts_hi); + + val = ((((uint64_t)n_ts_hi) << 32UL) | n_ts_lo); + + if (p_ts) + *p_ts = val; + + return 0; +} + +int nthw_tsm_get_time(nthw_tsm_t *p, uint64_t *p_time) +{ + uint32_t n_time_lo, n_time_hi; + uint64_t val; + + if (!p_time) + return -1; + + n_time_lo = field_get_updated(p->mp_fld_time_lo); + n_time_hi = field_get_updated(p->mp_fld_time_hi); + + val = ((((uint64_t)n_time_hi) << 32UL) | n_time_lo); + + if (p_time) + *p_time = val; + + return 0; +} + +int nthw_tsm_set_time(nthw_tsm_t *p, uint64_t n_time) +{ + field_set_val_flush32(p->mp_fld_time_lo, (n_time & 0xFFFFFFFF)); + field_set_val_flush32(p->mp_fld_time_hi, + (uint32_t)((n_time >> 32) & 0xFFFFFFFF)); + return 0; +} + +int nthw_tsm_set_timer_t0_enable(nthw_tsm_t *p, bool b_enable) +{ + field_update_register(p->mp_fld_timer_ctrl_timer_en_t0); + if (b_enable) + field_set_flush(p->mp_fld_timer_ctrl_timer_en_t0); + + else + field_clr_flush(p->mp_fld_timer_ctrl_timer_en_t0); + return 0; +} + +int nthw_tsm_set_timer_t0_max_count(nthw_tsm_t *p, uint32_t n_timer_val) +{ + /* Timer T0 - stat toggle timer */ + field_update_register(p->mp_fld_timer_timer_t0_max_count); + field_set_val_flush32(p->mp_fld_timer_timer_t0_max_count, + n_timer_val); /* ns (50*1000*1000) */ + return 0; +} + +int nthw_tsm_set_timer_t1_enable(nthw_tsm_t *p, bool b_enable) +{ + field_update_register(p->mp_fld_timer_ctrl_timer_en_t1); + if (b_enable) + field_set_flush(p->mp_fld_timer_ctrl_timer_en_t1); + + else + field_clr_flush(p->mp_fld_timer_ctrl_timer_en_t1); + return 0; +} + +int nthw_tsm_set_timer_t1_max_count(nthw_tsm_t *p, uint32_t n_timer_val) +{ + /* Timer T1 - keep alive timer */ + field_update_register(p->mp_fld_timer_timer_t1_max_count); + field_set_val_flush32(p->mp_fld_timer_timer_t1_max_count, + n_timer_val); /* ns (100*1000*1000) */ + return 0; +} + +int nthw_tsm_set_config_ts_format(nthw_tsm_t *p, uint32_t n_val) +{ + field_update_register(p->mp_fld_config_ts_format); + /* 0x1: Native - 10ns units, start date: 1970-01-01. */ + field_set_val_flush32(p->mp_fld_config_ts_format, n_val); + return 0; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_tsm.h b/drivers/net/ntnic/nthw/core/nthw_tsm.h new file mode 100644 index 0000000000..590e04c312 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_tsm.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_TSM_H__ +#define __NTHW_TSM_H__ + +struct nthw_tsm { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_tsm; + int mn_instance; + + nt_field_t *mp_fld_config_ts_format; + + nt_field_t *mp_fld_timer_ctrl_timer_en_t0; + nt_field_t *mp_fld_timer_ctrl_timer_en_t1; + + nt_field_t *mp_fld_timer_timer_t0_max_count; + + nt_field_t *mp_fld_timer_timer_t1_max_count; + + nt_register_t *mp_reg_ts_lo; + nt_field_t *mp_fld_ts_lo; + + nt_register_t *mp_reg_ts_hi; + nt_field_t *mp_fld_ts_hi; + + nt_register_t *mp_reg_time_lo; + nt_field_t *mp_fld_time_lo; + + nt_register_t *mp_reg_time_hi; + nt_field_t *mp_fld_time_hi; +}; + +typedef struct nthw_tsm nthw_tsm_t; +typedef struct nthw_tsm nthw_tsm; + +nthw_tsm_t *nthw_tsm_new(void); +void nthw_tsm_delete(nthw_tsm_t *p); +int nthw_tsm_init(nthw_tsm_t *p, nt_fpga_t *p_fpga, int n_instance); + +int nthw_tsm_get_ts(nthw_tsm_t *p, uint64_t *p_ts); +int nthw_tsm_get_time(nthw_tsm_t *p, uint64_t *p_time); +int nthw_tsm_set_time(nthw_tsm_t *p, uint64_t n_time); + +int nthw_tsm_set_timer_t0_enable(nthw_tsm_t *p, bool b_enable); +int nthw_tsm_set_timer_t0_max_count(nthw_tsm_t *p, uint32_t n_timer_val); +int nthw_tsm_set_timer_t1_enable(nthw_tsm_t *p, bool b_enable); +int nthw_tsm_set_timer_t1_max_count(nthw_tsm_t *p, uint32_t n_timer_val); + +int nthw_tsm_set_config_ts_format(nthw_tsm_t *p, uint32_t n_val); + +#endif /* __NTHW_TSM_H__ */ diff --git a/drivers/net/ntnic/nthw/nthw_dbs.c b/drivers/net/ntnic/nthw/nthw_dbs.c new file mode 100644 index 0000000000..9fc853da73 --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_dbs.c @@ -0,0 +1,1301 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_dbs.h" + +#undef DBS_PRINT_REGS + +static void set_shadow_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable, + uint32_t ir, uint32_t bs); +static void flush_tx_qos_data(nthw_dbs_t *p, uint32_t index); +static void set_shadow_tx_qp_data(nthw_dbs_t *p, uint32_t index, + uint32_t virtual_port); +static void flush_tx_qp_data(nthw_dbs_t *p, uint32_t index); +static void set_shadow_tx_dr_data(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address, uint32_t host_id, + uint32_t queue_size, uint32_t port, + uint32_t header, uint32_t packed); +static void flush_tx_dr_data(nthw_dbs_t *p, uint32_t index); +static void set_shadow_rx_dr_data(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address, uint32_t host_id, + uint32_t queue_size, uint32_t header, + uint32_t packed); +static void flush_rx_dr_data(nthw_dbs_t *p, uint32_t index); +static void set_shadow_tx_uw_data(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address, uint32_t host_id, + uint32_t queue_size, uint32_t packed, + uint32_t int_enable, uint32_t vec, uint32_t istk, + uint32_t in_order); +static void flush_tx_uw_data(nthw_dbs_t *p, uint32_t index); +static void set_shadow_rx_uw_data(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address, uint32_t host_id, + uint32_t queue_size, uint32_t packed, + uint32_t int_enable, uint32_t vec, + uint32_t istk); +static void flush_rx_uw_data(nthw_dbs_t *p, uint32_t index); +static void set_shadow_rx_am_data(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address, uint32_t enable, + uint32_t host_id, uint32_t packed, + uint32_t int_enable); +static void flush_rx_am_data(nthw_dbs_t *p, uint32_t index); +static void set_shadow_tx_am_data(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address, uint32_t enable, + uint32_t host_id, uint32_t packed, + uint32_t int_enable); +static void flush_tx_am_data(nthw_dbs_t *p, uint32_t index); + +nthw_dbs_t *nthw_dbs_new(void) +{ + nthw_dbs_t *p = malloc(sizeof(nthw_dbs_t)); + + if (p) + memset(p, 0, sizeof(nthw_dbs_t)); + return p; +} + +void nthw_dbs_delete(nthw_dbs_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_dbs_t)); + free(p); + } +} + +int dbs_init(nthw_dbs_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + nt_module_t *mod = fpga_query_module(p_fpga, MOD_DBS, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: DBS %d: no such instance\n", + p_fpga->p_fpga_info->mp_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_dbs = mod; + + p->mn_param_dbs_present = fpga_get_product_param(p_fpga, NT_DBS_PRESENT, 0); + if (p->mn_param_dbs_present == 0) { + NT_LOG(WRN, NTHW, + "%s: DBS %d: logical error: module found but not flagged at present\n", + p->mp_fpga->p_fpga_info->mp_adapter_id_str, p->mn_instance); + } + + p->mp_reg_rx_control = module_get_register(p->mp_mod_dbs, DBS_RX_CONTROL); + p->mp_fld_rx_control_last_queue = + register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_LQ); + p->mp_fld_rx_control_avail_monitor_enable = + register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_AME); + p->mp_fld_rx_control_avail_monitor_scan_speed = + register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_AMS); + p->mp_fld_rx_control_used_write_enable = + register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_UWE); + p->mp_fld_rx_control_used_writer_update_speed = + register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_UWS); + p->mp_fld_rx_control_rx_queues_enable = + register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_QE); + + p->mp_reg_tx_control = module_get_register(p->mp_mod_dbs, DBS_TX_CONTROL); + p->mp_fld_tx_control_last_queue = + register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_LQ); + p->mp_fld_tx_control_avail_monitor_enable = + register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_AME); + p->mp_fld_tx_control_avail_monitor_scan_speed = + register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_AMS); + p->mp_fld_tx_control_used_write_enable = + register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_UWE); + p->mp_fld_tx_control_used_writer_update_speed = + register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_UWS); + p->mp_fld_tx_control_tx_queues_enable = + register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_QE); + + p->mp_reg_rx_init = module_get_register(p->mp_mod_dbs, DBS_RX_INIT); + p->mp_fld_rx_init_init = + register_get_field(p->mp_reg_rx_init, DBS_RX_INIT_INIT); + p->mp_fld_rx_init_queue = + register_get_field(p->mp_reg_rx_init, DBS_RX_INIT_QUEUE); + p->mp_fld_rx_init_busy = + register_get_field(p->mp_reg_rx_init, DBS_RX_INIT_BUSY); + + p->mp_reg_rx_init_val = module_query_register(p->mp_mod_dbs, DBS_RX_INIT_VAL); + if (p->mp_reg_rx_init_val) { + p->mp_fld_rx_init_val_idx = register_query_field(p->mp_reg_rx_init_val, + DBS_RX_INIT_VAL_IDX); + p->mp_fld_rx_init_val_ptr = register_query_field(p->mp_reg_rx_init_val, + DBS_RX_INIT_VAL_PTR); + } + + p->mp_reg_rx_ptr = module_query_register(p->mp_mod_dbs, DBS_RX_PTR); + if (p->mp_reg_rx_ptr) { + p->mp_fld_rx_ptr_ptr = + register_query_field(p->mp_reg_rx_ptr, DBS_RX_PTR_PTR); + p->mp_fld_rx_ptr_queue = + register_query_field(p->mp_reg_rx_ptr, DBS_RX_PTR_QUEUE); + p->mp_fld_rx_ptr_valid = + register_query_field(p->mp_reg_rx_ptr, DBS_RX_PTR_VALID); + } + + p->mp_reg_tx_init = module_get_register(p->mp_mod_dbs, DBS_TX_INIT); + p->mp_fld_tx_init_init = + register_get_field(p->mp_reg_tx_init, DBS_TX_INIT_INIT); + p->mp_fld_tx_init_queue = + register_get_field(p->mp_reg_tx_init, DBS_TX_INIT_QUEUE); + p->mp_fld_tx_init_busy = + register_get_field(p->mp_reg_tx_init, DBS_TX_INIT_BUSY); + + p->mp_reg_tx_init_val = module_query_register(p->mp_mod_dbs, DBS_TX_INIT_VAL); + if (p->mp_reg_tx_init_val) { + p->mp_fld_tx_init_val_idx = register_query_field(p->mp_reg_tx_init_val, + DBS_TX_INIT_VAL_IDX); + p->mp_fld_tx_init_val_ptr = register_query_field(p->mp_reg_tx_init_val, + DBS_TX_INIT_VAL_PTR); + } + + p->mp_reg_tx_ptr = module_query_register(p->mp_mod_dbs, DBS_TX_PTR); + if (p->mp_reg_tx_ptr) { + p->mp_fld_tx_ptr_ptr = + register_query_field(p->mp_reg_tx_ptr, DBS_TX_PTR_PTR); + p->mp_fld_tx_ptr_queue = + register_query_field(p->mp_reg_tx_ptr, DBS_TX_PTR_QUEUE); + p->mp_fld_tx_ptr_valid = + register_query_field(p->mp_reg_tx_ptr, DBS_TX_PTR_VALID); + } + + p->mp_reg_rx_idle = module_query_register(p->mp_mod_dbs, DBS_RX_IDLE); + if (p->mp_reg_rx_idle) { + p->mp_fld_rx_idle_idle = + register_query_field(p->mp_reg_rx_idle, DBS_RX_IDLE_IDLE); + p->mp_fld_rx_idle_queue = + register_query_field(p->mp_reg_rx_idle, DBS_RX_IDLE_QUEUE); + p->mp_fld_rx_idle_busy = + register_query_field(p->mp_reg_rx_idle, DBS_RX_IDLE_BUSY); + } + + p->mp_reg_tx_idle = module_query_register(p->mp_mod_dbs, DBS_TX_IDLE); + if (p->mp_reg_tx_idle) { + p->mp_fld_tx_idle_idle = + register_query_field(p->mp_reg_tx_idle, DBS_TX_IDLE_IDLE); + p->mp_fld_tx_idle_queue = + register_query_field(p->mp_reg_tx_idle, DBS_TX_IDLE_QUEUE); + p->mp_fld_tx_idle_busy = + register_query_field(p->mp_reg_tx_idle, DBS_TX_IDLE_BUSY); + } + + p->mp_reg_rx_avail_monitor_control = + module_get_register(p->mp_mod_dbs, DBS_RX_AM_CTRL); + p->mp_fld_rx_avail_monitor_control_adr = + register_get_field(p->mp_reg_rx_avail_monitor_control, DBS_RX_AM_CTRL_ADR); + p->mp_fld_rx_avail_monitor_control_cnt = + register_get_field(p->mp_reg_rx_avail_monitor_control, DBS_RX_AM_CTRL_CNT); + + p->mp_reg_rx_avail_monitor_data = + module_get_register(p->mp_mod_dbs, DBS_RX_AM_DATA); + p->mp_fld_rx_avail_monitor_data_guest_physical_address = + register_get_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_GPA); + p->mp_fld_rx_avail_monitor_data_enable = + register_get_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_ENABLE); + p->mp_fld_rx_avail_monitor_data_host_id = + register_get_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_HID); + p->mp_fld_rx_avail_monitor_data_packed = + register_query_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_PCKED); + p->mp_fld_rx_avail_monitor_data_int = + register_query_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_INT); + + p->mp_reg_tx_avail_monitor_control = + module_get_register(p->mp_mod_dbs, DBS_TX_AM_CTRL); + p->mp_fld_tx_avail_monitor_control_adr = + register_get_field(p->mp_reg_tx_avail_monitor_control, DBS_TX_AM_CTRL_ADR); + p->mp_fld_tx_avail_monitor_control_cnt = + register_get_field(p->mp_reg_tx_avail_monitor_control, DBS_TX_AM_CTRL_CNT); + + p->mp_reg_tx_avail_monitor_data = + module_get_register(p->mp_mod_dbs, DBS_TX_AM_DATA); + p->mp_fld_tx_avail_monitor_data_guest_physical_address = + register_get_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_GPA); + p->mp_fld_tx_avail_monitor_data_enable = + register_get_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_ENABLE); + p->mp_fld_tx_avail_monitor_data_host_id = + register_get_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_HID); + p->mp_fld_tx_avail_monitor_data_packed = + register_query_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_PCKED); + p->mp_fld_tx_avail_monitor_data_int = + register_query_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_INT); + + p->mp_reg_rx_used_writer_control = + module_get_register(p->mp_mod_dbs, DBS_RX_UW_CTRL); + p->mp_fld_rx_used_writer_control_adr = + register_get_field(p->mp_reg_rx_used_writer_control, DBS_RX_UW_CTRL_ADR); + p->mp_fld_rx_used_writer_control_cnt = + register_get_field(p->mp_reg_rx_used_writer_control, DBS_RX_UW_CTRL_CNT); + + p->mp_reg_rx_used_writer_data = + module_get_register(p->mp_mod_dbs, DBS_RX_UW_DATA); + p->mp_fld_rx_used_writer_data_guest_physical_address = + register_get_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_GPA); + p->mp_fld_rx_used_writer_data_host_id = + register_get_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_HID); + p->mp_fld_rx_used_writer_data_queue_size = + register_get_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_QS); + p->mp_fld_rx_used_writer_data_packed = + register_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_PCKED); + p->mp_fld_rx_used_writer_data_int = + register_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_INT); + p->mp_fld_rx_used_writer_data_vec = + register_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_VEC); + p->mp_fld_rx_used_writer_data_istk = + register_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_ISTK); + + p->mp_reg_tx_used_writer_control = + module_get_register(p->mp_mod_dbs, DBS_TX_UW_CTRL); + p->mp_fld_tx_used_writer_control_adr = + register_get_field(p->mp_reg_tx_used_writer_control, DBS_TX_UW_CTRL_ADR); + p->mp_fld_tx_used_writer_control_cnt = + register_get_field(p->mp_reg_tx_used_writer_control, DBS_TX_UW_CTRL_CNT); + + p->mp_reg_tx_used_writer_data = + module_get_register(p->mp_mod_dbs, DBS_TX_UW_DATA); + p->mp_fld_tx_used_writer_data_guest_physical_address = + register_get_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_GPA); + p->mp_fld_tx_used_writer_data_host_id = + register_get_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_HID); + p->mp_fld_tx_used_writer_data_queue_size = + register_get_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_QS); + p->mp_fld_tx_used_writer_data_packed = + register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_PCKED); + p->mp_fld_tx_used_writer_data_int = + register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_INT); + p->mp_fld_tx_used_writer_data_vec = + register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_VEC); + p->mp_fld_tx_used_writer_data_istk = + register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_ISTK); + p->mp_fld_tx_used_writer_data_in_order = + register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_INO); + + p->mp_reg_rx_descriptor_reader_control = + module_get_register(p->mp_mod_dbs, DBS_RX_DR_CTRL); + p->mp_fld_rx_descriptor_reader_control_adr = + register_get_field(p->mp_reg_rx_descriptor_reader_control, DBS_RX_DR_CTRL_ADR); + p->mp_fld_rx_descriptor_reader_control_cnt = + register_get_field(p->mp_reg_rx_descriptor_reader_control, DBS_RX_DR_CTRL_CNT); + + p->mp_reg_rx_descriptor_reader_data = + module_get_register(p->mp_mod_dbs, DBS_RX_DR_DATA); + p->mp_fld_rx_descriptor_reader_data_guest_physical_address = + register_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_GPA); + p->mp_fld_rx_descriptor_reader_data_host_id = + register_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_HID); + p->mp_fld_rx_descriptor_reader_data_queue_size = + register_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_QS); + p->mp_fld_rx_descriptor_reader_data_header = + register_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_HDR); + p->mp_fld_rx_descriptor_reader_data_packed = + register_query_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_PCKED); + + p->mp_reg_tx_descriptor_reader_control = + module_get_register(p->mp_mod_dbs, DBS_TX_DR_CTRL); + p->mp_fld_tx_descriptor_reader_control_adr = + register_get_field(p->mp_reg_tx_descriptor_reader_control, DBS_TX_DR_CTRL_ADR); + p->mp_fld_tx_descriptor_reader_control_cnt = + register_get_field(p->mp_reg_tx_descriptor_reader_control, DBS_TX_DR_CTRL_CNT); + + p->mp_reg_tx_descriptor_reader_data = + module_get_register(p->mp_mod_dbs, DBS_TX_DR_DATA); + p->mp_fld_tx_descriptor_reader_data_guest_physical_address = + register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_GPA); + p->mp_fld_tx_descriptor_reader_data_host_id = + register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_HID); + p->mp_fld_tx_descriptor_reader_data_queue_size = + register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_QS); + p->mp_fld_tx_descriptor_reader_data_header = + register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_HDR); + p->mp_fld_tx_descriptor_reader_data_port = + register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_PORT); + p->mp_fld_tx_descriptor_reader_data_packed = + register_query_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_PCKED); + + p->mp_reg_tx_queue_property_control = + module_get_register(p->mp_mod_dbs, DBS_TX_QP_CTRL); + p->mp_fld_tx_queue_property_control_adr = + register_get_field(p->mp_reg_tx_queue_property_control, DBS_TX_QP_CTRL_ADR); + p->mp_fld_tx_queue_property_control_cnt = + register_get_field(p->mp_reg_tx_queue_property_control, DBS_TX_QP_CTRL_CNT); + + p->mp_reg_tx_queue_property_data = + module_get_register(p->mp_mod_dbs, DBS_TX_QP_DATA); + p->mp_fld_tx_queue_property_data_v_port = + register_get_field(p->mp_reg_tx_queue_property_data, DBS_TX_QP_DATA_VPORT); + + /* HW QoS Tx rate limiting policing RFC2697/RFC4111 */ + p->mp_reg_tx_queue_qos_control = + module_query_register(p->mp_mod_dbs, DBS_TX_QOS_CTRL); + p->mp_reg_tx_queue_qos_data = + module_query_register(p->mp_mod_dbs, DBS_TX_QOS_DATA); + if (p->mp_reg_tx_queue_qos_control) { + p->mp_reg_tx_queue_qos_control_adr = + register_query_field(p->mp_reg_tx_queue_qos_control, DBS_TX_QOS_CTRL_ADR); + p->mp_reg_tx_queue_qos_control_cnt = + register_query_field(p->mp_reg_tx_queue_qos_control, DBS_TX_QOS_CTRL_CNT); + + if (p->mp_reg_tx_queue_qos_data) { + p->mp_reg_tx_queue_qos_data_en = + register_query_field(p->mp_reg_tx_queue_qos_data, + DBS_TX_QOS_DATA_EN); + p->mp_reg_tx_queue_qos_data_ir = + register_query_field(p->mp_reg_tx_queue_qos_data, + DBS_TX_QOS_DATA_IR); + p->mp_reg_tx_queue_qos_data_bs = + register_query_field(p->mp_reg_tx_queue_qos_data, + DBS_TX_QOS_DATA_BS); + } + } + + p->mp_reg_tx_queue_qos_rate = + module_query_register(p->mp_mod_dbs, DBS_TX_QOS_RATE); + if (p->mp_reg_tx_queue_qos_rate) { + p->mp_reg_tx_queue_qos_rate_mul = + register_query_field(p->mp_reg_tx_queue_qos_rate, DBS_TX_QOS_RATE_MUL); + p->mp_reg_tx_queue_qos_rate_div = + register_query_field(p->mp_reg_tx_queue_qos_rate, DBS_TX_QOS_RATE_DIV); + } + + return 0; +} + +int dbs_reset_rx_control(nthw_dbs_t *p) +{ + field_set_val32(p->mp_fld_rx_control_last_queue, 0); + field_set_val32(p->mp_fld_rx_control_avail_monitor_enable, 0); + field_set_val32(p->mp_fld_rx_control_avail_monitor_scan_speed, 8); + field_set_val32(p->mp_fld_rx_control_used_write_enable, 0); + field_set_val32(p->mp_fld_rx_control_used_writer_update_speed, 5); + field_set_val32(p->mp_fld_rx_control_rx_queues_enable, 0); + register_flush(p->mp_reg_rx_control, 1); + return 0; +} + +int dbs_reset_tx_control(nthw_dbs_t *p) +{ + field_set_val32(p->mp_fld_tx_control_last_queue, 0); + field_set_val32(p->mp_fld_tx_control_avail_monitor_enable, 0); + field_set_val32(p->mp_fld_tx_control_avail_monitor_scan_speed, 5); + field_set_val32(p->mp_fld_tx_control_used_write_enable, 0); + field_set_val32(p->mp_fld_tx_control_used_writer_update_speed, 8); + field_set_val32(p->mp_fld_tx_control_tx_queues_enable, 0); + register_flush(p->mp_reg_tx_control, 1); + return 0; +} + +void dbs_reset(nthw_dbs_t *p) +{ + uint32_t i; + + NT_LOG(DBG, NTHW, "NthwDbs::%s: resetting DBS", __func__); + + dbs_reset_rx_control(p); + dbs_reset_tx_control(p); + + /* Reset RX memory banks and shado */ + for (i = 0; i < NT_DBS_RX_QUEUES_MAX; ++i) { + set_shadow_rx_am_data(p, i, 0, 0, 0, 0, 0); + flush_rx_am_data(p, i); + + set_shadow_rx_uw_data(p, i, 0, 0, 0, 0, 0, 0, 0); + flush_rx_uw_data(p, i); + + set_shadow_rx_dr_data(p, i, 0, 0, 0, 0, 0); + flush_rx_dr_data(p, i); + } + + /* Reset TX memory banks and shado */ + for (i = 0; i < NT_DBS_TX_QUEUES_MAX; ++i) { + set_shadow_tx_am_data(p, i, 0, 0, 0, 0, 0); + flush_tx_am_data(p, i); + + set_shadow_tx_uw_data(p, i, 0, 0, 0, 0, 0, 0, 0, 0); + flush_tx_uw_data(p, i); + + set_shadow_tx_dr_data(p, i, 0, 0, 0, 0, 0, 0); + flush_tx_dr_data(p, i); + + set_shadow_tx_qp_data(p, i, 0); + flush_tx_qp_data(p, i); + + set_shadow_tx_qos_data(p, i, 0, 0, 0); + flush_tx_qos_data(p, i); + } +} + +int set_rx_control(nthw_dbs_t *p, uint32_t last_queue, + uint32_t avail_monitor_enable, uint32_t avail_monitor_speed, + uint32_t used_write_enable, uint32_t used_write_speed, + uint32_t rx_queue_enable) +{ +#ifdef DBS_PRINT_REGS + printf("last_queue %u\n", last_queue); + printf("avail_monitor_enable %u\n", avail_monitor_enable); + printf("avail_monitor_speed %u\n", avail_monitor_speed); + printf("used_write_enable %u\n", used_write_enable); + printf("used_write_speed %u\n", used_write_speed); + printf("rx_queue_enable %u\n", rx_queue_enable); +#endif + + field_set_val32(p->mp_fld_rx_control_last_queue, last_queue); + field_set_val32(p->mp_fld_rx_control_avail_monitor_enable, avail_monitor_enable); + field_set_val32(p->mp_fld_rx_control_avail_monitor_scan_speed, + avail_monitor_speed); + field_set_val32(p->mp_fld_rx_control_used_write_enable, used_write_enable); + field_set_val32(p->mp_fld_rx_control_used_writer_update_speed, used_write_speed); + field_set_val32(p->mp_fld_rx_control_rx_queues_enable, rx_queue_enable); + register_flush(p->mp_reg_rx_control, 1); + return 0; +} + +int nthw_dbs_get_rx_control(nthw_dbs_t *p, uint32_t *last_queue, + uint32_t *avail_monitor_enable, + uint32_t *avail_monitor_speed, uint32_t *used_write_enable, + uint32_t *used_write_speed, uint32_t *rx_queue_enable) +{ + *last_queue = field_get_val32(p->mp_fld_rx_control_last_queue); + *avail_monitor_enable = + field_get_val32(p->mp_fld_rx_control_avail_monitor_enable); + *avail_monitor_speed = + field_get_val32(p->mp_fld_rx_control_avail_monitor_scan_speed); + *used_write_enable = field_get_val32(p->mp_fld_rx_control_used_write_enable); + *used_write_speed = + field_get_val32(p->mp_fld_rx_control_used_writer_update_speed); + *rx_queue_enable = field_get_val32(p->mp_fld_rx_control_rx_queues_enable); + return 0; +} + +int set_tx_control(nthw_dbs_t *p, uint32_t last_queue, + uint32_t avail_monitor_enable, uint32_t avail_monitor_speed, + uint32_t used_write_enable, uint32_t used_write_speed, + uint32_t tx_queue_enable) +{ +#ifdef DBS_PRINT_REGS + printf("last_queue %u\n", last_queue); + printf("avail_monitor_enable %u\n", avail_monitor_enable); + printf("avail_monitor_speed %u\n", avail_monitor_speed); + printf("used_write_enable %u\n", used_write_enable); + printf("used_write_speed %u\n", used_write_speed); +#endif + + field_set_val32(p->mp_fld_tx_control_last_queue, last_queue); + field_set_val32(p->mp_fld_tx_control_avail_monitor_enable, avail_monitor_enable); + field_set_val32(p->mp_fld_tx_control_avail_monitor_scan_speed, + avail_monitor_speed); + field_set_val32(p->mp_fld_tx_control_used_write_enable, used_write_enable); + field_set_val32(p->mp_fld_tx_control_used_writer_update_speed, used_write_speed); + field_set_val32(p->mp_fld_tx_control_tx_queues_enable, tx_queue_enable); + register_flush(p->mp_reg_tx_control, 1); + return 0; +} + +int nthw_dbs_get_tx_control(nthw_dbs_t *p, uint32_t *last_queue, + uint32_t *avail_monitor_enable, + uint32_t *avail_monitor_speed, uint32_t *used_write_enable, + uint32_t *used_write_speed, uint32_t *tx_queue_enable) +{ + *last_queue = field_get_val32(p->mp_fld_tx_control_last_queue); + *avail_monitor_enable = + field_get_val32(p->mp_fld_tx_control_avail_monitor_enable); + *avail_monitor_speed = + field_get_val32(p->mp_fld_tx_control_avail_monitor_scan_speed); + *used_write_enable = field_get_val32(p->mp_fld_tx_control_used_write_enable); + *used_write_speed = + field_get_val32(p->mp_fld_tx_control_used_writer_update_speed); + *tx_queue_enable = field_get_val32(p->mp_fld_tx_control_tx_queues_enable); + return 0; +} + +int set_rx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr, + uint32_t init, uint32_t queue) +{ + if (p->mp_reg_rx_init_val) { + field_set_val32(p->mp_fld_rx_init_val_idx, start_idx); + field_set_val32(p->mp_fld_rx_init_val_ptr, start_ptr); + register_flush(p->mp_reg_rx_init_val, 1); + } + field_set_val32(p->mp_fld_rx_init_init, init); + field_set_val32(p->mp_fld_rx_init_queue, queue); + register_flush(p->mp_reg_rx_init, 1); + return 0; +} + +int get_rx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy) +{ + *init = field_get_val32(p->mp_fld_rx_init_init); + *queue = field_get_val32(p->mp_fld_rx_init_queue); + *busy = field_get_val32(p->mp_fld_rx_init_busy); + return 0; +} + +int set_tx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr, + uint32_t init, uint32_t queue) +{ + if (p->mp_reg_tx_init_val) { + field_set_val32(p->mp_fld_tx_init_val_idx, start_idx); + field_set_val32(p->mp_fld_tx_init_val_ptr, start_ptr); + register_flush(p->mp_reg_tx_init_val, 1); + } + field_set_val32(p->mp_fld_tx_init_init, init); + field_set_val32(p->mp_fld_tx_init_queue, queue); + register_flush(p->mp_reg_tx_init, 1); + return 0; +} + +int get_tx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy) +{ + *init = field_get_val32(p->mp_fld_tx_init_init); + *queue = field_get_val32(p->mp_fld_tx_init_queue); + *busy = field_get_val32(p->mp_fld_tx_init_busy); + return 0; +} + +int set_rx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue) + +{ + if (!p->mp_reg_rx_idle) + return -ENOTSUP; + + field_set_val32(p->mp_fld_rx_idle_idle, idle); + field_set_val32(p->mp_fld_rx_idle_queue, queue); + register_flush(p->mp_reg_rx_idle, 1); + return 0; +} + +int get_rx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy) +{ + if (!p->mp_reg_rx_idle) + return -ENOTSUP; + + *idle = field_get_updated(p->mp_fld_rx_idle_idle); + *queue = 0; + *busy = field_get_updated(p->mp_fld_rx_idle_busy); + return 0; +} + +int set_tx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue) + +{ + if (!p->mp_reg_tx_idle) + return -ENOTSUP; + + field_set_val32(p->mp_fld_tx_idle_idle, idle); + field_set_val32(p->mp_fld_tx_idle_queue, queue); + register_flush(p->mp_reg_tx_idle, 1); + return 0; +} + +int get_tx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy) +{ + if (!p->mp_reg_tx_idle) + return -ENOTSUP; + + *idle = field_get_updated(p->mp_fld_tx_idle_idle); + *queue = 0; + *busy = field_get_updated(p->mp_fld_tx_idle_busy); + return 0; +} + +int set_rx_ptr_queue(nthw_dbs_t *p, uint32_t queue) +{ + if (!p->mp_reg_rx_ptr) + return -ENOTSUP; + + field_set_val32(p->mp_fld_rx_ptr_queue, queue); + register_flush(p->mp_reg_rx_ptr, 1); + return 0; +} + +int get_rx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid) +{ + if (!p->mp_reg_rx_ptr) + return -ENOTSUP; + + *ptr = field_get_updated(p->mp_fld_rx_ptr_ptr); + *queue = 0; + *valid = field_get_updated(p->mp_fld_rx_ptr_valid); + return 0; +} + +int set_tx_ptr_queue(nthw_dbs_t *p, uint32_t queue) +{ + if (!p->mp_reg_tx_ptr) + return -ENOTSUP; + + field_set_val32(p->mp_fld_tx_ptr_queue, queue); + register_flush(p->mp_reg_tx_ptr, 1); + return 0; +} + +int get_tx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid) +{ + if (!p->mp_reg_tx_ptr) + return -ENOTSUP; + + *ptr = field_get_updated(p->mp_fld_tx_ptr_ptr); + *queue = 0; + *valid = field_get_updated(p->mp_fld_tx_ptr_valid); + return 0; +} + +static void set_rx_am_data_index(nthw_dbs_t *p, uint32_t index) +{ + field_set_val32(p->mp_fld_rx_avail_monitor_control_adr, index); + field_set_val32(p->mp_fld_rx_avail_monitor_control_cnt, 1); + register_flush(p->mp_reg_rx_avail_monitor_control, 1); +} + +static void +set_shadow_rx_am_data_guest_physical_address(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address) +{ + p->m_rx_am_shadow[index].guest_physical_address = guest_physical_address; +} + +static void nthw_dbs_set_shadow_rx_am_data_enable(nthw_dbs_t *p, uint32_t index, + uint32_t enable) +{ + p->m_rx_am_shadow[index].enable = enable; +} + +static void set_shadow_rx_am_data_host_id(nthw_dbs_t *p, uint32_t index, + uint32_t host_id) +{ + p->m_rx_am_shadow[index].host_id = host_id; +} + +static void set_shadow_rx_am_data_packed(nthw_dbs_t *p, uint32_t index, + uint32_t packed) +{ + p->m_rx_am_shadow[index].packed = packed; +} + +static void set_shadow_rx_am_data_int_enable(nthw_dbs_t *p, uint32_t index, + uint32_t int_enable) +{ + p->m_rx_am_shadow[index].int_enable = int_enable; +} + +static void set_shadow_rx_am_data(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address, uint32_t enable, + uint32_t host_id, uint32_t packed, + uint32_t int_enable) +{ + set_shadow_rx_am_data_guest_physical_address(p, index, guest_physical_address); + nthw_dbs_set_shadow_rx_am_data_enable(p, index, enable); + set_shadow_rx_am_data_host_id(p, index, host_id); + set_shadow_rx_am_data_packed(p, index, packed); + set_shadow_rx_am_data_int_enable(p, index, int_enable); +} + +static void flush_rx_am_data(nthw_dbs_t *p, uint32_t index) +{ + field_set_val(p->mp_fld_rx_avail_monitor_data_guest_physical_address, + (uint32_t *)&p->m_rx_am_shadow[index].guest_physical_address, + 2); + field_set_val32(p->mp_fld_rx_avail_monitor_data_enable, + p->m_rx_am_shadow[index].enable); + field_set_val32(p->mp_fld_rx_avail_monitor_data_host_id, + p->m_rx_am_shadow[index].host_id); + if (p->mp_fld_rx_avail_monitor_data_packed) { + field_set_val32(p->mp_fld_rx_avail_monitor_data_packed, + p->m_rx_am_shadow[index].packed); + } + if (p->mp_fld_rx_avail_monitor_data_int) { + field_set_val32(p->mp_fld_rx_avail_monitor_data_int, + p->m_rx_am_shadow[index].int_enable); + } + + set_rx_am_data_index(p, index); + register_flush(p->mp_reg_rx_avail_monitor_data, 1); +} + +int set_rx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address, + uint32_t enable, uint32_t host_id, uint32_t packed, + uint32_t int_enable) +{ + if (!p->mp_reg_rx_avail_monitor_data) + return -ENOTSUP; + + set_shadow_rx_am_data(p, index, guest_physical_address, enable, host_id, + packed, int_enable); + flush_rx_am_data(p, index); + return 0; +} + +static void set_tx_am_data_index(nthw_dbs_t *p, uint32_t index) +{ + field_set_val32(p->mp_fld_tx_avail_monitor_control_adr, index); + field_set_val32(p->mp_fld_tx_avail_monitor_control_cnt, 1); + register_flush(p->mp_reg_tx_avail_monitor_control, 1); +} + +static void set_shadow_tx_am_data(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address, uint32_t enable, + uint32_t host_id, uint32_t packed, + uint32_t int_enable) +{ + p->m_tx_am_shadow[index].guest_physical_address = guest_physical_address; + p->m_tx_am_shadow[index].enable = enable; + p->m_tx_am_shadow[index].host_id = host_id; + p->m_tx_am_shadow[index].packed = packed; + p->m_tx_am_shadow[index].int_enable = int_enable; +} + +static void flush_tx_am_data(nthw_dbs_t *p, uint32_t index) +{ + field_set_val(p->mp_fld_tx_avail_monitor_data_guest_physical_address, + (uint32_t *)&p->m_tx_am_shadow[index].guest_physical_address, + 2); + field_set_val32(p->mp_fld_tx_avail_monitor_data_enable, + p->m_tx_am_shadow[index].enable); + field_set_val32(p->mp_fld_tx_avail_monitor_data_host_id, + p->m_tx_am_shadow[index].host_id); + if (p->mp_fld_tx_avail_monitor_data_packed) { + field_set_val32(p->mp_fld_tx_avail_monitor_data_packed, + p->m_tx_am_shadow[index].packed); + } + if (p->mp_fld_tx_avail_monitor_data_int) { + field_set_val32(p->mp_fld_tx_avail_monitor_data_int, + p->m_tx_am_shadow[index].int_enable); + } + + set_tx_am_data_index(p, index); + register_flush(p->mp_reg_tx_avail_monitor_data, 1); +} + +int set_tx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address, + uint32_t enable, uint32_t host_id, uint32_t packed, + uint32_t int_enable) +{ + if (!p->mp_reg_tx_avail_monitor_data) + return -ENOTSUP; + + set_shadow_tx_am_data(p, index, guest_physical_address, enable, host_id, + packed, int_enable); + flush_tx_am_data(p, index); + return 0; +} + +static void set_rx_uw_data_index(nthw_dbs_t *p, uint32_t index) +{ + field_set_val32(p->mp_fld_rx_used_writer_control_adr, index); + field_set_val32(p->mp_fld_rx_used_writer_control_cnt, 1); + register_flush(p->mp_reg_rx_used_writer_control, 1); +} + +static void +set_shadow_rx_uw_data_guest_physical_address(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address) +{ + p->m_rx_uw_shadow[index].guest_physical_address = guest_physical_address; +} + +static void set_shadow_rx_uw_data_host_id(nthw_dbs_t *p, uint32_t index, + uint32_t host_id) +{ + p->m_rx_uw_shadow[index].host_id = host_id; +} + +static void set_shadow_rx_uw_data_queue_size(nthw_dbs_t *p, uint32_t index, + uint32_t queue_size) +{ + p->m_rx_uw_shadow[index].queue_size = queue_size; +} + +static void set_shadow_rx_uw_data_packed(nthw_dbs_t *p, uint32_t index, + uint32_t packed) +{ + p->m_rx_uw_shadow[index].packed = packed; +} + +static void set_shadow_rx_uw_data_int_enable(nthw_dbs_t *p, uint32_t index, + uint32_t int_enable) +{ + p->m_rx_uw_shadow[index].int_enable = int_enable; +} + +static void set_shadow_rx_uw_data_vec(nthw_dbs_t *p, uint32_t index, uint32_t vec) +{ + p->m_rx_uw_shadow[index].vec = vec; +} + +static void set_shadow_rx_uw_data_istk(nthw_dbs_t *p, uint32_t index, uint32_t istk) +{ + p->m_rx_uw_shadow[index].istk = istk; +} + +static void set_shadow_rx_uw_data(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address, uint32_t host_id, + uint32_t queue_size, uint32_t packed, + uint32_t int_enable, uint32_t vec, uint32_t istk) +{ + set_shadow_rx_uw_data_guest_physical_address(p, index, guest_physical_address); + set_shadow_rx_uw_data_host_id(p, index, host_id); + set_shadow_rx_uw_data_queue_size(p, index, queue_size); + set_shadow_rx_uw_data_packed(p, index, packed); + set_shadow_rx_uw_data_int_enable(p, index, int_enable); + set_shadow_rx_uw_data_vec(p, index, vec); + set_shadow_rx_uw_data_istk(p, index, istk); +} + +static void flush_rx_uw_data(nthw_dbs_t *p, uint32_t index) +{ + field_set_val(p->mp_fld_rx_used_writer_data_guest_physical_address, + (uint32_t *)&p->m_rx_uw_shadow[index].guest_physical_address, + 2); + field_set_val32(p->mp_fld_rx_used_writer_data_host_id, + p->m_rx_uw_shadow[index].host_id); + if (module_is_version_newer(p->mp_mod_dbs, 0, 8)) { + field_set_val32(p->mp_fld_rx_used_writer_data_queue_size, + (1U << p->m_rx_uw_shadow[index].queue_size) - 1U); + } else { + field_set_val32(p->mp_fld_rx_used_writer_data_queue_size, + p->m_rx_uw_shadow[index].queue_size); + } + if (p->mp_fld_rx_used_writer_data_packed) { + field_set_val32(p->mp_fld_rx_used_writer_data_packed, + p->m_rx_uw_shadow[index].packed); + } + if (p->mp_fld_rx_used_writer_data_int) { + field_set_val32(p->mp_fld_rx_used_writer_data_int, + p->m_rx_uw_shadow[index].int_enable); + field_set_val32(p->mp_fld_rx_used_writer_data_vec, + p->m_rx_uw_shadow[index].vec); + field_set_val32(p->mp_fld_rx_used_writer_data_istk, + p->m_rx_uw_shadow[index].istk); + } + + set_rx_uw_data_index(p, index); + register_flush(p->mp_reg_rx_used_writer_data, 1); +} + +int set_rx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address, + uint32_t host_id, uint32_t queue_size, uint32_t packed, + uint32_t int_enable, uint32_t vec, uint32_t istk) +{ + if (!p->mp_reg_rx_used_writer_data) + return -ENOTSUP; + + set_shadow_rx_uw_data(p, index, guest_physical_address, host_id, queue_size, + packed, int_enable, vec, istk); + flush_rx_uw_data(p, index); + return 0; +} + +static void set_tx_uw_data_index(nthw_dbs_t *p, uint32_t index) +{ + field_set_val32(p->mp_fld_tx_used_writer_control_adr, index); + field_set_val32(p->mp_fld_tx_used_writer_control_cnt, 1); + register_flush(p->mp_reg_tx_used_writer_control, 1); +} + +static void +set_shadow_tx_uw_data_guest_physical_address(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address) +{ + p->m_tx_uw_shadow[index].guest_physical_address = guest_physical_address; +} + +static void set_shadow_tx_uw_data_host_id(nthw_dbs_t *p, uint32_t index, + uint32_t host_id) +{ + p->m_tx_uw_shadow[index].host_id = host_id; +} + +static void set_shadow_tx_uw_data_queue_size(nthw_dbs_t *p, uint32_t index, + uint32_t queue_size) +{ + p->m_tx_uw_shadow[index].queue_size = queue_size; +} + +static void set_shadow_tx_uw_data_packed(nthw_dbs_t *p, uint32_t index, + uint32_t packed) +{ + p->m_tx_uw_shadow[index].packed = packed; +} + +static void set_shadow_tx_uw_data_int_enable(nthw_dbs_t *p, uint32_t index, + uint32_t int_enable) +{ + p->m_tx_uw_shadow[index].int_enable = int_enable; +} + +static void set_shadow_tx_uw_data_vec(nthw_dbs_t *p, uint32_t index, uint32_t vec) +{ + p->m_tx_uw_shadow[index].vec = vec; +} + +static void set_shadow_tx_uw_data_istk(nthw_dbs_t *p, uint32_t index, uint32_t istk) +{ + p->m_tx_uw_shadow[index].istk = istk; +} + +static void set_shadow_tx_uw_data_in_order(nthw_dbs_t *p, uint32_t index, + uint32_t in_order) +{ + p->m_tx_uw_shadow[index].in_order = in_order; +} + +static void set_shadow_tx_uw_data(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address, uint32_t host_id, + uint32_t queue_size, uint32_t packed, + uint32_t int_enable, uint32_t vec, uint32_t istk, + uint32_t in_order) +{ + set_shadow_tx_uw_data_guest_physical_address(p, index, guest_physical_address); + set_shadow_tx_uw_data_host_id(p, index, host_id); + set_shadow_tx_uw_data_queue_size(p, index, queue_size); + set_shadow_tx_uw_data_packed(p, index, packed); + set_shadow_tx_uw_data_int_enable(p, index, int_enable); + set_shadow_tx_uw_data_vec(p, index, vec); + set_shadow_tx_uw_data_istk(p, index, istk); + set_shadow_tx_uw_data_in_order(p, index, in_order); +} + +static void flush_tx_uw_data(nthw_dbs_t *p, uint32_t index) +{ + field_set_val(p->mp_fld_tx_used_writer_data_guest_physical_address, + (uint32_t *)&p->m_tx_uw_shadow[index].guest_physical_address, + 2); + field_set_val32(p->mp_fld_tx_used_writer_data_host_id, + p->m_tx_uw_shadow[index].host_id); + if (module_is_version_newer(p->mp_mod_dbs, 0, 8)) { + field_set_val32(p->mp_fld_tx_used_writer_data_queue_size, + (1U << p->m_tx_uw_shadow[index].queue_size) - 1U); + } else { + field_set_val32(p->mp_fld_tx_used_writer_data_queue_size, + p->m_tx_uw_shadow[index].queue_size); + } + if (p->mp_fld_tx_used_writer_data_packed) { + field_set_val32(p->mp_fld_tx_used_writer_data_packed, + p->m_tx_uw_shadow[index].packed); + } + if (p->mp_fld_tx_used_writer_data_int) { + field_set_val32(p->mp_fld_tx_used_writer_data_int, + p->m_tx_uw_shadow[index].int_enable); + field_set_val32(p->mp_fld_tx_used_writer_data_vec, + p->m_tx_uw_shadow[index].vec); + field_set_val32(p->mp_fld_tx_used_writer_data_istk, + p->m_tx_uw_shadow[index].istk); + } + if (p->mp_fld_tx_used_writer_data_in_order) { + field_set_val32(p->mp_fld_tx_used_writer_data_in_order, + p->m_tx_uw_shadow[index].in_order); + } + + set_tx_uw_data_index(p, index); + register_flush(p->mp_reg_tx_used_writer_data, 1); +} + +int set_tx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address, + uint32_t host_id, uint32_t queue_size, uint32_t packed, + uint32_t int_enable, uint32_t vec, uint32_t istk, + uint32_t in_order) +{ + if (!p->mp_reg_tx_used_writer_data) + return -ENOTSUP; + + set_shadow_tx_uw_data(p, index, guest_physical_address, host_id, queue_size, + packed, int_enable, vec, istk, in_order); + flush_tx_uw_data(p, index); + return 0; +} + +static void set_rx_dr_data_index(nthw_dbs_t *p, uint32_t index) +{ + field_set_val32(p->mp_fld_rx_descriptor_reader_control_adr, index); + field_set_val32(p->mp_fld_rx_descriptor_reader_control_cnt, 1); + register_flush(p->mp_reg_rx_descriptor_reader_control, 1); +} + +static void +set_shadow_rx_dr_data_guest_physical_address(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address) +{ + p->m_rx_dr_shadow[index].guest_physical_address = guest_physical_address; +} + +static void set_shadow_rx_dr_data_host_id(nthw_dbs_t *p, uint32_t index, + uint32_t host_id) +{ + p->m_rx_dr_shadow[index].host_id = host_id; +} + +static void set_shadow_rx_dr_data_queue_size(nthw_dbs_t *p, uint32_t index, + uint32_t queue_size) +{ + p->m_rx_dr_shadow[index].queue_size = queue_size; +} + +static void set_shadow_rx_dr_data_header(nthw_dbs_t *p, uint32_t index, + uint32_t header) +{ + p->m_rx_dr_shadow[index].header = header; +} + +static void set_shadow_rx_dr_data_packed(nthw_dbs_t *p, uint32_t index, + uint32_t packed) +{ + p->m_rx_dr_shadow[index].packed = packed; +} + +static void set_shadow_rx_dr_data(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address, uint32_t host_id, + uint32_t queue_size, uint32_t header, + uint32_t packed) +{ + set_shadow_rx_dr_data_guest_physical_address(p, index, guest_physical_address); + set_shadow_rx_dr_data_host_id(p, index, host_id); + set_shadow_rx_dr_data_queue_size(p, index, queue_size); + set_shadow_rx_dr_data_header(p, index, header); + set_shadow_rx_dr_data_packed(p, index, packed); +} + +static void flush_rx_dr_data(nthw_dbs_t *p, uint32_t index) +{ + field_set_val(p->mp_fld_rx_descriptor_reader_data_guest_physical_address, + (uint32_t *)&p->m_rx_dr_shadow[index].guest_physical_address, + 2); + field_set_val32(p->mp_fld_rx_descriptor_reader_data_host_id, + p->m_rx_dr_shadow[index].host_id); + if (module_is_version_newer(p->mp_mod_dbs, 0, 8)) { + field_set_val32(p->mp_fld_rx_descriptor_reader_data_queue_size, + (1U << p->m_rx_dr_shadow[index].queue_size) - 1U); + } else { + field_set_val32(p->mp_fld_rx_descriptor_reader_data_queue_size, + p->m_rx_dr_shadow[index].queue_size); + } + field_set_val32(p->mp_fld_rx_descriptor_reader_data_header, + p->m_rx_dr_shadow[index].header); + if (p->mp_fld_rx_descriptor_reader_data_packed) { + field_set_val32(p->mp_fld_rx_descriptor_reader_data_packed, + p->m_rx_dr_shadow[index].packed); + } + + set_rx_dr_data_index(p, index); + register_flush(p->mp_reg_rx_descriptor_reader_data, 1); +} + +int set_rx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address, + uint32_t host_id, uint32_t queue_size, uint32_t header, + uint32_t packed) +{ + if (!p->mp_reg_rx_descriptor_reader_data) + return -ENOTSUP; + + set_shadow_rx_dr_data(p, index, guest_physical_address, host_id, queue_size, + header, packed); + flush_rx_dr_data(p, index); + return 0; +} + +static void set_tx_dr_data_index(nthw_dbs_t *p, uint32_t index) +{ + field_set_val32(p->mp_fld_tx_descriptor_reader_control_adr, index); + field_set_val32(p->mp_fld_tx_descriptor_reader_control_cnt, 1); + register_flush(p->mp_reg_tx_descriptor_reader_control, 1); +} + +static void +set_shadow_tx_dr_data_guest_physical_address(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address) +{ + p->m_tx_dr_shadow[index].guest_physical_address = guest_physical_address; +} + +static void set_shadow_tx_dr_data_host_id(nthw_dbs_t *p, uint32_t index, + uint32_t host_id) +{ + p->m_tx_dr_shadow[index].host_id = host_id; +} + +static void set_shadow_tx_dr_data_queue_size(nthw_dbs_t *p, uint32_t index, + uint32_t queue_size) +{ + p->m_tx_dr_shadow[index].queue_size = queue_size; +} + +static void set_shadow_tx_dr_data_header(nthw_dbs_t *p, uint32_t index, + uint32_t header) +{ + p->m_tx_dr_shadow[index].header = header; +} + +static void set_shadow_tx_dr_data_port(nthw_dbs_t *p, uint32_t index, uint32_t port) +{ + p->m_tx_dr_shadow[index].port = port; +} + +static void set_shadow_tx_dr_data_packed(nthw_dbs_t *p, uint32_t index, + uint32_t packed) +{ + p->m_tx_dr_shadow[index].packed = packed; +} + +static void set_shadow_tx_dr_data(nthw_dbs_t *p, uint32_t index, + uint64_t guest_physical_address, uint32_t host_id, + uint32_t queue_size, uint32_t port, + uint32_t header, uint32_t packed) +{ + set_shadow_tx_dr_data_guest_physical_address(p, index, guest_physical_address); + set_shadow_tx_dr_data_host_id(p, index, host_id); + set_shadow_tx_dr_data_queue_size(p, index, queue_size); + set_shadow_tx_dr_data_header(p, index, header); + set_shadow_tx_dr_data_port(p, index, port); + set_shadow_tx_dr_data_packed(p, index, packed); +} + +static void flush_tx_dr_data(nthw_dbs_t *p, uint32_t index) +{ + field_set_val(p->mp_fld_tx_descriptor_reader_data_guest_physical_address, + (uint32_t *)&p->m_tx_dr_shadow[index].guest_physical_address, + 2); + field_set_val32(p->mp_fld_tx_descriptor_reader_data_host_id, + p->m_tx_dr_shadow[index].host_id); + if (module_is_version_newer(p->mp_mod_dbs, 0, 8)) { + field_set_val32(p->mp_fld_tx_descriptor_reader_data_queue_size, + (1U << p->m_tx_dr_shadow[index].queue_size) - 1U); + } else { + field_set_val32(p->mp_fld_tx_descriptor_reader_data_queue_size, + p->m_tx_dr_shadow[index].queue_size); + } + field_set_val32(p->mp_fld_tx_descriptor_reader_data_header, + p->m_tx_dr_shadow[index].header); + field_set_val32(p->mp_fld_tx_descriptor_reader_data_port, + p->m_tx_dr_shadow[index].port); + if (p->mp_fld_tx_descriptor_reader_data_packed) { + field_set_val32(p->mp_fld_tx_descriptor_reader_data_packed, + p->m_tx_dr_shadow[index].packed); + } + + set_tx_dr_data_index(p, index); + register_flush(p->mp_reg_tx_descriptor_reader_data, 1); +} + +int set_tx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address, + uint32_t host_id, uint32_t queue_size, uint32_t port, + uint32_t header, uint32_t packed) +{ + if (!p->mp_reg_tx_descriptor_reader_data) + return -ENOTSUP; + + set_shadow_tx_dr_data(p, index, guest_physical_address, host_id, queue_size, + port, header, packed); + flush_tx_dr_data(p, index); + return 0; +} + +static void set_tx_qp_data_index(nthw_dbs_t *p, uint32_t index) +{ + field_set_val32(p->mp_fld_tx_queue_property_control_adr, index); + field_set_val32(p->mp_fld_tx_queue_property_control_cnt, 1); + register_flush(p->mp_reg_tx_queue_property_control, 1); +} + +static void set_shadow_tx_qp_data_virtual_port(nthw_dbs_t *p, uint32_t index, + uint32_t virtual_port) +{ + p->m_tx_qp_shadow[index].virtual_port = virtual_port; +} + +static void set_shadow_tx_qp_data(nthw_dbs_t *p, uint32_t index, + uint32_t virtual_port) +{ + set_shadow_tx_qp_data_virtual_port(p, index, virtual_port); +} + +static void flush_tx_qp_data(nthw_dbs_t *p, uint32_t index) +{ + field_set_val32(p->mp_fld_tx_queue_property_data_v_port, + p->m_tx_qp_shadow[index].virtual_port); + + set_tx_qp_data_index(p, index); + register_flush(p->mp_reg_tx_queue_property_data, 1); +} + +int nthw_dbs_set_tx_qp_data(nthw_dbs_t *p, uint32_t index, uint32_t virtual_port) +{ + if (!p->mp_reg_tx_queue_property_data) + return -ENOTSUP; + + set_shadow_tx_qp_data(p, index, virtual_port); + flush_tx_qp_data(p, index); + return 0; +} + +static void set_tx_qos_data_index(nthw_dbs_t *p, uint32_t index) +{ + field_set_val32(p->mp_reg_tx_queue_qos_control_adr, index); + field_set_val32(p->mp_reg_tx_queue_qos_control_cnt, 1); + register_flush(p->mp_reg_tx_queue_qos_control, 1); +} + +static void set_shadow_tx_qos_data_enable(nthw_dbs_t *p, uint32_t index, + uint32_t enable) +{ + p->m_tx_qos_shadow[index].enable = enable; +} + +static void set_shadow_tx_qos_data_ir(nthw_dbs_t *p, uint32_t index, uint32_t ir) +{ + p->m_tx_qos_shadow[index].ir = ir; +} + +static void set_shadow_tx_qos_data_bs(nthw_dbs_t *p, uint32_t index, uint32_t bs) +{ + p->m_tx_qos_shadow[index].bs = bs; +} + +static void set_shadow_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable, + uint32_t ir, uint32_t bs) +{ + set_shadow_tx_qos_data_enable(p, index, enable); + set_shadow_tx_qos_data_ir(p, index, ir); + set_shadow_tx_qos_data_bs(p, index, bs); +} + +static void flush_tx_qos_data(nthw_dbs_t *p, uint32_t index) +{ + field_set_val32(p->mp_reg_tx_queue_qos_data_en, p->m_tx_qos_shadow[index].enable); + field_set_val32(p->mp_reg_tx_queue_qos_data_ir, p->m_tx_qos_shadow[index].ir); + field_set_val32(p->mp_reg_tx_queue_qos_data_bs, p->m_tx_qos_shadow[index].bs); + + set_tx_qos_data_index(p, index); + register_flush(p->mp_reg_tx_queue_qos_data, 1); +} + +int set_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable, uint32_t ir, + uint32_t bs) +{ + if (!p->mp_reg_tx_queue_qos_data) + return -ENOTSUP; + + set_shadow_tx_qos_data(p, index, enable, ir, bs); + flush_tx_qos_data(p, index); + return 0; +} + +int set_tx_qos_rate(nthw_dbs_t *p, uint32_t mul, uint32_t div) +{ + if (!p->mp_reg_tx_queue_qos_rate) + return -ENOTSUP; + + field_set_val32(p->mp_reg_tx_queue_qos_rate_mul, mul); + field_set_val32(p->mp_reg_tx_queue_qos_rate_div, div); + register_flush(p->mp_reg_tx_queue_qos_rate, 1); + return 0; +} diff --git a/drivers/net/ntnic/nthw/nthw_dbs.h b/drivers/net/ntnic/nthw/nthw_dbs.h new file mode 100644 index 0000000000..d5891d7538 --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_dbs.h @@ -0,0 +1,313 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NTHW_DBS_HPP_ +#define NTHW_DBS_HPP_ + +#define NT_DBS_RX_QUEUES_MAX (128) +#define NT_DBS_TX_QUEUES_MAX (128) + +/* + * Struct for implementation of memory bank shadows + */ + +/* DBS_RX_AM_DATA */ +struct nthw_dbs_rx_am_data_s { + uint64_t guest_physical_address; + uint32_t enable; + uint32_t host_id; + uint32_t packed; + uint32_t int_enable; +}; + +/* DBS_TX_AM_DATA */ +struct nthw_dbs_tx_am_data_s { + uint64_t guest_physical_address; + uint32_t enable; + uint32_t host_id; + uint32_t packed; + uint32_t int_enable; +}; + +/* DBS_RX_UW_DATA */ +struct nthw_dbs_rx_uw_data_s { + uint64_t guest_physical_address; + uint32_t host_id; + uint32_t queue_size; + uint32_t packed; + uint32_t int_enable; + uint32_t vec; + uint32_t istk; +}; + +/* DBS_TX_UW_DATA */ +struct nthw_dbs_tx_uw_data_s { + uint64_t guest_physical_address; + uint32_t host_id; + uint32_t queue_size; + uint32_t packed; + uint32_t int_enable; + uint32_t vec; + uint32_t istk; + uint32_t in_order; +}; + +/* DBS_RX_DR_DATA */ +struct nthw_dbs_rx_dr_data_s { + uint64_t guest_physical_address; + uint32_t host_id; + uint32_t queue_size; + uint32_t header; + uint32_t packed; +}; + +/* DBS_TX_DR_DATA */ +struct nthw_dbs_tx_dr_data_s { + uint64_t guest_physical_address; + uint32_t host_id; + uint32_t queue_size; + uint32_t header; + uint32_t port; + uint32_t packed; +}; + +/* DBS_TX_QP_DATA */ +struct nthw_dbs_tx_qp_data_s { + uint32_t virtual_port; +}; + +struct nthw_dbs_tx_qos_data_s { + uint32_t enable; + uint32_t ir; + uint32_t bs; +}; + +struct nthw_dbs_s { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_dbs; + int mn_instance; + + int mn_param_dbs_present; + + nt_register_t *mp_reg_rx_control; + nt_field_t *mp_fld_rx_control_last_queue; + nt_field_t *mp_fld_rx_control_avail_monitor_enable; + nt_field_t *mp_fld_rx_control_avail_monitor_scan_speed; + nt_field_t *mp_fld_rx_control_used_write_enable; + nt_field_t *mp_fld_rx_control_used_writer_update_speed; + nt_field_t *mp_fld_rx_control_rx_queues_enable; + + nt_register_t *mp_reg_tx_control; + nt_field_t *mp_fld_tx_control_last_queue; + nt_field_t *mp_fld_tx_control_avail_monitor_enable; + nt_field_t *mp_fld_tx_control_avail_monitor_scan_speed; + nt_field_t *mp_fld_tx_control_used_write_enable; + nt_field_t *mp_fld_tx_control_used_writer_update_speed; + nt_field_t *mp_fld_tx_control_tx_queues_enable; + + nt_register_t *mp_reg_rx_init; + nt_field_t *mp_fld_rx_init_init; + nt_field_t *mp_fld_rx_init_queue; + nt_field_t *mp_fld_rx_init_busy; + + nt_register_t *mp_reg_rx_init_val; + nt_field_t *mp_fld_rx_init_val_idx; + nt_field_t *mp_fld_rx_init_val_ptr; + + nt_register_t *mp_reg_rx_ptr; + nt_field_t *mp_fld_rx_ptr_ptr; + nt_field_t *mp_fld_rx_ptr_queue; + nt_field_t *mp_fld_rx_ptr_valid; + + nt_register_t *mp_reg_tx_init; + nt_field_t *mp_fld_tx_init_init; + nt_field_t *mp_fld_tx_init_queue; + nt_field_t *mp_fld_tx_init_busy; + + nt_register_t *mp_reg_tx_init_val; + nt_field_t *mp_fld_tx_init_val_idx; + nt_field_t *mp_fld_tx_init_val_ptr; + + nt_register_t *mp_reg_tx_ptr; + nt_field_t *mp_fld_tx_ptr_ptr; + nt_field_t *mp_fld_tx_ptr_queue; + nt_field_t *mp_fld_tx_ptr_valid; + + nt_register_t *mp_reg_rx_idle; + nt_field_t *mp_fld_rx_idle_idle; + nt_field_t *mp_fld_rx_idle_queue; + nt_field_t *mp_fld_rx_idle_busy; + + nt_register_t *mp_reg_tx_idle; + nt_field_t *mp_fld_tx_idle_idle; + nt_field_t *mp_fld_tx_idle_queue; + nt_field_t *mp_fld_tx_idle_busy; + + nt_register_t *mp_reg_rx_avail_monitor_control; + nt_field_t *mp_fld_rx_avail_monitor_control_adr; + nt_field_t *mp_fld_rx_avail_monitor_control_cnt; + + nt_register_t *mp_reg_rx_avail_monitor_data; + nt_field_t *mp_fld_rx_avail_monitor_data_guest_physical_address; + nt_field_t *mp_fld_rx_avail_monitor_data_enable; + nt_field_t *mp_fld_rx_avail_monitor_data_host_id; + nt_field_t *mp_fld_rx_avail_monitor_data_packed; + nt_field_t *mp_fld_rx_avail_monitor_data_int; + + nt_register_t *mp_reg_tx_avail_monitor_control; + nt_field_t *mp_fld_tx_avail_monitor_control_adr; + nt_field_t *mp_fld_tx_avail_monitor_control_cnt; + + nt_register_t *mp_reg_tx_avail_monitor_data; + nt_field_t *mp_fld_tx_avail_monitor_data_guest_physical_address; + nt_field_t *mp_fld_tx_avail_monitor_data_enable; + nt_field_t *mp_fld_tx_avail_monitor_data_host_id; + nt_field_t *mp_fld_tx_avail_monitor_data_packed; + nt_field_t *mp_fld_tx_avail_monitor_data_int; + + nt_register_t *mp_reg_rx_used_writer_control; + nt_field_t *mp_fld_rx_used_writer_control_adr; + nt_field_t *mp_fld_rx_used_writer_control_cnt; + + nt_register_t *mp_reg_rx_used_writer_data; + nt_field_t *mp_fld_rx_used_writer_data_guest_physical_address; + nt_field_t *mp_fld_rx_used_writer_data_host_id; + nt_field_t *mp_fld_rx_used_writer_data_queue_size; + nt_field_t *mp_fld_rx_used_writer_data_packed; + nt_field_t *mp_fld_rx_used_writer_data_int; + nt_field_t *mp_fld_rx_used_writer_data_vec; + nt_field_t *mp_fld_rx_used_writer_data_istk; + + nt_register_t *mp_reg_tx_used_writer_control; + nt_field_t *mp_fld_tx_used_writer_control_adr; + nt_field_t *mp_fld_tx_used_writer_control_cnt; + + nt_register_t *mp_reg_tx_used_writer_data; + nt_field_t *mp_fld_tx_used_writer_data_guest_physical_address; + nt_field_t *mp_fld_tx_used_writer_data_host_id; + nt_field_t *mp_fld_tx_used_writer_data_queue_size; + nt_field_t *mp_fld_tx_used_writer_data_packed; + nt_field_t *mp_fld_tx_used_writer_data_int; + nt_field_t *mp_fld_tx_used_writer_data_vec; + nt_field_t *mp_fld_tx_used_writer_data_istk; + nt_field_t *mp_fld_tx_used_writer_data_in_order; + + nt_register_t *mp_reg_rx_descriptor_reader_control; + nt_field_t *mp_fld_rx_descriptor_reader_control_adr; + nt_field_t *mp_fld_rx_descriptor_reader_control_cnt; + + nt_register_t *mp_reg_rx_descriptor_reader_data; + nt_field_t *mp_fld_rx_descriptor_reader_data_guest_physical_address; + nt_field_t *mp_fld_rx_descriptor_reader_data_host_id; + nt_field_t *mp_fld_rx_descriptor_reader_data_queue_size; + nt_field_t *mp_fld_rx_descriptor_reader_data_header; + nt_field_t *mp_fld_rx_descriptor_reader_data_packed; + + nt_register_t *mp_reg_tx_descriptor_reader_control; + nt_field_t *mp_fld_tx_descriptor_reader_control_adr; + nt_field_t *mp_fld_tx_descriptor_reader_control_cnt; + + nt_register_t *mp_reg_tx_descriptor_reader_data; + nt_field_t *mp_fld_tx_descriptor_reader_data_guest_physical_address; + nt_field_t *mp_fld_tx_descriptor_reader_data_host_id; + nt_field_t *mp_fld_tx_descriptor_reader_data_queue_size; + nt_field_t *mp_fld_tx_descriptor_reader_data_port; + nt_field_t *mp_fld_tx_descriptor_reader_data_header; + nt_field_t *mp_fld_tx_descriptor_reader_data_packed; + + nt_register_t *mp_reg_tx_queue_property_control; + nt_field_t *mp_fld_tx_queue_property_control_adr; + nt_field_t *mp_fld_tx_queue_property_control_cnt; + + nt_register_t *mp_reg_tx_queue_property_data; + nt_field_t *mp_fld_tx_queue_property_data_v_port; + + nt_register_t *mp_reg_tx_queue_qos_control; + nt_field_t *mp_reg_tx_queue_qos_control_adr; + nt_field_t *mp_reg_tx_queue_qos_control_cnt; + + nt_register_t *mp_reg_tx_queue_qos_data; + nt_field_t *mp_reg_tx_queue_qos_data_en; + nt_field_t *mp_reg_tx_queue_qos_data_ir; + nt_field_t *mp_reg_tx_queue_qos_data_bs; + + nt_register_t *mp_reg_tx_queue_qos_rate; + nt_field_t *mp_reg_tx_queue_qos_rate_mul; + nt_field_t *mp_reg_tx_queue_qos_rate_div; + + struct nthw_dbs_rx_am_data_s m_rx_am_shadow[NT_DBS_RX_QUEUES_MAX]; + struct nthw_dbs_rx_uw_data_s m_rx_uw_shadow[NT_DBS_RX_QUEUES_MAX]; + struct nthw_dbs_rx_dr_data_s m_rx_dr_shadow[NT_DBS_RX_QUEUES_MAX]; + + struct nthw_dbs_tx_am_data_s m_tx_am_shadow[NT_DBS_TX_QUEUES_MAX]; + struct nthw_dbs_tx_uw_data_s m_tx_uw_shadow[NT_DBS_TX_QUEUES_MAX]; + struct nthw_dbs_tx_dr_data_s m_tx_dr_shadow[NT_DBS_TX_QUEUES_MAX]; + struct nthw_dbs_tx_qp_data_s m_tx_qp_shadow[NT_DBS_TX_QUEUES_MAX]; + struct nthw_dbs_tx_qos_data_s m_tx_qos_shadow[NT_DBS_TX_QUEUES_MAX]; +}; + +typedef struct nthw_dbs_s nthw_dbs_t; + +nthw_dbs_t *nthw_dbs_new(void); +void nthw_dbs_delete(nthw_dbs_t *p); +int dbs_init(nthw_dbs_t *p, nt_fpga_t *p_fpga, int n_instance); +void dbs_reset(nthw_dbs_t *p); + +int dbs_reset_rx_control(nthw_dbs_t *p); +int dbs_reset_tx_control(nthw_dbs_t *p); +int set_rx_control(nthw_dbs_t *p, uint32_t last_queue, + uint32_t avail_monitor_enable, uint32_t avail_monitor_speed, + uint32_t used_write_enable, uint32_t used_write_speed, + uint32_t rx_queue_enable); +int nthw_dbs_get_rx_control(nthw_dbs_t *p, uint32_t *last_queue, + uint32_t *avail_monitor_enable, + uint32_t *avail_monitor_speed, uint32_t *used_write_enable, + uint32_t *used_write_speed, uint32_t *rx_queue_enable); +int set_tx_control(nthw_dbs_t *p, uint32_t last_queue, + uint32_t avail_monitor_enable, uint32_t avail_monitor_speed, + uint32_t used_write_enable, uint32_t used_write_speed, + uint32_t tx_queue_enable); +int nthw_dbs_get_tx_control(nthw_dbs_t *p, uint32_t *last_queue, + uint32_t *avail_monitor_enable, + uint32_t *avail_monitor_speed, uint32_t *used_write_enable, + uint32_t *used_write_speed, uint32_t *tx_queue_enable); +int set_rx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr, + uint32_t init, uint32_t queue); +int get_rx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy); +int set_tx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr, + uint32_t init, uint32_t queue); +int get_tx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy); +int set_rx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue); +int get_rx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy); +int set_tx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue); +int get_tx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy); +int set_rx_ptr_queue(nthw_dbs_t *p, uint32_t queue); +int get_rx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid); +int set_tx_ptr_queue(nthw_dbs_t *p, uint32_t queue); +int get_tx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid); +int set_rx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address, + uint32_t enable, uint32_t host_id, uint32_t packed, + uint32_t int_enable); +int set_tx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address, + uint32_t enable, uint32_t host_id, uint32_t packed, + uint32_t int_enable); +int set_rx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address, + uint32_t host_id, uint32_t queue_size, uint32_t packed, + uint32_t int_enable, uint32_t vec, uint32_t istk); +int set_tx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address, + uint32_t host_id, uint32_t queue_size, uint32_t packed, + uint32_t int_enable, uint32_t vec, uint32_t istk, + uint32_t in_order); +int set_rx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address, + uint32_t host_id, uint32_t queue_size, uint32_t header, + uint32_t packed); +int set_tx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address, + uint32_t host_id, uint32_t queue_size, uint32_t port, + uint32_t header, uint32_t packed); +int nthw_dbs_set_tx_qp_data(nthw_dbs_t *p, uint32_t index, uint32_t virtual_port); +int set_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable, uint32_t ir, + uint32_t bs); +int set_tx_qos_rate(nthw_dbs_t *p, uint32_t mul, uint32_t div); + +#endif /* NTHW_DBS_H_ */ diff --git a/drivers/net/ntnic/nthw/nthw_drv.h b/drivers/net/ntnic/nthw/nthw_drv.h new file mode 100644 index 0000000000..7fdd9bf0e2 --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_drv.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_DRV_H__ +#define __NTHW_DRV_H__ + +#include "nthw_profile.h" + +typedef enum nt_meta_port_type_e { + PORT_TYPE_PHYSICAL, + PORT_TYPE_VIRTUAL, + PORT_TYPE_OVERRIDE, +} nt_meta_port_type_t; + +#include "nthw_helper.h" +#include "nthw_platform_drv.h" +#include "nthw_fpga_model.h" +#include "nthw_stat.h" +#include "nthw_dbs.h" +#include "nthw_epp.h" +#include "nthw_core.h" + +typedef struct nthwhw_info_s { + /* From FW */ + int hw_id; + int hw_id_emulated; + char hw_plat_id_str[32]; + + struct vpd_info_s { + int mn_mac_addr_count; + uint64_t mn_mac_addr_value; + uint8_t ma_mac_addr_octets[6]; + } vpd_info; +} nthw_hw_info_t; + +typedef struct fpga_info_s { + uint64_t n_fpga_ident; + + int n_fpga_type_id; + int n_fpga_prod_id; + int n_fpga_ver_id; + int n_fpga_rev_id; + + int n_fpga_build_time; + + int n_fpga_debug_mode; + + int n_nims; + int n_phy_ports; + int n_phy_quads; + int n_rx_ports; + int n_tx_ports; + + enum fpga_info_profile profile; + + struct nt_fpga_s *mp_fpga; + + struct nthw_rac *mp_nthw_rac; + struct nthw_hif *mp_nthw_hif; + struct nthw_pcie3 *mp_nthw_pcie3; + struct nthw_tsm *mp_nthw_tsm; + + nthw_dbs_t *mp_nthw_dbs; + nthw_epp_t *mp_nthw_epp; + + uint8_t *bar0_addr; /* Needed for register read/write */ + size_t bar0_size; + + int adapter_no; /* Needed for nthw_rac DMA array indexing */ + uint32_t pciident; /* Needed for nthw_rac DMA memzone_reserve */ + int numa_node; /* Needed for nthw_rac DMA memzone_reserve */ + + char *mp_adapter_id_str; /* Pointer to string literal used in nthw log messages */ + + struct nthwhw_info_s nthw_hw_info; + + nthw_adapter_id_t n_nthw_adapter_id; + +} fpga_info_t; + +#endif /* __NTHW_DRV_H__ */ diff --git a/drivers/net/ntnic/nthw/nthw_epp.c b/drivers/net/ntnic/nthw/nthw_epp.c new file mode 100644 index 0000000000..fbe3993b25 --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_epp.c @@ -0,0 +1,335 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_epp.h" + +#include /* ENOTSUP */ + +nthw_epp_t *nthw_epp_new(void) +{ + nthw_epp_t *p = malloc(sizeof(nthw_epp_t)); + + if (p) + memset(p, 0, sizeof(nthw_epp_t)); + return p; +} + +void nthw_epp_delete(nthw_epp_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_epp_t)); + free(p); + } +} + +int nthw_epp_present(nt_fpga_t *p_fpga, int n_instance) +{ + return nthw_epp_init(NULL, p_fpga, n_instance) == 0; +} + +int nthw_epp_init(nthw_epp_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + nt_module_t *mod = fpga_query_module(p_fpga, MOD_EPP, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: EPP %d: no such instance\n", + p_fpga->p_fpga_info->mp_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_epp = mod; + + p->mn_epp_categories = fpga_get_product_param(p_fpga, NT_EPP_CATEGORIES, 0); + + p->mp_reg_reciepe_memory_control = + module_get_register(p->mp_mod_epp, EPP_RCP_CTRL); + p->mp_fld_reciepe_memory_control_adr = + register_get_field(p->mp_reg_reciepe_memory_control, EPP_RCP_CTRL_ADR); + p->mp_fld_reciepe_memory_control_cnt = + register_get_field(p->mp_reg_reciepe_memory_control, EPP_RCP_CTRL_CNT); + + p->mp_reg_reciepe_memory_data = + module_get_register(p->mp_mod_epp, EPP_RCP_DATA); + p->mp_fld_reciepe_memory_data_tx_mtu_epp_enable = + register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_TX_MTU_EPP_EN); + p->mp_fld_reciepe_memory_data_queue_mtu_epp_enable = + register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_QUEUE_MTU_EPP_EN); + p->mp_fld_reciepe_memory_data_size_adjust_tx_port = + register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_SIZE_ADJUST_TXP); + p->mp_fld_reciepe_memory_data_size_adjust_virtual_port = + register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_SIZE_ADJUST_VPORT); + p->mp_fld_reciepe_memory_data_fixed18b_l2_mtu = + register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_FIXED_18B_L2_MTU); + p->mp_fld_reciepe_memory_data_txp_qos_epp_enable = + register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_TX_QOS_EPP_EN); + p->mp_fld_reciepe_memory_data_queue_qos_epp_enable = + register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_QUEUE_QOS_EPP_EN); + + p->mp_reg_txp_port_mtu_control = + module_get_register(p->mp_mod_epp, EPP_TXP_MTU_CTRL); + p->mp_fld_txp_port_mtu_control_adr = + register_get_field(p->mp_reg_txp_port_mtu_control, EPP_TXP_MTU_CTRL_ADR); + p->mp_fld_txp_port_mtu_control_cnt = + register_get_field(p->mp_reg_txp_port_mtu_control, EPP_TXP_MTU_CTRL_CNT); + + p->mp_reg_txp_port_mtu_data = + module_get_register(p->mp_mod_epp, EPP_TXP_MTU_DATA); + p->mp_fld_txp_port_mtu_data_max_mtu = + register_get_field(p->mp_reg_txp_port_mtu_data, EPP_TXP_MTU_DATA_MAX_MTU); + + p->mp_reg_queue_mtu_control = + module_get_register(p->mp_mod_epp, EPP_QUEUE_MTU_CTRL); + p->mp_fld_queue_mtu_control_adr = + register_get_field(p->mp_reg_queue_mtu_control, EPP_QUEUE_MTU_CTRL_ADR); + p->mp_fld_queue_mtu_control_cnt = + register_get_field(p->mp_reg_queue_mtu_control, EPP_QUEUE_MTU_CTRL_CNT); + + p->mp_reg_queue_mtu_data = + module_get_register(p->mp_mod_epp, EPP_QUEUE_MTU_DATA); + p->mp_fld_queue_mtu_data_max_mtu = + register_get_field(p->mp_reg_queue_mtu_data, EPP_QUEUE_MTU_DATA_MAX_MTU); + + p->mp_reg_txp_qos_control = + module_get_register(p->mp_mod_epp, EPP_TXP_QOS_CTRL); + p->mp_fld_txp_qos_control_adr = + register_get_field(p->mp_reg_txp_qos_control, EPP_TXP_QOS_CTRL_ADR); + p->mp_fld_txp_qos_control_cnt = + register_get_field(p->mp_reg_txp_qos_control, EPP_TXP_QOS_CTRL_CNT); + + p->mp_reg_txp_qos_data = module_get_register(p->mp_mod_epp, EPP_TXP_QOS_DATA); + p->mp_fld_txp_qos_data_enable = + register_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_EN); + p->mp_fld_txp_qos_data_information_rate = + register_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_IR); + p->mp_fld_txp_qos_data_information_rate_fractional = + register_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_IR_FRACTION); + p->mp_fld_txp_qos_data_burst_size = + register_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_BS); + + p->mp_reg_vport_qos_control = + module_get_register(p->mp_mod_epp, EPP_VPORT_QOS_CTRL); + p->mp_fld_vport_qos_control_adr = + register_get_field(p->mp_reg_vport_qos_control, EPP_VPORT_QOS_CTRL_ADR); + p->mp_fld_vport_qos_control_cnt = + register_get_field(p->mp_reg_vport_qos_control, EPP_VPORT_QOS_CTRL_CNT); + + p->mp_reg_vport_qos_data = + module_get_register(p->mp_mod_epp, EPP_VPORT_QOS_DATA); + p->mp_fld_vport_qos_data_enable = + register_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_EN); + p->mp_fld_vport_qos_data_information_rate = + register_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_IR); + p->mp_fld_vport_qos_data_information_rate_fractional = + register_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_IR_FRACTION); + p->mp_fld_vport_qos_data_burst_size = + register_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_BS); + + p->mp_reg_queue_vport_control = + module_get_register(p->mp_mod_epp, EPP_QUEUE_VPORT_CTRL); + p->mp_fld_queue_vport_control_adr = + register_get_field(p->mp_reg_queue_vport_control, EPP_QUEUE_VPORT_CTRL_ADR); + p->mp_fld_queue_vport_control_cnt = + register_get_field(p->mp_reg_queue_vport_control, EPP_QUEUE_VPORT_CTRL_CNT); + + p->mp_reg_queue_vport_data = + module_get_register(p->mp_mod_epp, EPP_QUEUE_VPORT_DATA); + p->mp_fld_queue_vport_data_vport = + register_get_field(p->mp_reg_queue_vport_data, EPP_QUEUE_VPORT_DATA_VPORT); + + return 0; +} + +int nthw_epp_setup(nthw_epp_t *p) +{ + if (p == NULL) + return 0; + + /* Set recieps for 2 first records */ + field_set_val32(p->mp_fld_reciepe_memory_control_cnt, 1); + + /* Zero all categories */ + for (int i = 0; i < p->mn_epp_categories; ++i) { + field_set_val32(p->mp_fld_reciepe_memory_control_adr, i); + register_flush(p->mp_reg_reciepe_memory_control, 1); + + field_set_val32(p->mp_fld_reciepe_memory_data_tx_mtu_epp_enable, 0); + field_set_val32(p->mp_fld_reciepe_memory_data_queue_mtu_epp_enable, 0); + field_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_tx_port, 0); + field_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_virtual_port, + 0); + field_set_val32(p->mp_fld_reciepe_memory_data_fixed18b_l2_mtu, 0); + field_set_val32(p->mp_fld_reciepe_memory_data_txp_qos_epp_enable, 0); + field_set_val32(p->mp_fld_reciepe_memory_data_queue_qos_epp_enable, 0); + register_flush(p->mp_reg_reciepe_memory_data, 1); + } + + for (int i = 0; i < NRECIPE; ++i) { + field_set_val32(p->mp_fld_reciepe_memory_control_adr, i); + register_flush(p->mp_reg_reciepe_memory_control, 1); + + field_set_val32(p->mp_fld_reciepe_memory_data_tx_mtu_epp_enable, 1); + field_set_val32(p->mp_fld_reciepe_memory_data_queue_mtu_epp_enable, 1); + field_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_tx_port, + rcp_data_size_adjust_txp[i]); + field_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_virtual_port, + rcp_data_size_adjust_vport[i]); + field_set_val32(p->mp_fld_reciepe_memory_data_fixed18b_l2_mtu, 1); + field_set_val32(p->mp_fld_reciepe_memory_data_txp_qos_epp_enable, 1); + field_set_val32(p->mp_fld_reciepe_memory_data_queue_qos_epp_enable, 1); + register_flush(p->mp_reg_reciepe_memory_data, 1); + } + /* phy mtu setup */ + field_set_val32(p->mp_fld_txp_port_mtu_control_cnt, 1); + for (int i = 0; i < 2; ++i) { + field_set_val32(p->mp_fld_txp_port_mtu_control_adr, i); + register_flush(p->mp_reg_txp_port_mtu_control, 1); + + field_set_val32(p->mp_fld_txp_port_mtu_data_max_mtu, MTUINITVAL); + register_flush(p->mp_reg_txp_port_mtu_data, 1); + } + /* phy QoS setup */ + field_set_val32(p->mp_fld_txp_qos_control_cnt, 1); + for (int i = 0; i < 2; ++i) { + field_set_val32(p->mp_fld_txp_qos_control_adr, i); + register_flush(p->mp_reg_txp_qos_control, 1); + + field_set_val32(p->mp_fld_txp_qos_data_enable, 0); + register_flush(p->mp_reg_txp_qos_data, 1); + } + + /* virt mtu setup */ + field_set_val32(p->mp_fld_queue_mtu_control_cnt, 1); + for (int i = 0; i < 128; ++i) { + field_set_val32(p->mp_fld_queue_mtu_control_adr, i); + register_flush(p->mp_reg_queue_mtu_control, 1); + + field_set_val32(p->mp_fld_queue_mtu_data_max_mtu, MTUINITVAL); + register_flush(p->mp_reg_queue_mtu_data, 1); + } + + /* virt QoS setup */ + field_set_val32(p->mp_fld_vport_qos_control_cnt, 1); + for (int i = 0; i < 128; ++i) { + field_set_val32(p->mp_fld_vport_qos_control_adr, i); + register_flush(p->mp_reg_vport_qos_control, 1); + + field_set_val32(p->mp_fld_vport_qos_data_enable, 0); + register_flush(p->mp_reg_vport_qos_data, 1); + } + + return 0; +} + +/* + * Set the MTU registers in context with the current setMTU request. + */ +int nthw_epp_set_mtu(nthw_epp_t *p, uint32_t port, uint32_t max_mtu, + nt_meta_port_type_t port_type) +{ + if (p == NULL) + return 0; + + if (port_type == PORT_TYPE_PHYSICAL) { + /* Set the TXP Mtu control register */ + field_set_val32(p->mp_fld_txp_port_mtu_control_adr, port); + field_set_val32(p->mp_fld_txp_port_mtu_control_cnt, 1); + register_flush(p->mp_reg_txp_port_mtu_control, 1); + + /* Set the TXP Mtu control register */ + field_set_val32(p->mp_fld_txp_port_mtu_data_max_mtu, max_mtu); + register_flush(p->mp_reg_txp_port_mtu_data, 1); + } else if (port_type == PORT_TYPE_VIRTUAL) { + /* Set the TXP Mtu control register */ + field_set_val32(p->mp_fld_queue_mtu_control_adr, port); + field_set_val32(p->mp_fld_queue_mtu_control_cnt, 1); + register_flush(p->mp_reg_queue_mtu_control, 1); + + /* Set the TXP Mtu control register */ + field_set_val32(p->mp_fld_queue_mtu_data_max_mtu, max_mtu); + register_flush(p->mp_reg_queue_mtu_data, 1); + } else { + NT_LOG(DBG, NTHW, "NthwEpp::%s - port_type unsupported", + __func__); + register_reset(p->mp_reg_queue_mtu_control); + register_flush(p->mp_reg_queue_mtu_control, 1); + register_reset(p->mp_reg_queue_mtu_data); + register_flush(p->mp_reg_queue_mtu_data, 1); + register_reset(p->mp_reg_txp_port_mtu_control); + register_flush(p->mp_reg_txp_port_mtu_control, 1); + register_reset(p->mp_reg_txp_port_mtu_data); + register_flush(p->mp_reg_txp_port_mtu_data, 1); + + return -ENOTSUP; + } + + return 0; +} + +int nthw_epp_set_txp_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate, + uint32_t information_rate_fractional, uint32_t burst_size) +{ + if (p == NULL) + return 0; + + field_set_val32(p->mp_fld_txp_qos_control_adr, port); + field_set_val32(p->mp_fld_txp_qos_control_cnt, 1); + register_flush(p->mp_reg_txp_qos_control, 1); + + uint32_t enable = ((information_rate | information_rate_fractional | + burst_size) != 0); + field_set_val32(p->mp_fld_txp_qos_data_enable, enable); + field_set_val32(p->mp_fld_txp_qos_data_information_rate, information_rate); + field_set_val32(p->mp_fld_txp_qos_data_information_rate_fractional, + information_rate_fractional); + field_set_val32(p->mp_fld_txp_qos_data_burst_size, burst_size); + register_flush(p->mp_reg_txp_qos_data, 1); + + return 0; +} + +int nthw_epp_set_vport_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate, + uint32_t information_rate_fractional, uint32_t burst_size) +{ + if (p == NULL) + return 0; + + field_set_val32(p->mp_fld_vport_qos_control_adr, port); + field_set_val32(p->mp_fld_vport_qos_control_cnt, 1); + register_flush(p->mp_reg_vport_qos_control, 1); + + uint32_t enable = ((information_rate | information_rate_fractional | + burst_size) != 0); + field_set_val32(p->mp_fld_vport_qos_data_enable, enable); + field_set_val32(p->mp_fld_vport_qos_data_information_rate, information_rate); + field_set_val32(p->mp_fld_vport_qos_data_information_rate_fractional, + information_rate_fractional); + field_set_val32(p->mp_fld_vport_qos_data_burst_size, burst_size); + register_flush(p->mp_reg_vport_qos_data, 1); + + return 0; +} + +int nthw_epp_set_queue_to_vport(nthw_epp_t *p, uint32_t qid, uint32_t vport) +{ + if (p == NULL) + return 0; + + field_set_val32(p->mp_fld_queue_vport_control_adr, qid); + field_set_val32(p->mp_fld_queue_vport_control_cnt, 1); + register_flush(p->mp_reg_queue_vport_control, 1); + + field_set_val32(p->mp_fld_queue_vport_data_vport, vport); + register_flush(p->mp_reg_queue_vport_data, 1); + return 0; +} diff --git a/drivers/net/ntnic/nthw/nthw_epp.h b/drivers/net/ntnic/nthw/nthw_epp.h new file mode 100644 index 0000000000..b404c9b61a --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_epp.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NTHW_EPP_HPP_ +#define NTHW_EPP_HPP_ + +/* VXLAN adds extra 50 bytes */ +#define VXLANDATASIZEADJUST 50 +#define VXLANDATASIZEADJUSTIPV6 70 +#define MTUINITVAL 1500 +#define NRECIPE 3 + +/* List of size adjust values to put in the recipe memory data register at startup */ +static const int rcp_data_size_adjust_txp[NRECIPE] = { 0, VXLANDATASIZEADJUST, + VXLANDATASIZEADJUSTIPV6 + }; +static const int rcp_data_size_adjust_vport[NRECIPE] = { 0, VXLANDATASIZEADJUST, + VXLANDATASIZEADJUSTIPV6 + }; + +struct nthw_epp_s { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_epp; + int mn_instance; + int mn_epp_categories; + + nt_register_t *mp_reg_reciepe_memory_control; + nt_field_t *mp_fld_reciepe_memory_control_adr; + nt_field_t *mp_fld_reciepe_memory_control_cnt; + + nt_register_t *mp_reg_reciepe_memory_data; + nt_field_t *mp_fld_reciepe_memory_data_tx_mtu_epp_enable; + nt_field_t *mp_fld_reciepe_memory_data_queue_mtu_epp_enable; + nt_field_t *mp_fld_reciepe_memory_data_size_adjust_tx_port; + nt_field_t *mp_fld_reciepe_memory_data_size_adjust_virtual_port; + nt_field_t *mp_fld_reciepe_memory_data_fixed18b_l2_mtu; + nt_field_t *mp_fld_reciepe_memory_data_txp_qos_epp_enable; + nt_field_t *mp_fld_reciepe_memory_data_queue_qos_epp_enable; + + nt_register_t *mp_reg_txp_port_mtu_control; + nt_field_t *mp_fld_txp_port_mtu_control_adr; + nt_field_t *mp_fld_txp_port_mtu_control_cnt; + + nt_register_t *mp_reg_txp_port_mtu_data; + nt_field_t *mp_fld_txp_port_mtu_data_max_mtu; + + nt_register_t *mp_reg_queue_mtu_control; + nt_field_t *mp_fld_queue_mtu_control_adr; + nt_field_t *mp_fld_queue_mtu_control_cnt; + + nt_register_t *mp_reg_queue_mtu_data; + nt_field_t *mp_fld_queue_mtu_data_max_mtu; + + nt_register_t *mp_reg_txp_qos_control; + nt_field_t *mp_fld_txp_qos_control_adr; + nt_field_t *mp_fld_txp_qos_control_cnt; + + nt_register_t *mp_reg_txp_qos_data; + nt_field_t *mp_fld_txp_qos_data_enable; + nt_field_t *mp_fld_txp_qos_data_information_rate; + nt_field_t *mp_fld_txp_qos_data_information_rate_fractional; + nt_field_t *mp_fld_txp_qos_data_burst_size; + + nt_register_t *mp_reg_vport_qos_control; + nt_field_t *mp_fld_vport_qos_control_adr; + nt_field_t *mp_fld_vport_qos_control_cnt; + + nt_register_t *mp_reg_vport_qos_data; + nt_field_t *mp_fld_vport_qos_data_enable; + nt_field_t *mp_fld_vport_qos_data_information_rate; + nt_field_t *mp_fld_vport_qos_data_information_rate_fractional; + nt_field_t *mp_fld_vport_qos_data_burst_size; + + nt_register_t *mp_reg_queue_vport_control; + nt_field_t *mp_fld_queue_vport_control_adr; + nt_field_t *mp_fld_queue_vport_control_cnt; + + nt_register_t *mp_reg_queue_vport_data; + nt_field_t *mp_fld_queue_vport_data_vport; +}; + +typedef struct nthw_epp_s nthw_epp_t; + +nthw_epp_t *nthw_epp_new(void); +void nthw_epp_delete(nthw_epp_t *p); + +int nthw_epp_present(nt_fpga_t *p_fpga, int n_instance); +int nthw_epp_init(nthw_epp_t *p, nt_fpga_t *p_fpga, int n_instance); +int nthw_epp_setup(nthw_epp_t *p); +int nthw_epp_set_mtu(nthw_epp_t *p, uint32_t port, uint32_t max_mtu, + nt_meta_port_type_t port_type); +int nthw_epp_set_txp_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate, + uint32_t information_rate_fractional, uint32_t burst_size); +int nthw_epp_set_vport_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate, + uint32_t information_rate_fractional, uint32_t burst_size); +int nthw_epp_set_queue_to_vport(nthw_epp_t *p, uint32_t qid, uint32_t vport); + +#endif /* NTHW_EPP_HPP_ */ diff --git a/drivers/net/ntnic/nthw/nthw_fpga_model.c b/drivers/net/ntnic/nthw/nthw_fpga_model.c new file mode 100644 index 0000000000..fca13e0f31 --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_fpga_model.c @@ -0,0 +1,1677 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include /* ctime */ + +#include "nthw_drv.h" /* fpga_info_s */ +#include "nthw_register.h" +#include "nthw_fpga_model.h" +#include "nthw_rac.h" +#include "ntlog.h" + +#include "nthw_fpga_instances.h" +#include "nthw_fpga_modules_defs.h" + +/* Generated code */ +nt_fpga_prod_init_t *nthw_fpga_instances[] = { &nthw_fpga_9563_055_024_0000, + NULL + }; + +static const struct { + const int a; + const char *b; +} sa_nthw_fpga_mod_map[] = { + { MOD_CAT, "CAT" }, + { MOD_CB, "CB" }, + { MOD_CCIP, "CCIP" }, + { MOD_CFP4_CTRL_GBOX, "CFP4_CTRL_GBOX" }, + { MOD_COR, "COR" }, + { MOD_CPY, "CPY" }, + { MOD_CSU, "CSU" }, + { MOD_DBS, "DBS" }, + { MOD_DDP, "DDP" }, + { MOD_EPP, "EPP" }, + { MOD_EQM, "EQM" }, + { MOD_FHM, "FHM" }, + { MOD_FLM, "FLM" }, + { MOD_GFG, "GFG" }, + { MOD_GMF, "GMF" }, + { MOD_GPIO_PHY, "GPIO_PHY" }, + { MOD_GPIO_PHY_PORTS, "GPIO_PHY_PORTS" }, + { MOD_GPIO_SFPP, "GPIO_SFPP" }, + { MOD_HFU, "HFU" }, + { MOD_HIF, "HIF" }, + { MOD_HSH, "HSH" }, + { MOD_HST, "HST" }, + { MOD_ICORE_10G, "ICORE_10G" }, + { MOD_IFR, "IFR" }, + { MOD_IIC, "IIC" }, + { MOD_INS, "INS" }, + { MOD_IOA, "IOA" }, + { MOD_IPF, "IPF" }, + { MOD_KM, "KM" }, + { MOD_LAO, "LAO" }, + { MOD_MAC, "MAC" }, + { MOD_MAC10, "MAC10" }, + { MOD_MAC100, "MAC100" }, + { MOD_MAC10G, "MAC10G" }, + { MOD_MAC1G, "MAC1G" }, + { MOD_MAC_PCS, "MAC_PCS" }, + { MOD_MAC_PCS_XXV, "MAC_PCS_XXV" }, + { MOD_MAC_RX, "MAC_RX" }, + { MOD_MAC_TFG, "MAC_TFG" }, + { MOD_MAC_TX, "MAC_TX" }, + { MOD_MCU, "MCU" }, + { MOD_MDG, "MDG" }, + { MOD_MSK, "MSK" }, + { MOD_NIF, "NIF" }, + { MOD_PCIE3, "PCIE3" }, + { MOD_PCI_RD_TG, "PCI_RD_TG" }, + { MOD_PCI_TA, "PCI_TA" }, + { MOD_PCI_WR_TG, "PCI_WR_TG" }, + { MOD_PCM_NT100A01_01, "PCM_NT100A01_01" }, + { MOD_PCM_NT50B01_01, "PCM_NT50B01_01" }, + { MOD_PCS, "PCS" }, + { MOD_PCS100, "PCS100" }, + { MOD_PDB, "PDB" }, + { MOD_PDI, "PDI" }, + { MOD_PHY10G, "PHY10G" }, + { MOD_PHY3S10G, "PHY3S10G" }, + { MOD_PM, "PM" }, + { MOD_PRM_NT100A01_01, "PRM_NT100A01_01" }, + { MOD_PRM_NT50B01_01, "PRM_NT50B01_01" }, + { MOD_PTP1588, "PTP1588" }, + { MOD_QM, "QM" }, + { MOD_QSL, "QSL" }, + { MOD_QSPI, "QSPI" }, + { MOD_R2DRP, "R2DRP" }, + { MOD_RAC, "RAC" }, + { MOD_RBH, "RBH" }, + { MOD_RFD, "RFD" }, + { MOD_RMC, "RMC" }, + { MOD_RNTC, "RNTC" }, + { MOD_ROA, "ROA" }, + { MOD_RPL, "RPL" }, + { MOD_RPP_LR, "RPP_LR" }, + { MOD_RST7000, "RST7000" }, + { MOD_RST7001, "RST7001" }, + { MOD_RST9500, "RST9500" }, + { MOD_RST9501, "RST9501" }, + { MOD_RST9502, "RST9502" }, + { MOD_RST9503, "RST9503" }, + { MOD_RST9504, "RST9504" }, + { MOD_RST9505, "RST9505" }, + { MOD_RST9506, "RST9506" }, + { MOD_RST9507, "RST9507" }, + { MOD_RST9508, "RST9508" }, + { MOD_RST9509, "RST9509" }, + { MOD_RST9510, "RST9510" }, + { MOD_RST9512, "RST9512" }, + { MOD_RST9513, "RST9513" }, + { MOD_RST9515, "RST9515" }, + { MOD_RST9516, "RST9516" }, + { MOD_RST9517, "RST9517" }, + { MOD_RST9519, "RST9519" }, + { MOD_RST9520, "RST9520" }, + { MOD_RST9521, "RST9521" }, + { MOD_RST9522, "RST9522" }, + { MOD_RST9523, "RST9523" }, + { MOD_RST9524, "RST9524" }, + { MOD_RST9525, "RST9525" }, + { MOD_RST9526, "RST9526" }, + { MOD_RST9527, "RST9527" }, + { MOD_RST9528, "RST9528" }, + { MOD_RST9529, "RST9529" }, + { MOD_RST9530, "RST9530" }, + { MOD_RST9531, "RST9531" }, + { MOD_RST9532, "RST9532" }, + { MOD_RST9533, "RST9533" }, + { MOD_RST9534, "RST9534" }, + { MOD_RST9535, "RST9535" }, + { MOD_RST9536, "RST9536" }, + { MOD_RST9537, "RST9537" }, + { MOD_RST9538, "RST9538" }, + { MOD_RST9539, "RST9539" }, + { MOD_RST9540, "RST9540" }, + { MOD_RST9541, "RST9541" }, + { MOD_RST9542, "RST9542" }, + { MOD_RST9543, "RST9543" }, + { MOD_RST9544, "RST9544" }, + { MOD_RST9545, "RST9545" }, + { MOD_RST9546, "RST9546" }, + { MOD_RST9547, "RST9547" }, + { MOD_RST9548, "RST9548" }, + { MOD_RST9549, "RST9549" }, + { MOD_RST9553, "RST9553" }, + { MOD_RST9555, "RST9555" }, + { MOD_RST9559, "RST9559" }, + { MOD_RST9563, "RST9563" }, + { MOD_RTD, "RTD" }, + { MOD_RTD_HMP, "RTD_HMP" }, + { MOD_RTX, "RTX" }, + { MOD_SDC, "SDC" }, + { MOD_SLC, "SLC" }, + { MOD_SLC_LR, "SLC_LR" }, + { MOD_SMM, "SMM" }, + { MOD_SMM_RX, "SMM_RX" }, + { MOD_SMM_TX, "SMM_TX" }, + { MOD_SPIM, "SPIM" }, + { MOD_SPIS, "SPIS" }, + { MOD_STA, "STA" }, + { MOD_TBH, "TBH" }, + { MOD_TEMPMON, "TEMPMON" }, + { MOD_TINT, "TINT" }, + { MOD_TMC, "TMC" }, + { MOD_TSM, "TSM" }, + { MOD_TX_CPY, "TX_CPY" }, + { MOD_TX_CSI, "TX_CSI" }, + { MOD_TX_CSO, "TX_CSO" }, + { MOD_TX_INS, "TX_INS" }, + { MOD_TX_RPL, "TX_RPL" }, + { 0L, NULL }, +}; + +/* NOTE: this needs to be (manually) synced with enum */ +static const char *const a_bus_type[] = { + "ERR", /* BUS_TYPE_UNKNOWN, */ + "BAR", /* BUS_TYPE_BAR, */ + "PCI", /* BUS_TYPE_PCI, */ + "CCIP", /* BUS_TYPE_CCIP, */ + "RAB0", /* BUS_TYPE_RAB0, */ + "RAB1", /* BUS_TYPE_RAB1, */ + "RAB2", /* BUS_TYPE_RAB2, */ + "NMB", /* BUS_TYPE_NMB, */ + "NDM", /* BUS_TYPE_NDM, */ +}; + +static const char *get_bus_name(int n_bus_type_id) +{ + if (n_bus_type_id >= 1 && n_bus_type_id <= (int)ARRAY_SIZE(a_bus_type)) + return a_bus_type[n_bus_type_id]; + + else + return "ERR"; +} + +/* + * Module name lookup by id from array + * Uses naive linear search as performance is not an issue here... + */ +static const char *nthw_fpga_mod_id_to_str(uint64_t n_fpga_mod_id) +{ + int i; + + for (i = 0; i <= (int)ARRAY_SIZE(sa_nthw_fpga_mod_map); i++) { + if ((uint64_t)sa_nthw_fpga_mod_map[i].a == n_fpga_mod_id) + break; + } + return (sa_nthw_fpga_mod_map[i].b ? sa_nthw_fpga_mod_map[i].b : + "unknown"); +} + +/* + * Force C linkage for xxx_addr_bases and xxx_module_versions + */ +static int read_data(struct fpga_info_s *p_fpga_info, int n_bus_type_id, uint32_t addr, + uint32_t len, uint32_t *p_data) +{ + int rc = -1; + + assert(p_fpga_info); + assert(p_data); + + switch (n_bus_type_id) { + case BUS_TYPE_BAR: + case BUS_TYPE_PCI: + assert(len == 1); + nthw_rac_reg_read32(p_fpga_info, addr, p_data); + rc = 0; + break; + case BUS_TYPE_RAB0: + assert(p_fpga_info->mp_nthw_rac); + rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, addr, 0, len, + p_data); + break; + case BUS_TYPE_RAB1: + assert(p_fpga_info->mp_nthw_rac); + rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, addr, 1, len, + p_data); + break; + case BUS_TYPE_RAB2: + assert(p_fpga_info->mp_nthw_rac); + rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, addr, 2, len, + p_data); + break; + default: + assert(false); + return -1; + } + + return rc; +} + +static int read_data_tsc(struct fpga_info_s *p_fpga_info, int n_bus_type_id, + uint32_t addr, uint32_t len, uint32_t *p_data, + uint64_t *p_tsc1, uint64_t *p_tsc2) +{ + int rc = -1; + + (void)p_tsc1; + (void)p_tsc2; + + rc = read_data(p_fpga_info, n_bus_type_id, addr, len, p_data); + + return rc; +} + +static int write_data(struct fpga_info_s *p_fpga_info, int n_bus_type_id, + uint32_t addr, uint32_t len, const uint32_t *p_data) +{ + int rc = -1; + + assert(p_fpga_info); + assert(p_data); + + switch (n_bus_type_id) { + case BUS_TYPE_BAR: + case BUS_TYPE_PCI: + assert(len == 1); + nthw_rac_reg_write32(p_fpga_info, addr, *p_data); + rc = 0; + break; + case BUS_TYPE_RAB0: + assert(p_fpga_info->mp_nthw_rac); + rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, addr, 0, len, + p_data); + break; + case BUS_TYPE_RAB1: + assert(p_fpga_info->mp_nthw_rac); + rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, addr, 1, len, + p_data); + break; + case BUS_TYPE_RAB2: + assert(p_fpga_info->mp_nthw_rac); + rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, addr, 2, len, + p_data); + break; + default: + assert(false); + return -1; + } + + return rc; +} + +/* + * FpgaMgr + */ +nt_fpga_mgr_t *fpga_mgr_new(void) +{ + nt_fpga_mgr_t *p = malloc(sizeof(nt_fpga_mgr_t)); + return p; +} + +void fpga_mgr_delete(nt_fpga_mgr_t *p) +{ + memset(p, 0, sizeof(nt_fpga_mgr_t)); + free(p); +} + +void fpga_mgr_init(nt_fpga_mgr_t *p) +{ + size_t i; + + /* Count fpga instance in array */ + p->mpa_fpga_prod_init = nthw_fpga_instances; + for (i = 0; i < ARRAY_SIZE(nthw_fpga_instances); i++) { + if (p->mpa_fpga_prod_init[i] == NULL) + break; + } + p->mn_fpgas = (int)i; +} + +nt_fpga_t *fpga_mgr_query_fpga(nt_fpga_mgr_t *p, uint64_t n_fpga_id, + struct fpga_info_s *p_fpga_info) +{ + int i; + + const int n_fpga_prod = FPGAID_TO_PRODUCTCODE(n_fpga_id); + const int n_fpga_ver = FPGAID_TO_VERSIONCODE(n_fpga_id); + const int n_fpga_rev = FPGAID_TO_REVISIONCODE(n_fpga_id); + + for (i = 0; i < p->mn_fpgas; i++) { + nt_fpga_prod_init_t *p_init = p->mpa_fpga_prod_init[i]; + + if (p_init->fpga_product_id == n_fpga_prod && + p_init->fpga_version == n_fpga_ver && + p_init->fpga_revision == n_fpga_rev) { + { + nt_fpga_t *p_fpga = fpga_new(); + + fpga_init(p_fpga, p_init, p_fpga_info); + return p_fpga; + } + } + } + + NT_LOG(ERR, NTHW, + "FPGA Id 0x%" PRIX64 ": %04d: %d.%d: no match found\n", n_fpga_id, + n_fpga_prod, n_fpga_ver, n_fpga_rev); + + return NULL; +} + +void fpga_mgr_show(nt_fpga_mgr_t *p, FILE *fh_out, int detail_level) +{ + int i; + + fprintf(fh_out, "\n"); /* start of records */ + for (i = 0; i < p->mn_fpgas; i++) { + nt_fpga_prod_init_t *p_init = p->mpa_fpga_prod_init[i]; + + if (detail_level == 0) { + fprintf(fh_out, "%04d-%02d-%02d\n", + p_init->fpga_product_id, p_init->fpga_version, + p_init->fpga_revision); + } else { + time_t fpga_build_time = p_init->fpga_build_time; + + fprintf(fh_out, "%04d-%02d-%02d: 0x%08lX: %s\n", + p_init->fpga_product_id, p_init->fpga_version, + p_init->fpga_revision, fpga_build_time, + (fpga_build_time ? ctime(&fpga_build_time) : + "NA\n")); + } + } + fprintf(fh_out, "\n"); /* end of records */ + fflush(fh_out); +} + +void fpga_mgr_log_dump(nt_fpga_mgr_t *p) +{ + int i; + + NT_LOG(DBG, NTHW, "%s: fpgas=%d\n", __func__, p->mn_fpgas); + for (i = 0; i < p->mn_fpgas; i++) { + nt_fpga_prod_init_t *p_init _unused = p->mpa_fpga_prod_init[i]; + NT_LOG(DBG, NTHW, "%s: fpga=%d/%d: %04d-%02d-%02d\n", __func__, + i, p->mn_fpgas, p_init->fpga_product_id, p_init->fpga_version, + p_init->fpga_revision); + } +} + +/* + * Fpga + */ +nt_fpga_t *fpga_new(void) +{ + nt_fpga_t *p = malloc(sizeof(nt_fpga_t)); + + if (p) + memset(p, 0, sizeof(nt_fpga_t)); + return p; +} + +void fpga_delete(nt_fpga_t *p) +{ + memset(p, 0, sizeof(nt_fpga_t)); + free(p); +} + +void fpga_delete_all(nt_fpga_t *p) +{ + int i; + + for (i = 0; i < p->mn_modules; i++) { + nt_module_t *p_mod = p->mpa_modules[i]; + + if (p_mod) + module_delete(p_mod); + } + + fpga_delete(p); +} + +void fpga_init(nt_fpga_t *p, nt_fpga_prod_init_t *fpga_prod_init, + struct fpga_info_s *p_fpga_info) +{ + int i; + + p->p_fpga_info = p_fpga_info; + p->mp_init = fpga_prod_init; + + p->m_item_id = fpga_prod_init->fpga_item_id; + p->m_product_id = fpga_prod_init->fpga_product_id; + p->m_fpga_version = fpga_prod_init->fpga_version; + p->m_fpga_revision = fpga_prod_init->fpga_revision; + p->m_fpga_patch_no = fpga_prod_init->fpga_patch_no; + p->m_fpga_build_no = fpga_prod_init->fpga_build_no; + p->m_fpga_build_time = fpga_prod_init->fpga_build_time; + + p->mn_params = fpga_prod_init->nb_prod_params; + + if (p->mn_params) { + p->mpa_params = malloc(p->mn_params * sizeof(nt_param_t *)); + if (p->mpa_params) { + memset(p->mpa_params, 0, + (p->mn_params * sizeof(nt_param_t *))); + for (i = 0; i < p->mn_params; i++) { + nt_param_t *p_param = param_new(); + + param_init(p_param, p, + &fpga_prod_init->product_params[i]); + p->mpa_params[i] = p_param; + } + } + } + + p->mn_modules = fpga_prod_init->nb_modules; + + if (p->mn_modules) { + p->mpa_modules = + malloc(fpga_prod_init->nb_modules * sizeof(nt_module_t *)); + if (p->mpa_modules) { + memset(p->mpa_modules, 0, + (p->mn_modules * sizeof(nt_module_t *))); + for (i = 0; i < p->mn_modules; i++) { + nt_module_t *p_mod = module_new(); + + module_init(p_mod, p, &fpga_prod_init->modules[i]); + p->mpa_modules[i] = p_mod; + } + } + } +} + +void fpga_set_debug_mode(nt_fpga_t *p, int n_debug_mode) +{ + int i; + + p->m_debug_mode = n_debug_mode; + + for (i = 0; i < p->mn_modules; i++) { + nt_module_t *p_mod = p->mpa_modules[i]; + + if (p_mod) + module_set_debug_mode(p_mod, n_debug_mode); + } +} + +nt_module_t *fpga_query_module(const nt_fpga_t *p, int id, int instance) +{ + int i; + + for (i = 0; i < p->mn_modules; i++) { + nt_module_t *p_mod = p->mpa_modules[i]; + + if (p_mod->m_mod_id == id && p_mod->m_instance == instance) + return p_mod; + } + return NULL; +} + +bool fpga_query(nt_fpga_t *p, int id, int instance) +{ + return (fpga_query_module(p, id, instance) != NULL); +} + +nt_fpga_module_init_t *fpga_lookup_init(nt_fpga_t *p, int id, int instance) +{ + int i; + + for (i = 0; i < p->mp_init->nb_modules; i++) { + nt_fpga_module_init_t *p_mod_init = &p->mp_init->modules[i]; + + if (p_mod_init->id == id && p_mod_init->instance == instance) + return p_mod_init; + } + return NULL; +} + +int fpga_get_product_param(const nt_fpga_t *p, const int n_param_id, + const int n_default_value) +{ + int i; + + for (i = 0; i < p->mn_params; i++) { + nt_param_t *p_param = p->mpa_params[i]; + + if (p_param->param_id == n_param_id) + return p_param->param_value; + } + + return n_default_value; +} + +int fpga_get_product_id(const nt_fpga_t *p) +{ + return p->m_product_id; +} + +int fpga_get_fpga_version(const nt_fpga_t *p) +{ + return p->m_fpga_version; +} + +int fpga_get_fpga_revision(const nt_fpga_t *p) +{ + return p->m_fpga_revision; +} + +void fpga_log_info(const nt_fpga_t *p _unused) +{ + NT_LOG(INF, NTHW, "FPGA: %d-%d-%d-%d-%d-%d (%08X)\n", p->m_item_id, + p->m_product_id, p->m_fpga_version, p->m_fpga_revision, + p->m_fpga_patch_no, p->m_fpga_build_no, p->m_fpga_build_time); +} + +void fpga_dump(const nt_fpga_t *p) +{ + NT_LOG(DBG, NTHW, "%s: id=%d ver=%d.%d params=%d modules=%d\n", + __func__, p->m_product_id, p->m_fpga_version, p->m_fpga_revision, + p->mn_params, p->mn_modules); + fpga_dump_params(p); + fpga_dump_modules(p); +} + +void fpga_dump_params(const nt_fpga_t *p) +{ + int i; + + NT_LOG(DBG, NTHW, "%s: params=%d\n", __func__, p->mn_params); + + for (i = 0; i < p->mn_params; i++) { + nt_param_t *p_par = p->mpa_params[i]; + + param_dump(p_par); + } +} + +void fpga_dump_modules(const nt_fpga_t *p) +{ + int i; + + NT_LOG(DBG, NTHW, "%s: modules=%d\n", __func__, p->mn_modules); + + for (i = 0; i < p->mn_modules; i++) { + nt_module_t *p_mod = p->mpa_modules[i]; + + module_dump(p_mod); + } +} + +/* + * Param + */ +nt_param_t *param_new(void) +{ + nt_param_t *p = malloc(sizeof(nt_param_t)); + return p; +} + +void param_delete(nt_param_t *p) +{ + if (p) { + memset(p, 0, sizeof(nt_param_t)); + free(p); + } +} + +void param_init(nt_param_t *p, nt_fpga_t *p_fpga, nt_fpga_prod_param_t *p_init) +{ + p->mp_owner = p_fpga; + p->mp_init = p_init; + + p->param_id = p_init->param_id; + p->param_value = p_init->param_value; +} + +void param_dump(const nt_param_t *p _unused) +{ + NT_LOG(DBG, NTHW, "%s: id=%d value=%d\n", __func__, p->param_id, + p->param_value); +} + +/* + * Module + */ +nt_module_t *module_new(void) +{ + nt_module_t *p = malloc(sizeof(nt_module_t)); + return p; +} + +void module_delete(nt_module_t *p) +{ + int i; + + for (i = 0; i < p->mn_registers; i++) { + nt_register_t *p_reg = p->mpa_registers[i]; + + if (p_reg) + register_delete(p_reg); + } + memset(p, 0, sizeof(nt_module_t)); + free(p); +} + +void module_init(nt_module_t *p, nt_fpga_t *p_fpga, nt_fpga_module_init_t *p_init) +{ + int i; + + p->mp_owner = p_fpga; + p->mp_init = p_init; + + p->m_mod_id = p_init->id; + p->m_instance = p_init->instance; + + /* Copy debug mode from owner */ + if (p->mp_owner) + p->m_debug_mode = p->mp_owner->m_debug_mode; + + else + p->m_debug_mode = 0; + + p->m_mod_def_id = p_init->def_id; + p->m_major_version = p_init->major_version; + p->m_minor_version = p_init->minor_version; + p->m_bus = p_init->bus_id; + p->m_addr_base = p_init->addr_base; + + p->mn_registers = p_init->nb_registers; + if (p->mn_registers) { + p->mpa_registers = + malloc(p->mn_registers * sizeof(nt_register_t *)); + if (p->mpa_registers) { + memset(p->mpa_registers, 0, + (p->mn_registers * sizeof(nt_register_t *))); + for (i = 0; i < p->mn_registers; i++) { + nt_register_t *p_reg = register_new(); + + register_init(p_reg, p, &p_init->registers[i]); + p->mpa_registers[i] = p_reg; + } + } + } +} + +void module_init2(nt_module_t *p, nt_fpga_t *p_fpga, int mod_id, int instance, + int debug_mode) +{ + nt_fpga_module_init_t *p_init = NULL; + + p_init = fpga_lookup_init(p_fpga, mod_id, instance); + module_init(p, p_fpga, p_init); + + /* set debug mode after regulat init... */ + p->m_debug_mode = debug_mode; +} + +void module_dump(const nt_module_t *p) +{ + NT_LOG(DBG, NTHW, + "%s: id=%d inst=%d def=%d ver=%d.%d busid=%d base=0x%X regs=%d\n", + __func__, p->m_mod_id, p->m_instance, p->m_mod_def_id, + p->m_major_version, p->m_minor_version, p->m_bus, p->m_addr_base, + p->mn_registers); + module_dump_registers(p); +} + +void module_dump_registers(const nt_module_t *p) +{ + int i; + + NT_LOG(DBG, NTHW, "%s: regs=%d\n", __func__, p->mn_registers); + + for (i = 0; i < p->mn_registers; i++) { + nt_register_t *p_reg = p->mpa_registers[i]; + + register_dump(p_reg); + } +} + +int module_get_major_version(const nt_module_t *p) +{ + return p->m_major_version; +} + +int module_get_minor_version(const nt_module_t *p) +{ + return p->m_minor_version; +} + +uint64_t module_get_version_packed64(const nt_module_t *p) +{ + return (((uint64_t)p->m_major_version & 0xFFFFFFFF) << 32) | + (p->m_minor_version & 0xFFFFFFFF); +} + +bool module_is_version_newer(const nt_module_t *p, int major_version, + int minor_version) +{ + if (major_version == p->m_major_version) + return p->m_minor_version >= minor_version; + return p->m_major_version >= major_version; +} + +static nt_register_t *module_lookup_register(nt_module_t *p, uint32_t id) +{ + int i; + nt_register_t *p_register = NULL; + + for (i = 0; i < p->mn_registers; i++) { + if (p->mpa_registers[i]->m_id == id) { + p_register = p->mpa_registers[i]; + break; + } + } + return p_register; +} + +nt_register_t *module_get_register(nt_module_t *p, uint32_t id) +{ + nt_register_t *p_register; + + if (p == NULL) { + NT_LOG(ERR, NTHW, "Illegal module context for register %d\n", + id); + return NULL; + } + + p_register = module_lookup_register(p, id); + if (!p_register) { + NT_LOG(ERR, NTHW, "Register %d not found in module: %s (%d)\n", + id, nthw_fpga_mod_id_to_str(p->m_mod_id), p->m_mod_id); + } + return p_register; +} + +nt_register_t *module_query_register(nt_module_t *p, uint32_t id) +{ + return module_lookup_register(p, id); +} + +int module_get_debug_mode(const nt_module_t *p) +{ + return p->m_debug_mode; +} + +void module_set_debug_mode(nt_module_t *p, unsigned int n_debug_mode) +{ + int i; + nt_register_t *p_register = NULL; + + p->m_debug_mode = n_debug_mode; + + for (i = 0; i < p->mn_registers; i++) { + p_register = p->mpa_registers[i]; + if (p_register) + register_set_debug_mode(p_register, n_debug_mode); + } +} + +int module_get_bus(const nt_module_t *p) +{ + return p->m_bus; +} + +uint32_t module_get_addr_base(const nt_module_t *p) +{ + return p->m_addr_base; +} + +void module_unsuppported(const nt_module_t *p) +{ + NT_LOG(ERR, NTHW, "Module %d not supported", p->mp_init->id); +} + +/* + * Register + */ +nt_register_t *register_new(void) +{ + nt_register_t *p = malloc(sizeof(nt_register_t)); + return p; +} + +void register_delete(nt_register_t *p) +{ + int i; + + for (i = 0; i < p->mn_fields; i++) { + nt_field_t *p_field = p->mpa_fields[i]; + + if (p_field) + field_delete(p_field); + } + + if (p->mp_shadow) + free(p->mp_shadow); + + if (p->mp_dirty) + free(p->mp_dirty); + + memset(p, 0, sizeof(nt_register_t)); + free(p); +} + +void register_init(nt_register_t *p, nt_module_t *p_module, + nt_fpga_register_init_t *p_init) +{ + int i; + + p->mp_owner = p_module; + + p->m_id = p_init->id; + p->mn_bit_width = p_init->bw; + p->mn_addr_rel = p_init->addr_rel; + p->m_addr = p_module->m_addr_base + p_init->addr_rel; + p->m_type = p_init->type; + p->m_len = + ((p_init->bw != (uint16_t)-1) ? + ((p_init->bw + 31) >> 5) : + 1); /* Old P200 registers have no bw at register level - default to BW=-1 */ + p->m_debug_mode = p_module->m_debug_mode; + + p->mn_fields = p_init->nb_fields; + if (p->mn_fields) { + p->mpa_fields = malloc(p->mn_fields * sizeof(nt_field_t *)); + + if (p->mpa_fields) { + memset(p->mpa_fields, 0, + (p->mn_fields * sizeof(nt_field_t *))); + for (i = 0; i < p->mn_fields; i++) { + nt_field_t *p_field = field_new(); + + field_init(p_field, p, &p_init->fields[i]); + p->mpa_fields[i] = p_field; + } + + p->mp_shadow = malloc(p->m_len * sizeof(uint32_t)); + if (p->mp_shadow) { + memset(p->mp_shadow, 0x00, + (p->m_len * sizeof(uint32_t))); + } + + p->mp_dirty = malloc(p->m_len * sizeof(bool)); + if (p->mp_dirty) { + memset(p->mp_dirty, 0x00, + (p->m_len * sizeof(bool))); + } + } + } +} + +void register_dump(const nt_register_t *p) +{ + NT_LOG(DBG, NTHW, + "%s(id=%d type=%d addr=0x%08X addrrel=0x%08X len=%d bw=%d\n", + __func__, p->m_id, p->m_type, p->m_addr, p->mn_addr_rel, p->m_len, + p->mn_bit_width); + register_dump_fields(p); +} + +void register_dump_fields(const nt_register_t *p) +{ + int i; + + NT_LOG(DBG, NTHW, "%s(addr=0x%08X fields=%d\n", __func__, p->m_addr, + p->mn_fields); + for (i = 0; i < p->mn_fields; i++) + field_dump(p->mpa_fields[i]); + NT_LOG(DBG, NTHW, "\n"); +} + +uint32_t register_get_address(const nt_register_t *p) +{ + return p->m_addr; +} + +void register_reset(const nt_register_t *p) +{ + int i; + nt_field_t *p_field = NULL; + + for (i = 0; i < p->mn_fields; i++) { + p_field = p->mpa_fields[i]; + if (p_field) + field_reset(p_field); + } +} + +static nt_field_t *register_lookup_field(const nt_register_t *p, uint32_t id) +{ + int i; + nt_field_t *p_field = NULL; + + if (!p) + return NULL; + + for (i = 0; i < p->mn_fields; i++) { + if (p->mpa_fields[i]->m_id == id) { + p_field = p->mpa_fields[i]; + break; + } + } + return p_field; +} + +nt_field_t *register_get_field(const nt_register_t *p, uint32_t id) +{ + nt_field_t *p_field; + + if (p == NULL) { + NT_LOG(ERR, NTHW, "Illegal register context for field %d\n", + id); + return NULL; + } + + p_field = register_lookup_field(p, id); + if (!p_field) { + NT_LOG(ERR, NTHW, "Field %d not found in module: %s (%d)\n", id, + nthw_fpga_mod_id_to_str(p->mp_owner->m_mod_id), + p->mp_owner->m_mod_id); + } + return p_field; +} + +nt_field_t *register_query_field(const nt_register_t *p, uint32_t id) +{ + return register_lookup_field(p, id); +} + +int register_get_bit_width(const nt_register_t *p) +{ + return p->mn_bit_width; +} + +uint32_t register_get_addr_rel(const nt_register_t *p) +{ + return p->mn_addr_rel; +} + +int register_get_debug_mode(const nt_module_t *p) +{ + return p->m_debug_mode; +} + +/* + * NOTE: do not set debug on fields - as register operation dumps typically are enough + */ +void register_set_debug_mode(nt_register_t *p, unsigned int n_debug_mode) +{ + int i; + nt_field_t *p_field = NULL; + + p->m_debug_mode = n_debug_mode; + + for (i = 0; i < p->mn_fields; i++) { + p_field = p->mpa_fields[i]; + if (p_field) + field_set_debug_mode(p_field, n_debug_mode); + } +} + +static int register_read_data(const nt_register_t *p) +{ + int rc = -1; + + const int n_bus_type_id = module_get_bus(p->mp_owner); + const uint32_t addr = p->m_addr; + const uint32_t len = p->m_len; + uint32_t *const p_data = p->mp_shadow; + + struct fpga_info_s *p_fpga_info = NULL; + + if (p && p->mp_owner && p->mp_owner->mp_owner) + p_fpga_info = p->mp_owner->mp_owner->p_fpga_info; + assert(p_fpga_info); + assert(p_data); + + rc = read_data(p_fpga_info, n_bus_type_id, addr, len, p_data); + return rc; +} + +static int register_read_data_tsc(const nt_register_t *p, uint64_t *p_tsc1, + uint64_t *p_tsc2) +{ + int rc = -1; + + const int n_bus_type_id = module_get_bus(p->mp_owner); + const uint32_t addr = p->m_addr; + const uint32_t len = p->m_len; + uint32_t *const p_data = p->mp_shadow; + + struct fpga_info_s *p_fpga_info = NULL; + + if (p && p->mp_owner && p->mp_owner->mp_owner) + p_fpga_info = p->mp_owner->mp_owner->p_fpga_info; + + rc = read_data_tsc(p_fpga_info, n_bus_type_id, addr, len, p_data, p_tsc1, p_tsc2); + + return rc; +} + +static int register_write_data(const nt_register_t *p, uint32_t cnt) +{ + int rc = -1; + + const int n_bus_type_id = module_get_bus(p->mp_owner); + const uint32_t addr = p->m_addr; + const uint32_t len = p->m_len; + uint32_t *const p_data = p->mp_shadow; + + struct fpga_info_s *p_fpga_info = NULL; + + if (p && p->mp_owner && p->mp_owner->mp_owner) + p_fpga_info = p->mp_owner->mp_owner->p_fpga_info; + assert(p_fpga_info); + assert(p_data); + + rc = write_data(p_fpga_info, n_bus_type_id, addr, (len * cnt), p_data); + + return rc; +} + +void register_get_val(const nt_register_t *p, uint32_t *p_data, uint32_t len) +{ + uint32_t i; + + if (len == (uint32_t)-1 || len > p->m_len) + len = p->m_len; + + assert(len <= p->m_len); + assert(p_data); + + for (i = 0; i < len; i++) + p_data[i] = p->mp_shadow[i]; +} + +uint32_t register_get_val32(const nt_register_t *p) +{ + uint32_t val = 0; + + register_get_val(p, &val, 1); + return val; +} + +void register_update(const nt_register_t *p) +{ + if (p && p->m_type != REGISTER_TYPE_WO) { + const char *const p_dev_name _unused = "NA"; + const int n_bus_type_id = module_get_bus(p->mp_owner); + + const char *const p_bus_name _unused = get_bus_name(n_bus_type_id); + const uint32_t addr _unused = p->m_addr; + const uint32_t len = p->m_len; + uint32_t *const p_data = p->mp_shadow; + + register_read_data(p); + if (p->m_debug_mode & ON_READ) { + uint32_t i = len; + + uint32_t *ptr _unused = p_data; + NT_LOG(DBG, NTHW, + "Register::read(Dev: %s, Bus: %s, Addr: 0x%08X, _cnt: %d, Data:", + p_dev_name, p_bus_name, addr, len); + while (i--) + NT_LOG(DBG, NTHW, " 0x%08X ", *ptr++); + NT_LOG(DBG, NTHW, ")\n"); + } + } +} + +uint32_t register_get_val_updated32(const nt_register_t *p) +{ + uint32_t val = 0; + + register_update(p); + register_get_val(p, &val, 1); + return val; +} + +void register_make_dirty(nt_register_t *p) +{ + uint32_t i; + + for (i = 0; i < p->m_len; i++) + p->mp_dirty[i] = true; +} + +void register_set_val(nt_register_t *p, const uint32_t *p_data, uint32_t len) +{ + assert(len <= p->m_len); + assert(p_data); + + if (len == (uint32_t)-1 || len > p->m_len) + len = p->m_len; + + if (p->mp_shadow != p_data) + memcpy(p->mp_shadow, p_data, (len * sizeof(uint32_t))); +} + +void register_set_val_flush(nt_register_t *p, const uint32_t *p_data, uint32_t len) +{ + register_set_val(p, p_data, len); + register_flush(p, 1); +} + +void register_flush(const nt_register_t *p, uint32_t cnt) +{ + int rc; + + if (p->m_type != REGISTER_TYPE_RO) { + const char *const p_dev_name = "NA"; + const int n_bus_type_id = module_get_bus(p->mp_owner); + const char *p_bus_name = get_bus_name(n_bus_type_id); + const uint32_t addr = p->m_addr; + const uint32_t len = p->m_len; + uint32_t *const p_data = p->mp_shadow; + uint32_t i; + + assert(len * cnt <= 256); + + if (p->m_debug_mode & ON_WRITE) { + uint32_t i = len * cnt; + uint32_t *ptr = p_data; + char *tmp_string = + ntlog_helper_str_alloc("Register::write"); + ntlog_helper_str_add(tmp_string, + "(Dev: %s, Bus: %s, Addr: 0x%08X, _cnt: %d, Data:", + p_dev_name, p_bus_name, addr, i); + while (i--) { + ntlog_helper_str_add(tmp_string, " 0x%08X", + *ptr++); + } + ntlog_helper_str_add(tmp_string, ")\n"); + NT_LOG(DBG, NTHW, "%s", tmp_string); + ntlog_helper_str_free(tmp_string); + } + + rc = register_write_data(p, cnt); + + if (rc) + NT_LOG(ERR, NTHW, "Register write error %d\n", rc); + + for (i = 0; i < cnt; i++) + p->mp_dirty[i] = false; + } +} + +void register_do_read_trig_ts(const nt_register_t *p, uint64_t *tsc1, + uint64_t *tsc2) +{ + register_read_data_tsc(p, tsc1, tsc2); +} + +void register_clr(nt_register_t *p) +{ + memset(p->mp_shadow, 0, p->m_len * sizeof(uint32_t)); + register_make_dirty(p); +} + +void register_set(nt_register_t *p) +{ + memset(p->mp_shadow, 0xff, p->m_len * sizeof(uint32_t)); + register_make_dirty(p); +} + +/* + * Field + */ +nt_field_t *field_new(void) +{ + nt_field_t *p = malloc(sizeof(nt_field_t)); + return p; +} + +void field_delete(nt_field_t *p) +{ + memset(p, 0, sizeof(nt_field_t)); + free(p); +} + +void field_init(nt_field_t *p, nt_register_t *p_reg, + const nt_fpga_field_init_t *p_init) +{ + p->mp_owner = p_reg; + + p->m_debug_mode = p_reg->m_debug_mode; + + p->m_id = p_init->id; + p->mn_bit_width = p_init->bw; + p->mn_bit_pos_low = p_init->low; + p->m_reset_val = (uint32_t)p_init->reset_val; + p->m_first_word = p_init->low / 32; + p->m_first_bit = p_init->low % 32; + p->m_front_mask = 0; + p->m_body_length = 0; + p->mn_words = (p_init->bw + 0x1f) / 0x20; + p->m_tail_mask = 0; + + { + int bits_remaining = p_init->bw; + int front_mask_length = 32 - p->m_first_bit; + + if (front_mask_length > bits_remaining) + front_mask_length = bits_remaining; + bits_remaining -= front_mask_length; + + p->m_front_mask = (uint32_t)(((1ULL << front_mask_length) - 1) + << p->m_first_bit); + + p->m_body_length = bits_remaining / 32; + bits_remaining -= p->m_body_length * 32; + p->m_tail_mask = (1 << bits_remaining) - 1; + + if (p->m_debug_mode >= 0x100) { + NT_LOG(DBG, NTHW, + "%s: fldid=%08d: [%08d:%08d] %08d/%08d: (%08d,%08d) (0x%08X,%08d,0x%08X)\n", + __func__, p_init->id, p_init->low, + (p_init->low + p_init->bw), p_init->bw, + ((p_init->bw + 31) / 32), p->m_first_word, + p->m_first_bit, p->m_front_mask, p->m_body_length, + p->m_tail_mask); + } + } +} + +int field_get_debug_mode(const nt_module_t *p) +{ + return p->m_debug_mode; +} + +void field_set_debug_mode(nt_field_t *p, unsigned int n_debug_mode) +{ + p->m_debug_mode = n_debug_mode; +} + +int field_get_bit_width(const nt_field_t *p) +{ + return p->mn_bit_width; +} + +int field_get_bit_pos_low(const nt_field_t *p) +{ + return p->mn_bit_pos_low; +} + +int field_get_bit_pos_high(const nt_field_t *p) +{ + return p->mn_bit_pos_low + p->mn_bit_width - 1; +} + +uint32_t field_get_mask(const nt_field_t *p) +{ + return p->m_front_mask; +} + +void field_reset(const nt_field_t *p) +{ + field_set_val32(p, (uint32_t)p->m_reset_val); +} + +uint32_t field_get_val_mask(const nt_field_t *p) +{ + return (p->m_front_mask >> p->mn_bit_pos_low); +} + +uint32_t field_get_reset_val(const nt_field_t *p) +{ + return (uint32_t)p->m_reset_val; +} + +void field_get_val(const nt_field_t *p, uint32_t *p_data, uint32_t len) +{ + uint32_t i; + uint32_t data_index = 0; + uint32_t shadow_index = p->m_first_word; + + union { + uint32_t w32[2]; + uint64_t w64; + } buf; + + (void)len; + assert(len == p->mn_words); + + /* handle front */ + buf.w32[0] = p->mp_owner->mp_shadow[shadow_index++] & p->m_front_mask; + + /* handle body */ + for (i = 0; i < p->m_body_length; i++) { + buf.w32[1] = p->mp_owner->mp_shadow[shadow_index++]; + buf.w64 = buf.w64 >> (p->m_first_bit); + assert(data_index < len); + p_data[data_index++] = buf.w32[0]; + buf.w64 = buf.w64 >> (32 - p->m_first_bit); + } + + /* handle tail */ + if (p->m_tail_mask) + buf.w32[1] = p->mp_owner->mp_shadow[shadow_index++] & p->m_tail_mask; + + else + buf.w32[1] = 0; + buf.w64 = buf.w64 >> (p->m_first_bit); + p_data[data_index++] = buf.w32[0]; + if (data_index < p->mn_words) + p_data[data_index++] = buf.w32[1]; +} + +void field_set_val(const nt_field_t *p, const uint32_t *p_data, uint32_t len) +{ + uint32_t i; + uint32_t data_index = 0; + uint32_t shadow_index = p->m_first_word; + + union { + uint32_t w32[2]; + uint64_t w64; + } buf; + + (void)len; + assert(len == p->mn_words); + + /* handle front */ + buf.w32[0] = 0; + buf.w32[1] = p_data[data_index++]; + buf.w64 = buf.w64 >> (32 - p->m_first_bit); + p->mp_owner->mp_shadow[shadow_index] = + (p->mp_owner->mp_shadow[shadow_index] & ~p->m_front_mask) | + (buf.w32[0] & p->m_front_mask); + shadow_index++; + + /* handle body */ + for (i = 0; i < p->m_body_length; i++) { + buf.w64 = buf.w64 >> (p->m_first_bit); + assert(data_index < len); + buf.w32[1] = p_data[data_index++]; + buf.w64 = buf.w64 >> (32 - p->m_first_bit); + p->mp_owner->mp_shadow[shadow_index++] = buf.w32[0]; + } + + /* handle tail */ + if (p->m_tail_mask) { + buf.w64 = buf.w64 >> (p->m_first_bit); + if (data_index < len) + buf.w32[1] = p_data[data_index]; + buf.w64 = buf.w64 >> (32 - p->m_first_bit); + p->mp_owner->mp_shadow[shadow_index] = + (p->mp_owner->mp_shadow[shadow_index] & ~p->m_tail_mask) | + (buf.w32[0] & p->m_tail_mask); + } + + register_make_dirty(p->mp_owner); +} + +void field_set_val_flush(const nt_field_t *p, const uint32_t *p_data, uint32_t len) +{ + field_set_val(p, p_data, len); + field_flush_register(p); +} + +uint32_t field_get_val32(const nt_field_t *p) +{ + uint32_t val; + + field_get_val(p, &val, 1); + return val; +} + +uint32_t field_get_updated(const nt_field_t *p) +{ + uint32_t val; + + register_update(p->mp_owner); + field_get_val(p, &val, 1); + + return val; +} + +void field_read_trig_with_tsc(const nt_field_t *p, uint64_t *tsc1, uint64_t *tsc2) +{ + register_do_read_trig_ts(p->mp_owner, tsc1, tsc2); +} + +void field_update_register(const nt_field_t *p) +{ + register_update(p->mp_owner); +} + +void field_flush_register(const nt_field_t *p) +{ + register_flush(p->mp_owner, 1); +} + +void field_set_val32(const nt_field_t *p, uint32_t val) +{ + field_set_val(p, &val, 1); +} + +void field_set_val_flush32(const nt_field_t *p, uint32_t val) +{ + field_set_val(p, &val, 1); + register_flush(p->mp_owner, 1); +} + +void field_clr_all(const nt_field_t *p) +{ + assert(p->m_body_length == 0); + field_set_val32(p, 0); +} + +void field_clr_flush(const nt_field_t *p) +{ + field_clr_all(p); + register_flush(p->mp_owner, 1); +} + +void field_set_all(const nt_field_t *p) +{ + assert(p->m_body_length == 0); + field_set_val32(p, ~0); +} + +void field_set_flush(const nt_field_t *p) +{ + field_set_all(p); + register_flush(p->mp_owner, 1); +} + +enum field_match { + FIELD_MATCH_CLR_ALL, + FIELD_MATCH_SET_ALL, + FIELD_MATCH_CLR_ANY, + FIELD_MATCH_SET_ANY, +}; + +static int field_wait_cond32(const nt_field_t *p, enum field_match e_match, + int n_poll_iterations, int n_poll_interval) +{ + const uint32_t n_mask = (1 << p->mn_bit_width) - 1; + + if (n_poll_iterations == -1) + n_poll_iterations = 10000; + if (n_poll_interval == -1) + n_poll_interval = 100; /* usec */ + + if (p->m_debug_mode) { + const char *const p_cond_name _unused = + ((e_match == FIELD_MATCH_SET_ALL) ? + "SetAll" : + ((e_match == FIELD_MATCH_CLR_ALL) ? + "ClrAll" : + ((e_match == FIELD_MATCH_CLR_ANY) ? + "ClrAny" : + "SetAny"))); + const char *const p_dev_name _unused = "NA"; + const char *const p_bus_name _unused = + get_bus_name(module_get_bus(p->mp_owner->mp_owner)); + uint32_t n_reg_addr _unused = register_get_address(p->mp_owner); + + uint32_t n_reg_mask _unused = + (((1 << p->mn_bit_width) - 1) << p->mn_bit_pos_low); + + NT_LOG(DBG, NTHW, + "Register::Field::wait%s32(Dev: %s, Bus: %s, Addr: 0x%08X, Mask: 0x%08X, Iterations: %d, Interval: %d)\n", + p_cond_name, p_dev_name, p_bus_name, n_reg_addr, n_reg_mask, + n_poll_iterations, n_poll_interval); + } + + while (true) { + uint32_t val = field_get_updated(p); + + if (e_match == FIELD_MATCH_SET_ANY && val != 0) { + return 0; + } else if (e_match == FIELD_MATCH_SET_ALL && val == n_mask) { + return 0; + } else if (e_match == FIELD_MATCH_CLR_ALL && val == 0) { + return 0; + } else if (e_match == FIELD_MATCH_CLR_ANY) { + uint32_t mask = field_get_mask(p); + + if (val != mask) + return 0; + } + + n_poll_iterations--; + if (n_poll_iterations <= 0) + return -1; + NT_OS_WAIT_USEC(n_poll_interval); + } + return 0; +} + +int field_wait_set_all32(const nt_field_t *p, int n_poll_iterations, + int n_poll_interval) +{ + return field_wait_cond32(p, FIELD_MATCH_SET_ALL, n_poll_iterations, + n_poll_interval); +} + +int field_wait_clr_all32(const nt_field_t *p, int n_poll_iterations, + int n_poll_interval) +{ + return field_wait_cond32(p, FIELD_MATCH_CLR_ALL, n_poll_iterations, + n_poll_interval); +} + +int field_wait_set_any32(const nt_field_t *p, int n_poll_iterations, + int n_poll_interval) +{ + return field_wait_cond32(p, FIELD_MATCH_SET_ANY, n_poll_iterations, + n_poll_interval); +} + +int field_wait_clr_any32(const nt_field_t *p, int n_poll_iterations, + int n_poll_interval) +{ + return field_wait_cond32(p, FIELD_MATCH_CLR_ANY, n_poll_iterations, + n_poll_interval); +} + +int field_wait_val_mask32(const nt_field_t *p, uint32_t n_wait_cond_value, + uint32_t n_wait_cond_mask, int n_poll_iterations, + int n_poll_interval) +{ + if (n_poll_iterations == -1) + n_poll_iterations = 10000; + if (n_poll_interval == -1) + n_poll_interval = 100; + + while (true) { + uint32_t val = field_get_updated(p); + + if (val == (n_wait_cond_value & n_wait_cond_mask)) + break; + n_poll_iterations--; + if (n_poll_iterations <= 0) + return -1; + NT_OS_WAIT_USEC(n_poll_interval); + } + return 0; +} + +void field_dump(const nt_field_t *p _unused) +{ + NT_LOG(DBG, NTHW, "%s: %02d: %02d %02d %02d: %02d: %X\n", __func__, + p->m_id, p->mn_bit_pos_low, (p->mn_bit_pos_low + p->mn_bit_width), + p->mn_bit_width, p->mn_words, p->m_reset_val); +} + +void field_dump_val(const nt_field_t *p) +{ + int i; + uint32_t buf[32]; + + field_get_val(p, buf, p->mn_words); + NT_LOG(DBG, NTHW, " @%d:", p->m_first_bit + p->m_first_word * 32); + NT_LOG(DBG, NTHW, "%X", buf[p->mn_words - 1]); + for (i = p->mn_words - 1; i > 0; i--) + NT_LOG(DBG, NTHW, "%08X", buf[i - 1]); + NT_LOG(DBG, NTHW, "\n"); +} + +void field_dump_init(const nt_fpga_field_init_t *p _unused) +{ + NT_LOG(DBG, NTHW, "%s: %02d: %02d %02d %02d: 0x%" PRIX64 "\n", __func__, + p->id, p->low, p->low + p->bw, p->bw, p->reset_val); +} + +/* + * nthw fpga model helpers + */ + +nt_fpga_t *nthw_get_fpga(struct fpga_info_s *p_fpga_info, uint64_t n_fpga_ident) +{ + nt_fpga_mgr_t *p_fpga_mgr = NULL; + nt_fpga_t *p_fpga = NULL; + int n_fpga_type_id, n_fpga_prod_id, n_fpga_ver_id, n_fpga_rev_id; + char s_fpga_prod_ver_rev_str[32]; + + p_fpga_mgr = fpga_mgr_new(); + fpga_mgr_init(p_fpga_mgr); + p_fpga = fpga_mgr_query_fpga(p_fpga_mgr, n_fpga_ident, p_fpga_info); + + n_fpga_type_id = FPGAID_TO_PRODUCTTYPE(n_fpga_ident); + n_fpga_prod_id = FPGAID_TO_PRODUCTCODE(n_fpga_ident); + n_fpga_ver_id = FPGAID_TO_VERSIONCODE(n_fpga_ident); + n_fpga_rev_id = FPGAID_TO_REVISIONCODE(n_fpga_ident); + + snprintf(s_fpga_prod_ver_rev_str, sizeof(s_fpga_prod_ver_rev_str), + "%04d-%04d-%02d-%02d", n_fpga_type_id, n_fpga_prod_id, n_fpga_ver_id, + n_fpga_rev_id); + + if (p_fpga == NULL) { + NT_LOG(ERR, NTHW, "%s: no match for FPGA: %s\n", __func__, + s_fpga_prod_ver_rev_str); + /* do not return here... */ + } + + if (p_fpga_mgr) { + fpga_mgr_delete(p_fpga_mgr); + p_fpga_mgr = NULL; + } + + return p_fpga; +} + +nt_module_t *nthw_get_module(nt_fpga_t *p_fpga, int n_mod, int n_instance) +{ + nt_module_t *p_mod = fpga_query_module(p_fpga, n_mod, n_instance); + return p_mod; +} + +nt_register_t *nthw_get_register(nt_module_t *p_mod, int n_reg) +{ + nt_register_t *p_reg = module_get_register(p_mod, n_reg); + return p_reg; +} + +nt_field_t *nthw_get_field(nt_register_t *p_reg, int n_fld) +{ + nt_field_t *p_fld = register_get_field(p_reg, n_fld); + return p_fld; +} diff --git a/drivers/net/ntnic/nthw/nthw_fpga_model.h b/drivers/net/ntnic/nthw/nthw_fpga_model.h new file mode 100644 index 0000000000..b00b7b6cfa --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_fpga_model.h @@ -0,0 +1,308 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_FPGA_MODEL_H__ +#define __NTHW_FPGA_MODEL_H__ + +#include +#include +#include "fpga_model.h" + +#ifndef FPGAID_TO_PRODUCTCODE +#define FPGAID_TO_PRODUCTTYPE(fpga_id) ((uint16_t)((fpga_id) >> 32) & 0xFF) +#define FPGAID_TO_PRODUCTCODE(fpga_id) ((uint16_t)((fpga_id) >> 16) & 0xFFFF) +#define FPGAID_TO_VERSIONCODE(fpga_id) ((uint16_t)((fpga_id) >> 8 & 0xFF)) +#define FPGAID_TO_REVISIONCODE(fpga_id) ((uint16_t)((fpga_id) >> 0 & 0xFF)) +#endif + +#define VERSION_PACKED64(_major_, _minor_) \ + ((((uint64_t)(_major_) & 0xFFFFFFFF) << 32) | ((_minor_) & 0xFFFFFFFF)) + +enum debug_mode { NO_DEBUG, ON_READ, ON_WRITE }; + +enum nthw_bus_type { + NTHW_BUS_UNKNOWN, + NTHW_BUS_BAR, + NTHW_BUS_PCI, + NTHW_BUS_NMB, + NTHW_BUS_NDM, + NTHW_BUS_RAB0, + NTHW_BUS_RAB1, + NTHW_BUS_RAB2 +}; + +struct nt_fpga_s; + +struct nt_param_s; + +struct nt_module_s; + +struct nt_register_s; + +struct nt_field_s; + +struct nt_fpga_mgr_s { + int mn_fpgas; + struct nt_fpga_prod_init **mpa_fpga_prod_init; +}; + +typedef struct nt_fpga_mgr_s nt_fpga_mgr_t; + +struct nt_fpga_s { + struct fpga_info_s *p_fpga_info; + + int m_item_id; + int m_product_id; + int m_fpga_version; + int m_fpga_revision; + int m_fpga_patch_no; + int m_fpga_build_no; + uint32_t m_fpga_build_time; + + int mn_params; + struct nt_param_s **mpa_params; + + int mn_modules; + struct nt_module_s **mpa_modules; + + nt_fpga_prod_init_t *mp_init; + + int m_debug_mode; +}; + +typedef struct nt_fpga_s nt_fpga_t; + +struct nt_param_s { + nt_fpga_t *mp_owner; + + int param_id; + int param_value; + + nt_fpga_prod_param_t *mp_init; +}; + +typedef struct nt_param_s nt_param_t; + +struct nt_module_s { + nt_fpga_t *mp_owner; + + int m_mod_id; + + int m_instance; + + int m_mod_def_id; + int m_major_version; + int m_minor_version; + + int m_bus; + uint32_t m_addr_base; + + int m_debug_mode; + + int mn_registers; + struct nt_register_s **mpa_registers; + + nt_fpga_module_init_t *mp_init; +}; + +typedef struct nt_module_s nt_module_t; + +struct nt_register_s { + nt_module_t *mp_owner; + + uint32_t m_id; + + uint32_t mn_bit_width; + uint32_t mn_addr_rel; + uint32_t m_addr; + uint32_t m_type; + uint32_t m_len; + + int m_debug_mode; + + int mn_fields; + struct nt_field_s **mpa_fields; + + uint32_t *mp_shadow; + bool *mp_dirty; + + nt_fpga_register_init_t *mp_init; +}; + +typedef struct nt_register_s nt_register_t; + +struct nt_field_s { + nt_register_t *mp_owner; + + uint32_t m_id; + + uint32_t mn_bit_width; + uint32_t mn_bit_pos_low; + uint32_t m_reset_val; + uint32_t m_first_word; + uint32_t m_first_bit; + uint32_t m_front_mask; + uint32_t m_body_length; + uint32_t mn_words; + uint32_t m_tail_mask; + + int m_debug_mode; + + nt_fpga_field_init_t *mp_init; +}; + +typedef struct nt_field_s nt_field_t; + +nt_fpga_mgr_t *fpga_mgr_new(void); +void fpga_mgr_init(nt_fpga_mgr_t *p); +void fpga_mgr_delete(nt_fpga_mgr_t *p); +nt_fpga_t *fpga_mgr_query_fpga(nt_fpga_mgr_t *p, uint64_t n_fpga_id, + struct fpga_info_s *p_fpga_info); + +void fpga_mgr_log_dump(nt_fpga_mgr_t *p); +void fpga_mgr_show(nt_fpga_mgr_t *p, FILE *out, int detail_level); + +nt_fpga_t *fpga_new(void); +void fpga_delete(nt_fpga_t *p); +void fpga_delete_all(nt_fpga_t *p); +void fpga_init(nt_fpga_t *p, nt_fpga_prod_init_t *fpga_prod_init, + struct fpga_info_s *p_fpga_info); + +int fpga_get_product_param(const nt_fpga_t *p, const int n_param_id, + const int default_value); +int fpga_get_product_id(const nt_fpga_t *p); +int fpga_get_fpga_version(const nt_fpga_t *p); +int fpga_get_fpga_revision(const nt_fpga_t *p); +nt_module_t *fpga_query_module(const nt_fpga_t *p, int id, int instance); +nt_fpga_module_init_t *fpga_lookup_init(nt_fpga_t *p, int id, int instance); +bool fpga_query(nt_fpga_t *p, int id, int instance); +void fpga_set_debug_mode(nt_fpga_t *p, int n_debug_mode); + +void fpga_log_info(const nt_fpga_t *p); +void fpga_dump(const nt_fpga_t *p); +void fpga_dump_params(const nt_fpga_t *p); +void fpga_dump_modules(const nt_fpga_t *p); + +nt_param_t *param_new(void); +void param_delete(nt_param_t *p); +void param_init(nt_param_t *p, nt_fpga_t *p_fpga, nt_fpga_prod_param_t *p_init); + +void param_dump(const nt_param_t *p); + +nt_module_t *module_new(void); +void module_delete(nt_module_t *p); +void module_init(nt_module_t *p, nt_fpga_t *p_fpga, + nt_fpga_module_init_t *p_init); +void module_init2(nt_module_t *p, nt_fpga_t *p_fpga, int mod_id, int instance, + int debug_mode); + +int module_get_major_version(const nt_module_t *p); +int module_get_minor_version(const nt_module_t *p); +uint64_t module_get_version_packed64(const nt_module_t *p); +bool module_is_version_newer(const nt_module_t *p, int major_version, + int minor_version); + +int module_get_bus(const nt_module_t *p); +nt_register_t *module_get_register(nt_module_t *p, uint32_t id); +nt_register_t *module_query_register(nt_module_t *p, uint32_t id); +int module_get_debug_mode(const nt_module_t *p); +void module_set_debug_mode(nt_module_t *p, unsigned int debug_mode); +uint32_t module_get_addr_base(const nt_module_t *p); +void module_unsuppported(const nt_module_t *p); + +void module_dump(const nt_module_t *p); +void module_dump_registers(const nt_module_t *p); + +nt_register_t *register_new(void); +void register_delete(nt_register_t *p); +void register_init(nt_register_t *p, nt_module_t *p_module, + nt_fpga_register_init_t *p_init); + +nt_field_t *register_get_field(const nt_register_t *p, uint32_t id); +nt_field_t *register_query_field(const nt_register_t *p, uint32_t id); + +uint32_t register_get_address(const nt_register_t *p); +uint32_t register_get_addr_rel(const nt_register_t *p); +int register_get_bit_width(const nt_register_t *p); +int register_get_debug_mode(const nt_module_t *p); +void register_set_debug_mode(nt_register_t *p, unsigned int debug_mode); + +void register_get_val(const nt_register_t *p, uint32_t *p_data, uint32_t len); +uint32_t register_get_val32(const nt_register_t *p); +uint32_t register_get_val_updated32(const nt_register_t *p); + +void register_set_val(nt_register_t *p, const uint32_t *p_data, uint32_t len); +void register_set_val_flush(nt_register_t *p, const uint32_t *p_data, + uint32_t len); + +void register_make_dirty(nt_register_t *p); +void register_update(const nt_register_t *p); +void register_reset(const nt_register_t *p); +void register_flush(const nt_register_t *p, uint32_t cnt); +void register_clr(nt_register_t *p); +void register_set(nt_register_t *p); + +void register_do_read_trig_ts(const nt_register_t *p, uint64_t *tsc1, + uint64_t *tsc2); + +void register_dump(const nt_register_t *p); +void register_dump_fields(const nt_register_t *p); + +nt_field_t *field_new(void); +void field_delete(nt_field_t *p); +void field_init(nt_field_t *p, nt_register_t *p_reg, + const nt_fpga_field_init_t *p_init); + +int field_get_debug_mode(const nt_module_t *p); +void field_set_debug_mode(nt_field_t *p, unsigned int n_debug_mode); +int field_get_bit_width(const nt_field_t *p); +int field_get_bit_pos_low(const nt_field_t *p); +int field_get_bit_pos_high(const nt_field_t *p); +uint32_t field_get_mask(const nt_field_t *p); +void field_reset(const nt_field_t *p); +uint32_t field_get_reset_val(const nt_field_t *p); +void field_get_val(const nt_field_t *p, uint32_t *p_data, uint32_t len); +void field_set_val(const nt_field_t *p, const uint32_t *p_data, uint32_t len); +void field_set_val_flush(const nt_field_t *p, const uint32_t *p_data, + uint32_t len); +uint32_t field_get_val_mask(const nt_field_t *p); +uint32_t field_get_val32(const nt_field_t *p); +uint32_t field_get_updated(const nt_field_t *p); +void field_read_trig_with_tsc(const nt_field_t *p, uint64_t *tsc1, uint64_t *tsc2); +void field_update_register(const nt_field_t *p); +void field_flush_register(const nt_field_t *p); +void field_set_val32(const nt_field_t *p, uint32_t val); +void field_set_val_flush32(const nt_field_t *p, uint32_t val); +void field_clr_all(const nt_field_t *p); +void field_clr_flush(const nt_field_t *p); +void field_set_all(const nt_field_t *p); +void field_set_flush(const nt_field_t *p); + +int field_wait_clr_all32(const nt_field_t *p, int n_poll_iterations, + int n_poll_interval); +int field_wait_set_all32(const nt_field_t *p, int n_poll_iterations, + int n_poll_interval); + +int field_wait_clr_any32(const nt_field_t *p, int n_poll_iterations, + int n_poll_interval); +int field_wait_set_any32(const nt_field_t *p, int n_poll_iterations, + int n_poll_interval); + +int field_wait_val_mask32(const nt_field_t *p, uint32_t n_wait_cond_value, + uint32_t n_wait_cond_mask, int n_poll_iterations, + int n_poll_interval); + +void field_dump(const nt_field_t *p); +void field_dump_val(const nt_field_t *p); +void field_dump_init(const nt_fpga_field_init_t *p); + +/* + * nthw helpers + */ +nt_fpga_t *nthw_get_fpga(struct fpga_info_s *p_fpga_info, uint64_t n_fpga_ident); +nt_module_t *nthw_get_module(nt_fpga_t *p_fpga, int n_mod, int n_instance); +nt_register_t *nthw_get_register(nt_module_t *p_mod, int n_reg); +nt_field_t *nthw_get_field(nt_register_t *p_reg, int n_fld); + +#endif /* __NTHW_FPGA_MODEL_H__ */ diff --git a/drivers/net/ntnic/nthw/nthw_helper.h b/drivers/net/ntnic/nthw/nthw_helper.h new file mode 100644 index 0000000000..22f6a0d471 --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_helper.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_HELPER_H__ +#define __NTHW_HELPER_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif + +#endif /* __NTHW_HELPER_H__ */ diff --git a/drivers/net/ntnic/nthw/nthw_platform.c b/drivers/net/ntnic/nthw/nthw_platform.c new file mode 100644 index 0000000000..203947e03a --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_platform.c @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nthw_platform_drv.h" + +nthw_adapter_id_t nthw_platform_get_nthw_adapter_id(const uint16_t n_pci_device_id) +{ + switch (n_pci_device_id) { + case NT_HW_PCI_DEVICE_ID_NT40E3: + return NT_HW_ADAPTER_ID_NT40E3; + case NT_HW_PCI_DEVICE_ID_NT100E3: + return NT_HW_ADAPTER_ID_NT100E3; + case NT_HW_PCI_DEVICE_ID_NT80E3: + return NT_HW_ADAPTER_ID_NT80E3; + case NT_HW_PCI_DEVICE_ID_NT40A00: + return NT_HW_ADAPTER_ID_NT40E3; + case NT_HW_PCI_DEVICE_ID_NT40A01: + return NT_HW_ADAPTER_ID_NT40E3; + case NT_HW_PCI_DEVICE_ID_NT200E3: + return NT_HW_ADAPTER_ID_NT200E3; + case NT_HW_PCI_DEVICE_ID_NT200A01: + return NT_HW_ADAPTER_ID_NT200A01; + case NT_HW_PCI_DEVICE_ID_NT200D01: + return NT_HW_ADAPTER_ID_NT200D01; + case NT_HW_PCI_DEVICE_ID_NT200A02: + return NT_HW_ADAPTER_ID_NT200A02; + case NT_HW_PCI_DEVICE_ID_NT50B01: + return NT_HW_ADAPTER_ID_NT50B01; + case NT_HW_PCI_DEVICE_ID_NT100A01: + return NT_HW_ADAPTER_ID_NT100A01; + default: + return NT_HW_ADAPTER_ID_UNKNOWN; + } +} diff --git a/drivers/net/ntnic/nthw/nthw_platform_drv.h b/drivers/net/ntnic/nthw/nthw_platform_drv.h new file mode 100644 index 0000000000..fee2dc4853 --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_platform_drv.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_PLATFORM_DRV_H__ +#define __NTHW_PLATFORM_DRV_H__ + +#include "nthw_helper.h" + +#define NT_HW_PCI_VENDOR_ID (0x18f4) + +#define NT_HW_PCI_DEVICE_ID_NT40E3 (0x145) +#define NT_HW_PCI_DEVICE_ID_NT100E3 (0x155) +#define NT_HW_PCI_DEVICE_ID_NT80E3 (0x165) +#define NT_HW_PCI_DEVICE_ID_NT40A00 (0x175) +#define NT_HW_PCI_DEVICE_ID_NT40A01 (0x185) +#define NT_HW_PCI_DEVICE_ID_NT200E3 (0x195) +#define NT_HW_PCI_DEVICE_ID_NT200A01 (0x1A5) +#define NT_HW_PCI_DEVICE_ID_NT200D01 (0x1B5) +#define NT_HW_PCI_DEVICE_ID_NT200A02 (0x1C5) +#define NT_HW_PCI_DEVICE_ID_NT50B01 (0x1D5) +#define NT_HW_PCI_DEVICE_ID_NT100A01 (0x1E5) + +enum nthw_adapter_id_e { + NT_HW_ADAPTER_ID_UNKNOWN = 0, + NT_HW_ADAPTER_ID_NT40E3, + NT_HW_ADAPTER_ID_NT40A01 = NT_HW_ADAPTER_ID_NT40E3, + NT_HW_ADAPTER_ID_NT50B01, + NT_HW_ADAPTER_ID_NT80E3, + NT_HW_ADAPTER_ID_NT100E3, + NT_HW_ADAPTER_ID_NT100A01, + NT_HW_ADAPTER_ID_NT200E3, + NT_HW_ADAPTER_ID_NT200A01, + NT_HW_ADAPTER_ID_NT200D01, + NT_HW_ADAPTER_ID_NT200A02, +}; + +typedef enum nthw_adapter_id_e nthw_adapter_id_t; + +nthw_adapter_id_t nthw_platform_get_nthw_adapter_id(const uint16_t n_pci_device_id); + +#endif /* __NTHW_PLATFORM_DRV_H__ */ diff --git a/drivers/net/ntnic/nthw/nthw_profile.h b/drivers/net/ntnic/nthw/nthw_profile.h new file mode 100644 index 0000000000..2fcb7b4adf --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_profile.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_PROFILE_H__ +#define __NTHW_PROFILE_H__ + +enum fpga_info_profile { + FPGA_INFO_PROFILE_UNKNOWN = 0, + FPGA_INFO_PROFILE_VSWITCH = 1, + FPGA_INFO_PROFILE_INLINE = 2, + FPGA_INFO_PROFILE_CAPTURE = 3, +}; + +#endif /* __NTHW_PROFILE_H__ */ diff --git a/drivers/net/ntnic/nthw/nthw_rac.c b/drivers/net/ntnic/nthw/nthw_rac.c new file mode 100644 index 0000000000..f3f6bee223 --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_rac.c @@ -0,0 +1,976 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nt_util.h" +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" +#include "nthw_rac.h" + +#include + +/* + * Prevent that RAB echo debug trace ever gets into a release build + */ +#if defined(DEBUG) +#undef RAB_DEBUG_ECHO +#else +#undef RAB_DEBUG_ECHO +#endif /* DEBUG */ + +#define RAB_DMA_WAIT (1000000) +#define RAB_DMA_BUF_CNT (0x4000) + +#define RAB_READ (0x01) +#define RAB_WRITE (0x02) +#define RAB_ECHO (0x08) +#define RAB_COMPLETION (0x0F) + +#define RAB_READ_ECHO (RAB_READ | RAB_ECHO) +#define RAB_WRITE_ECHO (RAB_WRITE | RAB_ECHO) + +#define RAB_OPR_LO (28) +#define RAB_OPR_HI (31) +#define RAB_OPR_BW (4) + +#define RAB_CNT_LO (20) +#define RAB_CNT_HI (27) +#define RAB_CNT_BW (8) + +#define RAB_BUSID_LO (16) +#define RAB_BUSID_HI (19) +#define RAB_BUSID_BW (4) + +#define RAB_ADDR_LO (0) +#define RAB_ADDR_HI (15) +#define RAB_ADDR_BW (16) + +nthw_rac_t *nthw_rac_new(void) +{ + nthw_rac_t *p = malloc(sizeof(nthw_rac_t)); + + memset(p, 0, sizeof(nthw_rac_t)); + return p; +} + +void nthw_rac_delete(nthw_rac_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_rac_t)); + free(p); + } +} + +int nthw_rac_init(nthw_rac_t *p, nt_fpga_t *p_fpga, struct fpga_info_s *p_fpga_info) +{ + assert(p_fpga_info); + + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + nt_module_t *mod = fpga_query_module(p_fpga, MOD_RAC, 0); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: RAC %d: no such instance\n", + p_adapter_id_str, 0); + return -1; + } + + p->mp_fpga = p_fpga; + p->mp_mod_rac = mod; + + { + /* + * RAC is a primary communication channel + * turn off debug by default + * except for rac_rab_init + */ + const int n_debug_mode = module_get_debug_mode(p->mp_mod_rac); + + if (n_debug_mode && n_debug_mode <= 0xff) { + module_set_debug_mode(p->mp_mod_rac, 0); + register_set_debug_mode(p->mp_reg_rab_init, n_debug_mode); + } + } + + /* Params */ + p->mn_param_rac_rab_interfaces = + fpga_get_product_param(p->mp_fpga, NT_RAC_RAB_INTERFACES, 3); + NT_LOG(DBG, NTHW, "%s: NT_RAC_RAB_INTERFACES=%d\n", p_adapter_id_str, + p->mn_param_rac_rab_interfaces); + + p->mn_param_rac_rab_ob_update = + fpga_get_product_param(p->mp_fpga, NT_RAC_RAB_OB_UPDATE, 0); + NT_LOG(DBG, NTHW, "%s: NT_RAC_RAB_OB_UPDATE=%d\n", p_adapter_id_str, + p->mn_param_rac_rab_ob_update); + + /* Optional dummy test registers */ + p->mp_reg_dummy0 = module_query_register(p->mp_mod_rac, RAC_DUMMY0); + p->mp_reg_dummy1 = module_query_register(p->mp_mod_rac, RAC_DUMMY1); + p->mp_reg_dummy2 = module_query_register(p->mp_mod_rac, RAC_DUMMY2); + + p->mp_reg_rab_init = module_get_register(p->mp_mod_rac, RAC_RAB_INIT); + p->mp_fld_rab_init = register_get_field(p->mp_reg_rab_init, RAC_RAB_INIT_RAB); + p->mn_fld_rab_init_bw = field_get_bit_width(p->mp_fld_rab_init); + p->mn_fld_rab_init_mask = field_get_mask(p->mp_fld_rab_init); + + /* RAC_RAB_INIT_RAB reg/field sanity checks: */ + assert(p->mn_fld_rab_init_mask == ((1UL << p->mn_fld_rab_init_bw) - 1)); + assert(p->mn_fld_rab_init_bw == p->mn_param_rac_rab_interfaces); + + p->mp_reg_dbg_ctrl = module_query_register(p->mp_mod_rac, RAC_DBG_CTRL); + if (p->mp_reg_dbg_ctrl) { + p->mp_fld_dbg_ctrl = + register_query_field(p->mp_reg_dbg_ctrl, RAC_DBG_CTRL_C); + } else { + p->mp_fld_dbg_ctrl = NULL; + } + p->mp_reg_dbg_data = module_query_register(p->mp_mod_rac, RAC_DBG_DATA); + if (p->mp_reg_dbg_data) { + p->mp_fld_dbg_data = + register_query_field(p->mp_reg_dbg_data, RAC_DBG_DATA_D); + } else { + p->mp_reg_dbg_data = NULL; + } + p->mp_reg_rab_ib_data = module_get_register(p->mp_mod_rac, RAC_RAB_IB_DATA); + p->mp_fld_rab_ib_data = + register_get_field(p->mp_reg_rab_ib_data, RAC_RAB_IB_DATA_D); + + p->mp_reg_rab_ob_data = module_get_register(p->mp_mod_rac, RAC_RAB_OB_DATA); + p->mp_fld_rab_ob_data = + register_get_field(p->mp_reg_rab_ob_data, RAC_RAB_OB_DATA_D); + + p->mp_reg_rab_buf_free = module_get_register(p->mp_mod_rac, RAC_RAB_BUF_FREE); + p->mp_fld_rab_buf_free_ib_free = + register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_IB_FREE); + p->mp_fld_rab_buf_free_ib_ovf = + register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_IB_OVF); + p->mp_fld_rab_buf_free_ob_free = + register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_OB_FREE); + p->mp_fld_rab_buf_free_ob_ovf = + register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_OB_OVF); + p->mp_fld_rab_buf_free_timeout = + register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_TIMEOUT); + + p->mp_reg_rab_buf_used = module_get_register(p->mp_mod_rac, RAC_RAB_BUF_USED); + p->mp_fld_rab_buf_used_ib_used = + register_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_IB_USED); + p->mp_fld_rab_buf_used_ob_used = + register_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_OB_USED); + p->mp_fld_rab_buf_used_flush = + register_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_FLUSH); + + /* + * RAC_RAB_DMA regs are optional - only found in real NT4GA - not found in 9231/9232 and + * earlier + */ + p->mp_reg_rab_dma_ib_lo = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_LO); + p->mp_fld_rab_dma_ib_lo_phy_addr = + register_get_field(p->mp_reg_rab_dma_ib_lo, RAC_RAB_DMA_IB_LO_PHYADDR); + + p->mp_reg_rab_dma_ib_hi = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_HI); + p->mp_fld_rab_dma_ib_hi_phy_addr = + register_get_field(p->mp_reg_rab_dma_ib_hi, RAC_RAB_DMA_IB_HI_PHYADDR); + + p->mp_reg_rab_dma_ob_lo = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_LO); + p->mp_fld_rab_dma_ob_lo_phy_addr = + register_get_field(p->mp_reg_rab_dma_ob_lo, RAC_RAB_DMA_OB_LO_PHYADDR); + + p->mp_reg_rab_dma_ob_hi = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_HI); + p->mp_fld_rab_dma_ob_hi_phy_addr = + register_get_field(p->mp_reg_rab_dma_ob_hi, RAC_RAB_DMA_OB_HI_PHYADDR); + + p->mp_reg_rab_dma_ib_wr = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_WR); + p->mp_fld_rab_dma_ib_wr_ptr = + register_get_field(p->mp_reg_rab_dma_ib_wr, RAC_RAB_DMA_IB_WR_PTR); + + p->mp_reg_rab_dma_ib_rd = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_RD); + p->mp_fld_rab_dma_ib_rd_ptr = + register_get_field(p->mp_reg_rab_dma_ib_rd, RAC_RAB_DMA_IB_RD_PTR); + + p->mp_reg_rab_dma_ob_wr = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_WR); + p->mp_fld_rab_dma_ob_wr_ptr = + register_get_field(p->mp_reg_rab_dma_ob_wr, RAC_RAB_DMA_OB_WR_PTR); + + p->rac_rab_init_addr = register_get_address(p->mp_reg_rab_init); + p->rac_rab_ib_data_addr = register_get_address(p->mp_reg_rab_ib_data); + p->rac_rab_ob_data_addr = register_get_address(p->mp_reg_rab_ob_data); + p->rac_rab_buf_free_addr = register_get_address(p->mp_reg_rab_buf_free); + p->rac_rab_buf_used_addr = register_get_address(p->mp_reg_rab_buf_used); + + /* + * RAC_RAB_DMA regs are optional - only found in real NT4GA - + * not found in 9231/9232 and earlier + */ + + p->rac_rab_dma_ib_lo_addr = register_get_address(p->mp_reg_rab_dma_ib_lo); + p->rac_rab_dma_ib_hi_addr = register_get_address(p->mp_reg_rab_dma_ib_hi); + p->rac_rab_dma_ob_lo_addr = register_get_address(p->mp_reg_rab_dma_ob_lo); + p->rac_rab_dma_ob_hi_addr = register_get_address(p->mp_reg_rab_dma_ob_hi); + p->rac_rab_dma_ib_rd_addr = register_get_address(p->mp_reg_rab_dma_ib_rd); + p->rac_rab_dma_ob_wr_addr = register_get_address(p->mp_reg_rab_dma_ob_wr); + p->rac_rab_dma_ib_wr_addr = register_get_address(p->mp_reg_rab_dma_ib_wr); + + p->rac_rab_buf_free_ib_free_mask = + field_get_mask(p->mp_fld_rab_buf_free_ib_free); + p->rac_rab_buf_free_ob_free_mask = + field_get_mask(p->mp_fld_rab_buf_free_ob_free); + p->rac_rab_buf_used_ib_used_mask = + field_get_mask(p->mp_fld_rab_buf_used_ib_used); + p->rac_rab_buf_used_ob_used_mask = + field_get_mask(p->mp_fld_rab_buf_used_ob_used); + + p->rac_rab_buf_used_flush_mask = field_get_mask(p->mp_fld_rab_buf_used_flush); + + p->rac_rab_buf_used_ob_used_low = + field_get_bit_pos_low(p->mp_fld_rab_buf_used_ob_used); + + p->mp_reg_rab_nmb_rd = module_query_register(p->mp_mod_rac, RAC_NMB_RD_ADR); + if (p->mp_reg_rab_nmb_rd) + p->rac_nmb_rd_adr_addr = register_get_address(p->mp_reg_rab_nmb_rd); + + p->mp_reg_rab_nmb_data = module_query_register(p->mp_mod_rac, RAC_NMB_DATA); + if (p->mp_reg_rab_nmb_data) + p->rac_nmb_data_addr = register_get_address(p->mp_reg_rab_nmb_data); + + p->mp_reg_rab_nmb_wr = module_query_register(p->mp_mod_rac, RAC_NMB_WR_ADR); + if (p->mp_reg_rab_nmb_wr) + p->rac_nmb_wr_adr_addr = register_get_address(p->mp_reg_rab_nmb_wr); + + p->mp_reg_rab_nmb_status = + module_query_register(p->mp_mod_rac, RAC_NMB_STATUS); + if (p->mp_reg_rab_nmb_status) { + p->rac_nmb_status_addr = + register_get_address(p->mp_reg_rab_nmb_status); + } + + p->m_dma = NULL; + + pthread_mutex_init(&p->m_mutex, NULL); + + return 0; +} + +int nthw_rac_get_rab_interface_count(const nthw_rac_t *p) +{ + return p->mn_param_rac_rab_interfaces; +} + +static inline int nthw_rac_wait_for_rab_done(const nthw_rac_t *p, uint32_t address, + uint32_t word_cnt) +{ + const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info; + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + uint32_t used = 0; + uint32_t retry; + + for (retry = 0; retry < 100000; retry++) { + nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &used); + used = (used & p->rac_rab_buf_used_ob_used_mask) >> + p->rac_rab_buf_used_ob_used_low; + if (used >= word_cnt) + break; + } + + if (used < word_cnt) { + NT_LOG(ERR, NTHW, + "%s: Fail rab bus r/w addr=0x%08X used=%x wordcount=%d\n", + p_adapter_id_str, address, used, word_cnt); + return -1; + } + return 0; +} + +/* + * NT_PCI_REG_P9xyz_RAC_RAB_INIT + * + * Initializes (resets) the programmable registers on the Register Access Buses (RAB). + * This initialization must be performed by software as part of the driver load procedure. + * + * Bit n of this field initializes the programmable registers on RAB interface n. + * Software must write one to the bit and then clear the bit again. + * + * All RAB module registers will be reset to their defaults. + * This includes the product specific RESET module (eg RST9xyz) + * As a consequence of this behavior the official reset sequence + * must be excersised - as all RAB modules will be held in reset. + */ +int nthw_rac_rab_init(nthw_rac_t *p, uint32_t n_rab_intf_mask) +{ + /* + * Write rac_rab_init + * Perform operation twice - first to get trace of operation - + * second to get things done... + */ + const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info; + + field_set_val_flush32(p->mp_fld_rab_init, n_rab_intf_mask); + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_init_addr, n_rab_intf_mask); + return 0; +} + +int nthw_rac_rab_reset(nthw_rac_t *p) +{ + const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info; + + const char *const p_adapter_id_str _unused = p_fpga_info->mp_adapter_id_str; + + /* RAC RAB bus "flip/flip" reset */ + const int n_rac_rab_bus_count = nthw_rac_get_rab_interface_count(p); + const int n_rac_rab_bus_mask = (1 << n_rac_rab_bus_count) - 1; + + NT_LOG(DBG, NTHW, "%s: NT_RAC_RAB_INTERFACES=%d (0x%02X)\n", + p_adapter_id_str, n_rac_rab_bus_count, n_rac_rab_bus_mask); + assert(n_rac_rab_bus_count); + assert(n_rac_rab_bus_mask); + + /* RAC RAB bus "flip/flip" reset first stage - new impl (ref RMT#37020) */ + nthw_rac_rab_init(p, 0); + nthw_rac_rab_init(p, n_rac_rab_bus_mask); + nthw_rac_rab_init(p, n_rac_rab_bus_mask & ~0x01); + + return 0; +} + +int nthw_rac_rab_setup(nthw_rac_t *p) +{ + int rc = 0; + + const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info; + uint32_t n_dma_buf_size = 2L * RAB_DMA_BUF_CNT * sizeof(uint32_t); + const size_t align_size = ALIGN_SIZE(n_dma_buf_size); + int numa_node = p_fpga_info->numa_node; + uint64_t dma_addr; + uint32_t buf; + + if (!p->m_dma) { + struct nt_dma_s *vfio_dma; + /* FPGA needs Page alignment (4K) */ + vfio_dma = nt_dma_alloc(align_size, 0x1000, numa_node); + + if (vfio_dma == NULL) { + NT_LOG(ERR, ETHDEV, "%s: nt_dma_alloc failed\n", + __func__); + return -1; + } + p->m_dma_in_buf = (uint32_t *)vfio_dma->addr; + p->m_dma_out_buf = p->m_dma_in_buf + RAB_DMA_BUF_CNT; + p->m_dma = vfio_dma; + } + + /* Setup DMA on the adapter */ + dma_addr = p->m_dma->iova; + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ib_lo_addr, + dma_addr & 0xffffffff); + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ib_hi_addr, + (uint32_t)(dma_addr >> 32) & 0xffffffff); + dma_addr += RAB_DMA_BUF_CNT * sizeof(uint32_t); + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ob_lo_addr, + dma_addr & 0xffffffff); + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ob_hi_addr, + (uint32_t)(dma_addr >> 32) & 0xffffffff); + + /* Set initial value of internal pointers */ + nthw_rac_reg_read32(p_fpga_info, p->rac_rab_dma_ib_rd_addr, &buf); + p->m_dma_in_ptr_wr = (uint16_t)(buf / sizeof(uint32_t)); + nthw_rac_reg_read32(p_fpga_info, p->rac_rab_dma_ob_wr_addr, &buf); + p->m_dma_out_ptr_rd = (uint16_t)(buf / sizeof(uint32_t)); + p->m_in_free = RAB_DMA_BUF_CNT; + + return rc; +} + +int nthw_rac_rab_dma_begin(nthw_rac_t *p) +{ + const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info; + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + + pthread_mutex_lock(&p->m_mutex); + + if (p->m_dma_active) { + pthread_mutex_unlock(&p->m_mutex); + NT_LOG(ERR, NTHW, + "%s: DMA begin requested, but a DMA transaction is already active\n", + p_adapter_id_str); + return -1; + } + + p->m_dma_active = true; + + return 0; +} + +static void nthw_rac_rab_dma_activate(nthw_rac_t *p) +{ + const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info; + const uint32_t completion = RAB_COMPLETION << RAB_OPR_LO; + + /* Write completion word */ + p->m_dma_in_buf[p->m_dma_in_ptr_wr] = completion; + p->m_dma_in_ptr_wr = + (uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1)); + + /* Clear output completion word */ + p->m_dma_out_buf[p->m_dma_out_ptr_rd] = 0; + + /* _update DMA pointer and start transfer */ + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ib_wr_addr, + (uint32_t)(p->m_dma_in_ptr_wr * sizeof(uint32_t))); +} + +static int nthw_rac_rab_dma_wait(nthw_rac_t *p) +{ + const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info; + const uint32_t completion = RAB_COMPLETION << RAB_OPR_LO; + uint32_t i; + + for (i = 0; i < RAB_DMA_WAIT; i++) { + NT_OS_WAIT_USEC_POLL(1); + if ((p->m_dma_out_buf[p->m_dma_out_ptr_rd] & completion) == + completion) + break; + } + + if (i == RAB_DMA_WAIT) { + NT_LOG(ERR, NTHW, + "%s: RAB: Unexpected value of completion (0x%08X)\n", + p_fpga_info->mp_adapter_id_str, + p->m_dma_out_buf[p->m_dma_out_ptr_rd]); + return -1; + } + + p->m_dma_out_ptr_rd = + (uint16_t)((p->m_dma_out_ptr_rd + 1) & (RAB_DMA_BUF_CNT - 1)); + p->m_in_free = RAB_DMA_BUF_CNT; + + return 0; +} + +int nthw_rac_rab_dma_commit(nthw_rac_t *p) +{ + int ret; + + if (!p->m_dma_active) { + /* Expecting mutex not to be locked! */ + assert(0); /* alert developer that something is wrong */ + return -1; + } + + nthw_rac_rab_dma_activate(p); + ret = nthw_rac_rab_dma_wait(p); + + p->m_dma_active = false; + + pthread_mutex_unlock(&p->m_mutex); + + return ret; +} + +void nthw_rac_reg_read32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr, + uint32_t *p_data) +{ + *p_data = *(volatile uint32_t *)((uint8_t *)p_fpga_info->bar0_addr + + reg_addr); +} + +void nthw_rac_reg_write32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr, + uint32_t p_data) +{ + *(volatile uint32_t *)((uint8_t *)p_fpga_info->bar0_addr + reg_addr) = + p_data; +} + +int nthw_rac_rab_write32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id, + uint32_t word_cnt, const uint32_t *p_data) +{ + const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info; + + if (word_cnt == 0 || word_cnt > 256) { + NT_LOG(ERR, NTHW, + "%s: Failed rab dma write length check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X\n", + p_fpga_info->mp_adapter_id_str, bus_id, address, word_cnt, + p->m_in_free); + assert(0); /* alert developer that something is wrong */ + return -1; + } + + if (p->m_in_free < (word_cnt + 3)) { + /* + * No more memory available. + * nthw_rac_rab_dma_commit() needs to be called to start and finish pending + * transfers. + */ + return -1; + } + + p->m_in_free -= (word_cnt + 1); + + /* Write the command word */ +#if defined(RAB_DEBUG_ECHO) + p->m_dma_in_buf[p->m_dma_in_ptr_wr] = + (RAB_WRITE_ECHO << RAB_OPR_LO) | + ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) | + (bus_id << RAB_BUSID_LO) | address; + p->m_dma_out_ptr_rd = (uint16_t)((p->m_dma_out_ptr_rd + word_cnt + 1) & + (RAB_DMA_BUF_CNT - 1)); +#else + p->m_dma_in_buf[p->m_dma_in_ptr_wr] = + (RAB_WRITE << RAB_OPR_LO) | + ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) | + (bus_id << RAB_BUSID_LO) | address; +#endif + p->m_dma_in_ptr_wr = + (uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1)); + + for (uint32_t i = 0; i < word_cnt; i++) { + p->m_dma_in_buf[p->m_dma_in_ptr_wr] = p_data[i]; + p->m_dma_in_ptr_wr = (uint16_t)((p->m_dma_in_ptr_wr + 1) & + (RAB_DMA_BUF_CNT - 1)); + } + + return 0; +} + +int nthw_rac_rab_read32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id, + uint32_t word_cnt, struct dma_buf_ptr *buf_ptr) +{ + const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info; + + if (word_cnt == 0 || word_cnt > 256) { + NT_LOG(ERR, NTHW, + "%s: Failed rab dma read length check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X\n", + p_fpga_info->mp_adapter_id_str, bus_id, address, word_cnt, + p->m_in_free); + assert(0); /* alert developer that something is wrong */ + return -1; + } + + if ((word_cnt + 3) > RAB_DMA_BUF_CNT) { + NT_LOG(ERR, NTHW, + "%s: Failed rab dma read length check - bus: %d addr: 0x%08X wordcount: %d: 0x%08X", + p_fpga_info->mp_adapter_id_str, bus_id, address, word_cnt); + return -1; + } + + if (p->m_in_free < 3) { + /* + * No more memory available. + * nthw_rac_rab_dma_commit() needs to be called to start and finish pending + * transfers. + */ + return -1; + } + + p->m_in_free -= 1; + + /* Write the command word */ +#if defined(RAB_DEBUG_ECHO) + p->m_dma_in_buf[p->m_dma_in_ptr_wr] = + (RAB_READ_ECHO << RAB_OPR_LO) | + ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) | + (bus_id << RAB_BUSID_LO) | address; + p->m_dma_out_ptr_rd = + (uint16_t)((p->m_dma_out_ptr_rd + 1) & (RAB_DMA_BUF_CNT - 1)); +#else + p->m_dma_in_buf[p->m_dma_in_ptr_wr] = + (RAB_READ << RAB_OPR_LO) | + ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) | + (bus_id << RAB_BUSID_LO) | address; +#endif + p->m_dma_in_ptr_wr = + (uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1)); + + buf_ptr->index = p->m_dma_out_ptr_rd; + buf_ptr->size = RAB_DMA_BUF_CNT; + buf_ptr->base = p->m_dma_out_buf; + p->m_dma_out_ptr_rd = (uint16_t)((p->m_dma_out_ptr_rd + word_cnt) & + (RAB_DMA_BUF_CNT - 1U)); + + return 0; +} + +int nthw_rac_rab_write32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id, + uint32_t word_cnt, const uint32_t *p_data) +{ + const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info; + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + int res = 0; + uint32_t rab_oper_wr; + uint32_t rab_oper_cmpl; + uint32_t rab_echo_oper_cmpl; + uint32_t word_cnt_expected; + uint32_t buf_used; + uint32_t buf_free; + uint32_t in_buf_free; + uint32_t out_buf_free; + + if (address > (1 << RAB_ADDR_BW)) { + NT_LOG(ERR, NTHW, + "%s: RAB: Illegal address: value too large %d - max %d\n", + p_adapter_id_str, address, (1 << RAB_ADDR_BW)); + return -1; + } + + if (bus_id > (1 << RAB_BUSID_BW)) { + NT_LOG(ERR, NTHW, + "%s: RAB: Illegal bus id: value too large %d - max %d\n", + p_adapter_id_str, bus_id, (1 << RAB_BUSID_BW)); + return -1; + } + + if (word_cnt == 0) { + NT_LOG(ERR, NTHW, + "%s: RAB: Illegal word count: value is zero (%d)\n", + p_adapter_id_str, word_cnt); + return -1; + } + + if (word_cnt > (1 << RAB_CNT_BW)) { + NT_LOG(ERR, NTHW, + "%s: RAB: Illegal word count: value too large %d - max %d\n", + p_adapter_id_str, word_cnt, (1 << RAB_CNT_BW)); + return -1; + } + + pthread_mutex_lock(&p->m_mutex); + + if (p->m_dma_active) { + NT_LOG(ERR, NTHW, "%s: RAB: Illegal operation: DMA enabled\n", + p_adapter_id_str); + res = -1; + goto exit_unlock_res; + } + + /* Read buffer free register */ + nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr, &buf_free); + + in_buf_free = buf_free & p->rac_rab_buf_free_ib_free_mask; + out_buf_free = (buf_free & p->rac_rab_buf_free_ob_free_mask) >> 16; + + /* Read buffer used register */ + nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &buf_used); + + buf_used = buf_used & (p->rac_rab_buf_used_ib_used_mask | + p->rac_rab_buf_used_ob_used_mask); + + /* + * Verify that output buffer can hold one completion word, + * input buffer can hold the number of words to be written + + * one write and one completion command + * and that the input and output "used" buffer is 0 + */ + if ((out_buf_free >= 1 && (in_buf_free >= word_cnt + 2)) && buf_used == 0) { + uint32_t i; + + word_cnt_expected = 0; + + /* Compose write command */ +#if defined(RAB_DEBUG_ECHO) + rab_oper_wr = + (RAB_WRITE_ECHO << RAB_OPR_LO) | + ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) | + (bus_id << RAB_BUSID_LO) | address; + word_cnt_expected += word_cnt + 1; +#else + rab_oper_wr = + (RAB_WRITE << RAB_OPR_LO) | + ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) | + (bus_id << RAB_BUSID_LO) | address; +#endif /* RAB_DEBUG_ECHO */ + + /* Write command */ + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr, + rab_oper_wr); + + /* Write da to input buffer */ + for (i = 0; i < word_cnt; i++) { + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr, + *p_data); + p_data++; + } + + /* Compose completion command */ + rab_oper_cmpl = (RAB_COMPLETION << RAB_OPR_LO); + word_cnt_expected++; + + /* Write command */ + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr, + rab_oper_cmpl); + + /* Wait until done */ + if (nthw_rac_wait_for_rab_done(p, address, word_cnt_expected)) { + res = -1; + goto exit_unlock_res; + } + +#if defined(RAB_DEBUG_ECHO) + { + uint32_t rab_echo_oper_wr; + + nthw_rac_reg_read32(p_fpga_info, p->rac_rab_ob_data_addr, + &rab_echo_oper_wr); + if (p->mn_param_rac_rab_ob_update) { + nthw_rac_reg_write32(p_fpga_info, + p->rac_rab_ob_data_addr, 0); + } + if (rab_oper_wr != rab_echo_oper_wr) { + NT_LOG(ERR, NTHW, + "%s: expected rab read echo oper (0x%08X) - read (0x%08X)\n", + p_adapter_id_str, rab_oper_wr, rab_echo_oper_wr); + } + } + + { + /* Read data from output buffer */ + uint32_t data; + + for (i = 0; i < word_cnt; i++) { + nthw_rac_reg_read32(p_fpga_info, + p->rac_rab_ob_data_addr, + &data); + if (p->mn_param_rac_rab_ob_update) { + nthw_rac_reg_write32(p_fpga_info, + p->rac_rab_ob_data_addr, 0); + } + } + } +#endif /* RAB_DEBUG_ECHO */ + + /* Read completion from out buffer */ + nthw_rac_reg_read32(p_fpga_info, p->rac_rab_ob_data_addr, + &rab_echo_oper_cmpl); + if (p->mn_param_rac_rab_ob_update) { + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ob_data_addr, + 0); + } + if (rab_echo_oper_cmpl != rab_oper_cmpl) { + NT_LOG(ERR, NTHW, + "%s: RAB: Unexpected value of completion (0x%08X)- inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n", + p_adapter_id_str, rab_echo_oper_cmpl, in_buf_free, + out_buf_free, buf_used); + res = -1; + goto exit_unlock_res; + } + + /* Read buffer free register */ + nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr, + &buf_free); + if (buf_free & 0x80000000) { + /* Clear Timeout and overflow bits */ + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_free_addr, + 0x0); + NT_LOG(ERR, NTHW, + "%s: RAB: timeout - Access outside register - bus: %d addr: 0x%08X - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n", + p_adapter_id_str, bus_id, address, in_buf_free, + out_buf_free, buf_used); + res = -1; + goto exit_unlock_res; + } + + res = 0; + goto exit_unlock_res; + } else { + NT_LOG(ERR, NTHW, + "%s: RAB: Fail rab bus buffer check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n", + p_adapter_id_str, bus_id, address, word_cnt, in_buf_free, + out_buf_free, buf_used); + res = -1; + goto exit_unlock_res; + } + +exit_unlock_res: + pthread_mutex_unlock(&p->m_mutex); + return res; +} + +int nthw_rac_rab_read32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id, + uint32_t word_cnt, uint32_t *p_data) +{ + const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info; + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + int res = 0; + uint32_t rab_oper_rd; + uint32_t word_cnt_expected; + uint32_t buf_used; + uint32_t buf_free; + uint32_t in_buf_free; + uint32_t out_buf_free; + + pthread_mutex_lock(&p->m_mutex); + + if (address > (1 << RAB_ADDR_BW)) { + NT_LOG(ERR, NTHW, + "%s: RAB: Illegal address: value too large %d - max %d\n", + p_adapter_id_str, address, (1 << RAB_ADDR_BW)); + res = -1; + goto exit_unlock_res; + } + + if (bus_id > (1 << RAB_BUSID_BW)) { + NT_LOG(ERR, NTHW, + "%s: RAB: Illegal bus id: value too large %d - max %d\n", + p_adapter_id_str, bus_id, (1 << RAB_BUSID_BW)); + res = -1; + goto exit_unlock_res; + } + + if (word_cnt == 0) { + NT_LOG(ERR, NTHW, + "%s: RAB: Illegal word count: value is zero (%d)\n", + p_adapter_id_str, word_cnt); + res = -1; + goto exit_unlock_res; + } + + if (word_cnt > (1 << RAB_CNT_BW)) { + NT_LOG(ERR, NTHW, + "%s: RAB: Illegal word count: value too large %d - max %d\n", + p_adapter_id_str, word_cnt, (1 << RAB_CNT_BW)); + res = -1; + goto exit_unlock_res; + } + + /* Read buffer free register */ + nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr, &buf_free); + + in_buf_free = buf_free & p->rac_rab_buf_free_ib_free_mask; + out_buf_free = (buf_free & p->rac_rab_buf_free_ob_free_mask) >> 16; + + /* Read buffer used register */ + nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &buf_used); + + buf_used = buf_used & (p->rac_rab_buf_used_ib_used_mask | + p->rac_rab_buf_used_ob_used_mask); + + /* + * Verify that output buffer can hold the number of words to be read, + * input buffer can hold one read command + * and that the input and output "used" buffer is 0 + */ + if ((out_buf_free >= word_cnt && in_buf_free >= 1) && buf_used == 0) { + word_cnt_expected = word_cnt; + +#if defined(RAB_DEBUG_ECHO) + rab_oper_rd = + (RAB_READ_ECHO << RAB_OPR_LO) | + ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) | + (bus_id << RAB_BUSID_LO) | address; + word_cnt_expected++; +#else + rab_oper_rd = (RAB_READ << RAB_OPR_LO) | (word_cnt << RAB_CNT_LO) | + (bus_id << RAB_BUSID_LO) | address; +#endif /* RAB_DEBUG_ECHO */ + + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr, + rab_oper_rd); + + /* Wait until done */ + if (nthw_rac_wait_for_rab_done(p, address, word_cnt_expected)) { + res = -1; + goto exit_unlock_res; + } + +#if defined(RAB_DEBUG_ECHO) + uint32_t rab_echo_oper_rd; + + nthw_rac_reg_read32(p_fpga_info, p->rac_rab_ob_data_addr, + &rab_echo_oper_rd); + if (p->mn_param_rac_rab_ob_update) { + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ob_data_addr, + 0); + } + if (rab_oper_rd != rab_echo_oper_rd) { + NT_LOG(ERR, NTHW, + "%s: RAB: expected rab read echo oper (0x%08X) - read (0x%08X)\n", + p_adapter_id_str, rab_oper_rd, rab_echo_oper_rd); + } +#endif /* RAB_DEBUG_ECHO */ + + /* Read data from output buffer */ + { + uint32_t i; + + for (i = 0; i < word_cnt; i++) { + nthw_rac_reg_read32(p_fpga_info, + p->rac_rab_ob_data_addr, + p_data); + if (p->mn_param_rac_rab_ob_update) { + nthw_rac_reg_write32(p_fpga_info, + p->rac_rab_ob_data_addr, + 0); + } + p_data++; + } + } + + /* Read buffer free register */ + nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr, + &buf_free); + if (buf_free & 0x80000000) { + /* Clear Timeout and overflow bits */ + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_free_addr, + 0x0); + NT_LOG(ERR, NTHW, + "%s: RAB: timeout - Access outside register - bus: %d addr: 0x%08X - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n", + p_adapter_id_str, bus_id, address, in_buf_free, + out_buf_free, buf_used); + res = -1; + goto exit_unlock_res; + } + + res = 0; + goto exit_unlock_res; + } else { + NT_LOG(ERR, NTHW, + "%s: RAB: Fail rab bus buffer check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n", + p_adapter_id_str, bus_id, address, word_cnt, in_buf_free, + out_buf_free, buf_used); + res = -1; + goto exit_unlock_res; + } + +exit_unlock_res: + pthread_mutex_unlock(&p->m_mutex); + return res; +} + +int nthw_rac_rab_flush(nthw_rac_t *p) +{ + const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info; + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + uint32_t data = 0; + uint32_t retry; + int res = 0; + + pthread_mutex_lock(&p->m_mutex); + + /* Set the flush bit */ + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_used_addr, + p->rac_rab_buf_used_flush_mask); + + /* Reset BUF FREE register */ + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_free_addr, 0x0); + + /* Wait until OB_USED and IB_USED are 0 */ + for (retry = 0; retry < 100000; retry++) { + nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &data); + + if ((data & 0xFFFFFFFF) == p->rac_rab_buf_used_flush_mask) + break; + } + + if (data != p->rac_rab_buf_used_flush_mask) { + NT_LOG(ERR, NTHW, "%s: RAB: Rab bus flush error.\n", + p_adapter_id_str); + res = -1; + } + + /* Clear flush bit when done */ + nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_used_addr, 0x0); + + pthread_mutex_unlock(&p->m_mutex); + return res; +} diff --git a/drivers/net/ntnic/nthw/nthw_rac.h b/drivers/net/ntnic/nthw/nthw_rac.h new file mode 100644 index 0000000000..737598d95a --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_rac.h @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_RAC_H__ +#define __NTHW_RAC_H__ + +#include "nt_util.h" +#include "nthw_bus.h" + +#include + +struct nthw_rac { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_rac; + + pthread_mutex_t m_mutex; + + int mn_param_rac_rab_interfaces; + int mn_param_rac_rab_ob_update; + + nt_register_t *mp_reg_dummy0; + nt_register_t *mp_reg_dummy1; + nt_register_t *mp_reg_dummy2; + + nt_register_t *mp_reg_rab_init; + nt_field_t *mp_fld_rab_init; + + int mn_fld_rab_init_bw; + uint32_t mn_fld_rab_init_mask; + + nt_register_t *mp_reg_dbg_ctrl; + nt_field_t *mp_fld_dbg_ctrl; + + nt_register_t *mp_reg_dbg_data; + nt_field_t *mp_fld_dbg_data; + + nt_register_t *mp_reg_rab_ib_data; + nt_field_t *mp_fld_rab_ib_data; + + nt_register_t *mp_reg_rab_ob_data; + nt_field_t *mp_fld_rab_ob_data; + + nt_register_t *mp_reg_rab_buf_free; + nt_field_t *mp_fld_rab_buf_free_ib_free; + nt_field_t *mp_fld_rab_buf_free_ib_ovf; + nt_field_t *mp_fld_rab_buf_free_ob_free; + nt_field_t *mp_fld_rab_buf_free_ob_ovf; + nt_field_t *mp_fld_rab_buf_free_timeout; + + nt_register_t *mp_reg_rab_buf_used; + nt_field_t *mp_fld_rab_buf_used_ib_used; + nt_field_t *mp_fld_rab_buf_used_ob_used; + nt_field_t *mp_fld_rab_buf_used_flush; + + nt_register_t *mp_reg_rab_dma_ib_lo; + nt_field_t *mp_fld_rab_dma_ib_lo_phy_addr; + + nt_register_t *mp_reg_rab_dma_ib_hi; + nt_field_t *mp_fld_rab_dma_ib_hi_phy_addr; + + nt_register_t *mp_reg_rab_dma_ob_hi; + nt_field_t *mp_fld_rab_dma_ob_hi_phy_addr; + + nt_register_t *mp_reg_rab_dma_ob_lo; + nt_field_t *mp_fld_rab_dma_ob_lo_phy_addr; + + nt_register_t *mp_reg_rab_dma_ib_wr; + nt_field_t *mp_fld_rab_dma_ib_wr_ptr; + + nt_register_t *mp_reg_rab_dma_ib_rd; + nt_field_t *mp_fld_rab_dma_ib_rd_ptr; + + nt_register_t *mp_reg_rab_dma_ob_wr; + nt_field_t *mp_fld_rab_dma_ob_wr_ptr; + + nt_register_t *mp_reg_rab_nmb_rd; + nt_register_t *mp_reg_rab_nmb_data; + nt_register_t *mp_reg_rab_nmb_wr; + nt_register_t *mp_reg_rab_nmb_status; + + uint32_t rac_rab_init_addr; + uint32_t rac_rab_ib_data_addr; + uint32_t rac_rab_ob_data_addr; + uint32_t rac_rab_buf_free_addr; + uint32_t rac_rab_buf_used_addr; + + uint32_t rac_rab_dma_ib_lo_addr; + uint32_t rac_rab_dma_ib_hi_addr; + uint32_t rac_rab_dma_ob_lo_addr; + uint32_t rac_rab_dma_ob_hi_addr; + uint32_t rac_rab_dma_ib_rd_addr; + uint32_t rac_rab_dma_ob_wr_addr; + uint32_t rac_rab_dma_ib_wr_addr; + + uint32_t rac_rab_buf_free_ib_free_mask; + uint32_t rac_rab_buf_free_ob_free_mask; + uint32_t rac_rab_buf_used_ib_used_mask; + uint32_t rac_rab_buf_used_ob_used_mask; + uint32_t rac_rab_buf_used_flush_mask; + + uint32_t rac_rab_buf_used_ob_used_low; + + uint32_t rac_nmb_rd_adr_addr; + uint32_t rac_nmb_data_addr; + uint32_t rac_nmb_wr_adr_addr; + uint32_t rac_nmb_status_addr; + + bool m_dma_active; + + struct nt_dma_s *m_dma; + + volatile uint32_t *m_dma_in_buf; + volatile uint32_t *m_dma_out_buf; + + uint16_t m_dma_out_ptr_rd; + uint16_t m_dma_in_ptr_wr; + uint32_t m_in_free; +}; + +typedef struct nthw_rac nthw_rac_t; +typedef struct nthw_rac nthw_rac; + +struct dma_buf_ptr { + uint32_t size; + uint32_t index; + volatile uint32_t *base; +}; + +nthw_rac_t *nthw_rac_new(void); +void nthw_rac_delete(nthw_rac_t *p); +int nthw_rac_init(nthw_rac_t *p, nt_fpga_t *p_fpga, struct fpga_info_s *p_fpga_info); + +int nthw_rac_get_rab_interface_count(const nthw_rac_t *p); + +int nthw_rac_rab_init(nthw_rac_t *p, uint32_t rab_intf_mask); + +int nthw_rac_rab_setup(nthw_rac_t *p); + +int nthw_rac_rab_reset(nthw_rac_t *p); + +int nthw_rac_rab_write32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id, + uint32_t word_cnt, const uint32_t *p_data); +int nthw_rac_rab_write32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id, + uint32_t word_cnt, const uint32_t *p_data); +int nthw_rac_rab_read32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id, + uint32_t word_cnt, uint32_t *p_data); +int nthw_rac_rab_read32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id, + uint32_t word_cnt, struct dma_buf_ptr *buf_ptr); + +int nthw_rac_rab_flush(nthw_rac_t *p); + +int nthw_rac_rab_dma_begin(nthw_rac_t *p); +int nthw_rac_rab_dma_commit(nthw_rac_t *p); + +void nthw_rac_reg_read32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr, + uint32_t *p_data); +void nthw_rac_reg_write32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr, + uint32_t p_data); + +#endif /* __NTHW_RAC_H__ */ diff --git a/drivers/net/ntnic/nthw/nthw_register.h b/drivers/net/ntnic/nthw/nthw_register.h index 5cdbd9fc5d..4fe3496b9f 100644 --- a/drivers/net/ntnic/nthw/nthw_register.h +++ b/drivers/net/ntnic/nthw/nthw_register.h @@ -10,6 +10,8 @@ #include #include +#include "nthw_fpga_model.h" + #include "fpga_model.h" #include "nthw_fpga_modules_defs.h" diff --git a/drivers/net/ntnic/nthw/nthw_stat.c b/drivers/net/ntnic/nthw/nthw_stat.c new file mode 100644 index 0000000000..fbecbc2dba --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_stat.c @@ -0,0 +1,266 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nt_util.h" +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_stat.h" + +#include + +nthw_stat_t *nthw_stat_new(void) +{ + nthw_stat_t *p = malloc(sizeof(nthw_stat_t)); + + if (p) + memset(p, 0, sizeof(nthw_stat_t)); + return p; +} + +void nthw_stat_delete(nthw_stat_t *p) +{ + if (p) + free(p); +} + +int nthw_stat_init(nthw_stat_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + uint64_t n_module_version_packed64 = -1; + nt_module_t *mod = fpga_query_module(p_fpga, MOD_STA, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: STAT %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_stat = mod; + + n_module_version_packed64 = module_get_version_packed64(p->mp_mod_stat); + NT_LOG(DBG, NTHW, "%s: STAT %d: version=0x%08lX\n", p_adapter_id_str, + p->mn_instance, n_module_version_packed64); + + { + nt_register_t *p_reg; + /* STA_CFG register */ + p_reg = module_get_register(p->mp_mod_stat, STA_CFG); + p->mp_fld_dma_ena = register_get_field(p_reg, STA_CFG_DMA_ENA); + p->mp_fld_cnt_clear = register_get_field(p_reg, STA_CFG_CNT_CLEAR); + + /* CFG: fields NOT available from v. 3 */ + p->mp_fld_tx_disable = + register_query_field(p_reg, STA_CFG_TX_DISABLE); + p->mp_fld_cnt_freeze = register_query_field(p_reg, STA_CFG_CNT_FRZ); + + /* STA_STATUS register */ + p_reg = module_get_register(p->mp_mod_stat, STA_STATUS); + p->mp_fld_stat_toggle_missed = + register_get_field(p_reg, STA_STATUS_STAT_TOGGLE_MISSED); + + /* HOST_ADR registers */ + p_reg = module_get_register(p->mp_mod_stat, STA_HOST_ADR_LSB); + p->mp_fld_dma_lsb = register_get_field(p_reg, STA_HOST_ADR_LSB_LSB); + + p_reg = module_get_register(p->mp_mod_stat, STA_HOST_ADR_MSB); + p->mp_fld_dma_msb = register_get_field(p_reg, STA_HOST_ADR_MSB_MSB); + } + + /* Params */ + p->mb_is_vswitch = p_fpga->p_fpga_info->profile == FPGA_INFO_PROFILE_VSWITCH; + + p->m_nb_nim_ports = fpga_get_product_param(p_fpga, NT_NIMS, 0); + p->m_nb_phy_ports = fpga_get_product_param(p_fpga, NT_PHY_PORTS, 0); + + p->m_nb_rx_ports = + fpga_get_product_param(p_fpga, NT_STA_RX_PORTS, -1); /* VSWITCH */ + if (p->m_nb_rx_ports == -1) { + p->m_nb_rx_ports = fpga_get_product_param(p_fpga, NT_RX_PORTS, + -1); /* non-VSWITCH */ + if (p->m_nb_rx_ports == -1) { + p->m_nb_rx_ports = fpga_get_product_param(p_fpga, + NT_PORTS, + 0); /* non-VSWITCH */ + } + } + + p->m_nb_tx_ports = fpga_get_product_param(p_fpga, NT_TX_PORTS, 0); + p->m_rx_port_replicate = + fpga_get_product_param(p_fpga, NT_RX_PORT_REPLICATE, 0); + + p->m_nb_color_counters = fpga_get_product_param(p_fpga, NT_STA_COLORS, 64) * + 2; /* VSWITCH */ + if (p->m_nb_color_counters == 0) { + p->m_nb_color_counters = + fpga_get_product_param(p_fpga, NT_CAT_FUNCS, 0) * + 2; /* non-VSWITCH */ + } + + p->m_nb_rx_host_buffers = fpga_get_product_param(p_fpga, NT_QUEUES, 0); + p->m_nb_tx_host_buffers = p->m_nb_rx_host_buffers; + + p->m_dbs_present = fpga_get_product_param(p_fpga, NT_DBS_PRESENT, 0); + + p->m_nb_rx_hb_counters = + (p->m_nb_rx_host_buffers * + (6 + 2 * (n_module_version_packed64 >= VERSION_PACKED64(0, 6) ? + p->m_dbs_present : + 0))); + + p->m_nb_tx_hb_counters = 0; + + p->m_nb_rx_port_counters = + 42 + 2 * (n_module_version_packed64 >= VERSION_PACKED64(0, 6) ? + p->m_dbs_present : + 0); + p->m_nb_tx_port_counters = 0; + + p->m_nb_counters = + p->m_nb_color_counters + p->m_nb_rx_hb_counters + p->m_nb_tx_hb_counters; + + p->mn_stat_layout_version = 0; + if (n_module_version_packed64 >= VERSION_PACKED64(0, 8)) { + p->mn_stat_layout_version = 6; + } else if (n_module_version_packed64 >= VERSION_PACKED64(0, 6)) { + p->mn_stat_layout_version = 5; + } else if (n_module_version_packed64 >= VERSION_PACKED64(0, 4)) { + p->mn_stat_layout_version = 4; + } else if (n_module_version_packed64 >= VERSION_PACKED64(0, 3)) { + p->mn_stat_layout_version = 3; + } else if (n_module_version_packed64 >= VERSION_PACKED64(0, 2)) { + p->mn_stat_layout_version = 2; + } else if (n_module_version_packed64 > VERSION_PACKED64(0, 0)) { + p->mn_stat_layout_version = 1; + } else { + p->mn_stat_layout_version = 0; + NT_LOG(ERR, NTHW, + "%s: unknown module_version 0x%08lX layout=%d\n", + p_adapter_id_str, n_module_version_packed64, + p->mn_stat_layout_version); + } + assert(p->mn_stat_layout_version); + + /* STA module 0.2+ adds IPF counters per port (Rx feature) */ + if (n_module_version_packed64 >= VERSION_PACKED64(0, 2)) + p->m_nb_rx_port_counters += 6; + + /* STA module 0.3+ adds TX stats */ + if (n_module_version_packed64 >= VERSION_PACKED64(0, 3) || + p->m_nb_tx_ports >= 1) + p->mb_has_tx_stats = true; + + /* STA module 0.3+ adds TX stat counters */ + if (n_module_version_packed64 >= VERSION_PACKED64(0, 3)) + p->m_nb_tx_port_counters += 22; + + /* STA module 0.4+ adds TX drop event counter */ + if (n_module_version_packed64 >= VERSION_PACKED64(0, 4)) + p->m_nb_tx_port_counters += 1; /* TX drop event counter */ + + /* + * STA module 0.6+ adds pkt filter drop octets+pkts, retransmit and + * duplicate counters + */ + if (n_module_version_packed64 >= VERSION_PACKED64(0, 6)) { + p->m_nb_rx_port_counters += 4; + p->m_nb_tx_port_counters += 1; + } + + if (p->mb_is_vswitch) { + p->m_nb_rx_port_counters = 5; + p->m_nb_tx_port_counters = 5; + } + + p->m_nb_counters += (p->m_nb_rx_ports * p->m_nb_rx_port_counters); + + if (p->mb_has_tx_stats) + p->m_nb_counters += (p->m_nb_tx_ports * p->m_nb_tx_port_counters); + + /* Output params (debug) */ + NT_LOG(DBG, NTHW, + "%s: nims=%d rxports=%d txports=%d rxrepl=%d colors=%d queues=%d\n", + p_adapter_id_str, p->m_nb_nim_ports, p->m_nb_rx_ports, p->m_nb_tx_ports, + p->m_rx_port_replicate, p->m_nb_color_counters, p->m_nb_rx_host_buffers); + NT_LOG(DBG, NTHW, + "%s: hbs=%d hbcounters=%d rxcounters=%d txcounters=%d\n", + p_adapter_id_str, p->m_nb_rx_host_buffers, p->m_nb_rx_hb_counters, + p->m_nb_rx_port_counters, p->m_nb_tx_port_counters); + NT_LOG(DBG, NTHW, "%s: layout=%d\n", p_adapter_id_str, + p->mn_stat_layout_version); + NT_LOG(DBG, NTHW, "%s: counters=%d (0x%X)\n", p_adapter_id_str, + p->m_nb_counters, p->m_nb_counters); + NT_LOG(DBG, NTHW, "%s: vswitch=%d\n", p_adapter_id_str, p->mb_is_vswitch); + + /* Init */ + if (p->mp_fld_tx_disable) + field_set_flush(p->mp_fld_tx_disable); + + field_update_register(p->mp_fld_cnt_clear); + field_set_flush(p->mp_fld_cnt_clear); + field_clr_flush(p->mp_fld_cnt_clear); + + field_update_register(p->mp_fld_stat_toggle_missed); + field_set_flush(p->mp_fld_stat_toggle_missed); + + field_update_register(p->mp_fld_dma_ena); + field_clr_flush(p->mp_fld_dma_ena); + field_update_register(p->mp_fld_dma_ena); + + return 0; +} + +int nthw_stat_set_dma_address(nthw_stat_t *p, uint64_t stat_dma_physical, + uint32_t *p_stat_dma_virtual) +{ + assert(p_stat_dma_virtual); + p->mp_timestamp = NULL; + + p->m_stat_dma_physical = stat_dma_physical; + p->mp_stat_dma_virtual = p_stat_dma_virtual; + + memset(p->mp_stat_dma_virtual, 0, (p->m_nb_counters * sizeof(uint32_t))); + + field_set_val_flush32(p->mp_fld_dma_msb, + (uint32_t)((p->m_stat_dma_physical >> 32) & + 0xffffffff)); + field_set_val_flush32(p->mp_fld_dma_lsb, + (uint32_t)(p->m_stat_dma_physical & 0xffffffff)); + + p->mp_timestamp = (uint64_t *)(p->mp_stat_dma_virtual + p->m_nb_counters); + NT_LOG(DBG, NTHW, + "%s: statDmaPhysical=%" PRIX64 " p_stat_dma_virtual=%" PRIX64 + " mp_timestamp=%" PRIX64 "\n", + __func__, p->m_stat_dma_physical, p->mp_stat_dma_virtual, + p->mp_timestamp); + if (p->mb_is_vswitch) + *p->mp_timestamp = NT_OS_GET_TIME_NS(); + + else + *p->mp_timestamp = (uint64_t)(int64_t)-1; + return 0; +} + +int nthw_stat_trigger(nthw_stat_t *p) +{ + int n_toggle_miss = field_get_updated(p->mp_fld_stat_toggle_missed); + + if (n_toggle_miss) + field_set_flush(p->mp_fld_stat_toggle_missed); + + if (p->mp_timestamp) + *p->mp_timestamp = -1; /* Clear old ts */ + + field_update_register(p->mp_fld_dma_ena); + field_set_flush(p->mp_fld_dma_ena); + + return 0; +} diff --git a/drivers/net/ntnic/nthw/nthw_stat.h b/drivers/net/ntnic/nthw/nthw_stat.h new file mode 100644 index 0000000000..7bce7ecd15 --- /dev/null +++ b/drivers/net/ntnic/nthw/nthw_stat.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_STAT_H__ +#define __NTHW_STAT_H__ + +struct nthw_stat { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_stat; + int mn_instance; + + int mn_stat_layout_version; + + bool mb_is_vswitch; + bool mb_has_tx_stats; + + int m_nb_phy_ports; + int m_nb_nim_ports; + + int m_nb_rx_ports; + int m_nb_tx_ports; + + int m_nb_rx_host_buffers; + int m_nb_tx_host_buffers; + + int m_dbs_present; + + int m_rx_port_replicate; + + int m_nb_color_counters; + + int m_nb_rx_hb_counters; + int m_nb_tx_hb_counters; + + int m_nb_rx_port_counters; + int m_nb_tx_port_counters; + + int m_nb_counters; + + nt_field_t *mp_fld_dma_ena; + nt_field_t *mp_fld_cnt_clear; + + nt_field_t *mp_fld_tx_disable; + + nt_field_t *mp_fld_cnt_freeze; + + nt_field_t *mp_fld_stat_toggle_missed; + + nt_field_t *mp_fld_dma_lsb; + nt_field_t *mp_fld_dma_msb; + + uint64_t m_stat_dma_physical; + uint32_t *mp_stat_dma_virtual; + + uint64_t last_ts; + + uint64_t *mp_timestamp; +}; + +typedef struct nthw_stat nthw_stat_t; +typedef struct nthw_stat nthw_stat; + +nthw_stat_t *nthw_stat_new(void); +int nthw_stat_init(nthw_stat_t *p, nt_fpga_t *p_fpga, int n_instance); +void nthw_stat_delete(nthw_stat_t *p); + +int nthw_stat_set_dma_address(nthw_stat_t *p, uint64_t stat_dma_physical, + uint32_t *p_stat_dma_virtual); +int nthw_stat_trigger(nthw_stat_t *p); + +#endif /* __NTHW_STAT_H__ */ diff --git a/drivers/net/ntnic/ntlog/include/ntlog.h b/drivers/net/ntnic/ntlog/include/ntlog.h new file mode 100644 index 0000000000..81bc014d66 --- /dev/null +++ b/drivers/net/ntnic/ntlog/include/ntlog.h @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NTOSS_SYSTEM_NTLOG_H +#define NTOSS_SYSTEM_NTLOG_H + +#include +#include + +#ifndef NT_LOG_MODULE_PREFIX + +/* DPDK modules */ +#define NT_LOG_MODULE_EAL 0 +#define NT_LOG_MODULE_MALLOC 1 +#define NT_LOG_MODULE_RING 2 +#define NT_LOG_MODULE_MEMPOOL 3 +#define NT_LOG_MODULE_TIMER 4 +#define NT_LOG_MODULE_PMD 5 +#define NT_LOG_MODULE_HASH 6 +#define NT_LOG_MODULE_LPM 7 +#define NT_LOG_MODULE_KNI 8 +#define NT_LOG_MODULE_ACL 9 +#define NT_LOG_MODULE_POWER 10 +#define NT_LOG_MODULE_METER 11 +#define NT_LOG_MODULE_SCHED 12 +#define NT_LOG_MODULE_PORT 13 +#define NT_LOG_MODULE_TABLE 14 +#define NT_LOG_MODULE_PIPELINE 15 +#define NT_LOG_MODULE_MBUF 16 +#define NT_LOG_MODULE_CRYPTODEV 17 +#define NT_LOG_MODULE_EFD 18 +#define NT_LOG_MODULE_EVENTDEV 19 +#define NT_LOG_MODULE_GSO 20 +#define NT_LOG_MODULE_USER1 24 +#define NT_LOG_MODULE_USER2 25 +#define NT_LOG_MODULE_USER3 26 +#define NT_LOG_MODULE_USER4 27 +#define NT_LOG_MODULE_USER5 28 +#define NT_LOG_MODULE_USER6 29 +#define NT_LOG_MODULE_USER7 30 +#define NT_LOG_MODULE_USER8 31 + +/* NT modules */ +#define NT_LOG_MODULE_GENERAL 10000 /* Should always be a first (smallest) */ +#define NT_LOG_MODULE_NTHW 10001 +#define NT_LOG_MODULE_FILTER 10002 +#define NT_LOG_MODULE_VDPA 10003 +#define NT_LOG_MODULE_FPGA 10004 +#define NT_LOG_MODULE_NTCONNECT 10005 +#define NT_LOG_MODULE_ETHDEV 10006 +#define NT_LOG_MODULE_END 10007 /* Mark for the range end of NT_LOG */ + +#define NT_LOG_MODULE_COUNT (NT_LOG_MODULE_END - NT_LOG_MODULE_GENERAL) +#define NT_LOG_MODULE_INDEX(module) ((module) - NT_LOG_MODULE_GENERAL) +#define NT_LOG_MODULE_PREFIX(type) NT_LOG_MODULE_##type + +#endif + +#ifndef NT_LOG_ENABLE +#define NT_LOG_ENABLE 1 +#endif + +#if defined NT_LOG_ENABLE && NT_LOG_ENABLE > 0 +#ifndef NT_LOG_ENABLE_ERR +#define NT_LOG_ENABLE_ERR 1 +#endif +#ifndef NT_LOG_ENABLE_WRN +#define NT_LOG_ENABLE_WRN 1 +#endif +#ifndef NT_LOG_ENABLE_INF +#define NT_LOG_ENABLE_INF 1 +#endif +#ifndef NT_LOG_ENABLE_DBG +#define NT_LOG_ENABLE_DBG 1 +#endif +#ifndef NT_LOG_ENABLE_DB1 +#define NT_LOG_ENABLE_DB1 0 +#endif +#ifndef NT_LOG_ENABLE_DB2 +#define NT_LOG_ENABLE_DB2 0 +#endif +#endif + +#if defined NT_LOG_ENABLE_ERR && NT_LOG_ENABLE_ERR > 0 +#define NT_LOG_NT_LOG_ERR(...) nt_log(__VA_ARGS__) +#else +#define NT_LOG_NT_LOG_ERR(...) +#endif + +#if defined NT_LOG_ENABLE_WRN && NT_LOG_ENABLE_WRN > 0 +#define NT_LOG_NT_LOG_WRN(...) nt_log(__VA_ARGS__) +#else +#define NT_LOG_NT_LOG_WRN(...) +#endif + +#if defined NT_LOG_ENABLE_INF && NT_LOG_ENABLE_INF > 0 +#define NT_LOG_NT_LOG_INF(...) nt_log(__VA_ARGS__) +#else +#define NT_LOG_NT_LOG_INF(...) +#endif + +#if defined NT_LOG_ENABLE_DBG && NT_LOG_ENABLE_DBG > 0 +#define NT_LOG_NT_LOG_DBG(...) nt_log(__VA_ARGS__) +#else +#define NT_LOG_NT_LOG_DBG(...) +#endif + +#if defined NT_LOG_ENABLE_DB1 && NT_LOG_ENABLE_DB1 > 0 +#define NT_LOG_NT_LOG_DB1(...) nt_log(__VA_ARGS__) +#else +#define NT_LOG_NT_LOG_DB1(...) +#endif + +#if defined NT_LOG_ENABLE_DB2 && NT_LOG_ENABLE_DB2 > 0 +#define NT_LOG_NT_LOG_DB2(...) nt_log(__VA_ARGS__) +#else +#define NT_LOG_NT_LOG_DB2(...) +#endif + +#define NT_LOG(level, module, ...) \ + NT_LOG_NT_LOG_##level(NT_LOG_##level, NT_LOG_MODULE_PREFIX(module), \ + #module ": " #level ": " __VA_ARGS__) + +enum nt_log_level { + NT_LOG_ERR = 0x001, + NT_LOG_WRN = 0x002, + NT_LOG_INF = 0x004, + NT_LOG_DBG = 0x008, + NT_LOG_DB1 = 0x010, + NT_LOG_DB2 = 0x020, +}; + +struct nt_log_impl { + int (*init)(void); + int (*log)(enum nt_log_level level, uint32_t module, const char *format, + va_list args); + int (*is_debug)(uint32_t module); +}; + +int nt_log_init(struct nt_log_impl *impl); + +int nt_log(enum nt_log_level level, uint32_t module, const char *format, ...); + +/* Returns 1 if RTE_DEBUG, 0 if lower log level, -1 if incorrect module */ +int nt_log_is_debug(uint32_t module); + +/* + * nt log helper functions + * to create a string for NT_LOG usage to output a one-liner log + * to use when one single function call to NT_LOG is not optimal - that is + * you do not know the number of parameters at programming time or it is variable + */ +char *ntlog_helper_str_alloc(const char *sinit); + +void ntlog_helper_str_reset(char *s, const char *sinit); + +void ntlog_helper_str_add(char *s, const char *format, ...); + +void ntlog_helper_str_free(char *s); + +#endif /* NTOSS_SYSTEM_NTLOG_H */ diff --git a/drivers/net/ntnic/ntlog/ntlog.c b/drivers/net/ntnic/ntlog/ntlog.c new file mode 100644 index 0000000000..def07f15d0 --- /dev/null +++ b/drivers/net/ntnic/ntlog/ntlog.c @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include +#include +#include +#include +#include +#include + +#include + +#define NTLOG_HELPER_STR_SIZE_MAX (1024) + +static struct nt_log_impl *user_impl; + +int nt_log_init(struct nt_log_impl *impl) +{ + user_impl = impl; + return user_impl->init(); +} + +static char *last_trailing_eol(char *s) +{ + int i = strlen(s) - 1; + /* Skip spaces */ + while (i > 0 && s[i] == ' ') + --i; + if (s[i] != '\n') + return NULL; + /* + * Find the last trailing EOL "hello_world\n\n\n" + * ^ + */ + while (i > 1 && s[i] == '\n' && s[i - 1] == '\n') + --i; + return &s[i]; +} + +/* Always terminates the NT_LOG statement with a !!!single!!! EOL. */ +int nt_log(enum nt_log_level level, uint32_t module, const char *format, ...) +{ + int rv = -1; + va_list args; + + if (user_impl == NULL) + return rv; + + char *actual_format = ntlog_helper_str_alloc(format); + char *eol = last_trailing_eol(actual_format); + + if (!eol) { /* If log line is not terminated with '\n' we add it. */ + strncat(actual_format, "\n", + NTLOG_HELPER_STR_SIZE_MAX - strlen(actual_format)); + } else { /* If multiple trailing EOLs, then keep just one of them. */ + *(eol + 1) = '\0'; + } + + va_start(args, format); + rv = user_impl->log(level, module, actual_format, args); + va_end(args); + + ntlog_helper_str_free(actual_format); + return rv; +} + +int nt_log_is_debug(uint32_t module) +{ + return user_impl->is_debug(module); +} + +char *ntlog_helper_str_alloc(const char *sinit) +{ + char *s = malloc(NTLOG_HELPER_STR_SIZE_MAX); + + if (!s) + return NULL; + if (sinit) + rte_strscpy(s, sinit, NTLOG_HELPER_STR_SIZE_MAX); + else + s[0] = '\0'; + return s; +} + +void ntlog_helper_str_reset(char *s, const char *sinit) +{ + if (s) { + if (sinit) + rte_strscpy(s, sinit, NTLOG_HELPER_STR_SIZE_MAX); + else + s[0] = '\0'; + } +} + +__rte_format_printf(2, 0) +void ntlog_helper_str_add(char *s, const char *format, ...) +{ + if (!s) + return; + va_list args; + + va_start(args, format); + int len = strlen(s); + + vsnprintf(&s[len], (NTLOG_HELPER_STR_SIZE_MAX - 1 - len), format, args); + va_end(args); +} + +void ntlog_helper_str_free(char *s) +{ + free(s); +} diff --git a/drivers/net/ntnic/ntutil/include/nt_util.h b/drivers/net/ntnic/ntutil/include/nt_util.h new file mode 100644 index 0000000000..3850ccd934 --- /dev/null +++ b/drivers/net/ntnic/ntutil/include/nt_util.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NTOSS_SYSTEM_NT_UTIL_H +#define NTOSS_SYSTEM_NT_UTIL_H + +#include +#include + +#define _unused __rte_unused + +#define PCIIDENT_TO_DOMAIN(pci_ident) \ + ((uint16_t)(((unsigned int)(pci_ident) >> 16) & 0xFFFFU)) +#define PCIIDENT_TO_BUSNR(pci_ident) \ + ((uint8_t)(((unsigned int)(pci_ident) >> 8) & 0xFFU)) +#define PCIIDENT_TO_DEVNR(pci_ident) \ + ((uint8_t)(((unsigned int)(pci_ident) >> 3) & 0x1FU)) +#define PCIIDENT_TO_FUNCNR(pci_ident) \ + ((uint8_t)(((unsigned int)(pci_ident) >> 0) & 0x7U)) + +#define PCIIDENT_PRINT_STR "%04x:%02x:%02x.%x" +#define BDF_TO_PCIIDENT(dom, bus, dev, fnc) \ + (((dom) << 16) | ((bus) << 8) | ((dev) << 3) | (fnc)) + +/* ALIGN: Align x to a boundary */ +#define ALIGN(x, a) \ + ({ \ + __typeof__(x) _a = (a); \ + ((x) + (_a - 1)) & ~(_a - 1); \ + }) + +/* PALIGN: Align pointer p to a boundary */ +#define PALIGN(p, a) ((__typeof__(p))ALIGN((unsigned long)(p), (a))) + +/* Allocation size matching minimum alignment of specified size */ +#define ALIGN_SIZE(_size_) (1 << rte_log2_u64(_size_)) + +#define NT_OS_WAIT_USEC(x) \ + rte_delay_us_sleep( \ + x) /* uses usleep which schedules out the calling thread */ +/* spins in a waiting loop calling pause asm instruction uses RDTSC - precise wait */ +#define NT_OS_WAIT_USEC_POLL(x) \ + rte_delay_us( \ + x) + +#define NT_OS_GET_TIME_US() \ + (rte_get_timer_cycles() / (rte_get_timer_hz() / 1000 / 1000)) +#define NT_OS_GET_TIME_NS() \ + (rte_get_timer_cycles() * 10 / (rte_get_timer_hz() / 1000 / 1000 / 100)) +#define NT_OS_GET_TIME_MONOTONIC_COUNTER() (rte_get_timer_cycles()) + +struct nt_dma_s { + uint64_t iova; + uint64_t addr; + uint64_t size; +}; + +struct nt_dma_s *nt_dma_alloc(uint64_t size, uint64_t align, int numa); +void nt_dma_free(struct nt_dma_s *vfio_addr); + +struct nt_util_vfio_impl { + int (*vfio_dma_map)(int vf_num, void *virt_addr, uint64_t *iova_addr, + uint64_t size); + int (*vfio_dma_unmap)(int vf_num, void *virt_addr, uint64_t iova_addr, + uint64_t size); +}; + +void nt_util_vfio_init(struct nt_util_vfio_impl *impl); + +#endif /* NTOSS_SYSTEM_NT_UTIL_H */ diff --git a/drivers/net/ntnic/ntutil/nt_util.c b/drivers/net/ntnic/ntutil/nt_util.c new file mode 100644 index 0000000000..8f5812bf8b --- /dev/null +++ b/drivers/net/ntnic/ntutil/nt_util.c @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "ntlog.h" +#include "nt_util.h" + +static struct nt_util_vfio_impl vfio_cb; + +void nt_util_vfio_init(struct nt_util_vfio_impl *impl) +{ + vfio_cb = *impl; +} + +struct nt_dma_s *nt_dma_alloc(uint64_t size, uint64_t align, int numa) +{ + int res; + struct nt_dma_s *vfio_addr; + + vfio_addr = rte_malloc(NULL, sizeof(struct nt_dma_s), 0); + if (!vfio_addr) { + NT_LOG(ERR, GENERAL, "VFIO rte_malloc failed\n"); + return NULL; + } + void *addr = rte_malloc_socket(NULL, size, align, numa); + + if (!addr) { + rte_free(vfio_addr); + NT_LOG(ERR, GENERAL, "VFIO rte_malloc_socket failed\n"); + return NULL; + } + res = vfio_cb.vfio_dma_map(0, addr, &vfio_addr->iova, + ALIGN_SIZE(size)); + if (res != 0) { + rte_free(addr); + rte_free(vfio_addr); + NT_LOG(ERR, GENERAL, "VFIO nt_dma_map failed\n"); + return NULL; + } + + vfio_addr->addr = (uint64_t)addr; + vfio_addr->size = ALIGN_SIZE(size); + + NT_LOG(DBG, GENERAL, + "VFIO DMA alloc addr=%" PRIX64 ", iova=%" PRIX64 + ", size=%u, align=0x%X\n", + vfio_addr->addr, vfio_addr->iova, vfio_addr->size, align); + + return vfio_addr; +} + +void nt_dma_free(struct nt_dma_s *vfio_addr) +{ + NT_LOG(DBG, GENERAL, + "VFIO DMA free addr=%" PRIX64 ", iova=%" PRIX64 ", size=%u\n", + vfio_addr->addr, vfio_addr->iova, vfio_addr->size); + + int res = vfio_cb.vfio_dma_unmap(0, (void *)(vfio_addr->addr), + vfio_addr->iova, vfio_addr->size); + if (res != 0) { + NT_LOG(WRN, GENERAL, + "VFIO DMA free FAILED addr=%" PRIX64 ", iova=%" PRIX64 + ", size=%u\n", + vfio_addr->addr, vfio_addr->iova, vfio_addr->size); + } + rte_free((void *)(vfio_addr->addr)); + rte_free(vfio_addr); +} From patchwork Mon Aug 21 13:54:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mykola Kostenok X-Patchwork-Id: 130579 X-Patchwork-Delegate: thomas@monjalon.net 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 409CB430C1; Mon, 21 Aug 2023 15:54:41 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 2B91D427E9; Mon, 21 Aug 2023 15:54:41 +0200 (CEST) Received: from egress-ip33a.ess.de.barracuda.com (egress-ip33a.ess.de.barracuda.com [18.185.115.192]) by mails.dpdk.org (Postfix) with ESMTP id 0614F40DF5 for ; Mon, 21 Aug 2023 15:54:39 +0200 (CEST) Received: from EUR04-DB3-obe.outbound.protection.outlook.com (mail-db3eur04lp2054.outbound.protection.outlook.com [104.47.12.54]) by mx-outbound43-64.eu-central-1c.ess.aws.cudaops.com (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 21 Aug 2023 13:54:37 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Xou50aHMeLLMrlcZ/Mi9yYyjgGRHspESUYYZZUHzArzYJxxxP0ANLJAED4dc9zQQv8R85NuTchNougChXtH13U0SoqJ58yf1RiD7b1A7qvn+A3EOCWZNKQSRtdAjesC4VKOm+8p5x19+xIAfsvnL4/Ay7NSxxK/wGuZp7vtFNexAuwoKymxe/GZ0hlgBb1NxNysfwEXNT8unzPP55rzvHH31qLm7U7gqCgJobRuPydETxuhkiZd5GqxwIg1JCWFR12i8Irt5UTtbJgDtzHU0RkzNWmbdDeWw/N/QYoDJmwoa+EybxR5eWKdhAcSQNLJi6CUUNn7VD8Vpo2OMpFXShA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=QN1r8nb22r3TNhgdyPWUuNgN+rHrTCdSvTj/pyrAazY=; b=IUrOK1tOHn2Tl5UHbQE1YBbrYd7wM4SwZ9XZec6AevBydYpfZLpqYlqE6Eco3/Ay+w9etfvWxRx93mQCgu8uncYbPLgGNgByDwLmYbPvAWRGa4cKG0vBlS2vgdd7dE0QqppnCUwJPiLcZac6JnPWWAnrPPc/gPCDpFck6iTwcIELoCKGu0y4EHFVTNh2Mk/qN9zXgxTOm4n4RKS6F4Mp3kq+yLICZSeIq29cqQDmKwUzF58c4/kCcidWYwfbBBwfUwuXTeQ+rpPT2rcZ9DpmlrM5Zr/ykOrKgZ73vuMoFMYpu4jX18F2r5UrGp0dPmU0+h8cvrAdtVeTntBaQZobqw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=fail (sender ip is 178.72.21.4) smtp.rcpttodomain=dpdk.org smtp.mailfrom=napatech.com; dmarc=fail (p=none sp=none pct=100) action=none header.from=napatech.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=napatech.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=QN1r8nb22r3TNhgdyPWUuNgN+rHrTCdSvTj/pyrAazY=; b=YMqTjItQxgkLSCdIguT1edgdhMEUOpy/Vwv+s4BYML5LMDhFaeVSUxWmmPpMJuxRw4enQSwItq7cMDiCL56OOvegonhe+jsxNRC4Fp+u6El0pkmL52GHVPyXS/fmcVzcf4mx8dyuRePNAd93uAD79uIBjO5mfNeqATUIel88qMI= Received: from DB8PR04CA0011.eurprd04.prod.outlook.com (2603:10a6:10:110::21) by DB9P190MB1321.EURP190.PROD.OUTLOOK.COM (2603:10a6:10:22d::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.24; Mon, 21 Aug 2023 13:54:28 +0000 Received: from DU2PEPF0001E9C5.eurprd03.prod.outlook.com (2603:10a6:10:110:cafe::c) by DB8PR04CA0011.outlook.office365.com (2603:10a6:10:110::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.20 via Frontend Transport; Mon, 21 Aug 2023 13:54:28 +0000 X-MS-Exchange-Authentication-Results: spf=fail (sender IP is 178.72.21.4) smtp.mailfrom=napatech.com; dkim=none (message not signed) header.d=none;dmarc=fail action=none header.from=napatech.com; Received-SPF: Fail (protection.outlook.com: domain of napatech.com does not designate 178.72.21.4 as permitted sender) receiver=protection.outlook.com; client-ip=178.72.21.4; helo=localhost.localdomain.com; Received: from localhost.localdomain.com (178.72.21.4) by DU2PEPF0001E9C5.mail.protection.outlook.com (10.167.8.74) with Microsoft SMTP Server id 15.20.6699.14 via Frontend Transport; Mon, 21 Aug 2023 13:54:28 +0000 From: Mykola Kostenok To: dev@dpdk.org, mko-plv@napatech.com Cc: ckm@napatech.com Subject: [PATCH v6 3/8] net/ntnic: adds NT200A02 adapter support Date: Mon, 21 Aug 2023 15:54:21 +0200 Message-Id: <20230821135426.1478754-3-mko-plv@napatech.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20230821135426.1478754-1-mko-plv@napatech.com> References: <20230816132552.2483752-1-mko-plv@napatech.com> <20230821135426.1478754-1-mko-plv@napatech.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU2PEPF0001E9C5:EE_|DB9P190MB1321:EE_ X-MS-Office365-Filtering-Correlation-Id: e52795d8-6135-4025-5c6a-08dba24e234d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: DnFwkADackdzq49xNfDcxLkRkG28jrelGp1tAWa6/FPazY5xGgFWeSZ0/40lS3yvHh5+2su051utZghZ22lqnE5siiw3WHP76FRBvYSIcrkRet2BHCqHPBI/PJSr5sTHdksBuhembFYSNXcdCceRHe0bB927A8gD5fj698eFczQfykFAMZ1LtZLaTSmC2N2Vz8YQrD7+q6FAOpvNubMd7TCRC7orQj43QzIcAMDuoAnI2vOnyzDNUeb7/tPvgZM/We82J1z0KjTJsxHOsc3/GAQgnACUNZR2tv7AH/Y3UTxfj9O23rqXsgAlcDnIupMN/chGIqPvaB7InbpYE2mxaNUIxTgQF8NRjDWT30vuSwEpvF/OY9u+VxuNHlCTRgVaW1k4RhwvMBMBvoUzX+7WcBNXfi3krTXkY0lNMKEae5sFFI3hWhWyS3g/KzMzoYDFyn4ZK4GdRYZo0Twk+YlNDmIoIPq+5N7pLayHQVcf4SQ71M37ToeyNqMkpJKUVSkhsMss7h+GLY1AWdRPCjfxybZqrqNErV1RJTT2cDUY+5681mP8SoIkF9CAptGcnttu6kR9+JbUG4pttYAMDS9v+9823sWJRdFw4LxJBYGM438fTZWqNEWq2AgbGbi9lHvFhEGLklJ+DBQMgp3Ke3gkx8XNVsypeveLj1HG7GnYGu4UFn1MALh5V49/IZag+7oAbX+M7rjiRo1CxclGo/0H989TBN6i45JXpwm6zisWy3nC9uS/SqvmCzmkEP56KaaYmNg5WOxrCuFY5EMSKZF9LA== X-Forefront-Antispam-Report: CIP:178.72.21.4; CTRY:DK; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:localhost.localdomain.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230031)(6069001)(396003)(136003)(346002)(376002)(39840400004)(186009)(1800799009)(82310400011)(451199024)(46966006)(36840700001)(36736006)(70586007)(70206006)(6512007)(316002)(66899024)(8676002)(8936002)(2616005)(956004)(4326008)(107886003)(1076003)(36756003)(41300700001)(356005)(81166007)(9316004)(478600001)(19627235002)(6666004)(6486002)(6506007)(40480700001)(83380400001)(30864003)(118246002)(2906002)(86362001)(34020700004)(47076005)(36860700001)(336012)(5660300002)(26005)(36900700001)(559001)(579004); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: bDpqTZ5p8QUGboW5keAduarW/9JNR8ONkABTQ4AevToqfNz9/NCtuwub40Ec5w/64ikKGDILBGKDFxb5uSMpPlqYdur7aQSJe/jPGD6sJjGzKOYm4ObB+yKbKH3xdxICVfzoXbntr0g+AWQoOXJ533eAB15OnxxLRQJJNcUlMliDXvRRrV4HdHBaExGB/xBsoa5sFpTQCb15TzpuIATvYgzDWfdBvHsFQ5T1lB3CbGPLHLKMni2z3XYRzWqliivtmtFyX2zC6s9iw46zpQxykOPV7MWagu1dnvO8aK+yuImaeq2AOzWA+Z1zDfq98EOQ1xdFLo3yZVcGRjGFQ5NQg7XbQg1OSL+MvJMMTI8Xig4SZd+YwDbHjAAhYIi8z8LMCw66CYumhqiXAPp1Kzit+nOFZT+0NXpEtbI4fm/9qryoTkuwbgNkK0xj/OVP7+o85xuRruiXUycH6XVCaZWQD3O2jZQIy8LIvaSzmXC08K6lXUPb/2mfgkAvAXB0JVDr6FIvCOBZtQuOnbYPThqVApqPFKAGDANa2m7ZTqKSieWM4vcpIM1+0he/cEFc+7/DGFUA6CPJzx3O1FK3JjIkbTyhgzV/FAuYTV+WC86om0uar2lxB2L2HcFQiXMRa0tbGuuLa31iqYnNgUfPdZIIFHI21TNa2hbZgJ8phN8XZgexHzGZR44GoVmlcFGHcSdoBuTxQyxiDMnTgnuC8m6q0muGkX4Rw0rzl4C86YwUn+idQ2FUeajA9Qr7Z3zM36L+WLwvbk8XV1/U41AqSWvwxsVM30W6VV0jepICo5I1wfE= X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Aug 2023 13:54:28.4759 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: e52795d8-6135-4025-5c6a-08dba24e234d X-MS-Exchange-CrossTenant-Id: c4540d0b-728a-4233-9da5-9ea30c7ec3ed X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=c4540d0b-728a-4233-9da5-9ea30c7ec3ed; Ip=[178.72.21.4]; Helo=[localhost.localdomain.com] X-MS-Exchange-CrossTenant-AuthSource: DU2PEPF0001E9C5.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9P190MB1321 X-BESS-ID: 1692626077-311072-12503-15882-1 X-BESS-VER: 2019.1_20230817.1828 X-BESS-Apparent-Source-IP: 104.47.12.54 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKVkYWBsbmpkB2BlA4xcDCxNzSNC 3FyCQ5LdHAKMkoxTDNMNEsJSUxJdXMyEypNhYA+MFF2kMAAAA= X-BESS-Outbound-Spam-Score: 0.00 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.250292 [from cloudscan13-215.eu-central-1a.ess.aws.cudaops.com] Rule breakdown below pts rule name description ---- ---------------------- -------------------------------- 0.00 LARGE_BODY_SHORTCUT META: X-BESS-Outbound-Spam-Status: SCORE=0.00 using account:ESS113687 scores of KILL_LEVEL=7.0 tests=LARGE_BODY_SHORTCUT X-BESS-BRTS-Status: 1 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 From: Christian Koue Muf The PMD is designed to support multiple different adapters, and this commit adds support for NT200A02 2x100G. Sensor and NIM code is included. Signed-off-by: Christian Koue Muf Reviewed-by: Mykola Kostenok --- v2: * Fixed WARNING:TYPO_SPELLING --- .../net/ntnic/adapter/common_adapter_defs.h | 14 + drivers/net/ntnic/adapter/nt4ga_adapter.c | 477 ++++ drivers/net/ntnic/adapter/nt4ga_adapter.h | 108 + drivers/net/ntnic/adapter/nt4ga_filter.h | 15 + drivers/net/ntnic/adapter/nt4ga_link.c | 178 ++ drivers/net/ntnic/adapter/nt4ga_link.h | 179 ++ drivers/net/ntnic/adapter/nt4ga_link_100g.c | 825 +++++++ drivers/net/ntnic/adapter/nt4ga_link_100g.h | 12 + drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c | 598 +++++ drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h | 41 + drivers/net/ntnic/adapter/nt4ga_stat.c | 705 ++++++ drivers/net/ntnic/adapter/nt4ga_stat.h | 202 ++ drivers/net/ntnic/meson.build | 24 + drivers/net/ntnic/nim/i2c_nim.c | 1974 +++++++++++++++++ drivers/net/ntnic/nim/i2c_nim.h | 122 + drivers/net/ntnic/nim/nim_defines.h | 146 ++ drivers/net/ntnic/nim/nt_link_speed.c | 105 + drivers/net/ntnic/nim/nt_link_speed.h | 34 + drivers/net/ntnic/nim/qsfp_registers.h | 57 + drivers/net/ntnic/nim/qsfp_sensors.c | 174 ++ drivers/net/ntnic/nim/qsfp_sensors.h | 18 + drivers/net/ntnic/nim/sfp_p_registers.h | 100 + drivers/net/ntnic/nim/sfp_sensors.c | 288 +++ drivers/net/ntnic/nim/sfp_sensors.h | 18 + .../net/ntnic/nthw/core/nthw_clock_profiles.c | 11 +- drivers/net/ntnic/nthw/core/nthw_core.h | 2 + drivers/net/ntnic/nthw/core/nthw_gmf.c | 290 +++ drivers/net/ntnic/nthw/core/nthw_gmf.h | 93 + .../nthw/core/nthw_nt200a02_u23_si5340_v5.h | 344 +++ drivers/net/ntnic/nthw/core/nthw_rmc.c | 156 ++ drivers/net/ntnic/nthw/core/nthw_rmc.h | 57 + .../ntnic/sensors/avr_sensors/avr_sensors.c | 104 + .../ntnic/sensors/avr_sensors/avr_sensors.h | 22 + .../sensors/board_sensors/board_sensors.c | 48 + .../sensors/board_sensors/board_sensors.h | 18 + .../net/ntnic/sensors/board_sensors/tempmon.c | 42 + .../net/ntnic/sensors/board_sensors/tempmon.h | 16 + .../ntnic/sensors/nim_sensors/nim_sensors.c | 54 + .../ntnic/sensors/nim_sensors/nim_sensors.h | 19 + drivers/net/ntnic/sensors/ntavr/avr_intf.h | 89 + drivers/net/ntnic/sensors/ntavr/ntavr.c | 78 + drivers/net/ntnic/sensors/ntavr/ntavr.h | 32 + drivers/net/ntnic/sensors/sensor_types.h | 259 +++ drivers/net/ntnic/sensors/sensors.c | 273 +++ drivers/net/ntnic/sensors/sensors.h | 127 ++ drivers/net/ntnic/sensors/stream_info.h | 86 + 46 files changed, 8632 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ntnic/adapter/common_adapter_defs.h create mode 100644 drivers/net/ntnic/adapter/nt4ga_adapter.c create mode 100644 drivers/net/ntnic/adapter/nt4ga_adapter.h create mode 100644 drivers/net/ntnic/adapter/nt4ga_filter.h create mode 100644 drivers/net/ntnic/adapter/nt4ga_link.c create mode 100644 drivers/net/ntnic/adapter/nt4ga_link.h create mode 100644 drivers/net/ntnic/adapter/nt4ga_link_100g.c create mode 100644 drivers/net/ntnic/adapter/nt4ga_link_100g.h create mode 100644 drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c create mode 100644 drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h create mode 100644 drivers/net/ntnic/adapter/nt4ga_stat.c create mode 100644 drivers/net/ntnic/adapter/nt4ga_stat.h create mode 100644 drivers/net/ntnic/nim/i2c_nim.c create mode 100644 drivers/net/ntnic/nim/i2c_nim.h create mode 100644 drivers/net/ntnic/nim/nim_defines.h create mode 100644 drivers/net/ntnic/nim/nt_link_speed.c create mode 100644 drivers/net/ntnic/nim/nt_link_speed.h create mode 100644 drivers/net/ntnic/nim/qsfp_registers.h create mode 100644 drivers/net/ntnic/nim/qsfp_sensors.c create mode 100644 drivers/net/ntnic/nim/qsfp_sensors.h create mode 100644 drivers/net/ntnic/nim/sfp_p_registers.h create mode 100644 drivers/net/ntnic/nim/sfp_sensors.c create mode 100644 drivers/net/ntnic/nim/sfp_sensors.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_gmf.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_gmf.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_nt200a02_u23_si5340_v5.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_rmc.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_rmc.h create mode 100644 drivers/net/ntnic/sensors/avr_sensors/avr_sensors.c create mode 100644 drivers/net/ntnic/sensors/avr_sensors/avr_sensors.h create mode 100644 drivers/net/ntnic/sensors/board_sensors/board_sensors.c create mode 100644 drivers/net/ntnic/sensors/board_sensors/board_sensors.h create mode 100644 drivers/net/ntnic/sensors/board_sensors/tempmon.c create mode 100644 drivers/net/ntnic/sensors/board_sensors/tempmon.h create mode 100644 drivers/net/ntnic/sensors/nim_sensors/nim_sensors.c create mode 100644 drivers/net/ntnic/sensors/nim_sensors/nim_sensors.h create mode 100644 drivers/net/ntnic/sensors/ntavr/avr_intf.h create mode 100644 drivers/net/ntnic/sensors/ntavr/ntavr.c create mode 100644 drivers/net/ntnic/sensors/ntavr/ntavr.h create mode 100644 drivers/net/ntnic/sensors/sensor_types.h create mode 100644 drivers/net/ntnic/sensors/sensors.c create mode 100644 drivers/net/ntnic/sensors/sensors.h create mode 100644 drivers/net/ntnic/sensors/stream_info.h diff --git a/drivers/net/ntnic/adapter/common_adapter_defs.h b/drivers/net/ntnic/adapter/common_adapter_defs.h new file mode 100644 index 0000000000..79167806f1 --- /dev/null +++ b/drivers/net/ntnic/adapter/common_adapter_defs.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _COMMON_ADAPTER_DEFS_H_ +#define _COMMON_ADAPTER_DEFS_H_ + +/* + * Declarations shared by NT adapter types. + */ +#define NUM_ADAPTER_MAX (8) +#define NUM_ADAPTER_PORTS_MAX (128) + +#endif /* _COMMON_ADAPTER_DEFS_H_ */ diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.c b/drivers/net/ntnic/adapter/nt4ga_adapter.c new file mode 100644 index 0000000000..259aae2831 --- /dev/null +++ b/drivers/net/ntnic/adapter/nt4ga_adapter.c @@ -0,0 +1,477 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_fpga.h" +#include "nt4ga_adapter.h" +#include "nt4ga_pci_ta_tg.h" +#include "nt4ga_link_100g.h" + +/* Sensors includes */ +#include "board_sensors.h" +#include "avr_sensors.h" + +/* + * Global variables shared by NT adapter types + */ +pthread_t monitor_tasks[NUM_ADAPTER_MAX]; +volatile int monitor_task_is_running[NUM_ADAPTER_MAX]; + +/* + * Signal-handler to stop all monitor threads + */ +static void stop_monitor_tasks(int signum) +{ + const size_t n = ARRAY_SIZE(monitor_task_is_running); + size_t i; + + /* Stop all monitor tasks */ + for (i = 0; i < n; i++) { + const int is_running = monitor_task_is_running[i]; + + monitor_task_is_running[i] = 0; + if (signum == -1 && is_running != 0) { + void *ret_val = NULL; + + pthread_join(monitor_tasks[i], &ret_val); + memset(&monitor_tasks[i], 0, sizeof(monitor_tasks[0])); + } + } +} + +int nt4ga_adapter_show_info(struct adapter_info_s *p_adapter_info, FILE *pfh) +{ + const char *const p_dev_name = p_adapter_info->p_dev_name; + const char *const p_adapter_id_str = p_adapter_info->mp_adapter_id_str; + fpga_info_t *p_fpga_info = &p_adapter_info->fpga_info; + hw_info_t *p_hw_info = &p_adapter_info->hw_info; + char a_pci_ident_str[32]; + + snprintf(a_pci_ident_str, sizeof(a_pci_ident_str), "" PCIIDENT_PRINT_STR "", + PCIIDENT_TO_DOMAIN(p_fpga_info->pciident), + PCIIDENT_TO_BUSNR(p_fpga_info->pciident), + PCIIDENT_TO_DEVNR(p_fpga_info->pciident), + PCIIDENT_TO_FUNCNR(p_fpga_info->pciident)); + + fprintf(pfh, "%s: DeviceName: %s\n", p_adapter_id_str, + (p_dev_name ? p_dev_name : "NA")); + fprintf(pfh, "%s: PCI Details:\n", p_adapter_id_str); + fprintf(pfh, "%s: %s: %08X: %04X:%04X %04X:%04X\n", p_adapter_id_str, + a_pci_ident_str, p_fpga_info->pciident, p_hw_info->pci_vendor_id, + p_hw_info->pci_device_id, p_hw_info->pci_sub_vendor_id, + p_hw_info->pci_sub_device_id); + fprintf(pfh, "%s: FPGA Details:\n", p_adapter_id_str); + fprintf(pfh, "%s: %03d-%04d-%02d-%02d [%016" PRIX64 "] (%08X)\n", + p_adapter_id_str, p_fpga_info->n_fpga_type_id, p_fpga_info->n_fpga_prod_id, + p_fpga_info->n_fpga_ver_id, p_fpga_info->n_fpga_rev_id, + p_fpga_info->n_fpga_ident, p_fpga_info->n_fpga_build_time); + fprintf(pfh, "%s: FpgaDebugMode=0x%x\n", p_adapter_id_str, + p_fpga_info->n_fpga_debug_mode); + fprintf(pfh, + "%s: Nims=%d PhyPorts=%d PhyQuads=%d RxPorts=%d TxPorts=%d\n", + p_adapter_id_str, p_fpga_info->n_nims, p_fpga_info->n_phy_ports, + p_fpga_info->n_phy_quads, p_fpga_info->n_rx_ports, p_fpga_info->n_tx_ports); + fprintf(pfh, "%s: Hw=0x%02X_rev%d: %s\n", p_adapter_id_str, + p_hw_info->hw_platform_id, p_fpga_info->nthw_hw_info.hw_id, + p_fpga_info->nthw_hw_info.hw_plat_id_str); + + nt4ga_stat_dump(p_adapter_info, pfh); + + return 0; +} + +/* + * SPI for sensors initialization + */ +static nthw_spi_v3_t *new_sensors_s_spi(struct nt_fpga_s *p_fpga) +{ + nthw_spi_v3_t *sensors_s_spi = nthw_spi_v3_new(); + + if (sensors_s_spi == NULL) { + NT_LOG(ERR, ETHDEV, "%s: SPI allocation error\n", __func__); + return NULL; + } + + if (nthw_spi_v3_init(sensors_s_spi, p_fpga, 0)) { + NT_LOG(ERR, ETHDEV, "%s: SPI initialization error\n", __func__); + nthw_spi_v3_delete(sensors_s_spi); + return NULL; + } + + return sensors_s_spi; +} + +/* + * SPI for sensors reading + */ +nthw_spis_t *new_sensors_t_spi(struct nt_fpga_s *p_fpga) +{ + nthw_spis_t *sensors_t_spi = nthw_spis_new(); + /* init SPI for sensor initialization process */ + if (sensors_t_spi == NULL) { + NT_LOG(ERR, ETHDEV, "%s: SPI allocation error\n", __func__); + return NULL; + } + + if (nthw_spis_init(sensors_t_spi, p_fpga, 0)) { + NT_LOG(ERR, ETHDEV, "%s: SPI initialization error\n", __func__); + nthw_spis_delete(sensors_t_spi); + return NULL; + } + + return sensors_t_spi; +} + +static void adapter_sensor_setup(hw_info_t *p_hw_info, struct adapter_info_s *adapter) +{ + struct nt_fpga_s *p_fpga = adapter->fpga_info.mp_fpga; + struct nt_sensor_group *sensors_list_ptr = NULL; + nthw_spi_v3_t *sensors_s_spi = new_sensors_s_spi(p_fpga); + + adapter->adapter_sensors_cnt = 0; + + /* FPGA */ + adapter->adapter_sensors = fpga_temperature_sensor_init(p_hw_info->n_nthw_adapter_id, + NT_SENSOR_FPGA_TEMP, p_fpga); + sensors_list_ptr = adapter->adapter_sensors; + adapter->adapter_sensors_cnt++; + + /* AVR */ + if (sensors_s_spi) { + if (nt_avr_sensor_mon_ctrl(sensors_s_spi, + SENSOR_MON_CTRL_REM_ALL_SENSORS) != 0) { + /* stop sensor monitoring */ + NT_LOG(ERR, ETHDEV, + "Failed to stop AVR sensors monitoring\n"); + } else { + NT_LOG(DBG, ETHDEV, "AVR sensors init started\n"); + + sensors_list_ptr->next = avr_sensor_init(sensors_s_spi, + p_hw_info->n_nthw_adapter_id, + "FAN0", + NT_SENSOR_SOURCE_ADAPTER, + NT_SENSOR_TYPE_FAN, + NT_SENSOR_NT200E3_FAN_SPEED, + SENSOR_MON_FAN, 0, + SENSOR_MON_BIG_ENDIAN, + SENSOR_MON_UNSIGNED, + &fan, 0xFFFF); + sensors_list_ptr = sensors_list_ptr->next; + adapter->adapter_sensors_cnt++; + + sensors_list_ptr->next = avr_sensor_init(sensors_s_spi, + p_hw_info->n_nthw_adapter_id, + "PSU0", + NT_SENSOR_SOURCE_ADAPTER, + NT_SENSOR_TYPE_TEMPERATURE, + NT_SENSOR_NT200E3_PSU0_TEMP, + SENSOR_MON_PSU_EXAR_7724_0, 0x15, + SENSOR_MON_LITTLE_ENDIAN, + SENSOR_MON_UNSIGNED, + &exar7724_tj, 0xFFFF); + sensors_list_ptr = sensors_list_ptr->next; + adapter->adapter_sensors_cnt++; + + sensors_list_ptr->next = avr_sensor_init(sensors_s_spi, + p_hw_info->n_nthw_adapter_id, + "PSU1", + NT_SENSOR_SOURCE_ADAPTER, + NT_SENSOR_TYPE_TEMPERATURE, + NT_SENSOR_NT200A02_PSU1_TEMP, + SENSOR_MON_MP2886A, 0x8d, + SENSOR_MON_BIG_ENDIAN, + SENSOR_MON_UNSIGNED, + &mp2886a_tj, 0xFFFF); + sensors_list_ptr = sensors_list_ptr->next; + adapter->adapter_sensors_cnt++; + + sensors_list_ptr->next = avr_sensor_init(sensors_s_spi, + p_hw_info->n_nthw_adapter_id, + "PCB", + NT_SENSOR_SOURCE_ADAPTER, + NT_SENSOR_TYPE_TEMPERATURE, + NT_SENSOR_NT200E3_PCB_TEMP, + SENSOR_MON_DS1775, 0, + SENSOR_MON_LITTLE_ENDIAN, + SENSOR_MON_SIGNED, + &ds1775_t, 0xFFFF); + sensors_list_ptr = sensors_list_ptr->next; + adapter->adapter_sensors_cnt++; + + NT_LOG(DBG, ETHDEV, "AVR sensors init finished\n"); + + if (nt_avr_sensor_mon_ctrl(sensors_s_spi, + SENSOR_MON_CTRL_RUN) != 0) { + /* start sensor monitoring */ + NT_LOG(ERR, ETHDEV, + "Failed to start AVR sensors monitoring\n"); + } else { + NT_LOG(DBG, ETHDEV, + "AVR sensors monitoring starteed\n"); + } + } + + nthw_spi_v3_delete(sensors_s_spi); + } +} + +int nt4ga_adapter_init(struct adapter_info_s *p_adapter_info) +{ + char *const p_dev_name = malloc(24); + char *const p_adapter_id_str = malloc(24); + fpga_info_t *fpga_info = &p_adapter_info->fpga_info; + hw_info_t *p_hw_info = &p_adapter_info->hw_info; + + /* + * IMPORTANT: Most variables cannot be determined before fpga model is instantiated + * (nthw_fpga_init()) + */ + int n_phy_ports = -1; + int n_nim_ports = -1; + int res = -1; + nt_fpga_t *p_fpga = NULL; + + (void)n_nim_ports; /* currently UNUSED - prevent warning */ + + p_hw_info->n_nthw_adapter_id = + nthw_platform_get_nthw_adapter_id(p_hw_info->pci_device_id); + + fpga_info->n_nthw_adapter_id = p_hw_info->n_nthw_adapter_id; + p_hw_info->hw_product_type = p_hw_info->pci_device_id & + 0x000f; /* ref: DN-0060 section 9 */ + /* ref: DN-0060 section 9 */ + p_hw_info->hw_platform_id = (p_hw_info->pci_device_id >> 4) & 0x00ff; + /* ref: DN-0060 section 9 */ + p_hw_info->hw_reserved1 = (p_hw_info->pci_device_id >> 12) & 0x000f; + + /* mp_dev_name */ + p_adapter_info->p_dev_name = p_dev_name; + if (p_dev_name) { + snprintf(p_dev_name, 24, "" PCIIDENT_PRINT_STR "", + PCIIDENT_TO_DOMAIN(p_adapter_info->fpga_info.pciident), + PCIIDENT_TO_BUSNR(p_adapter_info->fpga_info.pciident), + PCIIDENT_TO_DEVNR(p_adapter_info->fpga_info.pciident), + PCIIDENT_TO_FUNCNR(p_adapter_info->fpga_info.pciident)); + NT_LOG(DBG, ETHDEV, "%s: (0x%08X)\n", p_dev_name, + p_adapter_info->fpga_info.pciident); + } + + /* mp_adapter_id_str */ + p_adapter_info->mp_adapter_id_str = p_adapter_id_str; + + p_adapter_info->fpga_info.mp_adapter_id_str = p_adapter_id_str; + + if (p_adapter_id_str) { + snprintf(p_adapter_id_str, 24, "PCI:" PCIIDENT_PRINT_STR "", + PCIIDENT_TO_DOMAIN(p_adapter_info->fpga_info.pciident), + PCIIDENT_TO_BUSNR(p_adapter_info->fpga_info.pciident), + PCIIDENT_TO_DEVNR(p_adapter_info->fpga_info.pciident), + PCIIDENT_TO_FUNCNR(p_adapter_info->fpga_info.pciident)); + NT_LOG(DBG, ETHDEV, "%s: %s\n", p_adapter_id_str, p_dev_name); + } + + { + int i; + + for (i = 0; i < (int)ARRAY_SIZE(p_adapter_info->mp_port_id_str); + i++) { + char *p = malloc(32); + + if (p) { + snprintf(p, 32, "%s:intf_%d", + (p_adapter_id_str ? p_adapter_id_str : "NA"), + i); + NT_LOG(DBG, ETHDEV, "%s\n", p); + } + p_adapter_info->mp_port_id_str[i] = p; + } + } + + res = nthw_fpga_init(&p_adapter_info->fpga_info); + if (res) { + NT_LOG(ERR, ETHDEV, "%s: %s: FPGA=%04d res=x%08X [%s:%u]\n", + p_adapter_id_str, p_dev_name, fpga_info->n_fpga_prod_id, res, + __func__, __LINE__); + return res; + } + + assert(fpga_info); + p_fpga = fpga_info->mp_fpga; + assert(p_fpga); + n_phy_ports = fpga_info->n_phy_ports; + assert(n_phy_ports >= 1); + n_nim_ports = fpga_info->n_nims; + assert(n_nim_ports >= 1); + + /* + * HIF/PCI TA/TG + */ + { + res = nt4ga_pci_ta_tg_init(p_adapter_info); + if (res == 0) { + nt4ga_pci_ta_tg_measure_throughput_main(p_adapter_info, + 0, 0, + TG_PKT_SIZE, + TG_NUM_PACKETS, + TG_DELAY); + } else { + NT_LOG(WRN, ETHDEV, + "%s: PCI TA/TG is not available - skipping\n", + p_adapter_id_str); + } + } + + adapter_sensor_setup(p_hw_info, p_adapter_info); + + { + int i; + + assert(fpga_info->n_fpga_prod_id > 0); + for (i = 0; i < NUM_ADAPTER_PORTS_MAX; i++) { + /* Disable all ports. Must be enabled later */ + p_adapter_info->nt4ga_link.port_action[i].port_disable = + true; + } + switch (fpga_info->n_fpga_prod_id) { + /* NT200A02: 2x100G */ + case 9563: /* NT200A02 */ + res = nt4ga_link_100g_ports_init(p_adapter_info, p_fpga); + break; + default: + NT_LOG(ERR, ETHDEV, + "%s: Unsupported FPGA product: %04d\n", __func__, + fpga_info->n_fpga_prod_id); + res = -1; + break; + } + + if (res) { + NT_LOG(ERR, ETHDEV, + "%s: %s: %s: %u: FPGA=%04d res=x%08X\n", + p_adapter_id_str, p_dev_name, __func__, __LINE__, + fpga_info->n_fpga_prod_id, res); + return res; + } + } + + /* + * HostBuffer Systems + */ + p_adapter_info->n_rx_host_buffers = 0; + p_adapter_info->n_tx_host_buffers = 0; + + p_adapter_info->fpga_info.mp_nthw_epp = NULL; + if (nthw_epp_present(p_adapter_info->fpga_info.mp_fpga, 0)) { + p_adapter_info->fpga_info.mp_nthw_epp = nthw_epp_new(); + if (p_adapter_info->fpga_info.mp_nthw_epp == NULL) { + NT_LOG(ERR, ETHDEV, "%s: Cannot create EPP\n", + p_adapter_id_str); + return -1; + } + + res = nthw_epp_init(p_adapter_info->fpga_info.mp_nthw_epp, + p_adapter_info->fpga_info.mp_fpga, 0); + if (res != 0) { + NT_LOG(ERR, ETHDEV, "%s: Cannot initialize EPP\n", + p_adapter_id_str); + return res; + } + NT_LOG(DBG, ETHDEV, "%s: Initialized EPP\n", + p_adapter_id_str); + + res = nthw_epp_setup(p_adapter_info->fpga_info.mp_nthw_epp); + if (res != 0) { + NT_LOG(ERR, ETHDEV, "%s: Cannot setup EPP\n", + p_adapter_id_str); + return res; + } + } + + /* Nt4ga Stat init/setup */ + res = nt4ga_stat_init(p_adapter_info); + if (res != 0) { + NT_LOG(ERR, ETHDEV, + "%s: Cannot initialize the statistics module\n", + p_adapter_id_str); + return res; + } + res = nt4ga_stat_setup(p_adapter_info); + if (res != 0) { + NT_LOG(ERR, ETHDEV, "%s: Cannot setup the statistics module\n", + p_adapter_id_str); + return res; + } + + return 0; +} + +int nt4ga_adapter_deinit(struct adapter_info_s *p_adapter_info) +{ + fpga_info_t *fpga_info = &p_adapter_info->fpga_info; + int i; + int res; + struct nt_sensor_group *cur_adapter_sensor = NULL; + struct nt_sensor_group *next_adapter_sensor = NULL; + struct nim_sensor_group *cur_nim_sensor = NULL; + struct nim_sensor_group *next_nim_sensor = NULL; + + stop_monitor_tasks(-1); + + nt4ga_stat_stop(p_adapter_info); + + nthw_fpga_shutdown(&p_adapter_info->fpga_info); + + /* Rac rab reset flip flop */ + res = nthw_rac_rab_reset(fpga_info->mp_nthw_rac); + + /* Free adapter port ident strings */ + for (i = 0; i < fpga_info->n_phy_ports; i++) { + if (p_adapter_info->mp_port_id_str[i]) { + free(p_adapter_info->mp_port_id_str[i]); + p_adapter_info->mp_port_id_str[i] = NULL; + } + } + + /* Free adapter ident string */ + if (p_adapter_info->mp_adapter_id_str) { + free(p_adapter_info->mp_adapter_id_str); + p_adapter_info->mp_adapter_id_str = NULL; + } + + /* Free devname ident string */ + if (p_adapter_info->p_dev_name) { + free(p_adapter_info->p_dev_name); + p_adapter_info->p_dev_name = NULL; + } + + /* Free adapter sensors */ + if (p_adapter_info->adapter_sensors != NULL) { + do { + cur_adapter_sensor = p_adapter_info->adapter_sensors; + next_adapter_sensor = + p_adapter_info->adapter_sensors->next; + p_adapter_info->adapter_sensors = next_adapter_sensor; + + sensor_deinit(cur_adapter_sensor); + } while (next_adapter_sensor != NULL); + } + + /* Free NIM sensors */ + for (i = 0; i < fpga_info->n_phy_ports; i++) { + if (p_adapter_info->nim_sensors[i] != NULL) { + do { + cur_nim_sensor = p_adapter_info->nim_sensors[i]; + next_nim_sensor = + p_adapter_info->nim_sensors[i]->next; + p_adapter_info->nim_sensors[i] = next_nim_sensor; + free(cur_nim_sensor->sensor); + free(cur_nim_sensor); + } while (next_nim_sensor != NULL); + } + } + + return res; +} diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.h b/drivers/net/ntnic/adapter/nt4ga_adapter.h new file mode 100644 index 0000000000..6ae78a3743 --- /dev/null +++ b/drivers/net/ntnic/adapter/nt4ga_adapter.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NT4GA_ADAPTER_H_ +#define _NT4GA_ADAPTER_H_ + +#include "common_adapter_defs.h" + +struct adapter_info_s; + +/* + * DN-0060 section 9 + */ +typedef struct hw_info_s { + /* pciids */ + uint16_t pci_vendor_id; + uint16_t pci_device_id; + uint16_t pci_sub_vendor_id; + uint16_t pci_sub_device_id; + uint16_t pci_class_id; + + /* Derived from pciid */ + nthw_adapter_id_t n_nthw_adapter_id; + int hw_platform_id; + int hw_product_type; + int hw_reserved1; +} hw_info_t; + +/* + * Services provided by the adapter module + */ +#include "nt4ga_pci_ta_tg.h" +#include "nt4ga_filter.h" +#include "nt4ga_stat.h" +#include "nt4ga_link.h" + +#include "sensors.h" +#include "i2c_nim.h" +#include "sensor_types.h" + +typedef struct adapter_info_s { + struct nt4ga_pci_ta_tg_s nt4ga_pci_ta_tg; + struct nt4ga_stat_s nt4ga_stat; + struct nt4ga_filter_s nt4ga_filter; + struct nt4ga_link_s nt4ga_link; + + struct hw_info_s hw_info; + struct fpga_info_s fpga_info; + + uint16_t adapter_sensors_cnt; + uint16_t nim_sensors_cnt[NUM_ADAPTER_PORTS_MAX]; + struct nt_sensor_group *adapter_sensors; + struct nim_sensor_group *nim_sensors[NUM_ADAPTER_PORTS_MAX]; + + char *mp_port_id_str[NUM_ADAPTER_PORTS_MAX]; + char *mp_adapter_id_str; + char *p_dev_name; + volatile bool *pb_shutdown; + + int adapter_no; + int n_rx_host_buffers; + int n_tx_host_buffers; +} adapter_info_t; + +/* + * Monitor task operations. This structure defines the management hooks for + * Napatech network devices. The following hooks can be defined; unless noted + * otherwise, they are optional and can be filled with a null pointer. + * + * int (*mto_open)(int adapter, int port); + * The function to call when a network device transitions to the up state, + * e.g., `ip link set up`. + * + * int (*mto_stop)(int adapter, int port); + * The function to call when a network device transitions to the down state, + * e.g., `ip link set down`. + */ +struct monitor_task_ops { + int (*mto_open)(int adapter, int port); + int (*mto_stop)(int adapter, int port); +}; + +#include +#include + +/* The file nt4ga_adapter.c defines the next four variables. */ +extern pthread_t monitor_tasks[NUM_ADAPTER_MAX]; +extern volatile int monitor_task_is_running[NUM_ADAPTER_MAX]; + +/* + * Function that sets up signal handler(s) that stop the monitoring tasks. + */ +int set_up_signal_handlers_to_stop_monitoring_tasks(void); + +int nt4ga_adapter_init(struct adapter_info_s *p_adapter_info); +int nt4ga_adapter_deinit(struct adapter_info_s *p_adapter_info); + +int nt4ga_adapter_status(struct adapter_info_s *p_adapter_info); +int nt4ga_adapter_transmit_packet(struct adapter_info_s *p_adapter_info, + int n_intf_no, uint8_t *p_pkt, int n_pkt_len); + +int nt4ga_adapter_show_info(struct adapter_info_s *p_adapter_info, FILE *pfh); + +/* SPI for sensors reading */ +nthw_spis_t *new_sensors_t_spi(struct nt_fpga_s *p_fpga); + +#endif /* _NT4GA_ADAPTER_H_ */ diff --git a/drivers/net/ntnic/adapter/nt4ga_filter.h b/drivers/net/ntnic/adapter/nt4ga_filter.h new file mode 100644 index 0000000000..ad7e7d8c71 --- /dev/null +++ b/drivers/net/ntnic/adapter/nt4ga_filter.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NT4GA_FILTER_H_ +#define NT4GA_FILTER_H_ + +typedef struct nt4ga_filter_s { + int n_intf_cnt; + int n_queues_per_intf_cnt; + + struct flow_nic_dev *mp_flow_device; +} nt4ga_filter_t; + +#endif /* NT4GA_FILTER_H_ */ diff --git a/drivers/net/ntnic/adapter/nt4ga_link.c b/drivers/net/ntnic/adapter/nt4ga_link.c new file mode 100644 index 0000000000..7fbdb72897 --- /dev/null +++ b/drivers/net/ntnic/adapter/nt4ga_link.c @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include + +#include "ntlog.h" +#include "nthw_drv.h" +#include "nt4ga_adapter.h" + +#include "nt4ga_link.h" +#include "nt_util.h" + +/* + * port: speed capabilitoes + * This is actually an adapter capability mapped onto every port + */ +uint32_t nt4ga_port_get_link_speed_capabilities(struct adapter_info_s *p _unused, + int port _unused) +{ + nt4ga_link_t *const p_link = &p->nt4ga_link; + const uint32_t nt_link_speed_capa = p_link->speed_capa; + return nt_link_speed_capa; +} + +/* + * port: nim present + */ +bool nt4ga_port_get_nim_present(struct adapter_info_s *p, int port) +{ + nt4ga_link_t *const p_link = &p->nt4ga_link; + const bool nim_present = p_link->link_state[port].nim_present; + return nim_present; +} + +/* + * port: link mode + */ +void nt4ga_port_set_adm_state(struct adapter_info_s *p, int port, bool adm_state) +{ + nt4ga_link_t *const p_link = &p->nt4ga_link; + + p_link->port_action[port].port_disable = !adm_state; +} + +bool nt4ga_port_get_adm_state(struct adapter_info_s *p, int port) +{ + nt4ga_link_t *const p_link = &p->nt4ga_link; + const bool adm_state = !p_link->port_action[port].port_disable; + return adm_state; +} + +/* + * port: link status + */ +void nt4ga_port_set_link_status(struct adapter_info_s *p, int port, + bool link_status) +{ + /* Setting link state/status is (currently) the same as controlling the port adm state */ + nt4ga_port_set_adm_state(p, port, link_status); +} + +bool nt4ga_port_get_link_status(struct adapter_info_s *p, int port) +{ + nt4ga_link_t *const p_link = &p->nt4ga_link; + bool status = p_link->link_state[port].link_up; + return status; +} + +/* + * port: link speed + */ +void nt4ga_port_set_link_speed(struct adapter_info_s *p, int port, + nt_link_speed_t speed) +{ + nt4ga_link_t *const p_link = &p->nt4ga_link; + + p_link->port_action[port].port_speed = speed; + p_link->link_info[port].link_speed = speed; +} + +nt_link_speed_t nt4ga_port_get_link_speed(struct adapter_info_s *p, int port) +{ + nt4ga_link_t *const p_link = &p->nt4ga_link; + nt_link_speed_t speed = p_link->link_info[port].link_speed; + return speed; +} + +/* + * port: link autoneg + * Currently not fully supported by link code + */ +void nt4ga_port_set_link_autoneg(struct adapter_info_s *p _unused, + int port _unused, bool autoneg _unused) +{ + nt4ga_link_t *const p_link _unused = &p->nt4ga_link; +} + +bool nt4ga_port_get_link_autoneg(struct adapter_info_s *p _unused, + int port _unused) +{ + nt4ga_link_t *const p_link _unused = &p->nt4ga_link; + return true; +} + +/* + * port: link duplex + * Currently not fully supported by link code + */ +void nt4ga_port_set_link_duplex(struct adapter_info_s *p, int port, + nt_link_duplex_t duplex) +{ + nt4ga_link_t *const p_link = &p->nt4ga_link; + + p_link->port_action[port].port_duplex = duplex; +} + +nt_link_duplex_t nt4ga_port_get_link_duplex(struct adapter_info_s *p, int port) +{ + nt4ga_link_t *const p_link = &p->nt4ga_link; + nt_link_duplex_t duplex = p_link->link_info[port].link_duplex; + return duplex; +} + +/* + * port: loopback mode + */ +void nt4ga_port_set_loopback_mode(struct adapter_info_s *p, int port, + uint32_t mode) +{ + nt4ga_link_t *const p_link = &p->nt4ga_link; + + p_link->port_action[port].port_lpbk_mode = mode; +} + +uint32_t nt4ga_port_get_loopback_mode(struct adapter_info_s *p, int port) +{ + nt4ga_link_t *const p_link = &p->nt4ga_link; + + return p_link->port_action[port].port_lpbk_mode; +} + +/* + * port: nim capabilities + */ +nim_i2c_ctx_t nt4ga_port_get_nim_capabilities(struct adapter_info_s *p, int port) +{ + nt4ga_link_t *const p_link = &p->nt4ga_link; + nim_i2c_ctx_t nim_ctx = p_link->u.var100g.nim_ctx[port]; + return nim_ctx; +} + +/* + * port: tx power + */ +int nt4ga_port_tx_power(struct adapter_info_s *p, int port, bool disable) +{ + nt4ga_link_t *link_info = &p->nt4ga_link; + + if (link_info->u.nim_ctx[port].port_type == NT_PORT_TYPE_QSFP28_SR4 || + link_info->u.nim_ctx[port].port_type == NT_PORT_TYPE_QSFP28 || + link_info->u.nim_ctx[port].port_type == NT_PORT_TYPE_QSFP28_LR4) { + nim_i2c_ctx_t *nim_ctx = &link_info->u.var100g.nim_ctx[port]; + + if (!nim_ctx->specific_u.qsfp.rx_only) { + if (nim_qsfp_plus_nim_set_tx_laser_disable(nim_ctx, disable, + -1) != 0) + return 1; + } + } else { + return -1; + } + return 0; +} diff --git a/drivers/net/ntnic/adapter/nt4ga_link.h b/drivers/net/ntnic/adapter/nt4ga_link.h new file mode 100644 index 0000000000..2be9f49075 --- /dev/null +++ b/drivers/net/ntnic/adapter/nt4ga_link.h @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NT4GA_LINK_H_ +#define NT4GA_LINK_H_ + +#include "common_adapter_defs.h" +#include "nthw_drv.h" +#include "i2c_nim.h" +#include "nthw_fpga_rst_nt200a0x.h" + +/* + * Link state.\n + * Just after start of ntservice the link state might be unknown since the + * monitoring routine is busy reading NIM state and NIM data. This might also + * be the case after a NIM is plugged into an interface. + * The error state indicates a HW reading error. + */ +enum nt_link_state_e { + NT_LINK_STATE_UNKNOWN = 0, /* The link state has not been read yet */ + NT_LINK_STATE_DOWN = 1, /* The link state is DOWN */ + NT_LINK_STATE_UP = 2, /* The link state is UP */ + NT_LINK_STATE_ERROR = 3 /* The link state could not be read */ +}; + +typedef enum nt_link_state_e nt_link_state_t, *nt_link_state_p; + +/* + * Link duplex mode + */ +enum nt_link_duplex_e { + NT_LINK_DUPLEX_UNKNOWN = 0, + NT_LINK_DUPLEX_HALF = 0x01, /* Half duplex */ + NT_LINK_DUPLEX_FULL = 0x02, /* Full duplex */ +}; + +typedef enum nt_link_duplex_e nt_link_duplex_t; + +/* + * Link loopback mode + */ +enum nt_link_loopback_e { + NT_LINK_LOOPBACK_OFF = 0, + NT_LINK_LOOPBACK_HOST = 0x01, /* Host loopback mode */ + NT_LINK_LOOPBACK_LINE = 0x02, /* Line loopback mode */ +}; + +/* + * Link MDI mode + */ +enum nt_link_mdi_e { + NT_LINK_MDI_NA = 0, + NT_LINK_MDI_AUTO = 0x01, /* MDI auto */ + NT_LINK_MDI_MDI = 0x02, /* MDI mode */ + NT_LINK_MDI_MDIX = 0x04, /* MDIX mode */ +}; + +typedef enum nt_link_mdi_e nt_link_mdi_t; + +/* + * Link Auto/Manual mode + */ +enum nt_link_auto_neg_e { + NT_LINK_AUTONEG_NA = 0, + NT_LINK_AUTONEG_MANUAL = 0x01, + NT_LINK_AUTONEG_OFF = NT_LINK_AUTONEG_MANUAL, /* Auto negotiation OFF */ + NT_LINK_AUTONEG_AUTO = 0x02, + NT_LINK_AUTONEG_ON = NT_LINK_AUTONEG_AUTO, /* Auto negotiation ON */ +}; + +typedef enum nt_link_auto_neg_e nt_link_auto_neg_t; + +/* + * Callback functions to setup mac, pcs and phy + */ +typedef struct link_state_s { + bool link_disabled; + bool nim_present; + bool lh_nim_absent; + bool link_up; + enum nt_link_state_e link_state; + enum nt_link_state_e link_state_latched; +} link_state_t; + +typedef struct link_info_s { + enum nt_link_speed_e link_speed; + enum nt_link_duplex_e link_duplex; + enum nt_link_auto_neg_e link_auto_neg; +} link_info_t; + +typedef struct port_action_s { + bool port_disable; + enum nt_link_speed_e port_speed; + enum nt_link_duplex_e port_duplex; + uint32_t port_lpbk_mode; +} port_action_t; + +typedef struct adapter_100g_s { + nim_i2c_ctx_t + nim_ctx[NUM_ADAPTER_PORTS_MAX]; /* Should be the first field */ + nthw_mac_pcs_t mac_pcs100g[NUM_ADAPTER_PORTS_MAX]; + nthw_gpio_phy_t gpio_phy[NUM_ADAPTER_PORTS_MAX]; +} adapter_100g_t; + +typedef union adapter_var_s { + nim_i2c_ctx_t nim_ctx + [NUM_ADAPTER_PORTS_MAX]; /* First field in all the adaptors type */ + adapter_100g_t var100g; +} adapter_var_u; + +typedef struct nt4ga_link_s { + link_state_t link_state[NUM_ADAPTER_PORTS_MAX]; + link_info_t link_info[NUM_ADAPTER_PORTS_MAX]; + port_action_t port_action[NUM_ADAPTER_PORTS_MAX]; + uint32_t speed_capa; + /* */ + bool variables_initialized; + adapter_var_u u; +} nt4ga_link_t; + +bool nt4ga_port_get_nim_present(struct adapter_info_s *p, int port); + +/* + * port:s link mode + */ +void nt4ga_port_set_adm_state(struct adapter_info_s *p, int port, + bool adm_state); +bool nt4ga_port_get_adm_state(struct adapter_info_s *p, int port); + +/* + * port:s link status + */ +void nt4ga_port_set_link_status(struct adapter_info_s *p, int port, bool status); +bool nt4ga_port_get_link_status(struct adapter_info_s *p, int port); + +/* + * port: link autoneg + */ +void nt4ga_port_set_link_autoneg(struct adapter_info_s *p, int port, + bool autoneg); +bool nt4ga_port_get_link_autoneg(struct adapter_info_s *p, int port); + +/* + * port: link speed + */ +void nt4ga_port_set_link_speed(struct adapter_info_s *p, int port, + nt_link_speed_t speed); +nt_link_speed_t nt4ga_port_get_link_speed(struct adapter_info_s *p, int port); + +/* + * port: link duplex + */ +void nt4ga_port_set_link_duplex(struct adapter_info_s *p, int port, + nt_link_duplex_t duplex); +nt_link_duplex_t nt4ga_port_get_link_duplex(struct adapter_info_s *p, int port); + +/* + * port: loopback mode + */ +void nt4ga_port_set_loopback_mode(struct adapter_info_s *p, int port, + uint32_t mode); +uint32_t nt4ga_port_get_loopback_mode(struct adapter_info_s *p, int port); + +uint32_t nt4ga_port_get_link_speed_capabilities(struct adapter_info_s *p, + int port); + +/* + * port: nim capabilities + */ +nim_i2c_ctx_t nt4ga_port_get_nim_capabilities(struct adapter_info_s *p, + int port); + +/* + * port: tx power + */ +int nt4ga_port_tx_power(struct adapter_info_s *p, int port, bool disable); + +#endif /* NT4GA_LINK_H_ */ diff --git a/drivers/net/ntnic/adapter/nt4ga_link_100g.c b/drivers/net/ntnic/adapter/nt4ga_link_100g.c new file mode 100644 index 0000000000..8465b6a341 --- /dev/null +++ b/drivers/net/ntnic/adapter/nt4ga_link_100g.c @@ -0,0 +1,825 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nt_util.h" +#include "ntlog.h" +#include "i2c_nim.h" +#include "nt4ga_adapter.h" +#include "nt4ga_link_100g.h" + +#include /* memcmp, memset */ + +/* + * Prototypes + */ +static int swap_tx_rx_polarity(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs, + int port, bool swap); +static int reset_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs); + +/* + * Structs and types definitions + */ +enum link_up_state { + RESET, /* A valid signal is detected by NO local faults. */ + EXPECT_NO_LF, /* After that we check NO latched local fault bit before */ + /* de-asserting Remote fault indication. */ + WAIT_STABLE_LINK, /* Now we expect the link is up. */ + MONITOR_LINK /* After link-up we monitor link state. */ +}; + +typedef struct _monitoring_state { + /* Fields below are set by monitoring thread */ + enum link_up_state m_link_up_state; + enum nt_link_state_e link_state; + enum nt_link_state_e latch_link_state; + int m_time_out; +} monitoring_state_t, *monitoring_state_p; + +/* + * Global variables + */ + +/* + * External state, to be set by the network driver. + */ + +/* + * Utility functions + */ + +static void set_loopback(struct adapter_info_s *p_adapter_info, + nthw_mac_pcs_t *mac_pcs, int intf_no, uint32_t mode, + uint32_t last_mode) +{ + bool swap_polerity = true; + + switch (mode) { + case 1: + NT_LOG(INF, ETHDEV, "%s: Applying host loopback\n", + p_adapter_info->mp_port_id_str[intf_no]); + nthw_mac_pcs_set_fec(mac_pcs, true); + nthw_mac_pcs_set_host_loopback(mac_pcs, true); + swap_polerity = false; + break; + case 2: + NT_LOG(INF, ETHDEV, "%s: Applying line loopback\n", + p_adapter_info->mp_port_id_str[intf_no]); + nthw_mac_pcs_set_line_loopback(mac_pcs, true); + break; + default: + switch (last_mode) { + case 1: + NT_LOG(INF, ETHDEV, "%s: Removing host loopback\n", + p_adapter_info->mp_port_id_str[intf_no]); + nthw_mac_pcs_set_host_loopback(mac_pcs, false); + break; + case 2: + NT_LOG(INF, ETHDEV, "%s: Removing line loopback\n", + p_adapter_info->mp_port_id_str[intf_no]); + nthw_mac_pcs_set_line_loopback(mac_pcs, false); + break; + default: + /* Do nothing */ + break; + } + break; + } + + if ((p_adapter_info->fpga_info.nthw_hw_info.hw_id == 2 && + p_adapter_info->hw_info.n_nthw_adapter_id == NT_HW_ADAPTER_ID_NT200A01) || + p_adapter_info->hw_info.n_nthw_adapter_id == NT_HW_ADAPTER_ID_NT200A02) { + (void)swap_tx_rx_polarity(p_adapter_info, mac_pcs, intf_no, + swap_polerity); + } + + /* After changing the loopback the system must be properly reset */ + reset_rx(p_adapter_info, mac_pcs); + + NT_OS_WAIT_USEC(10000); /* 10ms - arbitrary choice */ + + if (!nthw_mac_pcs_is_rx_path_rst(mac_pcs)) { + nthw_mac_pcs_reset_bip_counters(mac_pcs); + if (!nthw_mac_pcs_get_fec_bypass(mac_pcs)) + nthw_mac_pcs_reset_fec_counters(mac_pcs); + } +} + +/* + * Function to retrieve the current state of a link (for one port) + */ +static int link_state_build(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs, + nthw_gpio_phy_t *gpio_phy, int port, + link_state_t *state, bool is_port_disabled) +{ + uint32_t abs; + uint32_t phy_link_state; + uint32_t lh_abs; + uint32_t ll_phy_link_state; + uint32_t link_down_cnt; + uint32_t nim_interr; + uint32_t lh_local_fault; + uint32_t lh_remote_fault; + uint32_t lh_internal_local_fault; + uint32_t lh_received_local_fault; + + memset(state, 0, sizeof(*state)); + state->link_disabled = is_port_disabled; + nthw_mac_pcs_get_link_summary(mac_pcs, &abs, &phy_link_state, &lh_abs, + &ll_phy_link_state, &link_down_cnt, + &nim_interr, &lh_local_fault, + &lh_remote_fault, &lh_internal_local_fault, + &lh_received_local_fault); + + assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX); + state->nim_present = + nthw_gpio_phy_is_module_present(gpio_phy, (uint8_t)port); + state->lh_nim_absent = !state->nim_present; + state->link_up = phy_link_state ? true : false; + + { + static char lsbuf[NUM_ADAPTER_MAX][NUM_ADAPTER_PORTS_MAX][256]; + char buf[255]; + const int adapter_no = drv->adapter_no; + + snprintf(buf, sizeof(buf), + "%s: Port = %d: abs = %u, phy_link_state = %u, lh_abs = %u, " + "ll_phy_link_state = %u, link_down_cnt = %u, nim_interr = %u, " + "lh_local_fault = %u, lh_remote_fault = %u, lh_internal_local_fault = %u, " + "lh_received_local_fault = %u", + drv->mp_adapter_id_str, mac_pcs->mn_instance, abs, + phy_link_state, lh_abs, ll_phy_link_state, + link_down_cnt, nim_interr, lh_local_fault, + lh_remote_fault, lh_internal_local_fault, + lh_received_local_fault); + if (strcmp(lsbuf[adapter_no][port], buf) != 0) { + rte_strscpy(lsbuf[adapter_no][port], buf, + sizeof(lsbuf[adapter_no][port]) - 1U); + lsbuf[adapter_no][port] + [sizeof(lsbuf[adapter_no][port]) - 1U] = '\0'; + NT_LOG(DBG, ETHDEV, "%s\n", lsbuf[adapter_no][port]); + } + } + return 0; +} + +/* + * Check whether a NIM module is present + */ +static bool nim_is_present(nthw_gpio_phy_t *gpio_phy, uint8_t if_no) +{ + assert(if_no < NUM_ADAPTER_PORTS_MAX); + + return nthw_gpio_phy_is_module_present(gpio_phy, if_no); +} + +/* + * Enable RX + */ +static int enable_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs) +{ + (void)drv; /* unused */ + nthw_mac_pcs_set_rx_enable(mac_pcs, true); + return 0; +} + +/* + * Enable TX + */ +static int enable_tx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs) +{ + (void)drv; /* unused */ + nthw_mac_pcs_set_tx_enable(mac_pcs, true); + nthw_mac_pcs_set_tx_sel_host(mac_pcs, true); + return 0; +} + +/* + * Disable RX + */ +static int disable_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs) +{ + (void)drv; /* unused */ + nthw_mac_pcs_set_rx_enable(mac_pcs, false); + return 0; +} + +/* + * Disable TX + */ +static int disable_tx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs) +{ + (void)drv; /* unused */ + nthw_mac_pcs_set_tx_enable(mac_pcs, false); + nthw_mac_pcs_set_tx_sel_host(mac_pcs, false); + return 0; +} + +/* + * Reset RX + */ +static int reset_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs) +{ + (void)drv; + + nthw_mac_pcs_rx_path_rst(mac_pcs, true); + NT_OS_WAIT_USEC(10000); /* 10ms */ + nthw_mac_pcs_rx_path_rst(mac_pcs, false); + NT_OS_WAIT_USEC(10000); /* 10ms */ + + return 0; +} + +/* + * Reset TX + */ + +/* + * Swap tx/rx polarity + */ +static int swap_tx_rx_polarity(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs, + int port, bool swap) +{ + const bool tx_polarity_swap[2][4] = { { true, true, false, false }, + { false, true, false, false } + }; + const bool rx_polarity_swap[2][4] = { { false, true, true, true }, + { false, true, true, false } + }; + uint8_t lane; + + (void)drv; + for (lane = 0U; lane < 4U; lane++) { + if (swap) { + nthw_mac_pcs_swap_gty_tx_polarity(mac_pcs, lane, + tx_polarity_swap[port][lane]); + nthw_mac_pcs_swap_gty_rx_polarity(mac_pcs, lane, + rx_polarity_swap[port][lane]); + } else { + nthw_mac_pcs_swap_gty_tx_polarity(mac_pcs, lane, false); + nthw_mac_pcs_swap_gty_rx_polarity(mac_pcs, lane, false); + } + } + return 0; +} + +/* + * Check link once NIM is installed and link can be expected. + */ +static int check_link_state(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs) +{ + bool rst_required; + bool ber; + bool fec_all_locked; + + rst_required = nthw_mac_pcs_reset_required(mac_pcs); + + ber = nthw_mac_pcs_get_hi_ber(mac_pcs); + + fec_all_locked = nthw_mac_pcs_get_fec_stat_all_am_locked(mac_pcs); + + if (rst_required || ber || !fec_all_locked) + reset_rx(drv, mac_pcs); + + return 0; +} + +/* + * Initialize NIM, Code based on nt200e3_2_ptp.cpp: MyPort::createNim() + */ +static int create_nim(adapter_info_t *drv, nt_fpga_t *fpga, int port, + bool enable) +{ + int res = 0; + const uint8_t valid_nim_id = 17U; + nthw_gpio_phy_t *gpio_phy; + nim_i2c_ctx_t *nim_ctx; + sfp_nim_state_t nim; + nt4ga_link_t *link_info = &drv->nt4ga_link; + nthw_mac_pcs_t *mac_pcs = &link_info->u.var100g.mac_pcs100g[port]; + + (void)fpga; /* unused */ + assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX); + assert(link_info->variables_initialized); + + gpio_phy = &link_info->u.var100g.gpio_phy[port]; + nim_ctx = &link_info->u.var100g.nim_ctx[port]; + + /* + * Check NIM is present before doing GPIO PHY reset. + */ + if (!nim_is_present(gpio_phy, (uint8_t)port)) { + NT_LOG(INF, ETHDEV, "%s: NIM module is absent\n", + drv->mp_port_id_str[port]); + return 0; + } + + if (!enable) { + disable_rx(drv, mac_pcs); + disable_tx(drv, mac_pcs); + reset_rx(drv, mac_pcs); + } + + /* + * Perform PHY reset. + */ + NT_LOG(DBG, ETHDEV, "%s: Performing NIM reset\n", + drv->mp_port_id_str[port]); + nthw_gpio_phy_set_reset(gpio_phy, (uint8_t)port, true); + NT_OS_WAIT_USEC(100000); /* pause 0.1s */ + nthw_gpio_phy_set_reset(gpio_phy, (uint8_t)port, false); + + /* + * Wait a little after a module has been inserted before trying to access I2C + * data, otherwise the module will not respond correctly. + */ + NT_OS_WAIT_USEC(1000000); /* pause 1.0s */ + + if (!nim_is_present(gpio_phy, (uint8_t)port)) { + NT_LOG(DBG, ETHDEV, "%s: NIM module is no longer absent!\n", + drv->mp_port_id_str[port]); + return -1; + } + + res = construct_and_preinit_nim(nim_ctx, NULL, port, + ((struct adapter_info_s *)drv)->nim_sensors, + &((struct adapter_info_s *)drv)->nim_sensors_cnt[port]); + if (res) + return res; + + res = nim_state_build(nim_ctx, &nim); + if (res) + return res; + + NT_LOG(DBG, NTHW, + "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'\n", + drv->mp_port_id_str[port], nim_ctx->nim_id, + nim_id_to_text(nim_ctx->nim_id), nim.br, nim_ctx->vendor_name, + nim_ctx->prod_no, nim_ctx->serial_no); + + /* + * Does the driver support the NIM module type? + */ + if (nim_ctx->nim_id != valid_nim_id) { + NT_LOG(ERR, NTHW, + "%s: The driver does not support the NIM module type %s\n", + drv->mp_port_id_str[port], nim_id_to_text(nim_ctx->nim_id)); + NT_LOG(DBG, NTHW, + "%s: The driver supports the NIM module type %s\n", + drv->mp_port_id_str[port], nim_id_to_text(valid_nim_id)); + return -1; + } + + if (enable) { + NT_LOG(DBG, ETHDEV, "%s: De-asserting low power\n", + drv->mp_port_id_str[port]); + nthw_gpio_phy_set_low_power(gpio_phy, (uint8_t)port, false); + } else { + NT_LOG(DBG, ETHDEV, "%s: Asserting low power\n", + drv->mp_port_id_str[port]); + nthw_gpio_phy_set_low_power(gpio_phy, (uint8_t)port, true); + } + + return res; +} + +/* + * Initialize one 100 Gbps port. + * The function shall not assume anything about the state of the adapter + * and/or port. + */ +static int port_init(adapter_info_t *drv, nt_fpga_t *fpga, int port) +{ + int adapter_id; + int hw_id; + int res; + nt4ga_link_t *link_info = &drv->nt4ga_link; + + nthw_mac_pcs_t *mac_pcs; + + assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX); + assert(link_info->variables_initialized); + + if (fpga && fpga->p_fpga_info) { + adapter_id = fpga->p_fpga_info->n_nthw_adapter_id; + hw_id = fpga->p_fpga_info->nthw_hw_info.hw_id; + } else { + adapter_id = -1; + hw_id = -1; + } + + mac_pcs = &link_info->u.var100g.mac_pcs100g[port]; + + /* + * Phase 1. Pre-state machine (`port init` functions) + * 1.1) Nt4gaAdapter::portInit() + */ + + /* No adapter set-up here, only state variables */ + + /* 1.2) MyPort::init() */ + link_info->link_info[port].link_speed = NT_LINK_SPEED_100G; + link_info->link_info[port].link_duplex = NT_LINK_DUPLEX_FULL; + link_info->link_info[port].link_auto_neg = NT_LINK_AUTONEG_OFF; + link_info->speed_capa |= NT_LINK_SPEED_100G; + nthw_mac_pcs_set_led_mode(mac_pcs, NTHW_MAC_PCS_LED_AUTO); + nthw_mac_pcs_set_receiver_equalization_mode(mac_pcs, + nthw_mac_pcs_receiver_mode_lpm); + + /* + * NT200A01 build 2 HW and NT200A02 that require GTY polarity swap + * if (adapter is `NT200A01 build 2 HW or NT200A02`) + */ + if (adapter_id == NT_HW_ADAPTER_ID_NT200A02 || + (adapter_id == NT_HW_ADAPTER_ID_NT200A01 && hw_id == 2)) + (void)swap_tx_rx_polarity(drv, mac_pcs, port, true); + + nthw_mac_pcs_set_ts_eop(mac_pcs, true); /* end-of-frame timestamping */ + + /* Work in ABSOLUTE timing mode, don't set IFG mode. */ + + /* Phase 2. Pre-state machine (`setup` functions) */ + + /* 2.1) nt200a0x.cpp:Myport::setup() */ + NT_LOG(DBG, ETHDEV, "%s: Setting up port %d\n", drv->mp_port_id_str[port], + port); + + NT_LOG(DBG, ETHDEV, "%s: Port %d: PHY TX enable\n", + drv->mp_port_id_str[port], port); + enable_tx(drv, mac_pcs); + reset_rx(drv, mac_pcs); + + /* 2.2) Nt4gaPort::setup() */ + if (nthw_gmf_init(NULL, fpga, port) == 0) { + nthw_gmf_t gmf; + + if (nthw_gmf_init(&gmf, fpga, port) == 0) + nthw_gmf_set_enable(&gmf, true); + } + + /* Phase 3. Link state machine steps */ + + /* 3.1) Create NIM, ::createNim() */ + res = create_nim(drv, fpga, port, true); + + if (res) { + NT_LOG(WRN, ETHDEV, "%s: NIM initialization failed\n", + drv->mp_port_id_str[port]); + return res; + } + + NT_LOG(DBG, ETHDEV, "%s: NIM initialized\n", drv->mp_port_id_str[port]); + + /* 3.2) MyPort::nimReady() */ + + /* 3.3) MyPort::nimReady100Gb() */ + + /* Setting FEC resets the lane counter in one half of the GMF */ + nthw_mac_pcs_set_fec(mac_pcs, true); + NT_LOG(DBG, ETHDEV, "%s: Port %d: HOST FEC enabled\n", + drv->mp_port_id_str[port], port); + + if (adapter_id == NT_HW_ADAPTER_ID_NT200A01 && hw_id == 1) { + const uint8_t tuning_s_r4[2][4][3] = { { { 8, 15, 8 }, + { 8, 15, 9 }, + { 7, 15, 9 }, + { 6, 15, 8 } + }, + { { 6, 15, 8 }, + { 3, 15, 12 }, + { 7, 15, 9 }, + { 7, 15, 8 } + } + }; + + uint8_t lane = 0; + + for (lane = 0; lane < 4; lane++) { + uint8_t pre, diff, post; + + /* Use short-range tuning values */ + pre = tuning_s_r4[port][lane][0]; + diff = tuning_s_r4[port][lane][1]; + post = tuning_s_r4[port][lane][2]; + + nthw_mac_pcs_set_gty_tx_tuning(mac_pcs, lane, pre, diff, + post); + } + } else if ((adapter_id == NT_HW_ADAPTER_ID_NT200A02) || + ((adapter_id == NT_HW_ADAPTER_ID_NT200A01) && + (hw_id == 2))) { + const uint8_t pre = 5; + const uint8_t diff = 25; + const uint8_t post = 12; + + uint8_t lane = 0; + + for (lane = 0; lane < 4; lane++) { + nthw_mac_pcs_set_gty_tx_tuning(mac_pcs, lane, pre, diff, + post); + } + } else { + NT_LOG(ERR, ETHDEV, + "%s: Unhandled AdapterId/HwId: %02x_hwid%d\n", __func__, + adapter_id, hw_id); + assert(0); + } + reset_rx(drv, mac_pcs); + + /* + * 3.4) MyPort::setLinkState() + * + * Compensation = 1640 - dly + * CMAC-core dly 188 ns + * FEC no correction 87 ns + * FEC active correction 211 + */ + if (nthw_mac_pcs_get_fec_valid(mac_pcs)) + nthw_mac_pcs_set_timestamp_comp_rx(mac_pcs, (1640 - 188 - 211)); + + else + nthw_mac_pcs_set_timestamp_comp_rx(mac_pcs, (1640 - 188 - 87)); + + /* 3.5) uint32_t MyPort::macConfig(nt_link_state_t link_state) */ + enable_rx(drv, mac_pcs); + + nthw_mac_pcs_set_host_loopback(mac_pcs, false); + + return res; +} + +/* + * State machine shared between kernel and userland + */ +static int common_ptp_nim_state_machine(void *data) +{ + adapter_info_t *drv = (adapter_info_t *)data; + fpga_info_t *fpga_info = &drv->fpga_info; + nt4ga_link_t *link_info = &drv->nt4ga_link; + nt_fpga_t *fpga = fpga_info->mp_fpga; + const int adapter_no = drv->adapter_no; + const int nb_ports = fpga_info->n_phy_ports; + uint32_t last_lpbk_mode[NUM_ADAPTER_PORTS_MAX]; + + nim_i2c_ctx_t *nim_ctx; + link_state_t *link_state; + nthw_mac_pcs_t *mac_pcs; + nthw_gpio_phy_t *gpio_phy; + + if (!fpga) { + NT_LOG(ERR, ETHDEV, "%s: fpga is NULL\n", drv->mp_adapter_id_str); + goto NT4GA_LINK_100G_MON_EXIT; + } + + assert(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX); + nim_ctx = link_info->u.var100g.nim_ctx; + link_state = link_info->link_state; + mac_pcs = link_info->u.var100g.mac_pcs100g; + gpio_phy = link_info->u.var100g.gpio_phy; + + monitor_task_is_running[adapter_no] = 1; + memset(last_lpbk_mode, 0, sizeof(last_lpbk_mode)); + + if (monitor_task_is_running[adapter_no]) { + NT_LOG(DBG, ETHDEV, "%s: link state machine running...\n", + drv->mp_adapter_id_str); + } + + while (monitor_task_is_running[adapter_no]) { + int i; + static bool reported_link[NUM_ADAPTER_PORTS_MAX] = { false }; + + /* Read sensors */ + if (drv->adapter_sensors != NULL) { + nthw_spis_t *t_spi = + new_sensors_t_spi(drv->fpga_info.mp_fpga); + if (t_spi) { + for (struct nt_sensor_group *ptr = + drv->adapter_sensors; + ptr != NULL; ptr = ptr->next) + ptr->read(ptr, t_spi); + nthw_spis_delete(t_spi); + } + } + + for (i = 0; i < nb_ports; i++) { + link_state_t new_link_state; + const bool is_port_disabled = + link_info->port_action[i].port_disable; + const bool was_port_disabled = + link_state[i].link_disabled; + const bool disable_port = is_port_disabled && + !was_port_disabled; + const bool enable_port = !is_port_disabled && + was_port_disabled; + + if (!monitor_task_is_running[adapter_no]) /* stop quickly */ + break; + + /* Reading NIM sensors */ + if (drv->nim_sensors[i] != NULL) { + nthw_spis_t *t_spi = new_sensors_t_spi(drv->fpga_info.mp_fpga); + if (t_spi) { + for (struct nim_sensor_group *ptr = + drv->nim_sensors[i]; + ptr != NULL; ptr = ptr->next) + ptr->read(ptr, t_spi); + nthw_spis_delete(t_spi); + } + } + + /* Has the administrative port state changed? */ + assert(!(disable_port && enable_port)); + if (disable_port) { + memset(&link_state[i], 0, + sizeof(link_state[i])); + link_state[i].link_disabled = true; + reported_link[i] = false; + /* Turn off laser and LED, etc. */ + (void)create_nim(drv, fpga, i, false); + NT_LOG(DBG, ETHDEV, "%s: Port %i is disabled\n", + drv->mp_port_id_str[i], i); + continue; + } + + if (enable_port) { + link_state[i].link_disabled = false; + NT_LOG(DBG, ETHDEV, "%s: Port %i is enabled\n", + drv->mp_port_id_str[i], i); + } + + if (is_port_disabled) + continue; + + if (link_info->port_action[i].port_lpbk_mode != + last_lpbk_mode[i]) { + /* Loopback mode has changed. Do something */ + if (!nim_is_present(&gpio_phy[i], + (uint8_t)i)) { + /* + * If there is no Nim present, we need to initialize the + * port anyway + */ + port_init(drv, fpga, i); + } + NT_LOG(INF, ETHDEV, + "%s: Loopback mode changed=%u\n", + drv->mp_port_id_str[i], + link_info->port_action[i].port_lpbk_mode); + set_loopback(drv, &mac_pcs[i], i, + link_info->port_action[i].port_lpbk_mode, + last_lpbk_mode[i]); + if (link_info->port_action[i].port_lpbk_mode == + 1) + link_state[i].link_up = true; + last_lpbk_mode[i] = + link_info->port_action[i].port_lpbk_mode; + continue; + } + + (void)link_state_build(drv, &mac_pcs[i], &gpio_phy[i], + i, &new_link_state, + is_port_disabled); + if (!new_link_state.nim_present) { + if (link_state[i].nim_present) { + NT_LOG(INF, ETHDEV, + "%s: NIM module removed\n", + drv->mp_port_id_str[i]); + } + link_state[i] = new_link_state; + continue; + } + + /* NIM module is present */ + if (new_link_state.lh_nim_absent || + !link_state[i].nim_present) { + sfp_nim_state_t new_state; + + NT_LOG(DBG, ETHDEV, "%s: NIM module inserted\n", + drv->mp_port_id_str[i]); + + if (port_init(drv, fpga, i)) { + NT_LOG(ERR, ETHDEV, + "%s: Failed to initialize NIM module\n", + drv->mp_port_id_str[i]); + continue; + } + if (nim_state_build(&nim_ctx[i], &new_state)) { + NT_LOG(ERR, ETHDEV, + "%s: Cannot read basic NIM data\n", + drv->mp_port_id_str[i]); + continue; + } + assert(new_state.br); /* Cannot be zero if NIM is present */ + NT_LOG(DBG, ETHDEV, + "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'\n", + drv->mp_port_id_str[i], nim_ctx->nim_id, + nim_id_to_text(nim_ctx->nim_id), + (unsigned int)new_state.br, + nim_ctx->vendor_name, nim_ctx->prod_no, + nim_ctx->serial_no); + + (void)link_state_build(drv, &mac_pcs[i], + &gpio_phy[i], i, + &link_state[i], + is_port_disabled); + + NT_LOG(DBG, ETHDEV, + "%s: NIM module initialized\n", + drv->mp_port_id_str[i]); + continue; + } + if (reported_link[i] != new_link_state.link_up) { + NT_LOG(INF, ETHDEV, "%s: link is %s\n", + drv->mp_port_id_str[i], + (new_link_state.link_up ? "up" : + "down")); + link_state[i].link_up = new_link_state.link_up; + reported_link[i] = new_link_state.link_up; + } + check_link_state(drv, &mac_pcs[i]); + } /* end-for */ + if (monitor_task_is_running[adapter_no]) + NT_OS_WAIT_USEC(5 * 100000U); /* 5 x 0.1s = 0.5s */ + } + +NT4GA_LINK_100G_MON_EXIT: + + NT_LOG(DBG, ETHDEV, + "%s: Stopped NT4GA 100 Gbps link monitoring thread.\n", + drv->mp_adapter_id_str); + + return 0; +} + +/* + * Userland NIM state machine + */ +static void *nt4ga_link_100g_mon(void *data) +{ + (void)common_ptp_nim_state_machine(data); + + return NULL; +} + +/* + * Initialize all ports + * The driver calls this function during initialization (of the driver). + */ +int nt4ga_link_100g_ports_init(struct adapter_info_s *p_adapter_info, + nt_fpga_t *fpga) +{ + fpga_info_t *fpga_info = &p_adapter_info->fpga_info; + const int adapter_no = p_adapter_info->adapter_no; + const int nb_ports = fpga_info->n_phy_ports; + int res = 0; + + NT_LOG(DBG, ETHDEV, "%s: Initializing ports\n", + p_adapter_info->mp_adapter_id_str); + + /* + * Initialize global variables + */ + assert(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX); + + if (res == 0 && !p_adapter_info->nt4ga_link.variables_initialized) { + nthw_mac_pcs_t *mac_pcs = + p_adapter_info->nt4ga_link.u.var100g.mac_pcs100g; + nim_i2c_ctx_t *nim_ctx = + p_adapter_info->nt4ga_link.u.var100g.nim_ctx; + nthw_gpio_phy_t *gpio_phy = + p_adapter_info->nt4ga_link.u.var100g.gpio_phy; + int i; + + for (i = 0; i < nb_ports; i++) { + const uint8_t instance = + (uint8_t)(2U + i); /* 2 + adapter port number */ + res = nthw_mac_pcs_init(&mac_pcs[i], fpga, + i /* int nInstance */); + if (res != 0) + break; + res = nthw_iic_init(&nim_ctx[i].hwiic, fpga, instance, + 8 /* timing */); + if (res != 0) + break; + nim_ctx[i].instance = instance; + nim_ctx[i].devaddr = 0x50; /* 0xA0 / 2 */ + nim_ctx[i].regaddr = 0U; + res = nthw_gpio_phy_init(&gpio_phy[i], fpga, + 0 /* Only one instance */); + if (res != 0) + break; + } + if (res == 0) + p_adapter_info->nt4ga_link.variables_initialized = true; + } + + /* Create state-machine thread */ + if (res == 0) { + if (!monitor_task_is_running[adapter_no]) { + res = pthread_create(&monitor_tasks[adapter_no], NULL, + nt4ga_link_100g_mon, p_adapter_info); + } + } + return res; +} diff --git a/drivers/net/ntnic/adapter/nt4ga_link_100g.h b/drivers/net/ntnic/adapter/nt4ga_link_100g.h new file mode 100644 index 0000000000..803b3454b7 --- /dev/null +++ b/drivers/net/ntnic/adapter/nt4ga_link_100g.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NT4GA_LINK_100G_H_ +#define NT4GA_LINK_100G_H_ + +#include "nthw_drv.h" + +int nt4ga_link_100g_ports_init(adapter_info_t *p_adapter_info, nt_fpga_t *p_fpga); + +#endif /* NT4GA_LINK_100G_H_ */ diff --git a/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c b/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c new file mode 100644 index 0000000000..07884e9219 --- /dev/null +++ b/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c @@ -0,0 +1,598 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" +#include "nt_util.h" +#include "nthw_drv.h" +#include "nt4ga_adapter.h" +#include "nt4ga_pci_ta_tg.h" +#include "nthw_pci_ta.h" +#include "nthw_pci_rd_tg.h" +#include "nthw_pci_wr_tg.h" + +int nt4ga_pci_ta_tg_init(struct adapter_info_s *p_adapter_info) +{ + const char *const p_adapter_id_str = p_adapter_info->mp_adapter_id_str; + fpga_info_t *fpga_info = &p_adapter_info->fpga_info; + nt_fpga_t *p_fpga = fpga_info->mp_fpga; + nt4ga_pci_ta_tg_t *p = &p_adapter_info->nt4ga_pci_ta_tg; + int res; + int n_err_cnt = 0; + + if (p) { + memset(p, 0, sizeof(nt4ga_pci_ta_tg_t)); + } else { + NT_LOG(ERR, NTHW, "%s: %s: null ptr\n", p_adapter_id_str, __func__); + return -1; + } + + assert(p_fpga); + + p->mp_nthw_pci_rd_tg = nthw_pci_rd_tg_new(); + assert(p->mp_nthw_pci_rd_tg); + res = nthw_pci_rd_tg_init(p->mp_nthw_pci_rd_tg, p_fpga, 0); + if (res) { + n_err_cnt++; + NT_LOG(WRN, NTHW, "%s: module PCI_RD_TG not found\n", + p_adapter_id_str); + } + + p->mp_nthw_pci_wr_tg = nthw_pci_wr_tg_new(); + assert(p->mp_nthw_pci_wr_tg); + res = nthw_pci_wr_tg_init(p->mp_nthw_pci_wr_tg, p_fpga, 0); + if (res) { + n_err_cnt++; + NT_LOG(WRN, NTHW, "%s: module PCI_WR_TG not found\n", + p_adapter_id_str); + } + + p->mp_nthw_pci_ta = nthw_pci_ta_new(); + assert(p->mp_nthw_pci_ta); + res = nthw_pci_ta_init(p->mp_nthw_pci_ta, p_fpga, 0); + if (res) { + n_err_cnt++; + NT_LOG(WRN, NTHW, "%s: module PCI_TA not found\n", + p_adapter_id_str); + } + + return n_err_cnt; +} + +static int nt4ga_pci_ta_tg_ta_write_control_enable(nt4ga_pci_ta_tg_t *p, + uint32_t enable) +{ + nthw_pci_ta_set_control_enable(p->mp_nthw_pci_ta, enable); + return 0; +} + +static int nt4ga_pci_ta_tg_ta_read_length_error(nt4ga_pci_ta_tg_t *p, uint32_t *p_data) +{ + nthw_pci_ta_get_length_error(p->mp_nthw_pci_ta, p_data); + return 0; +} + +static int nt4ga_pci_ta_tg_ta_read_packet_bad(nt4ga_pci_ta_tg_t *p, uint32_t *p_data) +{ + nthw_pci_ta_get_packet_bad(p->mp_nthw_pci_ta, p_data); + return 0; +} + +static int nt4ga_pci_ta_tg_ta_read_packet_good(nt4ga_pci_ta_tg_t *p, uint32_t *p_data) +{ + nthw_pci_ta_get_packet_good(p->mp_nthw_pci_ta, p_data); + return 0; +} + +static int nt4ga_pci_ta_tg_ta_read_payload_error(nt4ga_pci_ta_tg_t *p, + uint32_t *p_data) +{ + nthw_pci_ta_get_payload_error(p->mp_nthw_pci_ta, p_data); + return 0; +} + +static int nt4ga_pci_ta_tg_rd_tg_setup(nt4ga_pci_ta_tg_t *p, uint64_t iova, + int slot_addr, uint32_t req_size, bool wait, + bool wrap) +{ + const uint64_t n_phys_addr = (iova + (unsigned long)(slot_addr * req_size)); + + nthw_pci_rd_tg_set_ram_addr(p->mp_nthw_pci_rd_tg, slot_addr); + nthw_pci_rd_tg_set_phys_addr(p->mp_nthw_pci_rd_tg, n_phys_addr); + nthw_pci_rd_tg_set_ram_data(p->mp_nthw_pci_rd_tg, req_size, wait, wrap); + return 0; +} + +static int nt4ga_pci_ta_tg_rd_tg_run(nt4ga_pci_ta_tg_t *p, uint32_t num_iterations) +{ + nthw_pci_rd_tg_set_run(p->mp_nthw_pci_rd_tg, num_iterations); + return 0; +} + +static int nt4ga_pci_ta_tg_rd_tg_wait_ready(nt4ga_pci_ta_tg_t *p) +{ + int poll = 0; + uint32_t data = 0; + + while (data == 0) { + /* NOTE: Deliberately start with a sleep - ensures that the FPGA pipe is empty */ + NT_OS_WAIT_USEC(1000); + data = nthw_pci_rd_tg_get_ctrl_rdy(p->mp_nthw_pci_rd_tg); + poll++; + if (poll >= 1000) { + NT_LOG(ERR, NTHW, + "%s: FAILED waiting PCI RD TG ready: poll=%d\n", + __func__, poll); + return -1; + } + } + + return 0; +} + +static int nt4ga_pci_ta_tg_wr_tg_setup(nt4ga_pci_ta_tg_t *p, uint64_t iova, + int slot_addr, uint32_t req_size, bool wait, + bool wrap, bool inc) +{ + const uint64_t n_phys_addr = (iova + (unsigned long)(slot_addr * req_size)); + + nthw_pci_wr_tg_set_ram_addr(p->mp_nthw_pci_wr_tg, slot_addr); + nthw_pci_wr_tg_set_phys_addr(p->mp_nthw_pci_wr_tg, n_phys_addr); + nthw_pci_wr_tg_set_ram_data(p->mp_nthw_pci_wr_tg, req_size, wait, wrap, inc); + + return 0; +} + +static int nt4ga_pci_ta_tg_wr_tg_run(nt4ga_pci_ta_tg_t *p, uint32_t num_iterations) +{ + nthw_pci_wr_tg_set_run(p->mp_nthw_pci_wr_tg, num_iterations); + return 0; +} + +static int nt4ga_pci_ta_tg_wr_tg_wait_ready(nt4ga_pci_ta_tg_t *p) +{ + int poll = 0; + uint32_t data = 0; + + while (data == 0) { + /* NOTE: Deliberately start with a sleep - ensures that the FPGA pipe is empty */ + NT_OS_WAIT_USEC(1000); + data = nthw_pci_wr_tg_get_ctrl_rdy(p->mp_nthw_pci_wr_tg); + poll++; + if (poll >= 1000) { + NT_LOG(ERR, NTHW, + "%s: FAILED waiting PCI WR TG ready: poll=%d\n", + __func__, poll); + return -1; + } + } + + return 0; +} + +int nt4ga_pci_ta_tg_measure_throughput_run(struct adapter_info_s *p_adapter_info, + struct nthw_hif_end_point_counters *pri, + struct nthw_hif_end_point_counters *sla) +{ + nt4ga_pci_ta_tg_t *p = &p_adapter_info->nt4ga_pci_ta_tg; + + const int delay = pri->n_tg_delay; + const int pkt_size = pri->n_tg_pkt_size; + const int num_pkts = pri->n_tg_num_pkts; + const int n_direction = pri->n_tg_direction; + const uint8_t n_numa_node = (uint8_t)pri->n_numa_node; + const int dma_buf_size = (4 * 1024 * 1024); + + const size_t align_size = ALIGN_SIZE(dma_buf_size); + uint32_t *mem_addr; + uint64_t iova; + + int bo_error = 0; + + nthw_hif *p_master_instance = p_adapter_info->fpga_info.mp_nthw_hif; + nthw_hif *p_slave_instance = NULL; + + nthw_pcie3 *p_pci_master = p_adapter_info->fpga_info.mp_nthw_pcie3; + nthw_pcie3 *p_pci_slave = NULL; + + assert(p_master_instance || p_pci_master); + + struct nt_dma_s *p_dma; + /* FPGA needs a Page alignment (4K on Intel) */ + p_dma = nt_dma_alloc(align_size, 0x1000, n_numa_node); + if (p_dma == NULL) { + NT_LOG(DBG, ETHDEV, "%s: vfio_dma_alloc failed\n", __func__); + return 0; + } + mem_addr = (uint32_t *)p_dma->addr; + iova = p_dma->iova; + + NT_LOG(DBG, NTHW, + "%s: Running HIF bandwidth measurements on NUMA node %d\n", + __func__, n_numa_node); + + bo_error = 0; + { + int wrap; + + /* Stop any existing running test */ + bo_error |= nt4ga_pci_ta_tg_rd_tg_run(p, 0); + bo_error |= nt4ga_pci_ta_tg_rd_tg_wait_ready(p); + + bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 0); + bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p); + + bo_error |= nt4ga_pci_ta_tg_ta_write_control_enable(p, 0); + + /* Prepare the HIF Traffic generator */ + bo_error |= nt4ga_pci_ta_tg_ta_write_control_enable(p, 1); + bo_error |= nt4ga_pci_ta_tg_rd_tg_wait_ready(p); + bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p); + + /* + * Ensure that the hostbuffer memory contain data that can be read - + * For this we will ask the FPGA to write data to it. The last wrap packet + * does not generate any data it only wraps (unlike the PCIe2 TG) + */ + { + int pkt; + + for (pkt = 0; pkt < num_pkts; pkt++) { + if (pkt >= (num_pkts - 1)) + wrap = 1; + + else + wrap = 0; + bo_error |= nt4ga_pci_ta_tg_wr_tg_setup(p, iova, + pkt, pkt_size, + 0, wrap, 1); + bo_error |= nt4ga_pci_ta_tg_rd_tg_setup(p, iova, + pkt, pkt_size, + 0, wrap); + } + } + + bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 1); + bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p); + + /* Start WR TG Write once */ + bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 1); + /* Wait until WR TG ready */ + bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p); + + /* Verify that we have a packet */ + { + int pkt; + + for (pkt = 0; pkt < num_pkts; pkt++) { + uint32_t value = 0; + int poll; + + for (poll = 8; poll < pkt_size; + poll += 4, value++) { + if (*(uint32_t *)((uint8_t *)mem_addr + + (pkt * pkt_size) + + poll) != value) { + NT_LOG(ERR, NTHW, + "HIF TG: Prepare failed. Data write failed: #%d.%d: %016X:%08X\n", + pkt, poll, + *(uint32_t *)((uint8_t *) + mem_addr + + (pkt * + pkt_size) + + poll), + value); + + /* + * Break out of the verification loop on first + * Compare error + */ + bo_error |= 1; + break; + } + } + } + } + + switch (n_direction) { + case 1: /* Read only test */ + nt4ga_pci_ta_tg_wr_tg_run(p, 0xffff); + break; + case 2: /* Write only test */ + nt4ga_pci_ta_tg_rd_tg_run(p, 0xffff); + break; + case 3: /* Combined read/write test */ + nt4ga_pci_ta_tg_wr_tg_run(p, 0xffff); + nt4ga_pci_ta_tg_rd_tg_run(p, 0xffff); + break; + default: /* stop tests */ + nt4ga_pci_ta_tg_wr_tg_run(p, 0); + nt4ga_pci_ta_tg_rd_tg_run(p, 0); + break; + } + + do { + /* prep */ + if (p_pci_master) { + nthw_pcie3_end_point_counters_sample_pre(p_pci_master, + pri); + } + if (p_pci_slave) { + nthw_pcie3_end_point_counters_sample_pre(p_pci_slave, + sla); + } + + /* start measure */ + if (p_master_instance) + nthw_hif_stat_req_enable(p_master_instance); + if (p_pci_master) + nthw_pcie3_stat_req_enable(p_pci_master); + + if (p_slave_instance) + nthw_hif_stat_req_enable(p_slave_instance); + if (p_pci_slave) + nthw_pcie3_stat_req_enable(p_pci_slave); + + /* Wait */ + NT_OS_WAIT_USEC(delay); + + /* Stop measure */ + if (p_master_instance) + nthw_hif_stat_req_disable(p_master_instance); + if (p_pci_master) + nthw_pcie3_stat_req_disable(p_pci_master); + + if (p_slave_instance) + nthw_hif_stat_req_disable(p_slave_instance); + if (p_pci_slave) + nthw_pcie3_stat_req_disable(p_pci_slave); + + /* Post process master */ + if (p_master_instance) { + nthw_hif_end_point_counters_sample(p_master_instance, + pri); + } + + if (p_pci_master) { + nthw_pcie3_end_point_counters_sample_post(p_pci_master, + pri); + } + + /* Post process slave */ + if (p_slave_instance) { + nthw_hif_end_point_counters_sample(p_slave_instance, + sla); + } + + if (p_pci_slave) { + nthw_pcie3_end_point_counters_sample_post(p_pci_slave, + sla); + } + + { + /* Check for TA transmit errors */ + uint32_t dw_good_pkts, dw_bad_pkts, dw_bad_length, + dw_bad_payload; + nt4ga_pci_ta_tg_ta_read_packet_good(p, + &dw_good_pkts); + nt4ga_pci_ta_tg_ta_read_packet_bad(p, &dw_bad_pkts); + nt4ga_pci_ta_tg_ta_read_length_error(p, + &dw_bad_length); + nt4ga_pci_ta_tg_ta_read_payload_error(p, &dw_bad_payload); + + NT_LOG(DBG, NTHW, + "%s: NUMA node %u: HIF: TA: Good pkts, Bad pkts, Bad length, Bad payload\n", + __func__, n_numa_node); + NT_LOG(DBG, NTHW, + "%s: NUMA node %u: HIF: TA: 0x%08x 0x%08x 0x%08x 0x%08x\n", + __func__, n_numa_node, dw_good_pkts, + dw_bad_pkts, dw_bad_length, dw_bad_payload); + + if (dw_bad_pkts | dw_bad_length | dw_bad_payload) { + bo_error |= 1; + NT_LOG(ERR, NTHW, + "%s: NUMA node %u: HIF: TA: error detected\n", + __func__, n_numa_node); + NT_LOG(ERR, NTHW, + "%s: NUMA node %u: HIF: TA: Good packets received: %u\n", + __func__, n_numa_node, dw_good_pkts); + NT_LOG(ERR, NTHW, + "%s: NUMA node %u: HIF: TA: Bad packets received : %u\n", + __func__, n_numa_node, dw_bad_pkts); + NT_LOG(ERR, NTHW, + "%s: NUMA node %u: HIF: TA: Bad length received : %u\n", + __func__, n_numa_node, + dw_bad_length); + NT_LOG(ERR, NTHW, + "%s: NUMA node %u: HIF: TA: Bad payload received : %u\n", + __func__, n_numa_node, + dw_bad_payload); + } + } + + if (bo_error != 0) + break; + + break; /* for now only loop once */ + + /* + * Only do "signalstop" looping if a specific numa node and direction is to + * be tested. + */ + } while ((bo_error == 0) && (n_numa_node != UINT8_MAX) && + (n_direction != -1)); + + /* Stop the test */ + bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 0); + bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p); + + bo_error |= nt4ga_pci_ta_tg_rd_tg_run(p, 0); + bo_error |= nt4ga_pci_ta_tg_rd_tg_wait_ready(p); + + bo_error |= nt4ga_pci_ta_tg_ta_write_control_enable(p, 0); + + /* PCIe3 sanity checks */ + { +#if defined(DEBUG) + int do_loop = 1; +#else + int do_loop = 0; +#endif + + while (do_loop) { + do_loop = 0; + + if (p_master_instance) { + nthw_hif_stat_req_enable(p_master_instance); + NT_OS_WAIT_USEC(100); + nthw_hif_stat_req_disable(p_master_instance); + } + + if (do_loop == 0) + break; + + NT_LOG(DBG, NTHW, + "%s: WARNING this is wrong - wait again\n", + __func__); + NT_OS_WAIT_USEC(200 * 1000); + } + } + } + + /* Stop the test */ + + bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 0); + bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p); + + bo_error |= nt4ga_pci_ta_tg_rd_tg_run(p, 0); + bo_error |= nt4ga_pci_ta_tg_rd_tg_wait_ready(p); + + bo_error |= nt4ga_pci_ta_tg_ta_write_control_enable(p, 0); + + nt_dma_free(p_dma); + + return bo_error; +} + +int nt4ga_pci_ta_tg_measure_throughput_main(struct adapter_info_s *p_adapter_info, + const uint8_t numa_node, + const int direction, const int n_pkt_size, + const int n_batch_count, const int n_delay) +{ + /* All numa nodes is indicated by UINT8_MAX */ + const uint8_t numa_begin = (numa_node == UINT8_MAX ? 0 : numa_node); + const uint8_t numa_end = numa_begin; + + /* sanity check direction param */ + const int dir_begin = (direction <= 0 ? 1 : direction); + const int dir_end = (direction <= 0 ? 3 : direction); + + int bo_error = 0; + struct nthw_hif_end_points eps; + + if (n_delay == 0) + return -1; + + NT_LOG(DBG, NTHW, "HIF adapter throughput:\n"); + + /* Only do "signalstop"-looping if a specific numa node is to be tested. */ + { + uint8_t numa; + + for (numa = numa_begin; numa <= numa_end; numa++) { + { + int by_loop; + + for (by_loop = dir_begin; by_loop <= dir_end; + by_loop++) { + struct nthw_hif_end_point_counters *pri = + &eps.pri; + struct nthw_hif_end_point_counters *sla = + &eps.sla; + + pri->n_numa_node = numa; + pri->n_tg_direction = by_loop; + pri->n_tg_pkt_size = (n_pkt_size > 0 ? + n_pkt_size : + TG_PKT_SIZE); + pri->n_tg_num_pkts = + (n_batch_count > 0 ? + n_batch_count : + TG_NUM_PACKETS); + pri->n_tg_delay = (n_delay > 0 ? n_delay : + TG_DELAY); + pri->cur_rx = 0; + pri->cur_tx = 0; + pri->n_ref_clk_cnt = -1; + pri->bo_error = 0; + + sla->n_numa_node = numa; + sla->n_tg_direction = by_loop; + sla->n_tg_pkt_size = (n_pkt_size > 0 ? + n_pkt_size : + TG_PKT_SIZE); + sla->n_tg_num_pkts = + (n_batch_count > 0 ? + n_batch_count : + TG_NUM_PACKETS); + sla->n_tg_delay = (n_delay > 0 ? n_delay : + TG_DELAY); + sla->cur_rx = 0; + sla->cur_tx = 0; + pri->n_ref_clk_cnt = -1; + sla->bo_error = 0; + + bo_error += + nt4ga_pci_ta_tg_measure_throughput_run(p_adapter_info, + pri, sla); +#if defined(DEBUG) && (1) + { + NT_LOG(DBG, NTHW, + "%s: @ %d: %d %d %d %d: %016lX %016lX : %6ld Mbps %6ld Mbps\n", + __func__, pri->n_numa_node, + pri->n_tg_direction, + pri->n_tg_num_pkts, + pri->n_tg_pkt_size, + pri->n_tg_delay, + pri->cur_rx, pri->cur_tx, + (pri->cur_rx * 8UL / + 1000000UL), + (pri->cur_tx * 8UL / + 1000000UL)); + } + { + NT_LOG(DBG, NTHW, + "%s: @ %d: %d %d %d %d: %016lX %016lX : %6ld Mbps %6ld Mbps\n", + __func__, sla->n_numa_node, + sla->n_tg_direction, + sla->n_tg_num_pkts, + sla->n_tg_pkt_size, + sla->n_tg_delay, + sla->cur_rx, sla->cur_tx, + (sla->cur_rx * 8UL / + 1000000UL), + (sla->cur_tx * 8UL / + 1000000UL)); + } +#endif + + if (pri->bo_error != 0 || sla->bo_error != 0) + bo_error++; + if (bo_error) + break; + } + } + } + } + + if (bo_error != 0) { + NT_LOG(ERR, NTHW, "%s: error during bandwidth measurement\n", + __func__); + } + + NT_LOG(DBG, NTHW, "HIF adapter throughput: done\n"); + + NT_LOG(DBG, NTHW, "%s: [%s:%u] done\n", __func__, __FILE__, __LINE__); + + return 0; +} diff --git a/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h b/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h new file mode 100644 index 0000000000..8b46491f77 --- /dev/null +++ b/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NT4GA_PCI_TA_TG_H_ +#define _NT4GA_PCI_TA_TG_H_ + +#include + +#define TA_TG_DBG_SHOW_SUMMARY (1) + +#define TG_NUM_PACKETS (8) +#define TG_PKT_SIZE (2048 * 1) +#define TG_AREA_SIZE (TG_NUM_PACKETS * TG_PKT_SIZE) + +#define TG_DELAY (200000) /* usec */ + +/* Struct predefinitions */ +struct adapter_info_s; +struct nthw_hif_end_point_counters; + +struct nt4ga_pci_ta_tg_s { + struct nthw_pci_rd_tg *mp_nthw_pci_rd_tg; + struct nthw_pci_wr_tg *mp_nthw_pci_wr_tg; + struct nthw_pci_ta *mp_nthw_pci_ta; +}; + +typedef struct nt4ga_pci_ta_tg_s nt4ga_pci_ta_tg_t; +typedef struct nt4ga_pci_ta_tg_s nt4ga_pci_ta_tg; + +int nt4ga_pci_ta_tg_init(struct adapter_info_s *p_adapter_info); + +int nt4ga_pci_ta_tg_measure_throughput_run(struct adapter_info_s *p_adapter_info, + struct nthw_hif_end_point_counters *pri, + struct nthw_hif_end_point_counters *sla); +int nt4ga_pci_ta_tg_measure_throughput_main(struct adapter_info_s *p_adapter_info, + const uint8_t numa_node, + const int direction, const int n_pkt_size, + const int n_batch_count, const int n_delay); + +#endif /* _NT4GA_PCI_TA_TG_H_ */ diff --git a/drivers/net/ntnic/adapter/nt4ga_stat.c b/drivers/net/ntnic/adapter/nt4ga_stat.c new file mode 100644 index 0000000000..b61c73ea12 --- /dev/null +++ b/drivers/net/ntnic/adapter/nt4ga_stat.c @@ -0,0 +1,705 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" +#include "nt_util.h" +#include "nthw_drv.h" +#include "nthw_fpga.h" +#include "nt4ga_adapter.h" + +#define NO_FLAGS 0 + +/* Inline timestamp format s pcap 32:32 bits. Convert to nsecs */ +static inline uint64_t timestamp2ns(uint64_t ts) +{ + return ((ts >> 32) * 1000000000) + (ts & 0xffffffff); +} + +static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat, + uint32_t *p_stat_dma_virtual); +static int nt4ga_stat_collect_virt_v1_stats(nt4ga_stat_t *p_nt4ga_stat, + uint32_t *p_stat_dma_virtual); + +int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info _unused, + nt4ga_stat_t *p_nt4ga_stat) +{ + nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat; + + if (p_nthw_stat->mb_is_vswitch) { + /* + * Set all bits in the DMA block timestamp since 9530-42-05 and other Vswitch FPGA + * images may only clear all bits in this memory location. TBV + * Consequently, last_timestamp must be constructed via a system call. + */ + *p_nthw_stat->mp_timestamp = 0xFFFFFFFF; + p_nt4ga_stat->last_timestamp = NT_OS_GET_TIME_NS(); + nt4ga_stat_collect_virt_v1_stats(p_nt4ga_stat, + p_nt4ga_stat->p_stat_dma_virtual); + } else { + p_nt4ga_stat->last_timestamp = + timestamp2ns(*p_nthw_stat->mp_timestamp); + nt4ga_stat_collect_cap_v1_stats(p_nt4ga_stat, + p_nt4ga_stat->p_stat_dma_virtual); + } + return 0; +} + +int nt4ga_stat_init(struct adapter_info_s *p_adapter_info) +{ + const char *const p_adapter_id_str = p_adapter_info->mp_adapter_id_str; + fpga_info_t *fpga_info = &p_adapter_info->fpga_info; + nt_fpga_t *p_fpga = fpga_info->mp_fpga; + nt4ga_stat_t *p_nt4ga_stat = &p_adapter_info->nt4ga_stat; + + if (p_nt4ga_stat) { + memset(p_nt4ga_stat, 0, sizeof(nt4ga_stat_t)); + } else { + NT_LOG(ERR, ETHDEV, "%s: ERROR (%s:%d)", p_adapter_id_str, + __func__, __LINE__); + return -1; + } + + { + nthw_stat_t *p_nthw_stat = nthw_stat_new(); + nthw_rmc_t *p_nthw_rmc = nthw_rmc_new(); + + if (!p_nthw_stat) { + NT_LOG(ERR, ETHDEV, "%s: ERROR (%s:%d)", p_adapter_id_str, + __func__, __LINE__); + return -1; + } + + if (!p_nthw_rmc) { + nthw_stat_delete(p_nthw_stat); + + NT_LOG(ERR, ETHDEV, "%s: ERROR (%s:%d)", p_adapter_id_str, + __func__, __LINE__); + return -1; + } + + p_nt4ga_stat->mp_nthw_stat = p_nthw_stat; + nthw_stat_init(p_nthw_stat, p_fpga, 0); + + p_nt4ga_stat->mp_nthw_rmc = p_nthw_rmc; + nthw_rmc_init(p_nthw_rmc, p_fpga, 0); + + p_nt4ga_stat->mn_rx_host_buffers = p_nthw_stat->m_nb_rx_host_buffers; + p_nt4ga_stat->mn_tx_host_buffers = p_nthw_stat->m_nb_tx_host_buffers; + + p_nt4ga_stat->mn_rx_ports = p_nthw_stat->m_nb_rx_ports; + p_nt4ga_stat->mn_tx_ports = p_nthw_stat->m_nb_tx_ports; + } + + return 0; +} + +int nt4ga_stat_setup(struct adapter_info_s *p_adapter_info) +{ + const int n_physical_adapter_no _unused = p_adapter_info->adapter_no; + nt4ga_stat_t *p_nt4ga_stat = &p_adapter_info->nt4ga_stat; + nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat; + nthw_rmc_t *p_nthw_rmc = p_nt4ga_stat->mp_nthw_rmc; + + if (p_nthw_rmc) + nthw_rmc_block(p_nthw_rmc); + + /* Allocate and map memory for fpga statistics */ + { + uint32_t n_stat_size = + (uint32_t)(p_nthw_stat->m_nb_counters * sizeof(uint32_t) + + sizeof(p_nthw_stat->mp_timestamp)); + struct nt_dma_s *p_dma; + int numa_node = p_adapter_info->fpga_info.numa_node; + + /* FPGA needs a 16K alignment on Statistics */ + p_dma = nt_dma_alloc(n_stat_size, 0x4000, numa_node); + + if (!p_dma) { + NT_LOG(ERR, ETHDEV, "%s: pDma alloc failed\n", + __func__); + return -1; + } + + NT_LOG(DBG, ETHDEV, "%s: %x @%d %p %" PRIX64 " %" PRIX64 "\n", __func__, + n_stat_size, numa_node, p_dma->addr, p_dma->iova); + + NT_LOG(DBG, ETHDEV, + "DMA: Physical adapter %02ld, PA = 0x%016" PRIX64 + " DMA = 0x%016" PRIX64 " size = 0x%" PRIX64 "\n", + n_physical_adapter_no, p_dma->iova, p_dma->addr, n_stat_size); + + p_nt4ga_stat->p_stat_dma_virtual = (uint32_t *)p_dma->addr; + p_nt4ga_stat->n_stat_size = n_stat_size; + p_nt4ga_stat->p_stat_dma = p_dma; + + memset(p_nt4ga_stat->p_stat_dma_virtual, 0xaa, n_stat_size); + nthw_stat_set_dma_address(p_nthw_stat, p_dma->iova, + p_nt4ga_stat->p_stat_dma_virtual); + } + + if (p_nthw_rmc) + nthw_rmc_unblock(p_nthw_rmc, false); + + p_nt4ga_stat->mp_stat_structs_color = calloc(p_nthw_stat->m_nb_color_counters, + sizeof(struct color_counters)); + if (!p_nt4ga_stat->mp_stat_structs_color) { + NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n", __func__, + __LINE__); + return -1; + } + + p_nt4ga_stat->mp_stat_structs_hb = + calloc(p_nt4ga_stat->mn_rx_host_buffers + p_nt4ga_stat->mn_tx_host_buffers, + sizeof(struct host_buffer_counters)); + if (!p_nt4ga_stat->mp_stat_structs_hb) { + NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n", __func__, + __LINE__); + return -1; + } + + /* + * Separate memory allocation for VSWITCH and Inline to appropriate port counter structures. + */ + if (p_nthw_stat->mb_is_vswitch) { + p_nt4ga_stat->virt.mp_stat_structs_port_rx = + calloc(p_nthw_stat->m_nb_rx_host_buffers, + sizeof(struct port_counters_vswitch_v1)); + if (!p_nt4ga_stat->virt.mp_stat_structs_port_rx) { + NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n", + __func__, __LINE__); + return -1; + } + p_nt4ga_stat->virt.mp_stat_structs_port_tx = + calloc(p_nthw_stat->m_nb_tx_host_buffers, + sizeof(struct port_counters_vswitch_v1)); + if (!p_nt4ga_stat->virt.mp_stat_structs_port_tx) { + NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n", + __func__, __LINE__); + return -1; + } + p_nt4ga_stat->flm_stat_ver = 0; + p_nt4ga_stat->mp_stat_structs_flm = NULL; + } else { /* Inline */ + p_nt4ga_stat->cap.mp_stat_structs_port_rx = + calloc(NUM_ADAPTER_PORTS_MAX, + sizeof(struct port_counters_v2)); + if (!p_nt4ga_stat->cap.mp_stat_structs_port_rx) { + NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n", + __func__, __LINE__); + return -1; + } + p_nt4ga_stat->cap.mp_stat_structs_port_tx = + calloc(NUM_ADAPTER_PORTS_MAX, + sizeof(struct port_counters_v2)); + if (!p_nt4ga_stat->cap.mp_stat_structs_port_tx) { + NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n", + __func__, __LINE__); + return -1; + } + + p_nt4ga_stat->flm_stat_ver = 0; + + p_nt4ga_stat->mp_stat_structs_flm = + calloc(1, sizeof(struct flm_counters_v1)); + if (!p_nt4ga_stat->mp_stat_structs_flm) { + NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n", + __func__, __LINE__); + return -1; + } + } + + memset(p_nt4ga_stat->a_stat_structs_color_base, 0, + sizeof(struct color_counters) * NT_MAX_COLOR_FLOW_STATS); + p_nt4ga_stat->last_timestamp = 0; + + nthw_stat_trigger(p_nthw_stat); + + return 0; +} + +int nt4ga_stat_stop(struct adapter_info_s *p_adapter_info) +{ + nt4ga_stat_t *p_nt4ga_stat = &p_adapter_info->nt4ga_stat; + + if (p_nt4ga_stat->virt.mp_stat_structs_port_rx) { + free(p_nt4ga_stat->virt.mp_stat_structs_port_rx); + p_nt4ga_stat->virt.mp_stat_structs_port_rx = NULL; + } + if (p_nt4ga_stat->cap.mp_stat_structs_port_rx) { + free(p_nt4ga_stat->cap.mp_stat_structs_port_rx); + p_nt4ga_stat->cap.mp_stat_structs_port_rx = NULL; + } + + if (p_nt4ga_stat->virt.mp_stat_structs_port_tx) { + free(p_nt4ga_stat->virt.mp_stat_structs_port_tx); + p_nt4ga_stat->virt.mp_stat_structs_port_tx = NULL; + } + if (p_nt4ga_stat->cap.mp_stat_structs_port_tx) { + free(p_nt4ga_stat->cap.mp_stat_structs_port_tx); + p_nt4ga_stat->cap.mp_stat_structs_port_tx = NULL; + } + + if (p_nt4ga_stat->mp_stat_structs_color) { + free(p_nt4ga_stat->mp_stat_structs_color); + p_nt4ga_stat->mp_stat_structs_color = NULL; + } + + if (p_nt4ga_stat->mp_stat_structs_hb) { + free(p_nt4ga_stat->mp_stat_structs_hb); + p_nt4ga_stat->mp_stat_structs_hb = NULL; + } + + if (p_nt4ga_stat->mp_stat_structs_flm) { + free(p_nt4ga_stat->mp_stat_structs_flm); + p_nt4ga_stat->mp_stat_structs_flm = NULL; + } + + if (p_nt4ga_stat->p_stat_dma) { + nt_dma_free(p_nt4ga_stat->p_stat_dma); + p_nt4ga_stat->p_stat_dma = NULL; + } + + return 0; +} + +int nt4ga_stat_dump(struct adapter_info_s *p_adapter_info, FILE *pfh) +{ + const char *const p_adapter_id_str = p_adapter_info->mp_adapter_id_str; + fpga_info_t *fpga_info = &p_adapter_info->fpga_info; + nt4ga_stat_t *p_nt4ga_stat = &p_adapter_info->nt4ga_stat; + int i; + + for (i = 0; i < fpga_info->n_phy_ports; i++) { + fprintf(pfh, + "%s: Intf %02d: Rx: %016" PRIX64 " %016" PRIX64 + " %016" PRIX64 " Tx: %016" PRIX64 " %016" PRIX64 + " %016" PRIX64 "\n", + p_adapter_id_str, i, p_nt4ga_stat->a_port_rx_packets_total[i], + p_nt4ga_stat->a_port_rx_octets_total[i], + p_nt4ga_stat->a_port_rx_drops_total[i], + p_nt4ga_stat->a_port_tx_packets_total[i], + p_nt4ga_stat->a_port_tx_octets_total[i], + p_nt4ga_stat->a_port_tx_drops_total[i]); + } + + return 0; +} + +/* Called with stat mutex locked */ +static int nt4ga_stat_collect_virt_v1_stats(nt4ga_stat_t *p_nt4ga_stat, + uint32_t *p_stat_dma_virtual) +{ + nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat; + const int n_rx_ports = p_nt4ga_stat->mn_rx_ports; + const int n_tx_ports = p_nt4ga_stat->mn_tx_ports; + int c, h, p; + + if (!p_nthw_stat || !p_nt4ga_stat) + return -1; + + if (p_nthw_stat->mn_stat_layout_version != 6) { + NT_LOG(ERR, ETHDEV, "HW STA module version not supported"); + return -1; + } + + /* RX ports */ + for (c = 0; c < p_nthw_stat->m_nb_color_counters / 2; c++) { + const unsigned int tcp_flags_bits = 6U; + const uint32_t val_mask_dma = 0xffffffffULL >> tcp_flags_bits; + + p_nt4ga_stat->mp_stat_structs_color[c].color_packets += + p_stat_dma_virtual[c * 2] & val_mask_dma; + p_nt4ga_stat->mp_stat_structs_color[c].tcp_flags |= + (uint8_t)(p_stat_dma_virtual[c * 2] >> + (32 - tcp_flags_bits)); + p_nt4ga_stat->mp_stat_structs_color[c].color_bytes += + p_stat_dma_virtual[c * 2 + 1]; + } + + /* Move to Host buffer counters */ + p_stat_dma_virtual += p_nthw_stat->m_nb_color_counters; + + /* Host buffer counters */ + for (h = 0; h < p_nthw_stat->m_nb_rx_host_buffers; h++) { + p_nt4ga_stat->mp_stat_structs_hb[h].flush_packets += + p_stat_dma_virtual[h * 8]; + p_nt4ga_stat->mp_stat_structs_hb[h].drop_packets += + p_stat_dma_virtual[h * 8 + 1]; + p_nt4ga_stat->mp_stat_structs_hb[h].fwd_packets += + p_stat_dma_virtual[h * 8 + 2]; + p_nt4ga_stat->mp_stat_structs_hb[h].dbs_drop_packets += + p_stat_dma_virtual[h * 8 + 3]; + p_nt4ga_stat->mp_stat_structs_hb[h].flush_bytes += + p_stat_dma_virtual[h * 8 + 4]; + p_nt4ga_stat->mp_stat_structs_hb[h].drop_bytes += + p_stat_dma_virtual[h * 8 + 5]; + p_nt4ga_stat->mp_stat_structs_hb[h].fwd_bytes += + p_stat_dma_virtual[h * 8 + 6]; + p_nt4ga_stat->mp_stat_structs_hb[h].dbs_drop_bytes += + p_stat_dma_virtual[h * 8 + 7]; + } + + /* Move to Rx Port counters */ + p_stat_dma_virtual += p_nthw_stat->m_nb_rx_hb_counters; + + /* RX ports */ + for (p = 0; p < n_rx_ports; p++) { + p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters]; + p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].pkts += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 1]; + p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].drop_events += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 2]; + p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].qos_drop_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 3]; + p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].qos_drop_pkts += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 4]; + + /* Rx totals */ + p_nt4ga_stat->a_port_rx_octets_total[p] += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters]; + p_nt4ga_stat->a_port_rx_packets_total[p] += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 1]; + p_nt4ga_stat->a_port_rx_drops_total[p] += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 2]; + } + + /* Move to Tx Port counters */ + p_stat_dma_virtual += n_rx_ports * p_nthw_stat->m_nb_rx_port_counters; + + /* TX ports */ + for (p = 0; p < n_tx_ports; p++) { + p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters]; + p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].pkts += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 1]; + p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].drop_events += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 2]; + p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].qos_drop_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 3]; + p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].qos_drop_pkts += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 4]; + + /* Tx totals */ + p_nt4ga_stat->a_port_tx_octets_total[p] += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters]; + p_nt4ga_stat->a_port_tx_packets_total[p] += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 1]; + p_nt4ga_stat->a_port_tx_drops_total[p] += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 2]; + } + + return 0; +} + +/* Called with stat mutex locked */ +static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat, + uint32_t *p_stat_dma_virtual) +{ + nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat; + + const int n_rx_ports = p_nt4ga_stat->mn_rx_ports; + const int n_tx_ports = p_nt4ga_stat->mn_tx_ports; + int c, h, p; + + if (!p_nthw_stat || !p_nt4ga_stat) + return -1; + + if (p_nthw_stat->mn_stat_layout_version != 6) { + NT_LOG(ERR, ETHDEV, "HW STA module version not supported"); + return -1; + } + + /* RX ports */ + for (c = 0; c < p_nthw_stat->m_nb_color_counters / 2; c++) { + p_nt4ga_stat->mp_stat_structs_color[c].color_packets += + p_stat_dma_virtual[c * 2]; + p_nt4ga_stat->mp_stat_structs_color[c].color_bytes += + p_stat_dma_virtual[c * 2 + 1]; + } + + /* Move to Host buffer counters */ + p_stat_dma_virtual += p_nthw_stat->m_nb_color_counters; + + for (h = 0; h < p_nthw_stat->m_nb_rx_host_buffers; h++) { + p_nt4ga_stat->mp_stat_structs_hb[h].flush_packets += + p_stat_dma_virtual[h * 8]; + p_nt4ga_stat->mp_stat_structs_hb[h].drop_packets += + p_stat_dma_virtual[h * 8 + 1]; + p_nt4ga_stat->mp_stat_structs_hb[h].fwd_packets += + p_stat_dma_virtual[h * 8 + 2]; + p_nt4ga_stat->mp_stat_structs_hb[h].dbs_drop_packets += + p_stat_dma_virtual[h * 8 + 3]; + p_nt4ga_stat->mp_stat_structs_hb[h].flush_bytes += + p_stat_dma_virtual[h * 8 + 4]; + p_nt4ga_stat->mp_stat_structs_hb[h].drop_bytes += + p_stat_dma_virtual[h * 8 + 5]; + p_nt4ga_stat->mp_stat_structs_hb[h].fwd_bytes += + p_stat_dma_virtual[h * 8 + 6]; + p_nt4ga_stat->mp_stat_structs_hb[h].dbs_drop_bytes += + p_stat_dma_virtual[h * 8 + 7]; + } + + /* Move to Rx Port counters */ + p_stat_dma_virtual += p_nthw_stat->m_nb_rx_hb_counters; + + /* RX ports */ + for (p = 0; p < n_rx_ports; p++) { + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 0]; + + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].broadcast_pkts += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 1]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].multicast_pkts += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 2]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].unicast_pkts += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 3]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_alignment += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 4]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_code_violation += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 5]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_crc += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 6]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].undersize_pkts += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 7]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].oversize_pkts += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 8]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].fragments += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 9]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].jabbers_not_truncated += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 10]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].jabbers_truncated += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 11]; + + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_64_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 12]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_65_to_127_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 13]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_128_to_255_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 14]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_256_to_511_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 15]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_512_to_1023_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 16]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p] + .pkts_1024_to_1518_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 17]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p] + .pkts_1519_to_2047_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 18]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p] + .pkts_2048_to_4095_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 19]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p] + .pkts_4096_to_8191_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 20]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_8192_to_max_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 21]; + + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].mac_drop_events += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 22]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_lr += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 23]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].duplicate += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 24]; + + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_ip_chksum_error += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 25]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_udp_chksum_error += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 26]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_tcp_chksum_error += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 27]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_giant_undersize += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 28]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_baby_giant += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 29]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_not_isl_vlan_mpls += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 30]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_isl += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 31]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_vlan += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 32]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_isl_vlan += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 33]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_mpls += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 34]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_isl_mpls += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 35]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_vlan_mpls += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 36]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_isl_vlan_mpls += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 37]; + + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_no_filter += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 38]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_dedup_drop += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 39]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_filter_drop += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 40]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_overflow += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 41]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_dbs_drop += + p_nthw_stat->m_dbs_present ? + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + + 42] : + 0; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_no_filter += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 43]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_dedup_drop += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 44]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_filter_drop += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 45]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_overflow += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 46]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_dbs_drop += + p_nthw_stat->m_dbs_present ? + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + + 47] : + 0; + + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_first_hit += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 48]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_first_not_hit += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 49]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_mid_hit += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 50]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_mid_not_hit += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 51]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_last_hit += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 52]; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_last_not_hit += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 53]; + + /* Rx totals */ + uint64_t new_drop_events_sum = + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 22] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 38] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 39] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 40] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 41] + + (p_nthw_stat->m_dbs_present ? + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + + 42] : + 0); + + uint64_t new_packets_sum = + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 7] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 8] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 9] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 10] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 11] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 12] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 13] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 14] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 15] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 16] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 17] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 18] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 19] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 20] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 21]; + + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].drop_events += + new_drop_events_sum; + p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts += new_packets_sum; + + p_nt4ga_stat->a_port_rx_octets_total[p] += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 0]; + p_nt4ga_stat->a_port_rx_packets_total[p] += new_packets_sum; + p_nt4ga_stat->a_port_rx_drops_total[p] += new_drop_events_sum; + } + + /* Move to Tx Port counters */ + p_stat_dma_virtual += n_rx_ports * p_nthw_stat->m_nb_rx_port_counters; + + for (p = 0; p < n_tx_ports; p++) { + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 0]; + + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].broadcast_pkts += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 1]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].multicast_pkts += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 2]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].unicast_pkts += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 3]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_alignment += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 4]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_code_violation += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 5]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_crc += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 6]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].undersize_pkts += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 7]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].oversize_pkts += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 8]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].fragments += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 9]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].jabbers_not_truncated += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 10]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].jabbers_truncated += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 11]; + + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_64_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 12]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_65_to_127_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 13]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_128_to_255_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 14]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_256_to_511_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 15]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_512_to_1023_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 16]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p] + .pkts_1024_to_1518_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 17]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p] + .pkts_1519_to_2047_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 18]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p] + .pkts_2048_to_4095_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 19]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p] + .pkts_4096_to_8191_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 20]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_8192_to_max_octets += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 21]; + + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].mac_drop_events += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 22]; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_lr += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 23]; + + /* Tx totals */ + uint64_t new_drop_events_sum = + p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 22]; + + uint64_t new_packets_sum = + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 7] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 8] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 9] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 10] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 11] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 12] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 13] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 14] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 15] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 16] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 17] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 18] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 19] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 20] + + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 21]; + + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].drop_events += + new_drop_events_sum; + p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts += new_packets_sum; + + p_nt4ga_stat->a_port_tx_octets_total[p] += + p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 0]; + p_nt4ga_stat->a_port_tx_packets_total[p] += new_packets_sum; + p_nt4ga_stat->a_port_tx_drops_total[p] += new_drop_events_sum; + } + + return 0; +} diff --git a/drivers/net/ntnic/adapter/nt4ga_stat.h b/drivers/net/ntnic/adapter/nt4ga_stat.h new file mode 100644 index 0000000000..4a1067200c --- /dev/null +++ b/drivers/net/ntnic/adapter/nt4ga_stat.h @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NT4GA_STAT_H_ +#define NT4GA_STAT_H_ + +#include "nt_util.h" +#include "common_adapter_defs.h" + +#define NT_MAX_COLOR_FLOW_STATS 0x400 + +struct color_counters { + uint64_t color_packets; + uint64_t color_bytes; + uint8_t tcp_flags; +}; + +struct host_buffer_counters { + uint64_t flush_packets; + uint64_t drop_packets; + uint64_t fwd_packets; + uint64_t dbs_drop_packets; + uint64_t flush_bytes; + uint64_t drop_bytes; + uint64_t fwd_bytes; + uint64_t dbs_drop_bytes; +}; + +struct port_counters_v2 { + /* Rx/Tx common port counters */ + uint64_t drop_events; + uint64_t pkts; + /* FPGA counters */ + uint64_t octets; + uint64_t broadcast_pkts; + uint64_t multicast_pkts; + uint64_t unicast_pkts; + uint64_t pkts_alignment; + uint64_t pkts_code_violation; + uint64_t pkts_crc; + uint64_t undersize_pkts; + uint64_t oversize_pkts; + uint64_t fragments; + uint64_t jabbers_not_truncated; + uint64_t jabbers_truncated; + uint64_t pkts_64_octets; + uint64_t pkts_65_to_127_octets; + uint64_t pkts_128_to_255_octets; + uint64_t pkts_256_to_511_octets; + uint64_t pkts_512_to_1023_octets; + uint64_t pkts_1024_to_1518_octets; + uint64_t pkts_1519_to_2047_octets; + uint64_t pkts_2048_to_4095_octets; + uint64_t pkts_4096_to_8191_octets; + uint64_t pkts_8192_to_max_octets; + uint64_t mac_drop_events; + uint64_t pkts_lr; + /* Rx only port counters */ + uint64_t duplicate; + uint64_t pkts_ip_chksum_error; + uint64_t pkts_udp_chksum_error; + uint64_t pkts_tcp_chksum_error; + uint64_t pkts_giant_undersize; + uint64_t pkts_baby_giant; + uint64_t pkts_not_isl_vlan_mpls; + uint64_t pkts_isl; + uint64_t pkts_vlan; + uint64_t pkts_isl_vlan; + uint64_t pkts_mpls; + uint64_t pkts_isl_mpls; + uint64_t pkts_vlan_mpls; + uint64_t pkts_isl_vlan_mpls; + uint64_t pkts_no_filter; + uint64_t pkts_dedup_drop; + uint64_t pkts_filter_drop; + uint64_t pkts_overflow; + uint64_t pkts_dbs_drop; + uint64_t octets_no_filter; + uint64_t octets_dedup_drop; + uint64_t octets_filter_drop; + uint64_t octets_overflow; + uint64_t octets_dbs_drop; + uint64_t ipft_first_hit; + uint64_t ipft_first_not_hit; + uint64_t ipft_mid_hit; + uint64_t ipft_mid_not_hit; + uint64_t ipft_last_hit; + uint64_t ipft_last_not_hit; +}; + +struct port_counters_vswitch_v1 { + /* Rx/Tx common port counters */ + uint64_t octets; + uint64_t pkts; + uint64_t drop_events; + uint64_t qos_drop_octets; + uint64_t qos_drop_pkts; +}; + +struct flm_counters_v1 { + /* FLM 0.17 */ + uint64_t current; + uint64_t learn_done; + uint64_t learn_ignore; + uint64_t learn_fail; + uint64_t unlearn_done; + uint64_t unlearn_ignore; + uint64_t auto_unlearn_done; + uint64_t auto_unlearn_ignore; + uint64_t auto_unlearn_fail; + uint64_t timeout_unlearn_done; + uint64_t rel_done; + uint64_t rel_ignore; + /* FLM 0.20 */ + uint64_t prb_done; + uint64_t prb_ignore; + uint64_t sta_done; + uint64_t inf_done; + uint64_t inf_skip; + uint64_t pck_hit; + uint64_t pck_miss; + uint64_t pck_unh; + uint64_t pck_dis; + uint64_t csh_hit; + uint64_t csh_miss; + uint64_t csh_unh; + uint64_t cuc_start; + uint64_t cuc_move; +}; + +struct nt4ga_stat_s { + nthw_stat_t *mp_nthw_stat; + nthw_rmc_t *mp_nthw_rmc; + struct nt_dma_s *p_stat_dma; + uint32_t *p_stat_dma_virtual; + uint32_t n_stat_size; + + uint64_t last_timestamp; + + int mn_rx_host_buffers; + int mn_tx_host_buffers; + + int mn_rx_ports; + int mn_tx_ports; + + struct color_counters *mp_stat_structs_color; + /* For calculating increments between stats polls */ + struct color_counters a_stat_structs_color_base[NT_MAX_COLOR_FLOW_STATS]; + + union { + /*Port counters for VSWITCH/inline */ + struct { + struct port_counters_vswitch_v1 *mp_stat_structs_port_rx; + struct port_counters_vswitch_v1 *mp_stat_structs_port_tx; + } virt; + struct { + struct port_counters_v2 *mp_stat_structs_port_rx; + struct port_counters_v2 *mp_stat_structs_port_tx; + } cap; + }; + + struct host_buffer_counters *mp_stat_structs_hb; + + int flm_stat_ver; + struct flm_counters_v1 *mp_stat_structs_flm; + + /* Rx/Tx totals: */ + uint64_t n_totals_reset_timestamp; /* timestamp for last totals reset */ + + uint64_t a_port_rx_octets_total[NUM_ADAPTER_PORTS_MAX]; + /* Base is for calculating increments between statistics reads */ + uint64_t a_port_rx_octets_base[NUM_ADAPTER_PORTS_MAX]; + + uint64_t a_port_rx_packets_total[NUM_ADAPTER_PORTS_MAX]; + uint64_t a_port_rx_packets_base[NUM_ADAPTER_PORTS_MAX]; + + uint64_t a_port_rx_drops_total[NUM_ADAPTER_PORTS_MAX]; + uint64_t a_port_rx_drops_base[NUM_ADAPTER_PORTS_MAX]; + + uint64_t a_port_tx_octets_total[NUM_ADAPTER_PORTS_MAX]; + uint64_t a_port_tx_octets_base[NUM_ADAPTER_PORTS_MAX]; + + uint64_t a_port_tx_packets_base[NUM_ADAPTER_PORTS_MAX]; + uint64_t a_port_tx_packets_total[NUM_ADAPTER_PORTS_MAX]; + + uint64_t a_port_tx_drops_base[NUM_ADAPTER_PORTS_MAX]; + uint64_t a_port_tx_drops_total[NUM_ADAPTER_PORTS_MAX]; +}; + +typedef struct nt4ga_stat_s nt4ga_stat_t; + +int nt4ga_stat_init(struct adapter_info_s *p_adapter_info); +int nt4ga_stat_setup(struct adapter_info_s *p_adapter_info); +int nt4ga_stat_stop(struct adapter_info_s *p_adapter_info); + +int nt4ga_stat_dump(struct adapter_info_s *p_adapter_info, FILE *pfh); + +int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info, + nt4ga_stat_t *p_nt4ga_stat); + +#endif /* NT4GA_STAT_H_ */ diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build index 6f48af601f..1571111bce 100644 --- a/drivers/net/ntnic/meson.build +++ b/drivers/net/ntnic/meson.build @@ -16,22 +16,39 @@ endif # includes includes = [ include_directories('.'), + include_directories('adapter'), include_directories('include'), + include_directories('nim'), include_directories('ntlog/include'), include_directories('ntutil/include'), include_directories('nthw'), include_directories('nthw/core'), include_directories('nthw/supported'), + include_directories('sensors'), + include_directories('sensors/avr_sensors'), + include_directories('sensors/board_sensors'), + include_directories('sensors/nim_sensors'), + include_directories('sensors/ntavr'), ] # all sources sources = files( + 'adapter/nt4ga_adapter.c', + 'adapter/nt4ga_link.c', + 'adapter/nt4ga_link_100g.c', + 'adapter/nt4ga_pci_ta_tg.c', + 'adapter/nt4ga_stat.c', + 'nim/i2c_nim.c', + 'nim/nt_link_speed.c', + 'nim/qsfp_sensors.c', + 'nim/sfp_sensors.c', 'nthw/core/nthw_clock_profiles.c', 'nthw/core/nthw_fpga.c', 'nthw/core/nthw_fpga_nt200a0x.c', 'nthw/core/nthw_fpga_rst.c', 'nthw/core/nthw_fpga_rst9563.c', 'nthw/core/nthw_fpga_rst_nt200a0x.c', + 'nthw/core/nthw_gmf.c', 'nthw/core/nthw_gpio_phy.c', 'nthw/core/nthw_hif.c', 'nthw/core/nthw_iic.c', @@ -41,6 +58,7 @@ sources = files( 'nthw/core/nthw_pci_ta.c', 'nthw/core/nthw_pci_wr_tg.c', 'nthw/core/nthw_pcie3.c', + 'nthw/core/nthw_rmc.c', 'nthw/core/nthw_sdc.c', 'nthw/core/nthw_si5340.c', 'nthw/core/nthw_spi_v3.c', @@ -56,6 +74,12 @@ sources = files( 'nthw/supported/nthw_fpga_9563_055_024_0000.c', 'ntlog/ntlog.c', 'ntutil/nt_util.c', + 'sensors/avr_sensors/avr_sensors.c', + 'sensors/board_sensors/board_sensors.c', + 'sensors/board_sensors/tempmon.c', + 'sensors/nim_sensors/nim_sensors.c', + 'sensors/ntavr/ntavr.c', + 'sensors/sensors.c', ) if is_variable('default_cflags') diff --git a/drivers/net/ntnic/nim/i2c_nim.c b/drivers/net/ntnic/nim/i2c_nim.c new file mode 100644 index 0000000000..55740e6de6 --- /dev/null +++ b/drivers/net/ntnic/nim/i2c_nim.c @@ -0,0 +1,1974 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nthw_drv.h" +#include "i2c_nim.h" +#include "ntlog.h" +#include "nt_util.h" + +#include "nim_sensors.h" +#include "sfp_p_registers.h" +#include "qsfp_registers.h" +#include "sfp_sensors.h" +#include "qsfp_sensors.h" + +#include +#include /* memcmp, memset */ + +/* + * Nim functions + */ +#define QSFP_SUP_LEN_INFO_LIN_ADDR 142 /* 5bytes */ +#define QSFP_TRANSMITTER_TYPE_LIN_ADDR 147 /* 1byte */ +#define QSFP_CONTROL_STATUS_LIN_ADDR 86 +#define QSFP_SOFT_TX_ALL_DISABLE_BITS 0x0F +#define QSFP_SPEC_COMPLIANCE_CODES_ADDR 131 /* 8 bytes */ +#define QSFP_EXT_SPEC_COMPLIANCE_CODES_ADDR 192 /* 1 byte */ +#define NIM_READ false +#define NIM_WRITE true +#define NIM_PAGE_SEL_REGISTER 127 +#define nim_i2c_0xa0 0xA0 /* Basic I2C address */ +#define QSFP_VENDOR_NAME_LIN_ADDR 148 /* 16bytes */ +#define QSFP_VENDOR_PN_LIN_ADDR 168 /* 16bytes */ +#define QSFP_VENDOR_SN_LIN_ADDR 196 /* 16bytes */ +#define QSFP_VENDOR_DATE_LIN_ADDR 212 /* 8bytes */ +#define QSFP_VENDOR_REV_LIN_ADDR 184 /* 2bytes */ +#define QSFP_DMI_OPTION_LIN_ADDR 220 + +#define QSFP_EXTENDED_IDENTIFIER 129 +#define QSFP_POWER_CLASS_BITS_1_4 0xC0 +#define QSFP_POWER_CLASS_BITS_5_7 0x03 + +static bool sfp_is_supported_tri_speed_pn(char *prod_no) +{ + static const char *const pn_trispeed_list[] = { + "FCMJ-8521-3", "FCLF-8521-3", "FCLF8521P2BTL", "EOLT-C12-02A", + "AMXP-24RJS", "ABCU-5710RZ", "ABCU-5740RZ", "FCLF8522P2BTL", + }; + + /* Determine if copper SFP is supported 3-speed type */ + for (size_t i = 0; i < ARRAY_SIZE(pn_trispeed_list); i++) + if (strcmp(pn_trispeed_list[i], prod_no) == 0) + return true; + + return false; +} + +static bool page_addressing(nt_nim_identifier_t id) +{ + switch (id) { + case NT_NIM_SFP_SFP_PLUS: + return false; + case NT_NIM_XFP: + return true; + case NT_NIM_QSFP: + case NT_NIM_QSFP_PLUS: + case NT_NIM_QSFP28: + return true; + default: + NT_LOG(DBG, ETHDEV, "%s: Unknown NIM identifier %d\n", __func__, + id); + return false; + } +} + +nt_nim_identifier_t translate_nimid(const nim_i2c_ctx_t *ctx) +{ + return (nt_nim_identifier_t)ctx->nim_id; +} + +static int nim_read_write_i2c_data(nim_i2c_ctx_p ctx, bool do_write, + uint16_t lin_addr, uint8_t i2c_addr, + uint8_t reg_addr, uint8_t seq_cnt, uint8_t *p_data) +{ + /* Divide I2C_Addr by 2 because nthw_iic_read/writeData multiplies by 2 */ + const uint8_t i2c_devaddr = i2c_addr / 2U; + (void)lin_addr; /* Unused */ + + if (do_write) + return nthw_iic_write_data(&ctx->hwiic, i2c_devaddr, reg_addr, + seq_cnt, p_data); + else + return nthw_iic_read_data(&ctx->hwiic, i2c_devaddr, reg_addr, + seq_cnt, p_data); +} + +/* + * ------------------------------------------------------------------------------ + * Selects a new page for page addressing. This is only relevant if the NIM + * supports this. Since page switching can take substantial time the current page + * select is read and subsequently only changed if necessary. + * Important: + * XFP Standard 8077, Ver 4.5, Page 61 states that: + * If the host attempts to write a table select value which is not supported in + * a particular module, the table select byte will revert to 01h. + * This can lead to some surprising result that some pages seems to be duplicated. + * ------------------------------------------------------------------------------ + */ + +static int nim_setup_page(nim_i2c_ctx_p ctx, uint8_t page_sel) +{ + uint8_t curr_page_sel; + + /* Read the current page select value */ + if (nim_read_write_i2c_data(ctx, NIM_READ, NIM_PAGE_SEL_REGISTER, + nim_i2c_0xa0, NIM_PAGE_SEL_REGISTER, + sizeof(curr_page_sel), &curr_page_sel) != 0) + return -1; + + /* Only write new page select value if necessary */ + if (page_sel != curr_page_sel) { + if (nim_read_write_i2c_data(ctx, NIM_WRITE, NIM_PAGE_SEL_REGISTER, + nim_i2c_0xa0, NIM_PAGE_SEL_REGISTER, + sizeof(page_sel), &page_sel) != 0) + return -1; + } + return 0; +} + +static int nim_nim_read_write_data_lin(nim_i2c_ctx_p ctx, bool m_page_addressing, + uint16_t lin_addr, uint16_t length, + uint8_t *p_data, bool do_write) +{ + uint16_t i; + uint8_t reg_addr; /* The actual register address in I2C device */ + uint8_t i2c_addr; + int block_size = 128; /* Equal to size of MSA pages */ + int seq_cnt; + int max_seq_cnt = 1; + int multi_byte = 1; /* One byte per I2C register is default */ + const int m_port_no = ctx->instance - 2; + + if (lin_addr >= SFP_PHY_LIN_ADDR) { + /* + * This represents an address space at I2C address 0xAC for SFP modules + * containing a PHY. (eg 1G Copper SFP). Each register is 16bit and is + * accessed MSByte first and this reading latches the LSByte that is + * subsequently read from the same address. + */ + multi_byte = 2; + max_seq_cnt = 2; + + /* Test for correct multibyte access */ + if ((length % multi_byte) != 0) { + NT_LOG(ERR, ETHDEV, + "Port %d: %s: Uneven length (%d) for address range [0x%X..0x%X].", + m_port_no, __func__, length, SFP_PHY_LIN_ADDR, + SFP_PHY_LIN_ADDR + SFP_PHY_LIN_RNG - 1); + return -1; + } + + if (lin_addr + (length / 2) > + SFP_PHY_LIN_ADDR + SFP_PHY_LIN_RNG) { + NT_LOG(ERR, ETHDEV, + "Port %d: %s: Access above address range [0x%X..0x%X].", + m_port_no, __func__, SFP_PHY_LIN_ADDR, + SFP_PHY_LIN_ADDR + SFP_PHY_LIN_RNG - 1); + return -1; + } + } else if (lin_addr + length > 128) { + /* + * Page addressing could be relevant since the last byte is outside the + * basic range so check if it is enabled + */ + if (m_page_addressing) { + /* Crossing into the PHY address range is not allowed */ + if (lin_addr + length > SFP_PHY_LIN_ADDR) { + NT_LOG(ERR, ETHDEV, + "Port %d: %s: Access above paged address range [0..0x%X].", + m_port_no, __func__, SFP_PHY_LIN_ADDR); + return -1; + } + } else { + /* Access outside 0xA2 address range not allowed */ + if (lin_addr + length > 512) { + NT_LOG(ERR, ETHDEV, + "Port %d: %s: Access above address range [0..511].", + m_port_no, __func__); + return -1; + } + } + } + /* No missing else here - all devices supports access to address [0..127] */ + + for (i = 0; i < length;) { + bool use_page_select = false; + + /* + * Find out how much can be read from the current block in case of + * single byte access + */ + if (multi_byte == 1) + max_seq_cnt = block_size - (lin_addr % block_size); + + if (m_page_addressing) { + if (lin_addr >= 128) { /* Only page setup above this address */ + use_page_select = true; + + /* Map to [128..255] of 0xA0 device */ + reg_addr = (uint8_t)(block_size + + (lin_addr % block_size)); + } else { + reg_addr = (uint8_t)lin_addr; + } + i2c_addr = nim_i2c_0xa0; /* Base I2C address */ + } else { + if (lin_addr >= SFP_PHY_LIN_ADDR) { + /* Map to address [0..31] of 0xAC device */ + reg_addr = (uint8_t)(lin_addr - SFP_PHY_LIN_ADDR); + i2c_addr = nim_i2c_0xac; + } else if (lin_addr >= 256) { + /* Map to address [0..255] of 0xA2 device */ + reg_addr = (uint8_t)(lin_addr - 256); + i2c_addr = nim_i2c_0xa2; + } else { + reg_addr = (uint8_t)lin_addr; + i2c_addr = nim_i2c_0xa0; /* Base I2C address */ + } + } + + /* Now actually do the reading/writing */ + seq_cnt = length - i; /* Number of remaining bytes */ + + if (seq_cnt > max_seq_cnt) + seq_cnt = max_seq_cnt; + + /* + * Read a number of bytes without explicitly specifying a new address. + * This can speed up I2C access since automatic incrementation of the + * I2C device internal address counter can be used. It also allows + * a HW implementation, that can deal with block access. + * Furthermore it also allows for access to data that must be accessed + * as 16bit words reading two bytes at each address eg PHYs. + */ + if (use_page_select) { + if (nim_setup_page(ctx, + (uint8_t)((lin_addr / 128) - 1)) != 0) { + NT_LOG(ERR, ETHDEV, + "%s: Cannot set up page for linear address %u\n", + __func__, lin_addr); + return -1; + } + } + if (nim_read_write_i2c_data(ctx, do_write, lin_addr, i2c_addr, + reg_addr, (uint8_t)seq_cnt, + p_data) != 0) { + NT_LOG(ERR, ETHDEV, + "%s: Call to NIM_ReadWriteI2cData failed\n", + __func__); + return -1; + } + + p_data += seq_cnt; + i = (uint16_t)(i + seq_cnt); + lin_addr = (uint16_t)(lin_addr + (seq_cnt / multi_byte)); + } + return 0; +} + +int read_data_lin(nim_i2c_ctx_p ctx, uint16_t lin_addr, uint16_t length, + void *data) +{ + return nim_nim_read_write_data_lin(ctx, page_addressing(ctx->nim_id), + lin_addr, length, data, NIM_READ); +} + +static int write_data_lin(nim_i2c_ctx_p ctx, uint16_t lin_addr, uint16_t length, + void *data) +{ + return nim_nim_read_write_data_lin(ctx, page_addressing(ctx->nim_id), + lin_addr, length, data, NIM_WRITE); +} + +/* Read and return a single byte */ +static uint8_t read_byte(nim_i2c_ctx_p ctx, uint16_t addr) +{ + uint8_t data; + + read_data_lin(ctx, addr, sizeof(data), &data); + return data; +} + +static int nim_read_id(nim_i2c_ctx_t *ctx) +{ + /* We are only reading the first byte so we don't care about pages here. */ + const bool use_page_addressing = false; + + if (nim_nim_read_write_data_lin(ctx, use_page_addressing, + NIM_IDENTIFIER_ADDR, sizeof(ctx->nim_id), + &ctx->nim_id, NIM_READ) != 0) + return -1; + return 0; +} + +static int i2c_nim_common_construct(nim_i2c_ctx_p ctx) +{ + ctx->nim_id = 0; + int res = nim_read_id(ctx); + + if (res) { + NT_LOG(ERR, PMD, "Can't read NIM id."); + return res; + } + memset(ctx->vendor_name, 0, sizeof(ctx->vendor_name)); + memset(ctx->prod_no, 0, sizeof(ctx->prod_no)); + memset(ctx->serial_no, 0, sizeof(ctx->serial_no)); + memset(ctx->date, 0, sizeof(ctx->date)); + memset(ctx->rev, 0, sizeof(ctx->rev)); + + ctx->content_valid = false; + memset(ctx->len_info, 0, sizeof(ctx->len_info)); + ctx->pwr_level_req = 0; + ctx->pwr_level_cur = 0; + ctx->avg_pwr = false; + ctx->tx_disable = false; + ctx->lane_idx = -1; + ctx->lane_count = 1; + ctx->options = 0; + return 0; +} + +static int nim_read_vendor_info(nim_i2c_ctx_p ctx, uint16_t addr, + uint8_t max_len, char *p_data); + +#define XSFP_READ_VENDOR_INFO(x) \ + static void x##sfp_read_vendor_info(nim_i2c_ctx_t *ctx) \ + { \ + nim_read_vendor_info(ctx, Q##SFP_VENDOR_NAME_LIN_ADDR, \ + sizeof(ctx->vendor_name), \ + ctx->vendor_name); \ + nim_read_vendor_info(ctx, Q##SFP_VENDOR_PN_LIN_ADDR, \ + sizeof(ctx->prod_no), ctx->prod_no); \ + nim_read_vendor_info(ctx, Q##SFP_VENDOR_SN_LIN_ADDR, \ + sizeof(ctx->serial_no), ctx->serial_no); \ + nim_read_vendor_info(ctx, Q##SFP_VENDOR_DATE_LIN_ADDR, \ + sizeof(ctx->date), ctx->date); \ + nim_read_vendor_info(ctx, Q##SFP_VENDOR_REV_LIN_ADDR, \ + (uint8_t)(sizeof(ctx->rev) - 2), \ + ctx->rev); /*OBS Only two bytes*/ \ + } + +XSFP_READ_VENDOR_INFO() +XSFP_READ_VENDOR_INFO(q) + +static int sfp_nim_state_build(nim_i2c_ctx_t *ctx, sfp_nim_state_t *state) +{ + int res; + + assert(ctx && state); + assert(ctx->nim_id != NT_NIM_UNKNOWN && "Nim is not initialized"); + + (void)memset(state, 0, sizeof(*state)); + + res = nthw_iic_read_data(&ctx->hwiic, ctx->devaddr, SFP_BIT_RATE_ADDR, + sizeof(state->br), &state->br); + return res; +} + +static int qsfp_nim_state_build(nim_i2c_ctx_t *ctx, sfp_nim_state_t *state) +{ + int res = 0; /* unused due to no readings from HW */ + + assert(ctx && state); + assert(ctx->nim_id != NT_NIM_UNKNOWN && "Nim is not initialized"); + + (void)memset(state, 0, sizeof(*state)); + + switch (ctx->nim_id) { + case 12U: + state->br = 10U; /* QSFP: 4 x 1G = 4G */ + break; + case 13U: + state->br = 103U; /* QSFP+: 4 x 10G = 40G */ + break; + case 17U: + state->br = 255U; /* QSFP28: 4 x 25G = 100G */ + break; + default: + NT_LOG(INF, PMD, + "%s:%d nim_id = %u is not an QSFP/QSFP+/QSFP28 module\n", + __func__, __LINE__, ctx->nim_id); + res = -1; + } + + return res; +} + +int nim_state_build(nim_i2c_ctx_t *ctx, sfp_nim_state_t *state) +{ + if (translate_nimid(ctx) == NT_NIM_SFP_SFP_PLUS) + return sfp_nim_state_build(ctx, state); + else + return qsfp_nim_state_build(ctx, state); +} + +const char *nim_id_to_text(uint8_t nim_id) +{ + switch (nim_id) { + case 0x0: + return "UNKNOWN"; + case 0x1: + return "GBIC"; + case 0x2: + return "FIXED"; + case 0x3: + return "SFP/SFP+"; + case 0x04: + return "300 pin XBI"; + case 0x05: + return "XEN-PAK"; + case 0x06: + return "XFP"; + case 0x07: + return "XFF"; + case 0x08: + return "XFP-E"; + case 0x09: + return "XPAK"; + case 0x0A: + return "X2"; + case 0x0B: + return "DWDM"; + case 0x0C: + return "QSFP"; + case 0x0D: + return "QSFP+"; + case 0x11: + return "QSFP28"; + case 0x12: + return "CFP4"; + default: + return "ILLEGAL!"; + } +} + +/* + * Read and check the validity of the NIM basic data. + * This will also preload the cache + */ +static void check_content_valid(nim_i2c_ctx_p ctx, uint16_t start_addr) +{ + uint32_t sum = 0; + uint8_t buf[96]; + + read_data_lin(ctx, start_addr, sizeof(buf), &buf[0]); + + for (int i = 0; i < 63; i++) + sum += buf[i]; + + if ((sum & 0xFF) != buf[63]) { + ctx->content_valid = false; + } else { + sum = 0; + + for (int i = 64; i < 95; i++) + sum += buf[i]; + + ctx->content_valid = ((sum & 0xFF) == buf[95]); + } + if (ctx->content_valid) + NT_LOG(DBG, NTHW, "NIM content validation passed"); + else + NT_LOG(WRN, NTHW, "NIM content validation failed"); +} + +/* + * Set/reset Soft Rate__select bits (RS0 & RS1) + */ +static void nim_sfp_set_rate_sel_high(nim_i2c_ctx_p ctx, bool rx_rate_high, + bool tx_rate_high) +{ + const bool m_page_addressing = page_addressing(ctx->nim_id); + uint8_t data; + + nim_nim_read_write_data_lin(ctx, m_page_addressing, + SFP_CONTROL_STATUS_LIN_ADDR, sizeof(data), + &data, NIM_READ); + + if (rx_rate_high) + data |= SFP_SOFT_RATE0_BIT; + else + data &= (uint8_t)~(SFP_SOFT_RATE0_BIT); + + nim_nim_read_write_data_lin(ctx, m_page_addressing, + SFP_CONTROL_STATUS_LIN_ADDR, sizeof(data), + &data, NIM_WRITE); + + /* Read the Extended Status/Control and set/reset Soft RS1 bit */ + nim_nim_read_write_data_lin(ctx, m_page_addressing, + SFP_EXT_CTRL_STAT0_LIN_ADDR, sizeof(data), + &data, NIM_READ); + + if (tx_rate_high) + data |= SFP_SOFT_RATE1_BIT; + else + data &= (uint8_t)~(SFP_SOFT_RATE1_BIT); + + nim_nim_read_write_data_lin(ctx, m_page_addressing, + SFP_EXT_CTRL_STAT0_LIN_ADDR, sizeof(data), + &data, NIM_WRITE); +} + +/* + * Some NIM modules requires some changes to a rate setting. + */ +static int nim_sfp_set_rate_select(nim_i2c_ctx_p ctx, nt_link_speed_t speed) +{ + if ((speed & (int)ctx->speed_mask) == 0) { + char buf[128]; + + NT_LOG(ERR, ETHDEV, "%s - Speed (%s) not within SpeedMask (%s)", + nt_translate_link_speed(speed), + nt_translate_link_speed_mask(ctx->speed_mask, buf, + sizeof(buf))); + return -1; + } + + if (ctx->specific_u.sfp.dual_rate) { + uint64_t req_speed = nt_get_link_speed(speed); + uint64_t other_speed = + nt_get_link_speed((nt_link_speed_t)(ctx->speed_mask ^ (uint32_t)speed)); + bool rate_high = req_speed > other_speed; + /* + * Do this both for 1/10 and 10/25. For Sfp28 it is not known if + * this is necessary but it is believed not to do any harm. + */ + nim_sfp_set_rate_sel_high(ctx, rate_high, rate_high); + } + return 0; +} + +/* + * Disable TX laser. + */ +int nim_sfp_nim_set_tx_laser_disable(nim_i2c_ctx_p ctx, bool disable) +{ + int res; + uint8_t value; + const bool pg_addr = page_addressing(ctx->nim_id); + + res = nim_nim_read_write_data_lin(ctx, pg_addr, SFP_CONTROL_STATUS_LIN_ADDR, + sizeof(value), &value, NIM_READ); + if (res != 0) + return res; + + if (disable) + value |= SFP_SOFT_TX_DISABLE_BIT; + else + value &= (uint8_t)~SFP_SOFT_TX_DISABLE_BIT; + + res = nim_nim_read_write_data_lin(ctx, pg_addr, SFP_CONTROL_STATUS_LIN_ADDR, + sizeof(value), &value, NIM_WRITE); + + return res; +} + +/* + * Disable laser for specific lane or all lanes + */ +int nim_qsfp_plus_nim_set_tx_laser_disable(nim_i2c_ctx_p ctx, bool disable, + int lane_idx) +{ + uint8_t value; + uint8_t mask; + const bool pg_addr = page_addressing(ctx->nim_id); + + if (lane_idx < 0) /* If no lane is specified then all lanes */ + mask = QSFP_SOFT_TX_ALL_DISABLE_BITS; + else + mask = (uint8_t)(1U << lane_idx); + + if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_CONTROL_STATUS_LIN_ADDR, + sizeof(value), &value, NIM_READ) != 0) + return -1; + + if (disable) + value |= mask; + else + value &= (uint8_t)~mask; + + if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_CONTROL_STATUS_LIN_ADDR, + sizeof(value), &value, NIM_WRITE) != 0) + return -1; + return 0; +} + +/* + * Read vendor information at a certain address. Any trailing whitespace is + * removed and a missing string termination in the NIM data is handled. + */ +static int nim_read_vendor_info(nim_i2c_ctx_p ctx, uint16_t addr, + uint8_t max_len, char *p_data) +{ + const bool pg_addr = page_addressing(ctx->nim_id); + int i; + /* Subtract "1" from maxLen that includes a terminating "0" */ + + if (nim_nim_read_write_data_lin(ctx, pg_addr, addr, (uint8_t)(max_len - 1), + (uint8_t *)p_data, NIM_READ) != 0) + return -1; + + /* Terminate at first found white space */ + for (i = 0; i < max_len - 1; i++) { + if (*p_data == ' ' || *p_data == '\n' || *p_data == '\t' || + *p_data == '\v' || *p_data == '\f' || *p_data == '\r') { + *p_data = '\0'; + return 0; + } + + p_data++; + } + + /* + * Add line termination as the very last character, if it was missing in the + * NIM data + */ + *p_data = '\0'; + return 0; +} + +/* + * Import length info in various units from NIM module data and convert to meters + */ +static void nim_import_len_info(nim_i2c_ctx_p ctx, uint8_t *p_nim_len_info, + uint16_t *p_nim_units) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(ctx->len_info); i++) + if (*(p_nim_len_info + i) == 255) { + ctx->len_info[i] = 65535; + } else { + uint32_t len = *(p_nim_len_info + i) * *(p_nim_units + i); + + if (len > 65535) + ctx->len_info[i] = 65535; + else + ctx->len_info[i] = (uint16_t)len; + } +} + +static int qsfpplus_read_basic_data(nim_i2c_ctx_t *ctx) +{ + const bool pg_addr = page_addressing(ctx->nim_id); + uint8_t options; + uint8_t value; + uint8_t nim_len_info[5]; + uint16_t nim_units[5] = { 1000, 2, 1, 1, + 1 + }; /* QSFP MSA units in meters */ + const char *yes_no[2] _unused = { "No", "Yes" }; + + NT_LOG(DBG, ETHDEV, "Instance %d: NIM id: %s (%d)\n", ctx->instance, + nim_id_to_text(ctx->nim_id), ctx->nim_id); + + /* Read DMI options */ + if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_DMI_OPTION_LIN_ADDR, + sizeof(options), &options, NIM_READ) != 0) + return -1; + ctx->avg_pwr = options & QSFP_DMI_AVG_PWR_BIT; + NT_LOG(DBG, ETHDEV, + "Instance %d: NIM options: (DMI: Yes, AvgPwr: %s)\n", + ctx->instance, yes_no[ctx->avg_pwr]); + + qsfp_read_vendor_info(ctx); + NT_LOG(DBG, PMD, + "Instance %d: NIM info: (Vendor: %s, PN: %s, SN: %s, Date: %s, Rev: %s)\n", + ctx->instance, ctx->vendor_name, ctx->prod_no, ctx->serial_no, + ctx->date, ctx->rev); + + if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_SUP_LEN_INFO_LIN_ADDR, + sizeof(nim_len_info), nim_len_info, + NIM_READ) != 0) + return -1; + + /* + * Returns supported length information in meters for various fibers as 5 indivi- + * dual values: [SM(9um), EBW(50um), MM(50um), MM(62.5um), Copper] + * If no length information is available for a certain entry, the returned value + * will be zero. This will be the case for SFP modules - EBW entry. + * If the MSBit is set the returned value in the lower 31 bits indicates that the + * supported length is greater than this. + */ + + nim_import_len_info(ctx, nim_len_info, nim_units); + + /* Read required power level */ + if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_EXTENDED_IDENTIFIER, + sizeof(value), &value, NIM_READ) != 0) + return -1; + + /* + * Get power class according to SFF-8636 Rev 2.7, Table 6-16, Page 43: + * If power class >= 5 setHighPower must be called for the module to be fully + * functional + */ + if ((value & QSFP_POWER_CLASS_BITS_5_7) == 0) { + /* NIM in power class 1 - 4 */ + ctx->pwr_level_req = + (uint8_t)(((value & QSFP_POWER_CLASS_BITS_1_4) >> 6) + + 1); + } else { + /* NIM in power class 5 - 7 */ + ctx->pwr_level_req = + (uint8_t)((value & QSFP_POWER_CLASS_BITS_5_7) + 4); + } + + return 0; +} + +/* + * If true the user must actively select the desired rate. If false the module + * however can still support several rates without the user is required to select + * one of them. Supported rates must then be deduced from the product number. + * SFF-8636, Rev 2.10a: + * p40: 6.2.7 Rate Select + * p85: A.2 Rate Select + */ +static bool qsfp28_is_speed_selection_enabled(nim_i2c_ctx_p ctx) +{ + const uint8_t options_reg_addr = 195; + const uint8_t enh_options_reg_addr = 221; + + uint8_t rate_select_ena = (read_byte(ctx, options_reg_addr) >> 5) & + 0x01; /* bit: 5 */ + + if (rate_select_ena == 0) + return false; + + uint8_t rate_select_type = (read_byte(ctx, enh_options_reg_addr) >> 2) & + 0x03; /* bit 3..2 */ + + if (rate_select_type != 2) { + NT_LOG(DBG, NTHW, "NIM has unhandled rate select type (%d)", + rate_select_type); + return false; + } + + return true; /* When true selectRate() can be used */ +} + +/* + * Select a speed that is supported for a multi rate module. The possible speed + * values must be obtained by setSpeedMask(). + * Currently rate selection is assumed to be between 40Gb (10GBd) and 100G (25Gbd) + * The value in () are the baud rates for PAM-4 and are valid for extended rate + * select, version 2. + */ +static int qsfp28_set_link_speed(nim_i2c_ctx_p ctx, nt_link_speed_t speed) +{ + const uint8_t rx_rate_sel_addr = 87; + const uint8_t tx_rate_sel_addr = 88; + + if (ctx->lane_idx < 0) { + /* + * All lanes together + * The condition below indicates that the module supports rate selection + */ + if (ctx->speed_mask == (uint32_t)(NT_LINK_SPEED_40G | NT_LINK_SPEED_100G)) { + uint16_t data; + + if (speed == NT_LINK_SPEED_100G) { + data = 0xAAAA; + } else if (speed == NT_LINK_SPEED_40G) { + data = 0x0000; + } else { + NT_LOG(ERR, NTHW, "Unhandled NIM speed (%s).", + nt_translate_link_speed(speed)); + return -1; + } + + /* Set speed for Rx and Tx on all lanes */ + write_data_lin(ctx, rx_rate_sel_addr, sizeof(data), &data); + write_data_lin(ctx, tx_rate_sel_addr, sizeof(data), &data); + } else { + /* For ordinary modules only this speed is supported */ + if (speed != NT_LINK_SPEED_100G) { + NT_LOG(ERR, NTHW, + "NIM cannot select this speed (%s).", + nt_translate_link_speed(speed)); + return -1; + } + } + } else { + /* + * Individual lanes + * Currently we do not support QSFP28 modules that support rate selection when + * running on individual lanes but that might change in the future + */ + if (speed != NT_LINK_SPEED_25G) { + NT_LOG(ERR, NTHW, + "NIM cannot select this lane speed (%s).", + nt_translate_link_speed(speed)); + return -1; + } + } + return 0; +} + +int nim_set_link_speed(nim_i2c_ctx_p ctx, nt_link_speed_t speed) +{ + if (translate_nimid(ctx) == NT_NIM_SFP_SFP_PLUS) { + return nim_sfp_set_rate_select(ctx, speed); + } else if (translate_nimid(ctx) == NT_NIM_QSFP28) { + if (qsfp28_is_speed_selection_enabled(ctx)) + return qsfp28_set_link_speed(ctx, speed); + + return 0; /* NIM picks up the speed automatically */ + } + NT_LOG(ERR, ETHDEV, + "%s nim is not supported for adjustable link speed.", + nim_id_to_text(ctx->nim_id)); + return -1; +} + +/* + * Reads basic vendor and DMI information. + */ +static int sfp_read_basic_data(nim_i2c_ctx_p ctx) +{ + const char *yes_no[2] _unused = { "No", "Yes" }; + + check_content_valid(ctx, 0); + NT_LOG(DBG, PMD, "NIM id: %s (%d)", nim_id_to_text(ctx->nim_id), + ctx->nim_id); + + /* Read DMI options */ + uint8_t options; + + read_data_lin(ctx, SFP_DMI_OPTION_LIN_ADDR, sizeof(options), &options); + ctx->avg_pwr = options & SFP_DMI_AVG_PWR_BIT; + ctx->dmi_supp = options & SFP_DMI_IMPL_BIT; + ctx->specific_u.sfp.ext_cal = options & SFP_DMI_EXT_CAL_BIT; + ctx->specific_u.sfp.addr_chg = options & SFP_DMI_ADDR_CHG_BIT; + + if (ctx->dmi_supp) { + ctx->options |= + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } + + if (ctx->dmi_supp) { + NT_LOG(DBG, PMD, + "NIM options: (DMI: %s, AvgPwr: %s, ExtCal: %s, AddrChg: %s)", + yes_no[ctx->dmi_supp], yes_no[ctx->avg_pwr], + yes_no[ctx->specific_u.sfp.ext_cal], + yes_no[ctx->specific_u.sfp.addr_chg]); + } else { + NT_LOG(DBG, PMD, "NIM options: DMI not supported"); + } + /* Read enhanced options */ + read_data_lin(ctx, SFP_ENHANCED_OPTIONS_LIN_ADDR, sizeof(options), + &options); + ctx->tx_disable = options & SFP_SOFT_TX_DISABLE_IMPL_BIT; + + if (ctx->tx_disable) + ctx->options |= (1 << NIM_OPTION_TX_DISABLE); + + sfp_read_vendor_info(ctx); + + uint8_t nim_len_info[5]; + + read_data_lin(ctx, SFP_SUP_LEN_INFO_LIN_ADDR, sizeof(nim_len_info), + nim_len_info); + + /* + * Returns supported length information in meters for various fibers as 5 indivi- + * dual values: [SM(9um), EBW(50um), MM(50um), MM(62.5um), Copper] + * If no length information is available for a certain entry, the returned value + * will be zero. This will be the case for SFP modules - EBW entry. + * If the MSBit is set the returned value in the lower 31 bits indicates that the + * supported length is greater than this. + */ + + uint16_t nim_units[5] = { 1000, 100, 10, 10, + 1 + }; /* SFP MSA units in meters */ + nim_import_len_info(ctx, &nim_len_info[0], &nim_units[0]); + + if (ctx->len_info[0] != 0 || ctx->len_info[1] != 0) { + /* + * Make sure that for SFP modules the supported length for SM fibers + * which is given in both km and 100m units is are equal to the greatest + * value. + * The following test will also be valid if NIM_LEN_MAX has been set! + */ + if (ctx->len_info[1] > ctx->len_info[0]) + ctx->len_info[0] = ctx->len_info[1]; + + ctx->len_info[1] = 0; /* EBW is not supported for SFP */ + } + + read_data_lin(ctx, SFP_OPTION0_LIN_ADDR, sizeof(options), &options); + + if (options & SFP_POWER_LEVEL2_REQ_BIT) + ctx->pwr_level_req = 2; + else + ctx->pwr_level_req = 1; + + ctx->pwr_level_cur = 1; + + if (ctx->pwr_level_req == 2) { + /* Read the current power level status */ + read_data_lin(ctx, SFP_EXT_CTRL_STAT0_LIN_ADDR, sizeof(options), + &options); + + if (options & SFP_POWER_LEVEL2_GET_BIT) + ctx->pwr_level_cur = 2; + else + ctx->pwr_level_cur = 1; + } + return 0; +} + +/* + * Read the vendor product number and from this determine which QSFP DMI options + * that are present. This list also covers QSFP28 modules. + * This function should be used if automatic detection does not work. + */ +static bool qsfpplus_get_qsfp_options_from_pn(nim_i2c_ctx_p ctx) +{ + if (strcmp(ctx->prod_no, "FTL410QE1C") == 0) { + /* FINISAR FTL410QE1C, QSFP+ */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_TX_BIAS) | (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "FTL410QE2C") == 0) { + /* FINISAR FTL410QE2C, QSFP+ */ + ctx->options = (1 << NIM_OPTION_TEMP) | + (1 << NIM_OPTION_SUPPLY); + } else if (strcmp(ctx->prod_no, "FTL4C1QE1C") == 0) { + /* FINISAR FTL4C1QE1C, QSFP+ */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "AFBR-79E4Z") == 0) { + /* + * AFBR-79E4Z: The digital diagnostic accuracy is not guaranteed so only + * the mandatory temperature sensor is made available (although it will + * also be inaccurate) + */ + /* AVAGO 79E4Z, QSFP+ */ + ctx->options = (1 << NIM_OPTION_TEMP); + } else if (strcmp(ctx->prod_no, "AFBR-79E4Z-D") == 0) { + /* AVAGO 79E4Z-D, QSFP+ */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "AFBR-79EQDZ") == 0) { + /* AVAGO 79EQDZ, QSFP+ */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "AFBR-79EBRZ") == 0) { + /* + * Avago RxOnly BiDi NIM + * No sensors available not even the normally mandatory temp sensor and this + * is ok since the temp sensor is not mandatory on active optical modules + */ + /* SFF-8436_rev4.1, p67 */ + ctx->options = (1 << NIM_OPTION_RX_ONLY); + } else if (strcmp(ctx->prod_no, "AFBR-79EBPZ-NU1") == 0) { + /* + * Avago RxTx BiDi NIM + * No sensors available not even the normally mandatory temp sensor and this + * is ok since the temp sensor is not mandatory on active optical modules + */ + ctx->options = 0; + } else if (strcmp(ctx->prod_no, "AFBR-79EBPZ") == 0) { + /* + * Avago RxTx BiDi NIM + * No sensors available not even the normally mandatory temp sensor and this + * is ok since the temp sensor is not mandatory on active optical modules + */ + ctx->options = 0; + } else if (strcmp(ctx->prod_no, "AFBR-89CDDZ") == 0) { + /* AVAGO 89CDDZ, QSFP28 */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "AFBR-89BDDZ") == 0) { + /* AVAGO 89BDDZ, QSFP28, BiDi */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "AFBR-89BRDZ") == 0) { + /* + * AVAGO 89BRDZ, QSFP28, BiDi, RxOnly + * but sensors have been set as above except for Tx sensors + */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_RX_ONLY); + /* + * According to mail correspondence AFBR-89BRDZ is a RxOnly version of + * AFBR-89BDDZ with lasers default off. + * The lasers can be turned on however but should probably not because the + * receivers might be degraded, and this is the cause for selling them as RxOnly. + */ + } else if (strcmp(ctx->prod_no, "SQF1000L4LNGG01P") == 0) { + /* Sumitomo SQF1000L4LNGG01P, QSFP28 */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "SQF1000L4LNGG01B") == 0) { + /* Sumitomo SQF1000L4LNGG01B, QSFP28 */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "SQF1001L4LNGG01P") == 0) { + /* Sumitomo SQF1001L4LNGG01P, QSFP28 */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "SQF1001L4LNGG01B") == 0) { + /* Sumitomo SQF1001L4LNGG01B, QSFP28 */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "SQF1002L4LNGG01B") == 0) { + /* Sumitomo SQF1002L4LNGG01B, QSFP28 */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "FIM37700/171") == 0) { + /* Fujitsu FIM37700/171, QSFP28 */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "FIM37700/172") == 0) { + /* Fujitsu FIM37700/172, QSFP28 */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "TR-FC85S-NVS") == 0) { + /* InnoLight TR-FC85S-NVS, QSFP28 */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "TR-FC13L-NVS") == 0) { + /* InnoLight TR-FC13L-NVS, QSFP28 */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "FTLC9551REPM") == 0) { + /* Finisar FTLC9551REPM, QSFP28 */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else if (strcmp(ctx->prod_no, "FTLC9558REPM") == 0) { + /* Finisar FTLC9558REPM, QSFP28 */ + ctx->options = + (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) | + (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) | + (1 << NIM_OPTION_TX_POWER); + } else { + /* + * DO NOTE: The temperature sensor is not mandatory on active/passive copper + * and active optical modules + */ + ctx->options = (1 << NIM_OPTION_TEMP); + return false; + } + + return true; +} + +/* + * Try to figure out if a sensor is present by reading its value(s) and its limits. + * This is a highly impirical way that cannot be guaranteed to give the correct + * result but it was a wish not to be dependent on a PN table based solution. + */ +static void qsfpplus_find_qsfp_sensor_option(nim_i2c_ctx_p ctx, + uint16_t value_addr, + uint8_t lane_count, + uint16_t limit_addr, bool two_compl, + uint32_t sensor_option) +{ + uint8_t data[8]; + int i, j; + int value; + int value_list[4]; + int limit; + int limit_list[4]; + bool present; + + /* Read current value(s) */ + read_data_lin(ctx, value_addr, (uint16_t)(lane_count * 2), data); + + for (j = 0; j < lane_count; j++) { + value = 0; + + for (i = 0; i < 2; i++) { + value = value << 8; + value += data[2 * j + i]; + } + + if (two_compl && value >= 0x8000) + value = value - 0x10000; + + value_list[j] = value; + } + + /* Read limits Warning high/low Alarm high/low 4 values each two bytes */ + read_data_lin(ctx, limit_addr, 8, data); + + for (j = 0; j < 4; j++) { + limit = 0; + + for (i = 0; i < 2; i++) { + limit = limit << 8; + limit += data[2 * j + i]; + } + + if (two_compl && limit >= 0x8000) + limit = limit - 0x10000; + + limit_list[j] = limit; + } + + /* Find out if limits contradicts each other */ + int alarm_high = limit_list[0]; + int alarm_low = limit_list[1]; + int warn_high = limit_list[2]; + int warn_low = limit_list[3]; + + bool alarm_limits = false; /* Are they present - that is both not zero */ + bool warn_limits = false; + bool limit_conflict = false; + + if (alarm_high != 0 || alarm_low != 0) { + alarm_limits = true; + + if (alarm_high <= alarm_low) + limit_conflict = true; + } + + if (warn_high != 0 || warn_low != 0) { + warn_limits = true; + + /* Warning limits must be least restrictive */ + if (warn_high <= warn_low) + limit_conflict = true; + else if ((warn_high > alarm_high) || (warn_low < alarm_low)) + limit_conflict = true; + } + + /* Try to deduce if the sensor is present or not */ + present = false; + + if (limit_conflict) { + present = false; + } else if (warn_limits || + alarm_limits) { /* Is one or both present and not contradictory */ + present = true; + } else { + /* + * All limits are zero - look at the sensor value + * If one sensor is non-zero the sensor is set to be present + */ + for (j = 0; j < lane_count; j++) { + if (value_list[j] != 0) { + present = true; + break; + } + } + + /* + * If all limits and values are zero then present will be false here. In this + * case it is assumed that the sensor is not present: + * Experience indicates that for QSFP+ modules RxPwr will be non-zero even with + * no optical input. QSFP28 modules however can easily have RxPwr equal to zero + * with no optical input. + * For all investigated modules it was found that if RxPwr is implemented then + * the limits are also set. This is not always the case with TxBias and TxPwr + * but here the measured values will be non-zero when the laser is on what it + * will be just after initialization since it has no external hardware disable. + */ + } + + if (present) + ctx->options |= (1U << sensor_option); +} + +/* + * Find active QSFP sensors. + */ +static void qsfpplus_get_qsfp_options_from_data(nim_i2c_ctx_p ctx) +{ + ctx->options = 0; + + qsfpplus_find_qsfp_sensor_option(ctx, QSFP_TEMP_LIN_ADDR, 1, + QSFP_TEMP_THRESH_LIN_ADDR, true, + NIM_OPTION_TEMP); + + qsfpplus_find_qsfp_sensor_option(ctx, QSFP_VOLT_LIN_ADDR, 1, + QSFP_VOLT_THRESH_LIN_ADDR, false, + NIM_OPTION_SUPPLY); + + qsfpplus_find_qsfp_sensor_option(ctx, QSFP_RX_PWR_LIN_ADDR, 4, + QSFP_RX_PWR_THRESH_LIN_ADDR, false, + NIM_OPTION_RX_POWER); + + qsfpplus_find_qsfp_sensor_option(ctx, QSFP_TX_PWR_LIN_ADDR, 4, + QSFP_TX_PWR_THRESH_LIN_ADDR, false, + NIM_OPTION_TX_POWER); + + qsfpplus_find_qsfp_sensor_option(ctx, QSFP_TX_BIAS_LIN_ADDR, 4, + QSFP_BIAS_THRESH_LIN_ADDR, false, + NIM_OPTION_TX_BIAS); +} + +static void sfp_find_port_params(nim_i2c_ctx_p ctx) +{ + uint8_t data; + uint16_t bit_rate_nom; + uint8_t connector; + uint8_t gig_eth_comp; + uint8_t dmi_opt; + uint8_t fiber_chan_tx_tech; + unsigned int len_sm; + unsigned int len_mm_50um; + unsigned int len_mm_62_5um; + + ctx->specific_u.sfp.sfp28 = false; + + /* gigEthComp: */ + static const uint8_t eth_1000_b_t = 1 << 3; + static const uint8_t eth_1000_b_sx = 1 << 0; + static const uint8_t eth_1000_b_lx = 1 << 1; + + /* fiberChanTxTech: */ + static const uint8_t cu_passive = 1 << 2; + static const uint8_t cu_active = 1 << 3; + + /* dmiOpt: */ + static const uint8_t dd_present = 1 << 6; + + /* connector: */ + static const uint8_t cu_pig_tail = 0x21; + + ctx->port_type = NT_PORT_TYPE_SFP_NOT_RECOGNISED; + + read_data_lin(ctx, 12, sizeof(data), &data); + bit_rate_nom = (uint16_t)(data * 100); + + read_data_lin(ctx, 2, sizeof(connector), &connector); + read_data_lin(ctx, 6, sizeof(gig_eth_comp), &gig_eth_comp); + read_data_lin(ctx, 92, sizeof(dmi_opt), &dmi_opt); + read_data_lin(ctx, 8, sizeof(fiber_chan_tx_tech), &fiber_chan_tx_tech); + + read_data_lin(ctx, 15, sizeof(data), &data); + len_sm = (unsigned int)data * 100; /* Unit is 100m */ + + read_data_lin(ctx, 16, sizeof(data), &data); + len_mm_50um = (unsigned int)data * 10; /* Unit is 10m */ + + read_data_lin(ctx, 17, sizeof(data), &data); + len_mm_62_5um = (unsigned int)data * 10; /* Unit is 10m */ + + /* First find out if it is a SFP or a SFP+ NIM */ + if (bit_rate_nom == 0) { + /* + * A Nominal bit rate of zero indicates that it has not been defined and must + * be deduced from transceiver technology + */ + ctx->specific_u.sfp.sfpplus = !(gig_eth_comp & eth_1000_b_t); + } else if (bit_rate_nom == 25500) { + /* SFF-8024 - 4.4 Extended Specification Compliance References */ + read_data_lin(ctx, 36, sizeof(data), &data); + + if (data == 0x02) + ctx->port_type = NT_PORT_TYPE_SFP_28_SR; + else if (data == 0x03) + ctx->port_type = NT_PORT_TYPE_SFP_28_LR; + else if (data == 0x0B) + ctx->port_type = NT_PORT_TYPE_SFP_28_CR_CA_L; + else if (data == 0x0C) + ctx->port_type = NT_PORT_TYPE_SFP_28_CR_CA_S; + else if (data == 0x0D) + ctx->port_type = NT_PORT_TYPE_SFP_28_CR_CA_N; + else + ctx->port_type = NT_PORT_TYPE_SFP_28; + + ctx->specific_u.sfp.sfp28 = true; + ctx->specific_u.sfp.sfpplus = true; + + /* + * Whitelist of 25G transceivers known to also support 10G. + * There is no way to inquire about this capability. + */ + if ((strcmp(ctx->prod_no, "TR-PZ85S-N00") == 0) || + (strcmp(ctx->prod_no, "TR-PZ13L-N00") == 0) || + (strcmp(ctx->prod_no, "FTLF8536P4BCV") == 0) || + (strcmp(ctx->prod_no, "FTLF1436P4BCV") == 0)) { + ctx->specific_u.sfp.dual_rate = true; + + /* Change the port type for dual rate modules */ + if (ctx->port_type == NT_PORT_TYPE_SFP_28_SR) + ctx->port_type = NT_PORT_TYPE_SFP_28_SR_DR; + else if (ctx->port_type == NT_PORT_TYPE_SFP_28_LR) + ctx->port_type = NT_PORT_TYPE_SFP_28_LR_DR; + } + + return; + } + ctx->specific_u.sfp.sfpplus = (bit_rate_nom >= 10000); + /* Then find sub-types of each */ + if (ctx->specific_u.sfp.sfpplus) { + if (fiber_chan_tx_tech & cu_active) { + ctx->port_type = NT_PORT_TYPE_SFP_PLUS_ACTIVE_DAC; + } else if (fiber_chan_tx_tech & cu_passive) { + if (connector == cu_pig_tail) + ctx->port_type = + NT_PORT_TYPE_SFP_PLUS_PASSIVE_DAC; + else + ctx->port_type = NT_PORT_TYPE_SFP_PLUS_CU; + } else { + ctx->port_type = NT_PORT_TYPE_SFP_PLUS; + } + if (gig_eth_comp & (eth_1000_b_sx | eth_1000_b_lx)) { + ctx->port_type = NT_PORT_TYPE_SFP_PLUS_DUAL_RATE; + ctx->specific_u.sfp.dual_rate = true; + } + + read_data_lin(ctx, 65, sizeof(data), &data); + /* Test hard RATE_SELECT bit */ + ctx->specific_u.sfp.hw_rate_sel = ((data & (1 << 5)) != 0); + + read_data_lin(ctx, 93, sizeof(data), &data); + /* Test soft RATE_SELECT bit */ + ctx->specific_u.sfp.sw_rate_sel = ((data & (1 << 3)) != 0); + } else { /* SFP */ + /* 100M */ + if (bit_rate_nom != 0 && bit_rate_nom < 1000) { + ctx->port_type = NT_PORT_TYPE_SFP_FX; + /* 1G */ + } else { + ctx->specific_u.sfp.cu_type = false; + if (gig_eth_comp & eth_1000_b_sx) { + ctx->port_type = NT_PORT_TYPE_SFP_SX; + } else if (gig_eth_comp & eth_1000_b_lx) { + ctx->port_type = NT_PORT_TYPE_SFP_LX; + } else if (gig_eth_comp & eth_1000_b_t) { + ctx->specific_u.sfp.tri_speed = + sfp_is_supported_tri_speed_pn(ctx->prod_no); + + if (ctx->specific_u.sfp.tri_speed) { + ctx->port_type = + NT_PORT_TYPE_SFP_CU_TRI_SPEED; + } else { + ctx->port_type = NT_PORT_TYPE_SFP_CU; + } + ctx->specific_u.sfp.cu_type = true; + } else { + /* + * Not all modules report their ethernet compliance correctly so use + * length indicators + */ + if (len_sm > 0) + ctx->port_type = NT_PORT_TYPE_SFP_LX; + else if ((len_mm_50um > 0) || (len_mm_62_5um > 0)) + ctx->port_type = NT_PORT_TYPE_SFP_SX; + } + + /* Add Diagnostic Data suffix if necessary */ + if (dmi_opt & dd_present) { + if (ctx->port_type == NT_PORT_TYPE_SFP_SX) + ctx->port_type = NT_PORT_TYPE_SFP_SX_DD; + else if (ctx->port_type == NT_PORT_TYPE_SFP_LX) + ctx->port_type = NT_PORT_TYPE_SFP_LX_DD; + else if (ctx->port_type == NT_PORT_TYPE_SFP_CU) + ctx->port_type = NT_PORT_TYPE_SFP_CU_DD; + else if (ctx->port_type == + NT_PORT_TYPE_SFP_CU_TRI_SPEED) + ctx->port_type = + NT_PORT_TYPE_SFP_CU_TRI_SPEED_DD; + } + } + } +} + + +static void sfp_set_speed_mask(nim_i2c_ctx_p ctx) +{ + if (ctx->specific_u.sfp.sfp28) { + ctx->speed_mask = NT_LINK_SPEED_25G; /* Default for SFP28 */ + if (ctx->specific_u.sfp.dual_rate) + ctx->speed_mask |= NT_LINK_SPEED_10G; + } else if (ctx->specific_u.sfp.sfpplus) { + ctx->speed_mask = NT_LINK_SPEED_10G; /* Default for SFP+ */ + if (ctx->specific_u.sfp.dual_rate) + ctx->speed_mask |= NT_LINK_SPEED_1G; + if (ctx->port_type == NT_PORT_TYPE_SFP_PLUS_PASSIVE_DAC) + ctx->speed_mask |= NT_LINK_SPEED_1G; + if (ctx->port_type == NT_PORT_TYPE_SFP_PLUS_ACTIVE_DAC) + ctx->speed_mask |= NT_LINK_SPEED_1G; + } else { /* SFP */ + if (ctx->port_type == NT_PORT_TYPE_SFP_FX) { + ctx->speed_mask = NT_LINK_SPEED_100M; + } else { + ctx->speed_mask = NT_LINK_SPEED_1G; /* Default for SFP */ + if (ctx->specific_u.sfp.dual_rate || + ctx->specific_u.sfp.tri_speed) + ctx->speed_mask |= NT_LINK_SPEED_100M; + if (ctx->specific_u.sfp.tri_speed) + ctx->speed_mask |= NT_LINK_SPEED_10M; + } + } + if (ctx->port_type == NT_PORT_TYPE_SFP_28_CR_CA_L || + ctx->port_type == NT_PORT_TYPE_SFP_28_CR_CA_S || + ctx->port_type == NT_PORT_TYPE_SFP_28_CR_CA_N) { + /* Enable multiple speed setting for SFP28 DAC cables */ + ctx->speed_mask = (NT_LINK_SPEED_25G | NT_LINK_SPEED_10G | + NT_LINK_SPEED_1G); + } +} + +static void qsfp28_find_port_params(nim_i2c_ctx_p ctx) +{ + uint8_t fiber_chan_speed; + + /* Table 6-17 SFF-8636 */ + read_data_lin(ctx, QSFP_SPEC_COMPLIANCE_CODES_ADDR, 1, &fiber_chan_speed); + + if (fiber_chan_speed & (1 << 7)) { + /* SFF-8024, Rev 4.7, Table 4-4 */ + uint8_t extended_specification_compliance_code = 0; + + read_data_lin(ctx, QSFP_EXT_SPEC_COMPLIANCE_CODES_ADDR, 1, + &extended_specification_compliance_code); + + switch (extended_specification_compliance_code) { + case 0x02: + ctx->port_type = NT_PORT_TYPE_QSFP28_SR4; + break; + case 0x03: + ctx->port_type = NT_PORT_TYPE_QSFP28_LR4; + break; + case 0x0B: + ctx->port_type = NT_PORT_TYPE_QSFP28_CR_CA_L; + break; + case 0x0C: + ctx->port_type = NT_PORT_TYPE_QSFP28_CR_CA_S; + break; + case 0x0D: + ctx->port_type = NT_PORT_TYPE_QSFP28_CR_CA_N; + break; + case 0x25: + ctx->port_type = NT_PORT_TYPE_QSFP28_DR; + break; + case 0x26: + ctx->port_type = NT_PORT_TYPE_QSFP28_FR; + break; + case 0x27: + ctx->port_type = NT_PORT_TYPE_QSFP28_LR; + break; + default: + ctx->port_type = NT_PORT_TYPE_QSFP28; + } + } else { + ctx->port_type = NT_PORT_TYPE_QSFP28; + } +} + +/* + * If true the user must actively select the desired rate. If false the module + * however can still support several rates without the user is required to select + * one of them. Supported rates must then be deduced from the product number. + * SFF-8636, Rev 2.10a: + * p40: 6.2.7 Rate Select + * p85: A.2 Rate Select + */ +static bool qsfp28_is_rate_selection_enabled(nim_i2c_ctx_p ctx) +{ + const uint8_t ext_rate_select_compl_reg_addr = 141; + const uint8_t options_reg_addr = 195; + const uint8_t enh_options_reg_addr = 221; + + uint8_t rate_select_ena = (read_byte(ctx, options_reg_addr) >> 5) & + 0x01; /* bit: 5 */ + + if (rate_select_ena == 0) + return false; + + uint8_t rate_select_type = (read_byte(ctx, enh_options_reg_addr) >> 2) & + 0x03; /* bit 3..2 */ + + if (rate_select_type != 2) { + NT_LOG(DBG, PMD, "NIM has unhandled rate select type (%d)", + rate_select_type); + return false; + } + + uint8_t ext_rate_select_ver = read_byte(ctx, ext_rate_select_compl_reg_addr) & + 0x03; /* bit 1..0 */ + + if (ext_rate_select_ver != 0x02) { + NT_LOG(DBG, PMD, + "NIM has unhandled extended rate select version (%d)", + ext_rate_select_ver); + return false; + } + + return true; /* When true selectRate() can be used */ +} + +static void qsfp28_set_speed_mask(nim_i2c_ctx_p ctx) +{ + if (ctx->port_type == NT_PORT_TYPE_QSFP28_FR || + ctx->port_type == NT_PORT_TYPE_QSFP28_DR || + ctx->port_type == NT_PORT_TYPE_QSFP28_LR) { + if (ctx->lane_idx < 0) + ctx->speed_mask = NT_LINK_SPEED_100G; + else + ctx->speed_mask = + 0; /* PAM-4 modules can only run on all lanes together */ + } else { + if (ctx->lane_idx < 0) + ctx->speed_mask = NT_LINK_SPEED_100G; + else + ctx->speed_mask = NT_LINK_SPEED_25G; + + if (qsfp28_is_rate_selection_enabled(ctx)) { + /* + * It is assumed that if the module supports dual rates then the other rate + * is 10G per lane or 40G for all lanes. + */ + if (ctx->lane_idx < 0) + ctx->speed_mask |= NT_LINK_SPEED_40G; + else + ctx->speed_mask = NT_LINK_SPEED_10G; + } + } +} + +static void qsfpplus_find_port_params(nim_i2c_ctx_p ctx) +{ + uint8_t device_tech; + + read_data_lin(ctx, QSFP_TRANSMITTER_TYPE_LIN_ADDR, sizeof(device_tech), + &device_tech); + + switch (device_tech & 0xF0) { + case 0xA0: /* Copper cable unequalized */ + case 0xB0: /* Copper cable passive equalized */ + ctx->port_type = NT_PORT_TYPE_QSFP_PASSIVE_DAC; + break; + case 0xC0: /* Copper cable, near and far end limiting active equalizers */ + case 0xD0: /* Copper cable, far end limiting active equalizers */ + case 0xE0: /* Copper cable, near end limiting active equalizers */ + case 0xF0: /* Copper cable, linear active equalizers */ + ctx->port_type = NT_PORT_TYPE_QSFP_ACTIVE_DAC; + break; + default: /* Optical */ + ctx->port_type = NT_PORT_TYPE_QSFP_PLUS; + break; + } +} + +static void qsfpplus_set_speed_mask(nim_i2c_ctx_p ctx) +{ + ctx->speed_mask = (ctx->lane_idx < 0) ? NT_LINK_SPEED_40G : + (NT_LINK_SPEED_10G); +} + +static int sfp_preinit(nim_i2c_ctx_p ctx) +{ + int res = sfp_read_basic_data(ctx); + + if (!res) { + sfp_find_port_params(ctx); + sfp_set_speed_mask(ctx); + } + return res; +} + +static void qsfpplus_construct(nim_i2c_ctx_p ctx, int8_t lane_idx) +{ + assert(lane_idx < 4); + ctx->specific_u.qsfp.qsfp28 = false; + ctx->lane_idx = lane_idx; + ctx->lane_count = 4; +} + +static int qsfpplus_preinit(nim_i2c_ctx_p ctx, int8_t lane_idx) +{ + qsfpplus_construct(ctx, lane_idx); + int res = qsfpplus_read_basic_data(ctx); + + if (!res) { + qsfpplus_find_port_params(ctx); + /* + * If not on the known modules list try to figure out which sensors that are present + */ + if (!qsfpplus_get_qsfp_options_from_pn(ctx)) { + NT_LOG(DBG, NTHW, + "NIM options not known in advance - trying to detect"); + qsfpplus_get_qsfp_options_from_data(ctx); + } + + /* + * Read if TX_DISABLE has been implemented + * For passive optical modules this is required while it for copper and active + * optical modules is optional. Under all circumstances register 195.4 will + * indicate, if TX_DISABLE has been implemented in register 86.0-3 + */ + uint8_t value; + + read_data_lin(ctx, QSFP_OPTION3_LIN_ADDR, sizeof(value), &value); + + ctx->tx_disable = (value & QSFP_OPTION3_TX_DISABLE_BIT) != 0; + + if (ctx->tx_disable) + ctx->options |= (1 << NIM_OPTION_TX_DISABLE); + + /* + * Previously - considering AFBR-89BRDZ - code tried to establish if a module was + * RxOnly by testing the state of the lasers after reset. Lasers were for this + * module default disabled. + * However that code did not work for GigaLight, GQS-MPO400-SR4C so it was + * decided that this option should not be detected automatically but from PN + */ + ctx->specific_u.qsfp.rx_only = + (ctx->options & (1 << NIM_OPTION_RX_ONLY)) != 0; + qsfpplus_set_speed_mask(ctx); + } + return res; +} + +static void qsfp28_wait_for_ready_after_reset(nim_i2c_ctx_p ctx) +{ + uint8_t data; + bool init_complete_flag_present = false; + + /* + * Revision compliance + * 7: SFF-8636 Rev 2.5, 2.6 and 2.7 + * 8: SFF-8636 Rev 2.8, 2.9 and 2.10 + */ + read_data_lin(ctx, 1, + sizeof(ctx->specific_u.qsfp.specific_u.qsfp28.rev_compliance), + &ctx->specific_u.qsfp.specific_u.qsfp28.rev_compliance); + NT_LOG(DBG, NTHW, "NIM RevCompliance = %d", + ctx->specific_u.qsfp.specific_u.qsfp28.rev_compliance); + + /* Wait if lane_idx == -1 (all lanes are used) or lane_idx == 0 (the first lane) */ + if (ctx->lane_idx > 0) + return; + + if (ctx->specific_u.qsfp.specific_u.qsfp28.rev_compliance >= 7) { + /* Check if init complete flag is implemented */ + read_data_lin(ctx, 221, sizeof(data), &data); + init_complete_flag_present = (data & (1 << 4)) != 0; + } + + NT_LOG(DBG, NTHW, "NIM InitCompleteFlagPresent = %d", + init_complete_flag_present); + + /* + * If the init complete flag is not present then wait 500ms that together with 500ms + * after reset (in the adapter code) should be enough to read data from upper pages + * that otherwise would not be ready. Especially BiDi modules AFBR-89BDDZ have been + * prone to this when trying to read sensor options using getQsfpOptionsFromData() + * Probably because access to the paged address space is required. + */ + if (!init_complete_flag_present) { + NT_OS_WAIT_USEC(500000); + return; + } + + /* Otherwise wait for the init complete flag to be set */ + int count = 0; + + while (true) { + if (count > 10) { /* 1 s timeout */ + NT_LOG(WRN, NTHW, "Timeout waiting for module ready"); + break; + } + + read_data_lin(ctx, 6, sizeof(data), &data); + + if (data & 0x01) { + NT_LOG(DBG, NTHW, "Module ready after %dms", + count * 100); + break; + } + + NT_OS_WAIT_USEC(100000); /* 100 ms */ + count++; + } +} + +static void qsfp28_get_fec_options(nim_i2c_ctx_p ctx) +{ + const char *const nim_list[] = { + "AFBR-89BDDZ", /* Avago BiDi */ + "AFBR-89BRDZ", /* Avago BiDi, RxOnly */ + "FTLC4352RKPL", /* Finisar QSFP28-LR */ + "FTLC4352RHPL", /* Finisar QSFP28-DR */ + "FTLC4352RJPL", /* Finisar QSFP28-FR */ + "SFBR-89BDDZ-CS4", /* Foxconn, QSFP28 100G/40G BiDi */ + }; + + for (size_t i = 0; i < ARRAY_SIZE(nim_list); i++) { + if (ctx->prod_no == nim_list[i]) { + ctx->options |= (1 << NIM_OPTION_MEDIA_SIDE_FEC); + ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ena = + true; + NT_LOG(DBG, NTHW, "Found FEC info via PN list"); + return; + } + } + + /* + * For modules not in the list find FEC info via registers + * Read if the module has controllable FEC + * SFF-8636, Rev 2.10a TABLE 6-28 Equalizer, Emphasis, Amplitude and Timing) + * (Page 03h, Bytes 224-229) + */ + uint8_t data; + uint16_t addr = 227 + 3 * 128; + + read_data_lin(ctx, addr, sizeof(data), &data); + + /* Check if the module has FEC support that can be controlled */ + ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ctrl = + (data & (1 << 6)) != 0; + ctx->specific_u.qsfp.specific_u.qsfp28.host_side_fec_ctrl = + (data & (1 << 7)) != 0; + + if (ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ctrl) + ctx->options |= (1 << NIM_OPTION_MEDIA_SIDE_FEC); + + if (ctx->specific_u.qsfp.specific_u.qsfp28.host_side_fec_ctrl) + ctx->options |= (1 << NIM_OPTION_HOST_SIDE_FEC); +} + +static int qsfp28_preinit(nim_i2c_ctx_p ctx, int8_t lane_idx) +{ + int res = qsfpplus_preinit(ctx, lane_idx); + + if (!res) { + qsfp28_wait_for_ready_after_reset(ctx); + memset(&ctx->specific_u.qsfp.specific_u.qsfp28, 0, + sizeof(ctx->specific_u.qsfp.specific_u.qsfp28)); + ctx->specific_u.qsfp.qsfp28 = true; + qsfp28_find_port_params(ctx); + qsfp28_get_fec_options(ctx); + qsfp28_set_speed_mask(ctx); + } + return res; +} + +static void sfp_nim_add_all_sensors(uint8_t m_port_no, nim_i2c_ctx_t *ctx, + struct nim_sensor_group **nim_sensors_ptr, + uint16_t *nim_sensors_cnt) +{ + struct nim_sensor_group *sensor = NULL; + *nim_sensors_cnt = 0; + + if (ctx == NULL || nim_sensors_ptr == NULL) { + NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__); + return; + } + + /* + * If the user has not provided a name for the temperature sensor then apply + * one automatically + */ + if (strlen(sfp_sensors_level0[0].name) == 0) { + if (ctx->specific_u.sfp.sfp28) { + rte_strscpy(sfp_sensors_level0[0].name, "SFP28", + sizeof(sfp_sensors_level0[0].name)); + } else if (ctx->specific_u.sfp.sfpplus) { + rte_strscpy(sfp_sensors_level0[0].name, "SFP+", + sizeof(sfp_sensors_level0[0].name)); + } else { + rte_strscpy(sfp_sensors_level0[0].name, "SFP", + sizeof(sfp_sensors_level0[0].name)); + } + } + + /* allocate temperature sensor */ + nim_sensors_ptr[m_port_no] = allocate_nim_sensor_group(m_port_no, + ctx, + NT_SENSOR_SOURCE_PORT, + &sfp_sensors_level0[0]); + sensor = nim_sensors_ptr[m_port_no]; + sensor->read = &nim_read_sfp_temp; + (*nim_sensors_cnt)++; + + /* voltage */ + sensor->next = allocate_nim_sensor_group(m_port_no, + ctx, + NT_SENSOR_SOURCE_PORT, + &sfp_sensors_level1[0]); + sensor = sensor->next; + sensor->read = &nim_read_sfp_voltage; + (*nim_sensors_cnt)++; + + /* bias current */ + sensor->next = allocate_nim_sensor_group(m_port_no, + ctx, + NT_SENSOR_SOURCE_PORT, + &sfp_sensors_level1[1]); + sensor = sensor->next; + sensor->read = &nim_read_sfp_bias_current; + (*nim_sensors_cnt)++; + + /* tx power */ + sensor->next = allocate_nim_sensor_group(m_port_no, + ctx, + NT_SENSOR_SOURCE_PORT, + &sfp_sensors_level1[2]); + sensor = sensor->next; + sensor->read = &nim_read_sfp_tx_power; + (*nim_sensors_cnt)++; + + /* rx power */ + sensor->next = allocate_nim_sensor_group(m_port_no, + ctx, + NT_SENSOR_SOURCE_PORT, + &sfp_sensors_level1[3]); + sensor = sensor->next; + sensor->read = &nim_read_sfp_rx_power; + (*nim_sensors_cnt)++; +} + +static void +qsfp_plus_nim_add_all_sensors(uint8_t m_port_no, nim_i2c_ctx_t *ctx, + struct nim_sensor_group **nim_sensors_ptr, + uint16_t *nim_sensors_cnt) +{ + struct nim_sensor_group *sensor = NULL; + + if (ctx == NULL || nim_sensors_ptr == NULL) { + NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__); + return; + } + + /* + * If the user has not provided a name for the temperature sensor then apply + * one automatically + */ + if (strlen(qsfp_sensor_level0[0].name) == 0) { + if (ctx->specific_u.qsfp.qsfp28) + rte_strscpy(qsfp_sensor_level0[0].name, "QSFP28", + sizeof(qsfp_sensor_level0[0].name)); + else + rte_strscpy(qsfp_sensor_level0[0].name, "QSFP+", + sizeof(qsfp_sensor_level0[0].name)); + } + + /* temperature sensor */ + nim_sensors_ptr[m_port_no] = allocate_nim_sensor_group(m_port_no, ctx, + NT_SENSOR_SOURCE_PORT, + &qsfp_sensor_level0[0]); + sensor = nim_sensors_ptr[m_port_no]; + sensor->read = &nim_read_qsfp_temp; + (*nim_sensors_cnt)++; + + /* voltage */ + sensor->next = allocate_nim_sensor_group(m_port_no, ctx, + NT_SENSOR_SOURCE_LEVEL1_PORT, + &qsfp_sensor_level1[0]); + sensor = sensor->next; + sensor->read = &nim_read_qsfp_voltage; + (*nim_sensors_cnt)++; + + /* bias current sensors */ + for (uint8_t i = 1; i < 5; i++) { + sensor->next = allocate_nim_sensor_group(m_port_no, ctx, + NT_SENSOR_SOURCE_LEVEL1_PORT, + &qsfp_sensor_level1[i]); + sensor = sensor->next; + sensor->read = &nim_read_qsfp_bias_current; + (*nim_sensors_cnt)++; + } + + /* tx power */ + for (uint8_t i = 5; i < 9; i++) { + sensor->next = allocate_nim_sensor_group(m_port_no, ctx, + NT_SENSOR_SOURCE_LEVEL1_PORT, + &qsfp_sensor_level1[i]); + sensor = sensor->next; + sensor->read = &nim_read_qsfp_tx_power; + (*nim_sensors_cnt)++; + } + + /* rx power */ + for (uint8_t i = 9; i < 13; i++) { + sensor->next = allocate_nim_sensor_group(m_port_no, ctx, + NT_SENSOR_SOURCE_LEVEL1_PORT, + &qsfp_sensor_level1[i]); + sensor = sensor->next; + sensor->read = &nim_read_qsfp_rx_power; + (*nim_sensors_cnt)++; + } +} + +struct nim_sensor_group * +allocate_nim_sensor_group(uint8_t port, struct nim_i2c_ctx *ctx, + enum nt_sensor_source_e ssrc, + struct nt_adapter_sensor_description *sd) +{ + struct nim_sensor_group *sg = malloc(sizeof(struct nim_sensor_group)); + + if (sg == NULL) { + NT_LOG(ERR, ETHDEV, "%s: sensor group is NULL", __func__); + return NULL; + } + sg->sensor = allocate_sensor_by_description(port, ssrc, sd); + sg->ctx = ctx; + sg->next = NULL; + return sg; +} + +int construct_and_preinit_nim(nim_i2c_ctx_p ctx, void *extra, uint8_t port, + struct nim_sensor_group **nim_sensors_ptr, + uint16_t *nim_sensors_cnt) +{ + int res = i2c_nim_common_construct(ctx); + + switch (translate_nimid(ctx)) { + case NT_NIM_SFP_SFP_PLUS: + sfp_preinit(ctx); + sfp_nim_add_all_sensors(port, ctx, nim_sensors_ptr, + nim_sensors_cnt); + break; + case NT_NIM_QSFP_PLUS: + qsfpplus_preinit(ctx, extra ? *(int8_t *)extra : (int8_t)-1); + qsfp_plus_nim_add_all_sensors(port, ctx, nim_sensors_ptr, + nim_sensors_cnt); + break; + case NT_NIM_QSFP28: + qsfp28_preinit(ctx, extra ? *(int8_t *)extra : (int8_t)-1); + qsfp_plus_nim_add_all_sensors(port, ctx, nim_sensors_ptr, + nim_sensors_cnt); + break; + default: + res = 1; + NT_LOG(ERR, NTHW, "NIM type %s is not supported.\n", + nim_id_to_text(ctx->nim_id)); + } + + return res; +} diff --git a/drivers/net/ntnic/nim/i2c_nim.h b/drivers/net/ntnic/nim/i2c_nim.h new file mode 100644 index 0000000000..f664e6b7ee --- /dev/null +++ b/drivers/net/ntnic/nim/i2c_nim.h @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef I2C_NIM_H_ +#define I2C_NIM_H_ + +#include "nthw_drv.h" +#include "nim_defines.h" +#include "nt_link_speed.h" + +#include "sensors.h" + +typedef struct sfp_nim_state { + uint8_t br; /* bit rate, units of 100 MBits/sec */ +} sfp_nim_state_t, *sfp_nim_state_p; + +typedef struct nim_i2c_ctx { + nthw_iic_t hwiic; /* depends on *Fpga_t, instance number, and cycle time */ + uint8_t instance; + uint8_t devaddr; + uint8_t regaddr; + uint8_t nim_id; + nt_port_type_t port_type; + + char vendor_name[17]; + char prod_no[17]; + char serial_no[17]; + char date[9]; + char rev[5]; + bool avg_pwr; + bool content_valid; + uint8_t pwr_level_req; + uint8_t pwr_level_cur; + uint16_t len_info[5]; + uint32_t speed_mask; /* Speeds supported by the NIM */ + int8_t lane_idx; /* Is this associated with a single lane or all lanes (-1) */ + uint8_t lane_count; + uint32_t options; + bool tx_disable; + bool dmi_supp; + + union { + struct { + bool sfp28; + bool sfpplus; + bool dual_rate; + bool hw_rate_sel; + bool sw_rate_sel; + bool cu_type; + bool tri_speed; + bool ext_cal; + bool addr_chg; + } sfp; + + struct { + bool rx_only; + bool qsfp28; + union { + struct { + uint8_t rev_compliance; + bool media_side_fec_ctrl; + bool host_side_fec_ctrl; + bool media_side_fec_ena; + bool host_side_fec_ena; + } qsfp28; + } specific_u; + } qsfp; + + } specific_u; +} nim_i2c_ctx_t, *nim_i2c_ctx_p; + +struct nim_sensor_group { + struct nt_adapter_sensor *sensor; + void (*read)(struct nim_sensor_group *sg, nthw_spis_t *t_spi); + struct nim_i2c_ctx *ctx; + struct nim_sensor_group *next; +}; + +struct nim_sensor_group * +allocate_nim_sensor_group(uint8_t port, struct nim_i2c_ctx *ctx, + enum nt_sensor_source_e ssrc, + struct nt_adapter_sensor_description *sd); + +/* + * Utility functions + */ + +nt_nim_identifier_t translate_nimid(const nim_i2c_ctx_t *ctx); + +/* + * Builds an nim state for the port implied by `ctx`, returns zero + * if successful, and non-zero otherwise. SFP and QSFP nims are supported + */ +int nim_state_build(nim_i2c_ctx_t *ctx, sfp_nim_state_t *state); + +/* + * Returns a type name such as "SFP/SFP+" for a given NIM type identifier, + * or the string "ILLEGAL!". + */ +const char *nim_id_to_text(uint8_t nim_id); + +int nim_sfp_nim_set_tx_laser_disable(nim_i2c_ctx_p ctx, bool disable); + +int nim_qsfp_plus_nim_set_tx_laser_disable(nim_i2c_ctx_t *ctx, bool disable, + int lane_idx); + +int nim_set_link_speed(nim_i2c_ctx_p ctx, nt_link_speed_t speed); + +/* + * This function tries to classify NIM based on it's ID and some register reads + * and collects information into ctx structure. The @extra parameter could contain + * the initialization argument for specific type of NIMS. + */ +int construct_and_preinit_nim(nim_i2c_ctx_p ctx, void *extra, uint8_t port, + struct nim_sensor_group **nim_sensors_ptr, + uint16_t *nim_sensors_cnt); + +int read_data_lin(nim_i2c_ctx_p ctx, uint16_t lin_addr, uint16_t length, + void *data); + +#endif /* I2C_NIM_H_ */ diff --git a/drivers/net/ntnic/nim/nim_defines.h b/drivers/net/ntnic/nim/nim_defines.h new file mode 100644 index 0000000000..da3567d073 --- /dev/null +++ b/drivers/net/ntnic/nim/nim_defines.h @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NIM_DEFINES_H_ +#define NIM_DEFINES_H_ + +#define NIM_IDENTIFIER_ADDR 0 /* 1 byte */ + +#define SFP_BIT_RATE_ADDR 12 /* 1 byte */ +#define SFP_VENDOR_NAME_ADDR 20 /* 16bytes */ +#define SFP_VENDOR_PN_ADDR 40 /* 16bytes */ +#define SFP_VENDOR_REV_ADDR 56 /* 4bytes */ +#define SFP_VENDOR_SN_ADDR 68 /* 16bytes */ +#define SFP_VENDOR_DATE_ADDR 84 /* 8bytes */ + +#define SFP_CONTROL_STATUS_LIN_ADDR (110U + 256U) /* 0xA2 */ +#define SFP_SOFT_TX_DISABLE_BIT (1U << 6) + +#define QSFP_EXTENDED_IDENTIFIER 129 +#define QSFP_SUP_LEN_INFO_ADDR 142 /* 5bytes */ +#define QSFP_TRANSMITTER_TYPE_ADDR 147 /* 1byte */ +#define QSFP_VENDOR_NAME_ADDR 148 /* 16bytes */ +#define QSFP_VENDOR_PN_ADDR 168 /* 16bytes */ +#define QSFP_VENDOR_REV_ADDR 184 /* 2bytes */ +#define QSFP_VENDOR_SN_ADDR 196 /* 16bytes */ +#define QSFP_VENDOR_DATE_ADDR 212 /* 8bytes */ + +/* I2C addresses */ +#define nim_i2c_0xa0 0xA0 /* Basic I2C address */ +#define nim_i2c_0xa2 0xA2 /* Diagnostic monitoring */ +#define nim_i2c_0xac 0xAC /* Address of integrated PHY */ + +typedef enum { + NIM_OPTION_TEMP = 0, + NIM_OPTION_SUPPLY, + NIM_OPTION_RX_POWER, + NIM_OPTION_TX_BIAS, + NIM_OPTION_TX_POWER, + NIM_OPTION_TX_DISABLE, + /* Indicates that the module should be checked for the two next FEC types */ + NIM_OPTION_FEC, + NIM_OPTION_MEDIA_SIDE_FEC, + NIM_OPTION_HOST_SIDE_FEC, + NIM_OPTION_RX_ONLY +} nim_option_t; + +enum nt_nim_identifier_e { + NT_NIM_UNKNOWN = 0x00, /* Nim type is unknown */ + NT_NIM_GBIC = 0x01, /* Nim type = GBIC */ + NT_NIM_FIXED = 0x02, /* Nim type = FIXED */ + NT_NIM_SFP_SFP_PLUS = 0x03, /* Nim type = SFP/SFP+ */ + NT_NIM_300_PIN_XBI = 0x04, /* Nim type = 300 pin XBI */ + NT_NIM_XEN_PAK = 0x05, /* Nim type = XEN-PAK */ + NT_NIM_XFP = 0x06, /* Nim type = XFP */ + NT_NIM_XFF = 0x07, /* Nim type = XFF */ + NT_NIM_XFP_E = 0x08, /* Nim type = XFP-E */ + NT_NIM_XPAK = 0x09, /* Nim type = XPAK */ + NT_NIM_X2 = 0x0A, /* Nim type = X2 */ + NT_NIM_DWDM = 0x0B, /* Nim type = DWDM */ + NT_NIM_QSFP = 0x0C, /* Nim type = QSFP */ + NT_NIM_QSFP_PLUS = 0x0D, /* Nim type = QSFP+ */ + NT_NIM_QSFP28 = 0x11, /* Nim type = QSFP28 */ + NT_NIM_CFP4 = 0x12, /* Nim type = CFP4 */ +}; + +typedef enum nt_nim_identifier_e nt_nim_identifier_t; + +/* + * Port types + * The use of all non-generic XX_NOT_PRESENT is deprecated - use + * NT_PORT_TYPE_NIM_NOT_PRESENT instead + */ +enum nt_port_type_e { + NT_PORT_TYPE_NOT_AVAILABLE = + 0, /* The NIM/port type is not available (unknown) */ + NT_PORT_TYPE_NOT_RECOGNISED, /* The NIM/port type not recognized */ + NT_PORT_TYPE_RJ45, /* RJ45 type */ + NT_PORT_TYPE_SFP_NOT_PRESENT, /* SFP type but slot is empty */ + NT_PORT_TYPE_SFP_SX, /* SFP SX */ + NT_PORT_TYPE_SFP_SX_DD, /* SFP SX digital diagnostic */ + NT_PORT_TYPE_SFP_LX, /* SFP LX */ + NT_PORT_TYPE_SFP_LX_DD, /* SFP LX digital diagnostic */ + NT_PORT_TYPE_SFP_ZX, /* SFP ZX */ + NT_PORT_TYPE_SFP_ZX_DD, /* SFP ZX digital diagnostic */ + NT_PORT_TYPE_SFP_CU, /* SFP copper */ + NT_PORT_TYPE_SFP_CU_DD, /* SFP copper digital diagnostic */ + NT_PORT_TYPE_SFP_NOT_RECOGNISED, /* SFP unknown */ + NT_PORT_TYPE_XFP, /* XFP */ + NT_PORT_TYPE_XPAK, /* XPAK */ + NT_PORT_TYPE_SFP_CU_TRI_SPEED, /* SFP copper tri-speed */ + NT_PORT_TYPE_SFP_CU_TRI_SPEED_DD, /* SFP copper tri-speed digital diagnostic */ + NT_PORT_TYPE_SFP_PLUS, /* SFP+ type */ + NT_PORT_TYPE_SFP_PLUS_NOT_PRESENT, /* SFP+ type but slot is empty */ + NT_PORT_TYPE_XFP_NOT_PRESENT, /* XFP type but slot is empty */ + NT_PORT_TYPE_QSFP_PLUS_NOT_PRESENT, /* QSFP type but slot is empty */ + NT_PORT_TYPE_QSFP_PLUS, /* QSFP type */ + NT_PORT_TYPE_SFP_PLUS_PASSIVE_DAC, /* SFP+ Passive DAC */ + NT_PORT_TYPE_SFP_PLUS_ACTIVE_DAC, /* SFP+ Active DAC */ + NT_PORT_TYPE_CFP4, /* CFP4 type */ + NT_PORT_TYPE_CFP4_LR4 = NT_PORT_TYPE_CFP4, /* CFP4 100G, LR4 type */ + NT_PORT_TYPE_CFP4_NOT_PRESENT, /* CFP4 type but slot is empty */ + NT_PORT_TYPE_INITIALIZE, /* The port type is not fully established yet */ + NT_PORT_TYPE_NIM_NOT_PRESENT, /* Generic "Not present" */ + NT_PORT_TYPE_HCB, /* Test mode: Host Compliance Board */ + NT_PORT_TYPE_NOT_SUPPORTED, /* The NIM type is not supported in this context */ + NT_PORT_TYPE_SFP_PLUS_DUAL_RATE, /* SFP+ supports 1G/10G */ + NT_PORT_TYPE_CFP4_SR4, /* CFP4 100G, SR4 type */ + NT_PORT_TYPE_QSFP28_NOT_PRESENT, /* QSFP28 type but slot is empty */ + NT_PORT_TYPE_QSFP28, /* QSFP28 type */ + NT_PORT_TYPE_QSFP28_SR4, /* QSFP28-SR4 type */ + NT_PORT_TYPE_QSFP28_LR4, /* QSFP28-LR4 type */ + /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */ + NT_PORT_TYPE_QSFP_PLUS_4X10, + /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */ + NT_PORT_TYPE_QSFP_PASSIVE_DAC_4X10, + NT_PORT_TYPE_QSFP_PASSIVE_DAC = + NT_PORT_TYPE_QSFP_PASSIVE_DAC_4X10, /* QSFP passive DAC type */ + /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */ + NT_PORT_TYPE_QSFP_ACTIVE_DAC_4X10, + NT_PORT_TYPE_QSFP_ACTIVE_DAC = + NT_PORT_TYPE_QSFP_ACTIVE_DAC_4X10, /* QSFP active DAC type */ + NT_PORT_TYPE_SFP_28, /* SFP28 type */ + NT_PORT_TYPE_SFP_28_SR, /* SFP28-SR type */ + NT_PORT_TYPE_SFP_28_LR, /* SFP28-LR type */ + NT_PORT_TYPE_SFP_28_CR_CA_L, /* SFP28-CR-CA-L type */ + NT_PORT_TYPE_SFP_28_CR_CA_S, /* SFP28-CR-CA-S type */ + NT_PORT_TYPE_SFP_28_CR_CA_N, /* SFP28-CR-CA-N type */ + NT_PORT_TYPE_QSFP28_CR_CA_L, /* QSFP28-CR-CA-L type */ + NT_PORT_TYPE_QSFP28_CR_CA_S, /* QSFP28-CR-CA-S type */ + NT_PORT_TYPE_QSFP28_CR_CA_N, /* QSFP28-CR-CA-N type */ + NT_PORT_TYPE_SFP_28_SR_DR, /* SFP28-SR-DR type */ + NT_PORT_TYPE_SFP_28_LR_DR, /* SFP28-LR-DR type */ + NT_PORT_TYPE_SFP_FX, /* SFP FX */ + NT_PORT_TYPE_SFP_PLUS_CU, /* SFP+ CU type */ + /* QSFP28-FR type. Uses PAM4 modulation on one lane only */ + NT_PORT_TYPE_QSFP28_FR, + /* QSFP28-DR type. Uses PAM4 modulation on one lane only */ + NT_PORT_TYPE_QSFP28_DR, + /* QSFP28-LR type. Uses PAM4 modulation on one lane only */ + NT_PORT_TYPE_QSFP28_LR, +}; + +typedef enum nt_port_type_e nt_port_type_t, *nt_port_type_p; + +#endif /* NIM_DEFINES_H_ */ diff --git a/drivers/net/ntnic/nim/nt_link_speed.c b/drivers/net/ntnic/nim/nt_link_speed.c new file mode 100644 index 0000000000..35c75f5e56 --- /dev/null +++ b/drivers/net/ntnic/nim/nt_link_speed.c @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include + +#include "nt_link_speed.h" + +const char *nt_translate_link_speed(nt_link_speed_t link_speed) +{ + switch (link_speed) { + case NT_LINK_SPEED_UNKNOWN: + return "NotAvail"; + case NT_LINK_SPEED_10M: + return "10M"; + case NT_LINK_SPEED_100M: + return "100M"; + case NT_LINK_SPEED_1G: + return "1G"; + case NT_LINK_SPEED_10G: + return "10G"; + case NT_LINK_SPEED_25G: + return "25G"; + case NT_LINK_SPEED_40G: + return "40G"; + case NT_LINK_SPEED_50G: + return "50G"; + case NT_LINK_SPEED_100G: + return "100G"; + default: + /* DEBUG assert: remind developer that a switch/case entry is needed here.... */ + assert(false); + return "Unhandled"; + } +} + +uint64_t nt_get_link_speed(nt_link_speed_t e_link_speed) +{ + uint64_t n_link_speed = 0ULL; + + switch (e_link_speed) { + case NT_LINK_SPEED_UNKNOWN: + n_link_speed = 0UL; + break; + case NT_LINK_SPEED_10M: + n_link_speed = (10ULL * 1000ULL * 1000ULL); + break; + case NT_LINK_SPEED_100M: + n_link_speed = (100ULL * 1000ULL * 1000ULL); + break; + case NT_LINK_SPEED_1G: + n_link_speed = (1ULL * 1000ULL * 1000ULL * 1000ULL); + break; + case NT_LINK_SPEED_10G: + n_link_speed = (10ULL * 1000ULL * 1000ULL * 1000ULL); + break; + case NT_LINK_SPEED_25G: + n_link_speed = (25ULL * 1000ULL * 1000ULL * 1000ULL); + break; + case NT_LINK_SPEED_40G: + n_link_speed = (40ULL * 1000ULL * 1000ULL * 1000ULL); + break; + case NT_LINK_SPEED_50G: + n_link_speed = (50ULL * 1000ULL * 1000ULL * 1000ULL); + break; + case NT_LINK_SPEED_100G: + n_link_speed = (100ULL * 1000ULL * 1000ULL * 1000ULL); + break; + default: + /* DEBUG assert: remind developer that a switch/case entry is needed here.... */ + assert(false); + n_link_speed = 0UL; + break; + } + return n_link_speed; +} + +const char *nt_translate_link_speed_mask(uint32_t link_speed_mask, char *buffer, + uint32_t length) +{ + size_t len = 0; + + buffer[0] = 0; + + for (int i = 0; i < 32; i++) { + if ((1U << i) & link_speed_mask) { + len = strlen(buffer); + + if (len > 0) { + if ((length - len - 1) > 2) { + strncat(buffer, ", ", length); + len = strlen(buffer); + } + } + + if (len < (length - 1)) + strncat(buffer, nt_translate_link_speed(1 << i), + length); + } + } + + return buffer; +} diff --git a/drivers/net/ntnic/nim/nt_link_speed.h b/drivers/net/ntnic/nim/nt_link_speed.h new file mode 100644 index 0000000000..969e3fb867 --- /dev/null +++ b/drivers/net/ntnic/nim/nt_link_speed.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NT_LINK_SPEED_H_ +#define NT_LINK_SPEED_H_ + +#include + +/* + * Link speed. + * Note this is a bitmask. + */ +enum nt_link_speed_e { + NT_LINK_SPEED_UNKNOWN = 0, + NT_LINK_SPEED_10M = 0x01, /* 10 Mbps */ + NT_LINK_SPEED_100M = 0x02, /* 100 Mbps */ + NT_LINK_SPEED_1G = 0x04, /* 1 Gbps (Autoneg only) */ + NT_LINK_SPEED_10G = 0x08, /* 10 Gbps (Autoneg only) */ + NT_LINK_SPEED_40G = 0x10, /* 40 Gbps (Autoneg only) */ + NT_LINK_SPEED_100G = 0x20, /* 100 Gbps (Autoneg only) */ + NT_LINK_SPEED_50G = 0x40, /* 50 Gbps (Autoneg only) */ + NT_LINK_SPEED_25G = 0x80, /* 25 Gbps (Autoneg only) */ + NT_LINK_SPEED_END /* always keep this entry as the last in enum */ +}; + +typedef enum nt_link_speed_e nt_link_speed_t; + +const char *nt_translate_link_speed(nt_link_speed_t link_speed); +const char *nt_translate_link_speed_mask(uint32_t link_speed_mask, char *buffer, + uint32_t length); +uint64_t nt_get_link_speed(nt_link_speed_t e_link_speed); + +#endif /* NT_LINK_SPEED_H_ */ diff --git a/drivers/net/ntnic/nim/qsfp_registers.h b/drivers/net/ntnic/nim/qsfp_registers.h new file mode 100644 index 0000000000..366dcbf06e --- /dev/null +++ b/drivers/net/ntnic/nim/qsfp_registers.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _QSFP_REGISTERS_H +#define _QSFP_REGISTERS_H + +/* + * QSFP Registers + */ +#define QSFP_INT_STATUS_RX_LOS_ADDR 3 +#define QSFP_TEMP_LIN_ADDR 22 +#define QSFP_VOLT_LIN_ADDR 26 +#define QSFP_RX_PWR_LIN_ADDR 34 /* uint16_t [0..3] */ +#define QSFP_TX_BIAS_LIN_ADDR 42 /* uint16_t [0..3] */ +#define QSFP_TX_PWR_LIN_ADDR 50 /* uint16_t [0..3] */ + +#define QSFP_CONTROL_STATUS_LIN_ADDR 86 +#define QSFP_SOFT_TX_ALL_DISABLE_BITS 0x0F + +#define QSFP_EXTENDED_IDENTIFIER 129 +#define QSFP_POWER_CLASS_BITS_1_4 0xC0 +#define QSFP_POWER_CLASS_BITS_5_7 0x03 + +#define QSFP_SUP_LEN_INFO_LIN_ADDR 142 /* 5bytes */ +#define QSFP_TRANSMITTER_TYPE_LIN_ADDR 147 /* 1byte */ +#define QSFP_VENDOR_NAME_LIN_ADDR 148 /* 16bytes */ +#define QSFP_VENDOR_PN_LIN_ADDR 168 /* 16bytes */ +#define QSFP_VENDOR_SN_LIN_ADDR 196 /* 16bytes */ +#define QSFP_VENDOR_DATE_LIN_ADDR 212 /* 8bytes */ +#define QSFP_VENDOR_REV_LIN_ADDR 184 /* 2bytes */ + +#define QSFP_SPEC_COMPLIANCE_CODES_ADDR 131 /* 8 bytes */ +#define QSFP_EXT_SPEC_COMPLIANCE_CODES_ADDR 192 /* 1 byte */ + +#define QSFP_OPTION3_LIN_ADDR 195 +#define QSFP_OPTION3_TX_DISABLE_BIT (1 << 4) + +#define QSFP_DMI_OPTION_LIN_ADDR 220 +#define QSFP_DMI_AVG_PWR_BIT (1 << 3) + +#define QSFP_TEMP_THRESH_LIN_ADDR (128 + (3 * 128)) /* Page 3 */ +/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */ + +#define QSFP_VOLT_THRESH_LIN_ADDR (144 + (3 * 128)) /* Page 3 */ +/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */ + +#define QSFP_RX_PWR_THRESH_LIN_ADDR (176 + (3 * 128)) /* Page 3 */ +/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */ + +#define QSFP_BIAS_THRESH_LIN_ADDR (184 + (3 * 128)) /* Page 3 */ +/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */ + +#define QSFP_TX_PWR_THRESH_LIN_ADDR (192 + (3 * 128)) /* Page 3 */ +/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */ + +#endif /* _QSFP_REGISTERS_H */ diff --git a/drivers/net/ntnic/nim/qsfp_sensors.c b/drivers/net/ntnic/nim/qsfp_sensors.c new file mode 100644 index 0000000000..8264f8fb62 --- /dev/null +++ b/drivers/net/ntnic/nim/qsfp_sensors.c @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include + +#include "qsfp_sensors.h" + +#include "ntlog.h" +#include "qsfp_registers.h" + +static bool qsfp_plus_nim_get_sensor(nim_i2c_ctx_p ctx, uint16_t addr, + nim_option_t nim_option, uint8_t count, + uint16_t *p_lane_values) +{ + (void)nim_option; + + read_data_lin(ctx, addr, (uint16_t)(sizeof(uint16_t) * count), + p_lane_values); + + for (int i = 0; i < count; i++) { + *p_lane_values = (*p_lane_values); /* Swap to little endian */ + +#ifdef NIM_DMI_TEST_VALUE + if (nim_option == NIM_OPTION_RX_POWER) + *p_lane_values = (uint16_t)NIM_DMI_RX_PWR_TEST_VALUE; + else + *p_lane_values = (uint16_t)NIM_DMI_TEST_VALUE; +#endif + + p_lane_values++; + } + + return true; +} + +/* + * Read NIM temperature + */ +static bool qsfp_plus_nim_get_temperature(nim_i2c_ctx_p ctx, int16_t *p_value) +{ + return qsfp_plus_nim_get_sensor(ctx, QSFP_TEMP_LIN_ADDR, NIM_OPTION_TEMP, + 1, (uint16_t *)p_value); +} + +/* + * Read NIM supply voltage + */ +static bool qsfp_plus_nim_get_supply_voltage(nim_i2c_ctx_p ctx, uint16_t *p_value) +{ + return qsfp_plus_nim_get_sensor(ctx, QSFP_VOLT_LIN_ADDR, + NIM_OPTION_SUPPLY, 1, p_value); +} + +/* + * Read NIM bias current for four lanes + */ +static bool qsfp_plus_nim_get_tx_bias_current(nim_i2c_ctx_p ctx, uint16_t *p_value) +{ + return qsfp_plus_nim_get_sensor(ctx, QSFP_TX_BIAS_LIN_ADDR, + NIM_OPTION_TX_BIAS, 4, p_value); +} + +/* + * Read NIM TX optical power for four lanes + */ +static bool qsfp_plus_nim_get_tx_power(nim_i2c_ctx_p ctx, uint16_t *p_value) +{ + return qsfp_plus_nim_get_sensor(ctx, QSFP_TX_PWR_LIN_ADDR, + NIM_OPTION_TX_POWER, 4, p_value); +} + +/* + * Read NIM RX optical power for four lanes + */ +static bool qsfp_plus_nim_get_rx_power(nim_i2c_ctx_p ctx, uint16_t *p_value) +{ + return qsfp_plus_nim_get_sensor(ctx, QSFP_TX_PWR_LIN_ADDR, + NIM_OPTION_RX_POWER, 4, p_value); +} + +void nim_read_qsfp_temp(struct nim_sensor_group *sg, nthw_spis_t *t_spi) +{ + int16_t res; + (void)t_spi; + + if (sg == NULL || sg->ctx == NULL) { + NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__); + return; + } + + if (qsfp_plus_nim_get_temperature(sg->ctx, &res)) + update_sensor_value(sg->sensor, (int)(res * 10 / 256)); + + else + update_sensor_value(sg->sensor, -1); +} + +void nim_read_qsfp_voltage(struct nim_sensor_group *sg, nthw_spis_t *t_spi) +{ + uint16_t res; + (void)t_spi; + + if (sg == NULL || sg->ctx == NULL) { + NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__); + return; + } + + if (qsfp_plus_nim_get_supply_voltage(sg->ctx, &res)) + update_sensor_value(sg->sensor, (int)((res) / 10)); + + else + update_sensor_value(sg->sensor, -1); +} + +void nim_read_qsfp_bias_current(struct nim_sensor_group *sg, nthw_spis_t *t_spi) +{ + uint16_t temp[4] = { 0 }; + (void)t_spi; + + if (sg == NULL || sg->ctx == NULL) { + NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__); + return; + } + + bool res = qsfp_plus_nim_get_tx_bias_current(sg->ctx, temp); + + if (res) { + for (uint8_t i = 0; i < sg->ctx->lane_count; i++) + update_sensor_value(sg->sensor, (int)temp[i] * 2); + } else { + update_sensor_value(sg->sensor, -1); + } +} + +void nim_read_qsfp_tx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi) +{ + uint16_t temp[4] = { 0 }; + (void)t_spi; + + if (sg == NULL || sg->ctx == NULL) { + NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__); + return; + } + + bool res = qsfp_plus_nim_get_tx_power(sg->ctx, temp); + + if (res) { + for (uint8_t i = 0; i < sg->ctx->lane_count; i++) + update_sensor_value(sg->sensor, (int)temp[i]); + } else { + update_sensor_value(sg->sensor, -1); + } +} + +void nim_read_qsfp_rx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi) +{ + uint16_t temp[4] = { 0 }; + (void)t_spi; + + if (sg == NULL || sg->ctx == NULL) { + NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__); + return; + } + + bool res = qsfp_plus_nim_get_rx_power(sg->ctx, temp); + + if (res) { + for (uint8_t i = 0; i < sg->ctx->lane_count; i++) + update_sensor_value(sg->sensor, (int)temp[i]); + } else { + update_sensor_value(sg->sensor, -1); + } +} diff --git a/drivers/net/ntnic/nim/qsfp_sensors.h b/drivers/net/ntnic/nim/qsfp_sensors.h new file mode 100644 index 0000000000..de64b978cb --- /dev/null +++ b/drivers/net/ntnic/nim/qsfp_sensors.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _QSFP_H +#define _QSFP_H + +#include "sensors.h" +#include "i2c_nim.h" + +/* Read functions */ +void nim_read_qsfp_temp(struct nim_sensor_group *sg, nthw_spis_t *t_spi); +void nim_read_qsfp_voltage(struct nim_sensor_group *sg, nthw_spis_t *t_spi); +void nim_read_qsfp_bias_current(struct nim_sensor_group *sg, nthw_spis_t *t_spi); +void nim_read_qsfp_tx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi); +void nim_read_qsfp_rx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi); + +#endif /* _QSFP_H */ diff --git a/drivers/net/ntnic/nim/sfp_p_registers.h b/drivers/net/ntnic/nim/sfp_p_registers.h new file mode 100644 index 0000000000..a0fbe2afd7 --- /dev/null +++ b/drivers/net/ntnic/nim/sfp_p_registers.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _SFP_P_REG_H +#define _SFP_P_REG_H + +/* + * SFP/SFP+ Registers + */ +#define SFP_GB_ETH_COMP_CODES_LIN_ADDR 6 +#define SFP_GB_ETH_COMP_1000BASET_BIT (1 << 3) +#define SFP_GB_ETH_COMP_1000BASECX_BIT (1 << 2) +#define SFP_GB_ETH_COMP_1000BASELX_BIT (1 << 1) +#define SFP_GB_ETH_COMP_1000BASESX_BIT (1 << 0) + +#define SFP_FIBER_CHAN_TRANS_TECH_LIN_ADDR 8 +#define SFP_FIBER_CHAN_TRANS_TECH_ACTIVE_CU_BIT (1 << 3) +#define SFP_FIBER_CHAN_TRANS_TECH_PASSIVE_CU_BIT (1 << 2) + +#define SFP_FIBER_CHAN_TRANS_MEDIA_LIN_ADDR 9 +#define SFP_FIBER_CHAN_TRANS_MEDIA_MM62_BIT (1 << 3) +#define SFP_FIBER_CHAN_TRANS_MEDIA_MM50_BIT (1 << 2) +#define SFP_FIBER_CHAN_TRANS_MEDIA_SM_BIT (1 << 0) + +#define SFP_CU_LINK_LEN_LIN_ADDR 18 /* 1byte */ +#define SFP_SUP_LEN_INFO_LIN_ADDR 14 /* 5bytes */ +#define SFP_CU_LINK_LEN_LIN_ADDR 18 /* 1byte */ +#define SFP_VENDOR_NAME_LIN_ADDR 20 /* 16bytes */ +#define SFP_VENDOR_PN_LIN_ADDR 40 /* 16bytes */ +#define SFP_VENDOR_REV_LIN_ADDR 56 /* 4bytes */ +#define SFP_VENDOR_SN_LIN_ADDR 68 /* 16bytes */ +#define SFP_VENDOR_DATE_LIN_ADDR 84 /* 8bytes */ + +/* The following field is only relevant to SFP+ and is marked as reserved for SFP */ +#define SFP_OPTION0_LIN_ADDR 64 +#define SFP_POWER_LEVEL2_REQ_BIT (1 << 1) + +#define SFP_DMI_OPTION_LIN_ADDR (92) +#define SFP_DMI_IMPL_BIT (1 << 6) +#define SFP_DMI_EXT_CAL_BIT (1 << 4) +#define SFP_DMI_AVG_PWR_BIT (1 << 3) +#define SFP_DMI_ADDR_CHG_BIT (1 << 2) + +#define SFP_ENHANCED_OPTIONS_LIN_ADDR (93) +#define SFP_SOFT_TX_FAULT_IMPL_BIT (1 << 5) +#define SFP_SOFT_TX_DISABLE_IMPL_BIT (1 << 6) + +#define SFP_SFF8472_COMPLIANCE_LIN_ADDR 94 + +#define SFP_TEMP_THRESH_LIN_ADDR (0 + 256) +/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */ + +#define SFP_VOLT_THRESH_LIN_ADDR (8 + 256) +/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */ + +#define SFP_TX_BIAS_THRESH_LIN_ADDR (16 + 256) +/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */ + +#define SFP_TX_PWR_THRESH_LIN_ADDR (24 + 256) +/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */ + +#define SFP_RX_PWR_THRESH_LIN_ADDR (32 + 256) +/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */ + +/* Calibration data addresses */ +#define SFP_RX_PWR_COEFF_LIN_ADDR (56 + 256) /* 5 x 32bit float values */ + +#define SFP_TX_BIAS_SLOPE_LIN_ADDR (76 + 256) +#define SFP_TX_BIAS_OFFSET_LIN_ADDR (78 + 256) + +#define SFP_TX_PWR_SLOPE_LIN_ADDR (80 + 256) +#define SFP_TX_PWR_OFFSET_LIN_ADDR (82 + 256) + +#define SFP_TEMP_SLOPE_LIN_ADDR (84 + 256) +#define SFP_TEMP_OFFSET_LIN_ADDR (86 + 256) + +#define SFP_VOLT_SLOPE_LIN_ADDR (88 + 256) +#define SFP_VOLT_OFFSET_LIN_ADDR (90 + 256) + +/* Live data */ +#define SFP_TEMP_LIN_ADDR (96 + 256) +#define SFP_VOLT_LIN_ADDR (98 + 256) +#define SFP_TX_BIAS_LIN_ADDR (100 + 256) +#define SFP_TX_PWR_LIN_ADDR (102 + 256) +#define SFP_RX_PWR_LIN_ADDR (104 + 256) + +#define SFP_SOFT_RATE0_BIT (1 << 3) +#define SFP_TX_FAULT_SET_BIT (1 << 2) + +#define SFP_EXT_CTRL_STAT0_LIN_ADDR (118 + 256) /* 0xA2 area */ +#define SFP_SOFT_RATE1_BIT (1 << 3) +#define SFP_POWER_LEVEL2_GET_BIT (1 << 1) /* For reading the actual level */ +#define SFP_POWER_LEVEL2_SET_BIT (1 << 0) /* For setting the wanted level */ + +/* PHY addresses */ +#define SFP_PHY_LIN_ADDR (12 * 128) +#define SFP_PHY_LIN_RNG 32 /* 16bit words */ + +#endif /* _SFP_P_REG_H */ diff --git a/drivers/net/ntnic/nim/sfp_sensors.c b/drivers/net/ntnic/nim/sfp_sensors.c new file mode 100644 index 0000000000..766d6feaf3 --- /dev/null +++ b/drivers/net/ntnic/nim/sfp_sensors.c @@ -0,0 +1,288 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include + +#include "ntlog.h" +#include "sfp_sensors.h" + +#include "sfp_p_registers.h" + +/* + * Return calibrated data from an SFP module. + * It is first investigated if external calibration is to be used and if it is + * calibration data is retrieved. The function can only be used when calibration + * consists of a slope and offset factor. After function return p_data will point + * to 16bit data that can be either signed or unsigned. + */ +static bool sfp_nim_get_dmi_data(uint16_t data_addr, uint16_t slope_addr, + uint16_t offset_addr, void *p_value, + bool signed_data, nim_i2c_ctx_p ctx) +{ + int32_t value; + uint16_t slope = 1; + int16_t offset = 0; + + if (!ctx->dmi_supp) + return false; + + /* Read data in big endian format */ + read_data_lin(ctx, data_addr, 2, p_value); + *(uint16_t *)p_value = + htons(*(uint16_t *)p_value); /* Swap to little endian */ + + /* + * Inject test value which can be both signed and unsigned but handle + * here as unsigned + */ +#ifdef NIM_DMI_TEST_VALUE + *(uint16_t *)p_value = (uint16_t)NIM_DMI_TEST_VALUE; +#endif + +#if defined(NIM_DMI_TEST_SLOPE) || defined(NIM_DMI_TEST_OFFSET) + ctx->specific_u.sfp.ext_cal = true; +#endif + + if (ctx->specific_u.sfp.ext_cal) { + /* External calibration is needed */ + read_data_lin(ctx, slope_addr, sizeof(slope), &slope); + read_data_lin(ctx, offset_addr, sizeof(offset), &offset); + + /* Swap calibration to little endian */ + slope = htons(slope); + offset = htons(offset); + +#ifdef NIM_DMI_TEST_SLOPE + slope = NIM_DMI_TEST_SLOPE; +#endif + +#ifdef NIM_DMI_TEST_OFFSET + offset = NIM_DMI_TEST_OFFSET; /* 0x0140 equals 1.25 */ +#endif + + if (signed_data) { + value = *(int16_t *)p_value * slope / 256 + offset; + + if (value > INT16_MAX) + value = INT16_MAX; + else if (value < INT16_MIN) + value = INT16_MIN; + + *(int16_t *)p_value = (int16_t)value; + } else { + value = *(uint16_t *)p_value * slope / 256 + offset; + + if (value > UINT16_MAX) + value = UINT16_MAX; + else if (value < 0) + value = 0; + + *(uint16_t *)p_value = (uint16_t)value; + } + } + + return true; +} + +/* + * Read NIM temperature + */ +static bool sfp_nim_get_temperature(nim_i2c_ctx_p ctx, int16_t *p_value) +{ + return sfp_nim_get_dmi_data(SFP_TEMP_LIN_ADDR, SFP_TEMP_SLOPE_LIN_ADDR, + SFP_TEMP_OFFSET_LIN_ADDR, p_value, true, ctx); +} + +/* + * Read NIM supply voltage + */ +static bool sfp_nim_get_supply_voltage(nim_i2c_ctx_p ctx, uint16_t *p_value) +{ + return sfp_nim_get_dmi_data(SFP_VOLT_LIN_ADDR, SFP_VOLT_SLOPE_LIN_ADDR, + SFP_VOLT_OFFSET_LIN_ADDR, p_value, false, ctx); +} + +/* + * Read NIM bias current + */ +static bool sfp_nim_get_tx_bias_current(nim_i2c_ctx_p ctx, uint16_t *p_value) +{ + return sfp_nim_get_dmi_data(SFP_TX_BIAS_LIN_ADDR, + SFP_TX_BIAS_SLOPE_LIN_ADDR, + SFP_TX_BIAS_OFFSET_LIN_ADDR, p_value, false, + ctx); +} + +/* + * Read NIM TX optical power + */ +static bool sfp_nim_get_tx_power(nim_i2c_ctx_p ctx, uint16_t *p_value) +{ + return sfp_nim_get_dmi_data(SFP_TX_PWR_LIN_ADDR, + SFP_TX_PWR_SLOPE_LIN_ADDR, + SFP_TX_PWR_OFFSET_LIN_ADDR, p_value, false, + ctx); +} + +/* + * Return the SFP received power in units of 0.1uW from DMI data. + * If external calibration is necessary, the calibration data is retrieved and + * the calibration is carried out. + */ +static bool sfp_nim_get_calibrated_rx_power(nim_i2c_ctx_p ctx, uint16_t addr, + uint16_t *p_value) +{ + float rx_pwr_cal[5]; + float power_raised; + float rx_power; + + /* Read data in big endian format */ + read_data_lin(ctx, addr, sizeof(*p_value), p_value); + *(uint16_t *)p_value = + htons(*(uint16_t *)p_value); /* Swap to little endian */ + +#ifdef NIM_DMI_RX_PWR_TEST_VALUE + *p_value = NIM_DMI_RX_PWR_TEST_VALUE; +#endif + +#ifdef NIM_DMI_RX_PWR_CAL_DATA + ctx->specific_u.sfp.ext_cal = true; +#endif + + if (ctx->specific_u.sfp.ext_cal) { + /* Read calibration data in big endian format */ + read_data_lin(ctx, SFP_RX_PWR_COEFF_LIN_ADDR, sizeof(rx_pwr_cal), + rx_pwr_cal); + + for (int i = 0; i < 5; i++) { + uint32_t *p_val = (uint32_t *)&rx_pwr_cal[i]; + *p_val = ntohl(*p_val); /* 32 bit swap */ + } + +#ifdef NIM_DMI_RX_PWR_CAL_DATA + /* Testdata for verification */ + NIM_DMI_RX_PWR_CAL_DATA +#endif + + /* + * If SFP module specifies external calibration - use calibration data + * according to the polynomial correction formula + * RxPwrCal = Coeff0 + Coeff1 * RxPwr + Coeff2 * RxPwr^2 + + * Coeff3 * RxPwr^3 + Coeff4 * RxPwr^4 + */ + power_raised = 1.0; + rx_power = rx_pwr_cal[4]; /* Coeff0 */ + + for (int i = 3; i >= 0; i--) { + power_raised *= (float)*p_value; + rx_power += rx_pwr_cal[i] * power_raised; + } + + /* Check out for out of range */ + if (rx_power > 65535) + return false; + + if (rx_power < 0) + *p_value = 0; + else + *p_value = (uint16_t)rx_power; + } + + return true; +} + +/* + * Read RX optical power if it exists + */ +static bool sfp_nim_get_rx_power(nim_i2c_ctx_p ctx, uint16_t *p_value) +{ + return sfp_nim_get_calibrated_rx_power(ctx, SFP_RX_PWR_LIN_ADDR, p_value); +} + +void nim_read_sfp_temp(struct nim_sensor_group *sg, nthw_spis_t *t_spi) +{ + int16_t temp; + (void)t_spi; + + if (sg == NULL || sg->ctx == NULL) { + NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__); + return; + } + + if (sfp_nim_get_temperature(sg->ctx, &temp)) + update_sensor_value(sg->sensor, (int)(temp * 10 / 256)); + + else + update_sensor_value(sg->sensor, -1); +} + +void nim_read_sfp_voltage(struct nim_sensor_group *sg, nthw_spis_t *t_spi) +{ + uint16_t temp; + (void)t_spi; + + if (sg == NULL || sg->ctx == NULL) { + NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__); + return; + } + + if (sfp_nim_get_supply_voltage(sg->ctx, &temp)) { + update_sensor_value(sg->sensor, + (int)(temp / 10)); /* Unit: 100uV -> 1mV */ + } else { + update_sensor_value(sg->sensor, -1); + } +} + +void nim_read_sfp_bias_current(struct nim_sensor_group *sg, nthw_spis_t *t_spi) +{ + uint16_t temp; + (void)t_spi; + + if (sg == NULL || sg->ctx == NULL) { + NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__); + return; + } + + if (sfp_nim_get_tx_bias_current(sg->ctx, &temp)) + update_sensor_value(sg->sensor, (int)(temp * 2)); + + else + update_sensor_value(sg->sensor, -1); +} + +void nim_read_sfp_tx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi) +{ + uint16_t temp; + (void)t_spi; + + if (sg == NULL || sg->ctx == NULL) { + NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__); + return; + } + + if (sfp_nim_get_tx_power(sg->ctx, &temp)) + update_sensor_value(sg->sensor, (int)temp); + + else + update_sensor_value(sg->sensor, -1); +} + +void nim_read_sfp_rx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi) +{ + uint16_t temp; + (void)t_spi; + + if (sg == NULL || sg->ctx == NULL) { + NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__); + return; + } + + if (sfp_nim_get_rx_power(sg->ctx, &temp)) + update_sensor_value(sg->sensor, (int)temp); + + else + update_sensor_value(sg->sensor, -1); +} diff --git a/drivers/net/ntnic/nim/sfp_sensors.h b/drivers/net/ntnic/nim/sfp_sensors.h new file mode 100644 index 0000000000..ab56027dc8 --- /dev/null +++ b/drivers/net/ntnic/nim/sfp_sensors.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _SFP_H +#define _SFP_H + +#include "sensors.h" +#include "i2c_nim.h" + +/* Read functions */ +void nim_read_sfp_temp(struct nim_sensor_group *sg, nthw_spis_t *t_spi); +void nim_read_sfp_voltage(struct nim_sensor_group *sg, nthw_spis_t *t_spi); +void nim_read_sfp_bias_current(struct nim_sensor_group *sg, nthw_spis_t *t_spi); +void nim_read_sfp_tx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi); +void nim_read_sfp_rx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi); + +#endif /* _SFP_H */ diff --git a/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c index efdcc222a8..bd7cd2a27c 100644 --- a/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c +++ b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c @@ -5,5 +5,12 @@ #include "nthw_clock_profiles.h" /* Clock profile for NT200A02 2x40G, 2x100G */ -const int n_data_si5340_nt200a02_u23_v5; -const clk_profile_data_fmt2_t *p_data_si5340_nt200a02_u23_v5; +#define si5340_revd_register_t type_si5340_nt200a02_u23_v5 +#define si5340_revd_registers data_si5340_nt200a02_u23_v5 +#include "nthw_nt200a02_u23_si5340_v5.h" +const int n_data_si5340_nt200a02_u23_v5 = SI5340_REVD_REG_CONFIG_NUM_REGS; +const clk_profile_data_fmt2_t *p_data_si5340_nt200a02_u23_v5 = + (const clk_profile_data_fmt2_t *)&data_si5340_nt200a02_u23_v5[0]; +#undef si5340_revd_registers +#undef si5340_revd_register_t +#undef SI5340_REVD_REG_CONFIG_HEADER /*Disable the include once protection */ diff --git a/drivers/net/ntnic/nthw/core/nthw_core.h b/drivers/net/ntnic/nthw/core/nthw_core.h index 798a95d5cf..025b6b61cc 100644 --- a/drivers/net/ntnic/nthw/core/nthw_core.h +++ b/drivers/net/ntnic/nthw/core/nthw_core.h @@ -16,9 +16,11 @@ #include "nthw_pci_ta.h" #include "nthw_iic.h" +#include "nthw_gmf.h" #include "nthw_gpio_phy.h" #include "nthw_mac_pcs.h" #include "nthw_mac_pcs_xxv.h" +#include "nthw_rmc.h" #include "nthw_sdc.h" #include "nthw_spim.h" diff --git a/drivers/net/ntnic/nthw/core/nthw_gmf.c b/drivers/net/ntnic/nthw/core/nthw_gmf.c new file mode 100644 index 0000000000..fe63c461e5 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_gmf.c @@ -0,0 +1,290 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_gmf.h" + +nthw_gmf_t *nthw_gmf_new(void) +{ + nthw_gmf_t *p = malloc(sizeof(nthw_gmf_t)); + + if (p) + memset(p, 0, sizeof(nthw_gmf_t)); + return p; +} + +void nthw_gmf_delete(nthw_gmf_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_gmf_t)); + free(p); + } +} + +int nthw_gmf_init(nthw_gmf_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + nt_module_t *mod = fpga_query_module(p_fpga, MOD_GMF, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: GMF %d: no such instance\n", + p_fpga->p_fpga_info->mp_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_gmf = mod; + + p->mp_ctrl = module_get_register(p->mp_mod_gmf, GMF_CTRL); + p->mp_ctrl_enable = register_get_field(p->mp_ctrl, GMF_CTRL_ENABLE); + p->mp_ctrl_ifg_enable = register_get_field(p->mp_ctrl, GMF_CTRL_IFG_ENABLE); + p->mp_ctrl_ifg_auto_adjust_enable = + register_get_field(p->mp_ctrl, GMF_CTRL_IFG_AUTO_ADJUST_ENABLE); + + p->mp_speed = module_get_register(p->mp_mod_gmf, GMF_SPEED); + p->mp_speed_ifg_speed = register_get_field(p->mp_speed, GMF_SPEED_IFG_SPEED); + + p->mp_ifg_clock_delta = + module_get_register(p->mp_mod_gmf, GMF_IFG_SET_CLOCK_DELTA); + p->mp_ifg_clock_delta_delta = + register_get_field(p->mp_ifg_clock_delta, GMF_IFG_SET_CLOCK_DELTA_DELTA); + + p->mp_ifg_max_adjust_slack = + module_get_register(p->mp_mod_gmf, GMF_IFG_MAX_ADJUST_SLACK); + p->mp_ifg_max_adjust_slack_slack = + register_get_field(p->mp_ifg_max_adjust_slack, GMF_IFG_MAX_ADJUST_SLACK_SLACK); + + p->mp_debug_lane_marker = + module_get_register(p->mp_mod_gmf, GMF_DEBUG_LANE_MARKER); + p->mp_debug_lane_marker_compensation = + register_get_field(p->mp_debug_lane_marker, GMF_DEBUG_LANE_MARKER_COMPENSATION); + + p->mp_stat_sticky = module_get_register(p->mp_mod_gmf, GMF_STAT_STICKY); + p->mp_stat_sticky_data_underflowed = + register_get_field(p->mp_stat_sticky, GMF_STAT_STICKY_DATA_UNDERFLOWED); + p->mp_stat_sticky_ifg_adjusted = + register_get_field(p->mp_stat_sticky, GMF_STAT_STICKY_IFG_ADJUSTED); + + p->mn_param_gmf_ifg_speed_mul = + fpga_get_product_param(p_fpga, NT_GMF_IFG_SPEED_MUL, 1); + p->mn_param_gmf_ifg_speed_div = + fpga_get_product_param(p_fpga, NT_GMF_IFG_SPEED_DIV, 1); + + p->m_administrative_block = false; + + p->mp_stat_next_pkt = module_query_register(p->mp_mod_gmf, GMF_STAT_NEXT_PKT); + if (p->mp_stat_next_pkt) { + p->mp_stat_next_pkt_ns = + register_query_field(p->mp_stat_next_pkt, + GMF_STAT_NEXT_PKT_NS); + } else { + p->mp_stat_next_pkt_ns = NULL; + } + p->mp_stat_max_delayed_pkt = + module_query_register(p->mp_mod_gmf, GMF_STAT_MAX_DELAYED_PKT); + if (p->mp_stat_max_delayed_pkt) { + p->mp_stat_max_delayed_pkt_ns = + register_query_field(p->mp_stat_max_delayed_pkt, + GMF_STAT_MAX_DELAYED_PKT_NS); + } else { + p->mp_stat_max_delayed_pkt_ns = NULL; + } + p->mp_ctrl_ifg_tx_now_always = + register_query_field(p->mp_ctrl, GMF_CTRL_IFG_TX_NOW_ALWAYS); + p->mp_ctrl_ifg_tx_on_ts_always = + register_query_field(p->mp_ctrl, GMF_CTRL_IFG_TX_ON_TS_ALWAYS); + + p->mp_ctrl_ifg_tx_on_ts_adjust_on_set_clock = + register_query_field(p->mp_ctrl, GMF_CTRL_IFG_TX_ON_TS_ADJUST_ON_SET_CLOCK); + + p->mp_ifg_clock_delta_adjust = + module_query_register(p->mp_mod_gmf, GMF_IFG_SET_CLOCK_DELTA_ADJUST); + if (p->mp_ifg_clock_delta_adjust) { + p->mp_ifg_clock_delta_adjust_delta = + register_query_field(p->mp_ifg_clock_delta_adjust, + GMF_IFG_SET_CLOCK_DELTA_ADJUST_DELTA); + } else { + p->mp_ifg_clock_delta_adjust_delta = NULL; + } + return 0; +} + +void nthw_gmf_set_enable(nthw_gmf_t *p, bool enable) +{ + if (!p->m_administrative_block) + field_set_val_flush32(p->mp_ctrl_enable, enable ? 1 : 0); +} + +void nthw_gmf_set_ifg_enable(nthw_gmf_t *p, bool enable) +{ + field_set_val_flush32(p->mp_ctrl_ifg_enable, enable ? 1 : 0); +} + +void nthw_gmf_set_tx_now_always_enable(nthw_gmf_t *p, bool enable) +{ + if (p->mp_ctrl_ifg_tx_now_always) + field_set_val_flush32(p->mp_ctrl_ifg_tx_now_always, enable ? 1 : 0); +} + +void nthw_gmf_set_tx_on_ts_always_enable(nthw_gmf_t *p, bool enable) +{ + if (p->mp_ctrl_ifg_tx_on_ts_always) + field_set_val_flush32(p->mp_ctrl_ifg_tx_on_ts_always, enable ? 1 : 0); +} + +void nthw_gmf_set_tx_on_ts_adjust_on_set_clock(nthw_gmf_t *p, bool enable) +{ + if (p->mp_ctrl_ifg_tx_on_ts_adjust_on_set_clock) { + field_set_val_flush32(p->mp_ctrl_ifg_tx_on_ts_adjust_on_set_clock, + enable ? 1 : 0); + } +} + +void nthw_gmf_set_ifg_auto_adjust_enable(nthw_gmf_t *p, bool enable) +{ + field_set_val_flush32(p->mp_ctrl_ifg_auto_adjust_enable, enable); +} + +int nthw_gmf_set_ifg_speed_raw(nthw_gmf_t *p, uint64_t n_speed_val) +{ + if (n_speed_val <= + (1ULL << (field_get_bit_width(p->mp_speed_ifg_speed) - 1))) { + field_set_val(p->mp_speed_ifg_speed, (uint32_t *)&n_speed_val, + (field_get_bit_width(p->mp_speed_ifg_speed) <= 32 ? 1 : + 2)); + field_flush_register(p->mp_speed_ifg_speed); + return 0; + } + return -1; +} + +int nthw_gmf_get_ifg_speed_bit_width(nthw_gmf_t *p) +{ + const int n_bit_width = field_get_bit_width(p->mp_speed_ifg_speed); + + assert(n_bit_width >= + 22); /* Sanity check: GMF ver 1.2 is bw 22 - GMF ver 1.3 is bw 64 */ + return n_bit_width; +} + +int nthw_gmf_set_ifg_speed_bits(nthw_gmf_t *p, const uint64_t n_rate_limit_bits, + const uint64_t n_link_speed) +{ + const int n_bit_width = (nthw_gmf_get_ifg_speed_bit_width(p) / 2); + const double f_adj_rate = + ((double)((((double)n_rate_limit_bits) / (double)n_link_speed) * + p->mn_param_gmf_ifg_speed_mul) / + p->mn_param_gmf_ifg_speed_div); + const double f_speed = ((1UL / f_adj_rate) - 1) * exp2(n_bit_width); + uint64_t n_speed_val = (uint64_t)round(f_speed); + + return nthw_gmf_set_ifg_speed_raw(p, n_speed_val); +} + +int nthw_gmf_set_ifg_speed_percent(nthw_gmf_t *p, const double f_rate_limit_percent) +{ + uint64_t n_speed_val; + + if (f_rate_limit_percent == 0.0 || f_rate_limit_percent == 100.0) { + n_speed_val = 0; + } else if (f_rate_limit_percent <= 99) { + const int n_bit_width = (nthw_gmf_get_ifg_speed_bit_width(p) / 2); + const double f_adj_rate = + ((double)(f_rate_limit_percent * + (double)p->mn_param_gmf_ifg_speed_mul) / + p->mn_param_gmf_ifg_speed_div / 100); + const double f_speed = ((1UL / f_adj_rate) - 1) * exp2(n_bit_width); + + n_speed_val = (uint64_t)f_speed; + } else { + return -1; + } + + return nthw_gmf_set_ifg_speed_raw(p, n_speed_val); +} + +void nthw_gmf_set_delta(nthw_gmf_t *p, uint64_t delta) +{ + field_set_val(p->mp_ifg_clock_delta_delta, (uint32_t *)&delta, 2); + field_flush_register(p->mp_ifg_clock_delta_delta); +} + +void nthw_gmf_set_delta_adjust(nthw_gmf_t *p, uint64_t delta_adjust) +{ + if (p->mp_ifg_clock_delta_adjust) { + field_set_val(p->mp_ifg_clock_delta_adjust_delta, + (uint32_t *)&delta_adjust, 2); + field_flush_register(p->mp_ifg_clock_delta_adjust_delta); + } +} + +void nthw_gmf_set_slack(nthw_gmf_t *p, uint64_t slack) +{ + field_set_val(p->mp_ifg_max_adjust_slack_slack, (uint32_t *)&slack, 2); + field_flush_register(p->mp_ifg_max_adjust_slack_slack); +} + +void nthw_gmf_set_compensation(nthw_gmf_t *p, uint32_t compensation) +{ + field_set_val_flush32(p->mp_debug_lane_marker_compensation, compensation); +} + +uint32_t nthw_gmf_get_status_sticky(nthw_gmf_t *p) +{ + uint32_t status = 0; + + register_update(p->mp_stat_sticky); + + if (field_get_val32(p->mp_stat_sticky_data_underflowed)) + status |= GMF_STATUS_MASK_DATA_UNDERFLOWED; + if (field_get_val32(p->mp_stat_sticky_ifg_adjusted)) + status |= GMF_STATUS_MASK_IFG_ADJUSTED; + + return status; +} + +void nthw_gmf_set_status_sticky(nthw_gmf_t *p, uint32_t status) +{ + if (status & GMF_STATUS_MASK_DATA_UNDERFLOWED) + field_set_flush(p->mp_stat_sticky_data_underflowed); + if (status & GMF_STATUS_MASK_IFG_ADJUSTED) + field_set_flush(p->mp_stat_sticky_ifg_adjusted); +} + +uint64_t nthw_gmf_get_stat_next_pkt_ns(nthw_gmf_t *p) +{ + uint64_t value = ULONG_MAX; + + if (p->mp_stat_next_pkt) { + register_update(p->mp_stat_next_pkt); + field_get_val(p->mp_stat_next_pkt_ns, (uint32_t *)&value, 2); + } + return value; +} + +uint64_t nthw_gmf_get_stat_max_pk_delayedt_ns(nthw_gmf_t *p) +{ + uint64_t value = ULONG_MAX; + + if (p->mp_stat_max_delayed_pkt) { + register_update(p->mp_stat_max_delayed_pkt); + field_get_val(p->mp_stat_max_delayed_pkt_ns, (uint32_t *)&value, 2); + } + return value; +} + +void nthw_gmf_administrative_block(nthw_gmf_t *p) +{ + nthw_gmf_set_enable(p, false); + p->m_administrative_block = true; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_gmf.h b/drivers/net/ntnic/nthw/core/nthw_gmf.h new file mode 100644 index 0000000000..aec1342be7 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_gmf.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_GMF_H__ +#define __NTHW_GMF_H__ + +enum gmf_status_mask { + GMF_STATUS_MASK_DATA_UNDERFLOWED = 1, + GMF_STATUS_MASK_IFG_ADJUSTED +}; + +struct nthw_gmf { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_gmf; + int mn_instance; + /* */ + + nt_register_t *mp_ctrl; + nt_field_t *mp_ctrl_enable; + nt_field_t *mp_ctrl_ifg_enable; + nt_field_t *mp_ctrl_ifg_tx_now_always; + nt_field_t *mp_ctrl_ifg_tx_on_ts_always; + nt_field_t *mp_ctrl_ifg_tx_on_ts_adjust_on_set_clock; + nt_field_t *mp_ctrl_ifg_auto_adjust_enable; + + nt_register_t *mp_speed; + nt_field_t *mp_speed_ifg_speed; + + nt_register_t *mp_ifg_clock_delta; + nt_field_t *mp_ifg_clock_delta_delta; + + nt_register_t *mp_ifg_clock_delta_adjust; + nt_field_t *mp_ifg_clock_delta_adjust_delta; + + nt_register_t *mp_ifg_max_adjust_slack; + nt_field_t *mp_ifg_max_adjust_slack_slack; + + nt_register_t *mp_debug_lane_marker; + nt_field_t *mp_debug_lane_marker_compensation; + + nt_register_t *mp_stat_sticky; + nt_field_t *mp_stat_sticky_data_underflowed; + nt_field_t *mp_stat_sticky_ifg_adjusted; + + nt_register_t *mp_stat_next_pkt; + nt_field_t *mp_stat_next_pkt_ns; + + nt_register_t *mp_stat_max_delayed_pkt; + nt_field_t *mp_stat_max_delayed_pkt_ns; + + int mn_param_gmf_ifg_speed_mul; + int mn_param_gmf_ifg_speed_div; + + bool m_administrative_block; /* Used to enforce license expiry */ +}; + +typedef struct nthw_gmf nthw_gmf_t; +typedef struct nthw_gmf nthw_gmf; + +nthw_gmf_t *nthw_gmf_new(void); +void nthw_gmf_delete(nthw_gmf_t *p); +int nthw_gmf_init(nthw_gmf_t *p, nt_fpga_t *p_fpga, int n_instance); + +void nthw_gmf_set_enable(nthw_gmf_t *p, bool enable); +void nthw_gmf_set_ifg_enable(nthw_gmf_t *p, bool enable); + +void nthw_gmf_set_tx_now_always_enable(nthw_gmf_t *p, bool enable); +void nthw_gmf_set_tx_on_ts_always_enable(nthw_gmf_t *p, bool enable); +void nthw_gmf_set_tx_on_ts_adjust_on_set_clock(nthw_gmf_t *p, bool enable); +void nthw_gmf_set_ifg_auto_adjust_enable(nthw_gmf_t *p, bool enable); + +int nthw_gmf_get_ifg_speed_bit_width(nthw_gmf_t *p); + +int nthw_gmf_set_ifg_speed_raw(nthw_gmf_t *p, uint64_t n_speed_val); +int nthw_gmf_set_ifg_speed_bits(nthw_gmf_t *p, const uint64_t n_rate_limit_bits, + const uint64_t n_link_speed); +int nthw_gmf_set_ifg_speed_percent(nthw_gmf_t *p, const double f_rate_limit_percent); + +void nthw_gmf_set_delta(nthw_gmf_t *p, uint64_t delta); +void nthw_gmf_set_delta_adjust(nthw_gmf_t *p, uint64_t delta_adjust); +void nthw_gmf_set_slack(nthw_gmf_t *p, uint64_t slack); +void nthw_gmf_set_compensation(nthw_gmf_t *p, uint32_t compensation); + +uint32_t nthw_gmf_get_status_sticky(nthw_gmf_t *p); +void nthw_gmf_set_status_sticky(nthw_gmf_t *p, uint32_t status); + +uint64_t nthw_gmf_get_stat_next_pkt_ns(nthw_gmf_t *p); +uint64_t nthw_gmf_get_stat_max_pk_delayedt_ns(nthw_gmf_t *p); + +void nthw_gmf_administrative_block(nthw_gmf_t *p); /* Used to enforce license expiry blocking */ + +#endif /* __NTHW_GMF_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_nt200a02_u23_si5340_v5.h b/drivers/net/ntnic/nthw/core/nthw_nt200a02_u23_si5340_v5.h new file mode 100644 index 0000000000..f063a1048a --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_nt200a02_u23_si5340_v5.h @@ -0,0 +1,344 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef SI5340_REVD_REG_CONFIG_HEADER +#define SI5340_REVD_REG_CONFIG_HEADER + +#define SI5340_REVD_REG_CONFIG_NUM_REGS 326 + +typedef struct { + unsigned int address; /* 16-bit register address */ + unsigned char value; /* 8-bit register data */ +} si5340_revd_register_t; + +si5340_revd_register_t const si5340_revd_registers[SI5340_REVD_REG_CONFIG_NUM_REGS] = { + { 0x0B24, 0xC0 }, + { 0x0B25, 0x00 }, + { 0x0502, 0x01 }, + { 0x0505, 0x03 }, + { 0x0957, 0x17 }, + { 0x0B4E, 0x1A }, + { 0x0006, 0x00 }, + { 0x0007, 0x00 }, + { 0x0008, 0x00 }, + { 0x000B, 0x74 }, + { 0x0017, 0xF0 }, + { 0x0018, 0xFF }, + { 0x0021, 0x0F }, + { 0x0022, 0x00 }, + { 0x002B, 0x0A }, + { 0x002C, 0x20 }, + { 0x002D, 0x00 }, + { 0x002E, 0x00 }, + { 0x002F, 0x00 }, + { 0x0030, 0x00 }, + { 0x0031, 0x00 }, + { 0x0032, 0x00 }, + { 0x0033, 0x00 }, + { 0x0034, 0x00 }, + { 0x0035, 0x00 }, + { 0x0036, 0x00 }, + { 0x0037, 0x00 }, + { 0x0038, 0x00 }, + { 0x0039, 0x00 }, + { 0x003A, 0x00 }, + { 0x003B, 0x00 }, + { 0x003C, 0x00 }, + { 0x003D, 0x00 }, + { 0x0041, 0x00 }, + { 0x0042, 0x00 }, + { 0x0043, 0x00 }, + { 0x0044, 0x00 }, + { 0x009E, 0x00 }, + { 0x0102, 0x01 }, + { 0x0112, 0x02 }, + { 0x0113, 0x09 }, + { 0x0114, 0x3E }, + { 0x0115, 0x19 }, + { 0x0117, 0x06 }, + { 0x0118, 0x09 }, + { 0x0119, 0x3E }, + { 0x011A, 0x18 }, + { 0x0126, 0x06 }, + { 0x0127, 0x09 }, + { 0x0128, 0x3E }, + { 0x0129, 0x18 }, + { 0x012B, 0x06 }, + { 0x012C, 0x09 }, + { 0x012D, 0x3E }, + { 0x012E, 0x1A }, + { 0x013F, 0x00 }, + { 0x0140, 0x00 }, + { 0x0141, 0x40 }, + { 0x0206, 0x00 }, + { 0x0208, 0x00 }, + { 0x0209, 0x00 }, + { 0x020A, 0x00 }, + { 0x020B, 0x00 }, + { 0x020C, 0x00 }, + { 0x020D, 0x00 }, + { 0x020E, 0x00 }, + { 0x020F, 0x00 }, + { 0x0210, 0x00 }, + { 0x0211, 0x00 }, + { 0x0212, 0x00 }, + { 0x0213, 0x00 }, + { 0x0214, 0x00 }, + { 0x0215, 0x00 }, + { 0x0216, 0x00 }, + { 0x0217, 0x00 }, + { 0x0218, 0x00 }, + { 0x0219, 0x00 }, + { 0x021A, 0x00 }, + { 0x021B, 0x00 }, + { 0x021C, 0x00 }, + { 0x021D, 0x00 }, + { 0x021E, 0x00 }, + { 0x021F, 0x00 }, + { 0x0220, 0x00 }, + { 0x0221, 0x00 }, + { 0x0222, 0x00 }, + { 0x0223, 0x00 }, + { 0x0224, 0x00 }, + { 0x0225, 0x00 }, + { 0x0226, 0x00 }, + { 0x0227, 0x00 }, + { 0x0228, 0x00 }, + { 0x0229, 0x00 }, + { 0x022A, 0x00 }, + { 0x022B, 0x00 }, + { 0x022C, 0x00 }, + { 0x022D, 0x00 }, + { 0x022E, 0x00 }, + { 0x022F, 0x00 }, + { 0x0235, 0x00 }, + { 0x0236, 0x00 }, + { 0x0237, 0x00 }, + { 0x0238, 0xA6 }, + { 0x0239, 0x8B }, + { 0x023A, 0x00 }, + { 0x023B, 0x00 }, + { 0x023C, 0x00 }, + { 0x023D, 0x00 }, + { 0x023E, 0x80 }, + { 0x0250, 0x03 }, + { 0x0251, 0x00 }, + { 0x0252, 0x00 }, + { 0x0253, 0x00 }, + { 0x0254, 0x00 }, + { 0x0255, 0x00 }, + { 0x025C, 0x00 }, + { 0x025D, 0x00 }, + { 0x025E, 0x00 }, + { 0x025F, 0x00 }, + { 0x0260, 0x00 }, + { 0x0261, 0x00 }, + { 0x026B, 0x30 }, + { 0x026C, 0x35 }, + { 0x026D, 0x00 }, + { 0x026E, 0x00 }, + { 0x026F, 0x00 }, + { 0x0270, 0x00 }, + { 0x0271, 0x00 }, + { 0x0272, 0x00 }, + { 0x0302, 0x00 }, + { 0x0303, 0x00 }, + { 0x0304, 0x00 }, + { 0x0305, 0x00 }, + { 0x0306, 0x0D }, + { 0x0307, 0x00 }, + { 0x0308, 0x00 }, + { 0x0309, 0x00 }, + { 0x030A, 0x00 }, + { 0x030B, 0x80 }, + { 0x030C, 0x00 }, + { 0x030D, 0x00 }, + { 0x030E, 0x00 }, + { 0x030F, 0x00 }, + { 0x0310, 0x61 }, + { 0x0311, 0x08 }, + { 0x0312, 0x00 }, + { 0x0313, 0x00 }, + { 0x0314, 0x00 }, + { 0x0315, 0x00 }, + { 0x0316, 0x80 }, + { 0x0317, 0x00 }, + { 0x0318, 0x00 }, + { 0x0319, 0x00 }, + { 0x031A, 0x00 }, + { 0x031B, 0xD0 }, + { 0x031C, 0x1A }, + { 0x031D, 0x00 }, + { 0x031E, 0x00 }, + { 0x031F, 0x00 }, + { 0x0320, 0x00 }, + { 0x0321, 0xA0 }, + { 0x0322, 0x00 }, + { 0x0323, 0x00 }, + { 0x0324, 0x00 }, + { 0x0325, 0x00 }, + { 0x0326, 0x00 }, + { 0x0327, 0x00 }, + { 0x0328, 0x00 }, + { 0x0329, 0x00 }, + { 0x032A, 0x00 }, + { 0x032B, 0x00 }, + { 0x032C, 0x00 }, + { 0x032D, 0x00 }, + { 0x0338, 0x00 }, + { 0x0339, 0x1F }, + { 0x033B, 0x00 }, + { 0x033C, 0x00 }, + { 0x033D, 0x00 }, + { 0x033E, 0x00 }, + { 0x033F, 0x00 }, + { 0x0340, 0x00 }, + { 0x0341, 0x00 }, + { 0x0342, 0x00 }, + { 0x0343, 0x00 }, + { 0x0344, 0x00 }, + { 0x0345, 0x00 }, + { 0x0346, 0x00 }, + { 0x0347, 0x00 }, + { 0x0348, 0x00 }, + { 0x0349, 0x00 }, + { 0x034A, 0x00 }, + { 0x034B, 0x00 }, + { 0x034C, 0x00 }, + { 0x034D, 0x00 }, + { 0x034E, 0x00 }, + { 0x034F, 0x00 }, + { 0x0350, 0x00 }, + { 0x0351, 0x00 }, + { 0x0352, 0x00 }, + { 0x0359, 0x00 }, + { 0x035A, 0x00 }, + { 0x035B, 0x00 }, + { 0x035C, 0x00 }, + { 0x035D, 0x00 }, + { 0x035E, 0x00 }, + { 0x035F, 0x00 }, + { 0x0360, 0x00 }, + { 0x0802, 0x00 }, + { 0x0803, 0x00 }, + { 0x0804, 0x00 }, + { 0x0805, 0x00 }, + { 0x0806, 0x00 }, + { 0x0807, 0x00 }, + { 0x0808, 0x00 }, + { 0x0809, 0x00 }, + { 0x080A, 0x00 }, + { 0x080B, 0x00 }, + { 0x080C, 0x00 }, + { 0x080D, 0x00 }, + { 0x080E, 0x00 }, + { 0x080F, 0x00 }, + { 0x0810, 0x00 }, + { 0x0811, 0x00 }, + { 0x0812, 0x00 }, + { 0x0813, 0x00 }, + { 0x0814, 0x00 }, + { 0x0815, 0x00 }, + { 0x0816, 0x00 }, + { 0x0817, 0x00 }, + { 0x0818, 0x00 }, + { 0x0819, 0x00 }, + { 0x081A, 0x00 }, + { 0x081B, 0x00 }, + { 0x081C, 0x00 }, + { 0x081D, 0x00 }, + { 0x081E, 0x00 }, + { 0x081F, 0x00 }, + { 0x0820, 0x00 }, + { 0x0821, 0x00 }, + { 0x0822, 0x00 }, + { 0x0823, 0x00 }, + { 0x0824, 0x00 }, + { 0x0825, 0x00 }, + { 0x0826, 0x00 }, + { 0x0827, 0x00 }, + { 0x0828, 0x00 }, + { 0x0829, 0x00 }, + { 0x082A, 0x00 }, + { 0x082B, 0x00 }, + { 0x082C, 0x00 }, + { 0x082D, 0x00 }, + { 0x082E, 0x00 }, + { 0x082F, 0x00 }, + { 0x0830, 0x00 }, + { 0x0831, 0x00 }, + { 0x0832, 0x00 }, + { 0x0833, 0x00 }, + { 0x0834, 0x00 }, + { 0x0835, 0x00 }, + { 0x0836, 0x00 }, + { 0x0837, 0x00 }, + { 0x0838, 0x00 }, + { 0x0839, 0x00 }, + { 0x083A, 0x00 }, + { 0x083B, 0x00 }, + { 0x083C, 0x00 }, + { 0x083D, 0x00 }, + { 0x083E, 0x00 }, + { 0x083F, 0x00 }, + { 0x0840, 0x00 }, + { 0x0841, 0x00 }, + { 0x0842, 0x00 }, + { 0x0843, 0x00 }, + { 0x0844, 0x00 }, + { 0x0845, 0x00 }, + { 0x0846, 0x00 }, + { 0x0847, 0x00 }, + { 0x0848, 0x00 }, + { 0x0849, 0x00 }, + { 0x084A, 0x00 }, + { 0x084B, 0x00 }, + { 0x084C, 0x00 }, + { 0x084D, 0x00 }, + { 0x084E, 0x00 }, + { 0x084F, 0x00 }, + { 0x0850, 0x00 }, + { 0x0851, 0x00 }, + { 0x0852, 0x00 }, + { 0x0853, 0x00 }, + { 0x0854, 0x00 }, + { 0x0855, 0x00 }, + { 0x0856, 0x00 }, + { 0x0857, 0x00 }, + { 0x0858, 0x00 }, + { 0x0859, 0x00 }, + { 0x085A, 0x00 }, + { 0x085B, 0x00 }, + { 0x085C, 0x00 }, + { 0x085D, 0x00 }, + { 0x085E, 0x00 }, + { 0x085F, 0x00 }, + { 0x0860, 0x00 }, + { 0x0861, 0x00 }, + { 0x090E, 0x02 }, + { 0x091C, 0x04 }, + { 0x0943, 0x00 }, + { 0x0949, 0x00 }, + { 0x094A, 0x00 }, + { 0x094E, 0x49 }, + { 0x094F, 0x02 }, + { 0x095E, 0x00 }, + { 0x0A02, 0x00 }, + { 0x0A03, 0x07 }, + { 0x0A04, 0x01 }, + { 0x0A05, 0x07 }, + { 0x0A14, 0x00 }, + { 0x0A1A, 0x00 }, + { 0x0A20, 0x00 }, + { 0x0A26, 0x00 }, + { 0x0B44, 0x0F }, + { 0x0B4A, 0x08 }, + { 0x0B57, 0x0E }, + { 0x0B58, 0x01 }, + { 0x001C, 0x01 }, + { 0x0B24, 0xC3 }, + { 0x0B25, 0x02 }, +}; + +#endif /* SI5340_REVD_REG_CONFIG_HEADER */ diff --git a/drivers/net/ntnic/nthw/core/nthw_rmc.c b/drivers/net/ntnic/nthw/core/nthw_rmc.c new file mode 100644 index 0000000000..c4c6779ce0 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_rmc.c @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_rmc.h" + +nthw_rmc_t *nthw_rmc_new(void) +{ + nthw_rmc_t *p = malloc(sizeof(nthw_rmc_t)); + + if (p) + memset(p, 0, sizeof(nthw_rmc_t)); + return p; +} + +void nthw_rmc_delete(nthw_rmc_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_rmc_t)); + free(p); + } +} + +int nthw_rmc_init(nthw_rmc_t *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_RMC, n_instance); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: RMC %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_rmc = p_mod; + + /* Params */ + p->mb_is_vswitch = p_fpga->p_fpga_info->profile == FPGA_INFO_PROFILE_VSWITCH; + p->mn_ports = fpga_get_product_param(p_fpga, NT_RX_PORTS, + fpga_get_product_param(p_fpga, NT_PORTS, 0)); + p->mn_nims = fpga_get_product_param(p_fpga, NT_NIMS, 0); + p->mb_administrative_block = false; + + NT_LOG(DBG, NTHW, "%s: RMC %d: vswitch=%d\n", p_adapter_id_str, + p->mn_instance, p->mb_is_vswitch); + + p->mp_reg_ctrl = module_get_register(p->mp_mod_rmc, RMC_CTRL); + + p->mp_fld_ctrl_block_stat_drop = + register_get_field(p->mp_reg_ctrl, RMC_CTRL_BLOCK_STATT); + p->mp_fld_ctrl_block_keep_alive = + register_get_field(p->mp_reg_ctrl, RMC_CTRL_BLOCK_KEEPA); + p->mp_fld_ctrl_block_mac_port = + register_get_field(p->mp_reg_ctrl, RMC_CTRL_BLOCK_MAC_PORT); + + p->mp_reg_status = module_query_register(p->mp_mod_rmc, RMC_STATUS); + if (p->mp_reg_status) { + p->mp_fld_sf_ram_of = + register_get_field(p->mp_reg_status, RMC_STATUS_SF_RAM_OF); + p->mp_fld_descr_fifo_of = + register_get_field(p->mp_reg_status, RMC_STATUS_DESCR_FIFO_OF); + } + + p->mp_reg_dbg = module_query_register(p->mp_mod_rmc, RMC_DBG); + if (p->mp_reg_dbg) { + p->mp_fld_dbg_merge = + register_get_field(p->mp_reg_dbg, RMC_DBG_MERGE); + } + + p->mp_reg_mac_if = module_query_register(p->mp_mod_rmc, RMC_MAC_IF); + if (p->mp_reg_mac_if) { + p->mp_fld_mac_if_err = + register_get_field(p->mp_reg_mac_if, RMC_MAC_IF_ERR); + } + return 0; +} + +uint32_t nthw_rmc_get_mac_block(nthw_rmc_t *p) +{ + return field_get_updated(p->mp_fld_ctrl_block_mac_port); +} + +uint32_t nthw_rmc_get_status_sf_ram_of(nthw_rmc_t *p) +{ + return (p->mp_reg_status) ? field_get_updated(p->mp_fld_sf_ram_of) : + 0xffffffff; +} + +uint32_t nthw_rmc_get_status_descr_fifo_of(nthw_rmc_t *p) +{ + return (p->mp_reg_status) ? field_get_updated(p->mp_fld_descr_fifo_of) : + 0xffffffff; +} + +uint32_t nthw_rmc_get_dbg_merge(nthw_rmc_t *p) +{ + return (p->mp_reg_dbg) ? field_get_updated(p->mp_fld_dbg_merge) : 0xffffffff; +} + +uint32_t nthw_rmc_get_mac_if_err(nthw_rmc_t *p) +{ + return (p->mp_reg_mac_if) ? field_get_updated(p->mp_fld_mac_if_err) : + 0xffffffff; +} + +void nthw_rmc_set_mac_block(nthw_rmc_t *p, uint32_t mask) +{ + field_set_val_flush32(p->mp_fld_ctrl_block_mac_port, mask); +} + +void nthw_rmc_block(nthw_rmc_t *p) +{ + /* BLOCK_STATT(0)=1 BLOCK_KEEPA(1)=1 BLOCK_MAC_PORT(8:11)=~0 */ + if (!p->mb_administrative_block) { + field_set_flush(p->mp_fld_ctrl_block_stat_drop); + field_set_flush(p->mp_fld_ctrl_block_keep_alive); + field_set_flush(p->mp_fld_ctrl_block_mac_port); + } +} + +void nthw_rmc_unblock(nthw_rmc_t *p, bool b_is_slave) +{ + uint32_t n_block_mask = ~0U << (b_is_slave ? p->mn_nims : p->mn_ports); + + if (p->mb_is_vswitch) { + /* + * VSWITCH: NFV: block bits: phy_nim_ports(2) + rtd_ports(4) + + * roa_recirculate_port(1) + */ + n_block_mask = 1 << (2 + 4); /* block only ROA recirculate */ + } + + /* BLOCK_STATT(0)=0 BLOCK_KEEPA(1)=0 BLOCK_MAC_PORT(8:11)=0 */ + if (!p->mb_administrative_block) { + field_clr_flush(p->mp_fld_ctrl_block_stat_drop); + field_clr_flush(p->mp_fld_ctrl_block_keep_alive); + field_set_val_flush32(p->mp_fld_ctrl_block_mac_port, n_block_mask); + } +} + +void nthw_rmc_administrative_block(nthw_rmc_t *p) +{ + /* block all MAC ports */ + field_set_flush(p->mp_fld_ctrl_block_mac_port); + p->mb_administrative_block = true; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_rmc.h b/drivers/net/ntnic/nthw/core/nthw_rmc.h new file mode 100644 index 0000000000..b40f0a0994 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_rmc.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NTHW_RMC_H_ +#define NTHW_RMC_H_ + +struct nthw_rmc { + nt_fpga_t *mp_fpga; + nt_module_t *mp_mod_rmc; + int mn_instance; + + int mn_ports; + int mn_nims; + bool mb_is_vswitch; + + bool mb_administrative_block; + + /* RMC CTRL register */ + nt_register_t *mp_reg_ctrl; + nt_field_t *mp_fld_ctrl_block_stat_drop; + nt_field_t *mp_fld_ctrl_block_keep_alive; + nt_field_t *mp_fld_ctrl_block_mac_port; + + /* RMC Status register */ + nt_register_t *mp_reg_status; + nt_field_t *mp_fld_sf_ram_of; + nt_field_t *mp_fld_descr_fifo_of; + + /* RMC DBG register */ + nt_register_t *mp_reg_dbg; + nt_field_t *mp_fld_dbg_merge; + + /* RMC MAC_IF register */ + nt_register_t *mp_reg_mac_if; + nt_field_t *mp_fld_mac_if_err; +}; + +typedef struct nthw_rmc nthw_rmc_t; +typedef struct nthw_rmc nthw_rmc; + +nthw_rmc_t *nthw_rmc_new(void); +void nthw_rmc_delete(nthw_rmc_t *p); +int nthw_rmc_init(nthw_rmc_t *p, nt_fpga_t *p_fpga, int n_instance); + +uint32_t nthw_rmc_get_mac_block(nthw_rmc_t *p); +void nthw_rmc_set_mac_block(nthw_rmc_t *p, uint32_t mask); +void nthw_rmc_block(nthw_rmc_t *p); +void nthw_rmc_unblock(nthw_rmc_t *p, bool b_is_slave); +void nthw_rmc_administrative_block(nthw_rmc_t *p); + +uint32_t nthw_rmc_get_status_sf_ram_of(nthw_rmc_t *p); +uint32_t nthw_rmc_get_status_descr_fifo_of(nthw_rmc_t *p); +uint32_t nthw_rmc_get_dbg_merge(nthw_rmc_t *p); +uint32_t nthw_rmc_get_mac_if_err(nthw_rmc_t *p); + +#endif /* NTHW_RMC_H_ */ diff --git a/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.c b/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.c new file mode 100644 index 0000000000..bf120ccb39 --- /dev/null +++ b/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.c @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "avr_sensors.h" +#include "ntlog.h" + +#define MAX_ADAPTERS 2 + +uint8_t s_fpga_indexes[MAX_ADAPTERS] = { 0 }; /* _NTSD_MAX_NUM_ADAPTERS_ */ +static uint8_t get_fpga_idx(unsigned int adapter_no); + +/* + * This function setups monitoring of AVR sensors + */ +static uint8_t _avr_sensor_init(nthw_spi_v3_t *s_spi, uint8_t m_adapter_no, + const char *p_name, + enum sensor_mon_device avr_dev, + uint8_t avr_dev_reg, enum sensor_mon_endian end, + enum sensor_mon_sign si, uint16_t mask) +{ + uint8_t fpga_idx = get_fpga_idx(m_adapter_no); + struct sensor_mon_setup16 avr_sensor_setup; + + /* Setup monitoring in AVR placing results in FPGA */ + avr_sensor_setup.setup_cnt = 1; + avr_sensor_setup.setup_data[0].fpga_idx = fpga_idx; + avr_sensor_setup.setup_data[0].device = avr_dev; + avr_sensor_setup.setup_data[0].device_register = avr_dev_reg; + avr_sensor_setup.setup_data[0].format = (uint16_t)(end | si << 2); + + avr_sensor_setup.setup_data[0].mask = mask; + avr_sensor_setup.setup_data[0].pos = + 0; /* So far for all sensors in table */ + + /* + * At first it is the task of ntservice to test limit_low and limit_high on all + * board sensors. Later the test is going to be carried out by the AVR + */ + if (si == SENSOR_MON_SIGNED) { + avr_sensor_setup.setup_data[0].int16.limit_low = + SENSOR_MON_INT16_NAN; + avr_sensor_setup.setup_data[0].int16.limit_high = + SENSOR_MON_INT16_NAN; + } else { + avr_sensor_setup.setup_data[0].uint16.limit_low = + SENSOR_MON_UINT16_NAN; + avr_sensor_setup.setup_data[0].uint16.limit_high = + SENSOR_MON_UINT16_NAN; + } + + int result = nt_avr_sensor_mon_setup(&avr_sensor_setup, s_spi); + + if (result) + NT_LOG(ERR, ETHDEV, "%s: sensor initialization error\n", p_name); + + return fpga_idx; +} + +static void avr_read(struct nt_sensor_group *sg, nthw_spis_t *t_spi) +{ + uint32_t p_sensor_result; + + if (sg == NULL || sg->sensor == NULL) + return; + + sensor_read(t_spi, sg->sensor->fpga_idx, &p_sensor_result); + update_sensor_value(sg->sensor, sg->conv_func(p_sensor_result)); +} + +struct nt_sensor_group * +avr_sensor_init(nthw_spi_v3_t *s_spi, uint8_t m_adapter_no, const char *p_name, + enum nt_sensor_source_e ssrc, enum nt_sensor_type_e type, + unsigned int index, enum sensor_mon_device avr_dev, + uint8_t avr_dev_reg, enum sensor_mon_endian end, + enum sensor_mon_sign si, int (*conv_func)(uint32_t), + uint16_t mask) +{ + struct nt_sensor_group *sg = malloc(sizeof(struct nt_sensor_group)); + + if (sg == NULL) { + NT_LOG(ERR, ETHDEV, "%s: sensor group is NULL", __func__); + return NULL; + } + init_sensor_group(sg); + sg->sensor = allocate_sensor(m_adapter_no, p_name, ssrc, type, index, + NT_SENSOR_DISABLE_ALARM, si); + sg->sensor->fpga_idx = _avr_sensor_init(s_spi, m_adapter_no, p_name, avr_dev, + avr_dev_reg, end, si, mask); + sg->read = &avr_read; + sg->conv_func = conv_func; + sg->monitor = NULL; + sg->next = NULL; + return sg; +} + +static uint8_t get_fpga_idx(unsigned int adapter_no) +{ + uint8_t tmp = s_fpga_indexes[adapter_no]; + + s_fpga_indexes[adapter_no] = (uint8_t)(tmp + 1); + + return tmp; +} diff --git a/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.h b/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.h new file mode 100644 index 0000000000..b8c37a12cb --- /dev/null +++ b/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _AVR_SENSORS_H +#define _AVR_SENSORS_H + +#include + +#include "sensors.h" +#include "avr_intf.h" +#include "ntavr.h" + +struct nt_sensor_group * +avr_sensor_init(nthw_spi_v3_t *s_spi, uint8_t m_adapter_no, const char *p_name, + enum nt_sensor_source_e ssrc, enum nt_sensor_type_e type, + unsigned int index, enum sensor_mon_device avr_dev, + uint8_t avr_dev_reg, enum sensor_mon_endian end, + enum sensor_mon_sign si, int (*conv_func)(uint32_t), + uint16_t mask); + +#endif /* _AVR_SENSORS_H */ diff --git a/drivers/net/ntnic/sensors/board_sensors/board_sensors.c b/drivers/net/ntnic/sensors/board_sensors/board_sensors.c new file mode 100644 index 0000000000..8e52379df8 --- /dev/null +++ b/drivers/net/ntnic/sensors/board_sensors/board_sensors.c @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include + +#include "tempmon.h" +#include "board_sensors.h" +#include "ntlog.h" + +static void fpga_temperature_sensor_read(struct nt_sensor_group *sg, + nthw_spis_t *t_spi) +{ + int temp = 0; + (void)t_spi; + if (sg == NULL || sg->sensor == NULL) { + NT_LOG(ERR, ETHDEV, "failed to read FPGA temperature\n"); + return; + } + struct nt_fpga_sensor_monitor *temp_monitor = sg->monitor; + uint32_t val = field_get_updated(temp_monitor->fields[0]); + + temp = (val * 20159 - 44752896) / 16384; + + update_sensor_value(sg->sensor, temp); +} + +struct nt_sensor_group *fpga_temperature_sensor_init(uint8_t adapter_no, + unsigned int sensor_idx, + nt_fpga_t *p_fpga) +{ + struct nt_sensor_group *sg = malloc(sizeof(struct nt_sensor_group)); + + if (sg == NULL) { + NT_LOG(ERR, ETHDEV, "%s: sensor group is NULL", __func__); + return NULL; + } + init_sensor_group(sg); + sg->monitor = tempmon_new(); + tempmon_init(sg->monitor, p_fpga); + sg->sensor = + allocate_sensor(adapter_no, "FPGA", NT_SENSOR_SOURCE_ADAPTER, + NT_SENSOR_TYPE_TEMPERATURE, sensor_idx, + NT_SENSOR_DISABLE_ALARM, SENSOR_MON_UNSIGNED); + sg->read = &fpga_temperature_sensor_read; + return sg; +} diff --git a/drivers/net/ntnic/sensors/board_sensors/board_sensors.h b/drivers/net/ntnic/sensors/board_sensors/board_sensors.h new file mode 100644 index 0000000000..a7f75b7ae4 --- /dev/null +++ b/drivers/net/ntnic/sensors/board_sensors/board_sensors.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _BOARD_SENSORS_H +#define _BOARD_SENSORS_H + +#include + +#include "sensors.h" + +#include "nthw_fpga_model.h" + +struct nt_sensor_group *fpga_temperature_sensor_init(uint8_t adapter_no, + unsigned int sensor_idx, + nt_fpga_t *p_fpga); + +#endif /* _BOARD_SENSORS_H */ diff --git a/drivers/net/ntnic/sensors/board_sensors/tempmon.c b/drivers/net/ntnic/sensors/board_sensors/tempmon.c new file mode 100644 index 0000000000..2cd3709205 --- /dev/null +++ b/drivers/net/ntnic/sensors/board_sensors/tempmon.c @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "tempmon.h" +#include "ntlog.h" +#include "nthw_register.h" + +struct nt_fpga_sensor_monitor *tempmon_new(void) +{ + struct nt_fpga_sensor_monitor *temp = + malloc(sizeof(struct nt_fpga_sensor_monitor)); + if (temp == NULL) + NT_LOG(ERR, ETHDEV, "%s: monitor is NULL\n", __func__); + return temp; +} + +void tempmon_init(struct nt_fpga_sensor_monitor *t, nt_fpga_t *p_fpga) +{ + if (t == NULL || p_fpga == NULL) { + NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__); + return; + } + /* fetch initialized module */ + t->fpga = p_fpga; + t->mod = nthw_get_module(t->fpga, MOD_TEMPMON, 0); + if (t->mod == NULL) + NT_LOG(ERR, ETHDEV, "module is NULL\n"); + /* fetch register */ + t->reg = module_get_register(t->mod, TEMPMON_STAT); + if (t->reg == NULL) + NT_LOG(ERR, ETHDEV, "register is NULL\n"); + /* fetch fields */ + t->fields = malloc(sizeof(nt_field_t *)); + if (t->fields == NULL) { + NT_LOG(ERR, ETHDEV, "%s: field is NULL", __func__); + return; + } + t->fields[0] = register_get_field(t->reg, TEMPMON_STAT_TEMP); + if (t->fields[0] == NULL) + NT_LOG(ERR, ETHDEV, "field is NULL\n"); +} diff --git a/drivers/net/ntnic/sensors/board_sensors/tempmon.h b/drivers/net/ntnic/sensors/board_sensors/tempmon.h new file mode 100644 index 0000000000..6f2017b714 --- /dev/null +++ b/drivers/net/ntnic/sensors/board_sensors/tempmon.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _TEMPMON_H +#define _TEMPMON_H + +#include "nthw_fpga_model.h" +#include + +#include "sensors.h" + +struct nt_fpga_sensor_monitor *tempmon_new(void); +void tempmon_init(struct nt_fpga_sensor_monitor *t, nt_fpga_t *p_fpga); + +#endif /* _TEMPMON_H */ diff --git a/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.c b/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.c new file mode 100644 index 0000000000..e130855a35 --- /dev/null +++ b/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.c @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include + +#include "nim_sensors.h" +#include "ntlog.h" + +#define TEMP NT_SENSOR_TYPE_TEMPERATURE +#define VOLT NT_SENSOR_TYPE_VOLTAGE +#define CURR NT_SENSOR_TYPE_CURRENT +#define PWR NT_SENSOR_TYPE_POWER + +#define SNA NT_SENSOR_SUBTYPE_NA +#define AVG NT_SENSOR_SUBTYPE_POWER_AVERAGE + +#define ENA NT_SENSOR_ENABLE_ALARM +#define DIA NT_SENSOR_DISABLE_ALARM + +/* + * Sensors for SFP/SFP+/SFP28. The name of the level 0 temperature sensor is + * empty and will then be set automatically + */ +struct nt_adapter_sensor_description sfp_sensors_level0[1] = { + { TEMP, SNA, NT_SENSOR_SFP_TEMP, DIA, "" }, +}; + +struct nt_adapter_sensor_description sfp_sensors_level1[4] = { + { VOLT, SNA, NT_SENSOR_SFP_SUPPLY, DIA, "Supply" }, + { CURR, SNA, NT_SENSOR_SFP_TX_BIAS, DIA, "Tx Bias" }, + { PWR, AVG, NT_SENSOR_SFP_TX_POWER, DIA, "Tx" }, + { PWR, AVG, NT_SENSOR_SFP_RX_POWER, DIA, "Rx" } +}; + +struct nt_adapter_sensor_description qsfp_sensor_level0[1] = { + { TEMP, SNA, NT_SENSOR_QSFP_TEMP, DIA, "" }, +}; + +struct nt_adapter_sensor_description qsfp_sensor_level1[13] = { + { VOLT, SNA, NT_SENSOR_QSFP_SUPPLY, DIA, "Supply" }, + { CURR, SNA, NT_SENSOR_QSFP_TX_BIAS1, DIA, "Tx Bias 1" }, + { CURR, SNA, NT_SENSOR_QSFP_TX_BIAS2, DIA, "Tx Bias 2" }, + { CURR, SNA, NT_SENSOR_QSFP_TX_BIAS3, DIA, "Tx Bias 3" }, + { CURR, SNA, NT_SENSOR_QSFP_TX_BIAS4, DIA, "Tx Bias 4" }, + { PWR, AVG, NT_SENSOR_QSFP_TX_POWER1, DIA, "Tx 1" }, + { PWR, AVG, NT_SENSOR_QSFP_TX_POWER2, DIA, "Tx 2" }, + { PWR, AVG, NT_SENSOR_QSFP_TX_POWER3, DIA, "Tx 3" }, + { PWR, AVG, NT_SENSOR_QSFP_TX_POWER4, DIA, "Tx 4" }, + { PWR, AVG, NT_SENSOR_QSFP_RX_POWER1, DIA, "Rx 1" }, + { PWR, AVG, NT_SENSOR_QSFP_RX_POWER2, DIA, "Rx 2" }, + { PWR, AVG, NT_SENSOR_QSFP_RX_POWER3, DIA, "Rx 3" }, + { PWR, AVG, NT_SENSOR_QSFP_RX_POWER4, DIA, "Rx 4" } +}; diff --git a/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.h b/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.h new file mode 100644 index 0000000000..c68c9aa924 --- /dev/null +++ b/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NIM_SENSORS_H +#define _NIM_SENSORS_H + +#include +#include +#include "sensors.h" + +#define XFP_TEMP_LIN_ADDR 96 + +extern struct nt_adapter_sensor_description sfp_sensors_level0[1]; +extern struct nt_adapter_sensor_description sfp_sensors_level1[4]; +extern struct nt_adapter_sensor_description qsfp_sensor_level0[1]; +extern struct nt_adapter_sensor_description qsfp_sensor_level1[13]; + +#endif /* _NIM_SENSORS_H */ diff --git a/drivers/net/ntnic/sensors/ntavr/avr_intf.h b/drivers/net/ntnic/sensors/ntavr/avr_intf.h new file mode 100644 index 0000000000..feeec6e13a --- /dev/null +++ b/drivers/net/ntnic/sensors/ntavr/avr_intf.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _AVR_INTF +#define _AVR_INTF + +#include + +#define SENSOR_MON_UINT16_NAN 0xFFFF /* Most positive number used as NaN */ +#define SENSOR_MON_INT16_NAN \ + ((int16_t)0x8000) /* Most negative number used as NaN */ + +/* + * Specify the nature of the raw data. AVR and ntservice must use this + * information when comparing or converting to native format which is little endian + */ +enum sensor_mon_endian { SENSOR_MON_LITTLE_ENDIAN, SENSOR_MON_BIG_ENDIAN }; + +enum sensor_mon_sign { + SENSOR_MON_UNSIGNED, + SENSOR_MON_SIGNED, /* 2's complement */ +}; + +/* Define sensor devices */ +enum sensor_mon_device { + SENSOR_MON_PSU_EXAR_7724_0 = 0, /* NT40E3, NT100E3 */ + SENSOR_MON_PSU_EXAR_7724_1, /* NT40E3, NT100E3 */ + SENSOR_MON_PSU_LTM_4676_0, /* na NT100E3, page-0 */ + SENSOR_MON_PSU_LTM_4676_1, /* na NT100E3, page-0 */ + SENSOR_MON_INA219_1, /* NT40E3, NT100E3 */ + SENSOR_MON_INA219_2, /* NT40E3, NT100E3 */ + SENSOR_MON_MAX6642, /* NT40E3, NT100E3 */ + SENSOR_MON_DS1775, /* NT40E3, NT100E3 */ + SENSOR_MON_FAN, /* NT40E3, NT100E3 */ + SENSOR_MON_AVR, /* NT40E3, NT100E3 */ + SENSOR_MON_PEX8734, /* na NT100E3 */ + SENSOR_MON_RATE_COUNT, /* NT40E3, NT100E3 */ + SENSOR_MON_PSU_LTM_4676_0_1, /* na NT100E3, page-1 */ + SENSOR_MON_PSU_LTM_4676_1_1, /* na NT100E3, page-1 */ + SENSOR_MON_MP2886A, /* na, na, NT200A02, */ + SENSOR_MON_PSU_EM2260_1, /* na, na, na, na, NT200D01^M */ + SENSOR_MON_PSU_EM2120_2, /* na, na, na, na, NT200D01^M */ + SENSOR_MON_MP2886A_PSU_1, /* na, na, na, NT200A02, na, NT50B01, */ + SENSOR_MON_MP8869S_PSU_2, /* na, na, na, NT200A02, na, NT50B01, */ + SENSOR_MON_MP8645PGVT_PSU_3, /* na, na, na, NT200A02, na, NT50B01, */ + SENSOR_MON_MP8645PGVT_PSU_4, /* na, na, na, NT200A02, na, NT50B01, */ + SENSOR_MON_MP8869S_PSU_5, /* na, na, na, NT200A02, na, NT50B01, */ + SENSOR_MON_MP8869S_PSU_6, /* na, na, na, NT200A02, na, NT50B01, */ + SENSOR_MON_DEVICE_COUNT +}; + +#pragma pack(1) +struct sensor_mon_setup_data16 { + uint8_t fpga_idx; /* Destination of results */ + uint8_t device; /* Device to monitor */ + uint8_t device_register; /* Sensor within device */ + uint16_t mask; /* Indicates active bits */ + uint8_t pos; /* Position of first active bit */ + uint16_t format; /* b0,1:sensor_mon_endian_t endian */ + /* b2,3:sensor_mon_sign_t sign */ + union { + struct { + int16_t limit_low; /* Signed alarm limit low */ + int16_t limit_high; /* Signed alarm limit high */ + } int16; + + struct { + uint16_t limit_low; /* Unsigned alarm limit low */ + uint16_t limit_high; /* Unsigned alarm limit high */ + } uint16; + }; +}; + +#pragma pack() +struct sensor_mon_setup16 { + uint8_t setup_cnt; /* Number of entries in setup_data */ + struct sensor_mon_setup_data16 setup_data[40]; +}; + +/* Define sensor monitoring control */ +enum sensor_mon_control { + SENSOR_MON_CTRL_STOP = 0, /* Stop sensor monitoring */ + SENSOR_MON_CTRL_RUN = 1, /* Start sensor monitoring */ + SENSOR_MON_CTRL_REM_ALL_SENSORS = + 2, /* Stop and remove all sensor monitoring setup */ +}; + +#endif /* _AVR_INTF */ diff --git a/drivers/net/ntnic/sensors/ntavr/ntavr.c b/drivers/net/ntnic/sensors/ntavr/ntavr.c new file mode 100644 index 0000000000..6d8c3042b1 --- /dev/null +++ b/drivers/net/ntnic/sensors/ntavr/ntavr.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntavr.h" +#include "ntlog.h" + +static int txrx(nthw_spi_v3_t *s_spi, enum avr_opcodes opcode, size_t txsz, + uint16_t *tx, size_t *rxsz, uint16_t *rx) +{ + int res = 1; + struct tx_rx_buf m_tx = { .size = (uint16_t)txsz, .p_buf = tx }; + struct tx_rx_buf m_rx = { .size = (uint16_t)*rxsz, .p_buf = rx }; + + res = nthw_spi_v3_transfer(s_spi, opcode, &m_tx, &m_rx); + if (res) { + NT_LOG(ERR, ETHDEV, "%s transfer failed - %i", __func__, res); + return res; + } + + if (rxsz != NULL) + *rxsz = m_rx.size; + + return res; +} + +uint32_t sensor_read(nthw_spis_t *t_spi, uint8_t fpga_idx, + uint32_t *p_sensor_result) +{ + return nthw_spis_read_sensor(t_spi, fpga_idx, p_sensor_result); +} + +int nt_avr_sensor_mon_setup(struct sensor_mon_setup16 *p_setup, nthw_spi_v3_t *s_spi) +{ + int error; + size_t tx_size; + size_t rx_size = 0; + + tx_size = sizeof(struct sensor_mon_setup16) - sizeof(p_setup->setup_data); + tx_size += sizeof(p_setup->setup_data[0]) * p_setup->setup_cnt; + + error = txrx(s_spi, AVR_OP_SENSOR_MON_SETUP, tx_size, (uint16_t *)p_setup, + &rx_size, NULL); + + if (error) { + NT_LOG(ERR, ETHDEV, "%s failed\n", __func__); + return error; + } + + if (rx_size != 0) { + NT_LOG(ERR, ETHDEV, + "%s: Returned data: Expected size = 0, Actual = %zu", + __func__, rx_size); + return 1; + } + return 0; +} + +int nt_avr_sensor_mon_ctrl(nthw_spi_v3_t *s_spi, enum sensor_mon_control ctrl) +{ + int error; + size_t rx_size = 0; + + error = txrx(s_spi, AVR_OP_SENSOR_MON_CONTROL, sizeof(ctrl), + (uint16_t *)(&ctrl), &rx_size, NULL); + + if (error != 0) + return error; + + if (rx_size != 0) { + NT_LOG(ERR, ETHDEV, + "%s: Returned data: Expected size = 0, Actual = %zu", + __func__, rx_size); + return 1; + } + + return 0; +} diff --git a/drivers/net/ntnic/sensors/ntavr/ntavr.h b/drivers/net/ntnic/sensors/ntavr/ntavr.h new file mode 100644 index 0000000000..b7a7aeb908 --- /dev/null +++ b/drivers/net/ntnic/sensors/ntavr/ntavr.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTAVR_H +#define _NTAVR_H + +#include +#include + +#include "avr_intf.h" +#include "nthw_drv.h" +#include "nthw_spi_v3.h" + +/* + * @internal + * @brief AVR Device Enum + * + * Global names for identifying an AVR device for Generation2 adapters + */ +enum ntavr_device { + NTAVR_MAINBOARD, /* Mainboard AVR device */ + NTAVR_FRONTBOARD /* Frontboard AVR device */ +}; + +int nt_avr_sensor_mon_setup(struct sensor_mon_setup16 *p_setup, + nthw_spi_v3_t *s_spi); +int nt_avr_sensor_mon_ctrl(nthw_spi_v3_t *s_spi, enum sensor_mon_control ctrl); +uint32_t sensor_read(nthw_spis_t *t_spi, uint8_t fpga_idx, + uint32_t *p_sensor_result); + +#endif /* _NTAVR_H */ diff --git a/drivers/net/ntnic/sensors/sensor_types.h b/drivers/net/ntnic/sensors/sensor_types.h new file mode 100644 index 0000000000..bac4e925f9 --- /dev/null +++ b/drivers/net/ntnic/sensors/sensor_types.h @@ -0,0 +1,259 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _SENSOR_TYPES_H +#define _SENSOR_TYPES_H + +/* + * Sensor types + */ +enum nt_sensor_type_e { + NT_SENSOR_TYPE_UNKNOWN = 0, + NT_SENSOR_TYPE_TEMPERATURE = 1, /* Unit: 0.1 degree Celsius */ + NT_SENSOR_TYPE_VOLTAGE = 2, /* Unit: 1 mV */ + NT_SENSOR_TYPE_CURRENT = 3, /* Unit: 1 uA */ + NT_SENSOR_TYPE_POWER = 4, /* Unit: 0.1 uW */ + NT_SENSOR_TYPE_FAN = 5, /* Unit: 1 RPM (Revolutions Per Minute) */ + NT_SENSOR_TYPE_HIGH_POWER = 6, /* Unit: 1 mW */ + NT_SENSOR_TYPE_NUMBER = 7, +}; + +/* + * Generic SFP/SFP+/SFP28 sensors + * + * These sensors should be used instead of all adapter specific SFP sensors + * that have been deprecated.. + */ +enum nt_sensors_sfp { + NT_SENSOR_SFP_TEMP, + NT_SENSOR_SFP_SUPPLY, + NT_SENSOR_SFP_TX_BIAS, + NT_SENSOR_SFP_TX_POWER, + NT_SENSOR_SFP_RX_POWER, +}; + +/* + * Generic QSFP/QSFP+/QSFP28 sensors + * + * These sensors should be used instead of all adapter specific QSFP sensors + * that have been deprecated.. + */ +enum nt_sensors_qsfp { + NT_SENSOR_QSFP_TEMP, + NT_SENSOR_QSFP_SUPPLY, + NT_SENSOR_QSFP_TX_BIAS1, + NT_SENSOR_QSFP_TX_BIAS2, + NT_SENSOR_QSFP_TX_BIAS3, + NT_SENSOR_QSFP_TX_BIAS4, + NT_SENSOR_QSFP_TX_POWER1, + NT_SENSOR_QSFP_TX_POWER2, + NT_SENSOR_QSFP_TX_POWER3, + NT_SENSOR_QSFP_TX_POWER4, + NT_SENSOR_QSFP_RX_POWER1, + NT_SENSOR_QSFP_RX_POWER2, + NT_SENSOR_QSFP_RX_POWER3, + NT_SENSOR_QSFP_RX_POWER4, +}; + +typedef enum nt_sensor_type_e nt_sensor_type_t; + +/* + * Sensor subtypes + */ +enum nt_sensor_sub_type_e { + NT_SENSOR_SUBTYPE_NA = 0, + /* + * Subtype for NT_SENSOR_TYPE_POWER type on optical modules (optical modulation + * amplitude measured) + */ + NT_SENSOR_SUBTYPE_POWER_OMA, + /* Subtype for NT_SENSOR_TYPE_POWER type on optical modules (average power measured) */ + NT_SENSOR_SUBTYPE_POWER_AVERAGE, + /* Subtype for NT_SENSOR_TYPE_HIGH_POWER type on adapters (total power consumption) */ + NT_SENSOR_SUBTYPE_POWER_TOTAL +}; + +typedef enum nt_sensor_sub_type_e nt_sensor_sub_type_t; + +/* + * Sensor source + */ +enum nt_sensor_source_e { + NT_SENSOR_SOURCE_UNKNOWN = 0x00, /* Unknown source */ + /* + * Sensors located in a port. These are primary sensors - usually NIM temperature. Presence + * depends on adapter and NIM type. + */ + NT_SENSOR_SOURCE_PORT = + 0x01, + /* + * Level 1 sensors located in a port. These are secondary sensors - usually NIM supply + * voltage, Tx bias and Rx/Tx optical power. Presence depends on adapter and NIM type. + */ + NT_SENSOR_SOURCE_LEVEL1_PORT = + 0x02, +#ifndef DOXYGEN_INTERNAL_ONLY + NT_SENSOR_SOURCE_LEVEL2_PORT = + 0x04, /* Level 2 sensors located in a port */ +#endif + NT_SENSOR_SOURCE_ADAPTER = 0x08, /* Sensors mounted on the adapter */ + NT_SENSOR_SOURCE_LEVEL1_ADAPTER = + 0x10, /* Level 1 sensors mounted on the adapter */ +#ifndef DOXYGEN_INTERNAL_ONLY + NT_SENSOR_SOURCE_LEVEL2_ADAPTER = + 0x20, /* Level 2 sensors mounted on the adapter */ +#endif +}; + +/* + * Sensor state + */ +enum nt_sensor_state_e { + NT_SENSOR_STATE_UNKNOWN = 0, /* Unknown state */ + NT_SENSOR_STATE_INITIALIZING = 1, /* The sensor is initializing */ + NT_SENSOR_STATE_NORMAL = 2, /* Sensor values are within range */ + NT_SENSOR_STATE_ALARM = 3, /* Sensor values are out of range */ + NT_SENSOR_STATE_NOT_PRESENT = + 4 /* The sensor is not present, for example, SFP without diagnostics */ +}; + +typedef enum nt_sensor_state_e nt_sensor_state_t; + +/* + * Sensor value + */ +#define NT_SENSOR_NAN \ + (0x80000000) /* Indicates that sensor value or sensor limit is not valid (Not a Number) */ + +/* + * Master/Slave + */ +enum nt_bonding_type_e { + NT_BONDING_UNKNOWN, /* Unknown bonding type */ + NT_BONDING_MASTER, /* Adapter is master in the bonding */ + NT_BONDING_SLAVE, /* Adapter is slave in the bonding */ + NT_BONDING_PEER /* Adapter is bonded, but relationship is symmetric */ +}; + +enum nt_sensors_e { + /* Public sensors (Level 0) */ + NT_SENSOR_FPGA_TEMP, /* FPGA temperature sensor */ +}; + +/* + * Adapter types + */ +enum nt_adapter_type_e { + NT_ADAPTER_TYPE_UNKNOWN = 0, /* Unknown adapter type */ + NT_ADAPTER_TYPE_NT4E, /* NT4E network adapter */ + NT_ADAPTER_TYPE_NT20E, /* NT20E network adapter */ + NT_ADAPTER_TYPE_NT4E_STD, /* NT4E-STD network adapter */ + NT_ADAPTER_TYPE_NT4E_PORT, /* NTPORT4E expansion adapter */ + NT_ADAPTER_TYPE_NTBPE, /* NTBPE bypass adapter */ + NT_ADAPTER_TYPE_NT20E2, /* NT20E2 network adapter */ + NT_ADAPTER_TYPE_RESERVED1, /* Reserved */ + NT_ADAPTER_TYPE_RESERVED2, /* Reserved */ + NT_ADAPTER_TYPE_NT40E2_1, /* NT40E2-1 network adapter */ + NT_ADAPTER_TYPE_NT40E2_4, /* NT40E2-4 network adapter */ + NT_ADAPTER_TYPE_NT4E2_4T_BP, /* NT4E2-4T-BP bypass network adapter */ + NT_ADAPTER_TYPE_NT4E2_4_PTP, /* NT4E2-4 PTP network adapter with IEEE1588 */ + NT_ADAPTER_TYPE_NT20E2_PTP, /* NT20E2 PTP network adapter with IEEE1588 */ + NT_ADAPTER_TYPE_NT40E3_4_PTP, /* NT40E3 network adapter with IEEE1588 */ + NT_ADAPTER_TYPE_NT100E3_1_PTP, /* NT100E3 network adapter with IEEE1588 */ + NT_ADAPTER_TYPE_NT20E3_2_PTP, /* NT20E3 network adapter with IEEE1588 */ + NT_ADAPTER_TYPE_NT80E3_2_PTP, /* NT80E3 network adapter with IEEE1588 */ + NT_ADAPTER_TYPE_NT200E3_2, /* NT200E3 network adapter */ + NT_ADAPTER_TYPE_NT200A01, /* NT200A01 network adapter */ + NT_ADAPTER_TYPE_NT200A01_2X100 = + NT_ADAPTER_TYPE_NT200A01, /* NT200A01 2 x 100 Gbps network adapter */ + NT_ADAPTER_TYPE_NT40A01_4X1, /* NT40A01_4X1 network adapter with IEEE1588 */ + NT_ADAPTER_TYPE_NT200A01_2X40, /* NT200A01 2 x 40 Gbps network adapter */ + NT_ADAPTER_TYPE_NT80E3_2_PTP_8X10, /* NT80E3 8 x 10 Gbps network adapter with IEEE1588 */ + /* */ + NT_ADAPTER_TYPE_INTEL_A10_4X10, /* Intel PAC A10 GX 4 x 10 Gbps network adapter */ + NT_ADAPTER_TYPE_INTEL_A10_1X40, /* Intel PAC A10 GX 1 x 40 Gbps network adapter */ + /* */ + NT_ADAPTER_TYPE_NT200A01_8X10, /* NT200A01 8 x 10 Gbps network adapter */ + NT_ADAPTER_TYPE_NT200A02_2X100, /* NT200A02 2 x 100 Gbps network adapter */ + NT_ADAPTER_TYPE_NT200A02_2X40, /* NT200A02 2 x 40 Gbps network adapter */ + NT_ADAPTER_TYPE_NT200A01_2X25, /* Deprecated */ + NT_ADAPTER_TYPE_NT200A01_2X10_25 = + NT_ADAPTER_TYPE_NT200A01_2X25, /* NT200A01 2 x 10/25 Gbps network adapter */ + NT_ADAPTER_TYPE_NT200A02_2X25, /* Deprecated */ + NT_ADAPTER_TYPE_NT200A02_2X10_25 = + NT_ADAPTER_TYPE_NT200A02_2X25, /* NT200A02 2 x 10/25 Gbps network adapter */ + NT_ADAPTER_TYPE_NT200A02_4X25, /* Deprecated */ + NT_ADAPTER_TYPE_NT200A02_4X10_25 = + NT_ADAPTER_TYPE_NT200A02_4X25, /* NT200A02 4 x 10/25 Gbps network adapter */ + NT_ADAPTER_TYPE_NT200A02_8X10, /* NT200A02 8 x 10 Gbps network adapter */ + NT_ADAPTER_TYPE_NT50B01_2X25, /* Deprecated */ + NT_ADAPTER_TYPE_NT50B01_2X10_25 = + NT_ADAPTER_TYPE_NT50B01_2X25, /* NT50B01 2 x 10/25 Gbps network adapter */ + NT_ADAPTER_TYPE_NT200A02_2X1_10, /* NT200A02 2 x 1/10 Gbps network adapter */ + NT_ADAPTER_TYPE_NT100A01_4X1_10, /* NT100A01 4 x 1/10 Gbps network adapter */ + NT_ADAPTER_TYPE_NT100A01_4X10_25, /* NT100A01 4 x 10/25 Gbps network adapter */ + NT_ADAPTER_TYPE_NT50B01_2X1_10, /* NT50B01 2 x 1/10 Gbps network adapter */ + NT_ADAPTER_TYPE_NT40A11_4X1_10, /* NT40A11 4 x 1/10 Gbps network adapter */ +#ifndef DOXYGEN_INTERNAL_ONLY + NT_ADAPTER_TYPE_ML605 = 10000, /* NT20E2 eval board */ +#endif + NT_ADAPTER_TYPE_4GARCH_HAMOA = + (1U + << 29), /* Bit to mark to adapters as a 4GArch Hamoa adapter */ + NT_ADAPTER_TYPE_4GARCH = + (1U << 30), /* Bit to mark to adapters as a 4GArch adapter */ + /* NOTE: do *NOT* add normal adapters after the group bit mark enums */ +}; + +/* The NT200E3 adapter sensor id's */ +typedef enum nt_sensors_adapter_nt200_e3_e { + /* Public sensors (Level 0) */ + NT_SENSOR_NT200E3_FPGA_TEMP, /* FPGA temperature sensor */ + NT_SENSOR_NT200E3_FAN_SPEED, /* FAN speed sensor */ + /* MCU (Micro Controller Unit) temperature sensor located inside enclosure below FAN */ + NT_SENSOR_NT200E3_MCU_TEMP, + NT_SENSOR_NT200E3_PSU0_TEMP, /* Power supply 0 temperature sensor */ + NT_SENSOR_NT200E3_PSU1_TEMP, /* Power supply 1 temperature sensor */ + NT_SENSOR_NT200E3_PCB_TEMP, /* PCB temperature sensor */ + + /* Diagnostic sensors (Level 1) */ + /* Total power consumption (calculated value) - does not generate alarms */ + NT_SENSOR_NT200E3_NT200E3_POWER, + /* FPGA power consumption (calculated value) - does not generate alarms */ + NT_SENSOR_NT200E3_FPGA_POWER, + /* DDR4 RAM power consumption (calculated value) - does not generate alarms */ + NT_SENSOR_NT200E3_DDR4_POWER, + /* NIM power consumption (calculated value) - does not generate alarms */ + NT_SENSOR_NT200E3_NIM_POWER, + + NT_SENSOR_NT200E3_L1_MAX, /* Number of NT200E3 level 0,1 board sensors */ +} nt_sensors_adapter_nt200_e3_t; + +/* + * The following sensors are deprecated - generic types should be used instead + * The NIM temperature sensor must be the one with the lowest sensor_index + * (enum value) in order to be shown by the monitoring tool in port mode + */ +enum nt_sensors_port_nt200_e3_2_e { + /* Public sensors */ + NT_SENSOR_NT200E3_NIM, /* QSFP28 temperature sensor */ + + /* Diagnostic sensors (Level 1) */ + NT_SENSOR_NT200E3_SUPPLY, /* QSFP28 supply voltage sensor */ + NT_SENSOR_NT200E3_TX_BIAS1, /* QSFP28 TX bias line 0 current sensor */ + NT_SENSOR_NT200E3_TX_BIAS2, /* QSFP28 TX bias line 1 current sensor */ + NT_SENSOR_NT200E3_TX_BIAS3, /* QSFP28 TX bias line 2 current sensor */ + NT_SENSOR_NT200E3_TX_BIAS4, /* QSFP28 TX bias line 3 current sensor */ + NT_SENSOR_NT200E3_RX1, /* QSFP28 RX line 0 power sensor */ + NT_SENSOR_NT200E3_RX2, /* QSFP28 RX line 1 power sensor */ + NT_SENSOR_NT200E3_RX3, /* QSFP28 RX line 2 power sensor */ + NT_SENSOR_NT200E3_RX4, /* QSFP28 RX line 3 power sensor */ + NT_SENSOR_NT200E3_TX1, /* QSFP28 TX line 0 power sensor */ + NT_SENSOR_NT200E3_TX2, /* QSFP28 TX line 1 power sensor */ + NT_SENSOR_NT200E3_TX3, /* QSFP28 TX line 2 power sensor */ + NT_SENSOR_NT200E3_TX4, /* QSFP28 TX line 3 power sensor */ + NT_SENSOR_NT200E3_PORT_MAX, /* Number of NT200E3 port sensors */ +}; + +#endif diff --git a/drivers/net/ntnic/sensors/sensors.c b/drivers/net/ntnic/sensors/sensors.c new file mode 100644 index 0000000000..2a85843196 --- /dev/null +++ b/drivers/net/ntnic/sensors/sensors.c @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "sensors.h" +#include "ntlog.h" + +void sensor_deinit(struct nt_sensor_group *sg) +{ + if (sg) { + if (sg->sensor) + free(sg->sensor); + if (sg->monitor) + free(sg->monitor); + free(sg); + } +} + +struct nt_adapter_sensor * +allocate_sensor(uint8_t adapter_or_port_index, const char *p_name, + enum nt_sensor_source_e ssrc, enum nt_sensor_type_e type, + unsigned int index, enum nt_sensor_event_alarm_e event_alarm, + enum sensor_mon_sign si) +{ + struct nt_adapter_sensor *sensor = + (struct nt_adapter_sensor *)malloc(sizeof(struct nt_adapter_sensor)); + if (sensor == NULL) { + NT_LOG(ERR, ETHDEV, "%s: sensor is NULL", __func__); + return NULL; + } + + sensor->alarm = event_alarm; + sensor->m_enable_alarm = true; + sensor->m_intf_no = 0xFF; + sensor->m_adapter_no = 0xFF; + sensor->si = si; + + sensor->info.source = ssrc; + sensor->info.source_index = adapter_or_port_index; + sensor->info.sensor_index = index; + sensor->info.type = type; + sensor->info.sub_type = NT_SENSOR_SUBTYPE_NA; + sensor->info.state = NT_SENSOR_STATE_INITIALIZING; + sensor->info.value = NT_SENSOR_NAN; + sensor->info.value_lowest = NT_SENSOR_NAN; + sensor->info.value_highest = NT_SENSOR_NAN; + memset(sensor->info.name, 0, NT_INFO_SENSOR_NAME); + memcpy(sensor->info.name, p_name, + (strlen(p_name) > NT_INFO_SENSOR_NAME) ? NT_INFO_SENSOR_NAME : + strlen(p_name)); + sensor->info.name[NT_INFO_SENSOR_NAME] = '\0'; + + return sensor; +} + +void update_sensor_value(struct nt_adapter_sensor *sensor, int32_t value) +{ + if (sensor == NULL) + return; + sensor->info.value = value; + if (sensor->info.value_highest < value || + (unsigned int)sensor->info.value_highest == NT_SENSOR_NAN) + sensor->info.value_highest = value; + if (sensor->info.value_lowest > value || + (unsigned int)sensor->info.value_lowest == NT_SENSOR_NAN) + sensor->info.value_lowest = value; +} + +struct nt_adapter_sensor * +allocate_sensor_by_description(uint8_t adapter_or_port_index, + enum nt_sensor_source_e ssrc, + struct nt_adapter_sensor_description *descr) +{ + struct nt_adapter_sensor *sensor = + (struct nt_adapter_sensor *)malloc(sizeof(struct nt_adapter_sensor)); + if (sensor == NULL) { + NT_LOG(ERR, ETHDEV, "%s: sensor is NULL", __func__); + return NULL; + } + + sensor->alarm = descr->event_alarm; + sensor->m_enable_alarm = true; + sensor->m_intf_no = 0xFF; + sensor->m_adapter_no = 0xFF; + sensor->si = SENSOR_MON_UNSIGNED; + + sensor->info.source_index = adapter_or_port_index; + sensor->info.source = ssrc; + sensor->info.type = descr->type; + sensor->info.sensor_index = descr->index; + memset(sensor->info.name, 0, NT_INFO_SENSOR_NAME); + memcpy(sensor->info.name, descr->name, + (strlen(descr->name) > NT_INFO_SENSOR_NAME) ? + NT_INFO_SENSOR_NAME : + strlen(descr->name)); + sensor->info.name[NT_INFO_SENSOR_NAME] = '\0'; + + return sensor; +} + +void init_sensor_group(struct nt_sensor_group *sg) +{ + /* Set all pointers to NULL */ + sg->sensor = NULL; + sg->monitor = NULL; + sg->next = NULL; + sg->read = NULL; + sg->conv_func = NULL; +} + +/* Getters */ +int32_t get_value(struct nt_sensor_group *sg) +{ + return sg->sensor->info.value; +}; + +int32_t get_lowest(struct nt_sensor_group *sg) +{ + return sg->sensor->info.value_lowest; +}; + +int32_t get_highest(struct nt_sensor_group *sg) +{ + return sg->sensor->info.value_highest; +}; + +char *get_name(struct nt_sensor_group *sg) +{ + return sg->sensor->info.name; +}; + +/* Conversion functions */ +int null_signed(uint32_t p_sensor_result) +{ + return (int16_t)p_sensor_result; +} + +int null_unsigned(uint32_t p_sensor_result) +{ + return (uint16_t)p_sensor_result; +} + +/* + * ****************************************************************************** + * For EXAR7724: Convert a read Vch value to Napatech internal representation + * Doc: Vout = ReadVal * 0.015 (PRESCALE is accounted for) + * ****************************************************************************** + */ +int exar7724_vch(uint32_t p_sensor_result) +{ + return p_sensor_result * 15; /* NT unit: 1mV */ +} + +/* + * ****************************************************************************** + * For EXAR7724: Convert a read Vin value to Napatech internal representation + * Doc: Vout = ReadVal * 0.0125 + * ****************************************************************************** + */ +int exar7724_vin(uint32_t p_sensor_result) +{ + return (p_sensor_result * 25) / 2; /* NT unit: 1mV */ +} + +/* + * ****************************************************************************** + * For EXAR7724: Convert a read Tj value to Napatech internal representation + * Doc: Temp (in Kelvin) = (((ReadVal * 10mV) - 600mV) / (2mV/K)) + 300K = + * = ReadVal * 5K + * ****************************************************************************** + */ +int exar7724_tj(uint32_t p_sensor_result) +{ + /* + * A value of 2730 is used instead of 2732 which is more correct but since + * the temperature step is 5 degrees it is more natural to show these steps + */ + return p_sensor_result * 50 - 2730; /* NT unit: 0.1C */ +} + +/* + * ****************************************************************************** + * Conversion function for Linear Tecnology Linear_5s_11s format. + * The functions returns Y * 2**N, where N = b[15:11] is a 5-bit two's complement + * integer and Y = b[10:0] is an 11-bit two's complement integer. + * The multiplier value is used for scaling to Napatech units. + * ****************************************************************************** + */ +static int conv5s_11s(uint16_t value, int multiplier) +{ + int n, y; + + y = value & 0x07FF; + + if (value & 0x0400) + y -= 0x0800; /* The MSBit is a sign bit */ + + n = (value >> 11) & 0x1F; + + if (n & 0x10) + n -= 0x20; /* The MSBit is a sign bit */ + + y *= multiplier; + + if (n > 0) + y *= (1 << n); + + else if (n < 0) + y /= (1 << (-n)); + + return y; +} + +/* + * ****************************************************************************** + * Temperature conversion from Linear_5s_11s format. + * ****************************************************************************** + */ +int ltm4676_tj(uint32_t p_sensor_result) +{ + return (uint16_t)conv5s_11s(p_sensor_result, 10); /* NT unit: 0.1C */ +} + +/* + * ****************************************************************************** + * For MP2886a: Convert a read Tj value to Napatech internal representation + * ****************************************************************************** + */ +int mp2886a_tj(uint32_t p_sensor_result) +{ + /* + * MPS-2886p: READ_TEMPERATURE (register 0x8Dh) + * READ_TEMPERATURE is a 2-byte, unsigned integer. + */ + return (uint16_t)p_sensor_result; /* NT unit: 0.1C */ +} + +/* + * ****************************************************************************** + * For MAX6642: Convert a read temperature value to Napatech internal representation + * ****************************************************************************** + */ +int max6642_t(uint32_t p_sensor_result) +{ + if ((p_sensor_result >> 8) == 0xFF) + return NT_SENSOR_NAN; + + /* The six lower bits are not used */ + return (int)(((p_sensor_result >> 6) * 5) / + 2); /* NT unit: 0.25 deg, Native unit: 0.1C */ +} + +/* + * ****************************************************************************** + * For DS1775: Convert a read temperature value to Napatech internal representation + * ****************************************************************************** + */ +int ds1775_t(uint32_t p_sensor_result) +{ + return (p_sensor_result * 10) / + 256; /* NT unit: 0.1 deg, Native unit: 1/256 C */ +} + +/* + * ****************************************************************************** + * For FAN: Convert a tick count to RPM + * NT unit: RPM, Native unit: 2 ticks/revolution + * ****************************************************************************** + */ +int fan(uint32_t p_sensor_result) +{ + return (p_sensor_result * 60U / 4); +} diff --git a/drivers/net/ntnic/sensors/sensors.h b/drivers/net/ntnic/sensors/sensors.h new file mode 100644 index 0000000000..1424b8bc83 --- /dev/null +++ b/drivers/net/ntnic/sensors/sensors.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _SENSORS_H +#define _SENSORS_H + +#include "sensor_types.h" +#include "stream_info.h" +#include "nthw_platform_drv.h" +#include "nthw_drv.h" +#include "nthw_spi_v3.h" +#include "nthw_fpga_model.h" + +#include +#include +#include +#include +#include +#include "avr_intf.h" + +enum nt_sensor_event_alarm_e { + NT_SENSOR_ENABLE_ALARM, + NT_SENSOR_LOG_ALARM, + NT_SENSOR_DISABLE_ALARM, +}; + +/* + * Sensor Class types + */ +enum nt_sensor_class_e { + NT_SENSOR_CLASS_FPGA = + 0, /* Class for FPGA based sensors e.g FPGA temperature */ + NT_SENSOR_CLASS_MCU = + 1, /* Class for MCU based sensors e.g MCU temperature */ + NT_SENSOR_CLASS_PSU = + 2, /* Class for PSU based sensors e.g PSU temperature */ + NT_SENSOR_CLASS_PCB = + 3, /* Class for PCB based sensors e.g PCB temperature */ + NT_SENSOR_CLASS_NIM = + 4, /* Class for NIM based sensors e.g NIM temperature */ + NT_SENSOR_CLASS_ANY = 5, /* Class for ANY sensors e.g any sensors */ +}; + +typedef enum nt_sensor_class_e nt_sensor_class_t; + +/* + * Port of the sensor class + */ +struct nt_adapter_sensor { + uint8_t m_adapter_no; + uint8_t m_intf_no; + uint8_t fpga_idx; /* for AVR sensors */ + enum sensor_mon_sign si; + struct nt_info_sensor_s info; + enum nt_sensor_event_alarm_e alarm; + bool m_enable_alarm; +}; + +struct nt_fpga_sensor_monitor { + nt_fpga_t *fpga; + nt_module_t *mod; + + nt_register_t *reg; + nt_field_t **fields; + uint8_t fields_num; +}; + +/* + * Sensor description. + * Describe the static behavior of the sensor. + */ +struct nt_adapter_sensor_description { + enum nt_sensor_type_e type; /* Sensor type. */ + enum nt_sensor_sub_type_e sub_type; /* Sensor subtype (if any applicable) */ + unsigned int index; /* Sensor group index. */ + enum nt_sensor_event_alarm_e event_alarm; /* Enable/Disable event alarm */ + char name[20]; /* Sensor name. */ +}; + +struct nt_sensor_group { + struct nt_adapter_sensor *sensor; + struct nt_fpga_sensor_monitor *monitor; + void (*read)(struct nt_sensor_group *sg, nthw_spis_t *t_spi); + + /* conv params are needed to call current conversion functions */ + int (*conv_func)(uint32_t p_sensor_result); + /* i2c interface for NIM sensors */ + + struct nt_sensor_group *next; +}; + +void init_sensor_group(struct nt_sensor_group *sg); + +void update_sensor_value(struct nt_adapter_sensor *sensor, int32_t value); + +void sensor_deinit(struct nt_sensor_group *sg); + +/* getters */ +int32_t get_value(struct nt_sensor_group *sg); +int32_t get_lowest(struct nt_sensor_group *sg); +int32_t get_highest(struct nt_sensor_group *sg); +char *get_name(struct nt_sensor_group *sg); + +struct nt_adapter_sensor * +allocate_sensor(uint8_t adapter_or_port_index, const char *p_name, + enum nt_sensor_source_e ssrc, enum nt_sensor_type_e type, + unsigned int index, enum nt_sensor_event_alarm_e event_alarm, + enum sensor_mon_sign si); +struct nt_adapter_sensor * +allocate_sensor_by_description(uint8_t adapter_or_port_index, + enum nt_sensor_source_e ssrc, + struct nt_adapter_sensor_description *descr); + +/* conversion functions */ +int null_signed(uint32_t p_sensor_result); +int null_unsigned(uint32_t p_sensor_result); +int exar7724_tj(uint32_t p_sensor_result); +int max6642_t(uint32_t p_sensor_result); +int ds1775_t(uint32_t p_sensor_result); +int ltm4676_tj(uint32_t p_sensor_result); +int exar7724_vch(uint32_t p_sensor_result); +int exar7724_vin(uint32_t p_sensor_result); +int mp2886a_tj(uint32_t p_sensor_result); +int fan(uint32_t p_sensor_result); + +#endif /* _SENSORS_H */ diff --git a/drivers/net/ntnic/sensors/stream_info.h b/drivers/net/ntnic/sensors/stream_info.h new file mode 100644 index 0000000000..b94231fd8b --- /dev/null +++ b/drivers/net/ntnic/sensors/stream_info.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _STREAM_INFO_H +#define _STREAM_INFO_H + +#include "sensor_types.h" + +#include + +/* + * This structure will return the sensor specific information + * + * The units used for the fields: value, value_lowest, value_highest, limit_low and + * limit_high depend on the type field. See @ref nt_sensor_type_e. + * + * For the limit_low and limit_high fields the following applies:\n + * If the sensor is located in a NIM (Network Interface Module), the limits are read + * from the NIM module via the DMI (Diagnostic Monitoring Interface) from the alarm + * and warning thresholds section, and the units are changed to internal representation. + * Only the alarm thresholds are used and are read only once during initialization. + * The limits cannot be changed. + * + * The value field is updated internally on a regular basis and is also based on a + * value read from the NIM which is also changed to internal representation. + * + * Not all NIM types support DMI data, and its presence must be determined by reading an + * option flag. In general, a NIM can read out: temperature, supply voltage, + * TX bias, TX optical power and RX optical power but not all NIM types support all + * 5 values. + * + * If external calibration is used (most NIM use internal calibration), both the + * current value and the threshold values are subjected to the specified calibration + * along with the change to internal calibration. + */ +#define NT_INFO_SENSOR_NAME 50 +struct nt_info_sensor_s { + enum nt_sensor_source_e + source; /* The source of the sensor (port or adapter on which the sensor resides) */ + /* + * The source index - the adapter number for adapter sensors and port number for port + * sensors + */ + uint32_t source_index; + /* + * The sensor index within the source index (sensor number on the adapter or sensor number + * on the port) + */ + uint32_t sensor_index; + enum nt_sensor_type_e type; /* The sensor type */ + enum nt_sensor_sub_type_e sub_type; /* The sensor subtype (if applicable) */ + enum nt_sensor_state_e state; /* The current state (normal or alarm) */ + int32_t value; /* The current value */ + int32_t value_lowest; /* The lowest value registered */ + int32_t value_highest; /* The highest value registered */ + char name[NT_INFO_SENSOR_NAME + 1]; /* The sensor name */ + enum nt_adapter_type_e + adapter_type; /* The adapter type where the sensor resides */ +}; + +/* The NT200A02 adapter sensor id's */ +enum nt_sensors_adapter_nt200a02_e { + /* Public sensors (Level 0) */ + NT_SENSOR_NT200A02_FPGA_TEMP, /* FPGA temperature sensor */ + NT_SENSOR_NT200A02_FAN_SPEED, /* FAN speed sensor */ + + NT_SENSOR_NT200A02_MCU_TEMP, + NT_SENSOR_NT200A02_PSU0_TEMP, /* Power supply 0 temperature sensor */ + NT_SENSOR_NT200A02_PSU1_TEMP, /* Power supply 1 temperature sensor */ + NT_SENSOR_NT200A02_PCB_TEMP, /* PCB temperature sensor */ + + /* Diagnostic sensors (Level 1) */ + /* Total power consumption (calculated value) - does not generate alarms */ + NT_SENSOR_NT200A02_NT200A02_POWER, + /* FPGA power consumption (calculated value) - does not generate alarms */ + NT_SENSOR_NT200A02_FPGA_POWER, + /* DDR4 RAM power consumption (calculated value) - does not generate alarms */ + NT_SENSOR_NT200A02_DDR4_POWER, + /* NIM power consumption (calculated value) - does not generate alarms */ + NT_SENSOR_NT200A02_NIM_POWER, + + NT_SENSOR_NT200A02_L1_MAX, /* Number of NT200A01 level 0,1 board sensors */ +}; + +#endif From patchwork Mon Aug 21 13:54:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mykola Kostenok X-Patchwork-Id: 130580 X-Patchwork-Delegate: thomas@monjalon.net 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 8811F430C1; Mon, 21 Aug 2023 15:54:48 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 717A843067; Mon, 21 Aug 2023 15:54:42 +0200 (CEST) Received: from egress-ip4a.ess.de.barracuda.com (egress-ip4a.ess.de.barracuda.com [18.184.203.227]) by mails.dpdk.org (Postfix) with ESMTP id 4477E427E9 for ; Mon, 21 Aug 2023 15:54:39 +0200 (CEST) Received: from EUR05-DB8-obe.outbound.protection.outlook.com (mail-db8eur05lp2109.outbound.protection.outlook.com [104.47.17.109]) by mx-outbound43-64.eu-central-1c.ess.aws.cudaops.com (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 21 Aug 2023 13:54:38 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=CFH2BHlYHM8OpIyIYmQGqTgCkav1ga1MFLi/L6KnPUp3nWb25TygmcjXlY0p4SwAptt+V3luKlKKhgM+dDw9lvYzvBdWrhM2Z0WwdKQ0AVhpqonZRZd070/ctpWfMnw8TMgTiyWPnb7PG35pwMvMhvxiAwlrNIb1WiUwDB9ANmUJHGi9b45DPfc/ktoCgLyjtctHUR5djQGsq6XtpL5zJGmScPKd2o/iLsUbf2JWrnxtKye+f3boV+R6rrmHrGN2a96jrp/DuYUz97mLiqP8pbBTxntXV2oSOwnPUXqCjW8lC5PROzrKyc7816XxqwV07D0/9OHsWhuzXwU0SEDPJg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=yODdj00HN0jLeIGBLFWM4uG20tVhsHHCD5uh3/1gBN4=; b=n5XITIwMmAv2onlyLLzNKcYMtmh/9PTx/u70NzOdfc0HcDGd/s9eaCn0DMYuXcSYMWzJmwG365WlXtCtoSnBpyWsADiN1k+I7D+bo9Dp/WQzjC925t6u+gYCdRR2zbb3RkTiKemzn913NuWjm7HMjJPB5SCaT9JoBFYBwbrZ2F2HuntJGOO1XnJfs1460KcrblWWnSfJf2pwSVYZ09jjyA0LPmVpLSSKfeOcuOZd62ausG6xJaORCLs60/hdNxALiMZcmvOPIrDfmA58oaxA553uWr+As18deRaMeH87kELX4BFzcM05WSQzEq3hbR5AkvWTqrr7jAVjz/jxiZoVAQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=fail (sender ip is 178.72.21.4) smtp.rcpttodomain=dpdk.org smtp.mailfrom=napatech.com; dmarc=fail (p=none sp=none pct=100) action=none header.from=napatech.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=napatech.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=yODdj00HN0jLeIGBLFWM4uG20tVhsHHCD5uh3/1gBN4=; b=MzhOmRDea36yqAJbrSf804/wknSQXCRgEfeKs5euPrbv1VECymGxvyw8NkSb5j3nBMvsuJ+5BVxpMNVUBx0pvt9dBJPG0ctgoBotU/tHtv1jydU0xHrSRka8W9awU+33pjwalbFHWUJM5mqtmrOB2xj570wsI2F5qJtUqZgWC8E= Received: from DB8PR04CA0012.eurprd04.prod.outlook.com (2603:10a6:10:110::22) by PA4P190MB1231.EURP190.PROD.OUTLOOK.COM (2603:10a6:102:10a::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.20; Mon, 21 Aug 2023 13:54:29 +0000 Received: from DU2PEPF0001E9C5.eurprd03.prod.outlook.com (2603:10a6:10:110:cafe::77) by DB8PR04CA0012.outlook.office365.com (2603:10a6:10:110::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.20 via Frontend Transport; Mon, 21 Aug 2023 13:54:29 +0000 X-MS-Exchange-Authentication-Results: spf=fail (sender IP is 178.72.21.4) smtp.mailfrom=napatech.com; dkim=none (message not signed) header.d=none;dmarc=fail action=none header.from=napatech.com; Received-SPF: Fail (protection.outlook.com: domain of napatech.com does not designate 178.72.21.4 as permitted sender) receiver=protection.outlook.com; client-ip=178.72.21.4; helo=localhost.localdomain.com; Received: from localhost.localdomain.com (178.72.21.4) by DU2PEPF0001E9C5.mail.protection.outlook.com (10.167.8.74) with Microsoft SMTP Server id 15.20.6699.14 via Frontend Transport; Mon, 21 Aug 2023 13:54:28 +0000 From: Mykola Kostenok To: dev@dpdk.org, mko-plv@napatech.com Cc: ckm@napatech.com Subject: [PATCH v6 4/8] net/ntnic: adds flow related FPGA functionality Date: Mon, 21 Aug 2023 15:54:22 +0200 Message-Id: <20230821135426.1478754-4-mko-plv@napatech.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20230821135426.1478754-1-mko-plv@napatech.com> References: <20230816132552.2483752-1-mko-plv@napatech.com> <20230821135426.1478754-1-mko-plv@napatech.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU2PEPF0001E9C5:EE_|PA4P190MB1231:EE_ X-MS-Office365-Filtering-Correlation-Id: 46469189-2050-4b7c-e314-08dba24e2394 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: +xqTN4YCxpJrEo+HDqgbzIlMg3ApkhUBSXQyPQXSBh53JgPYn+cdDjdup0/sCXhFVMKIg3J5cWRJ1Y4zZkPQBfIwnp1ghIgkoaXUiHtbwHCyfbl5R0UcNEDKyrqESTvMe75uVecOAtvz/oK5kcr4IOhtvY28YjWrY+fIefpCl9BCjyWPHzzGXydhmEUhZ9SnhSwdlCLi02Wi6zVxKHyJ8oReFdC8ox8loPkFja9hL1YhEDccUQ0jlI+vB+7UmCMGzaQCnPmPD9mGXKBwVKwg0vF2/VBzscJEQJaa6qM1q32zVQHiVBMHFlrbQ/6b2LOkzs3XxnZX/ZGEx6B6fnzD1fNTmqqEawdeGdZMHgvsyETxY/SO3O/Edl8WaXzVAhWf/SUO8nZXZyRBF4VXq9jzSY1o1AyzuvXmeaWGGIjGADvXjl9jYdY9T42hT/vNKJ3A4fyb7GzNvgtyA5/QqQjoLxLjVimwKA+82TtQI+hclCnXJHRScZgq3oe7YSMOGoo4jhRnrLRhaP36Zt6eV4cRbHd8qBNlv2gwbG0//ekH26R5PmfkdwcAmGxEoEoeHM1D6TPf275RH/IfmZ4Jj+6ZCEyxuezc4ErCQDItj77ZbN0oY/Ey2LjI8IBzK1RKdQG1+UGFvQKXcX/DAiidmO7AKkN6x4rh86WsDrxwHYuFv7p57YQjlhi+M8lfBbK7VVR5TscH6ORZoX/UoBEpI+9xn1ouU91kS+PHoJTuisw0A347q1LmmG5kj9HbGb2UhFPo92Bizvy8j/oV5cTV1zrtzg== X-Forefront-Antispam-Report: CIP:178.72.21.4; CTRY:DK; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:localhost.localdomain.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230031)(6069001)(39840400004)(136003)(346002)(396003)(376002)(451199024)(82310400011)(186009)(1800799009)(36840700001)(46966006)(2906002)(36736006)(4326008)(30864003)(5660300002)(8676002)(8936002)(316002)(41300700001)(70586007)(118246002)(70206006)(478600001)(6486002)(6666004)(6506007)(6512007)(956004)(1076003)(107886003)(26005)(336012)(2616005)(83380400001)(47076005)(34020700004)(36860700001)(356005)(81166007)(9316004)(86362001)(40480700001)(36756003)(36900700001)(579004)(559001); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: 9FWqBR1ZacZwo6ckno+hJNTAHpk1SKrEHC0zwHRtB1bKghHHQfkFejAX11GzJU6er7kskW2mRacgSsdnpWsF9I4megXpQCmtKoIbw3Bst4LGeKFtCynLpcHssUhR0erkZlQwPfQf2oYLMwVVKPISlVeSCe/IrPFPmBzcFoSf0mCm+9KVC2vsp3hX7KBIEU+rHy254HAZx/u2DvhNq8DDV2uySbavkMN210qupiiq7vb5e/0Dlc853CQKSClHubLxlPQ9Cq+Ku4geUwq13Fm8PBGk+5qolYNVuootd2sTDM5rDucshvf8QzlD8ro9fNnCPgeqJJn1CCHEe86UlKZRGCrrjzOBxwvXj2+aeSNrlag1ke5rMmGjB0j0GIhAci3s3kF7TR3TEzu7UkU22MpiJWVUsL8HAIhQblsgPLQRMkW4syaLHob73m/rw6XX6Bk2DrlkOaaqTDtRXRz1YWO8GROpyNU2Qsk3LQKIGcQRhJhG4TFIPgJydBrGpaw6hi+WMex/R1S5D88SVyLviIGR9b4Xqny79veAPoyNXph6wKJ5TOG3JC6B4z1+DMY37hjVf+1Qam5zORmVVWMQSqb+cH0GSUzgBejN7zkV8IplT+QmF8ZmKQtJKnLSAz9LjXfZAjtB6O/Fj2PPVEcSvjIMIkD1pGO+CQhilAVx5vsgeOOuEymv3UwylBMd9ME0UUGMsfq8/s0XxNLG9AUc1TSWp8TMCa7Qu182aoem4zi6h1mNoltgQebSym9Pv2UZoccn6vmNFrUhj0NIi+cvVrSe/4to5kWupqGj6FYwNjbRbyg= X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Aug 2023 13:54:28.9447 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 46469189-2050-4b7c-e314-08dba24e2394 X-MS-Exchange-CrossTenant-Id: c4540d0b-728a-4233-9da5-9ea30c7ec3ed X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=c4540d0b-728a-4233-9da5-9ea30c7ec3ed; Ip=[178.72.21.4]; Helo=[localhost.localdomain.com] X-MS-Exchange-CrossTenant-AuthSource: DU2PEPF0001E9C5.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PA4P190MB1231 X-BESS-ID: 1692626077-311072-12493-15882-1 X-BESS-VER: 2019.1_20230817.1828 X-BESS-Apparent-Source-IP: 104.47.17.109 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKVkaWlgamZkB2BlDYxNQgLTUpxc Ak0TLRyDwpKdkkySLN2NzA1Dw1yTQ1zUipNhYAY+auwEMAAAA= X-BESS-Outbound-Spam-Score: 0.00 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.250292 [from cloudscan17-132.eu-central-1b.ess.aws.cudaops.com] Rule breakdown below pts rule name description ---- ---------------------- -------------------------------- 0.00 LARGE_BODY_SHORTCUT META: X-BESS-Outbound-Spam-Status: SCORE=0.00 using account:ESS113687 scores of KILL_LEVEL=7.0 tests=LARGE_BODY_SHORTCUT X-BESS-BRTS-Status: 1 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 From: Christian Koue Muf The PMD will control the registers used for flow programming, and this commit adds support for this. Signed-off-by: Christian Koue Muf Reviewed-by: Mykola Kostenok --- v2: * Fixed compilation with Fedora 38 --- drivers/net/ntnic/meson.build | 21 + .../ntnic/nthw/flow_filter/flow_nthw_cat.c | 1107 ++++++++++++++++ .../ntnic/nthw/flow_filter/flow_nthw_cat.h | 372 ++++++ .../ntnic/nthw/flow_filter/flow_nthw_csu.c | 146 +++ .../ntnic/nthw/flow_filter/flow_nthw_csu.h | 42 + .../ntnic/nthw/flow_filter/flow_nthw_flm.c | 1140 +++++++++++++++++ .../ntnic/nthw/flow_filter/flow_nthw_flm.h | 422 ++++++ .../ntnic/nthw/flow_filter/flow_nthw_hfu.c | 293 +++++ .../ntnic/nthw/flow_filter/flow_nthw_hfu.h | 100 ++ .../ntnic/nthw/flow_filter/flow_nthw_hsh.c | 254 ++++ .../ntnic/nthw/flow_filter/flow_nthw_hsh.h | 81 ++ .../ntnic/nthw/flow_filter/flow_nthw_hst.c | 202 +++ .../ntnic/nthw/flow_filter/flow_nthw_hst.h | 72 ++ .../ntnic/nthw/flow_filter/flow_nthw_ifr.c | 93 ++ .../ntnic/nthw/flow_filter/flow_nthw_ifr.h | 39 + .../ntnic/nthw/flow_filter/flow_nthw_info.c | 341 +++++ .../ntnic/nthw/flow_filter/flow_nthw_info.h | 104 ++ .../ntnic/nthw/flow_filter/flow_nthw_ioa.c | 234 ++++ .../ntnic/nthw/flow_filter/flow_nthw_ioa.h | 80 ++ .../net/ntnic/nthw/flow_filter/flow_nthw_km.c | 685 ++++++++++ .../net/ntnic/nthw/flow_filter/flow_nthw_km.h | 224 ++++ .../ntnic/nthw/flow_filter/flow_nthw_pdb.c | 230 ++++ .../ntnic/nthw/flow_filter/flow_nthw_pdb.h | 84 ++ .../ntnic/nthw/flow_filter/flow_nthw_qsl.c | 355 +++++ .../ntnic/nthw/flow_filter/flow_nthw_qsl.h | 121 ++ .../ntnic/nthw/flow_filter/flow_nthw_rmc.c | 112 ++ .../ntnic/nthw/flow_filter/flow_nthw_rmc.h | 40 + .../ntnic/nthw/flow_filter/flow_nthw_roa.c | 294 +++++ .../ntnic/nthw/flow_filter/flow_nthw_roa.h | 109 ++ .../ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c | 132 ++ .../ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h | 53 + .../ntnic/nthw/flow_filter/flow_nthw_slc.c | 109 ++ .../ntnic/nthw/flow_filter/flow_nthw_slc.h | 46 + .../ntnic/nthw/flow_filter/flow_nthw_slc_lr.c | 109 ++ .../ntnic/nthw/flow_filter/flow_nthw_slc_lr.h | 46 + .../ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c | 394 ++++++ .../ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h | 72 ++ .../ntnic/nthw/flow_filter/flow_nthw_tx_ins.c | 96 ++ .../ntnic/nthw/flow_filter/flow_nthw_tx_ins.h | 42 + .../ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c | 165 +++ .../ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h | 70 + 41 files changed, 8731 insertions(+) create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build index 1571111bce..c4f0a912d3 100644 --- a/drivers/net/ntnic/meson.build +++ b/drivers/net/ntnic/meson.build @@ -24,6 +24,7 @@ includes = [ include_directories('nthw'), include_directories('nthw/core'), include_directories('nthw/supported'), + include_directories('nthw/flow_filter'), include_directories('sensors'), include_directories('sensors/avr_sensors'), include_directories('sensors/board_sensors'), @@ -65,6 +66,26 @@ sources = files( 'nthw/core/nthw_spim.c', 'nthw/core/nthw_spis.c', 'nthw/core/nthw_tsm.c', + 'nthw/flow_filter/flow_nthw_cat.c', + 'nthw/flow_filter/flow_nthw_csu.c', + 'nthw/flow_filter/flow_nthw_flm.c', + 'nthw/flow_filter/flow_nthw_hfu.c', + 'nthw/flow_filter/flow_nthw_hsh.c', + 'nthw/flow_filter/flow_nthw_hst.c', + 'nthw/flow_filter/flow_nthw_ifr.c', + 'nthw/flow_filter/flow_nthw_info.c', + 'nthw/flow_filter/flow_nthw_ioa.c', + 'nthw/flow_filter/flow_nthw_km.c', + 'nthw/flow_filter/flow_nthw_pdb.c', + 'nthw/flow_filter/flow_nthw_qsl.c', + 'nthw/flow_filter/flow_nthw_rmc.c', + 'nthw/flow_filter/flow_nthw_roa.c', + 'nthw/flow_filter/flow_nthw_rpp_lr.c', + 'nthw/flow_filter/flow_nthw_slc.c', + 'nthw/flow_filter/flow_nthw_slc_lr.c', + 'nthw/flow_filter/flow_nthw_tx_cpy.c', + 'nthw/flow_filter/flow_nthw_tx_ins.c', + 'nthw/flow_filter/flow_nthw_tx_rpl.c', 'nthw/nthw_fpga_model.c', 'nthw/nthw_dbs.c', 'nthw/nthw_epp.c', diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.c new file mode 100644 index 0000000000..91376363c1 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.c @@ -0,0 +1,1107 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_cat.h" + +#include /* malloc */ +#include /* memset */ + +struct cat_nthw *cat_nthw_new(void) +{ + struct cat_nthw *p = malloc(sizeof(struct cat_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + + return p; +} + +void cat_nthw_delete(struct cat_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +void cat_nthw_set_debug_mode(struct cat_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_cat, n_debug_mode); +} + +int cat_nthw_init(struct cat_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_CAT, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: Cat %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_cat = p_mod; + + p->m_km_if_cnt = fpga_get_product_param(p->mp_fpga, NT_CAT_KM_IF_CNT, -1); + + /* CFN */ + p->mp_cfn_ctrl = module_get_register(p->m_cat, CAT_CFN_CTRL); + p->mp_cfn_addr = register_get_field(p->mp_cfn_ctrl, CAT_CFN_CTRL_ADR); + p->mp_cfn_cnt = register_get_field(p->mp_cfn_ctrl, CAT_CFN_CTRL_CNT); + p->mp_cfn_data = module_get_register(p->m_cat, CAT_CFN_DATA); + p->mp_cfn_data_enable = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ENABLE); + p->mp_cfn_data_inv = register_get_field(p->mp_cfn_data, CAT_CFN_DATA_INV); + p->mp_cfn_data_ptc_inv = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_INV); + p->mp_cfn_data_ptc_isl = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_ISL); + p->mp_cfn_data_ptc_mac = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_MAC); + p->mp_cfn_data_ptc_l2 = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_L2); + p->mp_cfn_data_ptc_vn_tag = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_VNTAG); + p->mp_cfn_data_ptc_vlan = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_VLAN); + p->mp_cfn_data_ptc_mpls = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_MPLS); + p->mp_cfn_data_ptc_l3 = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_L3); + p->mp_cfn_data_ptc_frag = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_FRAG); + p->mp_cfn_data_ptc_ip_prot = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_IP_PROT); + p->mp_cfn_data_ptc_l4 = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_L4); + p->mp_cfn_data_ptc_tunnel = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TUNNEL); + p->mp_cfn_data_ptc_tnl_l2 = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_L2); + p->mp_cfn_data_ptc_tnl_vlan = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_VLAN); + p->mp_cfn_data_ptc_tnl_mpls = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_MPLS); + p->mp_cfn_data_ptc_tnl_l3 = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_L3); + p->mp_cfn_data_ptc_tnl_frag = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_FRAG); + p->mp_cfn_data_ptc_tnl_ip_prot = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_IP_PROT); + p->mp_cfn_data_ptc_tnl_l4 = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_L4); + p->mp_cfn_data_err_inv = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_INV); + p->mp_cfn_data_err_cv = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_CV); + p->mp_cfn_data_err_fcs = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_FCS); + p->mp_cfn_data_err_trunc = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TRUNC); + p->mp_cfn_data_mac_port = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_MAC_PORT); + p->mp_cfn_data_pm_cmp = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_CMP); + p->mp_cfn_data_pm_dct = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_DCT); + p->mp_cfn_data_pm_ext_inv = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_EXT_INV); + p->mp_cfn_data_pm_cmb = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_CMB); + p->mp_cfn_data_pm_and_inv = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_AND_INV); + p->mp_cfn_data_pm_or_inv = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_OR_INV); + p->mp_cfn_data_pm_inv = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_INV); + p->mp_cfn_data_lc = register_get_field(p->mp_cfn_data, CAT_CFN_DATA_LC); + p->mp_cfn_data_lc_inv = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_LC_INV); + + if (p->m_km_if_cnt == -1) { + p->mp_cfn_data_km0_or = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_KM_OR); + } else { + p->mp_cfn_data_km0_or = + register_get_field(p->mp_cfn_data, CAT_CFN_DATA_KM0_OR); + p->mp_cfn_data_km1_or = + register_query_field(p->mp_cfn_data, CAT_CFN_DATA_KM1_OR); + } + + if (p->m_km_if_cnt < 0) { + /* KCE */ + p->mp_kce_ctrl[0] = module_get_register(p->m_cat, CAT_KCE_CTRL); + p->mp_kce_addr[0] = + register_get_field(p->mp_kce_ctrl[0], CAT_KCE_CTRL_ADR); + p->mp_kce_cnt[0] = + register_get_field(p->mp_kce_ctrl[0], CAT_KCE_CTRL_CNT); + p->mp_kce_data[0] = module_get_register(p->m_cat, CAT_KCE_DATA); + p->mp_kce_data_enable[0] = + register_get_field(p->mp_kce_data[0], CAT_KCE_DATA_ENABLE); + /* KCS */ + p->mp_kcs_ctrl[0] = module_get_register(p->m_cat, CAT_KCS_CTRL); + p->mp_kcs_addr[0] = + register_get_field(p->mp_kcs_ctrl[0], CAT_KCS_CTRL_ADR); + p->mp_kcs_cnt[0] = + register_get_field(p->mp_kcs_ctrl[0], CAT_KCS_CTRL_CNT); + p->mp_kcs_data[0] = module_get_register(p->m_cat, CAT_KCS_DATA); + p->mp_kcs_data_category[0] = + register_get_field(p->mp_kcs_data[0], CAT_KCS_DATA_CATEGORY); + /* FTE */ + p->mp_fte_ctrl[0] = module_get_register(p->m_cat, CAT_FTE_CTRL); + p->mp_fte_addr[0] = + register_get_field(p->mp_fte_ctrl[0], CAT_FTE_CTRL_ADR); + p->mp_fte_cnt[0] = + register_get_field(p->mp_fte_ctrl[0], CAT_FTE_CTRL_CNT); + p->mp_fte_data[0] = module_get_register(p->m_cat, CAT_FTE_DATA); + p->mp_fte_data_enable[0] = + register_get_field(p->mp_fte_data[0], CAT_FTE_DATA_ENABLE); + } else { + /* KCE 0 */ + p->mp_kce_ctrl[0] = module_get_register(p->m_cat, CAT_KCE0_CTRL); + p->mp_kce_addr[0] = + register_get_field(p->mp_kce_ctrl[0], CAT_KCE0_CTRL_ADR); + p->mp_kce_cnt[0] = + register_get_field(p->mp_kce_ctrl[0], CAT_KCE0_CTRL_CNT); + p->mp_kce_data[0] = module_get_register(p->m_cat, CAT_KCE0_DATA); + p->mp_kce_data_enable[0] = register_get_field(p->mp_kce_data[0], + CAT_KCE0_DATA_ENABLE); + /* KCS 0 */ + p->mp_kcs_ctrl[0] = module_get_register(p->m_cat, CAT_KCS0_CTRL); + p->mp_kcs_addr[0] = + register_get_field(p->mp_kcs_ctrl[0], CAT_KCS0_CTRL_ADR); + p->mp_kcs_cnt[0] = + register_get_field(p->mp_kcs_ctrl[0], CAT_KCS0_CTRL_CNT); + p->mp_kcs_data[0] = module_get_register(p->m_cat, CAT_KCS0_DATA); + p->mp_kcs_data_category[0] = + register_get_field(p->mp_kcs_data[0], CAT_KCS0_DATA_CATEGORY); + /* FTE 0 */ + p->mp_fte_ctrl[0] = module_get_register(p->m_cat, CAT_FTE0_CTRL); + p->mp_fte_addr[0] = + register_get_field(p->mp_fte_ctrl[0], CAT_FTE0_CTRL_ADR); + p->mp_fte_cnt[0] = + register_get_field(p->mp_fte_ctrl[0], CAT_FTE0_CTRL_CNT); + p->mp_fte_data[0] = module_get_register(p->m_cat, CAT_FTE0_DATA); + p->mp_fte_data_enable[0] = register_get_field(p->mp_fte_data[0], + CAT_FTE0_DATA_ENABLE); + /* KCE 1 */ + p->mp_kce_ctrl[1] = module_get_register(p->m_cat, CAT_KCE1_CTRL); + p->mp_kce_addr[1] = + register_get_field(p->mp_kce_ctrl[1], CAT_KCE1_CTRL_ADR); + p->mp_kce_cnt[1] = + register_get_field(p->mp_kce_ctrl[1], CAT_KCE1_CTRL_CNT); + p->mp_kce_data[1] = module_get_register(p->m_cat, CAT_KCE1_DATA); + p->mp_kce_data_enable[1] = register_get_field(p->mp_kce_data[1], + CAT_KCE1_DATA_ENABLE); + /* KCS 1 */ + p->mp_kcs_ctrl[1] = module_get_register(p->m_cat, CAT_KCS1_CTRL); + p->mp_kcs_addr[1] = + register_get_field(p->mp_kcs_ctrl[1], CAT_KCS1_CTRL_ADR); + p->mp_kcs_cnt[1] = + register_get_field(p->mp_kcs_ctrl[1], CAT_KCS1_CTRL_CNT); + p->mp_kcs_data[1] = module_get_register(p->m_cat, CAT_KCS1_DATA); + p->mp_kcs_data_category[1] = + register_get_field(p->mp_kcs_data[1], CAT_KCS1_DATA_CATEGORY); + /* FTE 1 */ + p->mp_fte_ctrl[1] = module_get_register(p->m_cat, CAT_FTE1_CTRL); + p->mp_fte_addr[1] = + register_get_field(p->mp_fte_ctrl[1], CAT_FTE1_CTRL_ADR); + p->mp_fte_cnt[1] = + register_get_field(p->mp_fte_ctrl[1], CAT_FTE1_CTRL_CNT); + p->mp_fte_data[1] = module_get_register(p->m_cat, CAT_FTE1_DATA); + p->mp_fte_data_enable[1] = register_get_field(p->mp_fte_data[1], + CAT_FTE1_DATA_ENABLE); + } + + /* CTE */ + p->mp_cte_ctrl = module_get_register(p->m_cat, CAT_CTE_CTRL); + p->mp_cte_addr = register_get_field(p->mp_cte_ctrl, CAT_CTE_CTRL_ADR); + p->mp_cte_cnt = register_get_field(p->mp_cte_ctrl, CAT_CTE_CTRL_CNT); + p->mp_cte_data = module_get_register(p->m_cat, CAT_CTE_DATA); + p->mp_cte_data_col = + register_get_field(p->mp_cte_data, CAT_CTE_DATA_COL_ENABLE); + p->mp_cte_data_cor = + register_get_field(p->mp_cte_data, CAT_CTE_DATA_COR_ENABLE); + p->mp_cte_data_hsh = + register_get_field(p->mp_cte_data, CAT_CTE_DATA_HSH_ENABLE); + p->mp_cte_data_qsl = + register_get_field(p->mp_cte_data, CAT_CTE_DATA_QSL_ENABLE); + p->mp_cte_data_ipf = + register_get_field(p->mp_cte_data, CAT_CTE_DATA_IPF_ENABLE); + p->mp_cte_data_slc = + register_get_field(p->mp_cte_data, CAT_CTE_DATA_SLC_ENABLE); + p->mp_cte_data_pdb = + register_get_field(p->mp_cte_data, CAT_CTE_DATA_PDB_ENABLE); + p->mp_cte_data_msk = + register_query_field(p->mp_cte_data, CAT_CTE_DATA_MSK_ENABLE); + p->mp_cte_data_hst = + register_query_field(p->mp_cte_data, CAT_CTE_DATA_HST_ENABLE); + p->mp_cte_data_epp = + register_query_field(p->mp_cte_data, CAT_CTE_DATA_EPP_ENABLE); + p->mp_cte_data_tpe = + register_query_field(p->mp_cte_data, CAT_CTE_DATA_TPE_ENABLE); + p->mp_cte_data_rrb = + register_query_field(p->mp_cte_data, CAT_CTE_DATA_RRB_ENABLE); + /* CTS */ + p->mp_cts_ctrl = module_get_register(p->m_cat, CAT_CTS_CTRL); + p->mp_cts_addr = register_get_field(p->mp_cts_ctrl, CAT_CTS_CTRL_ADR); + p->mp_cts_cnt = register_get_field(p->mp_cts_ctrl, CAT_CTS_CTRL_CNT); + p->mp_cts_data = module_get_register(p->m_cat, CAT_CTS_DATA); + p->mp_cts_data_cat_a = register_get_field(p->mp_cts_data, CAT_CTS_DATA_CAT_A); + p->mp_cts_data_cat_b = register_get_field(p->mp_cts_data, CAT_CTS_DATA_CAT_B); + /* COT */ + p->mp_cot_ctrl = module_get_register(p->m_cat, CAT_COT_CTRL); + p->mp_cot_addr = register_get_field(p->mp_cot_ctrl, CAT_COT_CTRL_ADR); + p->mp_cot_cnt = register_get_field(p->mp_cot_ctrl, CAT_COT_CTRL_CNT); + p->mp_cot_data = module_get_register(p->m_cat, CAT_COT_DATA); + p->mp_cot_data_color = register_get_field(p->mp_cot_data, CAT_COT_DATA_COLOR); + p->mp_cot_data_km = register_get_field(p->mp_cot_data, CAT_COT_DATA_KM); + p->mp_cot_data_nfv_sb = + register_query_field(p->mp_cot_data, CAT_COT_DATA_NFV_SB); + /* CCT */ + p->mp_cct_ctrl = module_get_register(p->m_cat, CAT_CCT_CTRL); + p->mp_cct_addr = register_get_field(p->mp_cct_ctrl, CAT_CCT_CTRL_ADR); + p->mp_cct_cnt = register_get_field(p->mp_cct_ctrl, CAT_CCT_CTRL_CNT); + p->mp_cct_data = module_get_register(p->m_cat, CAT_CCT_DATA); + p->mp_cct_data_color = register_get_field(p->mp_cct_data, CAT_CCT_DATA_COLOR); + p->mp_cct_data_km = register_get_field(p->mp_cct_data, CAT_CCT_DATA_KM); + /* EXO */ + p->mp_exo_ctrl = module_get_register(p->m_cat, CAT_EXO_CTRL); + p->mp_exo_addr = register_get_field(p->mp_exo_ctrl, CAT_EXO_CTRL_ADR); + p->mp_exo_cnt = register_get_field(p->mp_exo_ctrl, CAT_EXO_CTRL_CNT); + p->mp_exo_data = module_get_register(p->m_cat, CAT_EXO_DATA); + p->mp_exo_data_dyn = register_get_field(p->mp_exo_data, CAT_EXO_DATA_DYN); + p->mp_exo_data_ofs = register_get_field(p->mp_exo_data, CAT_EXO_DATA_OFS); + /* RCK */ + p->mp_rck_ctrl = module_get_register(p->m_cat, CAT_RCK_CTRL); + p->mp_rck_addr = register_get_field(p->mp_rck_ctrl, CAT_RCK_CTRL_ADR); + p->mp_rck_cnt = register_get_field(p->mp_rck_ctrl, CAT_RCK_CTRL_CNT); + p->mp_rck_data = module_get_register(p->m_cat, CAT_RCK_DATA); + /* LEN */ + p->mp_len_ctrl = module_get_register(p->m_cat, CAT_LEN_CTRL); + p->mp_len_addr = register_get_field(p->mp_len_ctrl, CAT_LEN_CTRL_ADR); + p->mp_len_cnt = register_get_field(p->mp_len_ctrl, CAT_LEN_CTRL_CNT); + p->mp_len_data = module_get_register(p->m_cat, CAT_LEN_DATA); + p->mp_len_data_lower = register_get_field(p->mp_len_data, CAT_LEN_DATA_LOWER); + p->mp_len_data_upper = register_get_field(p->mp_len_data, CAT_LEN_DATA_UPPER); + p->mp_len_data_dyn1 = register_get_field(p->mp_len_data, CAT_LEN_DATA_DYN1); + p->mp_len_data_dyn2 = register_get_field(p->mp_len_data, CAT_LEN_DATA_DYN2); + p->mp_len_data_inv = register_get_field(p->mp_len_data, CAT_LEN_DATA_INV); + + p->mp_cfn_data_ptc_cfp = + register_query_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_CFP); + p->mp_cfn_data_err_l3_cs = + register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_L3_CS); + p->mp_cfn_data_err_l4_cs = + register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_L4_CS); + p->mp_cfn_data_err_tnl_l3_cs = + register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TNL_L3_CS); + p->mp_cfn_data_err_tnl_l4_cs = + register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TNL_L4_CS); + p->mp_cfn_data_err_ttl_exp = + register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TTL_EXP); + p->mp_cfn_data_err_tnl_ttl_exp = + register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TNL_TTL_EXP); + + p->mp_kcc_ctrl = module_query_register(p->m_cat, CAT_KCC_CTRL); + if (p->mp_kcc_ctrl != NULL) { + p->mp_kcc_addr = + register_query_field(p->mp_kcc_ctrl, CAT_KCC_CTRL_ADR); + p->mp_kcc_cnt = + register_query_field(p->mp_kcc_ctrl, CAT_KCC_CTRL_CNT); + } + p->mp_kcc_data = module_query_register(p->m_cat, CAT_KCC_DATA); + if (p->mp_kcc_data != NULL) { + p->mp_kcc_data_key = + register_query_field(p->mp_kcc_data, CAT_KCC_DATA_KEY); + p->mp_kcc_data_category = + register_query_field(p->mp_kcc_data, CAT_KCC_DATA_CATEGORY); + p->mp_kcc_data_id = + register_query_field(p->mp_kcc_data, CAT_KCC_DATA_ID); + } + + p->mp_cce_ctrl = module_query_register(p->m_cat, CAT_CCE_CTRL); + if (p->mp_cce_ctrl != NULL) { + p->mp_cce_addr = + register_query_field(p->mp_cce_ctrl, CAT_CCE_CTRL_ADR); + p->mp_cce_cnt = + register_query_field(p->mp_cce_ctrl, CAT_CCE_CTRL_CNT); + } + p->mp_cce_data = module_query_register(p->m_cat, CAT_CCE_DATA); + if (p->mp_cce_data != NULL) { + p->mp_cce_data_imm = + register_query_field(p->mp_cce_data, CAT_CCE_DATA_IMM); + p->mp_cce_data_ind = + register_query_field(p->mp_cce_data, CAT_CCE_DATA_IND); + } + + p->mp_ccs_ctrl = module_query_register(p->m_cat, CAT_CCS_CTRL); + if (p->mp_ccs_ctrl != NULL) { + p->mp_ccs_addr = + register_query_field(p->mp_ccs_ctrl, CAT_CCS_CTRL_ADR); + p->mp_ccs_cnt = + register_query_field(p->mp_ccs_ctrl, CAT_CCS_CTRL_CNT); + } + p->mp_ccs_data = module_query_register(p->m_cat, CAT_CCS_DATA); + if (p->mp_ccs_data != NULL) { + p->mp_ccs_data_cor_en = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_COR_EN); + p->mp_ccs_data_cor = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_COR); + p->mp_ccs_data_hsh_en = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_HSH_EN); + p->mp_ccs_data_hsh = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_HSH); + p->mp_ccs_data_qsl_en = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_QSL_EN); + p->mp_ccs_data_qsl = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_QSL); + p->mp_ccs_data_ipf_en = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_IPF_EN); + p->mp_ccs_data_ipf = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_IPF); + p->mp_ccs_data_slc_en = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SLC_EN); + p->mp_ccs_data_slc = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SLC); + p->mp_ccs_data_pdb_en = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_PDB_EN); + p->mp_ccs_data_pdb = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_PDB); + p->mp_ccs_data_msk_en = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_MSK_EN); + p->mp_ccs_data_msk = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_MSK); + p->mp_ccs_data_hst_en = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_HST_EN); + p->mp_ccs_data_hst = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_HST); + p->mp_ccs_data_epp_en = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_EPP_EN); + p->mp_ccs_data_epp = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_EPP); + p->mp_ccs_data_tpe_en = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_TPE_EN); + p->mp_ccs_data_tpe = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_TPE); + p->mp_ccs_data_rrb_en = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_RRB_EN); + p->mp_ccs_data_rrb = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_RRB); + p->mp_ccs_data_sb0_type = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB0_TYPE); + p->mp_ccs_data_sb0_data = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB0_DATA); + p->mp_ccs_data_sb1_type = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB1_TYPE); + p->mp_ccs_data_sb1_data = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB1_DATA); + p->mp_ccs_data_sb2_type = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB2_TYPE); + p->mp_ccs_data_sb2_data = + register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB2_DATA); + } + + return 0; +} + +/* CFN */ +void cat_nthw_cfn_select(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_addr, val); +} + +void r(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_cnt, val); +} + +void cat_nthw_cfn_enable(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_enable, val); +} + +void cat_nthw_cfn_inv(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_inv, val); +} + +void cat_nthw_cfn_ptc_inv(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_inv, val); +} + +void cat_nthw_cfn_ptc_isl(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_isl, val); +} + +void cat_nthw_cfn_ptc_mac(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_mac, val); +} + +void cat_nthw_cfn_ptc_l2(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_l2, val); +} + +void cat_nthw_cfn_ptc_vn_tag(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_vn_tag, val); +} + +void cat_nthw_cfn_ptc_vlan(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_vlan, val); +} + +void cat_nthw_cfn_ptc_mpls(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_mpls, val); +} + +void cat_nthw_cfn_ptc_l3(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_l3, val); +} + +void cat_nthw_cfn_ptc_frag(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_frag, val); +} + +void cat_nthw_cfn_ptc_ip_prot(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_ip_prot, val); +} + +void cat_nthw_cfn_ptc_l4(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_l4, val); +} + +void cat_nthw_cfn_ptc_tunnel(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_tunnel, val); +} + +void cat_nthw_cfn_ptc_tnl_l2(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_tnl_l2, val); +} + +void cat_nthw_cfn_ptc_tnl_vlan(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_tnl_vlan, val); +} + +void cat_nthw_cfn_ptc_tnl_mpls(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_tnl_mpls, val); +} + +void cat_nthw_cfn_ptc_tnl_l3(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_tnl_l3, val); +} + +void cat_nthw_cfn_ptc_tnl_frag(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_tnl_frag, val); +} + +void cat_nthw_cfn_ptc_tnl_ip_prot(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_tnl_ip_prot, val); +} + +void cat_nthw_cfn_ptc_tnl_l4(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_ptc_tnl_l4, val); +} + +void cat_nthw_cfn_ptc_cfp(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cfn_data_ptc_cfp); + field_set_val32(p->mp_cfn_data_ptc_cfp, val); +} + +void cat_nthw_cfn_err_l3_cs(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cfn_data_err_l3_cs); + field_set_val32(p->mp_cfn_data_err_l3_cs, val); +} + +void cat_nthw_cfn_err_l4_cs(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cfn_data_err_l4_cs); + field_set_val32(p->mp_cfn_data_err_l4_cs, val); +} + +void cat_nthw_cfn_err_tnl_l3_cs(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cfn_data_err_tnl_l3_cs); + field_set_val32(p->mp_cfn_data_err_tnl_l3_cs, val); +} + +void cat_nthw_cfn_err_tnl_l4_cs(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cfn_data_err_tnl_l4_cs); + field_set_val32(p->mp_cfn_data_err_tnl_l4_cs, val); +} + +void cat_nthw_cfn_err_ttl_exp(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cfn_data_err_ttl_exp); + field_set_val32(p->mp_cfn_data_err_ttl_exp, val); +} + +void cat_nthw_cfn_err_tnl_ttl_exp(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cfn_data_err_tnl_ttl_exp); + field_set_val32(p->mp_cfn_data_err_tnl_ttl_exp, val); +} + +void cat_nthw_cfn_err_inv(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_err_inv, val); +} + +void cat_nthw_cfn_err_cv(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_err_cv, val); +} + +void cat_nthw_cfn_err_fcs(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_err_fcs, val); +} + +void cat_nthw_cfn_err_trunc(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_err_trunc, val); +} + +void cat_nthw_cfn_mac_port(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_mac_port, val); +} + +void cat_nthw_cfn_pm_cmp(const struct cat_nthw *p, const uint32_t *val) +{ + field_set_val(p->mp_cfn_data_pm_cmp, val, p->mp_cfn_data_pm_cmp->mn_words); +} + +void cat_nthw_cfn_pm_dct(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_pm_dct, val); +} + +void cat_nthw_cfn_pm_ext_inv(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_pm_ext_inv, val); +} + +void cat_nthw_cfn_pm_cmb(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_pm_cmb, val); +} + +void cat_nthw_cfn_pm_and_inv(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_pm_and_inv, val); +} + +void cat_nthw_cfn_pm_or_inv(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_pm_or_inv, val); +} + +void cat_nthw_cfn_pm_inv(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_pm_inv, val); +} + +void cat_nthw_cfn_lc(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_lc, val); +} + +void cat_nthw_cfn_lc_inv(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_lc_inv, val); +} + +void cat_nthw_cfn_km0_or(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cfn_data_km0_or, val); +} + +void cat_nthw_cfn_km1_or(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cfn_data_km1_or); + field_set_val32(p->mp_cfn_data_km1_or, val); +} + +void cat_nthw_cfn_flush(const struct cat_nthw *p) +{ + register_flush(p->mp_cfn_ctrl, 1); + register_flush(p->mp_cfn_data, 1); +} + +void cat_nthw_kce_select(const struct cat_nthw *p, int index, uint32_t val) +{ + field_set_val32(p->mp_kce_addr[index], val); +} + +void cat_nthw_kce_cnt(const struct cat_nthw *p, int index, uint32_t val) +{ + field_set_val32(p->mp_kce_cnt[index], val); +} + +void cat_nthw_kce_enable(const struct cat_nthw *p, int index, uint32_t val) +{ + field_set_val32(p->mp_kce_data_enable[index], val); +} + +void cat_nthw_kce_flush(const struct cat_nthw *p, int index) +{ + register_flush(p->mp_kce_ctrl[index], 1); + register_flush(p->mp_kce_data[index], 1); +} + +void cat_nthw_kcs_select(const struct cat_nthw *p, int index, uint32_t val) +{ + field_set_val32(p->mp_kcs_addr[index], val); +} + +void cat_nthw_kcs_cnt(const struct cat_nthw *p, int index, uint32_t val) +{ + field_set_val32(p->mp_kcs_cnt[index], val); +} + +void cat_nthw_kcs_category(const struct cat_nthw *p, int index, uint32_t val) +{ + field_set_val32(p->mp_kcs_data_category[index], val); +} + +void cat_nthw_kcs_flush(const struct cat_nthw *p, int index) +{ + register_flush(p->mp_kcs_ctrl[index], 1); + register_flush(p->mp_kcs_data[index], 1); +} + +void cat_nthw_fte_select(const struct cat_nthw *p, int index, uint32_t val) +{ + field_set_val32(p->mp_fte_addr[index], val); +} + +void cat_nthw_fte_cnt(const struct cat_nthw *p, int index, uint32_t val) +{ + field_set_val32(p->mp_fte_cnt[index], val); +} + +void cat_nthw_fte_enable(const struct cat_nthw *p, int index, uint32_t val) +{ + field_set_val32(p->mp_fte_data_enable[index], val); +} + +void cat_nthw_fte_flush(const struct cat_nthw *p, int index) +{ + register_flush(p->mp_fte_ctrl[index], 1); + register_flush(p->mp_fte_data[index], 1); +} + +void cat_nthw_cte_select(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cte_addr, val); +} + +void cat_nthw_cte_cnt(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cte_cnt, val); +} + +void cat_nthw_cte_enable_col(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cte_data_col, val); +} + +void cat_nthw_cte_enable_cor(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cte_data_cor, val); +} + +void cat_nthw_cte_enable_hsh(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cte_data_hsh, val); +} + +void cat_nthw_cte_enable_qsl(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cte_data_qsl, val); +} + +void cat_nthw_cte_enable_ipf(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cte_data_ipf, val); +} + +void cat_nthw_cte_enable_slc(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cte_data_slc, val); +} + +void cat_nthw_cte_enable_pdb(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cte_data_pdb, val); +} + +void cat_nthw_cte_enable_msk(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cte_data_msk); + field_set_val32(p->mp_cte_data_msk, val); +} + +void cat_nthw_cte_enable_hst(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cte_data_hst); + field_set_val32(p->mp_cte_data_hst, val); +} + +void cat_nthw_cte_enable_epp(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cte_data_epp); + field_set_val32(p->mp_cte_data_epp, val); +} + +void cat_nthw_cte_enable_tpe(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cte_data_tpe); + field_set_val32(p->mp_cte_data_tpe, val); +} + +void cat_nthw_cte_enable_rrb(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cte_data_rrb); + field_set_val32(p->mp_cte_data_rrb, val); +} + +void cat_nthw_cte_flush(const struct cat_nthw *p) +{ + register_flush(p->mp_cte_ctrl, 1); + register_flush(p->mp_cte_data, 1); +} + +void cat_nthw_cts_select(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cts_addr, val); +} + +void cat_nthw_cts_cnt(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cts_cnt, val); +} + +void cat_nthw_cts_cat_a(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cts_data_cat_a, val); +} + +void cat_nthw_cts_cat_b(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cts_data_cat_b, val); +} + +void cat_nthw_cts_flush(const struct cat_nthw *p) +{ + register_flush(p->mp_cts_ctrl, 1); + register_flush(p->mp_cts_data, 1); +} + +void cat_nthw_cot_select(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cot_addr, val); +} + +void cat_nthw_cot_cnt(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cot_cnt, val); +} + +void cat_nthw_cot_color(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cot_data_color, val); +} + +void cat_nthw_cot_km(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cot_data_km, val); +} + +void cat_nthw_cot_nfv_sb(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cot_data_nfv_sb); + field_set_val32(p->mp_cot_data_nfv_sb, val); +} + +void cat_nthw_cot_flush(const struct cat_nthw *p) +{ + register_flush(p->mp_cot_ctrl, 1); + register_flush(p->mp_cot_data, 1); +} + +void cat_nthw_cct_select(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cct_addr, val); +} + +void cat_nthw_cct_cnt(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cct_cnt, val); +} + +void cat_nthw_cct_color(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cct_data_color, val); +} + +void cat_nthw_cct_km(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cct_data_km, val); +} + +void cat_nthw_cct_flush(const struct cat_nthw *p) +{ + register_flush(p->mp_cct_ctrl, 1); + register_flush(p->mp_cct_data, 1); +} + +void cat_nthw_exo_select(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_exo_addr, val); +} + +void cat_nthw_exo_cnt(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_exo_cnt, val); +} + +void cat_nthw_exo_dyn(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_exo_data_dyn, val); +} + +void cat_nthw_exo_ofs(const struct cat_nthw *p, int32_t val) +{ + field_set_val32(p->mp_exo_data_ofs, val); +} + +void cat_nthw_exo_flush(const struct cat_nthw *p) +{ + register_flush(p->mp_exo_ctrl, 1); + register_flush(p->mp_exo_data, 1); +} + +void cat_nthw_rck_select(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rck_addr, val); +} + +void cat_nthw_rck_cnt(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rck_cnt, val); +} + +void cat_nthw_rck_data(const struct cat_nthw *p, uint32_t val) +{ + register_set_val(p->mp_rck_data, &val, 1); + register_make_dirty(p->mp_rck_data); +} + +void cat_nthw_rck_flush(const struct cat_nthw *p) +{ + register_flush(p->mp_rck_ctrl, 1); + register_flush(p->mp_rck_data, 1); +} + +void cat_nthw_len_select(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_len_addr, val); +} + +void cat_nthw_len_cnt(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_len_cnt, val); +} + +void cat_nthw_len_lower(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_len_data_lower, val); +} + +void cat_nthw_len_upper(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_len_data_upper, val); +} + +void cat_nthw_len_dyn1(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_len_data_dyn1, val); +} + +void cat_nthw_len_dyn2(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_len_data_dyn2, val); +} + +void cat_nthw_len_inv(const struct cat_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_len_data_inv, val); +} + +void cat_nthw_len_flush(const struct cat_nthw *p) +{ + register_flush(p->mp_len_ctrl, 1); + register_flush(p->mp_len_data, 1); +} + +void cat_nthw_kcc_select(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_kcc_addr); + field_set_val32(p->mp_kcc_addr, val); +} + +void cat_nthw_kcc_cnt(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_kcc_cnt); + field_set_val32(p->mp_kcc_cnt, val); +} + +void cat_nthw_kcc_key(const struct cat_nthw *p, uint32_t *val) +{ + assert(p->mp_kcc_data_key); + field_set_val(p->mp_kcc_data_key, val, 2); +} + +void cat_nthw_kcc_category(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_kcc_data_category); + field_set_val32(p->mp_kcc_data_category, val); +} + +void cat_nthw_kcc_id(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_kcc_data_id); + field_set_val32(p->mp_kcc_data_id, val); +} + +void cat_nthw_kcc_flush(const struct cat_nthw *p) +{ + assert(p->mp_kcc_ctrl); + assert(p->mp_kcc_data); + register_flush(p->mp_kcc_ctrl, 1); + register_flush(p->mp_kcc_data, 1); +} + +void cat_nthw_cce_select(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cce_addr); + field_set_val32(p->mp_cce_addr, val); +} + +void cat_nthw_cce_cnt(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cce_cnt); + field_set_val32(p->mp_cce_cnt, val); +} + +void cat_nthw_cce_data_imm(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cce_data_imm); + field_set_val32(p->mp_cce_data_imm, val); +} + +void cat_nthw_cce_data_ind(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_cce_data_ind); + field_set_val32(p->mp_cce_data_ind, val); +} + +void cat_nthw_cce_flush(const struct cat_nthw *p) +{ + assert(p->mp_cce_ctrl); + assert(p->mp_cce_data); + register_flush(p->mp_cce_ctrl, 1); + register_flush(p->mp_cce_data, 1); +} + +void cat_nthw_ccs_select(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_ccs_addr); + field_set_val32(p->mp_ccs_addr, val); +} + +void cat_nthw_ccs_cnt(const struct cat_nthw *p, uint32_t val) +{ + assert(p->mp_ccs_cnt); + field_set_val32(p->mp_ccs_cnt, val); +} + +#define CATNTHW_CCS_SET(name) \ + void cat_nthw_ccs_data_##name(const struct cat_nthw *p, uint32_t val) \ + { \ + assert(p->mp_ccs_data_##name); \ + field_set_val32(p->mp_ccs_data_##name, val); \ + } + +CATNTHW_CCS_SET(cor_en); +CATNTHW_CCS_SET(cor); +CATNTHW_CCS_SET(hsh_en); +CATNTHW_CCS_SET(hsh); +CATNTHW_CCS_SET(qsl_en); +CATNTHW_CCS_SET(qsl); +CATNTHW_CCS_SET(ipf_en); +CATNTHW_CCS_SET(ipf); +CATNTHW_CCS_SET(slc_en); +CATNTHW_CCS_SET(slc); +CATNTHW_CCS_SET(pdb_en); +CATNTHW_CCS_SET(pdb); +CATNTHW_CCS_SET(msk_en); +CATNTHW_CCS_SET(msk); +CATNTHW_CCS_SET(hst_en); +CATNTHW_CCS_SET(hst); +CATNTHW_CCS_SET(epp_en); +CATNTHW_CCS_SET(epp); +CATNTHW_CCS_SET(tpe_en); +CATNTHW_CCS_SET(tpe); +CATNTHW_CCS_SET(rrb_en); +CATNTHW_CCS_SET(rrb); +CATNTHW_CCS_SET(sb0_type); +CATNTHW_CCS_SET(sb0_data); +CATNTHW_CCS_SET(sb1_type); +CATNTHW_CCS_SET(sb1_data); +CATNTHW_CCS_SET(sb2_type); +CATNTHW_CCS_SET(sb2_data); + +void cat_nthw_ccs_flush(const struct cat_nthw *p) +{ + assert(p->mp_ccs_ctrl); + assert(p->mp_ccs_data); + register_flush(p->mp_ccs_ctrl, 1); + register_flush(p->mp_ccs_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.h new file mode 100644 index 0000000000..41ac891a93 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.h @@ -0,0 +1,372 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_CAT_H__ +#define __FLOW_NTHW_CAT_H__ + +#include /* uint32_t */ +#include "nthw_fpga_model.h" + +struct cat_nthw; + +typedef struct cat_nthw cat_nthw_t; + +struct cat_nthw *cat_nthw_new(void); +void cat_nthw_delete(struct cat_nthw *p); +int cat_nthw_init(struct cat_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int cat_nthw_setup(struct cat_nthw *p, int n_idx, int n_idx_cnt); +void cat_nthw_set_debug_mode(struct cat_nthw *p, unsigned int n_debug_mode); + +/* CFN */ +void cat_nthw_cfn_select(const struct cat_nthw *p, uint32_t val); +void r(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_enable(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_inv(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_inv(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_isl(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_cfp(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_mac(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_l2(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_vn_tag(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_vlan(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_mpls(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_l3(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_frag(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_ip_prot(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_l4(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_tunnel(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_tnl_l2(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_tnl_vlan(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_tnl_mpls(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_tnl_l3(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_tnl_frag(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_tnl_ip_prot(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_ptc_tnl_l4(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_err_inv(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_err_cv(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_err_fcs(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_err_trunc(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_err_l3_cs(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_err_l4_cs(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_err_tnl_l3_cs(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_err_tnl_l4_cs(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_err_ttl_exp(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_err_tnl_ttl_exp(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_mac_port(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_pm_cmp(const struct cat_nthw *p, const uint32_t *val); +void cat_nthw_cfn_pm_dct(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_pm_ext_inv(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_pm_cmb(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_pm_and_inv(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_pm_or_inv(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_pm_inv(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_lc(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_lc_inv(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_km0_or(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_km1_or(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cfn_flush(const struct cat_nthw *p); +/* KCE 0/1 */ +void cat_nthw_kce_select(const struct cat_nthw *p, int index, uint32_t val); +void cat_nthw_kce_cnt(const struct cat_nthw *p, int index, uint32_t val); +void cat_nthw_kce_enable(const struct cat_nthw *p, int index, uint32_t val); +void cat_nthw_kce_flush(const struct cat_nthw *p, int index); +/* KCS 0/1 */ +void cat_nthw_kcs_select(const struct cat_nthw *p, int index, uint32_t val); +void cat_nthw_kcs_cnt(const struct cat_nthw *p, int index, uint32_t val); +void cat_nthw_kcs_category(const struct cat_nthw *p, int index, uint32_t val); +void cat_nthw_kcs_flush(const struct cat_nthw *p, int index); +/* FTE 0/1 */ +void cat_nthw_fte_select(const struct cat_nthw *p, int index, uint32_t val); +void cat_nthw_fte_cnt(const struct cat_nthw *p, int index, uint32_t val); +void cat_nthw_fte_enable(const struct cat_nthw *p, int index, uint32_t val); +void cat_nthw_fte_flush(const struct cat_nthw *p, int index); +/* CTE */ +void cat_nthw_cte_select(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cte_cnt(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cte_enable_col(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cte_enable_cor(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cte_enable_hsh(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cte_enable_qsl(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cte_enable_ipf(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cte_enable_slc(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cte_enable_pdb(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cte_enable_msk(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cte_enable_hst(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cte_enable_epp(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cte_enable_tpe(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cte_enable_rrb(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cte_flush(const struct cat_nthw *p); +/* CTS */ +void cat_nthw_cts_select(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cts_cnt(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cts_flush(const struct cat_nthw *p); +void cat_nthw_cts_cat_a(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cts_cat_b(const struct cat_nthw *p, uint32_t val); +/* COT */ +void cat_nthw_cot_select(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cot_cnt(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cot_color(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cot_km(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cot_nfv_sb(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cot_flush(const struct cat_nthw *p); +/* CCT */ +void cat_nthw_cct_select(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cct_cnt(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cct_color(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cct_km(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cct_flush(const struct cat_nthw *p); +/* EXO */ +void cat_nthw_exo_select(const struct cat_nthw *p, uint32_t val); +void cat_nthw_exo_cnt(const struct cat_nthw *p, uint32_t val); +void cat_nthw_exo_dyn(const struct cat_nthw *p, uint32_t val); +void cat_nthw_exo_ofs(const struct cat_nthw *p, int32_t val); +void cat_nthw_exo_flush(const struct cat_nthw *p); +/* RCK */ +void cat_nthw_rck_select(const struct cat_nthw *p, uint32_t val); +void cat_nthw_rck_cnt(const struct cat_nthw *p, uint32_t val); +void cat_nthw_rck_data(const struct cat_nthw *p, uint32_t val); +void cat_nthw_rck_flush(const struct cat_nthw *p); +/* LEN */ +void cat_nthw_len_select(const struct cat_nthw *p, uint32_t val); +void cat_nthw_len_cnt(const struct cat_nthw *p, uint32_t val); +void cat_nthw_len_lower(const struct cat_nthw *p, uint32_t val); +void cat_nthw_len_upper(const struct cat_nthw *p, uint32_t val); +void cat_nthw_len_dyn1(const struct cat_nthw *p, uint32_t val); +void cat_nthw_len_dyn2(const struct cat_nthw *p, uint32_t val); +void cat_nthw_len_inv(const struct cat_nthw *p, uint32_t val); +void cat_nthw_len_flush(const struct cat_nthw *p); +/* KCC */ +void cat_nthw_kcc_select(const struct cat_nthw *p, uint32_t val); +void cat_nthw_kcc_cnt(const struct cat_nthw *p, uint32_t val); +void cat_nthw_kcc_key(const struct cat_nthw *p, uint32_t *val); +void cat_nthw_kcc_category(const struct cat_nthw *p, uint32_t val); +void cat_nthw_kcc_id(const struct cat_nthw *p, uint32_t val); +void cat_nthw_kcc_flush(const struct cat_nthw *p); +/* CCE */ +void cat_nthw_cce_select(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cce_cnt(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cce_data_imm(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cce_data_ind(const struct cat_nthw *p, uint32_t val); +void cat_nthw_cce_flush(const struct cat_nthw *p); +/* CCS */ +void cat_nthw_ccs_select(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_cnt(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_cor_en(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_cor(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_hsh_en(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_hsh(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_qsl_en(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_qsl(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_ipf_en(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_ipf(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_slc_en(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_slc(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_pdb_en(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_pdb(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_msk_en(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_msk(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_hst_en(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_hst(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_epp_en(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_epp(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_tpe_en(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_tpe(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_rrb_en(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_rrb(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_sb0_type(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_sb0_data(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_sb1_type(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_sb1_data(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_sb2_type(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_data_sb2_data(const struct cat_nthw *p, uint32_t val); +void cat_nthw_ccs_flush(const struct cat_nthw *p); + +struct cat_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + nt_module_t *m_cat; + int m_km_if_cnt; + + nt_register_t *mp_cfn_ctrl; + nt_field_t *mp_cfn_addr; + nt_field_t *mp_cfn_cnt; + nt_register_t *mp_cfn_data; + nt_field_t *mp_cfn_data_enable; + nt_field_t *mp_cfn_data_inv; + nt_field_t *mp_cfn_data_ptc_inv; + nt_field_t *mp_cfn_data_ptc_isl; + nt_field_t *mp_cfn_data_ptc_cfp; + nt_field_t *mp_cfn_data_ptc_mac; + nt_field_t *mp_cfn_data_ptc_l2; + nt_field_t *mp_cfn_data_ptc_vn_tag; + nt_field_t *mp_cfn_data_ptc_vlan; + nt_field_t *mp_cfn_data_ptc_mpls; + nt_field_t *mp_cfn_data_ptc_l3; + nt_field_t *mp_cfn_data_ptc_frag; + nt_field_t *mp_cfn_data_ptc_ip_prot; + nt_field_t *mp_cfn_data_ptc_l4; + nt_field_t *mp_cfn_data_ptc_tunnel; + nt_field_t *mp_cfn_data_ptc_tnl_l2; + nt_field_t *mp_cfn_data_ptc_tnl_vlan; + nt_field_t *mp_cfn_data_ptc_tnl_mpls; + nt_field_t *mp_cfn_data_ptc_tnl_l3; + nt_field_t *mp_cfn_data_ptc_tnl_frag; + nt_field_t *mp_cfn_data_ptc_tnl_ip_prot; + nt_field_t *mp_cfn_data_ptc_tnl_l4; + nt_field_t *mp_cfn_data_err_inv; + nt_field_t *mp_cfn_data_err_cv; + nt_field_t *mp_cfn_data_err_fcs; + nt_field_t *mp_cfn_data_err_trunc; + nt_field_t *mp_cfn_data_err_l3_cs; + nt_field_t *mp_cfn_data_err_l4_cs; + nt_field_t *mp_cfn_data_err_tnl_l3_cs; + nt_field_t *mp_cfn_data_err_tnl_l4_cs; + nt_field_t *mp_cfn_data_err_ttl_exp; + nt_field_t *mp_cfn_data_err_tnl_ttl_exp; + nt_field_t *mp_cfn_data_mac_port; + nt_field_t *mp_cfn_data_pm_cmp; + nt_field_t *mp_cfn_data_pm_dct; + nt_field_t *mp_cfn_data_pm_ext_inv; + nt_field_t *mp_cfn_data_pm_cmb; + nt_field_t *mp_cfn_data_pm_and_inv; + nt_field_t *mp_cfn_data_pm_or_inv; + nt_field_t *mp_cfn_data_pm_inv; + nt_field_t *mp_cfn_data_lc; + nt_field_t *mp_cfn_data_lc_inv; + nt_field_t *mp_cfn_data_km0_or; + nt_field_t *mp_cfn_data_km1_or; + + nt_register_t *mp_kce_ctrl[2]; + nt_field_t *mp_kce_addr[2]; + nt_field_t *mp_kce_cnt[2]; + nt_register_t *mp_kce_data[2]; + nt_field_t *mp_kce_data_enable[2]; + + nt_register_t *mp_kcs_ctrl[2]; + nt_field_t *mp_kcs_addr[2]; + nt_field_t *mp_kcs_cnt[2]; + nt_register_t *mp_kcs_data[2]; + nt_field_t *mp_kcs_data_category[2]; + + nt_register_t *mp_fte_ctrl[2]; + nt_field_t *mp_fte_addr[2]; + nt_field_t *mp_fte_cnt[2]; + nt_register_t *mp_fte_data[2]; + nt_field_t *mp_fte_data_enable[2]; + + nt_register_t *mp_cte_ctrl; + nt_field_t *mp_cte_addr; + nt_field_t *mp_cte_cnt; + nt_register_t *mp_cte_data; + nt_field_t *mp_cte_data_col; + nt_field_t *mp_cte_data_cor; + nt_field_t *mp_cte_data_hsh; + nt_field_t *mp_cte_data_qsl; + nt_field_t *mp_cte_data_ipf; + nt_field_t *mp_cte_data_slc; + nt_field_t *mp_cte_data_pdb; + nt_field_t *mp_cte_data_msk; + nt_field_t *mp_cte_data_hst; + nt_field_t *mp_cte_data_epp; + nt_field_t *mp_cte_data_tpe; + nt_field_t *mp_cte_data_rrb; + + nt_register_t *mp_cts_ctrl; + nt_field_t *mp_cts_addr; + nt_field_t *mp_cts_cnt; + nt_register_t *mp_cts_data; + nt_field_t *mp_cts_data_cat_a; + nt_field_t *mp_cts_data_cat_b; + + nt_register_t *mp_cot_ctrl; + nt_field_t *mp_cot_addr; + nt_field_t *mp_cot_cnt; + nt_register_t *mp_cot_data; + nt_field_t *mp_cot_data_color; + nt_field_t *mp_cot_data_km; + nt_field_t *mp_cot_data_nfv_sb; + + nt_register_t *mp_cct_ctrl; + nt_field_t *mp_cct_addr; + nt_field_t *mp_cct_cnt; + nt_register_t *mp_cct_data; + nt_field_t *mp_cct_data_color; + nt_field_t *mp_cct_data_km; + + nt_register_t *mp_exo_ctrl; + nt_field_t *mp_exo_addr; + nt_field_t *mp_exo_cnt; + nt_register_t *mp_exo_data; + nt_field_t *mp_exo_data_dyn; + nt_field_t *mp_exo_data_ofs; + + nt_register_t *mp_rck_ctrl; + nt_field_t *mp_rck_addr; + nt_field_t *mp_rck_cnt; + nt_register_t *mp_rck_data; + + nt_register_t *mp_len_ctrl; + nt_field_t *mp_len_addr; + nt_field_t *mp_len_cnt; + nt_register_t *mp_len_data; + nt_field_t *mp_len_data_lower; + nt_field_t *mp_len_data_upper; + nt_field_t *mp_len_data_dyn1; + nt_field_t *mp_len_data_dyn2; + nt_field_t *mp_len_data_inv; + nt_register_t *mp_kcc_ctrl; + nt_field_t *mp_kcc_addr; + nt_field_t *mp_kcc_cnt; + + nt_register_t *mp_kcc_data; + nt_field_t *mp_kcc_data_key; + nt_field_t *mp_kcc_data_category; + nt_field_t *mp_kcc_data_id; + + nt_register_t *mp_cce_ctrl; + nt_field_t *mp_cce_addr; + nt_field_t *mp_cce_cnt; + + nt_register_t *mp_cce_data; + nt_field_t *mp_cce_data_imm; + nt_field_t *mp_cce_data_ind; + + nt_register_t *mp_ccs_ctrl; + nt_field_t *mp_ccs_addr; + nt_field_t *mp_ccs_cnt; + + nt_register_t *mp_ccs_data; + nt_field_t *mp_ccs_data_cor_en; + nt_field_t *mp_ccs_data_cor; + + nt_field_t *mp_ccs_data_hsh_en; + nt_field_t *mp_ccs_data_hsh; + nt_field_t *mp_ccs_data_qsl_en; + nt_field_t *mp_ccs_data_qsl; + nt_field_t *mp_ccs_data_ipf_en; + nt_field_t *mp_ccs_data_ipf; + nt_field_t *mp_ccs_data_slc_en; + nt_field_t *mp_ccs_data_slc; + nt_field_t *mp_ccs_data_pdb_en; + nt_field_t *mp_ccs_data_pdb; + nt_field_t *mp_ccs_data_msk_en; + nt_field_t *mp_ccs_data_msk; + nt_field_t *mp_ccs_data_hst_en; + nt_field_t *mp_ccs_data_hst; + nt_field_t *mp_ccs_data_epp_en; + nt_field_t *mp_ccs_data_epp; + nt_field_t *mp_ccs_data_tpe_en; + nt_field_t *mp_ccs_data_tpe; + nt_field_t *mp_ccs_data_rrb_en; + nt_field_t *mp_ccs_data_rrb; + nt_field_t *mp_ccs_data_sb0_type; + nt_field_t *mp_ccs_data_sb0_data; + nt_field_t *mp_ccs_data_sb1_type; + nt_field_t *mp_ccs_data_sb1_data; + nt_field_t *mp_ccs_data_sb2_type; + nt_field_t *mp_ccs_data_sb2_data; +}; + +#endif /* __FLOW_NTHW_CAT_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.c new file mode 100644 index 0000000000..5a7f90ad69 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.c @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_csu.h" + +#include +#include + +void csu_nthw_set_debug_mode(struct csu_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_csu, n_debug_mode); +} + +struct csu_nthw *csu_nthw_new(void) +{ + struct csu_nthw *p = malloc(sizeof(struct csu_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + return p; +} + +void csu_nthw_delete(struct csu_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int csu_nthw_init(struct csu_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_CSU, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: Csu %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_csu = p_mod; + + p->mp_rcp_ctrl = module_get_register(p->m_csu, CSU_RCP_CTRL); + p->mp_rcp_ctrl_adr = register_get_field(p->mp_rcp_ctrl, CSU_RCP_CTRL_ADR); + p->mp_rcp_ctrl_cnt = register_get_field(p->mp_rcp_ctrl, CSU_RCP_CTRL_CNT); + p->mp_rcp_data = module_get_register(p->m_csu, CSU_RCP_DATA); + p->mp_rcp_data_ol3_cmd = + register_get_field(p->mp_rcp_data, CSU_RCP_DATA_OL3_CMD); + p->mp_rcp_data_ol4_cmd = + register_get_field(p->mp_rcp_data, CSU_RCP_DATA_OL4_CMD); + p->mp_rcp_data_il3_cmd = + register_get_field(p->mp_rcp_data, CSU_RCP_DATA_IL3_CMD); + p->mp_rcp_data_il4_cmd = + register_get_field(p->mp_rcp_data, CSU_RCP_DATA_IL4_CMD); + + return 0; +} + +void csu_nthw_rcp_select(const struct csu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_ctrl_adr, val); +} + +void csu_nthw_rcp_cnt(const struct csu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_ctrl_cnt, val); +} + +void csu_nthw_rcp_outer_l3_cmd(const struct csu_nthw *p, uint32_t val) +{ + /* + * Select L3 calc method for outer layer3. + * 0: Do not touch checksum field. + * 1: Check, but do not touch checksum field. + * 2: Insert checksum header value for BAD checksum. + * 3: Insert checksum header value for GOOD checksum. + */ + field_set_val32(p->mp_rcp_data_ol3_cmd, val); +} + +void csu_nthw_rcp_outer_l4_cmd(const struct csu_nthw *p, uint32_t val) +{ + /* + * Select L4 calc method for outer layer4. + * 0: Do not touch checksum field. + * 1: Check, but do not touch checksum field. + * 2: Insert checksum header value for BAD checksum. + * 3: Insert checksum header value for GOOD checksum. + * 4: Set UDP checksum value of ZERO for both IPv4/IPv6, set good checksum for TCP. + * 5: Set UDP checksum value of ZERO for IPv4, set good checksum for TCP. + * 6: Set UDP checksum value of ZERO for outer tunnel when tunnel is IPv4/IPv6 and UDP, + * otherwise GOOD checksum. + * 7: Set UDP checksum value of ZERO for outer tunnel when tunnel is IPv4 and UDP, otherwise + * GOOD checksum. + */ + field_set_val32(p->mp_rcp_data_ol4_cmd, val); +} + +void csu_nthw_rcp_inner_l3_cmd(const struct csu_nthw *p, uint32_t val) +{ + /* + * Select L3 calc method for inner layer3 (tunneled). + * 0: Do not touch checksum field. + * 1: Check, but do not touch checksum field. + * 2: Insert checksum header value for BAD checksum. + * 3: Insert checksum header value for GOOD checksum. + */ + field_set_val32(p->mp_rcp_data_il3_cmd, val); +} + +void csu_nthw_rcp_inner_l4_cmd(const struct csu_nthw *p, uint32_t val) +{ + /* + * Select L4 calc method for inner layer4 (tunneled). + * 0: Do not touch checksum field. + * 1: Check, but do not touch checksum field. + * 2: Insert checksum header value for BAD checksum. + * 3: Insert checksum header value for GOOD checksum. + * 4: Set UDP checksum value of ZERO for both IPv4/IPv6, set good checksum for TCP. + * 5: Set UDP checksum value of ZERO for IPv4, set good checksum for TCP. + * 6: Set UDP checksum value of ZERO for outer tunnel when tunnel is IPv4/IPv6 and UDP, + * otherwise GOOD checksum. + * 7: Set UDP checksum value of ZERO for outer tunnel when tunnel is IPv4 and UDP, otherwise + * GOOD checksum. + */ + field_set_val32(p->mp_rcp_data_il4_cmd, val); +} + +void csu_nthw_rcp_flush(const struct csu_nthw *p) +{ + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.h new file mode 100644 index 0000000000..6cb0e1f781 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _FLOW_NTHW_CSU_H_ +#define _FLOW_NTHW_CSU_H_ + +#include +#include "nthw_fpga_model.h" + +struct csu_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_csu; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_ctrl_adr; + nt_field_t *mp_rcp_ctrl_cnt; + nt_register_t *mp_rcp_data; + nt_field_t *mp_rcp_data_ol3_cmd; + nt_field_t *mp_rcp_data_ol4_cmd; + nt_field_t *mp_rcp_data_il3_cmd; + nt_field_t *mp_rcp_data_il4_cmd; +}; + +struct csu_nthw *csu_nthw_new(void); +void csu_nthw_delete(struct csu_nthw *p); +int csu_nthw_init(struct csu_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int csu_nthw_setup(struct csu_nthw *p, int n_idx, int n_idx_cnt); +void csu_nthw_set_debug_mode(struct csu_nthw *p, unsigned int n_debug_mode); + +void csu_nthw_rcp_select(const struct csu_nthw *p, uint32_t val); +void csu_nthw_rcp_cnt(const struct csu_nthw *p, uint32_t val); +void csu_nthw_rcp_outer_l3_cmd(const struct csu_nthw *p, uint32_t val); +void csu_nthw_rcp_outer_l4_cmd(const struct csu_nthw *p, uint32_t val); +void csu_nthw_rcp_inner_l3_cmd(const struct csu_nthw *p, uint32_t val); +void csu_nthw_rcp_inner_l4_cmd(const struct csu_nthw *p, uint32_t val); +void csu_nthw_rcp_flush(const struct csu_nthw *p); + +#endif /* _FLOW_NTHW_CSU_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.c new file mode 100644 index 0000000000..4549898cc1 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.c @@ -0,0 +1,1140 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" +#include "nthw_rac.h" + +#include "flow_nthw_flm.h" + +#include /* malloc */ +#include /* memset */ + +struct flm_nthw *flm_nthw_new(void) +{ + struct flm_nthw *p = malloc(sizeof(struct flm_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + + return p; +} + +void flm_nthw_delete(struct flm_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +void flm_nthw_set_debug_mode(struct flm_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_flm, n_debug_mode); +} + +int flm_nthw_init(struct flm_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_FLM, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: Flm %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_rac = p_fpga->p_fpga_info->mp_nthw_rac; + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_flm = p_mod; + + p->mp_control = module_get_register(p->m_flm, FLM_CONTROL); + p->mp_control_enable = + register_get_field(p->mp_control, FLM_CONTROL_ENABLE); + p->mp_control_init = register_get_field(p->mp_control, FLM_CONTROL_INIT); + p->mp_control_lds = register_get_field(p->mp_control, FLM_CONTROL_LDS); + p->mp_control_lfs = register_get_field(p->mp_control, FLM_CONTROL_LFS); + p->mp_control_lis = register_get_field(p->mp_control, FLM_CONTROL_LIS); + p->mp_control_uds = register_get_field(p->mp_control, FLM_CONTROL_UDS); + p->mp_control_uis = register_get_field(p->mp_control, FLM_CONTROL_UIS); + p->mp_control_rds = register_get_field(p->mp_control, FLM_CONTROL_RDS); + p->mp_control_ris = register_get_field(p->mp_control, FLM_CONTROL_RIS); + p->mp_control_pds = register_query_field(p->mp_control, FLM_CONTROL_PDS); + p->mp_control_pis = register_query_field(p->mp_control, FLM_CONTROL_PIS); + p->mp_control_crcwr = register_get_field(p->mp_control, FLM_CONTROL_CRCWR); + p->mp_control_crcrd = register_get_field(p->mp_control, FLM_CONTROL_CRCRD); + p->mp_control_rbl = register_get_field(p->mp_control, FLM_CONTROL_RBL); + p->mp_control_eab = register_get_field(p->mp_control, FLM_CONTROL_EAB); + p->mp_control_split_sdram_usage = + register_get_field(p->mp_control, FLM_CONTROL_SPLIT_SDRAM_USAGE); + + p->mp_status = module_get_register(p->m_flm, FLM_STATUS); + p->mp_status_calibdone = + register_get_field(p->mp_status, FLM_STATUS_CALIBDONE); + p->mp_status_initdone = + register_get_field(p->mp_status, FLM_STATUS_INITDONE); + p->mp_status_idle = register_get_field(p->mp_status, FLM_STATUS_IDLE); + p->mp_status_critical = + register_get_field(p->mp_status, FLM_STATUS_CRITICAL); + p->mp_status_panic = register_get_field(p->mp_status, FLM_STATUS_PANIC); + p->mp_status_crcerr = register_get_field(p->mp_status, FLM_STATUS_CRCERR); + p->mp_status_eft_bp = register_get_field(p->mp_status, FLM_STATUS_EFT_BP); + + p->mp_timeout = module_get_register(p->m_flm, FLM_TIMEOUT); + p->mp_timeout_t = register_get_field(p->mp_timeout, FLM_TIMEOUT_T); + + p->mp_scrub = module_get_register(p->m_flm, FLM_SCRUB); + p->mp_scrub_i = register_get_field(p->mp_scrub, FLM_SCRUB_I); + + p->mp_load_bin = module_get_register(p->m_flm, FLM_LOAD_BIN); + p->mp_load_bin_bin = register_get_field(p->mp_load_bin, FLM_LOAD_BIN_BIN); + + p->mp_load_pps = module_get_register(p->m_flm, FLM_LOAD_PPS); + p->mp_load_pps_pps = register_get_field(p->mp_load_pps, FLM_LOAD_PPS_PPS); + + p->mp_load_lps = module_get_register(p->m_flm, FLM_LOAD_LPS); + p->mp_load_lps_lps = register_get_field(p->mp_load_lps, FLM_LOAD_LPS_LPS); + + p->mp_load_aps = module_get_register(p->m_flm, FLM_LOAD_APS); + p->mp_load_aps_aps = register_get_field(p->mp_load_aps, FLM_LOAD_APS_APS); + + p->mp_prio = module_get_register(p->m_flm, FLM_PRIO); + p->mp_prio_limit0 = register_get_field(p->mp_prio, FLM_PRIO_LIMIT0); + p->mp_prio_ft0 = register_get_field(p->mp_prio, FLM_PRIO_FT0); + p->mp_prio_limit1 = register_get_field(p->mp_prio, FLM_PRIO_LIMIT1); + p->mp_prio_ft1 = register_get_field(p->mp_prio, FLM_PRIO_FT1); + p->mp_prio_limit2 = register_get_field(p->mp_prio, FLM_PRIO_LIMIT2); + p->mp_prio_ft2 = register_get_field(p->mp_prio, FLM_PRIO_FT2); + p->mp_prio_limit3 = register_get_field(p->mp_prio, FLM_PRIO_LIMIT3); + p->mp_prio_ft3 = register_get_field(p->mp_prio, FLM_PRIO_FT3); + + p->mp_pst_ctrl = module_get_register(p->m_flm, FLM_PST_CTRL); + p->mp_pst_ctrl_adr = register_get_field(p->mp_pst_ctrl, FLM_PST_CTRL_ADR); + p->mp_pst_ctrl_cnt = register_get_field(p->mp_pst_ctrl, FLM_PST_CTRL_CNT); + p->mp_pst_data = module_get_register(p->m_flm, FLM_PST_DATA); + p->mp_pst_data_bp = register_get_field(p->mp_pst_data, FLM_PST_DATA_BP); + p->mp_pst_data_pp = register_get_field(p->mp_pst_data, FLM_PST_DATA_PP); + p->mp_pst_data_tp = register_get_field(p->mp_pst_data, FLM_PST_DATA_TP); + + p->mp_rcp_ctrl = module_get_register(p->m_flm, FLM_RCP_CTRL); + p->mp_rcp_ctrl_adr = register_get_field(p->mp_rcp_ctrl, FLM_RCP_CTRL_ADR); + p->mp_rcp_ctrl_cnt = register_get_field(p->mp_rcp_ctrl, FLM_RCP_CTRL_CNT); + p->mp_rcp_data = module_get_register(p->m_flm, FLM_RCP_DATA); + p->mp_rcp_data_lookup = + register_get_field(p->mp_rcp_data, FLM_RCP_DATA_LOOKUP); + p->mp_rcp_data_qw0_dyn = + register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW0_DYN); + p->mp_rcp_data_qw0_ofs = + register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW0_OFS); + p->mp_rcp_data_qw0_sel = + register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW0_SEL); + p->mp_rcp_data_qw4_dyn = + register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW4_DYN); + p->mp_rcp_data_qw4_ofs = + register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW4_OFS); + p->mp_rcp_data_sw8_dyn = + register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW8_DYN); + p->mp_rcp_data_sw8_ofs = + register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW8_OFS); + p->mp_rcp_data_sw8_sel = + register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW8_SEL); + p->mp_rcp_data_sw9_dyn = + register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW9_DYN); + p->mp_rcp_data_sw9_ofs = + register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW9_OFS); + p->mp_rcp_data_mask = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_MASK); + p->mp_rcp_data_kid = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_KID); + p->mp_rcp_data_opn = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_OPN); + p->mp_rcp_data_ipn = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_IPN); + p->mp_rcp_data_byt_dyn = + register_get_field(p->mp_rcp_data, FLM_RCP_DATA_BYT_DYN); + p->mp_rcp_data_byt_ofs = + register_get_field(p->mp_rcp_data, FLM_RCP_DATA_BYT_OFS); + p->mp_rcp_data_txplm = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_TXPLM); + p->mp_rcp_data_auto_ipv4_mask = + register_get_field(p->mp_rcp_data, FLM_RCP_DATA_AUTO_IPV4_MASK); + + p->mp_buf_ctrl = module_get_register(p->m_flm, FLM_BUF_CTRL); + + p->mp_lrn_data = module_get_register(p->m_flm, FLM_LRN_DATA); + p->mp_inf_data = module_get_register(p->m_flm, FLM_INF_DATA); + p->mp_sta_data = module_get_register(p->m_flm, FLM_STA_DATA); + + p->mp_stat_lrn_done = module_get_register(p->m_flm, FLM_STAT_LRN_DONE); + p->mp_stat_lrn_done_cnt = + register_get_field(p->mp_stat_lrn_done, FLM_STAT_LRN_DONE_CNT); + + p->mp_stat_lrn_ignore = module_get_register(p->m_flm, FLM_STAT_LRN_IGNORE); + p->mp_stat_lrn_ignore_cnt = + register_get_field(p->mp_stat_lrn_ignore, FLM_STAT_LRN_IGNORE_CNT); + + p->mp_stat_lrn_fail = module_get_register(p->m_flm, FLM_STAT_LRN_FAIL); + p->mp_stat_lrn_fail_cnt = + register_get_field(p->mp_stat_lrn_fail, FLM_STAT_LRN_FAIL_CNT); + + p->mp_stat_unl_done = module_get_register(p->m_flm, FLM_STAT_UNL_DONE); + p->mp_stat_unl_done_cnt = + register_get_field(p->mp_stat_unl_done, FLM_STAT_UNL_DONE_CNT); + + p->mp_stat_unl_ignore = module_get_register(p->m_flm, FLM_STAT_UNL_IGNORE); + p->mp_stat_unl_ignore_cnt = + register_get_field(p->mp_stat_unl_ignore, FLM_STAT_UNL_IGNORE_CNT); + + p->mp_stat_prb_done = module_query_register(p->m_flm, FLM_STAT_PRB_DONE); + p->mp_stat_prb_done_cnt = + register_query_field(p->mp_stat_prb_done, FLM_STAT_PRB_DONE_CNT); + + p->mp_stat_prb_ignore = module_query_register(p->m_flm, FLM_STAT_PRB_IGNORE); + p->mp_stat_prb_ignore_cnt = register_query_field(p->mp_stat_prb_ignore, + FLM_STAT_PRB_IGNORE_CNT); + + p->mp_stat_rel_done = module_get_register(p->m_flm, FLM_STAT_REL_DONE); + p->mp_stat_rel_done_cnt = + register_get_field(p->mp_stat_rel_done, FLM_STAT_REL_DONE_CNT); + + p->mp_stat_rel_ignore = module_get_register(p->m_flm, FLM_STAT_REL_IGNORE); + p->mp_stat_rel_ignore_cnt = + register_get_field(p->mp_stat_rel_ignore, FLM_STAT_REL_IGNORE_CNT); + + p->mp_stat_aul_done = module_get_register(p->m_flm, FLM_STAT_AUL_DONE); + p->mp_stat_aul_done_cnt = + register_get_field(p->mp_stat_aul_done, FLM_STAT_AUL_DONE_CNT); + + p->mp_stat_aul_ignore = module_get_register(p->m_flm, FLM_STAT_AUL_IGNORE); + p->mp_stat_aul_ignore_cnt = + register_get_field(p->mp_stat_aul_ignore, FLM_STAT_AUL_IGNORE_CNT); + + p->mp_stat_aul_fail = module_get_register(p->m_flm, FLM_STAT_AUL_FAIL); + p->mp_stat_aul_fail_cnt = + register_get_field(p->mp_stat_aul_fail, FLM_STAT_AUL_FAIL_CNT); + + p->mp_stat_tul_done = module_get_register(p->m_flm, FLM_STAT_TUL_DONE); + p->mp_stat_tul_done_cnt = + register_get_field(p->mp_stat_tul_done, FLM_STAT_TUL_DONE_CNT); + + p->mp_stat_flows = module_get_register(p->m_flm, FLM_STAT_FLOWS); + p->mp_stat_flows_cnt = + register_get_field(p->mp_stat_flows, FLM_STAT_FLOWS_CNT); + + p->mp_stat_sta_done = module_query_register(p->m_flm, FLM_STAT_STA_DONE); + p->mp_stat_sta_done_cnt = + register_query_field(p->mp_stat_sta_done, FLM_STAT_STA_DONE_CNT); + + p->mp_stat_inf_done = module_query_register(p->m_flm, FLM_STAT_INF_DONE); + p->mp_stat_inf_done_cnt = + register_query_field(p->mp_stat_inf_done, FLM_STAT_INF_DONE_CNT); + + p->mp_stat_inf_skip = module_query_register(p->m_flm, FLM_STAT_INF_SKIP); + p->mp_stat_inf_skip_cnt = + register_query_field(p->mp_stat_inf_skip, FLM_STAT_INF_SKIP_CNT); + + p->mp_stat_pck_hit = module_query_register(p->m_flm, FLM_STAT_PCK_HIT); + p->mp_stat_pck_hit_cnt = + register_query_field(p->mp_stat_pck_hit, FLM_STAT_PCK_HIT_CNT); + + p->mp_stat_pck_miss = module_query_register(p->m_flm, FLM_STAT_PCK_MISS); + p->mp_stat_pck_miss_cnt = + register_query_field(p->mp_stat_pck_miss, FLM_STAT_PCK_MISS_CNT); + + p->mp_stat_pck_unh = module_query_register(p->m_flm, FLM_STAT_PCK_UNH); + p->mp_stat_pck_unh_cnt = + register_query_field(p->mp_stat_pck_unh, FLM_STAT_PCK_UNH_CNT); + + p->mp_stat_pck_dis = module_query_register(p->m_flm, FLM_STAT_PCK_DIS); + p->mp_stat_pck_dis_cnt = + register_query_field(p->mp_stat_pck_dis, FLM_STAT_PCK_DIS_CNT); + + p->mp_stat_csh_hit = module_query_register(p->m_flm, FLM_STAT_CSH_HIT); + p->mp_stat_csh_hit_cnt = + register_query_field(p->mp_stat_csh_hit, FLM_STAT_CSH_HIT_CNT); + + p->mp_stat_csh_miss = module_query_register(p->m_flm, FLM_STAT_CSH_MISS); + p->mp_stat_csh_miss_cnt = + register_query_field(p->mp_stat_csh_miss, FLM_STAT_CSH_MISS_CNT); + + p->mp_stat_csh_unh = module_query_register(p->m_flm, FLM_STAT_CSH_UNH); + p->mp_stat_csh_unh_cnt = + register_query_field(p->mp_stat_csh_unh, FLM_STAT_CSH_UNH_CNT); + + p->mp_stat_cuc_start = module_query_register(p->m_flm, FLM_STAT_CUC_START); + p->mp_stat_cuc_start_cnt = + register_query_field(p->mp_stat_cuc_start, FLM_STAT_CUC_START_CNT); + + p->mp_stat_cuc_move = module_query_register(p->m_flm, FLM_STAT_CUC_MOVE); + p->mp_stat_cuc_move_cnt = + register_query_field(p->mp_stat_cuc_move, FLM_STAT_CUC_MOVE_CNT); + + return 0; +} + +void flm_nthw_control_enable(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_control_enable, val); +} + +void flm_nthw_control_init(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_control_init, val); +} + +void flm_nthw_control_lds(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_control_lds, val); +} + +void flm_nthw_control_lfs(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_control_lfs, val); +} + +void flm_nthw_control_lis(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_control_lis, val); +} + +void flm_nthw_control_uds(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_control_uds, val); +} + +void flm_nthw_control_uis(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_control_uis, val); +} + +void flm_nthw_control_rds(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_control_rds, val); +} + +void flm_nthw_control_ris(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_control_ris, val); +} + +void flm_nthw_control_pds(const struct flm_nthw *p, uint32_t val) +{ + assert(p->mp_control_pds); + field_set_val32(p->mp_control_pds, val); +} + +void flm_nthw_control_pis(const struct flm_nthw *p, uint32_t val) +{ + assert(p->mp_control_pis); + field_set_val32(p->mp_control_pis, val); +} + +void flm_nthw_control_crcwr(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_control_crcwr, val); +} + +void flm_nthw_control_crcrd(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_control_crcrd, val); +} + +void flm_nthw_control_rbl(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_control_rbl, val); +} + +void flm_nthw_control_eab(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_control_eab, val); +} + +void flm_nthw_control_split_sdram_usage(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_control_split_sdram_usage, val); +} + +void flm_nthw_control_flush(const struct flm_nthw *p) +{ + register_flush(p->mp_control, 1); +} + +void flm_nthw_status_calibdone(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_status_calibdone); +} + +void flm_nthw_status_initdone(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_status_initdone); +} + +void flm_nthw_status_idle(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_status_idle); +} + +void flm_nthw_status_critical(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_status_critical); + + else + field_set_val32(p->mp_status_critical, *val); +} + +void flm_nthw_status_panic(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_status_panic); + + else + field_set_val32(p->mp_status_panic, *val); +} + +void flm_nthw_status_crcerr(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_status_crcerr); + + else + field_set_val32(p->mp_status_crcerr, *val); +} + +void flm_nthw_status_eft_bp(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_status_eft_bp); +} + +void flm_nthw_status_flush(const struct flm_nthw *p) +{ + register_flush(p->mp_status, 1); +} + +void flm_nthw_status_update(const struct flm_nthw *p) +{ + register_update(p->mp_status); +} + +void flm_nthw_timeout_t(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_timeout_t, val); +} + +void flm_nthw_timeout_flush(const struct flm_nthw *p) +{ + register_flush(p->mp_timeout, 1); +} + +void flm_nthw_scrub_i(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_scrub_i, val); +} + +void flm_nthw_scrub_flush(const struct flm_nthw *p) +{ + register_flush(p->mp_scrub, 1); +} + +void flm_nthw_load_bin(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_load_bin_bin, val); +} + +void flm_nthw_load_bin_flush(const struct flm_nthw *p) +{ + register_flush(p->mp_load_bin, 1); +} + +void flm_nthw_load_pps(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_load_pps_pps, val); +} + +void flm_nthw_load_pps_flush(const struct flm_nthw *p) +{ + register_flush(p->mp_load_pps, 1); +} + +void flm_nthw_load_lps(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_load_lps_lps, val); +} + +void flm_nthw_load_lps_flush(const struct flm_nthw *p) +{ + register_flush(p->mp_load_lps, 1); +} + +void flm_nthw_load_aps(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_load_aps_aps, val); +} + +void flm_nthw_load_aps_flush(const struct flm_nthw *p) +{ + register_flush(p->mp_load_aps, 1); +} + +void flm_nthw_prio_limit0(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_prio_limit0, val); +} + +void flm_nthw_prio_ft0(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_prio_ft0, val); +} + +void flm_nthw_prio_limit1(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_prio_limit1, val); +} + +void flm_nthw_prio_ft1(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_prio_ft1, val); +} + +void flm_nthw_prio_limit2(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_prio_limit2, val); +} + +void flm_nthw_prio_ft2(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_prio_ft2, val); +} + +void flm_nthw_prio_limit3(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_prio_limit3, val); +} + +void flm_nthw_prio_ft3(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_prio_ft3, val); +} + +void flm_nthw_prio_flush(const struct flm_nthw *p) +{ + register_flush(p->mp_prio, 1); +} + +void flm_nthw_pst_select(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_pst_ctrl_adr, val); +} + +void flm_nthw_pst_cnt(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_pst_ctrl_cnt, val); +} + +void flm_nthw_pst_bp(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_pst_data_bp, val); +} + +void flm_nthw_pst_pp(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_pst_data_pp, val); +} + +void flm_nthw_pst_tp(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_pst_data_tp, val); +} + +void flm_nthw_pst_flush(const struct flm_nthw *p) +{ + register_flush(p->mp_pst_ctrl, 1); + register_flush(p->mp_pst_data, 1); +} + +void flm_nthw_rcp_select(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_ctrl_adr, val); +} + +void flm_nthw_rcp_cnt(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_ctrl_cnt, val); +} + +void flm_nthw_rcp_lookup(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_lookup, val); +} + +void flm_nthw_rcp_qw0_dyn(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_qw0_dyn, val); +} + +void flm_nthw_rcp_qw0_ofs(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_qw0_ofs, val); +} + +void flm_nthw_rcp_qw0_sel(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_qw0_sel, val); +} + +void flm_nthw_rcp_qw4_dyn(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_qw4_dyn, val); +} + +void flm_nthw_rcp_qw4_ofs(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_qw4_ofs, val); +} + +void flm_nthw_rcp_sw8_dyn(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_sw8_dyn, val); +} + +void flm_nthw_rcp_sw8_ofs(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_sw8_ofs, val); +} + +void flm_nthw_rcp_sw8_sel(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_sw8_sel, val); +} + +void flm_nthw_rcp_sw9_dyn(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_sw9_dyn, val); +} + +void flm_nthw_rcp_sw9_ofs(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_sw9_ofs, val); +} + +void flm_nthw_rcp_mask(const struct flm_nthw *p, const uint32_t *val) +{ + field_set_val(p->mp_rcp_data_mask, val, 10); +} + +void flm_nthw_rcp_kid(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_kid, val); +} + +void flm_nthw_rcp_opn(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_opn, val); +} + +void flm_nthw_rcp_ipn(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ipn, val); +} + +void flm_nthw_rcp_byt_dyn(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_byt_dyn, val); +} + +void flm_nthw_rcp_byt_ofs(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_byt_ofs, val); +} + +void flm_nthw_rcp_txplm(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_txplm, val); +} + +void flm_nthw_rcp_auto_ipv4_mask(const struct flm_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_auto_ipv4_mask, val); +} + +void flm_nthw_rcp_flush(const struct flm_nthw *p) +{ + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +} + +int flm_nthw_buf_ctrl_update(const struct flm_nthw *p, uint32_t *lrn_free, + uint32_t *inf_avail, uint32_t *sta_avail) +{ + int ret = -1; + + struct nthw_rac *rac = (struct nthw_rac *)p->mp_rac; + uint32_t address_bufctrl = register_get_address(p->mp_buf_ctrl); + rab_bus_id_t bus_id = 1; + struct dma_buf_ptr bc_buf; + + ret = nthw_rac_rab_dma_begin(rac); + if (ret == 0) { + nthw_rac_rab_read32_dma(rac, address_bufctrl, bus_id, 2, &bc_buf); + ret = nthw_rac_rab_dma_commit(rac); + if (ret != 0) + return ret; + + uint32_t bc_mask = bc_buf.size - 1; + uint32_t bc_index = bc_buf.index; + *lrn_free = bc_buf.base[bc_index & bc_mask] & 0xffff; + *inf_avail = (bc_buf.base[bc_index & bc_mask] >> 16) & 0xffff; + *sta_avail = bc_buf.base[(bc_index + 1) & bc_mask] & 0xffff; + } + + return ret; +} + +int flm_nthw_lrn_data_flush(const struct flm_nthw *p, const uint32_t *data, + uint32_t word_count, uint32_t *lrn_free, + uint32_t *inf_avail, uint32_t *sta_avail) +{ + int ret = -1; + + struct nthw_rac *rac = (struct nthw_rac *)p->mp_rac; + uint32_t address = register_get_address(p->mp_lrn_data); + uint32_t address_bufctrl = register_get_address(p->mp_buf_ctrl); + rab_bus_id_t bus_id = 1; + struct dma_buf_ptr bc_buf; + + if (nthw_rac_rab_dma_begin(rac) == 0) { + /* Announce the number of words to write to LRN_DATA */ + uint32_t bufctrl_data[2]; + + bufctrl_data[0] = word_count; + bufctrl_data[1] = 0; + nthw_rac_rab_write32_dma(rac, address_bufctrl, bus_id, 2, + bufctrl_data); + nthw_rac_rab_write32_dma(rac, address, bus_id, word_count, data); + nthw_rac_rab_read32_dma(rac, address_bufctrl, bus_id, 2, &bc_buf); + ret = nthw_rac_rab_dma_commit(rac); + if (ret != 0) + return ret; + + uint32_t bc_mask = bc_buf.size - 1; + uint32_t bc_index = bc_buf.index; + *lrn_free = bc_buf.base[bc_index & bc_mask] & 0xffff; + *inf_avail = (bc_buf.base[bc_index & bc_mask] >> 16) & 0xffff; + *sta_avail = bc_buf.base[(bc_index + 1) & bc_mask] & 0xffff; + } + + return ret; +} + +int flm_nthw_inf_data_update(const struct flm_nthw *p, uint32_t *data, + uint32_t word_count, uint32_t *lrn_free, + uint32_t *inf_avail, uint32_t *sta_avail) +{ + int ret = -1; + + struct nthw_rac *rac = (struct nthw_rac *)p->mp_rac; + uint32_t address_infdata = register_get_address(p->mp_inf_data); + uint32_t address_bufctrl = register_get_address(p->mp_buf_ctrl); + rab_bus_id_t bus_id = 1; + struct dma_buf_ptr buf; + struct dma_buf_ptr bc_buf; + + ret = nthw_rac_rab_dma_begin(rac); + if (ret == 0) { + /* Announce the number of words to read from INF_DATA */ + uint32_t bufctrl_data[2]; + + bufctrl_data[0] = word_count << 16; + bufctrl_data[1] = 0; + nthw_rac_rab_write32_dma(rac, address_bufctrl, bus_id, 2, + bufctrl_data); + nthw_rac_rab_read32_dma(rac, address_infdata, bus_id, word_count, + &buf); + nthw_rac_rab_read32_dma(rac, address_bufctrl, bus_id, 2, &bc_buf); + ret = nthw_rac_rab_dma_commit(rac); + if (ret != 0) + return ret; + + uint32_t mask = buf.size - 1; + uint32_t index = buf.index; + + for (uint32_t i = 0; i < word_count; ++index, ++i) + data[i] = buf.base[index & mask]; + + uint32_t bc_mask = bc_buf.size - 1; + uint32_t bc_index = bc_buf.index; + *lrn_free = bc_buf.base[bc_index & bc_mask] & 0xffff; + *inf_avail = (bc_buf.base[bc_index & bc_mask] >> 16) & 0xffff; + *sta_avail = bc_buf.base[(bc_index + 1) & bc_mask] & 0xffff; + } + + return ret; +} + +int flm_nthw_sta_data_update(const struct flm_nthw *p, uint32_t *data, + uint32_t word_count, uint32_t *lrn_free, + uint32_t *inf_avail, uint32_t *sta_avail) +{ + int ret = -1; + + struct nthw_rac *rac = (struct nthw_rac *)p->mp_rac; + uint32_t address_stadata = register_get_address(p->mp_sta_data); + uint32_t address_bufctrl = register_get_address(p->mp_buf_ctrl); + rab_bus_id_t bus_id = 1; + struct dma_buf_ptr buf; + struct dma_buf_ptr bc_buf; + + ret = nthw_rac_rab_dma_begin(rac); + if (ret == 0) { + /* Announce the number of words to read from STA_DATA */ + uint32_t bufctrl_data[2]; + + bufctrl_data[0] = 0; + bufctrl_data[1] = word_count; + nthw_rac_rab_write32_dma(rac, address_bufctrl, bus_id, 2, + bufctrl_data); + nthw_rac_rab_read32_dma(rac, address_stadata, bus_id, word_count, + &buf); + nthw_rac_rab_read32_dma(rac, address_bufctrl, bus_id, 2, &bc_buf); + ret = nthw_rac_rab_dma_commit(rac); + if (ret != 0) + return ret; + + uint32_t mask = buf.size - 1; + uint32_t index = buf.index; + + for (uint32_t i = 0; i < word_count; ++index, ++i) + data[i] = buf.base[index & mask]; + + uint32_t bc_mask = bc_buf.size - 1; + uint32_t bc_index = bc_buf.index; + *lrn_free = bc_buf.base[bc_index & bc_mask] & 0xffff; + *inf_avail = (bc_buf.base[bc_index & bc_mask] >> 16) & 0xffff; + *sta_avail = bc_buf.base[(bc_index + 1) & bc_mask] & 0xffff; + } + + return ret; +} + +void flm_nthw_stat_lrn_done_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_stat_lrn_done_cnt); +} + +void flm_nthw_stat_lrn_done_update(const struct flm_nthw *p) +{ + register_update(p->mp_stat_lrn_done); +} + +void flm_nthw_stat_lrn_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_stat_lrn_ignore_cnt); +} + +void flm_nthw_stat_lrn_ignore_update(const struct flm_nthw *p) +{ + register_update(p->mp_stat_lrn_ignore); +} + +void flm_nthw_stat_lrn_fail_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_stat_lrn_fail_cnt); +} + +void flm_nthw_stat_lrn_fail_update(const struct flm_nthw *p) +{ + register_update(p->mp_stat_lrn_fail); +} + +void flm_nthw_stat_unl_done_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_stat_unl_done_cnt); +} + +void flm_nthw_stat_unl_done_update(const struct flm_nthw *p) +{ + register_update(p->mp_stat_unl_done); +} + +void flm_nthw_stat_unl_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_stat_unl_ignore_cnt); +} + +void flm_nthw_stat_unl_ignore_update(const struct flm_nthw *p) +{ + register_update(p->mp_stat_unl_ignore); +} + +void flm_nthw_stat_prb_done_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + assert(p->mp_stat_prb_done_cnt); + if (get) + *val = field_get_val32(p->mp_stat_prb_done_cnt); +} + +void flm_nthw_stat_prb_done_update(const struct flm_nthw *p) +{ + assert(p->mp_stat_prb_done); + register_update(p->mp_stat_prb_done); +} + +void flm_nthw_stat_prb_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + assert(p->mp_stat_prb_ignore_cnt); + if (get) + *val = field_get_val32(p->mp_stat_prb_ignore_cnt); +} + +void flm_nthw_stat_prb_ignore_update(const struct flm_nthw *p) +{ + assert(p->mp_stat_prb_ignore); + register_update(p->mp_stat_prb_ignore); +} + +void flm_nthw_stat_rel_done_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_stat_rel_done_cnt); +} + +void flm_nthw_stat_rel_done_update(const struct flm_nthw *p) +{ + register_update(p->mp_stat_rel_done); +} + +void flm_nthw_stat_rel_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_stat_rel_ignore_cnt); +} + +void flm_nthw_stat_rel_ignore_update(const struct flm_nthw *p) +{ + register_update(p->mp_stat_rel_ignore); +} + +void flm_nthw_stat_aul_done_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_stat_aul_done_cnt); +} + +void flm_nthw_stat_aul_done_update(const struct flm_nthw *p) +{ + register_update(p->mp_stat_aul_done); +} + +void flm_nthw_stat_aul_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_stat_aul_ignore_cnt); +} + +void flm_nthw_stat_aul_ignore_update(const struct flm_nthw *p) +{ + register_update(p->mp_stat_aul_ignore); +} + +void flm_nthw_stat_aul_fail_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_stat_aul_fail_cnt); +} + +void flm_nthw_stat_aul_fail_update(const struct flm_nthw *p) +{ + register_update(p->mp_stat_aul_fail); +} + +void flm_nthw_stat_tul_done_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_stat_tul_done_cnt); +} + +void flm_nthw_stat_tul_done_update(const struct flm_nthw *p) +{ + register_update(p->mp_stat_tul_done); +} + +void flm_nthw_stat_flows_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + if (get) + *val = field_get_val32(p->mp_stat_flows_cnt); +} + +void flm_nthw_stat_flows_update(const struct flm_nthw *p) +{ + register_update(p->mp_stat_flows); +} + +void flm_nthw_stat_sta_done_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + assert(p->mp_stat_sta_done_cnt); + if (get) + *val = field_get_val32(p->mp_stat_sta_done_cnt); +} + +void flm_nthw_stat_sta_done_update(const struct flm_nthw *p) +{ + assert(p->mp_stat_sta_done); + register_update(p->mp_stat_sta_done); +} + +void flm_nthw_stat_inf_done_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + assert(p->mp_stat_inf_done_cnt); + if (get) + *val = field_get_val32(p->mp_stat_inf_done_cnt); +} + +void flm_nthw_stat_inf_done_update(const struct flm_nthw *p) +{ + assert(p->mp_stat_inf_done); + register_update(p->mp_stat_inf_done); +} + +void flm_nthw_stat_inf_skip_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + assert(p->mp_stat_inf_skip_cnt); + if (get) + *val = field_get_val32(p->mp_stat_inf_skip_cnt); +} + +void flm_nthw_stat_inf_skip_update(const struct flm_nthw *p) +{ + assert(p->mp_stat_inf_skip); + register_update(p->mp_stat_inf_skip); +} + +void flm_nthw_stat_pck_hit_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + assert(p->mp_stat_pck_hit_cnt); + if (get) + *val = field_get_val32(p->mp_stat_pck_hit_cnt); +} + +void flm_nthw_stat_pck_hit_update(const struct flm_nthw *p) +{ + assert(p->mp_stat_pck_hit); + register_update(p->mp_stat_pck_hit); +} + +void flm_nthw_stat_pck_miss_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + assert(p->mp_stat_pck_miss_cnt); + if (get) + *val = field_get_val32(p->mp_stat_pck_miss_cnt); +} + +void flm_nthw_stat_pck_miss_update(const struct flm_nthw *p) +{ + assert(p->mp_stat_pck_miss); + register_update(p->mp_stat_pck_miss); +} + +void flm_nthw_stat_pck_unh_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + assert(p->mp_stat_pck_unh_cnt); + if (get) + *val = field_get_val32(p->mp_stat_pck_unh_cnt); +} + +void flm_nthw_stat_pck_unh_update(const struct flm_nthw *p) +{ + assert(p->mp_stat_pck_unh); + register_update(p->mp_stat_pck_unh); +} + +void flm_nthw_stat_pck_dis_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + assert(p->mp_stat_pck_dis_cnt); + if (get) + *val = field_get_val32(p->mp_stat_pck_dis_cnt); +} + +void flm_nthw_stat_pck_dis_update(const struct flm_nthw *p) +{ + assert(p->mp_stat_pck_dis); + register_update(p->mp_stat_pck_dis); +} + +void flm_nthw_stat_csh_hit_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + assert(p->mp_stat_csh_hit_cnt); + if (get) + *val = field_get_val32(p->mp_stat_csh_hit_cnt); +} + +void flm_nthw_stat_csh_hit_update(const struct flm_nthw *p) +{ + assert(p->mp_stat_csh_hit); + register_update(p->mp_stat_csh_hit); +} + +void flm_nthw_stat_csh_miss_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + assert(p->mp_stat_csh_miss_cnt); + if (get) + *val = field_get_val32(p->mp_stat_csh_miss_cnt); +} + +void flm_nthw_stat_csh_miss_update(const struct flm_nthw *p) +{ + assert(p->mp_stat_csh_miss); + register_update(p->mp_stat_csh_miss); +} + +void flm_nthw_stat_csh_unh_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + assert(p->mp_stat_csh_unh_cnt); + if (get) + *val = field_get_val32(p->mp_stat_csh_unh_cnt); +} + +void flm_nthw_stat_csh_unh_update(const struct flm_nthw *p) +{ + assert(p->mp_stat_csh_unh); + register_update(p->mp_stat_csh_unh); +} + +void flm_nthw_stat_cuc_start_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + assert(p->mp_stat_cuc_start_cnt); + if (get) + *val = field_get_val32(p->mp_stat_cuc_start_cnt); +} + +void flm_nthw_stat_cuc_start_update(const struct flm_nthw *p) +{ + assert(p->mp_stat_cuc_start); + register_update(p->mp_stat_cuc_start); +} + +void flm_nthw_stat_cuc_move_cnt(const struct flm_nthw *p, uint32_t *val, int get) +{ + assert(p->mp_stat_cuc_move_cnt); + if (get) + *val = field_get_val32(p->mp_stat_cuc_move_cnt); +} + +void flm_nthw_stat_cuc_move_update(const struct flm_nthw *p) +{ + assert(p->mp_stat_cuc_move); + register_update(p->mp_stat_cuc_move); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.h new file mode 100644 index 0000000000..4796d43940 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.h @@ -0,0 +1,422 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_FLM_H__ +#define __FLOW_NTHW_FLM_H__ + +#include /* uint32_t */ +#include "nthw_fpga_model.h" + +struct flm_nthw; + +typedef struct flm_nthw flm_nthw_t; + +struct flm_nthw *flm_nthw_new(void); +void flm_nthw_delete(struct flm_nthw *p); +int flm_nthw_init(struct flm_nthw *p, nt_fpga_t *p_fpga, int n_instance); +void flm_nthw_set_debug_mode(struct flm_nthw *p, unsigned int n_debug_mode); + +/* Control */ +void flm_nthw_control_enable(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_init(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_lds(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_lfs(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_lis(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_uds(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_uis(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_rds(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_ris(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_pds(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_pis(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_crcwr(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_crcrd(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_rbl(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_eab(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_split_sdram_usage(const struct flm_nthw *p, uint32_t val); +void flm_nthw_control_flush(const struct flm_nthw *p); + +/* Status */ +void flm_nthw_status_calibdone(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_status_initdone(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_status_idle(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_status_critical(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_status_panic(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_status_crcerr(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_status_eft_bp(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_status_flush(const struct flm_nthw *p); +void flm_nthw_status_update(const struct flm_nthw *p); + +/* Timeout */ +void flm_nthw_timeout_t(const struct flm_nthw *p, uint32_t val); +void flm_nthw_timeout_flush(const struct flm_nthw *p); + +/* Scrub */ +void flm_nthw_scrub_i(const struct flm_nthw *p, uint32_t val); +void flm_nthw_scrub_flush(const struct flm_nthw *p); + +/* Load BIN */ +void flm_nthw_load_bin(const struct flm_nthw *p, uint32_t val); +void flm_nthw_load_bin_flush(const struct flm_nthw *p); + +/* Load PPS */ +void flm_nthw_load_pps(const struct flm_nthw *p, uint32_t val); +void flm_nthw_load_pps_flush(const struct flm_nthw *p); + +/* Load LPS */ +void flm_nthw_load_lps(const struct flm_nthw *p, uint32_t val); +void flm_nthw_load_lps_flush(const struct flm_nthw *p); + +/* Load APS */ +void flm_nthw_load_aps(const struct flm_nthw *p, uint32_t val); +void flm_nthw_load_aps_flush(const struct flm_nthw *p); + +/* Prio */ +void flm_nthw_prio_limit0(const struct flm_nthw *p, uint32_t val); +void flm_nthw_prio_ft0(const struct flm_nthw *p, uint32_t val); +void flm_nthw_prio_limit1(const struct flm_nthw *p, uint32_t val); +void flm_nthw_prio_ft1(const struct flm_nthw *p, uint32_t val); +void flm_nthw_prio_limit2(const struct flm_nthw *p, uint32_t val); +void flm_nthw_prio_ft2(const struct flm_nthw *p, uint32_t val); +void flm_nthw_prio_limit3(const struct flm_nthw *p, uint32_t val); +void flm_nthw_prio_ft3(const struct flm_nthw *p, uint32_t val); +void flm_nthw_prio_flush(const struct flm_nthw *p); + +/* PST */ +void flm_nthw_pst_select(const struct flm_nthw *p, uint32_t val); +void flm_nthw_pst_cnt(const struct flm_nthw *p, uint32_t val); +void flm_nthw_pst_bp(const struct flm_nthw *p, uint32_t val); +void flm_nthw_pst_pp(const struct flm_nthw *p, uint32_t val); +void flm_nthw_pst_tp(const struct flm_nthw *p, uint32_t val); +void flm_nthw_pst_flush(const struct flm_nthw *p); + +/* RCP */ +void flm_nthw_rcp_select(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_cnt(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_lookup(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_qw0_dyn(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_qw0_ofs(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_qw0_sel(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_qw4_dyn(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_qw4_ofs(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_sw8_dyn(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_sw8_ofs(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_sw8_sel(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_sw9_dyn(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_sw9_ofs(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_mask(const struct flm_nthw *p, const uint32_t *val); +void flm_nthw_rcp_kid(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_opn(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_ipn(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_byt_dyn(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_byt_ofs(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_txplm(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_auto_ipv4_mask(const struct flm_nthw *p, uint32_t val); +void flm_nthw_rcp_flush(const struct flm_nthw *p); + +/* Buf Ctrl */ +int flm_nthw_buf_ctrl_update(const struct flm_nthw *p, uint32_t *lrn_free, + uint32_t *inf_avail, uint32_t *sta_avail); + +/* Lrn Data */ +int flm_nthw_lrn_data_flush(const struct flm_nthw *p, const uint32_t *data, + uint32_t word_count, uint32_t *lrn_free, + uint32_t *inf_avail, uint32_t *sta_avail); + +/* Inf Data */ +int flm_nthw_inf_data_update(const struct flm_nthw *p, uint32_t *data, + uint32_t word_count, uint32_t *lrn_free, + uint32_t *inf_avail, uint32_t *sta_avail); + +/* Sta Data */ +int flm_nthw_sta_data_update(const struct flm_nthw *p, uint32_t *data, + uint32_t word_count, uint32_t *lrn_free, + uint32_t *inf_avail, uint32_t *sta_avail); + +/* Stat Lrn _done */ +void flm_nthw_stat_lrn_done_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_lrn_done_update(const struct flm_nthw *p); + +/* Stat Lrn Ignore */ +void flm_nthw_stat_lrn_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_lrn_ignore_update(const struct flm_nthw *p); + +/* Stat Lrn Fail */ +void flm_nthw_stat_lrn_fail_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_lrn_fail_update(const struct flm_nthw *p); + +/* Stat Unl _done */ +void flm_nthw_stat_unl_done_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_unl_done_update(const struct flm_nthw *p); + +/* Stat Unl Ignore */ +void flm_nthw_stat_unl_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_unl_ignore_update(const struct flm_nthw *p); + +/* Stat Prb _done */ +void flm_nthw_stat_prb_done_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_prb_done_update(const struct flm_nthw *p); + +/* Stat Prb Ignore */ +void flm_nthw_stat_prb_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_prb_ignore_update(const struct flm_nthw *p); + +/* Stat Rel _done */ +void flm_nthw_stat_rel_done_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_rel_done_update(const struct flm_nthw *p); + +/* Stat Rel Ignore */ +void flm_nthw_stat_rel_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_rel_ignore_update(const struct flm_nthw *p); + +/* Stat Aul _done */ +void flm_nthw_stat_aul_done_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_aul_done_update(const struct flm_nthw *p); + +/* Stat Aul Ignore */ +void flm_nthw_stat_aul_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_aul_ignore_update(const struct flm_nthw *p); + +/* Stat Aul Fail */ +void flm_nthw_stat_aul_fail_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_aul_fail_update(const struct flm_nthw *p); + +/* Stat Tul _done */ +void flm_nthw_stat_tul_done_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_tul_done_update(const struct flm_nthw *p); + +/* Stat Flows */ +void flm_nthw_stat_flows_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_flows_update(const struct flm_nthw *p); + +/* Stat Sta _done */ +void flm_nthw_stat_sta_done_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_sta_done_update(const struct flm_nthw *p); + +/* Stat Inf _done */ +void flm_nthw_stat_inf_done_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_inf_done_update(const struct flm_nthw *p); + +/* Stat Inf Skip */ +void flm_nthw_stat_inf_skip_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_inf_skip_update(const struct flm_nthw *p); + +/* Stat Pck Hit */ +void flm_nthw_stat_pck_hit_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_pck_hit_update(const struct flm_nthw *p); + +/* Stat Pck Miss */ +void flm_nthw_stat_pck_miss_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_pck_miss_update(const struct flm_nthw *p); + +/* Stat Pck Unh */ +void flm_nthw_stat_pck_unh_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_pck_unh_update(const struct flm_nthw *p); + +/* Stat Pck Dis */ +void flm_nthw_stat_pck_dis_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_pck_dis_update(const struct flm_nthw *p); + +/* Stat Csh Hit */ +void flm_nthw_stat_csh_hit_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_csh_hit_update(const struct flm_nthw *p); + +/* Stat Csh Miss */ +void flm_nthw_stat_csh_miss_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_csh_miss_update(const struct flm_nthw *p); + +/* Stat Csh Unh */ +void flm_nthw_stat_csh_unh_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_csh_unh_update(const struct flm_nthw *p); + +/* Stat Cuc Start */ +void flm_nthw_stat_cuc_start_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_cuc_start_update(const struct flm_nthw *p); + +/* Stat Cuc Move */ +void flm_nthw_stat_cuc_move_cnt(const struct flm_nthw *p, uint32_t *val, int get); +void flm_nthw_stat_cuc_move_update(const struct flm_nthw *p); + +struct flm_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + void *mp_rac; + + nt_module_t *m_flm; + + nt_register_t *mp_control; + nt_field_t *mp_control_enable; + nt_field_t *mp_control_init; + nt_field_t *mp_control_lds; + nt_field_t *mp_control_lfs; + nt_field_t *mp_control_lis; + nt_field_t *mp_control_uds; + nt_field_t *mp_control_uis; + nt_field_t *mp_control_rds; + nt_field_t *mp_control_ris; + nt_field_t *mp_control_pds; + nt_field_t *mp_control_pis; + nt_field_t *mp_control_crcwr; + nt_field_t *mp_control_crcrd; + nt_field_t *mp_control_rbl; + nt_field_t *mp_control_eab; + nt_field_t *mp_control_split_sdram_usage; + + nt_register_t *mp_status; + nt_field_t *mp_status_calibdone; + nt_field_t *mp_status_initdone; + nt_field_t *mp_status_idle; + nt_field_t *mp_status_critical; + nt_field_t *mp_status_panic; + nt_field_t *mp_status_crcerr; + nt_field_t *mp_status_eft_bp; + + nt_register_t *mp_timeout; + nt_field_t *mp_timeout_t; + + nt_register_t *mp_scrub; + nt_field_t *mp_scrub_i; + + nt_register_t *mp_load_bin; + nt_field_t *mp_load_bin_bin; + + nt_register_t *mp_load_pps; + nt_field_t *mp_load_pps_pps; + + nt_register_t *mp_load_lps; + nt_field_t *mp_load_lps_lps; + + nt_register_t *mp_load_aps; + nt_field_t *mp_load_aps_aps; + + nt_register_t *mp_prio; + nt_field_t *mp_prio_limit0; + nt_field_t *mp_prio_ft0; + nt_field_t *mp_prio_limit1; + nt_field_t *mp_prio_ft1; + nt_field_t *mp_prio_limit2; + nt_field_t *mp_prio_ft2; + nt_field_t *mp_prio_limit3; + nt_field_t *mp_prio_ft3; + + nt_register_t *mp_pst_ctrl; + nt_field_t *mp_pst_ctrl_adr; + nt_field_t *mp_pst_ctrl_cnt; + nt_register_t *mp_pst_data; + nt_field_t *mp_pst_data_bp; + nt_field_t *mp_pst_data_pp; + nt_field_t *mp_pst_data_tp; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_ctrl_adr; + nt_field_t *mp_rcp_ctrl_cnt; + nt_register_t *mp_rcp_data; + nt_field_t *mp_rcp_data_lookup; + nt_field_t *mp_rcp_data_qw0_dyn; + nt_field_t *mp_rcp_data_qw0_ofs; + nt_field_t *mp_rcp_data_qw0_sel; + nt_field_t *mp_rcp_data_qw4_dyn; + nt_field_t *mp_rcp_data_qw4_ofs; + nt_field_t *mp_rcp_data_sw8_dyn; + nt_field_t *mp_rcp_data_sw8_ofs; + nt_field_t *mp_rcp_data_sw8_sel; + nt_field_t *mp_rcp_data_sw9_dyn; + nt_field_t *mp_rcp_data_sw9_ofs; + nt_field_t *mp_rcp_data_mask; + nt_field_t *mp_rcp_data_kid; + nt_field_t *mp_rcp_data_opn; + nt_field_t *mp_rcp_data_ipn; + nt_field_t *mp_rcp_data_byt_dyn; + nt_field_t *mp_rcp_data_byt_ofs; + nt_field_t *mp_rcp_data_txplm; + nt_field_t *mp_rcp_data_auto_ipv4_mask; + + nt_register_t *mp_buf_ctrl; + nt_field_t *mp_buf_ctrl_lrn_free; + nt_field_t *mp_buf_ctrl_inf_avail; + nt_field_t *mp_buf_ctrl_sta_avail; + + nt_register_t *mp_lrn_data; + nt_register_t *mp_inf_data; + nt_register_t *mp_sta_data; + + nt_register_t *mp_stat_lrn_done; + nt_field_t *mp_stat_lrn_done_cnt; + + nt_register_t *mp_stat_lrn_ignore; + nt_field_t *mp_stat_lrn_ignore_cnt; + + nt_register_t *mp_stat_lrn_fail; + nt_field_t *mp_stat_lrn_fail_cnt; + + nt_register_t *mp_stat_unl_done; + nt_field_t *mp_stat_unl_done_cnt; + + nt_register_t *mp_stat_unl_ignore; + nt_field_t *mp_stat_unl_ignore_cnt; + + nt_register_t *mp_stat_prb_done; + nt_field_t *mp_stat_prb_done_cnt; + + nt_register_t *mp_stat_prb_ignore; + nt_field_t *mp_stat_prb_ignore_cnt; + + nt_register_t *mp_stat_rel_done; + nt_field_t *mp_stat_rel_done_cnt; + + nt_register_t *mp_stat_rel_ignore; + nt_field_t *mp_stat_rel_ignore_cnt; + + nt_register_t *mp_stat_aul_done; + nt_field_t *mp_stat_aul_done_cnt; + + nt_register_t *mp_stat_aul_ignore; + nt_field_t *mp_stat_aul_ignore_cnt; + + nt_register_t *mp_stat_aul_fail; + nt_field_t *mp_stat_aul_fail_cnt; + + nt_register_t *mp_stat_tul_done; + nt_field_t *mp_stat_tul_done_cnt; + + nt_register_t *mp_stat_flows; + nt_field_t *mp_stat_flows_cnt; + + nt_register_t *mp_stat_sta_done; + nt_field_t *mp_stat_sta_done_cnt; + + nt_register_t *mp_stat_inf_done; + nt_field_t *mp_stat_inf_done_cnt; + + nt_register_t *mp_stat_inf_skip; + nt_field_t *mp_stat_inf_skip_cnt; + + nt_register_t *mp_stat_pck_hit; + nt_field_t *mp_stat_pck_hit_cnt; + + nt_register_t *mp_stat_pck_miss; + nt_field_t *mp_stat_pck_miss_cnt; + + nt_register_t *mp_stat_pck_unh; + nt_field_t *mp_stat_pck_unh_cnt; + + nt_register_t *mp_stat_pck_dis; + nt_field_t *mp_stat_pck_dis_cnt; + + nt_register_t *mp_stat_csh_hit; + nt_field_t *mp_stat_csh_hit_cnt; + + nt_register_t *mp_stat_csh_miss; + nt_field_t *mp_stat_csh_miss_cnt; + + nt_register_t *mp_stat_csh_unh; + nt_field_t *mp_stat_csh_unh_cnt; + + nt_register_t *mp_stat_cuc_start; + nt_field_t *mp_stat_cuc_start_cnt; + + nt_register_t *mp_stat_cuc_move; + nt_field_t *mp_stat_cuc_move_cnt; +}; + +#endif /* __FLOW_NTHW_FLM_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.c new file mode 100644 index 0000000000..b7fe7c5863 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.c @@ -0,0 +1,293 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_hfu.h" + +#include +#include + +void hfu_nthw_set_debug_mode(struct hfu_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_hfu, n_debug_mode); +} + +struct hfu_nthw *hfu_nthw_new(void) +{ + struct hfu_nthw *p = malloc(sizeof(struct hfu_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + return p; +} + +void hfu_nthw_delete(struct hfu_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int hfu_nthw_init(struct hfu_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_HFU, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: Hfu %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_hfu = fpga_query_module(p_fpga, MOD_HFU, n_instance); + + p->mp_rcp_ctrl = module_get_register(p->m_hfu, HFU_RCP_CTRL); + p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, HFU_RCP_CTRL_ADR); + p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, HFU_RCP_CTRL_CNT); + + p->mp_rcp_data = module_get_register(p->m_hfu, HFU_RCP_DATA); + p->mp_rcp_data_len_a_wr = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_WR); + p->mp_rcp_data_len_a_ol4len = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_OL4LEN); + p->mp_rcp_data_len_a_pos_dyn = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_POS_DYN); + p->mp_rcp_data_len_a_pos_ofs = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_POS_OFS); + p->mp_rcp_data_len_a_add_dyn = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_ADD_DYN); + p->mp_rcp_data_len_a_add_ofs = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_ADD_OFS); + p->mp_rcp_data_len_a_sub_dyn = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_SUB_DYN); + p->mp_rcp_data_len_b_wr = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_WR); + p->mp_rcp_data_len_b_pos_dyn = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_POS_DYN); + p->mp_rcp_data_len_b_pos_ofs = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_POS_OFS); + p->mp_rcp_data_len_b_add_dyn = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_ADD_DYN); + p->mp_rcp_data_len_b_add_ofs = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_ADD_OFS); + p->mp_rcp_data_len_b_sub_dyn = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_SUB_DYN); + p->mp_rcp_data_len_c_wr = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_WR); + p->mp_rcp_data_len_c_pos_dyn = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_POS_DYN); + p->mp_rcp_data_len_c_pos_ofs = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_POS_OFS); + p->mp_rcp_data_len_c_add_dyn = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_ADD_DYN); + p->mp_rcp_data_len_c_add_ofs = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_ADD_OFS); + p->mp_rcp_data_len_c_sub_dyn = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_SUB_DYN); + p->mp_rcp_data_ttl_wr = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_TTL_WR); + p->mp_rcp_data_ttl_pos_dyn = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_TTL_POS_DYN); + p->mp_rcp_data_ttl_pos_ofs = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_TTL_POS_OFS); + p->mp_rcp_data_csinf = register_get_field(p->mp_rcp_data, HFU_RCP_DATA_CSINF); + p->mp_rcp_data_l3prt = register_get_field(p->mp_rcp_data, HFU_RCP_DATA_L3PRT); + p->mp_rcp_data_l3frag = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_L3FRAG); + p->mp_rcp_data_tunnel = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_TUNNEL); + p->mp_rcp_data_l4prt = register_get_field(p->mp_rcp_data, HFU_RCP_DATA_L4PRT); + p->mp_rcp_data_ol3ofs = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_OL3OFS); + p->mp_rcp_data_ol4ofs = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_OL4OFS); + p->mp_rcp_data_il3ofs = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_IL3OFS); + p->mp_rcp_data_il4ofs = + register_get_field(p->mp_rcp_data, HFU_RCP_DATA_IL4OFS); + + return 0; +} + +void hfu_nthw_rcp_select(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_addr, val); +} + +void hfu_nthw_rcp_cnt(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_cnt, val); +} + +void hfu_nthw_rcp_len_a_wr(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_a_wr, val); +} + +void hfu_nthw_rcp_len_a_ol4len(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_a_ol4len, val); +} + +void hfu_nthw_rcp_len_a_pos_dyn(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_a_pos_dyn, val); +} + +void hfu_nthw_rcp_len_a_pos_ofs(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_a_pos_ofs, val); +} + +void hfu_nthw_rcp_len_a_add_dyn(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_a_add_dyn, val); +} + +void hfu_nthw_rcp_len_a_add_ofs(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_a_add_ofs, val); +} + +void hfu_nthw_rcp_len_a_sub_dyn(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_a_sub_dyn, val); +} + +void hfu_nthw_rcp_len_b_wr(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_b_wr, val); +} + +void hfu_nthw_rcp_len_b_pos_dyn(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_b_pos_dyn, val); +} + +void hfu_nthw_rcp_len_b_pos_ofs(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_b_pos_ofs, val); +} + +void hfu_nthw_rcp_len_b_add_dyn(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_b_add_dyn, val); +} + +void hfu_nthw_rcp_len_b_add_ofs(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_b_add_ofs, val); +} + +void hfu_nthw_rcp_len_b_sub_dyn(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_b_sub_dyn, val); +} + +void hfu_nthw_rcp_len_c_wr(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_c_wr, val); +} + +void hfu_nthw_rcp_len_c_pos_dyn(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_c_pos_dyn, val); +} + +void hfu_nthw_rcp_len_c_pos_ofs(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_c_pos_ofs, val); +} + +void hfu_nthw_rcp_len_c_add_dyn(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_c_add_dyn, val); +} + +void hfu_nthw_rcp_len_c_add_ofs(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_c_add_ofs, val); +} + +void hfu_nthw_rcp_len_c_sub_dyn(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len_c_sub_dyn, val); +} + +void hfu_nthw_rcp_ttl_wr(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ttl_wr, val); +} + +void hfu_nthw_rcp_ttl_pos_dyn(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ttl_pos_dyn, val); +} + +void hfu_nthw_rcp_ttl_pos_ofs(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ttl_pos_ofs, val); +} + +void hfu_nthw_rcp_csinf(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_csinf, val); +} + +void hfu_nthw_rcp_l3prt(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_l3prt, val); +} + +void hfu_nthw_rcp_l3frag(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_l3frag, val); +} + +void hfu_nthw_rcp_tunnel(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_tunnel, val); +} + +void hfu_nthw_rcp_l4prt(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_l4prt, val); +} + +void hfu_nthw_rcp_ol3ofs(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ol3ofs, val); +} + +void hfu_nthw_rcp_ol4ofs(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ol4ofs, val); +} + +void hfu_nthw_rcp_il3ofs(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_il3ofs, val); +} + +void hfu_nthw_rcp_il4ofs(const struct hfu_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_il4ofs, val); +} + +void hfu_nthw_rcp_flush(const struct hfu_nthw *p) +{ + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.h new file mode 100644 index 0000000000..ecba1a8822 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_HFU_H__ +#define __FLOW_NTHW_HFU_H__ + +#include +#include "nthw_fpga_model.h" + +struct hfu_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_hfu; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_addr; + nt_field_t *mp_rcp_cnt; + + nt_register_t *mp_rcp_data; + nt_field_t *mp_rcp_data_len_a_wr; + nt_field_t *mp_rcp_data_len_a_ol4len; + nt_field_t *mp_rcp_data_len_a_pos_dyn; + nt_field_t *mp_rcp_data_len_a_pos_ofs; + nt_field_t *mp_rcp_data_len_a_add_dyn; + nt_field_t *mp_rcp_data_len_a_add_ofs; + nt_field_t *mp_rcp_data_len_a_sub_dyn; + nt_field_t *mp_rcp_data_len_b_wr; + nt_field_t *mp_rcp_data_len_b_pos_dyn; + nt_field_t *mp_rcp_data_len_b_pos_ofs; + nt_field_t *mp_rcp_data_len_b_add_dyn; + nt_field_t *mp_rcp_data_len_b_add_ofs; + nt_field_t *mp_rcp_data_len_b_sub_dyn; + nt_field_t *mp_rcp_data_len_c_wr; + nt_field_t *mp_rcp_data_len_c_pos_dyn; + nt_field_t *mp_rcp_data_len_c_pos_ofs; + nt_field_t *mp_rcp_data_len_c_add_dyn; + nt_field_t *mp_rcp_data_len_c_add_ofs; + nt_field_t *mp_rcp_data_len_c_sub_dyn; + nt_field_t *mp_rcp_data_ttl_wr; + nt_field_t *mp_rcp_data_ttl_pos_dyn; + nt_field_t *mp_rcp_data_ttl_pos_ofs; + nt_field_t *mp_rcp_data_csinf; + nt_field_t *mp_rcp_data_l3prt; + nt_field_t *mp_rcp_data_l3frag; + nt_field_t *mp_rcp_data_tunnel; + nt_field_t *mp_rcp_data_l4prt; + nt_field_t *mp_rcp_data_ol3ofs; + nt_field_t *mp_rcp_data_ol4ofs; + nt_field_t *mp_rcp_data_il3ofs; + nt_field_t *mp_rcp_data_il4ofs; +}; + +struct hfu_nthw *hfu_nthw_new(void); +void hfu_nthw_delete(struct hfu_nthw *p); +int hfu_nthw_init(struct hfu_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int hfu_nthw_setup(struct hfu_nthw *p, int n_idx, int n_idx_cnt); +void hfu_nthw_set_debug_mode(struct hfu_nthw *p, unsigned int n_debug_mode); + +/* RCP */ +void hfu_nthw_rcp_select(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_cnt(const struct hfu_nthw *p, uint32_t val); + +void hfu_nthw_rcp_len_a_wr(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_a_ol4len(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_a_pos_dyn(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_a_pos_ofs(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_a_add_dyn(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_a_add_ofs(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_a_sub_dyn(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_b_wr(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_b_pos_dyn(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_b_pos_ofs(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_b_add_dyn(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_b_add_ofs(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_b_sub_dyn(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_c_wr(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_c_pos_dyn(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_c_pos_ofs(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_c_add_dyn(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_c_add_ofs(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_len_c_sub_dyn(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_ttl_wr(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_ttl_pos_dyn(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_ttl_pos_ofs(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_csinf(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_l3prt(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_l3frag(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_tunnel(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_l4prt(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_ol3ofs(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_ol4ofs(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_il3ofs(const struct hfu_nthw *p, uint32_t val); +void hfu_nthw_rcp_il4ofs(const struct hfu_nthw *p, uint32_t val); + +void hfu_nthw_rcp_flush(const struct hfu_nthw *p); + +#endif /* __FLOW_NTHW_HFU_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.c new file mode 100644 index 0000000000..0dc6434e88 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.c @@ -0,0 +1,254 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_hsh.h" + +#include /* malloc */ +#include /* memset */ + +void hsh_nthw_set_debug_mode(struct hsh_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_hsh, n_debug_mode); +} + +struct hsh_nthw *hsh_nthw_new(void) +{ + struct hsh_nthw *p = malloc(sizeof(struct hsh_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + + return p; +} + +void hsh_nthw_delete(struct hsh_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int hsh_nthw_init(struct hsh_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_HSH, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: Hsh %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_hsh = p_mod; + + /* RCP */ + p->mp_rcp_ctrl = module_get_register(p->m_hsh, HSH_RCP_CTRL); + p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, HSH_RCP_CTRL_ADR); + p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, HSH_RCP_CTRL_CNT); + p->mp_rcp_data = module_get_register(p->m_hsh, HSH_RCP_DATA); + p->mp_rcp_data_load_dist_type = + register_get_field(p->mp_rcp_data, HSH_RCP_DATA_LOAD_DIST_TYPE); + p->mp_rcp_data_mac_port_mask = + register_get_field(p->mp_rcp_data, HSH_RCP_DATA_MAC_PORT_MASK); + p->mp_rcp_data_sort = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_SORT); + p->mp_rcp_data_qw0_pe = + register_get_field(p->mp_rcp_data, HSH_RCP_DATA_QW0_PE); + p->mp_rcp_data_qw0_ofs = + register_get_field(p->mp_rcp_data, HSH_RCP_DATA_QW0_OFS); + p->mp_rcp_data_qw4_pe = + register_get_field(p->mp_rcp_data, HSH_RCP_DATA_QW4_PE); + p->mp_rcp_data_qw4_ofs = + register_get_field(p->mp_rcp_data, HSH_RCP_DATA_QW4_OFS); + p->mp_rcp_data_w8_pe = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W8_PE); + p->mp_rcp_data_w8_ofs = + register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W8_OFS); + p->mp_rcp_data_w8_sort = + register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W8_SORT); + p->mp_rcp_data_w9_pe = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W9_PE); + p->mp_rcp_data_w9_ofs = + register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W9_OFS); + p->mp_rcp_data_w9_sort = + register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W9_SORT); + p->mp_rcp_data_w9_p = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W9_P); + p->mp_rcp_data_p_mask = + register_get_field(p->mp_rcp_data, HSH_RCP_DATA_P_MASK); + p->mp_rcp_data_word_mask = + register_get_field(p->mp_rcp_data, HSH_RCP_DATA_WORD_MASK); + p->mp_rcp_data_seed = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_SEED); + p->mp_rcp_data_tnl_p = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_TNL_P); + p->mp_rcp_data_hsh_valid = + register_get_field(p->mp_rcp_data, HSH_RCP_DATA_HSH_VALID); + p->mp_rcp_data_hsh_type = + register_get_field(p->mp_rcp_data, HSH_RCP_DATA_HSH_TYPE); + p->mp_rcp_data_auto_ipv4_mask = + register_query_field(p->mp_rcp_data, HSH_RCP_DATA_AUTO_IPV4_MASK); + + /* Init */ + uint32_t val[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + field_set_val32(p->mp_rcp_addr, 0); + field_set_val32(p->mp_rcp_cnt, 1); + + field_set_val32(p->mp_rcp_data_load_dist_type, 0); + field_set_val(p->mp_rcp_data_mac_port_mask, val, + p->mp_rcp_data_mac_port_mask->mn_words); + field_set_val32(p->mp_rcp_data_sort, 0); + field_set_val32(p->mp_rcp_data_qw0_pe, 0); + field_set_val32(p->mp_rcp_data_qw0_ofs, 0); + field_set_val32(p->mp_rcp_data_qw4_pe, 0); + field_set_val32(p->mp_rcp_data_qw4_ofs, 0); + field_set_val32(p->mp_rcp_data_w8_pe, 0); + field_set_val32(p->mp_rcp_data_w8_ofs, 0); + field_set_val32(p->mp_rcp_data_w8_sort, 0); + field_set_val32(p->mp_rcp_data_w9_pe, 0); + field_set_val32(p->mp_rcp_data_w9_ofs, 0); + field_set_val32(p->mp_rcp_data_w9_sort, 0); + field_set_val32(p->mp_rcp_data_w9_p, 0); + field_set_val(p->mp_rcp_data_word_mask, val, 10); + field_set_val32(p->mp_rcp_data_seed, 0); + field_set_val32(p->mp_rcp_data_tnl_p, 0); + field_set_val32(p->mp_rcp_data_hsh_valid, 0); + field_set_val32(p->mp_rcp_data_hsh_type, 31); + + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); + + return 0; +} + +void hsh_nthw_rcp_select(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_addr, val); +} + +void hsh_nthw_rcp_cnt(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_cnt, val); +} + +void hsh_nthw_rcp_load_dist_type(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_load_dist_type, val); +} + +void hsh_nthw_rcp_mac_port_mask(const struct hsh_nthw *p, uint32_t *val) +{ + field_set_val(p->mp_rcp_data_mac_port_mask, val, + p->mp_rcp_data_mac_port_mask->mn_words); +} + +void hsh_nthw_rcp_sort(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_sort, val); +} + +void hsh_nthw_rcp_qw0_pe(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_qw0_pe, val); +} + +void hsh_nthw_rcp_qw0_ofs(const struct hsh_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_qw0_ofs, val); +} + +void hsh_nthw_rcp_qw4_pe(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_qw4_pe, val); +} + +void hsh_nthw_rcp_qw4_ofs(const struct hsh_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_qw4_ofs, val); +} + +void hsh_nthw_rcp_w8_pe(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_w8_pe, val); +} + +void hsh_nthw_rcp_w8_ofs(const struct hsh_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_w8_ofs, val); +} + +void hsh_nthw_rcp_w8_sort(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_w8_sort, val); +} + +void hsh_nthw_rcp_w9_pe(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_w9_pe, val); +} + +void hsh_nthw_rcp_w9_ofs(const struct hsh_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_w9_ofs, val); +} + +void hsh_nthw_rcp_w9_sort(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_w9_sort, val); +} + +void hsh_nthw_rcp_w9_p(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_w9_p, val); +} + +void hsh_nthw_rcp_p_mask(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_p_mask, val); +} + +void hsh_nthw_rcp_word_mask(const struct hsh_nthw *p, uint32_t *val) +{ + field_set_val(p->mp_rcp_data_word_mask, val, 10); +} + +void hsh_nthw_rcp_seed(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_seed, val); +} + +void hsh_nthw_rcp_tnl_p(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_tnl_p, val); +} + +void hsh_nthw_rcp_hsh_valid(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_hsh_valid, val); +} + +void hsh_nthw_rcp_hsh_type(const struct hsh_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_hsh_type, val); +} + +void hsh_nthw_rcp_auto_ipv4_mask(const struct hsh_nthw *p, uint32_t val) +{ + if (p->mp_rcp_data_auto_ipv4_mask) + field_set_val32(p->mp_rcp_data_auto_ipv4_mask, val); +} + +void hsh_nthw_rcp_flush(const struct hsh_nthw *p) +{ + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.h new file mode 100644 index 0000000000..7cb7dbb743 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_HSH_H__ +#define __FLOW_NTHW_HSH_H__ + +#include /* uint32_t */ +#include "nthw_fpga_model.h" + +struct hsh_nthw; + +typedef struct hsh_nthw hsh_nthw_t; + +struct hsh_nthw *hsh_nthw_new(void); +void hsh_nthw_delete(struct hsh_nthw *p); +int hsh_nthw_init(struct hsh_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int hsh_nthw_setup(struct hsh_nthw *p, int n_idx, int n_idx_cnt); +void hsh_nthw_set_debug_mode(struct hsh_nthw *p, unsigned int n_debug_mode); + +/* RCP */ +void hsh_nthw_rcp_select(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_cnt(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_load_dist_type(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_mac_port_mask(const struct hsh_nthw *p, uint32_t *val); +void hsh_nthw_rcp_sort(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_qw0_pe(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_qw0_ofs(const struct hsh_nthw *p, int32_t val); +void hsh_nthw_rcp_qw4_pe(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_qw4_ofs(const struct hsh_nthw *p, int32_t val); +void hsh_nthw_rcp_w8_pe(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_w8_ofs(const struct hsh_nthw *p, int32_t val); +void hsh_nthw_rcp_w8_sort(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_w9_pe(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_w9_ofs(const struct hsh_nthw *p, int32_t val); +void hsh_nthw_rcp_w9_sort(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_w9_p(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_p_mask(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_word_mask(const struct hsh_nthw *p, uint32_t *val); +void hsh_nthw_rcp_seed(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_tnl_p(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_hsh_valid(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_hsh_type(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_auto_ipv4_mask(const struct hsh_nthw *p, uint32_t val); +void hsh_nthw_rcp_flush(const struct hsh_nthw *p); + +struct hsh_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_hsh; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_addr; + nt_field_t *mp_rcp_cnt; + nt_register_t *mp_rcp_data; + nt_field_t *mp_rcp_data_load_dist_type; + nt_field_t *mp_rcp_data_mac_port_mask; + nt_field_t *mp_rcp_data_sort; + nt_field_t *mp_rcp_data_qw0_pe; + nt_field_t *mp_rcp_data_qw0_ofs; + nt_field_t *mp_rcp_data_qw4_pe; + nt_field_t *mp_rcp_data_qw4_ofs; + nt_field_t *mp_rcp_data_w8_pe; + nt_field_t *mp_rcp_data_w8_ofs; + nt_field_t *mp_rcp_data_w8_sort; + nt_field_t *mp_rcp_data_w9_pe; + nt_field_t *mp_rcp_data_w9_ofs; + nt_field_t *mp_rcp_data_w9_sort; + nt_field_t *mp_rcp_data_w9_p; + nt_field_t *mp_rcp_data_p_mask; + nt_field_t *mp_rcp_data_word_mask; + nt_field_t *mp_rcp_data_seed; + nt_field_t *mp_rcp_data_tnl_p; + nt_field_t *mp_rcp_data_hsh_valid; + nt_field_t *mp_rcp_data_hsh_type; + nt_field_t *mp_rcp_data_auto_ipv4_mask; +}; + +#endif /* __FLOW_NTHW_HSH_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.c new file mode 100644 index 0000000000..fc3dc443a2 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.c @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_hst.h" + +#include /* malloc */ +#include /* memset */ + +void hst_nthw_set_debug_mode(struct hst_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_hst, n_debug_mode); +} + +struct hst_nthw *hst_nthw_new(void) +{ + struct hst_nthw *p = malloc(sizeof(struct hst_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + + return p; +} + +void hst_nthw_delete(struct hst_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int hst_nthw_init(struct hst_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_HST, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: Hst %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_hst = p_mod; + + /* RCP */ + p->mp_rcp_ctrl = module_get_register(p->m_hst, HST_RCP_CTRL); + p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, HST_RCP_CTRL_ADR); + p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, HST_RCP_CTRL_CNT); + + p->mp_rcp_data = module_get_register(p->m_hst, HST_RCP_DATA); + p->mp_rcp_data_strip_mode = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_STRIP_MODE); + p->mp_rcp_data_start_dyn = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_START_DYN); + p->mp_rcp_data_start_ofs = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_START_OFS); + p->mp_rcp_data_end_dyn = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_END_DYN); + p->mp_rcp_data_end_ofs = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_END_OFS); + p->mp_rcp_data_modif0_cmd = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF0_CMD); + p->mp_rcp_data_modif0_dyn = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF0_DYN); + p->mp_rcp_data_modif0_ofs = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF0_OFS); + p->mp_rcp_data_modif0_value = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF0_VALUE); + p->mp_rcp_data_modif1_cmd = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF1_CMD); + p->mp_rcp_data_modif1_dyn = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF1_DYN); + p->mp_rcp_data_modif1_ofs = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF1_OFS); + p->mp_rcp_data_modif1_value = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF1_VALUE); + p->mp_rcp_data_modif2_cmd = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF2_CMD); + p->mp_rcp_data_modif2_dyn = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF2_DYN); + p->mp_rcp_data_modif2_ofs = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF2_OFS); + p->mp_rcp_data_modif2_value = + register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF2_VALUE); + + return 0; +} + +/* RCP */ +void hst_nthw_rcp_select(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_addr, val); +} + +void hst_nthw_rcp_cnt(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_cnt, val); +} + +void hst_nthw_rcp_strip_mode(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_strip_mode, val); +} + +void hst_nthw_rcp_start_dyn(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_start_dyn, val); +} + +void hst_nthw_rcp_start_ofs(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_start_ofs, val); +} + +void hst_nthw_rcp_end_dyn(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_end_dyn, val); +} + +void hst_nthw_rcp_end_ofs(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_end_ofs, val); +} + +void hst_nthw_rcp_modif0_cmd(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_modif0_cmd, val); +} + +void hst_nthw_rcp_modif0_dyn(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_modif0_dyn, val); +} + +void hst_nthw_rcp_modif0_ofs(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_modif0_ofs, val); +} + +void hst_nthw_rcp_modif0_value(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_modif0_value, val); +} + +void hst_nthw_rcp_modif1_cmd(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_modif1_cmd, val); +} + +void hst_nthw_rcp_modif1_dyn(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_modif1_dyn, val); +} + +void hst_nthw_rcp_modif1_ofs(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_modif1_ofs, val); +} + +void hst_nthw_rcp_modif1_value(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_modif1_value, val); +} + +void hst_nthw_rcp_modif2_cmd(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_modif2_cmd, val); +} + +void hst_nthw_rcp_modif2_dyn(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_modif2_dyn, val); +} + +void hst_nthw_rcp_modif2_ofs(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_modif2_ofs, val); +} + +void hst_nthw_rcp_modif2_value(const struct hst_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_modif2_value, val); +} + +void hst_nthw_rcp_flush(const struct hst_nthw *p) +{ + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.h new file mode 100644 index 0000000000..5bc7eb6e55 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_HST_H__ +#define __FLOW_NTHW_HST_H__ + +#include /* uint32_t */ +#include "nthw_fpga_model.h" + +struct hst_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_hst; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_addr; + nt_field_t *mp_rcp_cnt; + nt_register_t *mp_rcp_data; + nt_field_t *mp_rcp_data_strip_mode; + nt_field_t *mp_rcp_data_start_dyn; + nt_field_t *mp_rcp_data_start_ofs; + nt_field_t *mp_rcp_data_end_dyn; + nt_field_t *mp_rcp_data_end_ofs; + nt_field_t *mp_rcp_data_modif0_cmd; + nt_field_t *mp_rcp_data_modif0_dyn; + nt_field_t *mp_rcp_data_modif0_ofs; + nt_field_t *mp_rcp_data_modif0_value; + nt_field_t *mp_rcp_data_modif1_cmd; + nt_field_t *mp_rcp_data_modif1_dyn; + nt_field_t *mp_rcp_data_modif1_ofs; + nt_field_t *mp_rcp_data_modif1_value; + nt_field_t *mp_rcp_data_modif2_cmd; + nt_field_t *mp_rcp_data_modif2_dyn; + nt_field_t *mp_rcp_data_modif2_ofs; + nt_field_t *mp_rcp_data_modif2_value; +}; + +typedef struct hst_nthw hst_nthw_t; + +struct hst_nthw *hst_nthw_new(void); +void hst_nthw_delete(struct hst_nthw *p); +int hst_nthw_init(struct hst_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int hst_nthw_setup(struct hst_nthw *p, int n_idx, int n_idx_cnt); +void hst_nthw_set_debug_mode(struct hst_nthw *p, unsigned int n_debug_mode); + +/* RCP */ +void hst_nthw_rcp_select(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_cnt(const struct hst_nthw *p, uint32_t val); + +void hst_nthw_rcp_strip_mode(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_start_dyn(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_start_ofs(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_end_dyn(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_end_ofs(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_modif0_cmd(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_modif0_dyn(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_modif0_ofs(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_modif0_value(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_modif1_cmd(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_modif1_dyn(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_modif1_ofs(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_modif1_value(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_modif2_cmd(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_modif2_dyn(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_modif2_ofs(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_modif2_value(const struct hst_nthw *p, uint32_t val); +void hst_nthw_rcp_flush(const struct hst_nthw *p); + +#endif /* __FLOW_NTHW_HST_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.c new file mode 100644 index 0000000000..0f51a36e57 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.c @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_ifr.h" + +void ifr_nthw_set_debug_mode(struct ifr_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_ifr, n_debug_mode); +} + +struct ifr_nthw *ifr_nthw_new(void) +{ + struct ifr_nthw *p = malloc(sizeof(struct ifr_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + return p; +} + +void ifr_nthw_delete(struct ifr_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int ifr_nthw_init(struct ifr_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_IFR, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: Ifr %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_ifr = fpga_query_module(p_fpga, MOD_IFR, n_instance); + + p->mp_rcp_ctrl = module_get_register(p->m_ifr, IFR_RCP_CTRL); + p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, IFR_RCP_CTRL_ADR); + p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, IFR_RCP_CTRL_CNT); + p->mp_rcp_data = module_get_register(p->m_ifr, IFR_RCP_DATA); + p->mp_rcp_data_en = register_get_field(p->mp_rcp_data, IFR_RCP_DATA_EN); + p->mp_rcp_data_mtu = register_get_field(p->mp_rcp_data, IFR_RCP_DATA_MTU); + + return 0; +} + +void ifr_nthw_rcp_select(const struct ifr_nthw *p, uint32_t val) +{ + assert(p->mp_rcp_addr); + field_set_val32(p->mp_rcp_addr, val); +} + +void ifr_nthw_rcp_cnt(const struct ifr_nthw *p, uint32_t val) +{ + assert(p->mp_rcp_cnt); + field_set_val32(p->mp_rcp_cnt, val); +} + +void ifr_nthw_rcp_en(const struct ifr_nthw *p, uint32_t val) +{ + assert(p->mp_rcp_data_en); + field_set_val32(p->mp_rcp_data_en, val); +} + +void ifr_nthw_rcp_mtu(const struct ifr_nthw *p, uint32_t val) +{ + assert(p->mp_rcp_data_en); + field_set_val32(p->mp_rcp_data_mtu, val); +} + +void ifr_nthw_rcp_flush(const struct ifr_nthw *p) +{ + assert(p->mp_rcp_ctrl); + assert(p->mp_rcp_data); + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.h new file mode 100644 index 0000000000..626ca3d193 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_IFR_H__ +#define __FLOW_NTHW_IFR_H__ + +#include "nthw_fpga_model.h" + +struct ifr_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_ifr; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_addr; + nt_field_t *mp_rcp_cnt; + + nt_register_t *mp_rcp_data; + nt_field_t *mp_rcp_data_en; + nt_field_t *mp_rcp_data_mtu; +}; + +struct ifr_nthw *ifr_nthw_new(void); +void ifr_nthw_delete(struct ifr_nthw *p); +int ifr_nthw_init(struct ifr_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int ifr_nthw_setup(struct ifr_nthw *p, int n_idx, int n_idx_cnt); +void ifr_nthw_set_debug_mode(struct ifr_nthw *p, unsigned int n_debug_mode); + +/* IFR */ +void ifr_nthw_rcp_select(const struct ifr_nthw *p, uint32_t val); +void ifr_nthw_rcp_cnt(const struct ifr_nthw *p, uint32_t val); +void ifr_nthw_rcp_en(const struct ifr_nthw *p, uint32_t val); +void ifr_nthw_rcp_mtu(const struct ifr_nthw *p, uint32_t val); +void ifr_nthw_rcp_flush(const struct ifr_nthw *p); + +#endif /* __FLOW_NTHW_IFR_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.c new file mode 100644 index 0000000000..27b55e3b7c --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.c @@ -0,0 +1,341 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nt_util.h" +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" +#include "nthw_fpga_model.h" + +#include "flow_nthw_info.h" + +#include /* malloc */ +#include /* memset */ + +static inline unsigned int clamp_one(unsigned int val) +{ + return val > 1 ? 1 : val; +} + +struct info_nthw *info_nthw_new(void) +{ + struct info_nthw *p = malloc(sizeof(struct info_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + + return p; +} + +void info_nthw_delete(struct info_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int info_nthw_init(struct info_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + assert(n_instance >= 0 && n_instance < 256); + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + + unsigned int km_present = + clamp_one(fpga_get_product_param(p_fpga, NT_KM_PRESENT, 0)); + unsigned int kcc_present = + clamp_one(fpga_get_product_param(p_fpga, NT_CAT_KCC_PRESENT, 0)); + unsigned int ioa_present = + clamp_one(fpga_get_product_param(p_fpga, NT_IOA_PRESENT, 0)); + unsigned int roa_present = + clamp_one(fpga_get_product_param(p_fpga, NT_ROA_PRESENT, 0)); + unsigned int dbs_present = + clamp_one(fpga_get_product_param(p_fpga, NT_DBS_PRESENT, 0)); + unsigned int flm_present = + clamp_one(fpga_get_product_param(p_fpga, NT_FLM_PRESENT, 0)); + unsigned int hst_present = + clamp_one(fpga_get_product_param(p_fpga, NT_HST_PRESENT, 0)); + + /* Modules for Tx Packet Edit function */ + unsigned int hfu_present = + clamp_one(fpga_get_product_param(p_fpga, NT_HFU_PRESENT, 0)); + unsigned int tx_cpy_present = + clamp_one(fpga_get_product_param(p_fpga, NT_TX_CPY_PRESENT, 0)); + unsigned int tx_ins_present = + clamp_one(fpga_get_product_param(p_fpga, NT_TX_INS_PRESENT, 0)); + unsigned int tx_rpl_present = + clamp_one(fpga_get_product_param(p_fpga, NT_TX_RPL_PRESENT, 0)); + unsigned int csu_present = + clamp_one(fpga_get_product_param(p_fpga, NT_CSU_PRESENT, 0)); + unsigned int tpe_present = (hfu_present && tx_cpy_present && tx_ins_present && + tx_rpl_present && csu_present) ? + 1 : + 0; + + p->n_phy_ports = fpga_get_product_param(p_fpga, NT_PHY_PORTS, 0); + p->n_rx_ports = fpga_get_product_param(p_fpga, NT_RX_PORTS, 0); + p->n_ltx_avail = fpga_get_product_param(p_fpga, NT_LR_PRESENT, 0); + p->nb_cat_func = fpga_get_product_param(p_fpga, NT_CAT_FUNCS, 0); + p->nb_categories = fpga_get_product_param(p_fpga, NT_CATEGORIES, 0); + p->nb_queues = fpga_get_product_param(p_fpga, NT_QUEUES, 0); + p->nb_flow_types = fpga_get_product_param(p_fpga, NT_KM_FLOW_TYPES, 0) * + clamp_one(km_present + flm_present); + p->nb_pm_ext = fpga_get_product_param(p_fpga, NT_CAT_N_EXT, 0); + p->nb_len = fpga_get_product_param(p_fpga, NT_CAT_N_LEN, 0); + p->nb_kcc_size = + fpga_get_product_param(p_fpga, NT_CAT_KCC_SIZE, 0) * kcc_present; + p->nb_kcc_banks = + fpga_get_product_param(p_fpga, NT_CAT_KCC_BANKS, 0) * kcc_present; + p->nb_km_categories = + fpga_get_product_param(p_fpga, NT_KM_CATEGORIES, 0) * km_present; + p->nb_km_cam_banks = + fpga_get_product_param(p_fpga, NT_KM_CAM_BANKS, 0) * km_present; + p->nb_km_cam_record_words = + fpga_get_product_param(p_fpga, NT_KM_CAM_REC_WORDS, 0) * km_present; + p->nb_km_cam_records = + fpga_get_product_param(p_fpga, NT_KM_CAM_RECORDS, 0) * km_present; + p->nb_km_tcam_banks = + fpga_get_product_param(p_fpga, NT_KM_TCAM_BANKS, 0) * km_present; + p->nb_km_tcam_bank_width = + fpga_get_product_param(p_fpga, NT_KM_TCAM_BANK_WIDTH, 0) * + km_present; + p->nb_flm_categories = + fpga_get_product_param(p_fpga, NT_FLM_CATEGORIES, 0) * flm_present; + p->nb_flm_size_mb = fpga_get_product_param(p_fpga, NT_FLM_SIZE_MB, 0); + p->nb_flm_entry_size = fpga_get_product_param(p_fpga, NT_FLM_ENTRY_SIZE, 0); + p->nb_flm_variant = fpga_get_product_param(p_fpga, NT_FLM_VARIANT, 0); + p->nb_flm_prios = + fpga_get_product_param(p_fpga, NT_FLM_PRIOS, 0) * flm_present; + p->nb_flm_pst_profiles = + fpga_get_product_param(p_fpga, NT_FLM_PST_PROFILES, 0) * + flm_present; + p->nb_hst_categories = + fpga_get_product_param(p_fpga, NT_HST_CATEGORIES, 0) * hst_present; + p->nb_qsl_categories = fpga_get_product_param(p_fpga, NT_QSL_CATEGORIES, 0); + p->nb_qsl_qst_entries = fpga_get_product_param(p_fpga, NT_QSL_QST_SIZE, 0); + p->nb_pdb_categories = fpga_get_product_param(p_fpga, NT_PDB_CATEGORIES, 0); + p->nb_ioa_categories = + fpga_get_product_param(p_fpga, NT_IOA_CATEGORIES, 0) * ioa_present; + p->nb_roa_categories = + fpga_get_product_param(p_fpga, NT_ROA_CATEGORIES, 0) * roa_present; + p->nb_dbs_categories = + RTE_MIN(fpga_get_product_param(p_fpga, NT_DBS_RX_QUEUES, 0), + fpga_get_product_param(p_fpga, NT_DBS_TX_QUEUES, 0)) * + dbs_present; + p->nb_cat_km_if_cnt = fpga_get_product_param(p_fpga, NT_CAT_KM_IF_CNT, + km_present + flm_present); + p->m_cat_km_if_m0 = fpga_get_product_param(p_fpga, NT_CAT_KM_IF_M0, -1); + p->m_cat_km_if_m1 = fpga_get_product_param(p_fpga, NT_CAT_KM_IF_M1, -1); + p->nb_tpe_categories = + fpga_get_product_param(p_fpga, NT_TPE_CATEGORIES, 0) * tpe_present; + p->nb_tx_cpy_writers = + fpga_get_product_param(p_fpga, NT_TX_CPY_WRITERS, 0) * tpe_present; + p->nb_tx_cpy_mask_mem = + fpga_get_product_param(p_fpga, NT_CPY_MASK_MEM, 0) * tpe_present; + p->nb_tx_rpl_depth = + fpga_get_product_param(p_fpga, NT_TX_RPL_DEPTH, 0) * tpe_present; + p->nb_tx_rpl_ext_categories = + fpga_get_product_param(p_fpga, NT_TX_RPL_EXT_CATEGORIES, 0) * + tpe_present; + p->nb_tpe_ifr_categories = + fpga_get_product_param(p_fpga, NT_TX_MTU_PROFILE_IFR, 0); + return 0; +} + +unsigned int info_nthw_get_nb_phy_ports(const struct info_nthw *p) +{ + return p->n_phy_ports; +} + +unsigned int info_nthw_get_nb_rx_ports(const struct info_nthw *p) +{ + return p->n_rx_ports; +} + +unsigned int info_nthw_get_ltx_avail(const struct info_nthw *p) +{ + return p->n_ltx_avail; +} + +unsigned int info_nthw_get_nb_categories(const struct info_nthw *p) +{ + return p->nb_categories; +} + +unsigned int info_nthw_get_kcc_size(const struct info_nthw *p) +{ + return p->nb_kcc_size; +} + +unsigned int info_nthw_get_kcc_banks(const struct info_nthw *p) +{ + return p->nb_kcc_banks; +} + +unsigned int info_nthw_get_nb_queues(const struct info_nthw *p) +{ + return p->nb_queues; +} + +unsigned int info_nthw_get_nb_cat_funcs(const struct info_nthw *p) +{ + return p->nb_cat_func; +} + +unsigned int info_nthw_get_nb_km_flow_types(const struct info_nthw *p) +{ + return p->nb_flow_types; +} + +unsigned int info_nthw_get_nb_pm_ext(const struct info_nthw *p) +{ + return p->nb_pm_ext; +} + +unsigned int info_nthw_get_nb_len(const struct info_nthw *p) +{ + return p->nb_len; +} + +unsigned int info_nthw_get_nb_km_categories(const struct info_nthw *p) +{ + return p->nb_km_categories; +} + +unsigned int info_nthw_get_nb_km_cam_banks(const struct info_nthw *p) +{ + return p->nb_km_cam_banks; +} + +unsigned int info_nthw_get_nb_km_cam_record_words(const struct info_nthw *p) +{ + return p->nb_km_cam_record_words; +} + +unsigned int info_nthw_get_nb_km_cam_records(const struct info_nthw *p) +{ + return p->nb_km_cam_records; +} + +unsigned int info_nthw_get_nb_km_tcam_banks(const struct info_nthw *p) +{ + return p->nb_km_tcam_banks; +} + +unsigned int info_nthw_get_nb_km_tcam_bank_width(const struct info_nthw *p) +{ + return p->nb_km_tcam_bank_width; +} + +unsigned int info_nthw_get_nb_flm_categories(const struct info_nthw *p) +{ + return p->nb_flm_categories; +} + +unsigned int info_nthw_get_nb_flm_size_mb(const struct info_nthw *p) +{ + return p->nb_flm_size_mb; +} + +unsigned int info_nthw_get_nb_flm_entry_size(const struct info_nthw *p) +{ + return p->nb_flm_entry_size; +} + +unsigned int info_nthw_get_nb_flm_variant(const struct info_nthw *p) +{ + return p->nb_flm_variant; +} + +unsigned int info_nthw_get_nb_flm_prios(const struct info_nthw *p) +{ + return p->nb_flm_prios; +} + +unsigned int info_nthw_get_nb_flm_pst_profiles(const struct info_nthw *p) +{ + return p->nb_flm_pst_profiles; +} + +unsigned int info_nthw_get_nb_hst_categories(const struct info_nthw *p) +{ + return p->nb_hst_categories; +} + +unsigned int info_nthw_get_nb_qsl_categories(const struct info_nthw *p) +{ + return p->nb_qsl_categories; +} + +unsigned int info_nthw_get_nb_qsl_qst_entries(const struct info_nthw *p) +{ + return p->nb_qsl_qst_entries; +} + +unsigned int info_nthw_get_nb_pdb_categories(const struct info_nthw *p) +{ + return p->nb_pdb_categories; +} + +unsigned int info_nthw_get_nb_ioa_categories(const struct info_nthw *p) +{ + return p->nb_ioa_categories; +} + +unsigned int info_nthw_get_nb_roa_categories(const struct info_nthw *p) +{ + return p->nb_roa_categories; +} + +unsigned int info_nthw_get_nb_dbs_categories(const struct info_nthw *p) +{ + return p->nb_dbs_categories; +} + +unsigned int info_nthw_get_nb_cat_km_if_cnt(const struct info_nthw *p) +{ + return p->nb_cat_km_if_cnt; +} + +unsigned int info_nthw_get_nb_cat_km_if_m0(const struct info_nthw *p) +{ + return p->m_cat_km_if_m0; +} + +unsigned int info_nthw_get_nb_cat_km_if_m1(const struct info_nthw *p) +{ + return p->m_cat_km_if_m1; +} + +unsigned int info_nthw_get_nb_tpe_categories(const struct info_nthw *p) +{ + return p->nb_tpe_categories; +} + +unsigned int info_nthw_get_nb_tx_cpy_writers(const struct info_nthw *p) +{ + return p->nb_tx_cpy_writers; +} + +unsigned int info_nthw_get_nb_tx_cpy_mask_mem(const struct info_nthw *p) +{ + return p->nb_tx_cpy_mask_mem; +} + +unsigned int info_nthw_get_nb_tx_rpl_depth(const struct info_nthw *p) +{ + return p->nb_tx_rpl_depth; +} + +unsigned int info_nthw_get_nb_tx_rpl_ext_categories(const struct info_nthw *p) +{ + return p->nb_tx_rpl_ext_categories; +} + +unsigned int info_nthw_get_nb_tpe_ifr_categories(const struct info_nthw *p) +{ + return p->nb_tpe_ifr_categories; +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.h new file mode 100644 index 0000000000..c697ba84e9 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_INFO_H__ +#define __FLOW_NTHW_INFO_H__ + +#include /* uint32_t */ +#include "nthw_fpga_model.h" + +struct info_nthw; + +struct info_nthw *info_nthw_new(void); +void info_nthw_delete(struct info_nthw *p); +int info_nthw_init(struct info_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int info_nthw_setup(struct info_nthw *p, int n_idx, int n_idx_cnt); + +unsigned int info_nthw_get_nb_phy_ports(const struct info_nthw *p); +unsigned int info_nthw_get_nb_rx_ports(const struct info_nthw *p); +unsigned int info_nthw_get_ltx_avail(const struct info_nthw *p); + +unsigned int info_nthw_get_nb_categories(const struct info_nthw *p); +unsigned int info_nthw_get_nb_queues(const struct info_nthw *p); +unsigned int info_nthw_get_nb_cat_funcs(const struct info_nthw *p); +unsigned int info_nthw_get_nb_km_flow_types(const struct info_nthw *p); +unsigned int info_nthw_get_nb_pm_ext(const struct info_nthw *p); +unsigned int info_nthw_get_nb_len(const struct info_nthw *p); +unsigned int info_nthw_get_kcc_size(const struct info_nthw *p); +unsigned int info_nthw_get_kcc_banks(const struct info_nthw *p); +unsigned int info_nthw_get_nb_km_categories(const struct info_nthw *p); +unsigned int info_nthw_get_nb_km_cam_banks(const struct info_nthw *p); +unsigned int info_nthw_get_nb_km_cam_record_words(const struct info_nthw *p); +unsigned int info_nthw_get_nb_km_cam_records(const struct info_nthw *p); +unsigned int info_nthw_get_nb_km_tcam_banks(const struct info_nthw *p); +unsigned int info_nthw_get_nb_km_tcam_bank_width(const struct info_nthw *p); +unsigned int info_nthw_get_nb_flm_categories(const struct info_nthw *p); +unsigned int info_nthw_get_nb_flm_size_mb(const struct info_nthw *p); +unsigned int info_nthw_get_nb_flm_entry_size(const struct info_nthw *p); +unsigned int info_nthw_get_nb_flm_variant(const struct info_nthw *p); +unsigned int info_nthw_get_nb_flm_prios(const struct info_nthw *p); +unsigned int info_nthw_get_nb_flm_pst_profiles(const struct info_nthw *p); +unsigned int info_nthw_get_nb_hst_categories(const struct info_nthw *p); +unsigned int info_nthw_get_nb_qsl_categories(const struct info_nthw *p); +unsigned int info_nthw_get_nb_qsl_qst_entries(const struct info_nthw *p); +unsigned int info_nthw_get_nb_pdb_categories(const struct info_nthw *p); +unsigned int info_nthw_get_nb_ioa_categories(const struct info_nthw *p); +unsigned int info_nthw_get_nb_roa_categories(const struct info_nthw *p); +unsigned int info_nthw_get_nb_dbs_categories(const struct info_nthw *p); +unsigned int info_nthw_get_nb_cat_km_if_cnt(const struct info_nthw *p); +unsigned int info_nthw_get_nb_cat_km_if_m0(const struct info_nthw *p); +unsigned int info_nthw_get_nb_cat_km_if_m1(const struct info_nthw *p); +unsigned int info_nthw_get_nb_tpe_categories(const struct info_nthw *p); +unsigned int info_nthw_get_nb_tx_cpy_writers(const struct info_nthw *p); +unsigned int info_nthw_get_nb_tx_cpy_mask_mem(const struct info_nthw *p); +unsigned int info_nthw_get_nb_tx_rpl_depth(const struct info_nthw *p); +unsigned int info_nthw_get_nb_tx_rpl_ext_categories(const struct info_nthw *p); +unsigned int info_nthw_get_nb_tpe_ifr_categories(const struct info_nthw *p); + +struct info_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + unsigned int n_phy_ports; + unsigned int n_rx_ports; + unsigned int n_ltx_avail; + unsigned int nb_cat_func; + unsigned int nb_categories; + unsigned int nb_queues; + unsigned int nb_flow_types; + unsigned int nb_pm_ext; + unsigned int nb_len; + unsigned int nb_kcc_size; + unsigned int nb_kcc_banks; + unsigned int nb_km_categories; + unsigned int nb_km_cam_banks; + unsigned int nb_km_cam_record_words; + unsigned int nb_km_cam_records; + unsigned int nb_km_tcam_banks; + unsigned int nb_km_tcam_bank_width; + unsigned int nb_flm_categories; + unsigned int nb_flm_size_mb; + unsigned int nb_flm_entry_size; + unsigned int nb_flm_variant; + unsigned int nb_flm_prios; + unsigned int nb_flm_pst_profiles; + unsigned int nb_hst_categories; + unsigned int nb_qsl_categories; + unsigned int nb_qsl_qst_entries; + unsigned int nb_pdb_categories; + unsigned int nb_ioa_categories; + unsigned int nb_roa_categories; + unsigned int nb_dbs_categories; + unsigned int nb_cat_km_if_cnt; + unsigned int m_cat_km_if_m0; + unsigned int m_cat_km_if_m1; + unsigned int nb_tpe_categories; + unsigned int nb_tx_cpy_writers; + unsigned int nb_tx_cpy_mask_mem; + unsigned int nb_tx_rpl_depth; + unsigned int nb_tx_rpl_ext_categories; + unsigned int nb_tpe_ifr_categories; +}; + +#endif /* __FLOW_NTHW_INFO_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.c new file mode 100644 index 0000000000..a83d443f6f --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.c @@ -0,0 +1,234 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_ioa.h" + +#include /* malloc */ +#include /* memset */ + +void ioa_nthw_set_debug_mode(struct ioa_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_ioa, n_debug_mode); +} + +struct ioa_nthw *ioa_nthw_new(void) +{ + struct ioa_nthw *p = malloc(sizeof(struct ioa_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + + return p; +} + +void ioa_nthw_delete(struct ioa_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int ioa_nthw_init(struct ioa_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_IOA, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: Ioa %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_ioa = p_mod; + + /* RCP */ + p->mp_rcp_ctrl = module_get_register(p->m_ioa, IOA_RECIPE_CTRL); + p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, IOA_RECIPE_CTRL_ADR); + p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, IOA_RECIPE_CTRL_CNT); + p->mp_rcp_data = module_get_register(p->m_ioa, IOA_RECIPE_DATA); + p->mp_rcp_data_tunnel_pop = + register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_TUNNEL_POP); + p->mp_rcp_data_vlan_pop = + register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_POP); + p->mp_rcp_data_vlan_push = + register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_PUSH); + p->mp_rcp_data_vlan_vid = + register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_VID); + p->mp_rcp_data_vlan_dei = + register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_DEI); + p->mp_rcp_data_vlan_pcp = + register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_PCP); + p->mp_rcp_data_vlan_tpid_sel = + register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_TPID_SEL); + p->mp_rcp_data_queue_override_en = + register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_QUEUE_OVERRIDE_EN); + p->mp_rcp_data_queue_id = + register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_QUEUE_ID); + + /* Special Vlan Tpid */ + p->mp_special = module_get_register(p->m_ioa, IOA_VLAN_TPID_SPECIAL); + p->mp_special_vlan_tpid_cust_tpid0 = + register_get_field(p->mp_special, IOA_VLAN_TPID_SPECIAL_CUSTTPID0); + p->mp_special_vlan_tpid_cust_tpid1 = + register_get_field(p->mp_special, IOA_VLAN_TPID_SPECIAL_CUSTTPID1); + { + /* + * This extension in IOA is a messy way FPGA have chosen to + * put control bits for EPP module in IOA. It is accepted as + * we are going towards exchange IOA and ROA modules later + * to get higher scalability in future. + */ + p->mp_roa_epp_ctrl = + module_query_register(p->m_ioa, IOA_ROA_EPP_CTRL); + if (p->mp_roa_epp_ctrl) { + p->mp_roa_epp_addr = + register_get_field(p->mp_roa_epp_ctrl, + IOA_ROA_EPP_CTRL_ADR); + p->mp_roa_epp_cnt = + register_get_field(p->mp_roa_epp_ctrl, + IOA_ROA_EPP_CTRL_CNT); + } else { + p->mp_roa_epp_addr = NULL; + p->mp_roa_epp_cnt = NULL; + } + + p->mp_roa_epp_data = + module_query_register(p->m_ioa, IOA_ROA_EPP_DATA); + if (p->mp_roa_epp_data) { + p->mp_roa_epp_data_push_tunnel = + register_get_field(p->mp_roa_epp_data, + IOA_ROA_EPP_DATA_PUSH_TUNNEL); + p->mp_roa_epp_data_tx_port = + register_get_field(p->mp_roa_epp_data, + IOA_ROA_EPP_DATA_TX_PORT); + } else { + p->mp_roa_epp_data_push_tunnel = NULL; + p->mp_roa_epp_data_tx_port = NULL; + } + } + return 0; +} + +/* RCP */ +void ioa_nthw_rcp_select(const struct ioa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_addr, val); +} + +void ioa_nthw_rcp_cnt(const struct ioa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_cnt, val); +} + +void ioa_nthw_rcp_tunnel_pop(const struct ioa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_tunnel_pop, val); +} + +void ioa_nthw_rcp_vlan_pop(const struct ioa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_vlan_pop, val); +} + +void ioa_nthw_rcp_vlan_push(const struct ioa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_vlan_push, val); +} + +void ioa_nthw_rcp_vlan_vid(const struct ioa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_vlan_vid, val); +} + +void ioa_nthw_rcp_vlan_dei(const struct ioa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_vlan_dei, val); +} + +void ioa_nthw_rcp_vlan_pcp(const struct ioa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_vlan_pcp, val); +} + +void ioa_nthw_rcp_vlan_tpid_sel(const struct ioa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_vlan_tpid_sel, val); +} + +void ioa_nthw_rcp_queue_override_en(const struct ioa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_queue_override_en, val); +} + +void ioa_nthw_rcp_queue_id(const struct ioa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_queue_id, val); +} + +void ioa_nthw_rcp_flush(const struct ioa_nthw *p) +{ + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +} + +/* Vlan Tpid Special */ +void ioa_nthw_special_vlan_tpid_cust_tpid0(const struct ioa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_special_vlan_tpid_cust_tpid0, val); +} + +void ioa_nthw_special_vlan_tpid_cust_tpid1(const struct ioa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_special_vlan_tpid_cust_tpid1, val); +} + +void ioa_nthw_special_vlan_tpid_flush(const struct ioa_nthw *p) +{ + register_flush(p->mp_special, 1); +} + +void ioa_nthw_roa_epp_select(const struct ioa_nthw *p, uint32_t val) +{ + if (p->mp_roa_epp_addr) + field_set_val32(p->mp_roa_epp_addr, val); +} + +void ioa_nthw_roa_epp_cnt(const struct ioa_nthw *p, uint32_t val) +{ + if (p->mp_roa_epp_cnt) + field_set_val32(p->mp_roa_epp_cnt, val); +} + +void ioa_nthw_roa_epp_push_tunnel(const struct ioa_nthw *p, uint32_t val) +{ + if (p->mp_roa_epp_data_push_tunnel) + field_set_val32(p->mp_roa_epp_data_push_tunnel, val); +} + +void ioa_nthw_roa_epp_tx_port(const struct ioa_nthw *p, uint32_t val) +{ + if (p->mp_roa_epp_data_tx_port) + field_set_val32(p->mp_roa_epp_data_tx_port, val); +} + +void ioa_nthw_roa_epp_flush(const struct ioa_nthw *p) +{ + if (p->mp_roa_epp_ctrl) + register_flush(p->mp_roa_epp_ctrl, 1); + if (p->mp_roa_epp_data) + register_flush(p->mp_roa_epp_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.h new file mode 100644 index 0000000000..8ab30d2d28 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_IOA_H__ +#define __FLOW_NTHW_IOA_H__ + +#include "nthw_fpga_model.h" + +#include /* uint32_t */ + +struct ioa_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_ioa; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_addr; + nt_field_t *mp_rcp_cnt; + nt_register_t *mp_rcp_data; + + nt_field_t *mp_rcp_data_tunnel_pop; + nt_field_t *mp_rcp_data_vlan_pop; + nt_field_t *mp_rcp_data_vlan_push; + nt_field_t *mp_rcp_data_vlan_vid; + nt_field_t *mp_rcp_data_vlan_dei; + nt_field_t *mp_rcp_data_vlan_pcp; + nt_field_t *mp_rcp_data_vlan_tpid_sel; + nt_field_t *mp_rcp_data_queue_override_en; + nt_field_t *mp_rcp_data_queue_id; + + nt_register_t *mp_special; + nt_field_t *mp_special_vlan_tpid_cust_tpid0; + nt_field_t *mp_special_vlan_tpid_cust_tpid1; + + nt_register_t *mp_roa_epp_ctrl; + nt_field_t *mp_roa_epp_addr; + nt_field_t *mp_roa_epp_cnt; + nt_register_t *mp_roa_epp_data; + nt_field_t *mp_roa_epp_data_push_tunnel; + nt_field_t *mp_roa_epp_data_tx_port; +}; + +typedef struct ioa_nthw ioa_nthw_t; + +struct ioa_nthw *ioa_nthw_new(void); +void ioa_nthw_delete(struct ioa_nthw *p); +int ioa_nthw_init(struct ioa_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int ioa_nthw_setup(struct ioa_nthw *p, int n_idx, int n_idx_cnt); +void ioa_nthw_set_debug_mode(struct ioa_nthw *p, unsigned int n_debug_mode); + +/* RCP */ +void ioa_nthw_rcp_select(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_rcp_cnt(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_rcp_tunnel_pop(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_rcp_vlan_pop(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_rcp_vlan_push(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_rcp_vlan_vid(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_rcp_vlan_dei(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_rcp_vlan_pcp(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_rcp_vlan_tpid_sel(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_rcp_queue_override_en(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_rcp_queue_id(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_rcp_flush(const struct ioa_nthw *p); + +/* Vlan Tpid Special */ +void ioa_nthw_special_vlan_tpid_cust_tpid0(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_special_vlan_tpid_cust_tpid1(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_special_vlan_tpid_flush(const struct ioa_nthw *p); + +/* EPP module */ +void ioa_nthw_roa_epp_select(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_roa_epp_cnt(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_roa_epp_push_tunnel(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_roa_epp_tx_port(const struct ioa_nthw *p, uint32_t val); +void ioa_nthw_roa_epp_flush(const struct ioa_nthw *p); + +#endif /* __FLOW_NTHW_IOA_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.c new file mode 100644 index 0000000000..af54e14940 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.c @@ -0,0 +1,685 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_km.h" + +#include +#include /* malloc */ +#include /* memset */ + +#define CHECK_AND_SET_VALUE(_a, val) \ + do { \ + __typeof__(_a) (a) = (_a); \ + if (a) { \ + field_set_val32(a, val); \ + } \ + } while (0) + +void km_nthw_set_debug_mode(struct km_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_km, n_debug_mode); +} + +struct km_nthw *km_nthw_new(void) +{ + struct km_nthw *p = malloc(sizeof(struct km_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + + return p; +} + +void km_nthw_delete(struct km_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int km_nthw_init(struct km_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_KM, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: Km %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_km = p_mod; + + /* RCP */ + p->mp_rcp_ctrl = module_get_register(p->m_km, KM_RCP_CTRL); + p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, KM_RCP_CTRL_ADR); + p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, KM_RCP_CTRL_CNT); + p->mp_rcp_data = module_get_register(p->m_km, KM_RCP_DATA); + p->mp_rcp_data_qw0_dyn = + register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW0_DYN); + p->mp_rcp_data_qw0_ofs = + register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW0_OFS); + p->mp_rcp_data_qw0_sel_a = + register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW0_SEL_A); + p->mp_rcp_data_qw0_sel_b = + register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW0_SEL_B); + p->mp_rcp_data_qw4_dyn = + register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW4_DYN); + p->mp_rcp_data_qw4_ofs = + register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW4_OFS); + p->mp_rcp_data_qw4_sel_a = + register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW4_SEL_A); + p->mp_rcp_data_qw4_sel_b = + register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW4_SEL_B); + + p->mp_rcp_data_sw8_dyn = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_DYN); + p->mp_rcp_data_dw8_dyn = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW8_DYN); + + p->mp_rcp_data_swx_ovs_sb = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SWX_OVS_SB); + p->mp_rcp_data_swx_cch = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SWX_CCH); + p->mp_rcp_data_swx_sel_a = + register_get_field(p->mp_rcp_data, KM_RCP_DATA_SWX_SEL_A); + p->mp_rcp_data_swx_sel_b = + register_get_field(p->mp_rcp_data, KM_RCP_DATA_SWX_SEL_B); + p->mp_rcp_data_mask_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_MASK_A); + p->mp_rcp_data_mask_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_MASK_B); + p->mp_rcp_data_dual = register_get_field(p->mp_rcp_data, KM_RCP_DATA_DUAL); + p->mp_rcp_data_paired = + register_get_field(p->mp_rcp_data, KM_RCP_DATA_PAIRED); + p->mp_rcp_data_el_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_EL_A); + p->mp_rcp_data_el_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_EL_B); + p->mp_rcp_data_info_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_INFO_A); + p->mp_rcp_data_info_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_INFO_B); + p->mp_rcp_data_ftm_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_FTM_A); + p->mp_rcp_data_ftm_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_FTM_B); + p->mp_rcp_data_bank_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_BANK_A); + p->mp_rcp_data_bank_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_BANK_B); + p->mp_rcp_data_kl_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_KL_A); + p->mp_rcp_data_kl_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_KL_B); + p->mp_rcp_data_flow_set = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_FLOW_SET); + p->mp_rcp_data_keyway_a = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_KEYWAY_A); + p->mp_rcp_data_keyway_b = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_KEYWAY_B); + p->mp_rcp_data_synergy_mode = + register_get_field(p->mp_rcp_data, KM_RCP_DATA_SYNERGY_MODE); + + /* CAM */ + p->mp_cam_ctrl = module_get_register(p->m_km, KM_CAM_CTRL); + p->mp_cam_addr = register_get_field(p->mp_cam_ctrl, KM_CAM_CTRL_ADR); + p->mp_cam_cnt = register_get_field(p->mp_cam_ctrl, KM_CAM_CTRL_CNT); + p->mp_cam_data = module_get_register(p->m_km, KM_CAM_DATA); + p->mp_cam_data_w0 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W0); + p->mp_cam_data_w1 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W1); + p->mp_cam_data_w2 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W2); + p->mp_cam_data_w3 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W3); + p->mp_cam_data_w4 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W4); + p->mp_cam_data_w5 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W5); + p->mp_cam_data_ft0 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT0); + p->mp_cam_data_ft1 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT1); + p->mp_cam_data_ft2 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT2); + p->mp_cam_data_ft3 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT3); + p->mp_cam_data_ft4 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT4); + p->mp_cam_data_ft5 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT5); + /* TCAM */ + p->mp_tcam_ctrl = module_get_register(p->m_km, KM_TCAM_CTRL); + p->mp_tcam_addr = register_get_field(p->mp_tcam_ctrl, KM_TCAM_CTRL_ADR); + p->mp_tcam_cnt = register_get_field(p->mp_tcam_ctrl, KM_TCAM_CTRL_CNT); + p->mp_tcam_data = module_get_register(p->m_km, KM_TCAM_DATA); + p->mp_tcam_data_t = register_get_field(p->mp_tcam_data, KM_TCAM_DATA_T); + /* TCI */ + p->mp_tci_ctrl = module_get_register(p->m_km, KM_TCI_CTRL); + p->mp_tci_addr = register_get_field(p->mp_tci_ctrl, KM_TCI_CTRL_ADR); + p->mp_tci_cnt = register_get_field(p->mp_tci_ctrl, KM_TCI_CTRL_CNT); + p->mp_tci_data = module_get_register(p->m_km, KM_TCI_DATA); + p->mp_tci_data_color = register_get_field(p->mp_tci_data, KM_TCI_DATA_COLOR); + p->mp_tci_data_ft = register_get_field(p->mp_tci_data, KM_TCI_DATA_FT); + /* TCQ */ + p->mp_tcq_ctrl = module_get_register(p->m_km, KM_TCQ_CTRL); + p->mp_tcq_addr = register_get_field(p->mp_tcq_ctrl, KM_TCQ_CTRL_ADR); + p->mp_tcq_cnt = register_get_field(p->mp_tcq_ctrl, KM_TCQ_CTRL_CNT); + p->mp_tcq_data = module_get_register(p->m_km, KM_TCQ_DATA); + p->mp_tcq_data_bank_mask = + register_query_field(p->mp_tcq_data, KM_TCQ_DATA_BANK_MASK); + p->mp_tcq_data_qual = register_get_field(p->mp_tcq_data, KM_TCQ_DATA_QUAL); + + p->mp_rcp_data_dw0_b_dyn = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW0_B_DYN); + p->mp_rcp_data_dw0_b_ofs = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW0_B_OFS); + p->mp_rcp_data_dw2_b_dyn = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW2_B_DYN); + p->mp_rcp_data_dw2_b_ofs = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW2_B_OFS); + p->mp_rcp_data_sw4_b_dyn = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW4_B_DYN); + p->mp_rcp_data_sw4_b_ofs = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW4_B_OFS); + p->mp_rcp_data_sw5_b_dyn = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW5_B_DYN); + p->mp_rcp_data_sw5_b_ofs = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW5_B_OFS); + if (!p->mp_rcp_data_dw0_b_dyn) { + /* old field defines */ + p->mp_rcp_data_dw0_b_dyn = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_QW0_B_DYN); + p->mp_rcp_data_dw0_b_ofs = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_QW0_B_OFS); + p->mp_rcp_data_dw2_b_dyn = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_QW4_B_DYN); + p->mp_rcp_data_dw2_b_ofs = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_QW4_B_OFS); + p->mp_rcp_data_sw4_b_dyn = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_B_DYN); + p->mp_rcp_data_sw4_b_ofs = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_B_OFS); + p->mp_rcp_data_sw5_b_dyn = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_B_DYN); + p->mp_rcp_data_sw5_b_ofs = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_B_OFS); + } + + /* v0.6+ */ + if (p->mp_rcp_data_dw8_dyn) { + p->mp_rcp_data_dw8_ofs = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW8_OFS); + p->mp_rcp_data_dw8_sel_a = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW8_SEL_A); + p->mp_rcp_data_dw8_sel_b = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW8_SEL_B); + p->mp_rcp_data_dw10_dyn = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW10_DYN); + p->mp_rcp_data_dw10_ofs = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW10_OFS); + p->mp_rcp_data_dw10_sel_a = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW10_SEL_A); + p->mp_rcp_data_dw10_sel_b = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW10_SEL_B); + } else if (p->mp_rcp_data_sw8_dyn) { + p->mp_rcp_data_sw8_ofs = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_OFS); + p->mp_rcp_data_sw8_sel_a = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_SEL_A); + p->mp_rcp_data_sw8_sel_b = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_SEL_B); + p->mp_rcp_data_sw9_dyn = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_DYN); + p->mp_rcp_data_sw9_ofs = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_OFS); + p->mp_rcp_data_sw9_sel_a = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_SEL_A); + p->mp_rcp_data_sw9_sel_b = + register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_SEL_B); + } + + return 0; +} + +/* RCP */ +void km_nthw_rcp_select(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_addr, val); +}; + +void km_nthw_rcp_cnt(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_cnt, val); +}; + +void km_nthw_rcp_qw0_dyn(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_qw0_dyn, val); +}; + +void km_nthw_rcp_qw0_ofs(const struct km_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_qw0_ofs, val); +}; + +void km_nthw_rcp_qw0_sel_a(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_qw0_sel_a, val); +}; + +void km_nthw_rcp_qw0_sel_b(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_qw0_sel_b, val); +}; + +void km_nthw_rcp_qw4_dyn(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_qw4_dyn, val); +}; + +void km_nthw_rcp_qw4_ofs(const struct km_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_qw4_ofs, val); +}; + +void km_nthw_rcp_qw4_sel_a(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_qw4_sel_a, val); +}; + +void km_nthw_rcp_qw4_sel_b(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_qw4_sel_b, val); +}; + +void km_nthw_rcp_dw8_dyn(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_dw8_dyn, val); +}; + +void km_nthw_rcp_sw8_dyn(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_sw8_dyn, val); +}; + +void km_nthw_rcp_sw8_ofs(const struct km_nthw *p, int32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_sw8_ofs, val); +}; + +void km_nthw_rcp_sw8_sel_a(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_sw8_sel_a, val); +}; + +void km_nthw_rcp_sw8_sel_b(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_sw8_sel_b, val); +}; + +void km_nthw_rcp_sw9_dyn(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_sw9_dyn, val); +}; + +void km_nthw_rcp_sw9_ofs(const struct km_nthw *p, int32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_sw9_ofs, val); +}; + +void km_nthw_rcp_sw9_sel_a(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_sw9_sel_a, val); +}; + +void km_nthw_rcp_sw9_sel_b(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_sw9_sel_b, val); +}; + +void km_nthw_rcp_swx_ovs_sb(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_swx_ovs_sb, val); +}; + +void km_nthw_rcp_swx_cch(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_swx_cch, val); +}; + +void km_nthw_rcp_dw8_ofs(const struct km_nthw *p, int32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_dw8_ofs, val); +}; + +void km_nthw_rcp_dw8_sel_a(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_dw8_sel_a, val); +}; + +void km_nthw_rcp_dw8_sel_b(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_dw8_sel_b, val); +}; + +void km_nthw_rcp_dw10_dyn(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_dw10_dyn, val); +}; + +void km_nthw_rcp_dw10_ofs(const struct km_nthw *p, int32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_dw10_ofs, val); +}; + +void km_nthw_rcp_dw10_sel_a(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_dw10_sel_a, val); +}; + +void km_nthw_rcp_dw10_sel_b(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_dw10_sel_b, val); +}; + +void km_nthw_rcp_swx_sel_a(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_swx_sel_a, val); +}; + +void km_nthw_rcp_swx_sel_b(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_swx_sel_b, val); +}; + +void km_nthw_rcp_mask_a(const struct km_nthw *p, const uint32_t *val) +{ + field_set_val(p->mp_rcp_data_mask_a, val, p->mp_rcp_data_mask_a->mn_words); +}; + +void km_nthw_rcp_mask_b(const struct km_nthw *p, const uint32_t *val) +{ + field_set_val(p->mp_rcp_data_mask_b, val, p->mp_rcp_data_mask_b->mn_words); +}; + +void km_nthw_rcp_mask_d_a(const struct km_nthw *p, const uint32_t *val) +{ + field_set_val(p->mp_rcp_data_mask_a, val, p->mp_rcp_data_mask_a->mn_words); +}; /* for DW8/DW10 from v6+ */ + +void km_nthw_rcp_dual(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_dual, val); +}; + +void km_nthw_rcp_paired(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_paired, val); +}; + +void km_nthw_rcp_el_a(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_el_a, val); +}; + +void km_nthw_rcp_el_b(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_el_b, val); +}; + +void km_nthw_rcp_info_a(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_info_a, val); +}; + +void km_nthw_rcp_info_b(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_info_b, val); +}; + +void km_nthw_rcp_ftm_a(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ftm_a, val); +}; + +void km_nthw_rcp_ftm_b(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ftm_b, val); +}; + +void km_nthw_rcp_bank_a(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_bank_a, val); +}; + +void km_nthw_rcp_bank_b(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_bank_b, val); +}; + +void km_nthw_rcp_kl_a(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_kl_a, val); +}; + +void km_nthw_rcp_kl_b(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_kl_b, val); +}; + +void km_nthw_rcp_flow_set(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_flow_set, val); +}; + +void km_nthw_rcp_keyway_a(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_keyway_a, val); +}; + +void km_nthw_rcp_keyway_b(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_rcp_data_keyway_b, val); +}; + +void km_nthw_rcp_synergy_mode(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_synergy_mode, val); +}; + +void km_nthw_rcp_dw0_b_dyn(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_dw0_b_dyn, val); +}; + +void km_nthw_rcp_dw0_b_ofs(const struct km_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_dw0_b_ofs, val); +}; + +void km_nthw_rcp_dw2_b_dyn(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_dw2_b_dyn, val); +}; + +void km_nthw_rcp_dw2_b_ofs(const struct km_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_dw2_b_ofs, val); +}; + +void km_nthw_rcp_sw4_b_dyn(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_sw4_b_dyn, val); +}; + +void km_nthw_rcp_sw4_b_ofs(const struct km_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_sw4_b_ofs, val); +}; + +void km_nthw_rcp_sw5_b_dyn(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_sw5_b_dyn, val); +}; + +void km_nthw_rcp_sw5_b_ofs(const struct km_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_sw5_b_ofs, val); +}; + +void km_nthw_rcp_flush(const struct km_nthw *p) +{ + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +}; + +/* CAM */ +void km_nthw_cam_select(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cam_addr, val); +}; + +void km_nthw_cam_cnt(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cam_cnt, val); +}; + +void km_nthw_cam_w0(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cam_data_w0, val); +}; + +void km_nthw_cam_w1(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cam_data_w1, val); +}; + +void km_nthw_cam_w2(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cam_data_w2, val); +}; + +void km_nthw_cam_w3(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cam_data_w3, val); +}; + +void km_nthw_cam_w4(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cam_data_w4, val); +}; + +void km_nthw_cam_w5(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cam_data_w5, val); +}; + +void km_nthw_cam_ft0(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cam_data_ft0, val); +}; + +void km_nthw_cam_ft1(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cam_data_ft1, val); +}; + +void km_nthw_cam_ft2(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cam_data_ft2, val); +}; + +void km_nthw_cam_ft3(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cam_data_ft3, val); +}; + +void km_nthw_cam_ft4(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cam_data_ft4, val); +}; + +void km_nthw_cam_ft5(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_cam_data_ft5, val); +}; + +void km_nthw_cam_flush(const struct km_nthw *p) +{ + register_flush(p->mp_cam_ctrl, 1); + register_flush(p->mp_cam_data, 1); +}; + +/* TCAM */ +void km_nthw_tcam_select(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tcam_addr, val); +}; + +void km_nthw_tcam_cnt(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tcam_cnt, val); +}; + +void km_nthw_tcam_t(const struct km_nthw *p, uint32_t *val) +{ + field_set_val(p->mp_tcam_data_t, val, 3); +}; + +void km_nthw_tcam_flush(const struct km_nthw *p) +{ + register_flush(p->mp_tcam_ctrl, 1); + register_flush(p->mp_tcam_data, 1); +}; + +/* TCI */ +void km_nthw_tci_select(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tci_addr, val); +}; + +void km_nthw_tci_cnt(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tci_cnt, val); +}; + +void km_nthw_tci_color(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tci_data_color, val); +}; + +void km_nthw_tci_ft(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tci_data_ft, val); +}; + +void km_nthw_tci_flush(const struct km_nthw *p) +{ + register_flush(p->mp_tci_ctrl, 1); + register_flush(p->mp_tci_data, 1); +}; + +/* TCQ */ +void km_nthw_tcq_select(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tcq_addr, val); +}; + +void km_nthw_tcq_cnt(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tcq_cnt, val); +}; + +void km_nthw_tcq_bank_mask(const struct km_nthw *p, uint32_t val) +{ + CHECK_AND_SET_VALUE(p->mp_tcq_data_bank_mask, val); +}; + +void km_nthw_tcq_qual(const struct km_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tcq_data_qual, val); +}; + +void km_nthw_tcq_qual72(const struct km_nthw *p, uint32_t *val) +{ + field_set_val(p->mp_tcq_data_qual, val, 3); +}; /* to use in v4 */ + +void km_nthw_tcq_flush(const struct km_nthw *p) +{ + register_flush(p->mp_tcq_ctrl, 1); + register_flush(p->mp_tcq_data, 1); +}; diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.h new file mode 100644 index 0000000000..61f9ed2ae4 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.h @@ -0,0 +1,224 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_KM_H__ +#define __FLOW_NTHW_KM_H__ + +#include /* uint32_t */ +#include "nthw_fpga_model.h" + +struct km_nthw; + +typedef struct km_nthw km_nthw_t; + +struct km_nthw *km_nthw_new(void); +void km_nthw_delete(struct km_nthw *p); +int km_nthw_init(struct km_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int km_nthw_setup(struct km_nthw *p, int n_idx, int n_idx_cnt); +void km_nthw_set_debug_mode(struct km_nthw *p, unsigned int n_debug_mode); + +/* RCP initial v3 */ +void km_nthw_rcp_select(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_cnt(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_qw0_dyn(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_qw0_ofs(const struct km_nthw *p, int32_t val); +void km_nthw_rcp_qw0_sel_a(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_qw0_sel_b(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_qw4_dyn(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_qw4_ofs(const struct km_nthw *p, int32_t val); +void km_nthw_rcp_qw4_sel_a(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_qw4_sel_b(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_sw8_dyn(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_sw8_ofs(const struct km_nthw *p, int32_t val); +void km_nthw_rcp_sw8_sel_a(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_sw8_sel_b(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_sw9_dyn(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_sw9_ofs(const struct km_nthw *p, int32_t val); +void km_nthw_rcp_sw9_sel_a(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_sw9_sel_b(const struct km_nthw *p, uint32_t val); +/* subst in v6 */ +void km_nthw_rcp_dw8_dyn(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_dw8_ofs(const struct km_nthw *p, int32_t val); +void km_nthw_rcp_dw8_sel_a(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_dw8_sel_b(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_dw10_dyn(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_dw10_ofs(const struct km_nthw *p, int32_t val); +void km_nthw_rcp_dw10_sel_a(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_dw10_sel_b(const struct km_nthw *p, uint32_t val); + +void km_nthw_rcp_swx_ovs_sb(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_swx_cch(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_swx_sel_a(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_swx_sel_b(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_mask_a(const struct km_nthw *p, const uint32_t *val); +void km_nthw_rcp_mask_d_a(const struct km_nthw *p, const uint32_t *val); +void km_nthw_rcp_mask_b(const struct km_nthw *p, const uint32_t *val); +void km_nthw_rcp_dual(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_paired(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_el_a(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_el_b(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_info_a(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_info_b(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_ftm_a(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_ftm_b(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_bank_a(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_bank_b(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_kl_a(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_kl_b(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_flow_set(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_keyway_a(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_keyway_b(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_synergy_mode(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_dw0_b_dyn(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_dw0_b_ofs(const struct km_nthw *p, int32_t val); +void km_nthw_rcp_dw2_b_dyn(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_dw2_b_ofs(const struct km_nthw *p, int32_t val); +void km_nthw_rcp_sw4_b_dyn(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_sw4_b_ofs(const struct km_nthw *p, int32_t val); +void km_nthw_rcp_sw5_b_dyn(const struct km_nthw *p, uint32_t val); +void km_nthw_rcp_sw5_b_ofs(const struct km_nthw *p, int32_t val); +void km_nthw_rcp_flush(const struct km_nthw *p); +/* CAM */ +void km_nthw_cam_select(const struct km_nthw *p, uint32_t val); +void km_nthw_cam_cnt(const struct km_nthw *p, uint32_t val); +void km_nthw_cam_w0(const struct km_nthw *p, uint32_t val); +void km_nthw_cam_w1(const struct km_nthw *p, uint32_t val); +void km_nthw_cam_w2(const struct km_nthw *p, uint32_t val); +void km_nthw_cam_w3(const struct km_nthw *p, uint32_t val); +void km_nthw_cam_w4(const struct km_nthw *p, uint32_t val); +void km_nthw_cam_w5(const struct km_nthw *p, uint32_t val); +void km_nthw_cam_ft0(const struct km_nthw *p, uint32_t val); +void km_nthw_cam_ft1(const struct km_nthw *p, uint32_t val); +void km_nthw_cam_ft2(const struct km_nthw *p, uint32_t val); +void km_nthw_cam_ft3(const struct km_nthw *p, uint32_t val); +void km_nthw_cam_ft4(const struct km_nthw *p, uint32_t val); +void km_nthw_cam_ft5(const struct km_nthw *p, uint32_t val); +void km_nthw_cam_flush(const struct km_nthw *p); +/* TCAM */ +void km_nthw_tcam_select(const struct km_nthw *p, uint32_t val); +void km_nthw_tcam_cnt(const struct km_nthw *p, uint32_t val); +void km_nthw_tcam_t(const struct km_nthw *p, uint32_t *val); +void km_nthw_tcam_flush(const struct km_nthw *p); +/* TCI */ +void km_nthw_tci_select(const struct km_nthw *p, uint32_t val); +void km_nthw_tci_cnt(const struct km_nthw *p, uint32_t val); +void km_nthw_tci_color(const struct km_nthw *p, uint32_t val); +void km_nthw_tci_ft(const struct km_nthw *p, uint32_t val); +void km_nthw_tci_flush(const struct km_nthw *p); +/* TCQ */ +void km_nthw_tcq_select(const struct km_nthw *p, uint32_t val); +void km_nthw_tcq_cnt(const struct km_nthw *p, uint32_t val); +void km_nthw_tcq_bank_mask(const struct km_nthw *p, uint32_t val); +void km_nthw_tcq_qual(const struct km_nthw *p, uint32_t val); +void km_nthw_tcq_qual72(const struct km_nthw *p, uint32_t *val); + +void km_nthw_tcq_flush(const struct km_nthw *p); + +struct km_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_km; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_addr; + nt_field_t *mp_rcp_cnt; + nt_register_t *mp_rcp_data; + nt_field_t *mp_rcp_data_qw0_dyn; + nt_field_t *mp_rcp_data_qw0_ofs; + nt_field_t *mp_rcp_data_qw0_sel_a; + nt_field_t *mp_rcp_data_qw0_sel_b; + nt_field_t *mp_rcp_data_qw4_dyn; + nt_field_t *mp_rcp_data_qw4_ofs; + nt_field_t *mp_rcp_data_qw4_sel_a; + nt_field_t *mp_rcp_data_qw4_sel_b; + nt_field_t *mp_rcp_data_sw8_dyn; + nt_field_t *mp_rcp_data_sw8_ofs; + nt_field_t *mp_rcp_data_sw8_sel_a; + nt_field_t *mp_rcp_data_sw8_sel_b; + nt_field_t *mp_rcp_data_sw9_dyn; + nt_field_t *mp_rcp_data_sw9_ofs; + nt_field_t *mp_rcp_data_sw9_sel_a; + nt_field_t *mp_rcp_data_sw9_sel_b; + + nt_field_t *mp_rcp_data_dw8_dyn; /* substituted Sw from v6+ */ + nt_field_t *mp_rcp_data_dw8_ofs; /* substituted Sw from v6+ */ + nt_field_t *mp_rcp_data_dw8_sel_a; /* substituted Sw from v6+ */ + nt_field_t *mp_rcp_data_dw8_sel_b; /* substituted Sw from v6+ */ + nt_field_t *mp_rcp_data_dw10_dyn; /* substituted Sw from v6+ */ + nt_field_t *mp_rcp_data_dw10_ofs; /* substituted Sw from v6+ */ + nt_field_t *mp_rcp_data_dw10_sel_a; /* substituted Sw from v6+ */ + nt_field_t *mp_rcp_data_dw10_sel_b; /* substituted Sw from v6+ */ + + nt_field_t *mp_rcp_data_swx_ovs_sb; + nt_field_t *mp_rcp_data_swx_cch; + nt_field_t *mp_rcp_data_swx_sel_a; + nt_field_t *mp_rcp_data_swx_sel_b; + nt_field_t *mp_rcp_data_mask_a; + nt_field_t *mp_rcp_data_mask_b; + nt_field_t *mp_rcp_data_dual; + nt_field_t *mp_rcp_data_paired; + nt_field_t *mp_rcp_data_el_a; + nt_field_t *mp_rcp_data_el_b; + nt_field_t *mp_rcp_data_info_a; + nt_field_t *mp_rcp_data_info_b; + nt_field_t *mp_rcp_data_ftm_a; + nt_field_t *mp_rcp_data_ftm_b; + nt_field_t *mp_rcp_data_bank_a; + nt_field_t *mp_rcp_data_bank_b; + nt_field_t *mp_rcp_data_kl_a; + nt_field_t *mp_rcp_data_kl_b; + nt_field_t *mp_rcp_data_flow_set; + nt_field_t *mp_rcp_data_keyway_a; + nt_field_t *mp_rcp_data_keyway_b; + nt_field_t *mp_rcp_data_synergy_mode; + nt_field_t *mp_rcp_data_dw0_b_dyn; + nt_field_t *mp_rcp_data_dw0_b_ofs; + nt_field_t *mp_rcp_data_dw2_b_dyn; + nt_field_t *mp_rcp_data_dw2_b_ofs; + nt_field_t *mp_rcp_data_sw4_b_dyn; + nt_field_t *mp_rcp_data_sw4_b_ofs; + nt_field_t *mp_rcp_data_sw5_b_dyn; + nt_field_t *mp_rcp_data_sw5_b_ofs; + + nt_register_t *mp_cam_ctrl; + nt_field_t *mp_cam_addr; + nt_field_t *mp_cam_cnt; + nt_register_t *mp_cam_data; + nt_field_t *mp_cam_data_w0; + nt_field_t *mp_cam_data_w1; + nt_field_t *mp_cam_data_w2; + nt_field_t *mp_cam_data_w3; + nt_field_t *mp_cam_data_w4; + nt_field_t *mp_cam_data_w5; + nt_field_t *mp_cam_data_ft0; + nt_field_t *mp_cam_data_ft1; + nt_field_t *mp_cam_data_ft2; + nt_field_t *mp_cam_data_ft3; + nt_field_t *mp_cam_data_ft4; + nt_field_t *mp_cam_data_ft5; + + nt_register_t *mp_tcam_ctrl; + nt_field_t *mp_tcam_addr; + nt_field_t *mp_tcam_cnt; + nt_register_t *mp_tcam_data; + nt_field_t *mp_tcam_data_t; + + nt_register_t *mp_tci_ctrl; + nt_field_t *mp_tci_addr; + nt_field_t *mp_tci_cnt; + nt_register_t *mp_tci_data; + nt_field_t *mp_tci_data_color; + nt_field_t *mp_tci_data_ft; + + nt_register_t *mp_tcq_ctrl; + nt_field_t *mp_tcq_addr; + nt_field_t *mp_tcq_cnt; + nt_register_t *mp_tcq_data; + nt_field_t *mp_tcq_data_bank_mask; + nt_field_t *mp_tcq_data_qual; +}; + +#endif /* __FLOW_NTHW_KM_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.c new file mode 100644 index 0000000000..e823a527bb --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.c @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_pdb.h" + +#include /* malloc */ +#include /* memset */ + +void pdb_nthw_set_debug_mode(struct pdb_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_pdb, n_debug_mode); +} + +struct pdb_nthw *pdb_nthw_new(void) +{ + struct pdb_nthw *p = malloc(sizeof(struct pdb_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + + return p; +} + +void pdb_nthw_delete(struct pdb_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int pdb_nthw_init(struct pdb_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_PDB, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: Pdb %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_pdb = p_mod; + + /* RCP */ + p->mp_rcp_ctrl = module_get_register(p->m_pdb, PDB_RCP_CTRL); + p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, PDB_RCP_CTRL_ADR); + p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, PDB_RCP_CTRL_CNT); + p->mp_rcp_data = module_get_register(p->m_pdb, PDB_RCP_DATA); + p->mp_rcp_data_descriptor = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_DESCRIPTOR); + p->mp_rcp_data_desc_len = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_DESC_LEN); + p->mp_rcp_data_tx_port = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_TX_PORT); + p->mp_rcp_data_tx_ignore = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_TX_IGNORE); + p->mp_rcp_data_tx_now = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_TX_NOW); + p->mp_rcp_data_crc_overwrite = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_CRC_OVERWRITE); + p->mp_rcp_data_align = register_get_field(p->mp_rcp_data, PDB_RCP_DATA_ALIGN); + p->mp_rcp_data_ofs0_dyn = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS0_DYN); + p->mp_rcp_data_ofs0_rel = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS0_REL); + p->mp_rcp_data_ofs1_dyn = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS1_DYN); + p->mp_rcp_data_ofs1_rel = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS1_REL); + p->mp_rcp_data_ofs2_dyn = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS2_DYN); + p->mp_rcp_data_ofs2_rel = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS2_REL); + p->mp_rcp_data_ip_prot_tnl = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_IP_PROT_TNL); + p->mp_rcp_data_ppc_hsh = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_PPC_HSH); + p->mp_rcp_data_duplicate_en = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_DUPLICATE_EN); + p->mp_rcp_data_duplicate_bit = + register_get_field(p->mp_rcp_data, PDB_RCP_DATA_DUPLICATE_BIT); + p->mp_rcp_data_pcap_keep_fcs = + register_query_field(p->mp_rcp_data, PDB_RCP_DATA_PCAP_KEEP_FCS); + /* CONFIG */ + p->mp_config = module_get_register(p->m_pdb, PDB_CONFIG); + p->mp_config_ts_format = + register_get_field(p->mp_config, PDB_CONFIG_TS_FORMAT); + p->mp_config_port_ofs = + register_get_field(p->mp_config, PDB_CONFIG_PORT_OFS); + + return 0; +} + +/* RCP */ +void pdb_nthw_rcp_select(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_addr, val); +} + +void pdb_nthw_rcp_cnt(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_cnt, val); +} + +void pdb_nthw_rcp_descriptor(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_descriptor, val); +} + +void pdb_nthw_rcp_desc_len(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_desc_len, val); +} + +void pdb_nthw_rcp_tx_port(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_tx_port, val); +} + +void pdb_nthw_rcp_tx_ignore(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_tx_ignore, val); +} + +void pdb_nthw_rcp_tx_now(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_tx_now, val); +} + +void pdb_nthw_rcp_crc_overwrite(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_crc_overwrite, val); +} + +void pdb_nthw_rcp_align(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_align, val); +} + +void pdb_nthw_rcp_ofs0_dyn(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ofs0_dyn, val); +} + +void pdb_nthw_rcp_ofs0_rel(const struct pdb_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_ofs0_rel, val); +} + +void pdb_nthw_rcp_ofs1_dyn(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ofs1_dyn, val); +} + +void pdb_nthw_rcp_ofs1_rel(const struct pdb_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_ofs1_rel, val); +} + +void pdb_nthw_rcp_ofs2_dyn(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ofs2_dyn, val); +} + +void pdb_nthw_rcp_ofs2_rel(const struct pdb_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_ofs2_rel, val); +} + +void pdb_nthw_rcp_ip_prot_tnl(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ip_prot_tnl, val); +} + +void pdb_nthw_rcp_ppc_hsh(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ppc_hsh, val); +} + +void pdb_nthw_rcp_duplicate_en(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_duplicate_en, val); +} + +void pdb_nthw_rcp_duplicate_bit(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_duplicate_bit, val); +} + +void pdb_nthw_rcp_data_pcap_keep_fcs(const struct pdb_nthw *p, uint32_t val) +{ + if (p->mp_rcp_data_pcap_keep_fcs) + field_set_val32(p->mp_rcp_data_pcap_keep_fcs, val); +} + +void pdb_nthw_rcp_flush(const struct pdb_nthw *p) +{ + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +} + +/* CONFIG */ +void pdb_nthw_config_ts_format(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_config_ts_format, val); +} + +void pdb_nthw_config_port_ofs(const struct pdb_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_config_port_ofs, val); +} + +void pdb_nthw_config_flush(const struct pdb_nthw *p) +{ + register_flush(p->mp_config, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.h new file mode 100644 index 0000000000..aed050eca5 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_PDB_H__ +#define __FLOW_NTHW_PDB_H__ + +#include /* uint32_t */ +#include "nthw_fpga_model.h" + +struct pdb_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_pdb; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_addr; + nt_field_t *mp_rcp_cnt; + nt_register_t *mp_rcp_data; + nt_field_t *mp_rcp_data_descriptor; + nt_field_t *mp_rcp_data_desc_len; + nt_field_t *mp_rcp_data_tx_port; + nt_field_t *mp_rcp_data_tx_ignore; + nt_field_t *mp_rcp_data_tx_now; + nt_field_t *mp_rcp_data_crc_overwrite; + nt_field_t *mp_rcp_data_align; + nt_field_t *mp_rcp_data_ofs0_dyn; + nt_field_t *mp_rcp_data_ofs0_rel; + nt_field_t *mp_rcp_data_ofs1_dyn; + nt_field_t *mp_rcp_data_ofs1_rel; + nt_field_t *mp_rcp_data_ofs2_dyn; + nt_field_t *mp_rcp_data_ofs2_rel; + nt_field_t *mp_rcp_data_ip_prot_tnl; + nt_field_t *mp_rcp_data_ppc_hsh; + nt_field_t *mp_rcp_data_duplicate_en; + nt_field_t *mp_rcp_data_duplicate_bit; + nt_field_t *mp_rcp_data_pcap_keep_fcs; + + nt_register_t *mp_config; + nt_field_t *mp_config_ts_format; + nt_field_t *mp_config_port_ofs; +}; + +typedef struct pdb_nthw pdb_nthw_t; + +struct pdb_nthw *pdb_nthw_new(void); +void pdb_nthw_delete(struct pdb_nthw *p); +int pdb_nthw_init(struct pdb_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int pdb_nthw_setup(struct pdb_nthw *p, int n_idx, int n_idx_cnt); +void pdb_nthw_set_debug_mode(struct pdb_nthw *p, unsigned int n_debug_mode); + +/* RCP */ +void pdb_nthw_rcp_select(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_cnt(const struct pdb_nthw *p, uint32_t val); + +void pdb_nthw_rcp_descriptor(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_desc_len(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_tx_port(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_tx_ignore(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_tx_now(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_crc_overwrite(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_align(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_ofs0_dyn(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_ofs0_rel(const struct pdb_nthw *p, int32_t val); +void pdb_nthw_rcp_ofs1_dyn(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_ofs1_rel(const struct pdb_nthw *p, int32_t val); +void pdb_nthw_rcp_ofs2_dyn(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_ofs2_rel(const struct pdb_nthw *p, int32_t val); +void pdb_nthw_rcp_ip_prot_tnl(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_ppc_hsh(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_duplicate_en(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_duplicate_bit(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_data_pcap_keep_fcs(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_rcp_flush(const struct pdb_nthw *p); + +/* CONFIG */ +void pdb_nthw_config_ts_format(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_config_port_ofs(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_config_port_ofs(const struct pdb_nthw *p, uint32_t val); +void pdb_nthw_config_flush(const struct pdb_nthw *p); + +#endif /* __FLOW_NTHW_PDB_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.c new file mode 100644 index 0000000000..6c13824df6 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.c @@ -0,0 +1,355 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_qsl.h" + +#include /* malloc */ +#include /* memset */ + +void qsl_nthw_set_debug_mode(struct qsl_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_qsl, n_debug_mode); +} + +struct qsl_nthw *qsl_nthw_new(void) +{ + struct qsl_nthw *p = malloc(sizeof(struct qsl_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + + return p; +} + +void qsl_nthw_delete(struct qsl_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int qsl_nthw_init(struct qsl_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_QSL, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: QSL %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_qsl = p_mod; + + /* RCP */ + p->mp_rcp_ctrl = module_get_register(p->m_qsl, QSL_RCP_CTRL); + p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, QSL_RCP_CTRL_ADR); + p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, QSL_RCP_CTRL_CNT); + p->mp_rcp_data = module_get_register(p->m_qsl, QSL_RCP_DATA); + p->mp_rcp_data_discard = + register_get_field(p->mp_rcp_data, QSL_RCP_DATA_DISCARD); + p->mp_rcp_data_drop = register_get_field(p->mp_rcp_data, QSL_RCP_DATA_DROP); + p->mp_rcp_data_tbl_lo = + register_get_field(p->mp_rcp_data, QSL_RCP_DATA_TBL_LO); + p->mp_rcp_data_tbl_hi = + register_get_field(p->mp_rcp_data, QSL_RCP_DATA_TBL_HI); + p->mp_rcp_data_tbl_idx = + register_get_field(p->mp_rcp_data, QSL_RCP_DATA_TBL_IDX); + p->mp_rcp_data_tbl_msk = + register_get_field(p->mp_rcp_data, QSL_RCP_DATA_TBL_MSK); + p->mp_rcp_data_cao = register_query_field(p->mp_rcp_data, QSL_RCP_DATA_CAO); + p->mp_rcp_data_lr = register_query_field(p->mp_rcp_data, QSL_RCP_DATA_LR); + p->mp_rcp_data_tsa = register_query_field(p->mp_rcp_data, QSL_RCP_DATA_TSA); + p->mp_rcp_data_vli = register_query_field(p->mp_rcp_data, QSL_RCP_DATA_VLI); + + /* QST */ + p->mp_qst_ctrl = module_get_register(p->m_qsl, QSL_QST_CTRL); + p->mp_qst_addr = register_get_field(p->mp_qst_ctrl, QSL_QST_CTRL_ADR); + p->mp_qst_cnt = register_get_field(p->mp_qst_ctrl, QSL_QST_CTRL_CNT); + p->mp_qst_data = module_get_register(p->m_qsl, QSL_QST_DATA); + p->mp_qst_data_queue = register_get_field(p->mp_qst_data, QSL_QST_DATA_QUEUE); + p->mp_qst_data_en = register_query_field(p->mp_qst_data, QSL_QST_DATA_EN); + p->mp_qst_data_tx_port = + register_query_field(p->mp_qst_data, QSL_QST_DATA_TX_PORT); + p->mp_qst_data_lre = register_query_field(p->mp_qst_data, QSL_QST_DATA_LRE); + p->mp_qst_data_tci = register_query_field(p->mp_qst_data, QSL_QST_DATA_TCI); + p->mp_qst_data_ven = register_query_field(p->mp_qst_data, QSL_QST_DATA_VEN); + /* QEN */ + p->mp_qen_ctrl = module_get_register(p->m_qsl, QSL_QEN_CTRL); + p->mp_qen_addr = register_get_field(p->mp_qen_ctrl, QSL_QEN_CTRL_ADR); + p->mp_qen_cnt = register_get_field(p->mp_qen_ctrl, QSL_QEN_CTRL_CNT); + p->mp_qen_data = module_get_register(p->m_qsl, QSL_QEN_DATA); + p->mp_qen_data_en = register_get_field(p->mp_qen_data, QSL_QEN_DATA_EN); + /* UNMQ */ + p->mp_unmq_ctrl = module_get_register(p->m_qsl, QSL_UNMQ_CTRL); + p->mp_unmq_addr = register_get_field(p->mp_unmq_ctrl, QSL_UNMQ_CTRL_ADR); + p->mp_unmq_cnt = register_get_field(p->mp_unmq_ctrl, QSL_UNMQ_CTRL_CNT); + p->mp_unmq_data = module_get_register(p->m_qsl, QSL_UNMQ_DATA); + p->mp_unmq_data_dest_queue = + register_get_field(p->mp_unmq_data, QSL_UNMQ_DATA_DEST_QUEUE); + p->mp_unmq_data_en = register_get_field(p->mp_unmq_data, QSL_UNMQ_DATA_EN); + + if (!p->mp_qst_data_en) { + /* changed name from EN to QEN in v0.7 */ + p->mp_qst_data_en = + register_get_field(p->mp_qst_data, QSL_QST_DATA_QEN); + } + + /* LTX - not there anymore from v0.7+ */ + p->mp_ltx_ctrl = module_query_register(p->m_qsl, QSL_LTX_CTRL); + if (p->mp_ltx_ctrl) { + p->mp_ltx_addr = + register_get_field(p->mp_ltx_ctrl, QSL_LTX_CTRL_ADR); + p->mp_ltx_cnt = register_get_field(p->mp_ltx_ctrl, QSL_LTX_CTRL_CNT); + } else { + p->mp_ltx_addr = NULL; + p->mp_ltx_cnt = NULL; + } + p->mp_ltx_data = module_query_register(p->m_qsl, QSL_LTX_DATA); + if (p->mp_ltx_data) { + p->mp_ltx_data_lr = + register_get_field(p->mp_ltx_data, QSL_LTX_DATA_LR); + p->mp_ltx_data_tx_port = + register_get_field(p->mp_ltx_data, QSL_LTX_DATA_TX_PORT); + p->mp_ltx_data_tsa = + register_get_field(p->mp_ltx_data, QSL_LTX_DATA_TSA); + } else { + p->mp_ltx_data_lr = NULL; + p->mp_ltx_data_tx_port = NULL; + p->mp_ltx_data_tsa = NULL; + } + return 0; +} + +int qsl_nthw_setup(struct qsl_nthw *p, int n_idx, int n_idx_cnt) +{ + (void)p; + (void)n_idx; + (void)n_idx_cnt; + + return 0; +} + +/* RCP */ +void qsl_nthw_rcp_select(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_addr, val); +}; + +void qsl_nthw_rcp_cnt(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_cnt, val); +} + +void qsl_nthw_rcp_discard(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_discard, val); +} + +void qsl_nthw_rcp_drop(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_drop, val); +} + +void qsl_nthw_rcp_tbl_lo(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_tbl_lo, val); +} + +void qsl_nthw_rcp_tbl_hi(const struct qsl_nthw *p, uint32_t val) + +{ + field_set_val32(p->mp_rcp_data_tbl_hi, val); +} + +void qsl_nthw_rcp_tbl_idx(const struct qsl_nthw *p, uint32_t val) + +{ + field_set_val32(p->mp_rcp_data_tbl_idx, val); +} + +void qsl_nthw_rcp_tbl_msk(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_tbl_msk, val); +} + +void qsl_nthw_rcp_cao(const struct qsl_nthw *p, uint32_t val) +{ + if (p->mp_rcp_data_cao) + field_set_val32(p->mp_rcp_data_cao, val); +} + +void qsl_nthw_rcp_lr(const struct qsl_nthw *p, uint32_t val) +{ + if (p->mp_rcp_data_lr) + field_set_val32(p->mp_rcp_data_lr, val); +} + +void qsl_nthw_rcp_tsa(const struct qsl_nthw *p, uint32_t val) +{ + if (p->mp_rcp_data_tsa) + field_set_val32(p->mp_rcp_data_tsa, val); +} + +void qsl_nthw_rcp_vli(const struct qsl_nthw *p, uint32_t val) +{ + if (p->mp_rcp_data_vli) + field_set_val32(p->mp_rcp_data_vli, val); +} + +void qsl_nthw_rcp_flush(const struct qsl_nthw *p) +{ + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +} + +/* LTX */ +void qsl_nthw_ltx_select(const struct qsl_nthw *p, uint32_t val) +{ + if (p->mp_ltx_addr) + field_set_val32(p->mp_ltx_addr, val); +} + +void qsl_nthw_ltx_cnt(const struct qsl_nthw *p, uint32_t val) +{ + if (p->mp_ltx_addr) + field_set_val32(p->mp_ltx_cnt, val); +} + +void qsl_nthw_ltx_lr(const struct qsl_nthw *p, uint32_t val) +{ + if (p->mp_ltx_data_lr) + field_set_val32(p->mp_ltx_data_lr, val); +} + +void qsl_nthw_ltx_tx_port(const struct qsl_nthw *p, uint32_t val) +{ + if (p->mp_ltx_data_tx_port) + field_set_val32(p->mp_ltx_data_tx_port, val); +} + +void qsl_nthw_ltx_tsa(const struct qsl_nthw *p, uint32_t val) +{ + if (p->mp_ltx_data_tsa) + field_set_val32(p->mp_ltx_data_tsa, val); +}; + +void qsl_nthw_ltx_flush(const struct qsl_nthw *p) +{ + register_flush(p->mp_ltx_ctrl, 1); + register_flush(p->mp_ltx_data, 1); +} + +/* QST */ +void qsl_nthw_qst_select(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_qst_addr, val); +} + +void qsl_nthw_qst_cnt(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_qst_cnt, val); +} + +void qsl_nthw_qst_queue(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_qst_data_queue, val); +} + +void qsl_nthw_qst_en(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_qst_data_en, val); +} + +void qsl_nthw_qst_tx_port(const struct qsl_nthw *p, uint32_t val) +{ + if (p->mp_qst_data_tx_port) + field_set_val32(p->mp_qst_data_tx_port, val); +} + +void qsl_nthw_qst_lre(const struct qsl_nthw *p, uint32_t val) +{ + if (p->mp_qst_data_lre) + field_set_val32(p->mp_qst_data_lre, val); +} + +void qsl_nthw_qst_tci(const struct qsl_nthw *p, uint32_t val) +{ + if (p->mp_qst_data_tci) + field_set_val32(p->mp_qst_data_tci, val); +} + +void qsl_nthw_qst_ven(const struct qsl_nthw *p, uint32_t val) +{ + if (p->mp_qst_data_ven) + field_set_val32(p->mp_qst_data_ven, val); +} + +void qsl_nthw_qst_flush(const struct qsl_nthw *p) +{ + register_flush(p->mp_qst_ctrl, 1); + register_flush(p->mp_qst_data, 1); +} + +/* QEN */ +void qsl_nthw_qen_select(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_qen_addr, val); +} + +void qsl_nthw_qen_cnt(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_qen_cnt, val); +} + +void qsl_nthw_qen_en(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_qen_data_en, val); +} + +void qsl_nthw_qen_flush(const struct qsl_nthw *p) +{ + register_flush(p->mp_qen_ctrl, 1); + register_flush(p->mp_qen_data, 1); +} + +/* UNMQ */ +void qsl_nthw_unmq_select(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_unmq_addr, val); +} + +void qsl_nthw_unmq_cnt(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_unmq_cnt, val); +} + +void qsl_nthw_unmq_dest_queue(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_unmq_data_dest_queue, val); +} + +void qsl_nthw_unmq_en(const struct qsl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_unmq_data_en, val); +} + +void qsl_nthw_unmq_flush(const struct qsl_nthw *p) +{ + register_flush(p->mp_unmq_ctrl, 1); + register_flush(p->mp_unmq_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.h new file mode 100644 index 0000000000..eeebbcf1c4 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_QSL_H__ +#define __FLOW_NTHW_QSL_H__ + +#include /* uint32_t */ +#include "nthw_fpga_model.h" + +struct qsl_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_qsl; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_addr; + nt_field_t *mp_rcp_cnt; + nt_register_t *mp_rcp_data; + nt_field_t *mp_rcp_data_discard; + nt_field_t *mp_rcp_data_drop; + nt_field_t *mp_rcp_data_tbl_lo; + nt_field_t *mp_rcp_data_tbl_hi; + nt_field_t *mp_rcp_data_tbl_idx; + nt_field_t *mp_rcp_data_tbl_msk; + nt_field_t *mp_rcp_data_cao; + nt_field_t *mp_rcp_data_lr; + nt_field_t *mp_rcp_data_tsa; + nt_field_t *mp_rcp_data_vli; + + nt_register_t *mp_ltx_ctrl; + nt_field_t *mp_ltx_addr; + nt_field_t *mp_ltx_cnt; + nt_register_t *mp_ltx_data; + nt_field_t *mp_ltx_data_lr; + nt_field_t *mp_ltx_data_tx_port; + nt_field_t *mp_ltx_data_tsa; + + nt_register_t *mp_qst_ctrl; + nt_field_t *mp_qst_addr; + nt_field_t *mp_qst_cnt; + nt_register_t *mp_qst_data; + nt_field_t *mp_qst_data_queue; + nt_field_t *mp_qst_data_en; + nt_field_t *mp_qst_data_tx_port; + nt_field_t *mp_qst_data_lre; + nt_field_t *mp_qst_data_tci; + nt_field_t *mp_qst_data_ven; + + nt_register_t *mp_qen_ctrl; + nt_field_t *mp_qen_addr; + nt_field_t *mp_qen_cnt; + nt_register_t *mp_qen_data; + nt_field_t *mp_qen_data_en; + + nt_register_t *mp_unmq_ctrl; + nt_field_t *mp_unmq_addr; + nt_field_t *mp_unmq_cnt; + nt_register_t *mp_unmq_data; + nt_field_t *mp_unmq_data_dest_queue; + nt_field_t *mp_unmq_data_en; +}; + +typedef struct qsl_nthw qsl_nthw_t; + +struct qsl_nthw *qsl_nthw_new(void); +void qsl_nthw_delete(struct qsl_nthw *p); +int qsl_nthw_init(struct qsl_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int qsl_nthw_setup(struct qsl_nthw *p, int n_idx, int n_idx_cnt); +void qsl_nthw_set_debug_mode(struct qsl_nthw *p, unsigned int n_debug_mode); + +/* RCP */ +void qsl_nthw_rcp_select(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_rcp_cnt(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_rcp_discard(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_rcp_drop(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_rcp_tbl_lo(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_rcp_tbl_hi(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_rcp_tbl_idx(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_rcp_tbl_msk(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_rcp_cao(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_rcp_lr(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_rcp_tsa(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_rcp_vli(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_rcp_flush(const struct qsl_nthw *p); + +/* LTX */ +void qsl_nthw_ltx_select(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_ltx_cnt(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_ltx_lr(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_ltx_tx_port(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_ltx_tsa(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_ltx_flush(const struct qsl_nthw *p); + +/* QST */ +void qsl_nthw_qst_select(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_qst_cnt(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_qst_queue(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_qst_en(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_qst_tx_port(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_qst_lre(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_qst_tci(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_qst_ven(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_qst_flush(const struct qsl_nthw *p); + +/* QEN */ +void qsl_nthw_qen_select(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_qen_cnt(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_qen_en(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_qen_flush(const struct qsl_nthw *p); + +/* UNMQ */ +void qsl_nthw_unmq_select(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_unmq_cnt(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_unmq_dest_queue(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_unmq_en(const struct qsl_nthw *p, uint32_t val); +void qsl_nthw_unmq_flush(const struct qsl_nthw *p); + +#endif /* __FLOW_NTHW_QSL_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.c new file mode 100644 index 0000000000..8f519b7728 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_rmc.h" + +#include /* malloc */ +#include /* memset */ + +void rmc_nthw_set_debug_mode(struct rmc_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_rmc, n_debug_mode); +} + +struct rmc_nthw *rmc_nthw_new(void) +{ + struct rmc_nthw *p = malloc(sizeof(struct rmc_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + + return p; +} + +void rmc_nthw_delete(struct rmc_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int rmc_nthw_init(struct rmc_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_RMC, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: RMC %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_rmc = p_mod; + + /* CTRL */ + p->mp_ctrl = module_get_register(p->m_rmc, RMC_CTRL); + p->mp_ctrl_block_statt = + register_get_field(p->mp_ctrl, RMC_CTRL_BLOCK_STATT); + p->mp_ctrl_block_keep_a = + register_get_field(p->mp_ctrl, RMC_CTRL_BLOCK_KEEPA); + p->mp_ctrl_block_rpp_slice = + register_query_field(p->mp_ctrl, RMC_CTRL_BLOCK_RPP_SLICE); + p->mp_ctrl_block_mac_port = + register_get_field(p->mp_ctrl, RMC_CTRL_BLOCK_MAC_PORT); + p->mp_ctrl_lag_phy_odd_even = + register_get_field(p->mp_ctrl, RMC_CTRL_LAG_PHY_ODD_EVEN); + return 0; +} + +int rmc_nthw_setup(struct rmc_nthw *p, int n_idx, int n_idx_cnt) +{ + (void)p; + (void)n_idx; + (void)n_idx_cnt; + + return 0; +} + +/* CTRL */ +void rmc_nthw_ctrl_block_statt(const struct rmc_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_ctrl_block_statt, val); +} + +void rmc_nthw_ctrl_block_keep_a(const struct rmc_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_ctrl_block_keep_a, val); +} + +void rmc_nthw_ctrl_block_rpp_slice(const struct rmc_nthw *p, uint32_t val) +{ + if (p->mp_ctrl_block_rpp_slice) + field_set_val32(p->mp_ctrl_block_rpp_slice, val); +} + +void rmc_nthw_ctrl_block_mac_port(const struct rmc_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_ctrl_block_mac_port, val); +} + +void rmc_nthw_ctrl_lag_phy_odd_even(const struct rmc_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_ctrl_lag_phy_odd_even, val); +} + +void rmc_nthw_ctrl_flush(const struct rmc_nthw *p) +{ + register_flush(p->mp_ctrl, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.h new file mode 100644 index 0000000000..57d5776002 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_RMC_H__ +#define __FLOW_NTHW_RMC_H__ + +#include /* uint32_t */ +#include "nthw_fpga_model.h" + +struct rmc_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_rmc; + + nt_register_t *mp_ctrl; + nt_field_t *mp_ctrl_block_statt; + nt_field_t *mp_ctrl_block_keep_a; + nt_field_t *mp_ctrl_block_rpp_slice; + nt_field_t *mp_ctrl_block_mac_port; + nt_field_t *mp_ctrl_lag_phy_odd_even; +}; + +struct rmc_nthw *rmc_nthw_new(void); +void rmc_nthw_delete(struct rmc_nthw *p); +int rmc_nthw_init(struct rmc_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int rmc_nthw_setup(struct rmc_nthw *p, int n_idx, int n_idx_cnt); +void rmc_nthw_set_debug_mode(struct rmc_nthw *p, unsigned int n_debug_mode); + +/* CTRL */ +void rmc_nthw_ctrl_block_statt(const struct rmc_nthw *p, uint32_t val); +void rmc_nthw_ctrl_block_keep_a(const struct rmc_nthw *p, uint32_t val); +void rmc_nthw_ctrl_block_rpp_slice(const struct rmc_nthw *p, uint32_t val); +void rmc_nthw_ctrl_block_mac_port(const struct rmc_nthw *p, uint32_t val); +void rmc_nthw_ctrl_lag_phy_odd_even(const struct rmc_nthw *p, uint32_t val); +void rmc_nthw_ctrl_flush(const struct rmc_nthw *p); + +#endif /* __FLOW_NTHW_RMC_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.c new file mode 100644 index 0000000000..934778f426 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.c @@ -0,0 +1,294 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_roa.h" + +#include /* malloc */ +#include /* memset */ + +void roa_nthw_set_debug_mode(struct roa_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_roa, n_debug_mode); +} + +struct roa_nthw *roa_nthw_new(void) +{ + struct roa_nthw *p = malloc(sizeof(struct roa_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + + return p; +} + +void roa_nthw_delete(struct roa_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int roa_nthw_init(struct roa_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_ROA, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: ROA %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_roa = p_mod; + + /* TUN HDR */ + p->mp_tun_hdr_ctrl = module_get_register(p->m_roa, ROA_TUNHDR_CTRL); + p->mp_tun_hdr_addr = + register_get_field(p->mp_tun_hdr_ctrl, ROA_TUNHDR_CTRL_ADR); + p->mp_tun_hdr_cnt = + register_get_field(p->mp_tun_hdr_ctrl, ROA_TUNHDR_CTRL_CNT); + p->mp_tun_hdr_data = module_get_register(p->m_roa, ROA_TUNHDR_DATA); + p->mp_tun_hdr_data_tunnel_hdr = + register_get_field(p->mp_tun_hdr_data, ROA_TUNHDR_DATA_TUNNEL_HDR); + /* TUN CFG */ + p->mp_tun_cfg_ctrl = module_get_register(p->m_roa, ROA_TUNCFG_CTRL); + p->mp_tun_cfg_addr = + register_get_field(p->mp_tun_cfg_ctrl, ROA_TUNCFG_CTRL_ADR); + p->mp_tun_cfg_cnt = + register_get_field(p->mp_tun_cfg_ctrl, ROA_TUNCFG_CTRL_CNT); + p->mp_tun_cfg_data = module_get_register(p->m_roa, ROA_TUNCFG_DATA); + p->mp_tun_cfg_data_tun_len = + register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_LEN); + p->mp_tun_cfg_data_tun_type = + register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_TYPE); + p->mp_tun_cfg_data_tun_vlan = + register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_VLAN); + p->mp_tun_cfg_data_ip_type = + register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IP_TYPE); + p->mp_tun_cfg_data_ipcs_upd = + register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IPCS_UPD); + p->mp_tun_cfg_data_ipcs_precalc = + register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IPCS_PRECALC); + p->mp_tun_cfg_data_iptl_upd = + register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IPTL_UPD); + p->mp_tun_cfg_data_iptl_precalc = + register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IPTL_PRECALC); + p->mp_tun_cfg_data_vxlan_udp_len_upd = + register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_VXLAN_UDP_LEN_UPD); + p->mp_tun_cfg_data_tx_lag_ix = + register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TX_LAG_IX); + p->mp_tun_cfg_data_recirculate = + register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_RECIRCULATE); + p->mp_tun_cfg_data_push_tunnel = + register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_PUSH_TUNNEL); + p->mp_tun_cfg_data_recirc_port = + register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_RECIRC_PORT); + p->mp_tun_cfg_data_recirc_bypass = + register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_RECIRC_BYPASS); + /* CONFIG */ + p->mp_config = module_get_register(p->m_roa, ROA_CONFIG); + p->mp_config_fwd_recirculate = + register_get_field(p->mp_config, ROA_CONFIG_FWD_RECIRCULATE); + p->mp_config_fwd_normal_pcks = + register_get_field(p->mp_config, ROA_CONFIG_FWD_NORMAL_PCKS); + p->mp_config_fwd_tx_port0 = + register_get_field(p->mp_config, ROA_CONFIG_FWD_TXPORT0); + p->mp_config_fwd_tx_port1 = + register_get_field(p->mp_config, ROA_CONFIG_FWD_TXPORT1); + p->mp_config_fwd_cell_builder_pcks = + register_get_field(p->mp_config, ROA_CONFIG_FWD_CELLBUILDER_PCKS); + p->mp_config_fwd_non_normal_pcks = + register_get_field(p->mp_config, ROA_CONFIG_FWD_NON_NORMAL_PCKS); + /* LAG */ + p->mp_lag_cfg_ctrl = module_get_register(p->m_roa, ROA_LAGCFG_CTRL); + p->mp_lag_cfg_addr = + register_get_field(p->mp_lag_cfg_ctrl, ROA_LAGCFG_CTRL_ADR); + p->mp_lag_cfg_cnt = + register_get_field(p->mp_lag_cfg_ctrl, ROA_LAGCFG_CTRL_CNT); + p->mp_lag_cfg_data = module_get_register(p->m_roa, ROA_LAGCFG_DATA); + p->mp_lag_cfg_data_tx_phy_port = + register_get_field(p->mp_lag_cfg_data, ROA_LAGCFG_DATA_TXPHY_PORT); + + return 0; +} + +/* TUN HDR */ +void roa_nthw_tun_hdr_select(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_hdr_addr, val); +} + +void roa_nthw_tun_hdr_cnt(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_hdr_cnt, val); +} + +void roa_nthw_tun_hdr_tunnel_hdr(const struct roa_nthw *p, uint32_t *val) +{ + field_set_val(p->mp_tun_hdr_data_tunnel_hdr, val, 4); +} + +void roa_nthw_tun_hdr_flush(const struct roa_nthw *p) +{ + register_flush(p->mp_tun_hdr_ctrl, 1); + register_flush(p->mp_tun_hdr_data, 1); +} + +/* TUN CFG */ +void roa_nthw_tun_cfg_select(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_addr, val); +} + +void roa_nthw_tun_cfg_cnt(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_cnt, val); +} + +void roa_nthw_tun_cfg_tun_len(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_data_tun_len, val); +} + +void roa_nthw_tun_cfg_tun_type(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_data_tun_type, val); +} + +void roa_nthw_tun_cfg_tun_vlan(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_data_tun_vlan, val); +} + +void roa_nthw_tun_cfg_ip_type(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_data_ip_type, val); +} + +void roa_nthw_tun_cfg_ipcs_upd(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_data_ipcs_upd, val); +} + +void roa_nthw_tun_cfg_ipcs_precalc(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_data_ipcs_precalc, val); +} + +void roa_nthw_tun_cfg_iptl_upd(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_data_iptl_upd, val); +} + +void roa_nthw_tun_cfg_iptl_precalc(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_data_iptl_precalc, val); +} + +void roa_nthw_tun_cfg_vxlan_udp_len_upd(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_data_vxlan_udp_len_upd, val); +} + +void roa_nthw_tun_cfg_tx_lag_ix(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_data_tx_lag_ix, val); +}; + +void roa_nthw_tun_cfg_recirculate(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_data_recirculate, val); +} + +void roa_nthw_tun_cfg_push_tunnel(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_data_push_tunnel, val); +} + +void roa_nthw_tun_cfg_recirc_port(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_data_recirc_port, val); +} + +void roa_nthw_tun_cfg_recirc_bypass(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_tun_cfg_data_recirc_bypass, val); +} + +void roa_nthw_tun_cfg_flush(const struct roa_nthw *p) +{ + register_flush(p->mp_tun_cfg_ctrl, 1); + register_flush(p->mp_tun_cfg_data, 1); +} + +/* ROA CONFIG */ +void roa_nthw_config_fwd_recirculate(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_config_fwd_recirculate, val); +} + +void roa_nthw_config_fwd_normal_pcks(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_config_fwd_normal_pcks, val); +} + +void roa_nthw_config_fwd_tx_port0(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_config_fwd_tx_port0, val); +} + +void roa_nthw_config_fwd_tx_port1(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_config_fwd_tx_port1, val); +} + +void roa_nthw_config_fwd_cell_builder_pcks(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_config_fwd_cell_builder_pcks, val); +} + +void roa_nthw_config_fwd_non_normal_pcks(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_config_fwd_non_normal_pcks, val); +} + +void roa_nthw_config_flush(const struct roa_nthw *p) +{ + register_flush(p->mp_config, 1); +} + +/* LAG */ +void roa_nthw_lag_cfg_select(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_lag_cfg_addr, val); +} + +void roa_nthw_lag_cfg_cnt(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_lag_cfg_cnt, val); +} + +void roa_nthw_lag_cfg_tx_phy_port(const struct roa_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_lag_cfg_data_tx_phy_port, val); +} + +void roa_nthw_lag_cfg_flush(const struct roa_nthw *p) +{ + register_flush(p->mp_lag_cfg_ctrl, 1); + register_flush(p->mp_lag_cfg_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.h new file mode 100644 index 0000000000..9398ef5ae9 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_ROA_H__ +#define __FLOW_NTHW_ROA_H__ + +#include /* uint32_t */ +#include "nthw_fpga_model.h" + +struct roa_nthw; + +typedef struct roa_nthw roa_nthw_t; + +struct roa_nthw *roa_nthw_new(void); +void roa_nthw_delete(struct roa_nthw *p); +int roa_nthw_init(struct roa_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int roa_nthw_setup(struct roa_nthw *p, int n_idx, int n_idx_cnt); +void roa_nthw_set_debug_mode(struct roa_nthw *p, unsigned int n_debug_mode); + +/* TUN HDR */ +void roa_nthw_tun_hdr_select(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_hdr_cnt(const struct roa_nthw *p, uint32_t val); + +void roa_nthw_tun_hdr_tunnel_hdr(const struct roa_nthw *p, uint32_t *val); +void roa_nthw_tun_hdr_flush(const struct roa_nthw *p); + +/* TUN CFG */ +void roa_nthw_tun_cfg_select(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_cnt(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_tun_len(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_tun_type(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_tun_vlan(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_ip_type(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_ipcs_upd(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_ipcs_precalc(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_iptl_upd(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_iptl_precalc(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_vxlan_udp_len_upd(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_tx_lag_ix(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_recirculate(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_push_tunnel(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_recirc_port(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_recirc_bypass(const struct roa_nthw *p, uint32_t val); +void roa_nthw_tun_cfg_flush(const struct roa_nthw *p); + +/* ROA CONFIG */ +void roa_nthw_config_fwd_recirculate(const struct roa_nthw *p, uint32_t val); +void roa_nthw_config_fwd_normal_pcks(const struct roa_nthw *p, uint32_t val); +void roa_nthw_config_fwd_tx_port0(const struct roa_nthw *p, uint32_t val); +void roa_nthw_config_fwd_tx_port1(const struct roa_nthw *p, uint32_t val); +void roa_nthw_config_fwd_cell_builder_pcks(const struct roa_nthw *p, uint32_t val); +void roa_nthw_config_fwd_non_normal_pcks(const struct roa_nthw *p, uint32_t val); +void roa_nthw_config_flush(const struct roa_nthw *p); + +/* LAG */ +void roa_nthw_lag_cfg_select(const struct roa_nthw *p, uint32_t val); +void roa_nthw_lag_cfg_cnt(const struct roa_nthw *p, uint32_t val); +void roa_nthw_lag_cfg_tx_phy_port(const struct roa_nthw *p, uint32_t val); +void roa_nthw_lag_cfg_flush(const struct roa_nthw *p); + +struct roa_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_roa; + + nt_register_t *mp_tun_hdr_ctrl; + nt_field_t *mp_tun_hdr_addr; + nt_field_t *mp_tun_hdr_cnt; + nt_register_t *mp_tun_hdr_data; + nt_field_t *mp_tun_hdr_data_tunnel_hdr; + + nt_register_t *mp_tun_cfg_ctrl; + nt_field_t *mp_tun_cfg_addr; + nt_field_t *mp_tun_cfg_cnt; + nt_register_t *mp_tun_cfg_data; + nt_field_t *mp_tun_cfg_data_tun_len; + nt_field_t *mp_tun_cfg_data_tun_type; + nt_field_t *mp_tun_cfg_data_tun_vlan; + nt_field_t *mp_tun_cfg_data_ip_type; + nt_field_t *mp_tun_cfg_data_ipcs_upd; + nt_field_t *mp_tun_cfg_data_ipcs_precalc; + nt_field_t *mp_tun_cfg_data_iptl_upd; + nt_field_t *mp_tun_cfg_data_iptl_precalc; + nt_field_t *mp_tun_cfg_data_vxlan_udp_len_upd; + nt_field_t *mp_tun_cfg_data_tx_lag_ix; + nt_field_t *mp_tun_cfg_data_recirculate; + nt_field_t *mp_tun_cfg_data_push_tunnel; + nt_field_t *mp_tun_cfg_data_recirc_port; + nt_field_t *mp_tun_cfg_data_recirc_bypass; + + nt_register_t *mp_config; + nt_field_t *mp_config_fwd_recirculate; + nt_field_t *mp_config_fwd_normal_pcks; + nt_field_t *mp_config_fwd_tx_port0; + nt_field_t *mp_config_fwd_tx_port1; + nt_field_t *mp_config_fwd_cell_builder_pcks; + nt_field_t *mp_config_fwd_non_normal_pcks; + + nt_register_t *mp_lag_cfg_ctrl; + nt_field_t *mp_lag_cfg_addr; + nt_field_t *mp_lag_cfg_cnt; + nt_register_t *mp_lag_cfg_data; + nt_field_t *mp_lag_cfg_data_tx_phy_port; +}; + +#endif /* __FLOW_NTHW_ROA_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c new file mode 100644 index 0000000000..2ce3ce6cf8 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_rpp_lr.h" + +#include +#include + +void rpp_lr_nthw_set_debug_mode(struct rpp_lr_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_rpp_lr, n_debug_mode); +} + +struct rpp_lr_nthw *rpp_lr_nthw_new(void) +{ + struct rpp_lr_nthw *p = malloc(sizeof(struct rpp_lr_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + return p; +} + +void rpp_lr_nthw_delete(struct rpp_lr_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int rpp_lr_nthw_init(struct rpp_lr_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_RPP_LR, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: RppLr %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_rpp_lr = fpga_query_module(p_fpga, MOD_RPP_LR, n_instance); + + p->mp_rcp_ctrl = module_get_register(p->m_rpp_lr, RPP_LR_RCP_CTRL); + p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, RPP_LR_RCP_CTRL_ADR); + p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, RPP_LR_RCP_CTRL_CNT); + p->mp_rcp_data = module_get_register(p->m_rpp_lr, RPP_LR_RCP_DATA); + p->mp_rcp_data_exp = register_get_field(p->mp_rcp_data, RPP_LR_RCP_DATA_EXP); + + p->mp_ifr_rcp_ctrl = module_query_register(p->m_rpp_lr, RPP_LR_IFR_RCP_CTRL); + p->mp_ifr_rcp_addr = + register_query_field(p->mp_ifr_rcp_ctrl, RPP_LR_IFR_RCP_CTRL_ADR); + p->mp_ifr_rcp_cnt = + register_query_field(p->mp_ifr_rcp_ctrl, RPP_LR_IFR_RCP_CTRL_CNT); + p->mp_ifr_rcp_data = module_query_register(p->m_rpp_lr, RPP_LR_IFR_RCP_DATA); + p->mp_ifr_rcp_data_en = + register_query_field(p->mp_ifr_rcp_data, RPP_LR_IFR_RCP_DATA_EN); + p->mp_ifr_rcp_data_mtu = + register_query_field(p->mp_ifr_rcp_data, RPP_LR_IFR_RCP_DATA_MTU); + + return 0; +} + +void rpp_lr_nthw_rcp_select(const struct rpp_lr_nthw *p, uint32_t val) +{ + assert(p->mp_rcp_addr); + field_set_val32(p->mp_rcp_addr, val); +} + +void rpp_lr_nthw_rcp_cnt(const struct rpp_lr_nthw *p, uint32_t val) +{ + assert(p->mp_rcp_cnt); + field_set_val32(p->mp_rcp_cnt, val); +} + +void rpp_lr_nthw_rcp_exp(const struct rpp_lr_nthw *p, uint32_t val) +{ + assert(p->mp_rcp_data_exp); + field_set_val32(p->mp_rcp_data_exp, val); +} + +void rpp_lr_nthw_rcp_flush(const struct rpp_lr_nthw *p) +{ + assert(p->mp_rcp_ctrl); + assert(p->mp_rcp_data); + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +} + +void rpp_lr_nthw_ifr_rcp_select(const struct rpp_lr_nthw *p, uint32_t val) +{ + assert(p->mp_ifr_rcp_addr); + field_set_val32(p->mp_ifr_rcp_addr, val); +} + +void rpp_lr_nthw_ifr_rcp_cnt(const struct rpp_lr_nthw *p, uint32_t val) +{ + assert(p->mp_ifr_rcp_cnt); + field_set_val32(p->mp_ifr_rcp_cnt, val); +} + +void rpp_lr_nthw_ifr_rcp_en(const struct rpp_lr_nthw *p, uint32_t val) +{ + assert(p->mp_ifr_rcp_data_en); + field_set_val32(p->mp_ifr_rcp_data_en, val); +} + +void rpp_lr_nthw_ifr_rcp_mtu(const struct rpp_lr_nthw *p, uint32_t val) +{ + assert(p->mp_ifr_rcp_data_mtu); + field_set_val32(p->mp_ifr_rcp_data_mtu, val); +} + +void rpp_lr_nthw_ifr_rcp_flush(const struct rpp_lr_nthw *p) +{ + assert(p->mp_ifr_rcp_ctrl); + assert(p->mp_ifr_rcp_data); + register_flush(p->mp_ifr_rcp_ctrl, 1); + register_flush(p->mp_ifr_rcp_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h new file mode 100644 index 0000000000..e442c9d8d2 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_RPP_LR_H__ +#define __FLOW_NTHW_RPP_LR_H__ + +#include +#include "nthw_fpga_model.h" + +struct rpp_lr_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_rpp_lr; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_addr; + nt_field_t *mp_rcp_cnt; + + nt_register_t *mp_rcp_data; + nt_field_t *mp_rcp_data_exp; + + nt_register_t *mp_ifr_rcp_ctrl; + nt_field_t *mp_ifr_rcp_addr; + nt_field_t *mp_ifr_rcp_cnt; + + nt_register_t *mp_ifr_rcp_data; + nt_field_t *mp_ifr_rcp_data_en; + nt_field_t *mp_ifr_rcp_data_mtu; +}; + +struct rpp_lr_nthw *rpp_lr_nthw_new(void); +void rpp_lr_nthw_delete(struct rpp_lr_nthw *p); +int rpp_lr_nthw_init(struct rpp_lr_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int rpp_lr_nthw_setup(struct rpp_lr_nthw *p, int n_idx, int n_idx_cnt); +void rpp_lr_nthw_set_debug_mode(struct rpp_lr_nthw *p, unsigned int n_debug_mode); + +/* RCP */ +void rpp_lr_nthw_rcp_select(const struct rpp_lr_nthw *p, uint32_t val); +void rpp_lr_nthw_rcp_cnt(const struct rpp_lr_nthw *p, uint32_t val); +void rpp_lr_nthw_rcp_exp(const struct rpp_lr_nthw *p, uint32_t val); +void rpp_lr_nthw_rcp_flush(const struct rpp_lr_nthw *p); + +/* RCP IFR */ +void rpp_lr_nthw_ifr_rcp_select(const struct rpp_lr_nthw *p, uint32_t val); +void rpp_lr_nthw_ifr_rcp_cnt(const struct rpp_lr_nthw *p, uint32_t val); +void rpp_lr_nthw_ifr_rcp_en(const struct rpp_lr_nthw *p, uint32_t val); +void rpp_lr_nthw_ifr_rcp_mtu(const struct rpp_lr_nthw *p, uint32_t val); +void rpp_lr_nthw_ifr_rcp_flush(const struct rpp_lr_nthw *p); + +#endif /* __FLOW_NTHW_RPP_LR_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.c new file mode 100644 index 0000000000..a409e68869 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.c @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_slc.h" + +#include /* malloc */ +#include /* memset */ + +void slc_nthw_set_debug_mode(struct slc_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_slc, n_debug_mode); +} + +struct slc_nthw *slc_nthw_new(void) +{ + struct slc_nthw *p = malloc(sizeof(struct slc_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + + return p; +} + +void slc_nthw_delete(struct slc_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int slc_nthw_init(struct slc_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_SLC, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: Slc %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_slc = fpga_query_module(p_fpga, MOD_SLC, n_instance); + + /* RCP */ + p->mp_rcp_ctrl = module_get_register(p->m_slc, SLC_RCP_CTRL); + p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, SLC_RCP_CTRL_ADR); + p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, SLC_RCP_CTRL_CNT); + p->mp_rcp_data = module_get_register(p->m_slc, SLC_RCP_DATA); + p->mp_rcp_data_tail_slc_en = + register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_SLC_EN); + p->mp_rcp_data_tail_dyn = + register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_DYN); + p->mp_rcp_data_tail_ofs = + register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_OFS); + p->mp_rcp_data_pcap = register_get_field(p->mp_rcp_data, SLC_RCP_DATA_PCAP); + + return 0; +} + +/* RCP */ +void slc_nthw_rcp_select(const struct slc_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_addr, val); +} + +void slc_nthw_rcp_cnt(const struct slc_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_cnt, val); +} + +void slc_nthw_rcp_tail_slc_en(const struct slc_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_tail_slc_en, val); +} + +void slc_nthw_rcp_tail_dyn(const struct slc_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_tail_dyn, val); +} + +void slc_nthw_rcp_tail_ofs(const struct slc_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_tail_ofs, val); +} + +void slc_nthw_rcp_pcap(const struct slc_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_pcap, val); +} + +void slc_nthw_rcp_flush(const struct slc_nthw *p) +{ + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.h new file mode 100644 index 0000000000..e0f58e27e4 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_SLC_H__ +#define __FLOW_NTHW_SLC_H__ + +#include /* uint32_t */ +#include "nthw_fpga_model.h" + +struct slc_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_slc; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_addr; + nt_field_t *mp_rcp_cnt; + nt_register_t *mp_rcp_data; + + nt_field_t *mp_rcp_data_tail_slc_en; + nt_field_t *mp_rcp_data_tail_dyn; + nt_field_t *mp_rcp_data_tail_ofs; + nt_field_t *mp_rcp_data_pcap; +}; + +typedef struct slc_nthw slc_nthw_t; + +struct slc_nthw *slc_nthw_new(void); +void slc_nthw_delete(struct slc_nthw *p); +int slc_nthw_init(struct slc_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int slc_nthw_setup(struct slc_nthw *p, int n_idx, int n_idx_cnt); +void slc_nthw_set_debug_mode(struct slc_nthw *p, unsigned int n_debug_mode); + +/* RCP */ +void slc_nthw_rcp_select(const struct slc_nthw *p, uint32_t val); +void slc_nthw_rcp_cnt(const struct slc_nthw *p, uint32_t val); +void slc_nthw_rcp_tail_slc_en(const struct slc_nthw *p, uint32_t val); +void slc_nthw_rcp_tail_dyn(const struct slc_nthw *p, uint32_t val); +void slc_nthw_rcp_tail_ofs(const struct slc_nthw *p, int32_t val); +void slc_nthw_rcp_pcap(const struct slc_nthw *p, uint32_t val); +void slc_nthw_rcp_flush(const struct slc_nthw *p); + +#endif /* __FLOW_NTHW_SLC_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.c new file mode 100644 index 0000000000..f106974bdd --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.c @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_slc_lr.h" + +#include /* malloc */ +#include /* memset */ + +void slc_lr_nthw_set_debug_mode(struct slc_lr_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_slc_lr, n_debug_mode); +} + +struct slc_lr_nthw *slc_lr_nthw_new(void) +{ + struct slc_lr_nthw *p = malloc(sizeof(struct slc_lr_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + + return p; +} + +void slc_lr_nthw_delete(struct slc_lr_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int slc_lr_nthw_init(struct slc_lr_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_SLC_LR, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: Slc %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_slc_lr = fpga_query_module(p_fpga, MOD_SLC_LR, n_instance); + + /* RCP */ + p->mp_rcp_ctrl = module_get_register(p->m_slc_lr, SLC_RCP_CTRL); + p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, SLC_RCP_CTRL_ADR); + p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, SLC_RCP_CTRL_CNT); + p->mp_rcp_data = module_get_register(p->m_slc_lr, SLC_RCP_DATA); + p->mp_rcp_data_tail_slc_en = + register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_SLC_EN); + p->mp_rcp_data_tail_dyn = + register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_DYN); + p->mp_rcp_data_tail_ofs = + register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_OFS); + p->mp_rcp_data_pcap = register_get_field(p->mp_rcp_data, SLC_RCP_DATA_PCAP); + + return 0; +} + +/* RCP */ +void slc_lr_nthw_rcp_select(const struct slc_lr_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_addr, val); +} + +void slc_lr_nthw_rcp_cnt(const struct slc_lr_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_cnt, val); +} + +void slc_lr_nthw_rcp_tail_slc_en(const struct slc_lr_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_tail_slc_en, val); +} + +void slc_lr_nthw_rcp_tail_dyn(const struct slc_lr_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_tail_dyn, val); +} + +void slc_lr_nthw_rcp_tail_ofs(const struct slc_lr_nthw *p, int32_t val) +{ + field_set_val32(p->mp_rcp_data_tail_ofs, val); +} + +void slc_lr_nthw_rcp_pcap(const struct slc_lr_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_pcap, val); +} + +void slc_lr_nthw_rcp_flush(const struct slc_lr_nthw *p) +{ + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.h new file mode 100644 index 0000000000..533f2efbeb --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_SLC_LR_H__ +#define __FLOW_NTHW_SLC_LR_H__ + +#include /* uint32_t */ +#include "nthw_fpga_model.h" + +struct slc_lr_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_slc_lr; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_addr; + nt_field_t *mp_rcp_cnt; + nt_register_t *mp_rcp_data; + + nt_field_t *mp_rcp_data_tail_slc_en; + nt_field_t *mp_rcp_data_tail_dyn; + nt_field_t *mp_rcp_data_tail_ofs; + nt_field_t *mp_rcp_data_pcap; +}; + +typedef struct slc_lr_nthw slc_lr_nthw_t; + +struct slc_lr_nthw *slc_lr_nthw_new(void); +void slc_lr_nthw_delete(struct slc_lr_nthw *p); +int slc_lr_nthw_init(struct slc_lr_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int slc_lr_nthw_setup(struct slc_lr_nthw *p, int n_idx, int n_idx_cnt); +void slc_lr_nthw_set_debug_mode(struct slc_lr_nthw *p, unsigned int n_debug_mode); + +/* RCP */ +void slc_lr_nthw_rcp_select(const struct slc_lr_nthw *p, uint32_t val); +void slc_lr_nthw_rcp_cnt(const struct slc_lr_nthw *p, uint32_t val); +void slc_lr_nthw_rcp_tail_slc_en(const struct slc_lr_nthw *p, uint32_t val); +void slc_lr_nthw_rcp_tail_dyn(const struct slc_lr_nthw *p, uint32_t val); +void slc_lr_nthw_rcp_tail_ofs(const struct slc_lr_nthw *p, int32_t val); +void slc_lr_nthw_rcp_pcap(const struct slc_lr_nthw *p, uint32_t val); +void slc_lr_nthw_rcp_flush(const struct slc_lr_nthw *p); + +#endif /* __FLOW_NTHW_SLC_LR_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c new file mode 100644 index 0000000000..4d28d8cc3d --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c @@ -0,0 +1,394 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_tx_cpy.h" + +#include +#include + +void tx_cpy_nthw_set_debug_mode(struct tx_cpy_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_tx_cpy, n_debug_mode); +} + +struct tx_cpy_nthw *tx_cpy_nthw_new(void) +{ + struct tx_cpy_nthw *p = malloc(sizeof(struct tx_cpy_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + return p; +} + +void tx_cpy_nthw_delete(struct tx_cpy_nthw *p) +{ + if (p) { + free(p->m_writers); + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int tx_cpy_nthw_init(struct tx_cpy_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_TX_CPY, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: TxCpy %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_tx_cpy = fpga_query_module(p_fpga, MOD_TX_CPY, n_instance); + + const int writers_cnt = + fpga_get_product_param(p->mp_fpga, NT_TX_CPY_WRITERS, 0); + if (writers_cnt < 1) + return -1; + + p->m_writers_cnt = (unsigned int)writers_cnt; + p->m_writers = calloc(p->m_writers_cnt, sizeof(struct tx_cpy_writers_s)); + if (p->m_writers == NULL) + return -1; + + const int variant = + fpga_get_product_param(p->mp_fpga, NT_TX_CPY_VARIANT, 0); + + switch (p->m_writers_cnt) { + default: + case 6: + p->m_writers[5].mp_writer_ctrl = + module_get_register(p->m_tx_cpy, CPY_WRITER5_CTRL); + p->m_writers[5].mp_writer_ctrl_addr = + register_get_field(p->m_writers[5].mp_writer_ctrl, + CPY_WRITER5_CTRL_ADR); + p->m_writers[5].mp_writer_ctrl_cnt = + register_get_field(p->m_writers[5].mp_writer_ctrl, + CPY_WRITER5_CTRL_CNT); + p->m_writers[5].mp_writer_data = + module_get_register(p->m_tx_cpy, CPY_WRITER5_DATA); + p->m_writers[5].mp_writer_data_reader_select = + register_get_field(p->m_writers[5].mp_writer_data, + CPY_WRITER5_DATA_READER_SELECT); + p->m_writers[5].mp_writer_data_dyn = + register_get_field(p->m_writers[5].mp_writer_data, + CPY_WRITER5_DATA_DYN); + p->m_writers[5].mp_writer_data_ofs = + register_get_field(p->m_writers[5].mp_writer_data, + CPY_WRITER5_DATA_OFS); + p->m_writers[5].mp_writer_data_len = + register_get_field(p->m_writers[5].mp_writer_data, + CPY_WRITER5_DATA_LEN); + if (variant != 0) { + p->m_writers[5].mp_writer_data_mask_pointer = + register_get_field(p->m_writers[5].mp_writer_data, + CPY_WRITER5_DATA_MASK_POINTER); + p->m_writers[5].mp_writer_mask_ctrl = + module_get_register(p->m_tx_cpy, CPY_WRITER5_MASK_CTRL); + p->m_writers[5].mp_writer_mask_ctrl_addr = + register_get_field(p->m_writers[5].mp_writer_mask_ctrl, + CPY_WRITER5_MASK_CTRL_ADR); + p->m_writers[5].mp_writer_mask_ctrl_cnt = + register_get_field(p->m_writers[5].mp_writer_mask_ctrl, + CPY_WRITER5_MASK_CTRL_CNT); + p->m_writers[5].mp_writer_mask_data = + module_get_register(p->m_tx_cpy, CPY_WRITER5_MASK_DATA); + p->m_writers[5].mp_writer_mask_data_byte_mask = + register_get_field(p->m_writers[5].mp_writer_mask_data, + CPY_WRITER5_MASK_DATA_BYTE_MASK); + } + /* Fallthrough */ + case 5: + p->m_writers[4].mp_writer_ctrl = + module_get_register(p->m_tx_cpy, CPY_WRITER4_CTRL); + p->m_writers[4].mp_writer_ctrl_addr = + register_get_field(p->m_writers[4].mp_writer_ctrl, CPY_WRITER4_CTRL_ADR); + p->m_writers[4].mp_writer_ctrl_cnt = + register_get_field(p->m_writers[4].mp_writer_ctrl, CPY_WRITER4_CTRL_CNT); + p->m_writers[4].mp_writer_data = + module_get_register(p->m_tx_cpy, CPY_WRITER4_DATA); + p->m_writers[4].mp_writer_data_reader_select = + register_get_field(p->m_writers[4].mp_writer_data, + CPY_WRITER4_DATA_READER_SELECT); + p->m_writers[4].mp_writer_data_dyn = + register_get_field(p->m_writers[4].mp_writer_data, CPY_WRITER4_DATA_DYN); + p->m_writers[4].mp_writer_data_ofs = + register_get_field(p->m_writers[4].mp_writer_data, CPY_WRITER4_DATA_OFS); + p->m_writers[4].mp_writer_data_len = + register_get_field(p->m_writers[4].mp_writer_data, CPY_WRITER4_DATA_LEN); + if (variant != 0) { + p->m_writers[4].mp_writer_data_mask_pointer = + register_get_field(p->m_writers[4].mp_writer_data, + CPY_WRITER4_DATA_MASK_POINTER); + p->m_writers[4].mp_writer_mask_ctrl = + module_get_register(p->m_tx_cpy, CPY_WRITER4_MASK_CTRL); + p->m_writers[4].mp_writer_mask_ctrl_addr = + register_get_field(p->m_writers[4].mp_writer_mask_ctrl, + CPY_WRITER4_MASK_CTRL_ADR); + p->m_writers[4].mp_writer_mask_ctrl_cnt = + register_get_field(p->m_writers[4].mp_writer_mask_ctrl, + CPY_WRITER4_MASK_CTRL_CNT); + p->m_writers[4].mp_writer_mask_data = + module_get_register(p->m_tx_cpy, CPY_WRITER4_MASK_DATA); + p->m_writers[4].mp_writer_mask_data_byte_mask = + register_get_field(p->m_writers[4].mp_writer_mask_data, + CPY_WRITER4_MASK_DATA_BYTE_MASK); + } + /* Fallthrough */ + case 4: + p->m_writers[3].mp_writer_ctrl = + module_get_register(p->m_tx_cpy, CPY_WRITER3_CTRL); + p->m_writers[3].mp_writer_ctrl_addr = + register_get_field(p->m_writers[3].mp_writer_ctrl, CPY_WRITER3_CTRL_ADR); + p->m_writers[3].mp_writer_ctrl_cnt = + register_get_field(p->m_writers[3].mp_writer_ctrl, CPY_WRITER3_CTRL_CNT); + p->m_writers[3].mp_writer_data = + module_get_register(p->m_tx_cpy, CPY_WRITER3_DATA); + p->m_writers[3].mp_writer_data_reader_select = + register_get_field(p->m_writers[3].mp_writer_data, + CPY_WRITER3_DATA_READER_SELECT); + p->m_writers[3].mp_writer_data_dyn = + register_get_field(p->m_writers[3].mp_writer_data, CPY_WRITER3_DATA_DYN); + p->m_writers[3].mp_writer_data_ofs = + register_get_field(p->m_writers[3].mp_writer_data, CPY_WRITER3_DATA_OFS); + p->m_writers[3].mp_writer_data_len = + register_get_field(p->m_writers[3].mp_writer_data, CPY_WRITER3_DATA_LEN); + if (variant != 0) { + p->m_writers[3].mp_writer_data_mask_pointer = + register_get_field(p->m_writers[3].mp_writer_data, + CPY_WRITER3_DATA_MASK_POINTER); + p->m_writers[3].mp_writer_mask_ctrl = + module_get_register(p->m_tx_cpy, CPY_WRITER3_MASK_CTRL); + p->m_writers[3].mp_writer_mask_ctrl_addr = + register_get_field(p->m_writers[3].mp_writer_mask_ctrl, + CPY_WRITER3_MASK_CTRL_ADR); + p->m_writers[3].mp_writer_mask_ctrl_cnt = + register_get_field(p->m_writers[3].mp_writer_mask_ctrl, + CPY_WRITER3_MASK_CTRL_CNT); + p->m_writers[3].mp_writer_mask_data = + module_get_register(p->m_tx_cpy, CPY_WRITER3_MASK_DATA); + p->m_writers[3].mp_writer_mask_data_byte_mask = + register_get_field(p->m_writers[3].mp_writer_mask_data, + CPY_WRITER3_MASK_DATA_BYTE_MASK); + } + /* Fallthrough */ + case 3: + p->m_writers[2].mp_writer_ctrl = + module_get_register(p->m_tx_cpy, CPY_WRITER2_CTRL); + p->m_writers[2].mp_writer_ctrl_addr = + register_get_field(p->m_writers[2].mp_writer_ctrl, CPY_WRITER2_CTRL_ADR); + p->m_writers[2].mp_writer_ctrl_cnt = + register_get_field(p->m_writers[2].mp_writer_ctrl, CPY_WRITER2_CTRL_CNT); + p->m_writers[2].mp_writer_data = + module_get_register(p->m_tx_cpy, CPY_WRITER2_DATA); + p->m_writers[2].mp_writer_data_reader_select = + register_get_field(p->m_writers[2].mp_writer_data, + CPY_WRITER2_DATA_READER_SELECT); + p->m_writers[2].mp_writer_data_dyn = + register_get_field(p->m_writers[2].mp_writer_data, CPY_WRITER2_DATA_DYN); + p->m_writers[2].mp_writer_data_ofs = + register_get_field(p->m_writers[2].mp_writer_data, CPY_WRITER2_DATA_OFS); + p->m_writers[2].mp_writer_data_len = + register_get_field(p->m_writers[2].mp_writer_data, CPY_WRITER2_DATA_LEN); + if (variant != 0) { + p->m_writers[2].mp_writer_data_mask_pointer = + register_get_field(p->m_writers[2].mp_writer_data, + CPY_WRITER2_DATA_MASK_POINTER); + p->m_writers[2].mp_writer_mask_ctrl = + module_get_register(p->m_tx_cpy, CPY_WRITER2_MASK_CTRL); + p->m_writers[2].mp_writer_mask_ctrl_addr = + register_get_field(p->m_writers[2].mp_writer_mask_ctrl, + CPY_WRITER2_MASK_CTRL_ADR); + p->m_writers[2].mp_writer_mask_ctrl_cnt = + register_get_field(p->m_writers[2].mp_writer_mask_ctrl, + CPY_WRITER2_MASK_CTRL_CNT); + p->m_writers[2].mp_writer_mask_data = + module_get_register(p->m_tx_cpy, CPY_WRITER2_MASK_DATA); + p->m_writers[2].mp_writer_mask_data_byte_mask = + register_get_field(p->m_writers[2].mp_writer_mask_data, + CPY_WRITER2_MASK_DATA_BYTE_MASK); + } + /* Fallthrough */ + case 2: + p->m_writers[1].mp_writer_ctrl = + module_get_register(p->m_tx_cpy, CPY_WRITER1_CTRL); + p->m_writers[1].mp_writer_ctrl_addr = + register_get_field(p->m_writers[1].mp_writer_ctrl, CPY_WRITER1_CTRL_ADR); + p->m_writers[1].mp_writer_ctrl_cnt = + register_get_field(p->m_writers[1].mp_writer_ctrl, CPY_WRITER1_CTRL_CNT); + p->m_writers[1].mp_writer_data = + module_get_register(p->m_tx_cpy, CPY_WRITER1_DATA); + p->m_writers[1].mp_writer_data_reader_select = + register_get_field(p->m_writers[1].mp_writer_data, + CPY_WRITER1_DATA_READER_SELECT); + p->m_writers[1].mp_writer_data_dyn = + register_get_field(p->m_writers[1].mp_writer_data, CPY_WRITER1_DATA_DYN); + p->m_writers[1].mp_writer_data_ofs = + register_get_field(p->m_writers[1].mp_writer_data, CPY_WRITER1_DATA_OFS); + p->m_writers[1].mp_writer_data_len = + register_get_field(p->m_writers[1].mp_writer_data, CPY_WRITER1_DATA_LEN); + if (variant != 0) { + p->m_writers[1].mp_writer_data_mask_pointer = + register_get_field(p->m_writers[1].mp_writer_data, + CPY_WRITER1_DATA_MASK_POINTER); + p->m_writers[1].mp_writer_mask_ctrl = + module_get_register(p->m_tx_cpy, CPY_WRITER1_MASK_CTRL); + p->m_writers[1].mp_writer_mask_ctrl_addr = + register_get_field(p->m_writers[1].mp_writer_mask_ctrl, + CPY_WRITER1_MASK_CTRL_ADR); + p->m_writers[1].mp_writer_mask_ctrl_cnt = + register_get_field(p->m_writers[1].mp_writer_mask_ctrl, + CPY_WRITER1_MASK_CTRL_CNT); + p->m_writers[1].mp_writer_mask_data = + module_get_register(p->m_tx_cpy, CPY_WRITER1_MASK_DATA); + p->m_writers[1].mp_writer_mask_data_byte_mask = + register_get_field(p->m_writers[1].mp_writer_mask_data, + CPY_WRITER1_MASK_DATA_BYTE_MASK); + } + /* Fallthrough */ + case 1: + p->m_writers[0].mp_writer_ctrl = + module_get_register(p->m_tx_cpy, CPY_WRITER0_CTRL); + p->m_writers[0].mp_writer_ctrl_addr = + register_get_field(p->m_writers[0].mp_writer_ctrl, CPY_WRITER0_CTRL_ADR); + p->m_writers[0].mp_writer_ctrl_cnt = + register_get_field(p->m_writers[0].mp_writer_ctrl, CPY_WRITER0_CTRL_CNT); + p->m_writers[0].mp_writer_data = + module_get_register(p->m_tx_cpy, CPY_WRITER0_DATA); + p->m_writers[0].mp_writer_data_reader_select = + register_get_field(p->m_writers[0].mp_writer_data, + CPY_WRITER0_DATA_READER_SELECT); + p->m_writers[0].mp_writer_data_dyn = + register_get_field(p->m_writers[0].mp_writer_data, CPY_WRITER0_DATA_DYN); + p->m_writers[0].mp_writer_data_ofs = + register_get_field(p->m_writers[0].mp_writer_data, CPY_WRITER0_DATA_OFS); + p->m_writers[0].mp_writer_data_len = + register_get_field(p->m_writers[0].mp_writer_data, CPY_WRITER0_DATA_LEN); + if (variant != 0) { + p->m_writers[0].mp_writer_data_mask_pointer = + register_get_field(p->m_writers[0].mp_writer_data, + CPY_WRITER0_DATA_MASK_POINTER); + p->m_writers[0].mp_writer_mask_ctrl = + module_get_register(p->m_tx_cpy, CPY_WRITER0_MASK_CTRL); + p->m_writers[0].mp_writer_mask_ctrl_addr = + register_get_field(p->m_writers[0].mp_writer_mask_ctrl, + CPY_WRITER0_MASK_CTRL_ADR); + p->m_writers[0].mp_writer_mask_ctrl_cnt = + register_get_field(p->m_writers[0].mp_writer_mask_ctrl, + CPY_WRITER0_MASK_CTRL_CNT); + p->m_writers[0].mp_writer_mask_data = + module_get_register(p->m_tx_cpy, CPY_WRITER0_MASK_DATA); + p->m_writers[0].mp_writer_mask_data_byte_mask = + register_get_field(p->m_writers[0].mp_writer_mask_data, + CPY_WRITER0_MASK_DATA_BYTE_MASK); + } + break; + case 0: + return -1; + } + + return 0; +} + +void tx_cpy_nthw_writer_select(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val) +{ + assert(index < p->m_writers_cnt); + field_set_val32(p->m_writers[index].mp_writer_ctrl_addr, val); +} + +void tx_cpy_nthw_writer_cnt(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val) +{ + assert(index < p->m_writers_cnt); + field_set_val32(p->m_writers[index].mp_writer_ctrl_cnt, val); +} + +void tx_cpy_nthw_writer_reader_select(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val) +{ + assert(index < p->m_writers_cnt); + field_set_val32(p->m_writers[index].mp_writer_data_reader_select, val); +} + +void tx_cpy_nthw_writer_dyn(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val) +{ + assert(index < p->m_writers_cnt); + field_set_val32(p->m_writers[index].mp_writer_data_dyn, val); +} + +void tx_cpy_nthw_writer_ofs(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val) +{ + assert(index < p->m_writers_cnt); + field_set_val32(p->m_writers[index].mp_writer_data_ofs, val); +} + +void tx_cpy_nthw_writer_len(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val) +{ + assert(index < p->m_writers_cnt); + field_set_val32(p->m_writers[index].mp_writer_data_len, val); +} + +void tx_cpy_nthw_writer_mask_pointer(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val) +{ + assert(index < p->m_writers_cnt); + assert(p->m_writers[index].mp_writer_data_mask_pointer); + field_set_val32(p->m_writers[index].mp_writer_data_mask_pointer, val); +} + +void tx_cpy_nthw_writer_flush(const struct tx_cpy_nthw *p, unsigned int index) +{ + assert(index < p->m_writers_cnt); + register_flush(p->m_writers[index].mp_writer_ctrl, 1); + register_flush(p->m_writers[index].mp_writer_data, 1); +} + +void tx_cpy_nthw_writer_mask_select(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val) +{ + assert(index < p->m_writers_cnt); + assert(p->m_writers[index].mp_writer_mask_ctrl_addr); + field_set_val32(p->m_writers[index].mp_writer_mask_ctrl_addr, val); +} + +void tx_cpy_nthw_writer_mask_cnt(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val) +{ + assert(index < p->m_writers_cnt); + assert(p->m_writers[index].mp_writer_mask_ctrl_cnt); + field_set_val32(p->m_writers[index].mp_writer_mask_ctrl_cnt, val); +} + +void tx_cpy_nthw_writer_mask(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val) +{ + assert(index < p->m_writers_cnt); + assert(p->m_writers[index].mp_writer_mask_data_byte_mask); + field_set_val32(p->m_writers[index].mp_writer_mask_data_byte_mask, val); +} + +void tx_cpy_nthw_writer_mask_flush(const struct tx_cpy_nthw *p, unsigned int index) +{ + assert(index < p->m_writers_cnt); + assert(p->m_writers[index].mp_writer_mask_ctrl); + assert(p->m_writers[index].mp_writer_mask_data); + register_flush(p->m_writers[index].mp_writer_mask_ctrl, 1); + register_flush(p->m_writers[index].mp_writer_mask_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h new file mode 100644 index 0000000000..f97983b29a --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_TX_CPY_H__ +#define __FLOW_NTHW_TX_CPY_H__ + +#include +#include "nthw_fpga_model.h" + +struct tx_cpy_writers_s { + nt_register_t *mp_writer_ctrl; + nt_field_t *mp_writer_ctrl_addr; + nt_field_t *mp_writer_ctrl_cnt; + + nt_register_t *mp_writer_data; + nt_field_t *mp_writer_data_reader_select; + nt_field_t *mp_writer_data_dyn; + nt_field_t *mp_writer_data_ofs; + nt_field_t *mp_writer_data_len; + nt_field_t *mp_writer_data_mask_pointer; + + nt_register_t *mp_writer_mask_ctrl; + nt_field_t *mp_writer_mask_ctrl_addr; + nt_field_t *mp_writer_mask_ctrl_cnt; + + nt_register_t *mp_writer_mask_data; + nt_field_t *mp_writer_mask_data_byte_mask; +}; + +struct tx_cpy_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_tx_cpy; + + unsigned int m_writers_cnt; + struct tx_cpy_writers_s *m_writers; +}; + +struct tx_cpy_nthw *tx_cpy_nthw_new(void); +void tx_cpy_nthw_delete(struct tx_cpy_nthw *p); +int tx_cpy_nthw_init(struct tx_cpy_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int tx_cpy_nthw_setup(struct tx_cpy_nthw *p, int n_idx, int n_idx_cnt); +void tx_cpy_nthw_set_debug_mode(struct tx_cpy_nthw *p, unsigned int n_debug_mode); + +void tx_cpy_nthw_writer_select(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val); +void tx_cpy_nthw_writer_cnt(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val); +void tx_cpy_nthw_writer_reader_select(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val); +void tx_cpy_nthw_writer_dyn(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val); +void tx_cpy_nthw_writer_ofs(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val); +void tx_cpy_nthw_writer_len(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val); +void tx_cpy_nthw_writer_mask_pointer(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val); +void tx_cpy_nthw_writer_flush(const struct tx_cpy_nthw *p, unsigned int index); + +void tx_cpy_nthw_writer_mask_select(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val); +void tx_cpy_nthw_writer_mask_cnt(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val); +void tx_cpy_nthw_writer_mask(const struct tx_cpy_nthw *p, unsigned int index, + uint32_t val); +void tx_cpy_nthw_writer_mask_flush(const struct tx_cpy_nthw *p, unsigned int index); + +#endif /* __FLOW_NTHW_TX_CPY_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.c new file mode 100644 index 0000000000..998c3613ee --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.c @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_tx_ins.h" + +#include +#include + +void tx_ins_nthw_set_debug_mode(struct tx_ins_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_tx_ins, n_debug_mode); +} + +struct tx_ins_nthw *tx_ins_nthw_new(void) +{ + struct tx_ins_nthw *p = malloc(sizeof(struct tx_ins_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + return p; +} + +void tx_ins_nthw_delete(struct tx_ins_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int tx_ins_nthw_init(struct tx_ins_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_TX_INS, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: TxIns %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_tx_ins = fpga_query_module(p_fpga, MOD_TX_INS, n_instance); + + p->mp_rcp_ctrl = module_get_register(p->m_tx_ins, INS_RCP_CTRL); + p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, INS_RCP_CTRL_ADR); + p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, INS_RCP_CTRL_CNT); + p->mp_rcp_data = module_get_register(p->m_tx_ins, INS_RCP_DATA); + p->mp_rcp_data_dyn = register_get_field(p->mp_rcp_data, INS_RCP_DATA_DYN); + p->mp_rcp_data_ofs = register_get_field(p->mp_rcp_data, INS_RCP_DATA_OFS); + p->mp_rcp_data_len = register_get_field(p->mp_rcp_data, INS_RCP_DATA_LEN); + + return 0; +} + +void tx_ins_nthw_rcp_select(const struct tx_ins_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_addr, val); +} + +void tx_ins_nthw_rcp_cnt(const struct tx_ins_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_cnt, val); +} + +void tx_ins_nthw_rcp_dyn(const struct tx_ins_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_dyn, val); +} + +void tx_ins_nthw_rcp_ofs(const struct tx_ins_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ofs, val); +} + +void tx_ins_nthw_rcp_len(const struct tx_ins_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len, val); +} + +void tx_ins_nthw_rcp_flush(const struct tx_ins_nthw *p) +{ + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.h new file mode 100644 index 0000000000..813bd30c62 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_TX_INS_H__ +#define __FLOW_NTHW_TX_INS_H__ + +#include +#include "nthw_fpga_model.h" + +struct tx_ins_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_tx_ins; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_addr; + nt_field_t *mp_rcp_cnt; + + nt_register_t *mp_rcp_data; + nt_field_t *mp_rcp_data_dyn; + nt_field_t *mp_rcp_data_ofs; + nt_field_t *mp_rcp_data_len; +}; + +struct tx_ins_nthw *tx_ins_nthw_new(void); +void tx_ins_nthw_delete(struct tx_ins_nthw *p); +int tx_ins_nthw_init(struct tx_ins_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int tx_ins_nthw_setup(struct tx_ins_nthw *p, int n_idx, int n_idx_cnt); +void tx_ins_nthw_set_debug_mode(struct tx_ins_nthw *p, unsigned int n_debug_mode); + +/* RCP */ +void tx_ins_nthw_rcp_select(const struct tx_ins_nthw *p, uint32_t val); +void tx_ins_nthw_rcp_cnt(const struct tx_ins_nthw *p, uint32_t val); +void tx_ins_nthw_rcp_dyn(const struct tx_ins_nthw *p, uint32_t val); +void tx_ins_nthw_rcp_ofs(const struct tx_ins_nthw *p, uint32_t val); +void tx_ins_nthw_rcp_len(const struct tx_ins_nthw *p, uint32_t val); +void tx_ins_nthw_rcp_flush(const struct tx_ins_nthw *p); + +#endif /* __FLOW_NTHW_TX_INS_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c new file mode 100644 index 0000000000..5e7e26f74d --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "flow_nthw_tx_rpl.h" + +#include +#include + +void tx_rpl_nthw_set_debug_mode(struct tx_rpl_nthw *p, unsigned int n_debug_mode) +{ + module_set_debug_mode(p->m_tx_rpl, n_debug_mode); +} + +struct tx_rpl_nthw *tx_rpl_nthw_new(void) +{ + struct tx_rpl_nthw *p = malloc(sizeof(struct tx_rpl_nthw)); + + if (p) + (void)memset(p, 0, sizeof(*p)); + return p; +} + +void tx_rpl_nthw_delete(struct tx_rpl_nthw *p) +{ + if (p) { + (void)memset(p, 0, sizeof(*p)); + free(p); + } +} + +int tx_rpl_nthw_init(struct tx_rpl_nthw *p, nt_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_TX_RPL, n_instance); + + assert(n_instance >= 0 && n_instance < 256); + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: TxRpl %d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->m_physical_adapter_no = (uint8_t)n_instance; + p->m_tx_rpl = fpga_query_module(p_fpga, MOD_TX_RPL, n_instance); + + p->mp_rcp_ctrl = module_get_register(p->m_tx_rpl, RPL_RCP_CTRL); + p->mp_rcp_ctrl_addr = register_get_field(p->mp_rcp_ctrl, RPL_RCP_CTRL_ADR); + p->mp_rcp_ctrl_cnt = register_get_field(p->mp_rcp_ctrl, RPL_RCP_CTRL_CNT); + p->mp_rcp_data = module_get_register(p->m_tx_rpl, RPL_RCP_DATA); + p->mp_rcp_data_dyn = register_get_field(p->mp_rcp_data, RPL_RCP_DATA_DYN); + p->mp_rcp_data_ofs = register_get_field(p->mp_rcp_data, RPL_RCP_DATA_OFS); + p->mp_rcp_data_len = register_get_field(p->mp_rcp_data, RPL_RCP_DATA_LEN); + p->mp_rcp_data_rpl_ptr = + register_get_field(p->mp_rcp_data, RPL_RCP_DATA_RPL_PTR); + p->mp_rcp_data_ext_prio = + register_get_field(p->mp_rcp_data, RPL_RCP_DATA_EXT_PRIO); + + p->mp_ext_ctrl = module_get_register(p->m_tx_rpl, RPL_EXT_CTRL); + p->mp_ext_ctrl_addr = register_get_field(p->mp_ext_ctrl, RPL_EXT_CTRL_ADR); + p->mp_ext_ctrl_cnt = register_get_field(p->mp_ext_ctrl, RPL_EXT_CTRL_CNT); + p->mp_ext_data = module_get_register(p->m_tx_rpl, RPL_EXT_DATA); + p->mp_ext_data_rpl_ptr = + register_get_field(p->mp_ext_data, RPL_EXT_DATA_RPL_PTR); + + p->mp_rpl_ctrl = module_get_register(p->m_tx_rpl, RPL_RPL_CTRL); + p->mp_rpl_ctrl_addr = register_get_field(p->mp_rpl_ctrl, RPL_RPL_CTRL_ADR); + p->mp_rpl_ctrl_cnt = register_get_field(p->mp_rpl_ctrl, RPL_RPL_CTRL_CNT); + p->mp_rpl_data = module_get_register(p->m_tx_rpl, RPL_RPL_DATA); + p->mp_rpl_data_value = register_get_field(p->mp_rpl_data, RPL_RPL_DATA_VALUE); + + return 0; +} + +void tx_rpl_nthw_rcp_select(const struct tx_rpl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_ctrl_addr, val); +} + +void tx_rpl_nthw_rcp_cnt(const struct tx_rpl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_ctrl_cnt, val); +} + +void tx_rpl_nthw_rcp_dyn(const struct tx_rpl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_dyn, val); +} + +void tx_rpl_nthw_rcp_ofs(const struct tx_rpl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ofs, val); +} + +void tx_rpl_nthw_rcp_len(const struct tx_rpl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_len, val); +} + +void tx_rpl_nthw_rcp_rpl_ptr(const struct tx_rpl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_rpl_ptr, val); +} + +void tx_rpl_nthw_rcp_ext_prio(const struct tx_rpl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rcp_data_ext_prio, val); +} + +void tx_rpl_nthw_rcp_flush(const struct tx_rpl_nthw *p) +{ + register_flush(p->mp_rcp_ctrl, 1); + register_flush(p->mp_rcp_data, 1); +} + +void tx_rpl_nthw_ext_select(const struct tx_rpl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_ext_ctrl_addr, val); +} + +void tx_rpl_nthw_ext_cnt(const struct tx_rpl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_ext_ctrl_cnt, val); +} + +void tx_rpl_nthw_ext_rpl_ptr(const struct tx_rpl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_ext_data_rpl_ptr, val); +} + +void tx_rpl_nthw_ext_flush(const struct tx_rpl_nthw *p) +{ + register_flush(p->mp_ext_ctrl, 1); + register_flush(p->mp_ext_data, 1); +} + +void tx_rpl_nthw_rpl_select(const struct tx_rpl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rpl_ctrl_addr, val); +} + +void tx_rpl_nthw_rpl_cnt(const struct tx_rpl_nthw *p, uint32_t val) +{ + field_set_val32(p->mp_rpl_ctrl_cnt, val); +} + +void tx_rpl_nthw_rpl_value(const struct tx_rpl_nthw *p, const uint32_t *val) +{ + field_set_val(p->mp_rpl_data_value, val, 4); +} + +void tx_rpl_nthw_rpl_flush(const struct tx_rpl_nthw *p) +{ + register_flush(p->mp_rpl_ctrl, 1); + register_flush(p->mp_rpl_data, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h new file mode 100644 index 0000000000..e5f724361b --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_NTHW_TX_RPL_H__ +#define __FLOW_NTHW_TX_RPL_H__ + +#include +#include "nthw_fpga_model.h" + +struct tx_rpl_nthw { + uint8_t m_physical_adapter_no; + nt_fpga_t *mp_fpga; + + nt_module_t *m_tx_rpl; + + nt_register_t *mp_rcp_ctrl; + nt_field_t *mp_rcp_ctrl_addr; + nt_field_t *mp_rcp_ctrl_cnt; + + nt_register_t *mp_rcp_data; + nt_field_t *mp_rcp_data_dyn; + nt_field_t *mp_rcp_data_ofs; + nt_field_t *mp_rcp_data_len; + nt_field_t *mp_rcp_data_rpl_ptr; + nt_field_t *mp_rcp_data_ext_prio; + + nt_register_t *mp_ext_ctrl; + nt_field_t *mp_ext_ctrl_addr; + nt_field_t *mp_ext_ctrl_cnt; + + nt_register_t *mp_ext_data; + nt_field_t *mp_ext_data_rpl_ptr; + + nt_register_t *mp_rpl_ctrl; + nt_field_t *mp_rpl_ctrl_addr; + nt_field_t *mp_rpl_ctrl_cnt; + + nt_register_t *mp_rpl_data; + nt_field_t *mp_rpl_data_value; +}; + +struct tx_rpl_nthw *tx_rpl_nthw_new(void); +void tx_rpl_nthw_delete(struct tx_rpl_nthw *p); +int tx_rpl_nthw_init(struct tx_rpl_nthw *p, nt_fpga_t *p_fpga, int n_instance); + +int tx_rpl_nthw_setup(struct tx_rpl_nthw *p, int n_idx, int n_idx_cnt); +void tx_rpl_nthw_set_debug_mode(struct tx_rpl_nthw *p, unsigned int n_debug_mode); + +/* RCP */ +void tx_rpl_nthw_rcp_select(const struct tx_rpl_nthw *p, uint32_t val); +void tx_rpl_nthw_rcp_cnt(const struct tx_rpl_nthw *p, uint32_t val); +void tx_rpl_nthw_rcp_dyn(const struct tx_rpl_nthw *p, uint32_t val); +void tx_rpl_nthw_rcp_ofs(const struct tx_rpl_nthw *p, uint32_t val); +void tx_rpl_nthw_rcp_len(const struct tx_rpl_nthw *p, uint32_t val); +void tx_rpl_nthw_rcp_rpl_ptr(const struct tx_rpl_nthw *p, uint32_t val); +void tx_rpl_nthw_rcp_ext_prio(const struct tx_rpl_nthw *p, uint32_t val); +void tx_rpl_nthw_rcp_flush(const struct tx_rpl_nthw *p); + +void tx_rpl_nthw_ext_select(const struct tx_rpl_nthw *p, uint32_t val); +void tx_rpl_nthw_ext_cnt(const struct tx_rpl_nthw *p, uint32_t val); +void tx_rpl_nthw_ext_rpl_ptr(const struct tx_rpl_nthw *p, uint32_t val); +void tx_rpl_nthw_ext_flush(const struct tx_rpl_nthw *p); + +void tx_rpl_nthw_rpl_select(const struct tx_rpl_nthw *p, uint32_t val); +void tx_rpl_nthw_rpl_cnt(const struct tx_rpl_nthw *p, uint32_t val); +void tx_rpl_nthw_rpl_value(const struct tx_rpl_nthw *p, const uint32_t *val); +void tx_rpl_nthw_rpl_flush(const struct tx_rpl_nthw *p); + +#endif /* __FLOW_NTHW_TX_RPL_H__ */ From patchwork Mon Aug 21 13:54:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mykola Kostenok X-Patchwork-Id: 130585 X-Patchwork-Delegate: thomas@monjalon.net 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 8B7CA430C1; Mon, 21 Aug 2023 15:56:18 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6D69343290; Mon, 21 Aug 2023 15:54:52 +0200 (CEST) Received: from egress-ip4a.ess.de.barracuda.com (egress-ip4a.ess.de.barracuda.com [18.184.203.227]) by mails.dpdk.org (Postfix) with ESMTP id B5FD34325F for ; Mon, 21 Aug 2023 15:54:47 +0200 (CEST) Received: from EUR04-DB3-obe.outbound.protection.outlook.com (mail-db3eur04lp2058.outbound.protection.outlook.com [104.47.12.58]) by mx-outbound13-194.eu-central-1a.ess.aws.cudaops.com (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 21 Aug 2023 13:54:46 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=KXbqqhL9NwjzreRmtCIJ+LQrWVcLldpVmt5U333V5JYM+EoFogS17T2z409KOpwgfQWueQKLIcI3z5CjpEZumc7wTGayWq67qokJlSHJwUbbMWXaRtRkVP67WZ4MCkg/IlADwctqoxHYzK1GOROUqDr/KzOKbxGeJnwGRX5CjeJi34hxlTrCHNgtu/ev7BIGBGIgF2P5dUoR6pHF7gr4s2oIp2e1CZPY72tnDAlJjtF4SXW1hHa8nw4wZ8e9cqknIL9GDKyW8Myc2qs1noTcrF0aT7EtZ4clYHJ5AX50jdBXIwqnLYESesvzEpuhFqBm+YaZXpWPvCjzk4lYUV4ccQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=BJGBbX/YN6mvX7XNCdGIyRByuDIDrJpPNLN3y9eEUUc=; b=FdFUlvZqWMS5jIeGalW2zKNkSYayFmZ1R3jufLKcF4leoDezkoFw8UNBBg3LfP2lM4HN3QuVmk5PI7MfqwgADBdH4u1oFkAwH19+OFr8bpQ0m4GyhWv9mNFuAIbwZCmLCaBRofx7RvrtBYE13MTzaZ4q1VQ9oa7XshR+d4rHXa6DmBhVYUiO8CFrIRIOhuSNSiolhT61LbvsFu8uaWYqR0RXf81aYp+A1eEH2YTsZupicGqa8hF6UJUKCWGDn35p+oPIZeq2XpCRMz+pRopYIo+APFXc/zb/QSEkM7v5jAF5PCgVd4nTEC0eW3DmeCtIChuLONNSJ2QIgdqLjfhsVg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=fail (sender ip is 178.72.21.4) smtp.rcpttodomain=dpdk.org smtp.mailfrom=napatech.com; dmarc=fail (p=none sp=none pct=100) action=none header.from=napatech.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=napatech.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=BJGBbX/YN6mvX7XNCdGIyRByuDIDrJpPNLN3y9eEUUc=; b=D0QW3SF+Bn848uBLGeUHAmO3qbCfIi4d4UjTQXL5v2qRTHSM8YSSXhX0SRbiSgqRx/1vrtz/H7YAci4pBaHX76jrhxnLUlKKansF9nM7ZyQT6O6uZoMYgEMushs2JRE5GbsXv+7dAuBAikIpwCbchFu/LeYoJoXexaRsdCk8reU= Received: from DB8PR04CA0020.eurprd04.prod.outlook.com (2603:10a6:10:110::30) by AM9P190MB1329.EURP190.PROD.OUTLOOK.COM (2603:10a6:20b:26a::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.24; Mon, 21 Aug 2023 13:54:29 +0000 Received: from DU2PEPF0001E9C5.eurprd03.prod.outlook.com (2603:10a6:10:110:cafe::72) by DB8PR04CA0020.outlook.office365.com (2603:10a6:10:110::30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.20 via Frontend Transport; Mon, 21 Aug 2023 13:54:29 +0000 X-MS-Exchange-Authentication-Results: spf=fail (sender IP is 178.72.21.4) smtp.mailfrom=napatech.com; dkim=none (message not signed) header.d=none;dmarc=fail action=none header.from=napatech.com; Received-SPF: Fail (protection.outlook.com: domain of napatech.com does not designate 178.72.21.4 as permitted sender) receiver=protection.outlook.com; client-ip=178.72.21.4; helo=localhost.localdomain.com; Received: from localhost.localdomain.com (178.72.21.4) by DU2PEPF0001E9C5.mail.protection.outlook.com (10.167.8.74) with Microsoft SMTP Server id 15.20.6699.14 via Frontend Transport; Mon, 21 Aug 2023 13:54:29 +0000 From: Mykola Kostenok To: dev@dpdk.org, mko-plv@napatech.com Cc: ckm@napatech.com Subject: [PATCH v6 5/8] net/ntnic: adds FPGA abstraction layer Date: Mon, 21 Aug 2023 15:54:23 +0200 Message-Id: <20230821135426.1478754-5-mko-plv@napatech.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20230821135426.1478754-1-mko-plv@napatech.com> References: <20230816132552.2483752-1-mko-plv@napatech.com> <20230821135426.1478754-1-mko-plv@napatech.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU2PEPF0001E9C5:EE_|AM9P190MB1329:EE_ X-MS-Office365-Filtering-Correlation-Id: 0258555b-4e97-4784-05ec-08dba24e23f9 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 1j13f4NV0UV92YnTje2oMJ5xzl/2eqo97Ugh2f0H2LerJeW7r2JaFKwotdhw436v9lBBIbCZdmPRSJ1OJHcuqN3EXgiqeJhfQqT5CtQ3ymhEUf0rR1GJk9znCUB+wGA/p22IFd8epvFY2DbubTv2N9O/WilH3+EMR+jS31zfCHaJeJB/WLeM6D0eW1T675g9gpcHcWUeEJ7AuPL/9oNP1/BJlDhDTARzmtuUWG/VPGOR90jYVmIMn9K3s2OOiHeLOvquKR1DQ/oCExuAh7m76spTAh/mMWDTLwKv9GnTmeIgFcpkZa5PiLmGQhG8475F2pdzeplofdh9+powh2MzMZhxAtMjAzm8PLTvBZ1XlwI69BgPktTEq9E4/IvAu3f4IM7VVsRR2r3y8xDucYGRlZ/cZxeAU1vTr1GSy0pppkG2zd8s9uVPitbvD9JWpLq78etfmLGdCL0/6EfeM6KljYrBgQ2tb6ivQJD5YuefMAPnMVDOFfTC+R4N0PqXOZJWrNgV0uZrBkMW6pICUMpg0Vg56D+s1daIns597J7rGiydcbwMl5JGxa/dqD8TzPk5fHPgxE8+hXY6SXxKhdFmhMr/9GZH/iQR/E+avkolCYAUGPRCmxmVdExMI5k9GfsVSFRzJqcR8Vfb3le0FY+IlAq9wr6yZ6ovNQS9HmyWOPl0spZAmqq+UHWGQZuMNSHIc151cOIwps2NkS/2xYK62vA2l/RqB9w1pJZumARsdghHGt1xNVEBhCSVwZ04/vFRQFTxP05riiM6XL+3MKAbe1kExS8FLEhjC110+QHZrv2t2b3s7ngolAndHkCdwAjJR1Nf+u7zu+P0bSGcptfYKg== X-Forefront-Antispam-Report: CIP:178.72.21.4; CTRY:DK; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:localhost.localdomain.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230031)(6069001)(346002)(39840400004)(376002)(136003)(396003)(82310400011)(451199024)(186009)(1800799009)(36840700001)(46966006)(118246002)(2906002)(30864003)(40480700001)(6506007)(6486002)(83380400001)(5660300002)(336012)(26005)(34020700004)(86362001)(36860700001)(47076005)(8676002)(2616005)(8936002)(956004)(107886003)(4326008)(70206006)(316002)(6512007)(70586007)(36736006)(9316004)(478600001)(356005)(81166007)(6666004)(36756003)(41300700001)(1076003)(21314003)(36900700001)(559001)(579004)(309714004); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: WXeqgHxfeUT9WMG5BB85/dAA4BiMjpLtgux+DdBcJvQZTkn83GrLfhC/EbnPdxe7gM2COKT+dspvzbc8nuqc0W0xnB/e7+QK4US7l/AxkdtyiqDZ6CmldB88Lp/ulCYA7rtPDDefkMVapBsXDunTGFmEdfi5I05W21uAaIkD0zc2WSnokH+ePG9xdoCSLbX31iWxTSlbXg8UHP36+gzO4lzM5KWxZ//z6LpN+nZ+3tvJL+cqVnNW4tfNTvKOvE+WxCmlarF+fc51KnVZ4uXPsxVpZrYITnVclM4ImoAFhO0Wl8IY+H67ZNC/67S/0p9ijlmanbYeAv0vgSxkyfAj3Mnr1vN0D6B1IbOPcE7T41o5pUb6JMNoO0k5HvGZT9tA8tmo2OSoIU0cMHgDd4uZA7GNGc3SreAiPifb6pK26ov0Xd9JpjMSRSIghrASTJVp+NBSgawg5pEK4du4vgZV89Ur6U9Wpq135hnGdueK8qIVIXrfdvdYUQbIa0HeU9nTr461wRUvYh5/G+v8O/6moBks+JN+JJYv8llYTsP85KvXAvwH2Imb0AWuz5bePCQu8bzZuP9LMkP8/tDarPe4Glz8iClNwAVT2aZl7g96wD3oim64TZNey1NB1J0K6mq4pPflCRwyq6kKq/pStrkpvozAasMyFAYmmM8bluOU1A7QRSRXxmGTTReWhsYxfV9s3FKiBNoiTrHW05+Knf1lpzY6Mobs3iCgXAMI+mxmSx5IQUbPnmmOU0wEb5c3xoz7YZ8itj8hc3sXAeGDKRt0tgCP6f8qIdwMd4npeGktoy0= X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Aug 2023 13:54:29.6009 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 0258555b-4e97-4784-05ec-08dba24e23f9 X-MS-Exchange-CrossTenant-Id: c4540d0b-728a-4233-9da5-9ea30c7ec3ed X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=c4540d0b-728a-4233-9da5-9ea30c7ec3ed; Ip=[178.72.21.4]; Helo=[localhost.localdomain.com] X-MS-Exchange-CrossTenant-AuthSource: DU2PEPF0001E9C5.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM9P190MB1329 X-BESS-ID: 1692626085-303522-12320-18274-1 X-BESS-VER: 2019.1_20230817.1828 X-BESS-Apparent-Source-IP: 104.47.12.58 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKViYGFsaWFkB2BlA40dDcwsAkNd nMIsXA2NDAxCLJzNzI2MzCLCnJLNXSLFmpNhYAD2JgdEMAAAA= X-BESS-Outbound-Spam-Score: 0.00 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.250292 [from cloudscan16-232.eu-central-1b.ess.aws.cudaops.com] Rule breakdown below pts rule name description ---- ---------------------- -------------------------------- 0.00 LARGE_BODY_SHORTCUT META: X-BESS-Outbound-Spam-Status: SCORE=0.00 using account:ESS113687 scores of KILL_LEVEL=7.0 tests=LARGE_BODY_SHORTCUT X-BESS-BRTS-Status: 1 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 From: Christian Koue Muf The FPGA abstraction layer limits the need to rewrite flow logic when new FPGA modules are created. Signed-off-by: Christian Koue Muf Reviewed-by: Mykola Kostenok --- v2: * Fixed compilation with Fedora 38 * Fixed WARNING:TYPO_SPELLING --- drivers/net/ntnic/meson.build | 21 + .../ntnic/nthw/flow_api/flow_api_actions.c | 205 ++ .../ntnic/nthw/flow_api/flow_api_actions.h | 284 +++ .../ntnic/nthw/flow_api/flow_api_backend.c | 182 ++ .../ntnic/nthw/flow_api/flow_api_backend.h | 1818 +++++++++++++++++ .../net/ntnic/nthw/flow_api/flow_api_engine.h | 475 +++++ .../ntnic/nthw/flow_api/flow_api_nic_setup.h | 32 + .../nthw/flow_api/flow_engine/flow_group.c | 125 ++ .../nthw/flow_api/flow_engine/flow_hasher.c | 213 ++ .../nthw/flow_api/flow_engine/flow_hasher.h | 20 + .../nthw/flow_api/flow_engine/flow_kcc.c | 434 ++++ .../ntnic/nthw/flow_api/flow_engine/flow_km.c | 1434 +++++++++++++ .../nthw/flow_api/flow_engine/flow_tunnel.c | 787 +++++++ .../ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c | 1789 ++++++++++++++++ .../nthw/flow_api/hw_mod/hw_mod_cat_v18.h | 138 ++ .../nthw/flow_api/hw_mod/hw_mod_cat_v21.h | 88 + .../nthw/flow_api/hw_mod/hw_mod_cat_v22.h | 83 + .../ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c | 1099 ++++++++++ .../nthw/flow_api/hw_mod/hw_mod_flm_v17.h | 274 +++ .../nthw/flow_api/hw_mod/hw_mod_flm_v20.h | 102 + .../ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c | 195 ++ .../nthw/flow_api/hw_mod/hw_mod_hsh_v5.h | 36 + .../ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c | 178 ++ .../nthw/flow_api/hw_mod/hw_mod_hst_v2.h | 32 + .../ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c | 271 +++ .../nthw/flow_api/hw_mod/hw_mod_ioa_v4.h | 36 + .../ntnic/nthw/flow_api/hw_mod/hw_mod_km.c | 629 ++++++ .../ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h | 93 + .../ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c | 219 ++ .../nthw/flow_api/hw_mod/hw_mod_pdb_v9.h | 39 + .../ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c | 348 ++++ .../nthw/flow_api/hw_mod/hw_mod_qsl_v7.h | 45 + .../ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c | 112 + .../nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h | 20 + .../ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c | 358 ++++ .../nthw/flow_api/hw_mod/hw_mod_roa_v6.h | 49 + .../ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c | 132 ++ .../nthw/flow_api/hw_mod/hw_mod_slc_lr.c | 132 ++ .../nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h | 19 + .../nthw/flow_api/hw_mod/hw_mod_slc_v1.h | 19 + .../ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c | 983 +++++++++ .../nthw/flow_api/hw_mod/hw_mod_tpe_v1.h | 103 + .../nthw/flow_api/hw_mod/hw_mod_tpe_v2.h | 37 + .../nthw/flow_api/stream_binary_flow_api.h | 697 +++++++ 44 files changed, 14385 insertions(+) create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_actions.c create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_actions.h create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_backend.c create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_backend.h create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_engine.h create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h create mode 100644 drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build index c4f0a912d3..b816021b11 100644 --- a/drivers/net/ntnic/meson.build +++ b/drivers/net/ntnic/meson.build @@ -24,6 +24,7 @@ includes = [ include_directories('nthw'), include_directories('nthw/core'), include_directories('nthw/supported'), + include_directories('nthw/flow_api'), include_directories('nthw/flow_filter'), include_directories('sensors'), include_directories('sensors/avr_sensors'), @@ -66,6 +67,26 @@ sources = files( 'nthw/core/nthw_spim.c', 'nthw/core/nthw_spis.c', 'nthw/core/nthw_tsm.c', + 'nthw/flow_api/flow_api_actions.c', + 'nthw/flow_api/flow_api_backend.c', + 'nthw/flow_api/flow_engine/flow_group.c', + 'nthw/flow_api/flow_engine/flow_hasher.c', + 'nthw/flow_api/flow_engine/flow_kcc.c', + 'nthw/flow_api/flow_engine/flow_km.c', + 'nthw/flow_api/flow_engine/flow_tunnel.c', + 'nthw/flow_api/hw_mod/hw_mod_cat.c', + 'nthw/flow_api/hw_mod/hw_mod_flm.c', + 'nthw/flow_api/hw_mod/hw_mod_hsh.c', + 'nthw/flow_api/hw_mod/hw_mod_hst.c', + 'nthw/flow_api/hw_mod/hw_mod_ioa.c', + 'nthw/flow_api/hw_mod/hw_mod_km.c', + 'nthw/flow_api/hw_mod/hw_mod_pdb.c', + 'nthw/flow_api/hw_mod/hw_mod_qsl.c', + 'nthw/flow_api/hw_mod/hw_mod_rmc.c', + 'nthw/flow_api/hw_mod/hw_mod_roa.c', + 'nthw/flow_api/hw_mod/hw_mod_slc.c', + 'nthw/flow_api/hw_mod/hw_mod_slc_lr.c', + 'nthw/flow_api/hw_mod/hw_mod_tpe.c', 'nthw/flow_filter/flow_nthw_cat.c', 'nthw/flow_filter/flow_nthw_csu.c', 'nthw/flow_filter/flow_nthw_flm.c', diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_actions.c b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.c new file mode 100644 index 0000000000..945ab7d743 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.c @@ -0,0 +1,205 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include +#include /* htons, htonl, ntohs */ + +#include "ntlog.h" + +#include "stream_binary_flow_api.h" +#include "flow_api_actions.h" +#include "flow_api_backend.h" +#include "flow_api_engine.h" + +int flow_actions_create_roa_tunhdr(struct flow_api_backend_s *be, int index, + struct tunnel_header_s *tun) +{ + int err = 0; + int num_writes = (tun->ip_version == 4) ? 4 : 8; + + /* + * Write 4 * 4 words = 64 bytes (IPv4) or 8 * 4 words = 128 bytes (IPv6) + */ + for (int i = 0; (i < num_writes) && !err; i++) { + for (int ii = 0; (ii < 4) && !err; ii++) { + /* must write each 4 words backwards! */ + err |= hw_mod_roa_tunhdr_set(be, HW_ROA_TUNHDR, + index, i * 4 + ii, + ntohl(tun->d.hdr32[(i + 1) * 4 - ii - 1])); + } + } + + return err; +} + +int flow_actions_create_roa_tuncfg(struct flow_api_backend_s *be, int index, + uint64_t color_actions) +{ + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_PRESET_ALL, index, 0); + /* + * If tunnel header specified + */ + int tun_len = get_roa_tunhdr_len(color_actions); + + if (tun_len) { + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TUN_LEN, index, + tun_len); + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TUN_TYPE, index, + roa_get_tun_type(color_actions)); + + /* set the total tunnel IP header length */ + if (get_roa_tun_ip_type(color_actions) == 1) { + /* IPv6 */ + if ((size_t)tun_len > (sizeof(struct flow_elem_eth) + + sizeof(struct flow_elem_ipv6))) { + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_UPD, index, 1); + /* tunnel header length excludes the IPv6 header itself */ + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_PRECALC, index, + (uint32_t)(tun_len - + (sizeof(struct flow_elem_eth) + + sizeof(struct flow_elem_ipv6)))); + } + } else { + /* IPv4 */ + if ((size_t)tun_len > sizeof(struct flow_elem_eth)) { + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_UPD, + index, 1); + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_PRECALC, index, + (uint32_t)(tun_len - + sizeof(struct flow_elem_eth))); + } + } + + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IP_TYPE, index, + get_roa_tun_ip_type(color_actions)); + + if (get_roa_tun_ip_type(color_actions) == 1) { + /* IPv6 - Do not update the IP checksum in the tunnel header */ + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_UPD, index, + 0); + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_PRECALC, + index, 0); + } else { + /* IPv4 */ + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_UPD, + index, 1); + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_PRECALC, + index, + get_roa_tun_ip_csum(color_actions)); + } + + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_VXLAN_UDP_LEN_UPD, + index, 1); + + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_PUSH_TUNNEL, index, 1); + } + + /* bypass must be > 0 or recirculate_port >= 0 - bypass wins */ + uint8_t recirculate_bypass = roa_get_recirc_bypass_port(color_actions); + + if (recirculate_bypass) { + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_BYPASS, index, + recirculate_bypass); + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRCULATE, index, 1); + + } else { + int32_t recirculate_port = roa_get_recirc_port(color_actions); + + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_BYPASS, index, + 255); + + if (recirculate_port >= 0) { + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_PORT, + index, recirculate_port); + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRCULATE, + index, 1); + } + } + + uint8_t tx = roa_get_tx(color_actions); + + if (tx) { + if (tx == DESTINATION_TX_PHY0) { + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TX_LAG_IX, + index, ROA_TX_PHY0); + } else if (tx == DESTINATION_TX_PHY1) { + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TX_LAG_IX, + index, ROA_TX_PHY1); + } else if (tx == (DESTINATION_TX_PHY0 | DESTINATION_TX_PHY1)) { + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TX_LAG_IX, + index, ROA_TX_PHY0); + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_BYPASS, + index, 0x81); /* port 1 - only port left */ + hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRCULATE, + index, 1); + + } else { + return -1; /* ERR */ + } + } + + /* + * Special IOA memory that contains ROA information - bad FPGA design + */ + if (tx || tun_len) { + if (be->ioa.ver > 3 && tun_len && + get_roa_tun_ip_type(color_actions) == 1) { + /* IPv6 VxLAN tunnel. Select EPP recipe 2 */ + hw_mod_ioa_roa_epp_set(be, HW_IOA_ROA_EPP_PUSH_TUNNEL, + index, 2); + } else { + /* IPv4 VxLAN tunnel or no tunnel (select recipe 1 or 0) */ + hw_mod_ioa_roa_epp_set(be, HW_IOA_ROA_EPP_PUSH_TUNNEL, + index, !!tun_len); + } + hw_mod_ioa_roa_epp_set(be, HW_IOA_ROA_EPP_TX_PORT, index, tx); + } + + return 0; +} + +int flow_actions_create_ioa_config(struct flow_api_backend_s *be, int index, + uint64_t color_actions) +{ + if (color_actions & ioa_set_vxlan_pop(0)) { + hw_mod_ioa_rcp_set(be, HW_IOA_RCP_TUNNEL_POP, index, 1); + NT_LOG(DBG, FILTER, "Pop outer Tunnel (Vxlan)\n"); + } + + if (color_actions & ioa_set_vlan_pop(0)) { + hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_POP, index, 1); + NT_LOG(DBG, FILTER, "Pop outer Vlan\n"); + } + + int tpid_sel = ioa_get_tpid_sel(color_actions); + + if (color_actions & ioa_set_vlan_push(0, 0)) { + uint16_t tci = ioa_get_vlan_tci(color_actions); + + NT_LOG(DBG, FILTER, "Push Vlan with TPID/TCI %04x/%04x\n", + tpid_sel ? 0x88a8 : 0x8100, tci); + hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_VID, index, + tci & 0x0FFF); + hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_DEI, index, + (tci >> 12) & 0x1); + hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_PCP, index, + (tci >> 13) & 0x7); + hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_PUSH, index, 1); + } + + int queue = ioa_get_queue(color_actions); + + if (queue >= 0) { + hw_mod_ioa_rcp_set(be, HW_IOA_RCP_QUEUE_OVERRIDE_EN, index, 1); + hw_mod_ioa_rcp_set(be, HW_IOA_RCP_QUEUE_ID, index, queue); + } + + hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_TPID_SEL, index, tpid_sel); + + return 0; +} diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_actions.h b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.h new file mode 100644 index 0000000000..400066e817 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.h @@ -0,0 +1,284 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _FLOW_ACTIONS_H_ +#define _FLOW_ACTIONS_H_ + +struct flow_api_backend_s; +struct tunnel_header_s; + +#define MAX_COLOR_FLOW_STATS 0x400 + +#define ROA_RECIRC_BYPASS_PHY_OFFSET 0x80 +#define MAX_REPLICATION_PORTS 2 + +enum { + DESTINATION_TX_NONE = 0, + DESTINATION_TX_PHY0 = 1, + DESTINATION_TX_PHY1 = 2 +}; + +enum { TUN_IPV4 = 0, TUN_IPV6 }; + +enum { + VLAN_TPID_802_1Q = 0, + VLAN_TPID_802_1AD, + VLAN_TPID_CUSTOM_0, + VLAN_TPID_CUSTOM_1 +}; + +enum { ROA_TX_NO_RETRANSMIT = 0, ROA_TX_PHY0, ROA_TX_PHY1, ROA_TX_RESERVED }; + +/* + * before version 6 of QSL + */ +#if (MAX_COLOR_FLOW_STATS == 0x4000) +#define MAX_HW_FLOW_STATS_OLD 0x3fff + +#else +#if (MAX_COLOR_FLOW_STATS == 0x400) +#define MAX_HW_FLOW_STATS_OLD 0x03ff +#else +#error *** Unsupported number of color statistics counter *** +#endif +#endif + +/* + * OLD behavior substituted from 4.1+ + * + * 13:0 Mark (color) 16384 flow stats + * 21:14 IOA index 256 entries + * 29:22 ROA index 256 entries + * 31:30 1 to indicate this layout + * or + * 9:0 Mark (color) 1024 flow stats + * 19:10 IOA index 1024 entries + * 29:20 ROA index 1024 entries + * 31:30 0 to indicate this layout + */ +static inline uint32_t set_color_action_old(uint32_t color, uint32_t ioa_rcp, + uint32_t roa_rcp) +{ +#if (MAX_COLOR_FLOW_STATS == 0x400) + uint32_t color_action = (color & MAX_HW_FLOW_STATS_OLD) | + ((ioa_rcp & 0x3ff) << 10) | + ((roa_rcp & 0x3ff) << 20) | (0 << 30); +#else + uint32_t color_action = (color & MAX_HW_FLOW_STATS_OLD) | + ((ioa_rcp & 0xff) << 14) | + ((roa_rcp & 0xff) << 22) | (1 << 30); +#endif + return color_action; +} + +#define BITMASK(a, b) ((1U << ((a) - (b) + 1)) - 1) + +/* + * 9:0 Mark (color) 1024 flow stats + * 17:10 IOA index 256 entries + * 25:18 ROA index 256 entries + * 30:26 QSL and HSH 32 recipes indexable + * 31:31 CAO implicitly when color_action is set + */ +#define FLOW_MARK_MASK BITMASK(9, 0) +#define IOA_RCP_MASK BITMASK(17, 10) +#define ROA_RCP_MASK BITMASK(25, 18) +#define QSL_HSH_MASK BITMASK(30, 26) + +static inline uint32_t set_color_action(uint32_t mark, uint32_t ioa_rcp, + uint32_t roa_rcp, uint32_t qsl_hsh) +{ + uint32_t color_action = (mark & FLOW_MARK_MASK) | + ((ioa_rcp & IOA_RCP_MASK) << 10) | + ((roa_rcp & ROA_RCP_MASK) << 18) | + ((qsl_hsh & QSL_HSH_MASK) << 26) | (1 << 31); + return color_action; +} + +/* + * This is a bitmask representation in SW for + * roa config settings. It is mostly done for + * effective cache matching + * + * ROA config bit offs bits + * ---------------------------- + * recirc port 7:0 8 -> uses hbx > 0 + * recirc bypass 15:8 8 -> uses hbx > 0 if set, will override + * tunnel type 19:16 4 + * tx port 23:20 4 -> txport + 1 + * tun_ip_type 24:24 1 + * recirculate 25:25 1 -> recirculate port set + * tunhdr_len 33:26 8 -> tunnel header length - 0 if none + * ip_csum_prec 49:34 16 -> tunnel ip header checksum pre-calculated + * new_recirc_port 50:50 1 -> indication of a new port for recirculate has been allocated. + * Needs default queue + */ + +static inline uint64_t set_roa_new_recirc_port(uint64_t actions) +{ + actions |= 1ULL << 50; + return actions; +} + +static inline uint8_t get_roa_new_recirc_port(uint64_t actions) +{ + return (uint8_t)((actions >> 50) & 1); +} + +static inline uint64_t set_roa_tun_ip_type(uint64_t actions, uint8_t ip_type) +{ + actions |= (uint64_t)(ip_type & 1) << 24; + return actions; +} + +static inline uint8_t get_roa_tun_ip_type(uint64_t actions) +{ + return (uint8_t)((actions >> 24) & 1); +} + +static inline uint64_t set_roa_tun_ip_csum(uint64_t actions, uint16_t csum) +{ + actions |= (uint64_t)csum << 34; + return actions; +} + +static inline uint16_t get_roa_tun_ip_csum(uint64_t actions) +{ + return (uint16_t)((actions >> 34) & 0xffff); +} + +static inline uint64_t set_roa_tunhdr_len(uint64_t actions, uint8_t length) +{ + actions |= (uint64_t)length << 26; + return actions; +} + +static inline uint8_t get_roa_tunhdr_len(uint64_t actions) +{ + return (uint8_t)((actions >> 26) & 0xff); +} + +static inline uint64_t set_roa_tx(uint64_t actions, uint8_t txport) +{ + actions |= ((txport + ROA_TX_PHY0) & 0x0f) << 20; + return actions; +} + +static inline uint8_t roa_get_tx(uint64_t actions) +{ + return (actions >> 20) & 0x0f; +} + +static inline uint64_t set_roa_tun_type(uint64_t actions, uint8_t type) +{ + actions |= (type & 0x0f) << 16; + return actions; +} + +static inline uint8_t roa_get_tun_type(uint64_t actions) +{ + return (actions >> 16) & 0x0f; +} + +static inline uint64_t set_roa_recirculate(uint64_t actions, uint8_t port) +{ + actions |= (1ULL << 25) | port; + return actions; +} + +static inline int32_t roa_get_recirc_port(uint64_t actions) +{ + if (!((1ULL << 25) & actions)) + return -1; + return (actions & 0xff); +} + +static inline uint64_t set_roa_recirc_bypass(uint64_t actions, uint8_t port) +{ + actions |= ((uint64_t)port & 0xff) << 8; + return actions; +} + +static inline uint8_t roa_get_recirc_bypass_port(uint64_t actions) +{ + return ((actions >> 8) & 0xff); +} + +/* + * This is a bitmask representation in SW for + * ioa action settings. It is mostly done for + * effective cache matching + * + * IOA action bit offs bits + * -------------------------------- + * tci 15:0 16 + * queue 23:16 8 uses hbx + * tpid select 27:24 4 + * pop vxlan 28 1 + * pop vlan 29 1 + * push vlan 30 1 + * queue override 31 1 + */ + +static inline uint64_t ioa_set_queue(uint64_t actions, uint8_t hb) +{ + actions |= (1 << 31) | ((uint64_t)hb << 16); + return actions; +} + +static inline int ioa_get_queue(uint64_t actions) +{ + if (!(actions & (1 << 31))) + return -1; + return ((actions >> 16) & 0xff); +} + +static inline uint64_t ioa_set_vxlan_pop(uint64_t actions) +{ + actions |= 1 << 28; + return actions; +} + +static inline uint64_t ioa_set_vlan_pop(uint64_t actions) +{ + actions |= 1 << 29; + return actions; +} + +static inline uint64_t ioa_set_vlan_push_qinq(uint64_t actions) +{ + actions |= (VLAN_TPID_802_1AD & 0x0f) << 24; + return actions; +} + +static inline uint8_t ioa_get_tpid_sel(uint64_t actions) +{ + return (uint8_t)((actions >> 24) & 0x0f); +} + +static inline uint64_t ioa_set_vlan_push(uint64_t actions, uint16_t tci) +{ + actions |= (1 << 30) | tci; + return actions; +} + +static inline uint64_t ioa_set_vlan_pcp(uint64_t actions, uint8_t pcp) +{ + actions |= (1 << 30) | ((uint16_t)(pcp & 7) << 13); + return actions; +} + +static inline uint16_t ioa_get_vlan_tci(uint64_t actions) +{ + return (uint16_t)(actions & 0xffff); +} + +int flow_actions_create_roa_tunhdr(struct flow_api_backend_s *be, int index, + struct tunnel_header_s *tun); +int flow_actions_create_roa_tuncfg(struct flow_api_backend_s *be, int index, + uint64_t color_actions); +int flow_actions_create_ioa_config(struct flow_api_backend_s *be, int index, + uint64_t color_actions); + +#endif /* _FLOW_ACTIONS_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_backend.c b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.c new file mode 100644 index 0000000000..f4d71acb51 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.c @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include +#include + +#include "flow_api_backend.h" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +static const struct { + const char *name; + int (*allocate)(struct flow_api_backend_s *be); + void (*free)(struct flow_api_backend_s *be); + int (*reset)(struct flow_api_backend_s *be); + bool (*present)(struct flow_api_backend_s *be); +} module[] = { + { "CAT", hw_mod_cat_alloc, hw_mod_cat_free, hw_mod_cat_reset, + hw_mod_cat_present + }, + { "KM", hw_mod_km_alloc, hw_mod_km_free, hw_mod_km_reset, + hw_mod_km_present + }, + { "FLM", hw_mod_flm_alloc, hw_mod_flm_free, hw_mod_flm_reset, + hw_mod_flm_present + }, + { "HSH", hw_mod_hsh_alloc, hw_mod_hsh_free, hw_mod_hsh_reset, + hw_mod_hsh_present + }, + { "HST", hw_mod_hst_alloc, hw_mod_hst_free, hw_mod_hst_reset, + hw_mod_hst_present + }, + { "QSL", hw_mod_qsl_alloc, hw_mod_qsl_free, hw_mod_qsl_reset, + hw_mod_qsl_present + }, + { "SLC", hw_mod_slc_alloc, hw_mod_slc_free, hw_mod_slc_reset, + hw_mod_slc_present + }, + { "SLC LR", hw_mod_slc_lr_alloc, hw_mod_slc_lr_free, + hw_mod_slc_lr_reset, hw_mod_slc_lr_present + }, + { "PDB", hw_mod_pdb_alloc, hw_mod_pdb_free, hw_mod_pdb_reset, + hw_mod_pdb_present + }, + { "IOA", hw_mod_ioa_alloc, hw_mod_ioa_free, hw_mod_ioa_reset, + hw_mod_ioa_present + }, + { "ROA", hw_mod_roa_alloc, hw_mod_roa_free, hw_mod_roa_reset, + hw_mod_roa_present + }, + { "RMC", hw_mod_rmc_alloc, hw_mod_rmc_free, hw_mod_rmc_reset, + hw_mod_rmc_present + }, + { "TPE", hw_mod_tpe_alloc, hw_mod_tpe_free, hw_mod_tpe_reset, + hw_mod_tpe_present + }, +}; + +#define MOD_COUNT (ARRAY_SIZE(module)) + +void *callocate_mod(struct common_func_s *mod, int sets, ...) +{ +#define MAX_SETS 38 + void *base = NULL; + void **plist[MAX_SETS]; + int len[MAX_SETS]; + int offs[MAX_SETS]; + unsigned int total_bytes = 0; + int cnt, elem_size; + + assert(sets <= MAX_SETS); + assert(sets > 0); + + va_list args; + + va_start(args, sets); + + for (int i = 0; i < sets; i++) { + plist[i] = va_arg(args, void *); + cnt = va_arg(args, int); + elem_size = va_arg(args, int); + offs[i] = EXTRA_INDEXES * elem_size; + len[i] = offs[i] + cnt * elem_size; + total_bytes += len[i]; + } + base = calloc(1, total_bytes); + if (base) { + char *p_b = (char *)base; + + for (int i = 0; i < sets; i++) { + (*plist[i]) = (void *)((char *)p_b + offs[i]); + p_b += len[i]; + } + } else { + NT_LOG(ERR, FILTER, "ERROR: module memory allocation failed\n"); + } + + va_end(args); + + mod->base = base; + mod->allocated_size = total_bytes; + + return base; +} + +void zero_module_cache(struct common_func_s *mod) +{ + memset(mod->base, 0, mod->allocated_size); +} + +int flow_api_backend_init(struct flow_api_backend_s *dev, + const struct flow_api_backend_ops *iface, + void *be_dev) +{ + assert(dev); + dev->iface = iface; + dev->be_dev = be_dev; + dev->num_phy_ports = iface->get_nb_phy_port(be_dev); + dev->num_rx_ports = iface->get_nb_rx_port(be_dev); + dev->max_categories = iface->get_nb_categories(be_dev); + dev->max_queues = iface->get_nb_queues(be_dev); + + NT_LOG(DBG, FILTER, + "*************** FLOW REGISTER MODULES AND INITIALIZE - SET ALL TO DEFAULT *****************\n"); + /* + * Create Cache and SW, version independent, NIC module representation + */ + for (unsigned int mod = 0; mod < MOD_COUNT; mod++) { + if (!module[mod].present(dev)) + continue; + if (module[mod].allocate(dev) == 0 && + module[mod].reset(dev) == 0) { + /* OK */ + continue; + } else { + NT_LOG(ERR, FILTER, + "ERROR: Initialization of NIC module failed : [ %s ]\n", + module[mod].name); + flow_api_backend_done(dev); + NT_LOG(ERR, FILTER, + "*************** Failed to create Binary Flow API *******************\n"); + NT_LOG(ERR, FILTER, + "******** ERROR ERROR: Binary Flow API will not be available ********\n"); + NT_LOG(ERR, FILTER, + "********************************************************************\n"); + return -1; + } + } + + return 0; +} + +int flow_api_backend_reset(struct flow_api_backend_s *dev) +{ + assert(dev); + + for (unsigned int mod = 0; mod < MOD_COUNT; mod++) { + if (module[mod].reset(dev) == 0) { + /* OK */ + continue; + } else { + NT_LOG(ERR, FILTER, + "ERROR: Resetting NIC module failed : [ %s ]\n", + module[mod].name); + return -1; + } + } + + return 0; +} + +int flow_api_backend_done(struct flow_api_backend_s *dev) +{ + for (unsigned int mod = 0; mod < MOD_COUNT; mod++) + module[mod].free(dev); + return 0; +} diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_backend.h b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.h new file mode 100644 index 0000000000..c3386adea9 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.h @@ -0,0 +1,1818 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_API_BACKEND_H__ +#define __FLOW_API_BACKEND_H__ + +/* + * Flow API + * Direct access to NIC HW module memory and register fields in a + * module version independent representation + */ + +#include +#include +#include + +#include "ntlog.h" + +/* supported module versions */ +#include "../flow_api/hw_mod/hw_mod_km_v7.h" +#include "flow_api/hw_mod/hw_mod_cat_v18.h" +#include "flow_api/hw_mod/hw_mod_cat_v21.h" +#include "flow_api/hw_mod/hw_mod_cat_v22.h" +#include "flow_api/hw_mod/hw_mod_flm_v17.h" +#include "flow_api/hw_mod/hw_mod_flm_v20.h" +#include "flow_api/hw_mod/hw_mod_hst_v2.h" +#include "flow_api/hw_mod/hw_mod_km_v7.h" +#include "flow_api/hw_mod/hw_mod_qsl_v7.h" +#include "flow_api/hw_mod/hw_mod_pdb_v9.h" +#include "flow_api/hw_mod/hw_mod_slc_v1.h" +#include "flow_api/hw_mod/hw_mod_slc_lr_v2.h" +#include "flow_api/hw_mod/hw_mod_roa_v6.h" +#include "flow_api/hw_mod/hw_mod_hsh_v5.h" +#include "flow_api/hw_mod/hw_mod_ioa_v4.h" +#include "flow_api/hw_mod/hw_mod_rmc_v1_3.h" +#include "flow_api/hw_mod/hw_mod_tpe_v1.h" +#include "flow_api/hw_mod/hw_mod_tpe_v2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_PHYS_ADAPTERS 8 + +#define VER_MAJOR(ver) (((ver) >> 16) & 0xffff) +#define VER_MINOR(ver) ((ver) & 0xffff) + +struct flow_api_backend_s; +struct common_func_s; + +#define CAST_COMMON(mod) ((struct common_func_s *)(mod)) + +void *callocate_mod(struct common_func_s *mod, int sets, ...); +void zero_module_cache(struct common_func_s *mod); + +#define ZERO_MOD_CACHE(mod) (zero_module_cache(CAST_COMMON(mod))) + +#define ALL_ENTRIES -1000 +#define ALL_BANK_ENTRIES -1001 + +static inline int error_index_too_large(const char *func) +{ + NT_LOG(INF, FILTER, "ERROR:%s: Index too large\n", func); + return -2; +} + +static inline int error_word_off_too_large(const char *func) +{ + NT_LOG(INF, FILTER, "ERROR:%s: Word offset too large\n", func); + return -3; +} + +static inline int error_unsup_ver(const char *func, const char *mod, int ver) +{ + NT_LOG(INF, FILTER, "ERROR:%s: Unsupported NIC module: %s ver %i.%i\n", + func, mod, VER_MAJOR(ver), VER_MINOR(ver)); + return -4; +} + +static inline int error_unsup_field(const char *func) +{ + NT_LOG(INF, FILTER, "ERROR:%s: Unsupported field in NIC module\n", + func); + return -5; +} + +static inline int error_resource_count(const char *func, const char *resource, + const char *mod, int ver) +{ + NT_LOG(INF, FILTER, + "ERROR:%s: Insufficient resource [ %s ] : NIC module:" + "%s ver %i.%i\n", + func, resource, mod, VER_MAJOR(ver), VER_MINOR(ver)); + return -4; +} + +#define NOT_FOUND 0xffffffff + +enum { EXTRA_INDEXES }; +#define COPY_INDEX (EXTRA_INDEX_COPY - EXTRA_INDEXES) + +static inline void get_set(uint32_t *cached_val, uint32_t *val, int get) +{ + if (get) + *val = *cached_val; + else + *cached_val = *val; +} + +static inline void get_set_signed(int32_t *cached_val, uint32_t *val, int get) +{ + if (get) + *val = (uint32_t)*cached_val; + else + *cached_val = (int32_t)*val; +} + +static inline int find_equal_index(void *be_module_reg, + unsigned int type_size, unsigned int idx, unsigned int start, + unsigned int nb_elements, uint32_t *value, int get, const char *func) +{ + unsigned int i; + if (!get) + return error_unsup_field(func); + *value = NOT_FOUND; + if (start >= nb_elements) + return error_index_too_large(func); + for (i = start; i < nb_elements; i++) { + if (idx == i) + continue; + if (memcmp((uint8_t *)be_module_reg + idx * type_size, + (uint8_t *)be_module_reg + i * type_size, + type_size) == 0) { + *value = i; + break; + } + } + return 0; +} + +static inline int do_compare_indexes(void *be_module_reg, + unsigned int type_size, unsigned int idx, unsigned int cmp_idx, + unsigned int nb_elements, int get, const char *func) +{ + if (!get) + return error_unsup_field(func); + if (cmp_idx >= nb_elements) + return error_index_too_large(func); + if (idx != cmp_idx && + (memcmp((uint8_t *)be_module_reg + idx * type_size, + (uint8_t *)be_module_reg + cmp_idx * type_size, + type_size) == 0)) + return 1; + return 0; +} + +static inline int is_non_zero(const void *addr, size_t n) +{ + size_t i = 0; + const uint8_t *p = (const uint8_t *)addr; + + for (i = 0; i < n; i++) { + if (p[i] != 0) + return 1; + } + return 0; +} + +static inline int is_all_bits_set(const void *addr, size_t n) +{ + size_t i = 0; + const uint8_t *p = (const uint8_t *)addr; + + for (i = 0; i < n; i++) { + if (p[i] != 0xff) + return 0; + } + return 1; +} + +enum cte_index_e { + CT_COL = 0, + CT_COR = 1, + CT_HSH = 2, + CT_QSL = 3, + CT_IPF = 4, + CT_SLC = 5, + CT_PDB = 6, + CT_MSK = 7, + CT_HST = 8, + CT_EPP = 9, + CT_TPE = 10, + CT_RRB = 11, + CT_CNT +}; + +/* Sideband info bit indicator */ +#define SWX_INFO (1 << 6) + +enum frame_offs_e { + DYN_SOF = 0, + DYN_L2 = 1, + DYN_FIRST_VLAN = 2, + DYN_MPLS = 3, + DYN_L3 = 4, + DYN_ID_IPV4_6 = 5, + DYN_FINAL_IP_DST = 6, + DYN_L4 = 7, + DYN_L4_PAYLOAD = 8, + DYN_TUN_PAYLOAD = 9, + DYN_TUN_L2 = 10, + DYN_TUN_VLAN = 11, + DYN_TUN_MPLS = 12, + DYN_TUN_L3 = 13, + DYN_TUN_ID_IPV4_6 = 14, + DYN_TUN_FINAL_IP_DST = 15, + DYN_TUN_L4 = 16, + DYN_TUN_L4_PAYLOAD = 17, + DYN_EOF = 18, + DYN_L3_PAYLOAD_END = 19, + DYN_TUN_L3_PAYLOAD_END = 20, + SB_VNI = SWX_INFO | 1, + SB_MAC_PORT = SWX_INFO | 2, + SB_KCC_ID = SWX_INFO | 3 +}; + +enum km_flm_if_select_e { KM_FLM_IF_FIRST = 0, KM_FLM_IF_SECOND = 1 }; + +enum { + QW0_SEL_EXCLUDE = 0, + QW0_SEL_FIRST32 = 1, + QW0_SEL_SECOND32 = 2, + QW0_SEL_FIRST64 = 3, + QW0_SEL_ALL128 = 4, +}; + +enum { + QW4_SEL_EXCLUDE = 0, + QW4_SEL_FIRST32 = 1, + QW4_SEL_FIRST64 = 2, + QW4_SEL_ALL128 = 3, +}; + +enum { + SW8_SEL_EXCLUDE = 0, + SW8_SEL_FIRST16 = 1, + SW8_SEL_SECOND16 = 2, + SW8_SEL_ALL32 = 3, +}; + +enum { + DW8_SEL_EXCLUDE = 0, + DW8_SEL_FIRST16 = 1, + DW8_SEL_SECOND16 = 2, + DW8_SEL_FIRST32 = 3, + DW8_SEL_FIRST32_SWAP16 = 4, + DW8_SEL_ALL64 = 5, +}; + +enum { + SW9_SEL_EXCLUDE = 0, + SW9_SEL_FIRST16 = 1, + SW9_SEL_ALL32 = 2, +}; + +enum { + DW10_SEL_EXCLUDE = 0, + DW10_SEL_FIRST16 = 1, + DW10_SEL_FIRST32 = 2, + DW10_SEL_ALL64 = 3, +}; + +enum { + SWX_SEL_EXCLUDE = 0, + SWX_SEL_ALL32 = 1, +}; + +enum { + PROT_OTHER = 0, + PROT_L2_ETH2 = 1, + PROT_L2_SNAP = 2, + PROT_L2_LLC = 3, + PROT_L2_RAW = 4, + PROT_L2_PPPOE_D = 5, + PROT_L2_PPOE_S = 6 +}; + +enum { PROT_L3_IPV4 = 1, PROT_L3_IPV6 = 2 }; + +enum { PROT_L4_TCP = 1, PROT_L4_UDP = 2, PROT_L4_SCTP = 3, PROT_L4_ICMP = 4 }; + +enum { + PROT_TUN_IP_IN_IP = 1, + PROT_TUN_ETHER_IP = 2, + PROT_TUN_GREV0 = 3, + PROT_TUN_GREV1 = 4, + PROT_TUN_GTPV0U = 5, + PROT_TUN_GTPV1U = 6, + PROT_TUN_GTPV1C = 7, + PROT_TUN_GTPV2C = 8, + PROT_TUN_VXLAN = 9, + PROT_TUN_PSEUDO_WIRE = 10 +}; + +enum { PROT_TUN_L2_OTHER = 0, PROT_TUN_L2_ETH2 = 1 }; + +enum { PROT_TUN_L3_OTHER = 0, PROT_TUN_L3_IPV4 = 1, PROT_TUN_L3_IPV6 = 2 }; + +enum { + PROT_TUN_L4_OTHER = 0, + PROT_TUN_L4_TCP = 1, + PROT_TUN_L4_UDP = 2, + PROT_TUN_L4_SCTP = 3, + PROT_TUN_L4_ICMP = 4 +}; + +enum { + IP_FRAG_NOT_A_FRAG = 0, + IP_FRAG_FIRST = 1, + IP_FRAG_MIDDLE = 2, + IP_FRAG_LAST = 3 +}; + +enum { + HASH_HASH_NONE = 0, + HASH_USER_DEFINED = 1, + HASH_LAST_MPLS_LABEL = 2, + HASH_ALL_MPLS_LABELS = 3, + HASH_2TUPLE = 4, + HASH_2TUPLESORTED = 5, + HASH_LAST_VLAN_ID = 6, + HASH_ALL_VLAN_IDS = 7, + HASH_5TUPLE = 8, + HASH_5TUPLESORTED = 9, + HASH_3TUPLE_GRE_V0 = 10, + HASH_3TUPLE_GRE_V0_SORTED = 11, + HASH_5TUPLE_SCTP = 12, + HASH_5TUPLE_SCTP_SORTED = 13, + HASH_3TUPLE_GTP_V0 = 14, + HASH_3TUPLE_GTP_V0_SORTED = 15, + HASH_3TUPLE_GTP_V1V2 = 16, + HASH_3TUPLE_GTP_V1V2_SORTED = 17, + HASH_HASHINNER_2TUPLE = 18, + HASH_HASHINNER_2TUPLESORTED = 19, + HASH_HASHINNER_5TUPLE = 20, + HASH_HASHINNER_5TUPLESORTED = 21, + HASH_KM = 30, + HASH_ROUND_ROBIN = 31, + HASH_OUTER_DST_IP = 32, + HASH_INNER_SRC_IP = 33, +}; + +enum { + CPY_SELECT_DSCP_IPV4 = 0, + CPY_SELECT_DSCP_IPV6 = 1, + CPY_SELECT_RQI_QFI = 2, + CPY_SELECT_IPV4 = 3, + CPY_SELECT_PORT = 4, + CPY_SELECT_TEID = 5, +}; + +#define RCK_CML(_comp_) (1 << ((_comp_) * 4)) +#define RCK_CMU(_comp_) (1 << ((_comp_) * 4 + 1)) +#define RCK_SEL(_comp_) (1 << ((_comp_) * 4 + 2)) +#define RCK_SEU(_comp_) (1 << ((_comp_) * 4 + 3)) + +#define RCK_EXT(x) (((uint32_t)(x) << 6)) + +#define FIELD_START_INDEX 100 + +#define COMMON_FUNC_INFO_S \ + int ver; \ + void *base; \ + unsigned int allocated_size; \ + int debug + +struct common_func_s { + COMMON_FUNC_INFO_S; +}; + +struct cat_func_s { + COMMON_FUNC_INFO_S; + uint32_t nb_cat_funcs; + uint32_t nb_flow_types; + uint32_t nb_pm_ext; + uint32_t nb_len; + uint32_t kcc_size; + uint32_t cts_num; + uint32_t kcc_banks; + uint32_t kcc_id_bit_size; + uint32_t kcc_records; + uint32_t km_if_count; + int32_t km_if_m0; + int32_t km_if_m1; + + union { + struct hw_mod_cat_v18_s v18; + struct hw_mod_cat_v21_s v21; + struct hw_mod_cat_v22_s v22; + }; +}; + +enum hw_cat_e { + /* + * functions initial CAT v18 + */ + /* 00 */ HW_CAT_CFN_SET_ALL_DEFAULTS = 0, + /* 01 */ HW_CAT_CFN_PRESET_ALL, + /* 02 */ HW_CAT_CFN_COMPARE, + /* 03 */ HW_CAT_CFN_FIND, + /* 04 */ HW_CAT_CFN_COPY_FROM, + /* 05 */ HW_CAT_COT_PRESET_ALL, + /* 06 */ HW_CAT_COT_COMPARE, + /* 07 */ HW_CAT_COT_FIND, + /* fields */ + /* 00 */ HW_CAT_CFN_ENABLE = FIELD_START_INDEX, + /* 01 */ HW_CAT_CFN_INV, + /* 02 */ HW_CAT_CFN_PTC_INV, + /* 03 */ HW_CAT_CFN_PTC_ISL, + /* 04 */ HW_CAT_CFN_PTC_CFP, + /* 05 */ HW_CAT_CFN_PTC_MAC, + /* 06 */ HW_CAT_CFN_PTC_L2, + /* 07 */ HW_CAT_CFN_PTC_VNTAG, + /* 08 */ HW_CAT_CFN_PTC_VLAN, + /* 09 */ HW_CAT_CFN_PTC_MPLS, + /* 10 */ HW_CAT_CFN_PTC_L3, + /* 11 */ HW_CAT_CFN_PTC_FRAG, + /* 12 */ HW_CAT_CFN_PTC_IP_PROT, + /* 13 */ HW_CAT_CFN_PTC_L4, + /* 14 */ HW_CAT_CFN_PTC_TUNNEL, + /* 15 */ HW_CAT_CFN_PTC_TNL_L2, + /* 16 */ HW_CAT_CFN_PTC_TNL_VLAN, + /* 17 */ HW_CAT_CFN_PTC_TNL_MPLS, + /* 18 */ HW_CAT_CFN_PTC_TNL_L3, + /* 19 */ HW_CAT_CFN_PTC_TNL_FRAG, + /* 20 */ HW_CAT_CFN_PTC_TNL_IP_PROT, + /* 21 */ HW_CAT_CFN_PTC_TNL_L4, + /* 22 */ HW_CAT_CFN_ERR_INV, + /* 23 */ HW_CAT_CFN_ERR_CV, + /* 24 */ HW_CAT_CFN_ERR_FCS, + /* 25 */ HW_CAT_CFN_ERR_TRUNC, + /* 26 */ HW_CAT_CFN_ERR_L3_CS, + /* 27 */ HW_CAT_CFN_ERR_L4_CS, + /* 28 */ HW_CAT_CFN_MAC_PORT, + /* 29 */ HW_CAT_CFN_PM_CMP, + /* 30 */ HW_CAT_CFN_PM_DCT, + /* 31 */ HW_CAT_CFN_PM_EXT_INV, + /* 32 */ HW_CAT_CFN_PM_CMB, + /* 33 */ HW_CAT_CFN_PM_AND_INV, + /* 34 */ HW_CAT_CFN_PM_OR_INV, + /* 35 */ HW_CAT_CFN_PM_INV, + /* 36 */ HW_CAT_CFN_LC, + /* 37 */ HW_CAT_CFN_LC_INV, + /* 38 */ HW_CAT_CFN_KM0_OR, + /* 39 */ HW_CAT_CFN_KM1_OR, + /* 40 */ HW_CAT_KCE_ENABLE_BM, + /* 41 */ HW_CAT_KCS_CATEGORY, + /* 42 */ HW_CAT_FTE_ENABLE_BM, + /* 43 */ HW_CAT_CTE_ENABLE_BM, + /* 44 */ HW_CAT_CTS_CAT_A, + /* 45 */ HW_CAT_CTS_CAT_B, + /* 46 */ HW_CAT_COT_COLOR, + /* 47 */ HW_CAT_COT_KM, + /* 48 */ HW_CAT_CCT_COLOR, + /* 49 */ HW_CAT_CCT_KM, + /* 50 */ HW_CAT_KCC_KEY, + /* 51 */ HW_CAT_KCC_CATEGORY, + /* 52 */ HW_CAT_KCC_ID, + /* 53 */ HW_CAT_EXO_DYN, + /* 54 */ HW_CAT_EXO_OFS, + /* 55 */ HW_CAT_RCK_DATA, + /* 56 */ HW_CAT_LEN_LOWER, + /* 57 */ HW_CAT_LEN_UPPER, + /* 58 */ HW_CAT_LEN_DYN1, + /* 59 */ HW_CAT_LEN_DYN2, + /* 60 */ HW_CAT_LEN_INV, + /* 61 */ HW_CAT_CFN_ERR_TNL_L3_CS, + /* 62 */ HW_CAT_CFN_ERR_TNL_L4_CS, + /* 63 */ HW_CAT_CFN_ERR_TTL_EXP, + /* 64 */ HW_CAT_CFN_ERR_TNL_TTL_EXP, + + /* 65 */ HW_CAT_CCE_IMM, + /* 66 */ HW_CAT_CCE_IND, + /* 67 */ HW_CAT_CCS_COR_EN, + /* 68 */ HW_CAT_CCS_COR, + /* 69 */ HW_CAT_CCS_HSH_EN, + /* 70 */ HW_CAT_CCS_HSH, + /* 71 */ HW_CAT_CCS_QSL_EN, + /* 72 */ HW_CAT_CCS_QSL, + /* 73 */ HW_CAT_CCS_IPF_EN, + /* 74 */ HW_CAT_CCS_IPF, + /* 75 */ HW_CAT_CCS_SLC_EN, + /* 76 */ HW_CAT_CCS_SLC, + /* 77 */ HW_CAT_CCS_PDB_EN, + /* 78 */ HW_CAT_CCS_PDB, + /* 79 */ HW_CAT_CCS_MSK_EN, + /* 80 */ HW_CAT_CCS_MSK, + /* 81 */ HW_CAT_CCS_HST_EN, + /* 82 */ HW_CAT_CCS_HST, + /* 83 */ HW_CAT_CCS_EPP_EN, + /* 84 */ HW_CAT_CCS_EPP, + /* 85 */ HW_CAT_CCS_TPE_EN, + /* 86 */ HW_CAT_CCS_TPE, + /* 87 */ HW_CAT_CCS_RRB_EN, + /* 88 */ HW_CAT_CCS_RRB, + /* 89 */ HW_CAT_CCS_SB0_TYPE, + /* 90 */ HW_CAT_CCS_SB0_DATA, + /* 91 */ HW_CAT_CCS_SB1_TYPE, + /* 92 */ HW_CAT_CCS_SB1_DATA, + /* 93 */ HW_CAT_CCS_SB2_TYPE, + /* 94 */ HW_CAT_CCS_SB2_DATA, + +}; + +bool hw_mod_cat_present(struct flow_api_backend_s *be); +int hw_mod_cat_alloc(struct flow_api_backend_s *be); +void hw_mod_cat_free(struct flow_api_backend_s *be); +int hw_mod_cat_reset(struct flow_api_backend_s *be); +int hw_mod_cat_cfn_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_cat_cfn_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, int word_off, uint32_t value); +int hw_mod_cat_cfn_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, int word_off, uint32_t *value); +/* KCE/KCS/FTE KM */ +int hw_mod_cat_kce_km_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int start_idx, + int count); +int hw_mod_cat_kce_km_set(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t value); +int hw_mod_cat_kce_km_get(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t *value); +int hw_mod_cat_kcs_km_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int start_idx, + int count); +int hw_mod_cat_kcs_km_set(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t value); +int hw_mod_cat_kcs_km_get(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t *value); +int hw_mod_cat_fte_km_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int start_idx, + int count); +int hw_mod_cat_fte_km_set(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t value); +int hw_mod_cat_fte_km_get(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t *value); +/* KCE/KCS/FTE FLM */ +int hw_mod_cat_kce_flm_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int start_idx, + int count); +int hw_mod_cat_kce_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t value); +int hw_mod_cat_kce_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t *value); +int hw_mod_cat_kcs_flm_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int start_idx, + int count); +int hw_mod_cat_kcs_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t value); +int hw_mod_cat_kcs_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t *value); +int hw_mod_cat_fte_flm_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int start_idx, + int count); +int hw_mod_cat_fte_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t value); +int hw_mod_cat_fte_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t *value); + +int hw_mod_cat_cte_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_cat_cte_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value); +int hw_mod_cat_cte_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value); +int hw_mod_cat_cts_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_cat_cts_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value); +int hw_mod_cat_cts_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value); +int hw_mod_cat_cot_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_cat_cot_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value); +int hw_mod_cat_cot_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value); +int hw_mod_cat_cct_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_cat_cct_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value); +int hw_mod_cat_cct_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value); +int hw_mod_cat_kcc_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_cat_kcc_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, int word_off, uint32_t value); +int hw_mod_cat_kcc_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, int word_off, uint32_t *value); + +int hw_mod_cat_exo_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_cat_exo_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value); +int hw_mod_cat_exo_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value); +int hw_mod_cat_rck_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_cat_rck_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value); +int hw_mod_cat_rck_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value); +int hw_mod_cat_len_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_cat_len_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value); +int hw_mod_cat_len_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value); +/* added in v22 */ +int hw_mod_cat_cce_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_cat_cce_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value); +int hw_mod_cat_cce_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value); +int hw_mod_cat_ccs_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_cat_ccs_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value); +int hw_mod_cat_ccs_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value); + +struct km_func_s { + COMMON_FUNC_INFO_S; + uint32_t nb_categories; + uint32_t nb_cam_banks; + uint32_t nb_cam_record_words; + uint32_t nb_cam_records; + uint32_t nb_tcam_banks; + uint32_t nb_tcam_bank_width; + /* not read from backend, but rather set using version */ + uint32_t nb_km_rcp_mask_a_word_size; + uint32_t nb_km_rcp_mask_b_word_size; + union { + struct hw_mod_km_v7_s v7; + }; +}; + +enum hw_km_e { + /* functions */ + HW_KM_RCP_PRESET_ALL = 0, + HW_KM_CAM_PRESET_ALL, + /* to sync and reset hw with cache - force write all entries in a bank */ + HW_KM_TCAM_BANK_RESET, + /* fields */ + HW_KM_RCP_QW0_DYN = FIELD_START_INDEX, + HW_KM_RCP_QW0_OFS, + HW_KM_RCP_QW0_SEL_A, + HW_KM_RCP_QW0_SEL_B, + HW_KM_RCP_QW4_DYN, + HW_KM_RCP_QW4_OFS, + HW_KM_RCP_QW4_SEL_A, + HW_KM_RCP_QW4_SEL_B, + HW_KM_RCP_DW8_DYN, + HW_KM_RCP_DW8_OFS, + HW_KM_RCP_DW8_SEL_A, + HW_KM_RCP_DW8_SEL_B, + HW_KM_RCP_DW10_DYN, + HW_KM_RCP_DW10_OFS, + HW_KM_RCP_DW10_SEL_A, + HW_KM_RCP_DW10_SEL_B, + HW_KM_RCP_SWX_CCH, + HW_KM_RCP_SWX_SEL_A, + HW_KM_RCP_SWX_SEL_B, + HW_KM_RCP_MASK_A, + HW_KM_RCP_MASK_B, + HW_KM_RCP_DUAL, + HW_KM_RCP_PAIRED, + HW_KM_RCP_EL_A, + HW_KM_RCP_EL_B, + HW_KM_RCP_INFO_A, + HW_KM_RCP_INFO_B, + HW_KM_RCP_FTM_A, + HW_KM_RCP_FTM_B, + HW_KM_RCP_BANK_A, + HW_KM_RCP_BANK_B, + HW_KM_RCP_KL_A, + HW_KM_RCP_KL_B, + HW_KM_RCP_KEYWAY_A, + HW_KM_RCP_KEYWAY_B, + HW_KM_RCP_SYNERGY_MODE, + HW_KM_RCP_DW0_B_DYN, + HW_KM_RCP_DW0_B_OFS, + HW_KM_RCP_DW2_B_DYN, + HW_KM_RCP_DW2_B_OFS, + HW_KM_RCP_SW4_B_DYN, + HW_KM_RCP_SW4_B_OFS, + HW_KM_RCP_SW5_B_DYN, + HW_KM_RCP_SW5_B_OFS, + HW_KM_CAM_W0, + HW_KM_CAM_W1, + HW_KM_CAM_W2, + HW_KM_CAM_W3, + HW_KM_CAM_W4, + HW_KM_CAM_W5, + HW_KM_CAM_FT0, + HW_KM_CAM_FT1, + HW_KM_CAM_FT2, + HW_KM_CAM_FT3, + HW_KM_CAM_FT4, + HW_KM_CAM_FT5, + HW_KM_TCAM_T, + HW_KM_TCI_COLOR, + HW_KM_TCI_FT, + HW_KM_TCQ_BANK_MASK, + HW_KM_TCQ_QUAL +}; + +bool hw_mod_km_present(struct flow_api_backend_s *be); +int hw_mod_km_alloc(struct flow_api_backend_s *be); +void hw_mod_km_free(struct flow_api_backend_s *be); +int hw_mod_km_reset(struct flow_api_backend_s *be); +int hw_mod_km_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_km_rcp_set(struct flow_api_backend_s *be, enum hw_km_e field, + int index, int word_off, uint32_t value); +int hw_mod_km_rcp_get(struct flow_api_backend_s *be, enum hw_km_e field, + int index, int word_off, uint32_t *value); +int hw_mod_km_cam_flush(struct flow_api_backend_s *be, int start_bank, + int start_record, int count); +int hw_mod_km_cam_set(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t value); +int hw_mod_km_cam_get(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t *value); +int hw_mod_km_tcam_flush(struct flow_api_backend_s *be, int start_bank, + int count); +int hw_mod_km_tcam_set(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int byte, int byte_val, uint32_t *value_set); +int hw_mod_km_tcam_get(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int byte, int byte_val, uint32_t *value_set); +int hw_mod_km_tci_flush(struct flow_api_backend_s *be, int start_bank, + int start_record, int count); +int hw_mod_km_tci_set(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t value); +int hw_mod_km_tci_get(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t *value); +int hw_mod_km_tcq_flush(struct flow_api_backend_s *be, int start_bank, + int start_record, int count); +int hw_mod_km_tcq_set(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t *value); +int hw_mod_km_tcq_get(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t *value); + +struct hst_func_s { + COMMON_FUNC_INFO_S; + uint32_t nb_hst_rcp_categories; + union { + struct hw_mod_hst_v2_s v2; + }; +}; + +enum hw_hst_e { + /* functions */ + HW_HST_RCP_PRESET_ALL = 0, + HW_HST_RCP_FIND, + HW_HST_RCP_COMPARE, + /* Control fields */ + HW_HST_RCP_STRIP_MODE = FIELD_START_INDEX, + HW_HST_RCP_START_DYN, + HW_HST_RCP_START_OFS, + HW_HST_RCP_END_DYN, + HW_HST_RCP_END_OFS, + HW_HST_RCP_MODIF0_CMD, + HW_HST_RCP_MODIF0_DYN, + HW_HST_RCP_MODIF0_OFS, + HW_HST_RCP_MODIF0_VALUE, + HW_HST_RCP_MODIF1_CMD, + HW_HST_RCP_MODIF1_DYN, + HW_HST_RCP_MODIF1_OFS, + HW_HST_RCP_MODIF1_VALUE, + HW_HST_RCP_MODIF2_CMD, + HW_HST_RCP_MODIF2_DYN, + HW_HST_RCP_MODIF2_OFS, + HW_HST_RCP_MODIF2_VALUE, + +}; + +bool hw_mod_hst_present(struct flow_api_backend_s *be); +int hw_mod_hst_alloc(struct flow_api_backend_s *be); +void hw_mod_hst_free(struct flow_api_backend_s *be); +int hw_mod_hst_reset(struct flow_api_backend_s *be); + +int hw_mod_hst_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_hst_rcp_set(struct flow_api_backend_s *be, enum hw_hst_e field, + int index, uint32_t value); +int hw_mod_hst_rcp_get(struct flow_api_backend_s *be, enum hw_hst_e field, + int index, uint32_t *value); + +struct flm_func_s { + COMMON_FUNC_INFO_S; + uint32_t nb_categories; + uint32_t nb_size_mb; + uint32_t nb_entry_size; + uint32_t nb_variant; + uint32_t nb_prios; + uint32_t nb_pst_profiles; + union { + struct hw_mod_flm_v17_s v17; + struct hw_mod_flm_v20_s v20; + }; +}; + +enum hw_flm_e { + /* functions */ + HW_FLM_CONTROL_PRESET_ALL = 0, + HW_FLM_RCP_PRESET_ALL, + HW_FLM_FLOW_LRN_DATA_V17, + HW_FLM_FLOW_INF_DATA_V17, + HW_FLM_FLOW_STA_DATA_V17, + /* Control fields */ + HW_FLM_CONTROL_ENABLE = FIELD_START_INDEX, + HW_FLM_CONTROL_INIT, + HW_FLM_CONTROL_LDS, + HW_FLM_CONTROL_LFS, + HW_FLM_CONTROL_LIS, + HW_FLM_CONTROL_UDS, + HW_FLM_CONTROL_UIS, + HW_FLM_CONTROL_RDS, + HW_FLM_CONTROL_RIS, + HW_FLM_CONTROL_PDS, + HW_FLM_CONTROL_PIS, + HW_FLM_CONTROL_CRCWR, + HW_FLM_CONTROL_CRCRD, + HW_FLM_CONTROL_RBL, + HW_FLM_CONTROL_EAB, + HW_FLM_CONTROL_SPLIT_SDRAM_USAGE, + HW_FLM_STATUS_CALIBDONE, + HW_FLM_STATUS_INITDONE, + HW_FLM_STATUS_IDLE, + HW_FLM_STATUS_CRITICAL, + HW_FLM_STATUS_PANIC, + HW_FLM_STATUS_CRCERR, + HW_FLM_STATUS_EFT_BP, + HW_FLM_TIMEOUT_T, + HW_FLM_SCRUB_I, + HW_FLM_LOAD_BIN, + HW_FLM_LOAD_PPS, + HW_FLM_LOAD_LPS, + HW_FLM_LOAD_APS, + HW_FLM_PRIO_LIMIT0, + HW_FLM_PRIO_FT0, + HW_FLM_PRIO_LIMIT1, + HW_FLM_PRIO_FT1, + HW_FLM_PRIO_LIMIT2, + HW_FLM_PRIO_FT2, + HW_FLM_PRIO_LIMIT3, + HW_FLM_PRIO_FT3, + HW_FLM_PST_PRESET_ALL, + HW_FLM_PST_BP, + HW_FLM_PST_PP, + HW_FLM_PST_TP, + HW_FLM_RCP_LOOKUP, + HW_FLM_RCP_QW0_DYN, + HW_FLM_RCP_QW0_OFS, + HW_FLM_RCP_QW0_SEL, + HW_FLM_RCP_QW4_DYN, + HW_FLM_RCP_QW4_OFS, + HW_FLM_RCP_SW8_DYN, + HW_FLM_RCP_SW8_OFS, + HW_FLM_RCP_SW8_SEL, + HW_FLM_RCP_SW9_DYN, + HW_FLM_RCP_SW9_OFS, + HW_FLM_RCP_MASK, + HW_FLM_RCP_KID, + HW_FLM_RCP_OPN, + HW_FLM_RCP_IPN, + HW_FLM_RCP_BYT_DYN, + HW_FLM_RCP_BYT_OFS, + HW_FLM_RCP_TXPLM, + HW_FLM_RCP_AUTO_IPV4_MASK, + HW_FLM_BUF_CTRL_LRN_FREE, + HW_FLM_BUF_CTRL_INF_AVAIL, + HW_FLM_BUF_CTRL_STA_AVAIL, + HW_FLM_STAT_LRN_DONE, + HW_FLM_STAT_LRN_IGNORE, + HW_FLM_STAT_LRN_FAIL, + HW_FLM_STAT_UNL_DONE, + HW_FLM_STAT_UNL_IGNORE, + HW_FLM_STAT_REL_DONE, + HW_FLM_STAT_REL_IGNORE, + HW_FLM_STAT_PRB_DONE, + HW_FLM_STAT_PRB_IGNORE, + HW_FLM_STAT_AUL_DONE, + HW_FLM_STAT_AUL_IGNORE, + HW_FLM_STAT_AUL_FAIL, + HW_FLM_STAT_TUL_DONE, + HW_FLM_STAT_FLOWS, + HW_FLM_STAT_STA_DONE, /* module ver 0.20 */ + HW_FLM_STAT_INF_DONE, /* module ver 0.20 */ + HW_FLM_STAT_INF_SKIP, /* module ver 0.20 */ + HW_FLM_STAT_PCK_HIT, /* module ver 0.20 */ + HW_FLM_STAT_PCK_MISS, /* module ver 0.20 */ + HW_FLM_STAT_PCK_UNH, /* module ver 0.20 */ + HW_FLM_STAT_PCK_DIS, /* module ver 0.20 */ + HW_FLM_STAT_CSH_HIT, /* module ver 0.20 */ + HW_FLM_STAT_CSH_MISS, /* module ver 0.20 */ + HW_FLM_STAT_CSH_UNH, /* module ver 0.20 */ + HW_FLM_STAT_CUC_START, /* module ver 0.20 */ + HW_FLM_STAT_CUC_MOVE, /* module ver 0.20 */ +}; + +bool hw_mod_flm_present(struct flow_api_backend_s *be); +int hw_mod_flm_alloc(struct flow_api_backend_s *be); +void hw_mod_flm_free(struct flow_api_backend_s *be); +int hw_mod_flm_reset(struct flow_api_backend_s *be); + +int hw_mod_flm_control_flush(struct flow_api_backend_s *be); +int hw_mod_flm_control_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value); +int hw_mod_flm_control_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value); + +int hw_mod_flm_status_flush(struct flow_api_backend_s *be); +int hw_mod_flm_status_update(struct flow_api_backend_s *be); +int hw_mod_flm_status_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value); +int hw_mod_flm_status_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value); + +int hw_mod_flm_timeout_flush(struct flow_api_backend_s *be); +int hw_mod_flm_timeout_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value); +int hw_mod_flm_timeout_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value); + +int hw_mod_flm_scrub_flush(struct flow_api_backend_s *be); +int hw_mod_flm_scrub_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value); +int hw_mod_flm_scrub_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value); + +int hw_mod_flm_load_bin_flush(struct flow_api_backend_s *be); +int hw_mod_flm_load_bin_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value); +int hw_mod_flm_load_bin_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value); + +int hw_mod_flm_load_pps_flush(struct flow_api_backend_s *be); +int hw_mod_flm_load_pps_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value); +int hw_mod_flm_load_pps_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value); + +int hw_mod_flm_load_lps_flush(struct flow_api_backend_s *be); +int hw_mod_flm_load_lps_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value); +int hw_mod_flm_load_lps_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value); + +int hw_mod_flm_load_aps_flush(struct flow_api_backend_s *be); +int hw_mod_flm_load_aps_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value); +int hw_mod_flm_load_aps_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value); + +int hw_mod_flm_prio_flush(struct flow_api_backend_s *be); +int hw_mod_flm_prio_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value); +int hw_mod_flm_prio_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value); + +int hw_mod_flm_pst_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_flm_pst_set(struct flow_api_backend_s *be, enum hw_flm_e field, + int index, uint32_t value); +int hw_mod_flm_pst_get(struct flow_api_backend_s *be, enum hw_flm_e field, + int index, uint32_t *value); + +int hw_mod_flm_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_flm_rcp_set_mask(struct flow_api_backend_s *be, enum hw_flm_e field, + int index, uint32_t *value); +int hw_mod_flm_rcp_set(struct flow_api_backend_s *be, enum hw_flm_e field, + int index, uint32_t value); +int hw_mod_flm_rcp_get(struct flow_api_backend_s *be, enum hw_flm_e field, + int index, uint32_t *value); + +int hw_mod_flm_buf_ctrl_update(struct flow_api_backend_s *be); +int hw_mod_flm_buf_ctrl_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value); + +int hw_mod_flm_stat_update(struct flow_api_backend_s *be); +int hw_mod_flm_stat_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value); + +int hw_mod_flm_lrn_data_set_flush(struct flow_api_backend_s *be, + enum hw_flm_e field, const uint32_t *value); +int hw_mod_flm_inf_data_update_get(struct flow_api_backend_s *be, + enum hw_flm_e field, uint32_t *value, + uint32_t word_cnt); +int hw_mod_flm_sta_data_update_get(struct flow_api_backend_s *be, + enum hw_flm_e field, uint32_t *value); + +struct hsh_func_s { + COMMON_FUNC_INFO_S; + uint32_t nb_rcp; + union { + struct hw_mod_hsh_v5_s v5; + }; +}; + +enum hw_hsh_e { + /* functions */ + HW_HSH_RCP_PRESET_ALL = 0, + HW_HSH_RCP_COMPARE, + HW_HSH_RCP_FIND, + /* fields */ + HW_HSH_RCP_LOAD_DIST_TYPE = FIELD_START_INDEX, + HW_HSH_RCP_MAC_PORT_MASK, + HW_HSH_RCP_SORT, + HW_HSH_RCP_QW0_PE, + HW_HSH_RCP_QW0_OFS, + HW_HSH_RCP_QW4_PE, + HW_HSH_RCP_QW4_OFS, + HW_HSH_RCP_W8_PE, + HW_HSH_RCP_W8_OFS, + HW_HSH_RCP_W8_SORT, + HW_HSH_RCP_W9_PE, + HW_HSH_RCP_W9_OFS, + HW_HSH_RCP_W9_SORT, + HW_HSH_RCP_W9_P, + HW_HSH_RCP_P_MASK, + HW_HSH_RCP_WORD_MASK, + HW_HSH_RCP_SEED, + HW_HSH_RCP_TNL_P, + HW_HSH_RCP_HSH_VALID, + HW_HSH_RCP_HSH_TYPE, + HW_HSH_RCP_AUTO_IPV4_MASK + +}; + +bool hw_mod_hsh_present(struct flow_api_backend_s *be); +int hw_mod_hsh_alloc(struct flow_api_backend_s *be); +void hw_mod_hsh_free(struct flow_api_backend_s *be); +int hw_mod_hsh_reset(struct flow_api_backend_s *be); +int hw_mod_hsh_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_hsh_rcp_set(struct flow_api_backend_s *be, enum hw_hsh_e field, + uint32_t index, uint32_t word_off, uint32_t value); +int hw_mod_hsh_rcp_get(struct flow_api_backend_s *be, enum hw_hsh_e field, + uint32_t index, uint32_t word_off, uint32_t *value); + +struct qsl_func_s { + COMMON_FUNC_INFO_S; + uint32_t nb_rcp_categories; + uint32_t nb_qst_entries; + union { + struct hw_mod_qsl_v7_s v7; + }; +}; + +enum hw_qsl_e { + /* functions */ + HW_QSL_RCP_PRESET_ALL = 0, + HW_QSL_RCP_COMPARE, + HW_QSL_RCP_FIND, + HW_QSL_QST_PRESET_ALL, + /* fields */ + HW_QSL_RCP_DISCARD = FIELD_START_INDEX, + HW_QSL_RCP_DROP, + HW_QSL_RCP_TBL_LO, + HW_QSL_RCP_TBL_HI, + HW_QSL_RCP_TBL_IDX, + HW_QSL_RCP_TBL_MSK, + HW_QSL_RCP_LR, + HW_QSL_RCP_TSA, + HW_QSL_RCP_VLI, + HW_QSL_QST_QUEUE, + HW_QSL_QST_EN, /* Alias: HW_QSL_QST_QEN */ + HW_QSL_QST_TX_PORT, + HW_QSL_QST_LRE, + HW_QSL_QST_TCI, + HW_QSL_QST_VEN, + HW_QSL_QEN_EN, + HW_QSL_UNMQ_DEST_QUEUE, + HW_QSL_UNMQ_EN, + +}; + +bool hw_mod_qsl_present(struct flow_api_backend_s *be); +int hw_mod_qsl_alloc(struct flow_api_backend_s *be); +void hw_mod_qsl_free(struct flow_api_backend_s *be); +int hw_mod_qsl_reset(struct flow_api_backend_s *be); +int hw_mod_qsl_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_qsl_rcp_set(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t value); +int hw_mod_qsl_rcp_get(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t *value); +int hw_mod_qsl_qst_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_qsl_qst_set(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t value); +int hw_mod_qsl_qst_get(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t *value); +int hw_mod_qsl_qen_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_qsl_qen_set(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t value); +int hw_mod_qsl_qen_get(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t *value); +int hw_mod_qsl_unmq_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_qsl_unmq_set(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t value); +int hw_mod_qsl_unmq_get(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t *value); + +struct slc_func_s { + COMMON_FUNC_INFO_S; + union { + struct hw_mod_slc_v1_s v1; + }; +}; + +enum hw_slc_e { + /* functions */ + HW_SLC_RCP_PRESET_ALL = 0, + HW_SLC_RCP_COMPARE, + HW_SLC_RCP_FIND, + /* fields */ + HW_SLC_RCP_SLC_EN = FIELD_START_INDEX, + HW_SLC_RCP_DYN, + HW_SLC_RCP_OFS, + HW_SLC_RCP_PCAP +}; + +bool hw_mod_slc_present(struct flow_api_backend_s *be); +int hw_mod_slc_alloc(struct flow_api_backend_s *be); +void hw_mod_slc_free(struct flow_api_backend_s *be); +int hw_mod_slc_reset(struct flow_api_backend_s *be); +int hw_mod_slc_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_slc_rcp_set(struct flow_api_backend_s *be, enum hw_slc_e field, + uint32_t index, uint32_t value); +int hw_mod_slc_rcp_get(struct flow_api_backend_s *be, enum hw_slc_e field, + uint32_t index, uint32_t *value); + +struct slc_lr_func_s { + COMMON_FUNC_INFO_S; + union { + struct hw_mod_slc_lr_v2_s v2; + }; +}; + +enum hw_slc_lr_e { + /* functions */ + HW_SLC_LR_RCP_PRESET_ALL = 0, + HW_SLC_LR_RCP_COMPARE, + HW_SLC_LR_RCP_FIND, + /* fields */ + HW_SLC_LR_RCP_SLC_EN = FIELD_START_INDEX, + HW_SLC_LR_RCP_DYN, + HW_SLC_LR_RCP_OFS, + HW_SLC_LR_RCP_PCAP +}; + +bool hw_mod_slc_lr_present(struct flow_api_backend_s *be); +int hw_mod_slc_lr_alloc(struct flow_api_backend_s *be); +void hw_mod_slc_lr_free(struct flow_api_backend_s *be); +int hw_mod_slc_lr_reset(struct flow_api_backend_s *be); +int hw_mod_slc_lr_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_slc_lr_rcp_set(struct flow_api_backend_s *be, enum hw_slc_lr_e field, + uint32_t index, uint32_t value); +int hw_mod_slc_lr_rcp_get(struct flow_api_backend_s *be, enum hw_slc_lr_e field, + uint32_t index, uint32_t *value); + +struct pdb_func_s { + COMMON_FUNC_INFO_S; + uint32_t nb_pdb_rcp_categories; + + union { + struct hw_mod_pdb_v9_s v9; + }; +}; + +enum hw_pdb_e { + /* functions */ + HW_PDB_RCP_PRESET_ALL = 0, + HW_PDB_RCP_COMPARE, + HW_PDB_RCP_FIND, + /* fields */ + HW_PDB_RCP_DESCRIPTOR = FIELD_START_INDEX, + HW_PDB_RCP_DESC_LEN, + HW_PDB_RCP_TX_PORT, + HW_PDB_RCP_TX_IGNORE, + HW_PDB_RCP_TX_NOW, + HW_PDB_RCP_CRC_OVERWRITE, + HW_PDB_RCP_ALIGN, + HW_PDB_RCP_OFS0_DYN, + HW_PDB_RCP_OFS0_REL, + HW_PDB_RCP_OFS1_DYN, + HW_PDB_RCP_OFS1_REL, + HW_PDB_RCP_OFS2_DYN, + HW_PDB_RCP_OFS2_REL, + HW_PDB_RCP_IP_PROT_TNL, + HW_PDB_RCP_PPC_HSH, + HW_PDB_RCP_DUPLICATE_EN, + HW_PDB_RCP_DUPLICATE_BIT, + HW_PDB_RCP_PCAP_KEEP_FCS, + HW_PDB_CONFIG_TS_FORMAT, + HW_PDB_CONFIG_PORT_OFS, +}; + +bool hw_mod_pdb_present(struct flow_api_backend_s *be); +int hw_mod_pdb_alloc(struct flow_api_backend_s *be); +void hw_mod_pdb_free(struct flow_api_backend_s *be); +int hw_mod_pdb_reset(struct flow_api_backend_s *be); +int hw_mod_pdb_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_pdb_rcp_set(struct flow_api_backend_s *be, enum hw_pdb_e field, + uint32_t index, uint32_t value); +int hw_mod_pdb_rcp_get(struct flow_api_backend_s *be, enum hw_pdb_e field, + uint32_t index, uint32_t *value); +int hw_mod_pdb_config_flush(struct flow_api_backend_s *be); +int hw_mod_pdb_config_set(struct flow_api_backend_s *be, enum hw_pdb_e field, + uint32_t value); + +struct ioa_func_s { + COMMON_FUNC_INFO_S; + uint32_t nb_rcp_categories; + uint32_t nb_roa_epp_entries; + union { + struct hw_mod_ioa_v4_s v4; + }; +}; + +enum hw_ioa_e { + /* functions */ + HW_IOA_RCP_PRESET_ALL = 0, + HW_IOA_RCP_COMPARE, + HW_IOA_RCP_FIND, + HW_IOA_ROA_EPP_PRESET_ALL, + HW_IOA_ROA_EPP_COMPARE, + HW_IOA_ROA_EPP_FIND, + /* fields */ + HW_IOA_RCP_TUNNEL_POP = FIELD_START_INDEX, + HW_IOA_RCP_VLAN_POP, + HW_IOA_RCP_VLAN_PUSH, + HW_IOA_RCP_VLAN_VID, + HW_IOA_RCP_VLAN_DEI, + HW_IOA_RCP_VLAN_PCP, + HW_IOA_RCP_VLAN_TPID_SEL, + HW_IOA_RCP_QUEUE_OVERRIDE_EN, + HW_IOA_RCP_QUEUE_ID, + HW_IOA_CONFIG_CUST_TPID_0, + HW_IOA_CONFIG_CUST_TPID_1, + HW_IOA_ROA_EPP_PUSH_TUNNEL, + HW_IOA_ROA_EPP_TX_PORT, +}; + +bool hw_mod_ioa_present(struct flow_api_backend_s *be); +int hw_mod_ioa_alloc(struct flow_api_backend_s *be); +void hw_mod_ioa_free(struct flow_api_backend_s *be); +int hw_mod_ioa_reset(struct flow_api_backend_s *be); +int hw_mod_ioa_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_ioa_rcp_set(struct flow_api_backend_s *be, enum hw_ioa_e field, + uint32_t index, uint32_t value); +int hw_mod_ioa_rcp_get(struct flow_api_backend_s *be, enum hw_ioa_e field, + uint32_t index, uint32_t *value); +int hw_mod_ioa_config_flush(struct flow_api_backend_s *be); +int hw_mod_ioa_config_set(struct flow_api_backend_s *be, enum hw_ioa_e field, + uint32_t value); + +int hw_mod_ioa_roa_epp_set(struct flow_api_backend_s *be, enum hw_ioa_e field, + uint32_t index, uint32_t value); +int hw_mod_ioa_roa_epp_get(struct flow_api_backend_s *be, enum hw_ioa_e field, + uint32_t index, uint32_t *value); +int hw_mod_ioa_roa_epp_flush(struct flow_api_backend_s *be, int start_idx, + int count); + +struct roa_func_s { + COMMON_FUNC_INFO_S; + uint32_t nb_tun_categories; + uint32_t nb_lag_entries; + union { + struct hw_mod_roa_v6_s v6; + }; +}; + +enum hw_roa_e { + /* functions */ + HW_ROA_TUNHDR_COMPARE = 0, + HW_ROA_TUNCFG_PRESET_ALL, + HW_ROA_TUNCFG_COMPARE, + HW_ROA_TUNCFG_FIND, + /* fields */ + HW_ROA_TUNHDR = FIELD_START_INDEX, + HW_ROA_TUNCFG_TUN_LEN, + HW_ROA_TUNCFG_TUN_TYPE, + HW_ROA_TUNCFG_TUN_VLAN, + HW_ROA_TUNCFG_IP_TYPE, + HW_ROA_TUNCFG_IPCS_UPD, + HW_ROA_TUNCFG_IPCS_PRECALC, + HW_ROA_TUNCFG_IPTL_UPD, + HW_ROA_TUNCFG_IPTL_PRECALC, + HW_ROA_TUNCFG_VXLAN_UDP_LEN_UPD, + HW_ROA_TUNCFG_TX_LAG_IX, + HW_ROA_TUNCFG_RECIRCULATE, + HW_ROA_TUNCFG_PUSH_TUNNEL, + HW_ROA_TUNCFG_RECIRC_PORT, + HW_ROA_TUNCFG_RECIRC_BYPASS, + HW_ROA_CONFIG_FWD_RECIRCULATE, + HW_ROA_CONFIG_FWD_NORMAL_PCKS, + HW_ROA_CONFIG_FWD_TXPORT0, + HW_ROA_CONFIG_FWD_TXPORT1, + HW_ROA_CONFIG_FWD_CELLBUILDER_PCKS, + HW_ROA_CONFIG_FWD_NON_NORMAL_PCKS, + HW_ROA_LAGCFG_TXPHY_PORT, + HW_ROA_IGS_PKT_DROP, + HW_ROA_IGS_BYTE_DROP, + HW_ROA_RCC_PKT_DROP, + HW_ROA_RCC_BYTE_DROP, +}; + +bool hw_mod_roa_present(struct flow_api_backend_s *be); +int hw_mod_roa_alloc(struct flow_api_backend_s *be); +void hw_mod_roa_free(struct flow_api_backend_s *be); +int hw_mod_roa_reset(struct flow_api_backend_s *be); +int hw_mod_roa_tunhdr_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_roa_tunhdr_set(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t index, uint32_t word_off, uint32_t value); +int hw_mod_roa_tunhdr_get(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t index, uint32_t word_off, uint32_t *value); +int hw_mod_roa_tuncfg_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_roa_tuncfg_set(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t index, uint32_t value); +int hw_mod_roa_tuncfg_get(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t index, uint32_t *value); +int hw_mod_roa_config_flush(struct flow_api_backend_s *be); +int hw_mod_roa_config_set(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t value); +int hw_mod_roa_config_get(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t *value); +int hw_mod_roa_lagcfg_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_roa_lagcfg_set(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t index, uint32_t value); +int hw_mod_roa_lagcfg_get(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t index, uint32_t *value); +int hw_mod_roa_igs_pkt_set(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t value); +int hw_mod_roa_igs_pkt_get(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t *value); +int hw_mod_roa_igs_pkt_flush(struct flow_api_backend_s *be); +int hw_mod_roa_igs_byte_set(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t value); +int hw_mod_roa_igs_byte_get(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t *value); +int hw_mod_roa_igs_byte_flush(struct flow_api_backend_s *be); +int hw_mod_roa_rcc_pkt_set(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t value); +int hw_mod_roa_rcc_pkt_get(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t *value); +int hw_mod_roa_rcc_pkt_flush(struct flow_api_backend_s *be); +int hw_mod_roa_rcc_byte_set(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t value); +int hw_mod_roa_rcc_byte_get(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t *value); +int hw_mod_roa_rcc_byte_flush(struct flow_api_backend_s *be); + +struct rmc_func_s { + COMMON_FUNC_INFO_S; + union { + struct hw_mod_rmc_v1_3_s v1_3; + }; +}; + +enum hw_rmc_e { + HW_RMC_BLOCK_STATT = FIELD_START_INDEX, + HW_RMC_BLOCK_KEEPA, + HW_RMC_BLOCK_RPP_SLICE, + HW_RMC_BLOCK_MAC_PORT, + HW_RMC_LAG_PHY_ODD_EVEN, +}; + +bool hw_mod_rmc_present(struct flow_api_backend_s *be); +int hw_mod_rmc_alloc(struct flow_api_backend_s *be); +void hw_mod_rmc_free(struct flow_api_backend_s *be); +int hw_mod_rmc_reset(struct flow_api_backend_s *be); +int hw_mod_rmc_ctrl_set(struct flow_api_backend_s *be, enum hw_rmc_e field, + uint32_t value); +int hw_mod_rmc_ctrl_get(struct flow_api_backend_s *be, enum hw_rmc_e field, + uint32_t *value); +int hw_mod_rmc_ctrl_flush(struct flow_api_backend_s *be); + +struct tpe_func_s { + COMMON_FUNC_INFO_S; + uint32_t nb_rcp_categories; + uint32_t nb_ifr_categories; + uint32_t nb_cpy_writers; + uint32_t nb_rpl_depth; + uint32_t nb_rpl_ext_categories; + union { + struct hw_mod_tpe_v1_s v1; + struct hw_mod_tpe_v2_s v2; + }; +}; + +enum hw_tpe_e { + /* functions */ + HW_TPE_PRESET_ALL = 0, + HW_TPE_FIND, + HW_TPE_COMPARE, + /* Control fields */ + HW_TPE_RPP_RCP_EXP = FIELD_START_INDEX, + HW_TPE_IFR_RCP_EN, + HW_TPE_IFR_RCP_MTU, + HW_TPE_INS_RCP_DYN, + HW_TPE_INS_RCP_OFS, + HW_TPE_INS_RCP_LEN, + HW_TPE_RPL_RCP_DYN, + HW_TPE_RPL_RCP_OFS, + HW_TPE_RPL_RCP_LEN, + HW_TPE_RPL_RCP_RPL_PTR, + HW_TPE_RPL_RCP_EXT_PRIO, + HW_TPE_RPL_EXT_RPL_PTR, + HW_TPE_RPL_EXT_META_RPL_LEN, /* SW only */ + HW_TPE_RPL_RPL_VALUE, + HW_TPE_CPY_RCP_READER_SELECT, + HW_TPE_CPY_RCP_DYN, + HW_TPE_CPY_RCP_OFS, + HW_TPE_CPY_RCP_LEN, + HW_TPE_HFU_RCP_LEN_A_WR, + HW_TPE_HFU_RCP_LEN_A_OUTER_L4_LEN, + HW_TPE_HFU_RCP_LEN_A_POS_DYN, + HW_TPE_HFU_RCP_LEN_A_POS_OFS, + HW_TPE_HFU_RCP_LEN_A_ADD_DYN, + HW_TPE_HFU_RCP_LEN_A_ADD_OFS, + HW_TPE_HFU_RCP_LEN_A_SUB_DYN, + HW_TPE_HFU_RCP_LEN_B_WR, + HW_TPE_HFU_RCP_LEN_B_POS_DYN, + HW_TPE_HFU_RCP_LEN_B_POS_OFS, + HW_TPE_HFU_RCP_LEN_B_ADD_DYN, + HW_TPE_HFU_RCP_LEN_B_ADD_OFS, + HW_TPE_HFU_RCP_LEN_B_SUB_DYN, + HW_TPE_HFU_RCP_LEN_C_WR, + HW_TPE_HFU_RCP_LEN_C_POS_DYN, + HW_TPE_HFU_RCP_LEN_C_POS_OFS, + HW_TPE_HFU_RCP_LEN_C_ADD_DYN, + HW_TPE_HFU_RCP_LEN_C_ADD_OFS, + HW_TPE_HFU_RCP_LEN_C_SUB_DYN, + HW_TPE_HFU_RCP_TTL_WR, + HW_TPE_HFU_RCP_TTL_POS_DYN, + HW_TPE_HFU_RCP_TTL_POS_OFS, + HW_TPE_HFU_RCP_CS_INF, + HW_TPE_HFU_RCP_L3_PRT, + HW_TPE_HFU_RCP_L3_FRAG, + HW_TPE_HFU_RCP_TUNNEL, + HW_TPE_HFU_RCP_L4_PRT, + HW_TPE_HFU_RCP_OUTER_L3_OFS, + HW_TPE_HFU_RCP_OUTER_L4_OFS, + HW_TPE_HFU_RCP_INNER_L3_OFS, + HW_TPE_HFU_RCP_INNER_L4_OFS, + HW_TPE_CSU_RCP_OUTER_L3_CMD, + HW_TPE_CSU_RCP_OUTER_L4_CMD, + HW_TPE_CSU_RCP_INNER_L3_CMD, + HW_TPE_CSU_RCP_INNER_L4_CMD, +}; + +bool hw_mod_tpe_present(struct flow_api_backend_s *be); +int hw_mod_tpe_alloc(struct flow_api_backend_s *be); +void hw_mod_tpe_free(struct flow_api_backend_s *be); +int hw_mod_tpe_reset(struct flow_api_backend_s *be); + +int hw_mod_tpe_rpp_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_tpe_rpp_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value); +int hw_mod_tpe_rpp_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value); + +int hw_mod_tpe_rpp_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_tpe_rpp_ifr_rcp_set(struct flow_api_backend_s *be, + enum hw_tpe_e field, int index, uint32_t value); +int hw_mod_tpe_rpp_ifr_rcp_get(struct flow_api_backend_s *be, + enum hw_tpe_e field, int index, uint32_t *value); + +int hw_mod_tpe_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_tpe_ifr_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value); +int hw_mod_tpe_ifr_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value); + +int hw_mod_tpe_ins_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_tpe_ins_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value); +int hw_mod_tpe_ins_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value); + +int hw_mod_tpe_rpl_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_tpe_rpl_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value); +int hw_mod_tpe_rpl_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value); + +int hw_mod_tpe_rpl_ext_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_tpe_rpl_ext_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value); +int hw_mod_tpe_rpl_ext_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value); + +int hw_mod_tpe_rpl_rpl_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_tpe_rpl_rpl_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value); +int hw_mod_tpe_rpl_rpl_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value); + +int hw_mod_tpe_cpy_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_tpe_cpy_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value); +int hw_mod_tpe_cpy_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value); + +int hw_mod_tpe_hfu_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_tpe_hfu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value); +int hw_mod_tpe_hfu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value); + +int hw_mod_tpe_csu_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count); +int hw_mod_tpe_csu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value); +int hw_mod_tpe_csu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value); + +enum debug_mode_e { + FLOW_BACKEND_DEBUG_MODE_NONE = 0x0000, + FLOW_BACKEND_DEBUG_MODE_WRITE = 0x0001 +}; + +struct flow_api_backend_ops { + int version; + int (*set_debug_mode)(void *dev, enum debug_mode_e mode); + int (*get_nb_phy_port)(void *dev); + int (*get_nb_rx_port)(void *dev); + int (*get_ltx_avail)(void *dev); + int (*get_nb_cat_funcs)(void *dev); + int (*get_nb_categories)(void *dev); + int (*get_nb_cat_km_if_cnt)(void *dev); + int (*get_nb_cat_km_if_m0)(void *dev); + int (*get_nb_cat_km_if_m1)(void *dev); + + int (*get_nb_queues)(void *dev); + int (*get_nb_km_flow_types)(void *dev); + int (*get_nb_pm_ext)(void *dev); + int (*get_nb_len)(void *dev); + int (*get_kcc_size)(void *dev); + int (*get_kcc_banks)(void *dev); + int (*get_nb_km_categories)(void *dev); + int (*get_nb_km_cam_banks)(void *dev); + int (*get_nb_km_cam_record_words)(void *dev); + int (*get_nb_km_cam_records)(void *dev); + int (*get_nb_km_tcam_banks)(void *dev); + int (*get_nb_km_tcam_bank_width)(void *dev); + int (*get_nb_flm_categories)(void *dev); + int (*get_nb_flm_size_mb)(void *dev); + int (*get_nb_flm_entry_size)(void *dev); + int (*get_nb_flm_variant)(void *dev); + int (*get_nb_flm_prios)(void *dev); + int (*get_nb_flm_pst_profiles)(void *dev); + int (*get_nb_hst_categories)(void *dev); + int (*get_nb_qsl_categories)(void *dev); + int (*get_nb_qsl_qst_entries)(void *dev); + int (*get_nb_pdb_categories)(void *dev); + int (*get_nb_ioa_categories)(void *dev); + int (*get_nb_roa_categories)(void *dev); + int (*get_nb_tpe_categories)(void *dev); + int (*get_nb_tx_cpy_writers)(void *dev); + int (*get_nb_tx_cpy_mask_mem)(void *dev); + int (*get_nb_tx_rpl_depth)(void *dev); + int (*get_nb_tx_rpl_ext_categories)(void *dev); + int (*get_nb_tpe_ifr_categories)(void *dev); + + int (*alloc_rx_queue)(void *dev, int queue_id); + int (*free_rx_queue)(void *dev, int hw_queue); + + /* CAT */ + bool (*get_cat_present)(void *dev); + uint32_t (*get_cat_version)(void *dev); + int (*cat_cfn_flush)(void *dev, const struct cat_func_s *cat, + int cat_func, int cnt); + int (*cat_kce_flush)(void *dev, const struct cat_func_s *cat, + int km_if_idx, int index, int cnt); + int (*cat_kcs_flush)(void *dev, const struct cat_func_s *cat, + int km_if_idx, int cat_func, int cnt); + int (*cat_fte_flush)(void *dev, const struct cat_func_s *cat, + int km_if_idx, int index, int cnt); + int (*cat_cte_flush)(void *dev, const struct cat_func_s *cat, + int cat_func, int cnt); + int (*cat_cts_flush)(void *dev, const struct cat_func_s *cat, int index, + int cnt); + int (*cat_cot_flush)(void *dev, const struct cat_func_s *cat, + int cat_func, int cnt); + int (*cat_cct_flush)(void *dev, const struct cat_func_s *cat, int index, + int cnt); + int (*cat_exo_flush)(void *dev, const struct cat_func_s *cat, int index, + int cnt); + int (*cat_rck_flush)(void *dev, const struct cat_func_s *cat, int index, + int cnt); + int (*cat_len_flush)(void *dev, const struct cat_func_s *cat, int index, + int cnt); + int (*cat_kcc_flush)(void *dev, const struct cat_func_s *cat, int index, + int cnt); + int (*cat_cce_flush)(void *dev, const struct cat_func_s *cat, int index, + int cnt); + int (*cat_ccs_flush)(void *dev, const struct cat_func_s *cat, int index, + int cnt); + + /* KM */ + bool (*get_km_present)(void *dev); + uint32_t (*get_km_version)(void *dev); + int (*km_rcp_flush)(void *dev, const struct km_func_s *km, int category, + int cnt); + int (*km_cam_flush)(void *dev, const struct km_func_s *km, int bank, + int record, int cnt); + int (*km_tcam_flush)(void *dev, const struct km_func_s *km, int bank, + int byte, int value, int cnt); + int (*km_tci_flush)(void *dev, const struct km_func_s *km, int bank, + int record, int cnt); + int (*km_tcq_flush)(void *dev, const struct km_func_s *km, int bank, + int record, int cnt); + + /* FLM */ + bool (*get_flm_present)(void *dev); + uint32_t (*get_flm_version)(void *dev); + int (*flm_control_flush)(void *dev, const struct flm_func_s *flm); + int (*flm_status_flush)(void *dev, const struct flm_func_s *flm); + int (*flm_status_update)(void *dev, const struct flm_func_s *flm); + int (*flm_timeout_flush)(void *dev, const struct flm_func_s *flm); + int (*flm_scrub_flush)(void *dev, const struct flm_func_s *flm); + int (*flm_load_bin_flush)(void *dev, const struct flm_func_s *flm); + int (*flm_load_pps_flush)(void *dev, const struct flm_func_s *flm); + int (*flm_load_lps_flush)(void *dev, const struct flm_func_s *flm); + int (*flm_load_aps_flush)(void *dev, const struct flm_func_s *flm); + int (*flm_prio_flush)(void *dev, const struct flm_func_s *flm); + int (*flm_pst_flush)(void *dev, const struct flm_func_s *flm, int index, + int cnt); + int (*flm_rcp_flush)(void *dev, const struct flm_func_s *flm, int index, + int cnt); + int (*flm_buf_ctrl_update)(void *dev, const struct flm_func_s *flm); + int (*flm_stat_update)(void *dev, const struct flm_func_s *flm); + int (*flm_lrn_data_flush)(void *be_dev, const struct flm_func_s *flm, + const uint32_t *lrn_data, uint32_t size); + int (*flm_inf_data_update)(void *be_dev, const struct flm_func_s *flm, + uint32_t *lrn_data, uint32_t size); + int (*flm_sta_data_update)(void *be_dev, const struct flm_func_s *flm, + uint32_t *lrn_data, uint32_t size); + + /* HSH */ + bool (*get_hsh_present)(void *dev); + uint32_t (*get_hsh_version)(void *dev); + int (*hsh_rcp_flush)(void *dev, const struct hsh_func_s *hsh, + int category, int cnt); + + /* HST */ + bool (*get_hst_present)(void *dev); + uint32_t (*get_hst_version)(void *dev); + int (*hst_rcp_flush)(void *dev, const struct hst_func_s *hst, + int category, int cnt); + + /* QSL */ + bool (*get_qsl_present)(void *dev); + uint32_t (*get_qsl_version)(void *dev); + int (*qsl_rcp_flush)(void *dev, const struct qsl_func_s *qsl, + int category, int cnt); + int (*qsl_qst_flush)(void *dev, const struct qsl_func_s *qsl, int entry, + int cnt); + int (*qsl_qen_flush)(void *dev, const struct qsl_func_s *qsl, int entry, + int cnt); + int (*qsl_unmq_flush)(void *dev, const struct qsl_func_s *qsl, + int entry, int cnt); + + /* SLC */ + bool (*get_slc_present)(void *dev); + uint32_t (*get_slc_version)(void *dev); + int (*slc_rcp_flush)(void *dev, const struct slc_func_s *slc, + int category, int cnt); + + /* SLC LR */ + bool (*get_slc_lr_present)(void *dev); + uint32_t (*get_slc_lr_version)(void *dev); + int (*slc_lr_rcp_flush)(void *dev, const struct slc_lr_func_s *slc_lr, + int category, int cnt); + + /* PDB */ + bool (*get_pdb_present)(void *dev); + uint32_t (*get_pdb_version)(void *dev); + int (*pdb_rcp_flush)(void *dev, const struct pdb_func_s *pdb, + int category, int cnt); + int (*pdb_config_flush)(void *dev, const struct pdb_func_s *pdb); + + /* IOA */ + bool (*get_ioa_present)(void *dev); + uint32_t (*get_ioa_version)(void *dev); + int (*ioa_rcp_flush)(void *dev, const struct ioa_func_s *ioa, int index, + int cnt); + int (*ioa_special_tpid_flush)(void *dev, const struct ioa_func_s *ioa); + int (*ioa_roa_epp_flush)(void *dev, const struct ioa_func_s *ioa, + int index, int cnt); + + /* ROA */ + bool (*get_roa_present)(void *dev); + uint32_t (*get_roa_version)(void *dev); + int (*roa_tunhdr_flush)(void *dev, const struct roa_func_s *roa, + int index, int cnt); + int (*roa_tuncfg_flush)(void *dev, const struct roa_func_s *roa, + int index, int cnt); + int (*roa_config_flush)(void *dev, const struct roa_func_s *roa); + int (*roa_lagcfg_flush)(void *dev, const struct roa_func_s *roa, + int index, int cnt); + + /* RMC */ + bool (*get_rmc_present)(void *dev); + uint32_t (*get_rmc_version)(void *dev); + int (*rmc_ctrl_flush)(void *dev, const struct rmc_func_s *rmc); + + /* TPE */ + bool (*get_tpe_present)(void *dev); + uint32_t (*get_tpe_version)(void *dev); + int (*tpe_rpp_rcp_flush)(void *dev, const struct tpe_func_s *tpe, + int index, int cnt); + int (*tpe_rpp_ifr_rcp_flush)(void *dev, const struct tpe_func_s *tpe, + int index, int cnt); + int (*tpe_ifr_rcp_flush)(void *dev, const struct tpe_func_s *tpe, + int index, int cnt); + int (*tpe_ins_rcp_flush)(void *dev, const struct tpe_func_s *tpe, + int index, int cnt); + int (*tpe_rpl_rcp_flush)(void *dev, const struct tpe_func_s *tpe, + int index, int cnt); + int (*tpe_rpl_ext_flush)(void *dev, const struct tpe_func_s *tpe, + int index, int cnt); + int (*tpe_rpl_rpl_flush)(void *dev, const struct tpe_func_s *tpe, + int index, int cnt); + int (*tpe_cpy_rcp_flush)(void *dev, const struct tpe_func_s *tpe, + int index, int cnt); + int (*tpe_hfu_rcp_flush)(void *dev, const struct tpe_func_s *tpe, + int index, int cnt); + int (*tpe_csu_rcp_flush)(void *dev, const struct tpe_func_s *tpe, + int index, int cnt); +}; + +struct flow_api_backend_s { + void *be_dev; + const struct flow_api_backend_ops *iface; + + /* flow filter FPGA modules */ + struct cat_func_s cat; + struct km_func_s km; + struct flm_func_s flm; + struct hsh_func_s hsh; + struct hst_func_s hst; + struct qsl_func_s qsl; + struct slc_func_s slc; + struct slc_lr_func_s slc_lr; + struct pdb_func_s pdb; + struct ioa_func_s ioa; + struct roa_func_s roa; + struct rmc_func_s rmc; + struct tpe_func_s tpe; + + /* NIC attributes */ + unsigned int num_phy_ports; + unsigned int num_rx_ports; + + /* flow filter resource capacities */ + unsigned int max_categories; + unsigned int max_queues; +}; + +int flow_api_backend_init(struct flow_api_backend_s *dev, + const struct flow_api_backend_ops *iface, + void *be_dev); +int flow_api_backend_reset(struct flow_api_backend_s *dev); +int flow_api_backend_done(struct flow_api_backend_s *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* __FLOW_API_BACKEND_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_engine.h b/drivers/net/ntnic/nthw/flow_api/flow_api_engine.h new file mode 100644 index 0000000000..bee12b71f7 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_api_engine.h @@ -0,0 +1,475 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _FLOW_API_ENGINE_H_ +#define _FLOW_API_ENGINE_H_ + +#include +#include "stream_binary_flow_api.h" + +struct flow_elem; +/* + * **************************************************** + * Resource management + * **************************************************** + */ +#define BIT_CONTAINER_8_ALIGN(x) (((x) + 7) / 8) + +/* + * Resource management + * These are free resources in FPGA + * Other FPGA memory lists are linked to one of these + * and will implicitly follow them + */ +enum res_type_e { + RES_QUEUE, + RES_CAT_CFN, + RES_CAT_COT, + RES_CAT_EXO, + RES_CAT_LEN, + RES_KM_FLOW_TYPE, + RES_KM_CATEGORY, + RES_HSH_RCP, + RES_PDB_RCP, + RES_QSL_RCP, + RES_QSL_QST, + RES_SLC_RCP, + RES_IOA_RCP, + RES_ROA_RCP, + RES_FLM_FLOW_TYPE, + RES_FLM_RCP, + RES_HST_RCP, + RES_TPE_RCP, + RES_TPE_EXT, + RES_TPE_RPL, + RES_COUNT, + RES_INVALID +}; + +/* + * **************************************************** + * Flow NIC offload management + * **************************************************** + */ +#define MAX_OUTPUT_DEST (128) +#define NB_QSL_QEN_ADDR 32 + +#define INVALID_FLOW_STAT_ID 0xffffffff + +#define MAX_WORD_NUM 24 +#define MAX_BANKS 6 + +#define MAX_TCAM_START_OFFSETS 4 + +#define MAX_TAG_INDEX 8 + +#define MAX_FLM_MTRS_SUPPORTED 4 +#define MAX_CPY_WRITERS_SUPPORTED 8 + +/* + * 128 128 32 32 32 + * Have | QW0 || QW4 || SW8 || SW9 | SWX in FPGA + * + * Each word may start at any offset, though + * they are combined in chronological order, with all enabled to + * build the extracted match data, thus that is how the match key + * must be build + * + */ +enum extractor_e { + KM_USE_EXTRACTOR_UNDEF, + KM_USE_EXTRACTOR_QWORD, + KM_USE_EXTRACTOR_SWORD, +}; + +struct match_elem_s { + enum extractor_e extr; + int masked_for_tcam; /* if potentially selected for TCAM */ + uint32_t e_word[4]; + uint32_t e_mask[4]; + + int extr_start_offs_id; + int8_t rel_offs; + uint32_t word_len; +}; + +enum cam_tech_use_e { KM_CAM, KM_TCAM, KM_SYNERGY }; + +#define MAX_MATCH_FIELDS 16 + +struct km_flow_def_s { + struct flow_api_backend_s *be; + + /* For keeping track of identical entries */ + struct km_flow_def_s *reference; + struct km_flow_def_s *root; + + /* For collect flow elements and sorting */ + struct match_elem_s match[MAX_MATCH_FIELDS]; + struct match_elem_s *match_map[MAX_MATCH_FIELDS]; + int num_ftype_elem; + + /* Finally formatted CAM/TCAM entry */ + enum cam_tech_use_e target; + uint32_t entry_word[MAX_WORD_NUM]; + uint32_t entry_mask[MAX_WORD_NUM]; + int key_word_size; + + /* TCAM calculated possible bank start offsets */ + int start_offsets[MAX_TCAM_START_OFFSETS]; + int num_start_offsets; + + /* Flow information */ + + /* + * HW input port ID needed for compare. In port must be identical on flow + * types + */ + uint32_t port_id; + uint32_t info; /* used for color (actions) */ + int info_set; + int flow_type; /* 0 is illegal and used as unset */ + int flushed_to_target; /* if this km entry has been finally programmed into NIC hw */ + + /* CAM specific bank management */ + int cam_paired; + int record_indexes[MAX_BANKS]; + int bank_used; + uint32_t *cuckoo_moves; /* for CAM statistics only */ + struct cam_distrib_s *cam_dist; + struct hasher_s *hsh; + + /* TCAM specific bank management */ + struct tcam_distrib_s *tcam_dist; + int tcam_start_bank; + int tcam_record; +}; + +/* + * KCC-CAM + */ +struct kcc_key_s { + uint64_t sb_data : 32; + uint64_t sb_type : 8; + uint64_t cat_cfn : 8; + uint64_t port : 16; +}; + +#define KCC_ID_INVALID 0xffffffff + +struct kcc_flow_def_s { + struct flow_api_backend_s *be; + union { + uint64_t key64; + uint32_t key32[2]; + struct kcc_key_s key; + }; + uint32_t km_category; + uint32_t id; + + uint8_t *kcc_unique_ids; + + int flushed_to_target; + int record_indexes[MAX_BANKS]; + int bank_used; + uint32_t *cuckoo_moves; /* for CAM statistics only */ + struct kcc_cam_distrib_s *cam_dist; + struct hasher_s *hsh; +}; + +/* + * Tunnel encapsulation header definition + */ +enum { TUN_TYPE_VXLAN = 0, TUN_TYPE_NVGRE = 1 }; + +#define MAX_TUN_HDR_SIZE 128 + +struct tunnel_header_s { + union { + uint8_t hdr8[MAX_TUN_HDR_SIZE]; + uint32_t hdr32[(MAX_TUN_HDR_SIZE + 3) / 4]; + } d; + uint32_t user_port_id; + uint8_t len; + + uint8_t nb_vlans; + + uint8_t ip_version; /* 4: v4, 6: v6 */ + uint16_t ip_csum_precalc; + + uint8_t new_outer; + uint8_t l2_len; + uint8_t l3_len; + uint8_t l4_len; +}; + +enum port_type_e { + PORT_NONE, /* not defined or drop */ + PORT_INTERNAL, /* no queues attached */ + PORT_PHY, /* MAC phy output queue */ + PORT_VIRT, /* Memory queues to Host */ +}; + +enum special_partial_match_e { + SPCIAL_MATCH_NONE, + SPECIAL_MATCH_LACP, +}; + +#define PORT_ID_NONE 0xffffffff + +struct output_s { + uint32_t owning_port_id; /* the port who owns this output destination */ + enum port_type_e type; + int id; /* depending on port type: queue ID or physical port id or not used */ + int active; /* activated */ +}; + +struct nic_flow_def { + /* + * Frame Decoder match info collected + */ + int l2_prot; + int l3_prot; + int l4_prot; + int tunnel_prot; + int tunnel_l3_prot; + int tunnel_l4_prot; + int vlans; + int fragmentation; + /* + * Additional meta data for various functions + */ + int in_port_override; + int l4_dst_port; + /* + * Output destination info collection + */ + struct output_s dst_id[MAX_OUTPUT_DEST]; /* define the output to use */ + /* total number of available queues defined for all outputs - i.e. number of dst_id's */ + int dst_num_avail; + + /* + * To identify high priority match with mark for special SW processing (non-OVS) + */ + enum special_partial_match_e special_match; + + /* + * Mark or Action info collection + */ + uint32_t mark; + uint64_t roa_actions; + uint64_t ioa_actions; + + uint32_t jump_to_group; + + uint32_t mtr_ids[MAX_FLM_MTRS_SUPPORTED]; + + int full_offload; + /* + * Action push tunnel + */ + struct tunnel_header_s tun_hdr; + + /* + * If DPDK RTE tunnel helper API used + * this holds the tunnel if used in flow + */ + struct tunnel_s *tnl; + + /* + * Header Stripper + */ + int header_strip_start_dyn; + int header_strip_start_ofs; + int header_strip_end_dyn; + int header_strip_end_ofs; + int header_strip_removed_outer_ip; + + /* + * Modify field + */ + struct { + uint32_t select; + uint32_t dyn; + uint32_t ofs; + uint32_t len; + uint32_t level; + union { + uint8_t value8[16]; + uint16_t value16[8]; + uint32_t value32[4]; + }; + } modify_field[MAX_CPY_WRITERS_SUPPORTED]; + + uint32_t modify_field_count; + uint8_t ttl_sub_enable; + uint8_t ttl_sub_ipv4; + uint8_t ttl_sub_outer; + + /* + * Key Matcher flow definitions + */ + struct km_flow_def_s km; + + /* + * Key Matcher Category CAM + */ + struct kcc_flow_def_s *kcc; + int kcc_referenced; + + /* + * TX fragmentation IFR/RPP_LR MTU recipe + */ + uint8_t flm_mtu_fragmentation_recipe; +}; + +enum flow_handle_type { + FLOW_HANDLE_TYPE_FLOW, + FLOW_HANDLE_TYPE_FLM, +}; + +struct flow_handle { + enum flow_handle_type type; + + struct flow_eth_dev *dev; + struct flow_handle *next; + struct flow_handle *prev; + + union { + struct { + /* + * 1st step conversion and validation of flow + * verified and converted flow match + actions structure + */ + struct nic_flow_def *fd; + /* + * 2nd step NIC HW resource allocation and configuration + * NIC resource management structures + */ + struct { + int index; /* allocation index into NIC raw resource table */ + /* number of contiguous allocations needed for this resource */ + int count; + /* + * This resource if not initially created by this flow, but reused + * by it + */ + int referenced; + } resource[RES_COUNT]; + int flushed; + + uint32_t flow_stat_id; + uint32_t color; + int cao_enabled; + uint32_t cte; + + uint32_t port_id; /* MAC port ID or override of virtual in_port */ + uint32_t flm_ref_count; + uint8_t flm_group_index; + uint8_t flm_ft_index; + }; + + struct { + uint32_t flm_data[10]; + uint8_t flm_prot; + uint8_t flm_kid; + uint8_t flm_prio; + + uint16_t flm_rpl_ext_ptr; + uint32_t flm_nat_ipv4; + uint16_t flm_nat_port; + uint8_t flm_dscp; + uint32_t flm_teid; + uint8_t flm_rqi; + uint8_t flm_qfi; + + uint8_t flm_mtu_fragmentation_recipe; + + struct flow_handle *flm_owner; + }; + }; +}; + +void km_attach_ndev_resource_management(struct km_flow_def_s *km, + void **handle); +void km_free_ndev_resource_management(void **handle); + +int km_get_cam_population_level(void *cam_dist, uint32_t *cam_elem, + uint32_t *cuckoo_moves); + +int km_add_match_elem(struct km_flow_def_s *km, uint32_t e_word[4], + uint32_t e_mask[4], uint32_t word_len, + enum frame_offs_e start, int8_t offset); + +int km_key_create(struct km_flow_def_s *km, uint32_t port_id); +/* + * Compares 2 KM key definitions after first collect validate and optimization. + * km is compared against an existing km1. + * if identical, km1 flow_type is returned + */ +int km_key_compare(struct km_flow_def_s *km, struct km_flow_def_s *km1); + +void km_set_info(struct km_flow_def_s *km, int on); +int km_rcp_set(struct km_flow_def_s *km, int index); + +int km_refer_data_match_entry(struct km_flow_def_s *km, + struct km_flow_def_s *km1); +int km_write_data_match_entry(struct km_flow_def_s *km, uint32_t color); +int km_clear_data_match_entry(struct km_flow_def_s *km); + +void kcc_attach_ndev_resource_management(struct kcc_flow_def_s *kcc, + void **handle); +void kcc_free_ndev_resource_management(void **handle); +int kcc_alloc_unique_id(struct kcc_flow_def_s *kcc); +void kcc_free_unique_id(struct kcc_flow_def_s *kcc); +int kcc_key_compare(struct kcc_flow_def_s *kcc, struct kcc_flow_def_s *kcc1); +int kcc_add_km_category(struct kcc_flow_def_s *kcc, uint32_t category); + +int kcc_key_add_no_sideband(struct kcc_flow_def_s *kcc); +int kcc_key_add_vlan(struct kcc_flow_def_s *kcc, uint16_t tpid, uint16_t vid); +int kcc_key_add_vxlan(struct kcc_flow_def_s *kcc, uint32_t vni); +int kcc_key_add_port(struct kcc_flow_def_s *kcc, uint16_t port); +int kcc_key_add_cat_cfn(struct kcc_flow_def_s *kcc, uint8_t cat_cfn); +uint8_t kcc_key_get_cat_cfn(struct kcc_flow_def_s *kcc); + +int kcc_write_data_match_entry(struct kcc_flow_def_s *kcc); +int kcc_key_ref_count_add(struct kcc_flow_def_s *kcc); +int kcc_key_ref_count_dec(struct kcc_flow_def_s *kcc); + +/* + * Group management + */ +int flow_group_handle_create(void **handle, uint32_t group_count); +int flow_group_handle_destroy(void **handle); + +int flow_group_translate_get(void *handle, uint8_t owner_id, uint32_t group_in, + uint32_t *group_out); +int flow_group_translate_release(void *handle, uint32_t translated_group); + +/* + * Actions management + */ +uint8_t flow_tunnel_alloc_virt_port(void); +uint8_t flow_tunnel_free_virt_port(uint8_t virt_port); +struct tunnel_s *tunnel_parse(const struct flow_elem *elem, int *idx, + uint32_t *vni); +int tunnel_release(struct tunnel_s *tnl); +uint8_t get_tunnel_vport(struct tunnel_s *rtnl); +void tunnel_set_flow_stat_id(struct tunnel_s *rtnl, uint32_t flow_stat_id); +int tunnel_get_definition(struct tunnel_cfg_s *tun, uint32_t flow_stat_id, + uint8_t vport); + +int is_virtual_port(uint8_t virt_port); +int flow_tunnel_create_vxlan_hdr(struct flow_api_backend_s *be, + struct nic_flow_def *fd, + const struct flow_elem *elem); + +/* + * statistics + */ +uint32_t flow_actions_create_flow_stat_id(uint32_t *stat_map, uint32_t mark); +void flow_actions_delete_flow_stat_id(uint32_t *stat_map, + uint32_t flow_stat_id); + +#endif /* _FLOW_API_ENGINE_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h b/drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h new file mode 100644 index 0000000000..c4db0f4c5c --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_API_NIC_SETUP_H__ +#define __FLOW_API_NIC_SETUP_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct flow_api_backend_ops; /* Operation list for common FPGA module API for backend */ +struct flow_nic_dev; /* adapter device */ + +/* + * Flow capable NIC backend - creating flow api instance for adapter nr (backend) + */ +struct flow_nic_dev *flow_api_create(uint8_t adapter_no, + const struct flow_api_backend_ops *be_if, + void *be_dev); +int flow_api_done(struct flow_nic_dev *dev); +void *flow_api_get_be_dev(struct flow_nic_dev *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* __FLOW_API_NIC_SETUP_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c new file mode 100644 index 0000000000..9b6e5484a0 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "flow_api_backend.h" +#include "flow_api_engine.h" + +#include +#include + +#define OWNER_ID_COUNT 256 + +struct group_lookup_entry_s { + uint64_t ref_counter; + uint32_t *reverse_lookup; +}; + +struct group_handle_s { + uint32_t group_count; + + uint32_t *translation_table; + + struct group_lookup_entry_s *lookup_entries; +}; + +int flow_group_handle_create(void **handle, uint32_t group_count) +{ + struct group_handle_s *group_handle; + + *handle = calloc(1, sizeof(struct group_handle_s)); + group_handle = *handle; + + group_handle->group_count = group_count; + group_handle->translation_table = calloc((uint32_t)(group_count * OWNER_ID_COUNT), + sizeof(uint32_t)); + group_handle->lookup_entries = + calloc(group_count, sizeof(struct group_lookup_entry_s)); + + return *handle != NULL ? 0 : -1; +} + +int flow_group_handle_destroy(void **handle) +{ + if (*handle) { + struct group_handle_s *group_handle = + (struct group_handle_s *)*handle; + + free(group_handle->translation_table); + free(group_handle->lookup_entries); + + free(*handle); + *handle = NULL; + } + + return 0; +} + +int flow_group_translate_get(void *handle, uint8_t owner_id, uint32_t group_in, + uint32_t *group_out) +{ + struct group_handle_s *group_handle = (struct group_handle_s *)handle; + uint32_t *table_ptr; + uint32_t lookup; + + if (group_handle == NULL || group_in >= group_handle->group_count) + return -1; + + /* Don't translate group 0 */ + if (group_in == 0) { + *group_out = 0; + return 0; + } + + table_ptr = &group_handle->translation_table[owner_id * OWNER_ID_COUNT + + group_in]; + lookup = *table_ptr; + + if (lookup == 0) { + for (lookup = 1; + lookup < group_handle->group_count && + group_handle->lookup_entries[lookup].ref_counter > 0; + ++lookup) + ; + + if (lookup < group_handle->group_count) { + group_handle->lookup_entries[lookup].reverse_lookup = + table_ptr; + group_handle->lookup_entries[lookup].ref_counter += 1; + + *table_ptr = lookup; + } else { + return -1; + } + } else { + group_handle->lookup_entries[lookup].ref_counter += 1; + } + *group_out = lookup; + return 0; +} + +int flow_group_translate_release(void *handle, uint32_t translated_group) +{ + struct group_handle_s *group_handle = (struct group_handle_s *)handle; + struct group_lookup_entry_s *lookup; + + if (group_handle == NULL || + translated_group >= group_handle->group_count) + return -1; + + /* Don't translate group 0 */ + if (translated_group == 0) + return 0; + + lookup = &group_handle->lookup_entries[translated_group]; + + if (lookup->reverse_lookup && lookup->ref_counter > 0) { + lookup->ref_counter -= 1; + if (lookup->ref_counter == 0) { + *lookup->reverse_lookup = 0; + lookup->reverse_lookup = NULL; + } + } + + return 0; +} diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c new file mode 100644 index 0000000000..6982129e17 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c @@ -0,0 +1,213 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "flow_hasher.h" + +#include + +/* #define TESTING */ + +#ifdef TESTING +#include +int hash_test(struct hasher_s *hsh, int banks, int record_bw); +#endif + +static uint32_t shuffle(uint32_t x) +{ + return (((x & 0x00000002) << 29) | ((x & 0xAAAAAAA8) >> 3) | + ((x & 0x15555555) << 3) | ((x & 0x40000000) >> 29)); +} + +static uint32_t ror_inv(uint32_t x, const int s) +{ + return ((x >> s) | ((~x) << (32 - s))); +} + +static uint32_t combine(uint32_t x, uint32_t y) +{ + uint32_t x1 = ror_inv(x, 15); + uint32_t x2 = ror_inv(x, 13); + uint32_t y1 = ror_inv(y, 3); + uint32_t y2 = ror_inv(y, 27); + + return (x ^ y ^ + ((x1 & y1 & ~x2 & ~y2) | (x1 & ~y1 & x2 & ~y2) | + (x1 & ~y1 & ~x2 & y2) | (~x1 & y1 & x2 & ~y2) | + (~x1 & y1 & ~x2 & y2) | (~x1 & ~y1 & x2 & y2))); +} + +static uint32_t mix(uint32_t x, uint32_t y) +{ + return shuffle(combine(x, y)); +} + +static uint64_t ror_inv3(uint64_t x) +{ + const uint64_t m = 0xE0000000E0000000ULL; + + return (((x >> 3) | m) ^ ((x << 29) & m)); +} + +static uint64_t ror_inv13(uint64_t x) +{ + const uint64_t m = 0xFFF80000FFF80000ULL; + + return (((x >> 13) | m) ^ ((x << 19) & m)); +} + +static uint64_t ror_inv15(uint64_t x) +{ + const uint64_t m = 0xFFFE0000FFFE0000ULL; + + return (((x >> 15) | m) ^ ((x << 17) & m)); +} + +static uint64_t ror_inv27(uint64_t x) +{ + const uint64_t m = 0xFFFFFFE0FFFFFFE0ULL; + + return (((x >> 27) | m) ^ ((x << 5) & m)); +} + +static uint64_t shuffle64(uint64_t x) +{ + return (((x & 0x0000000200000002) << 29) | + ((x & 0xAAAAAAA8AAAAAAA8) >> 3) | + ((x & 0x1555555515555555) << 3) | + ((x & 0x4000000040000000) >> 29)); +} + +static uint64_t pair(uint32_t x, uint32_t y) +{ + return (((uint64_t)x << 32) | y); +} + +static uint64_t combine64(uint64_t x, uint64_t y) +{ + uint64_t x1 = ror_inv15(x); + uint64_t x2 = ror_inv13(x); + uint64_t y1 = ror_inv3(y); + uint64_t y2 = ror_inv27(y); + + return (x ^ y ^ + ((x1 & y1 & ~x2 & ~y2) | (x1 & ~y1 & x2 & ~y2) | + (x1 & ~y1 & ~x2 & y2) | (~x1 & y1 & x2 & ~y2) | + (~x1 & y1 & ~x2 & y2) | (~x1 & ~y1 & x2 & y2))); +} + +static uint64_t mix64(uint64_t x, uint64_t y) +{ + return shuffle64(combine64(x, y)); +} + +static uint32_t calc16(const uint32_t key[16]) +{ + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Layer 0 */ + /* \./ \./ \./ \./ \./ \./ \./ \./ */ + /* 0 1 2 3 4 5 6 7 Layer 1 */ + /* \__.__/ \__.__/ \__.__/ \__.__/ */ + /* 0 1 2 3 Layer 2 */ + /* \______.______/ \______.______/ */ + /* 0 1 Layer 3 */ + /* \______________.______________/ */ + /* 0 Layer 4 */ + /* / \ */ + /* \./ */ + /* 0 Layer 5 */ + /* / \ */ + /* \./ Layer 6 */ + /* value */ + + uint64_t z; + uint32_t x; + + z = mix64(mix64(mix64(pair(key[0], key[8]), pair(key[1], key[9])), + mix64(pair(key[2], key[10]), pair(key[3], key[11]))), + mix64(mix64(pair(key[4], key[12]), pair(key[5], key[13])), + mix64(pair(key[6], key[14]), pair(key[7], key[15])))); + + x = mix((uint32_t)(z >> 32), (uint32_t)z); + x = mix(x, ror_inv(x, 17)); + x = combine(x, ror_inv(x, 17)); + + return x; +} + +uint32_t gethash(struct hasher_s *hsh, const uint32_t key[16], int *result) +{ + uint64_t val; + uint32_t res; + + val = calc16(key); + res = (uint32_t)val; + + if (hsh->cam_bw > 32) + val = (val << (hsh->cam_bw - 32)) ^ val; + + for (int i = 0; i < hsh->banks; i++) { + result[i] = (unsigned int)(val & hsh->cam_records_bw_mask); + val = val >> hsh->cam_records_bw; + } + return res; +} + +int init_hasher(struct hasher_s *hsh, int banks, int nb_records) +{ + hsh->banks = banks; + hsh->cam_records_bw = (int)(log2(nb_records - 1) + 1); + hsh->cam_records_bw_mask = (1U << hsh->cam_records_bw) - 1; + hsh->cam_bw = hsh->banks * hsh->cam_records_bw; + +#ifdef TESTING + int res = hash_test(hsh, _banks, (int)log2(nb_records - 1) + 1); + + if (res) + printf("ERROR: testing hasher\n"); +#endif + + return 0; +} + +#ifdef TESTING +int hash_test(struct hasher_s *hsh, int banks, int record_bw) +{ + int res = 0; + int val[10], resval[10]; + uint32_t bits = 0; + + uint32_t inval[16] = { 0xaaaabbbb, 0xccccdddd, 0xeeeeffff, 0x88881111 }; + const uint32_t result = 0xACECAE65; + + for (int i = 0; i < 16; i++) + printf("%08x,", inval[i]); + printf("\nbanks %i, records bit width: %i\n", banks, record_bw); + + uint32_t ret = gethash(hsh, inval, val); + + printf("Return VAL = %08X == %08X\n", ret, result); + res += (ret != result) ? 1 : 0; + + int shft = (banks * record_bw) - 32; + int mask = (1 << record_bw) - 1; + + if (shft > 0) { + bits = (ret >> (32 - shft)); + ret ^= ret << shft; + } + + resval[0] = ret & mask; + ret >>= record_bw; + resval[1] = ret & mask; + ret >>= record_bw; + resval[2] = ret & mask; + resval[2] |= (bits << (record_bw - shft)); + + for (int i = 0; i < 3; i++) { + printf("HASH %i: %i == %i\n", i, val[i], resval[i]); + res += (val[i] != resval[i]) ? 1 : 0; + } + + return res; +} +#endif diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h new file mode 100644 index 0000000000..6365a396d2 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _FLOW_HASHER_H_ +#define _FLOW_HASHER_H_ + +#include + +struct hasher_s { + int banks; + int cam_records_bw; + uint32_t cam_records_bw_mask; + int cam_bw; +}; + +int init_hasher(struct hasher_s *hsh, int banks, int nb_records); +uint32_t gethash(struct hasher_s *hsh, const uint32_t key[16], int *result); + +#endif /* _FLOW_HASHER_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c new file mode 100644 index 0000000000..ddf1742588 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c @@ -0,0 +1,434 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include "flow_api_backend.h" +#include "flow_api_engine.h" +#include "flow_hasher.h" + +/* + * KCC-CAM structures and defines + */ +struct kcc_cam_distrib_s { + struct kcc_flow_def_s *kcc_owner; + int ref_cnt; +}; + +#define BE_CAM_KCC_DIST_IDX(bnk) \ + ({ \ + int _temp_bnk = (bnk); \ + (_temp_bnk * kcc->be->cat.kcc_records + kcc->record_indexes[_temp_bnk]); \ + }) + + +#define BE_CAM_ENTRIES \ + (kcc->be->cat.kcc_size * sizeof(struct kcc_cam_distrib_s)) +#define BE_UNIQUE_IDS_SIZE ((1U << kcc->be->cat.kcc_id_bit_size) / 8) + +#define KCC_CUCKOO_MOVE_MAX_DEPTH 8 +static int kcc_cam_addr_reserved_stack[KCC_CUCKOO_MOVE_MAX_DEPTH]; + +void kcc_attach_ndev_resource_management(struct kcc_flow_def_s *kcc, + void **handle) +{ + /* + * KCC entries occupied in CAM - to manage the cuckoo shuffling + * and manage CAM population and usage + */ + if (!*handle) { + *handle = calloc(1, BE_CAM_ENTRIES + sizeof(uint32_t) + + BE_UNIQUE_IDS_SIZE + + sizeof(struct hasher_s)); + NT_LOG(DBG, FILTER, + "Allocate NIC DEV KCC-CAM record manager\n"); + } + kcc->cam_dist = (struct kcc_cam_distrib_s *)*handle; + kcc->cuckoo_moves = + (uint32_t *)((char *)kcc->cam_dist + BE_CAM_ENTRIES); + kcc->kcc_unique_ids = (uint8_t *)((char *)kcc->cam_dist + + BE_CAM_ENTRIES + sizeof(uint32_t)); + + kcc->hsh = (struct hasher_s *)((char *)kcc->kcc_unique_ids + + BE_UNIQUE_IDS_SIZE); + init_hasher(kcc->hsh, kcc->be->cat.kcc_banks, kcc->be->cat.kcc_records); +} + +void kcc_free_ndev_resource_management(void **handle) +{ + if (*handle) { + free(*handle); + NT_LOG(DBG, FILTER, "Free NIC DEV KCC-CAM record manager\n"); + } + *handle = NULL; +} + +/* + * Key for KCC CAM + */ +int kcc_key_add_no_sideband(struct kcc_flow_def_s *kcc) +{ + kcc->key.sb_data = 0xffffffff; + kcc->key.sb_type = 0; + return 0; +} + +int kcc_key_add_vlan(struct kcc_flow_def_s *kcc, uint16_t tpid, uint16_t vid) +{ + kcc->key.sb_data = ((uint32_t)tpid << 16) | (vid & 0x0fff); + kcc->key.sb_type = 1; + return 0; +} + +int kcc_key_add_vxlan(struct kcc_flow_def_s *kcc, uint32_t vni) +{ + kcc->key.sb_data = (vni & 0x00ffffff) | 0x02000000; + kcc->key.sb_type = 2; + return 0; +} + +int kcc_key_add_port(struct kcc_flow_def_s *kcc, uint16_t port) +{ + kcc->key.port = port; + return 0; +} + +int kcc_key_add_cat_cfn(struct kcc_flow_def_s *kcc, uint8_t cat_cfn) +{ + kcc->key.cat_cfn = cat_cfn; + return 0; +} + +uint8_t kcc_key_get_cat_cfn(struct kcc_flow_def_s *kcc) +{ + return kcc->key.cat_cfn; +} + +/* + * other settings for KCC CAM + */ +int kcc_add_km_category(struct kcc_flow_def_s *kcc, uint32_t category) +{ + kcc->km_category = category; + return 0; +} + +int kcc_alloc_unique_id(struct kcc_flow_def_s *kcc) +{ + uint32_t i, ii; + /* search a free unique ID in allocation bitmap */ + for (i = 0; i < BE_UNIQUE_IDS_SIZE; i++) + if (kcc->kcc_unique_ids[i] != 0xff) + break; + + if (i == BE_UNIQUE_IDS_SIZE) + return -1; + + for (ii = 0; ii < 8; ii++) { + if ((kcc->kcc_unique_ids[i] & (uint8_t)(1U << ii)) == 0) { + kcc->kcc_unique_ids[i] = + (uint8_t)(kcc->kcc_unique_ids[i] | + (uint8_t)(1U << ii)); + kcc->id = (uint16_t)(i * 8 + ii); + NT_LOG(DBG, FILTER, "Allocate new KCC ID : %i\n", + kcc->id); + return (int)kcc->id; + } + } + return -1; +} + +void kcc_free_unique_id(struct kcc_flow_def_s *kcc) +{ + if (kcc->id == KCC_ID_INVALID) + return; + + uint32_t idx = kcc->id >> 3; + uint8_t shft = (uint8_t)(kcc->id & 7); + + assert(idx < BE_UNIQUE_IDS_SIZE); + if (idx < BE_UNIQUE_IDS_SIZE) { + assert(kcc->kcc_unique_ids[idx] & (uint8_t)(1 << shft)); + kcc->kcc_unique_ids[idx] &= (uint8_t)~(1 << shft); + NT_LOG(DBG, FILTER, "Free KCC ID : %i\n", kcc->id); + kcc->id = KCC_ID_INVALID; + } +} + +int kcc_key_compare(struct kcc_flow_def_s *kcc, struct kcc_flow_def_s *kcc1) +{ + if (kcc->key64 == kcc1->key64) + return 1; + return 0; +} + +static int kcc_cam_populate(struct kcc_flow_def_s *kcc, int bank) +{ + int res; + int idx = bank * kcc->be->cat.kcc_records + kcc->record_indexes[bank]; + + res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 0, + kcc->key32[0]); + if (res) + return -1; + res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 1, + kcc->key32[1]); + if (res) + return -1; + res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_CATEGORY, idx, 0, + kcc->km_category); + if (res) + return -1; + res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_ID, idx, 0, kcc->id); + if (res) + return -1; + res = hw_mod_cat_kcc_flush(kcc->be, idx, 1); + + kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].kcc_owner = kcc; + kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].ref_cnt = 1; + return res; +} + +static int kcc_cam_reset_entry(struct kcc_flow_def_s *kcc, int bank) +{ + int res = 0; + int idx = bank * kcc->be->cat.kcc_records + kcc->record_indexes[bank]; + + res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 0, 0); + if (res) + return -1; + res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 1, 0); + if (res) + return -1; + res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_CATEGORY, idx, 0, 0); + if (res) + return -1; + res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_ID, idx, 0, 0); + if (res) + return -1; + res = hw_mod_cat_kcc_flush(kcc->be, idx, 1); + + kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].kcc_owner = NULL; + kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].ref_cnt = 0; + + kcc->key64 = 0UL; + kcc->km_category = 0; + /* "kcc->id" holds an allocated unique id, so cleared/freed later */ + return res; +} + +static int kcc_move_cuckoo_index(struct kcc_flow_def_s *kcc) +{ + assert(kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)].kcc_owner); + + for (uint32_t bank = 0; bank < kcc->be->cat.kcc_banks; bank++) { + /* It will not select itself */ + if (kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].kcc_owner == + NULL) { + /* + * Populate in new position + */ + int res = kcc_cam_populate(kcc, bank); + + if (res) { + NT_LOG(DBG, FILTER, + "Error: failed to write to KM CAM in cuckoo move\n"); + return 0; + } + + /* + * Reset/free entry in old bank + * HW flushes are really not needed, the old addresses are always taken over + * by the caller If you change this code in future updates, this may no + * longer be true then! + */ + kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)] + .kcc_owner = NULL; + NT_LOG(DBG, FILTER, + "KCC Cuckoo hash moved from bank %i to bank %i (%04X => %04X)\n", + kcc->bank_used, bank, + BE_CAM_KCC_DIST_IDX(kcc->bank_used), + BE_CAM_KCC_DIST_IDX(bank)); + + kcc->bank_used = bank; + (*kcc->cuckoo_moves)++; + return 1; + } + } + return 0; +} + +static int kcc_move_cuckoo_index_level(struct kcc_flow_def_s *kcc_parent, + int bank_idx, int levels, + int cam_adr_list_len) +{ + struct kcc_flow_def_s *kcc = kcc_parent->cam_dist[bank_idx].kcc_owner; + + assert(levels <= KCC_CUCKOO_MOVE_MAX_DEPTH); + + if (kcc_move_cuckoo_index(kcc)) + return 1; + if (levels <= 1) + return 0; + + assert(cam_adr_list_len < KCC_CUCKOO_MOVE_MAX_DEPTH); + + kcc_cam_addr_reserved_stack[cam_adr_list_len++] = bank_idx; + + for (uint32_t i = 0; i < kcc->be->cat.kcc_banks; i++) { + int reserved = 0; + int new_idx = BE_CAM_KCC_DIST_IDX(i); + + for (int i_reserved = 0; i_reserved < cam_adr_list_len; + i_reserved++) { + if (kcc_cam_addr_reserved_stack[i_reserved] == + new_idx) { + reserved = 1; + break; + } + } + if (reserved) + continue; + + int res = kcc_move_cuckoo_index_level(kcc, new_idx, levels - 1, + cam_adr_list_len); + if (res) { + if (kcc_move_cuckoo_index(kcc)) + return 1; + + else + assert(0); + } + } + + return 0; +} + +static uint32_t kcc_hsh_key[16]; + +static int kcc_write_data_to_cam(struct kcc_flow_def_s *kcc) +{ + int res = 0; + int val[MAX_BANKS]; + + kcc_hsh_key[0] = kcc->key32[1]; + kcc_hsh_key[1] = kcc->key32[0]; + NT_LOG(DBG, FILTER, "TEMP TEMP TEMP"); + NT_LOG(DBG, FILTER, "Hash key[0] %08x", kcc_hsh_key[0]); + NT_LOG(DBG, FILTER, "Hash key[1] %08x", kcc_hsh_key[1]); + NT_LOG(DBG, FILTER, "TEMP TEMP TEMP - swapped"); + + /* 2-15 never changed - remains zero */ + + gethash(kcc->hsh, kcc_hsh_key, val); + + for (uint32_t i = 0; i < kcc->be->cat.kcc_banks; i++) + kcc->record_indexes[i] = val[i]; + NT_LOG(DBG, FILTER, "KCC HASH [%03X, %03X, %03X]\n", + kcc->record_indexes[0], kcc->record_indexes[1], + kcc->record_indexes[2]); + + int bank = -1; + /* + * first step, see if any of the banks are free + */ + for (uint32_t i_bank = 0; i_bank < kcc->be->cat.kcc_banks; i_bank++) { + if (kcc->cam_dist[BE_CAM_KCC_DIST_IDX(i_bank)].kcc_owner == + NULL) { + bank = i_bank; + break; + } + } + + if (bank < 0) { + /* + * Second step - cuckoo move existing flows if possible + */ + for (uint32_t i_bank = 0; i_bank < kcc->be->cat.kcc_banks; + i_bank++) { + if (kcc_move_cuckoo_index_level(kcc, + BE_CAM_KCC_DIST_IDX(i_bank), + 4, 0)) { + bank = i_bank; + break; + } + } + + if (bank < 0) + return -1; + } + + /* populate CAM */ + NT_LOG(DBG, FILTER, "KCC Bank = %i (addr %04X)\n", bank, + BE_CAM_KCC_DIST_IDX(bank)); + res = kcc_cam_populate(kcc, bank); + if (res == 0) { + kcc->flushed_to_target = 1; + kcc->bank_used = bank; + } else { + NT_LOG(DBG, FILTER, "KCC CAM populate failed\n"); + } + return res; +} + +int kcc_write_data_match_entry(struct kcc_flow_def_s *kcc) +{ + int res = -1; + + NT_LOG(DBG, FILTER, + "KCC Write Data entry. Create New Key: %016lx, KM category %i, id %i\n", + kcc->key64, kcc->km_category, kcc->id); + res = kcc_write_data_to_cam(kcc); + return res; +} + +static int kcc_clear_data_match_entry(struct kcc_flow_def_s *kcc) +{ + int res = 0; + + if (kcc->flushed_to_target) { + res = kcc_cam_reset_entry(kcc, kcc->bank_used); + kcc->flushed_to_target = 0; + kcc->bank_used = 0; + } + return res; +} + +int kcc_key_ref_count_add(struct kcc_flow_def_s *kcc) +{ + assert(kcc->bank_used >= 0 && + kcc->bank_used < (int)kcc->be->cat.kcc_banks); + + struct kcc_cam_distrib_s *cam_entry = + &kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)]; + + NT_LOG(DBG, FILTER, + "KCC ADD Ref existing Key: %016lx, KM category %i, id %i (new ref count %i)\n", + kcc->key64, kcc->km_category, kcc->id, cam_entry->ref_cnt + 1); + return ++cam_entry->ref_cnt; +} + +int kcc_key_ref_count_dec(struct kcc_flow_def_s *kcc) +{ + if (kcc->bank_used < 0 || kcc->bank_used >= (int)kcc->be->cat.kcc_banks) + return -1; + + struct kcc_cam_distrib_s *cam_entry = + &kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)]; + + if (cam_entry->ref_cnt) { + if (--cam_entry->ref_cnt == 0) { + kcc_clear_data_match_entry(kcc); + NT_LOG(DBG, FILTER, + "KCC DEC Ref on Key became zero - Delete\n"); + } + } + + NT_LOG(DBG, FILTER, + "KCC DEC Ref on Key: %016lx, KM category %i, id %i (new ref count %i)\n", + kcc->key64, kcc->km_category, kcc->id, cam_entry->ref_cnt); + return cam_entry->ref_cnt; +} diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c new file mode 100644 index 0000000000..560be9f7d3 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c @@ -0,0 +1,1434 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include + +#include "flow_api_backend.h" +#include "flow_api_engine.h" +#include "flow_hasher.h" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +static const struct cam_match_masks_s { + uint32_t word_len; + uint32_t key_mask[4]; +} cam_masks[] = { + { 4, + { 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff + } + }, /* IP6_SRC, IP6_DST */ + { 4, + { 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000 + } + }, /* DMAC,SMAC,ethtype */ + { 4, + { 0xffffffff, 0xffff0000, 0x00000000, + 0xffff0000 + } + }, /* DMAC,ethtype */ + { 4, + { 0x00000000, 0x0000ffff, 0xffffffff, + 0xffff0000 + } + }, /* SMAC,ethtype */ + { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000 } }, /* ETH_128 */ + { 2, + { 0xffffffff, 0xffffffff, 0x00000000, + 0x00000000 + } + }, /* IP4_COMBINED */ + { 1, { 0xffffffff, 0x00000000, 0x00000000, 0x00000000 } }, + /* + * ETH_TYPE, IP4_TTL_PROTO, IP4_SRC, IP4_DST, IP6_FLOW_TC, + * IP6_NEXT_HDR_HOP, TP_PORT_COMBINED, SIDEBAND_VNI + */ + { 1, + { 0xffff0000, 0x00000000, 0x00000000, + 0x00000000 + } + }, /* IP4_IHL_TOS, TP_PORT_SRC32_OR_ICMP, TCP_CTRL */ + { 1, + { 0x0000ffff, 0x00000000, 0x00000000, + 0x00000000 + } + }, /* TP_PORT_DST32 */ + { 1, + { 0x00030000, 0x00000000, 0x00000000, + 0x00000000 + } + }, /* IPv4 TOS mask bits used often by OVS */ + { 1, + { 0x00300000, 0x00000000, 0x00000000, + 0x00000000 + } + }, /* IPv6 TOS mask bits used often by OVS */ +}; + +#define NUM_CAM_MASKS (ARRAY_SIZE(cam_masks)) + +/* + * CAM structures and defines + */ +struct cam_distrib_s { + struct km_flow_def_s *km_owner; +}; + +#define CAM_DIST_IDX(bnk, rec) ((bnk) * km->be->km.nb_cam_records + (rec)) +#define CAM_KM_DIST_IDX(bnk) \ + ({ \ + int _temp_bnk = (bnk); \ + CAM_DIST_IDX(_temp_bnk, km->record_indexes[_temp_bnk]); \ + }) + +#define CUCKOO_MOVE_MAX_DEPTH 8 +static int cam_addr_reserved_stack[CUCKOO_MOVE_MAX_DEPTH]; + +/* + * TCAM structures and defines + */ +struct tcam_distrib_s { + struct km_flow_def_s *km_owner; +}; + +#define TCAM_DIST_IDX(bnk, rec) ((bnk) * km->be->km.nb_tcam_bank_width + (rec)) + +static int tcam_find_mapping(struct km_flow_def_s *km); + +void km_attach_ndev_resource_management(struct km_flow_def_s *km, void **handle) +{ +#define CAM_ENTRIES \ + (km->be->km.nb_cam_banks * km->be->km.nb_cam_records * \ + sizeof(struct cam_distrib_s)) +#define TCAM_ENTRIES \ + (km->be->km.nb_tcam_bank_width * km->be->km.nb_tcam_banks * \ + sizeof(struct tcam_distrib_s)) + /* + * KM entries occupied in CAM - to manage the cuckoo shuffling + * and manage CAM population and usage + * KM entries occupied in TCAM - to manage population and usage + */ + if (!*handle) { + *handle = calloc(1, (size_t)CAM_ENTRIES + sizeof(uint32_t) + + (size_t)TCAM_ENTRIES + + sizeof(struct hasher_s)); + NT_LOG(DBG, FILTER, + "Allocate NIC DEV CAM and TCAM record manager\n"); + } + km->cam_dist = (struct cam_distrib_s *)*handle; + km->cuckoo_moves = (uint32_t *)((char *)km->cam_dist + CAM_ENTRIES); + km->tcam_dist = + (struct tcam_distrib_s *)((char *)km->cam_dist + CAM_ENTRIES + + sizeof(uint32_t)); + + km->hsh = (struct hasher_s *)((char *)km->tcam_dist + TCAM_ENTRIES); + init_hasher(km->hsh, km->be->km.nb_cam_banks, + km->be->km.nb_cam_records); +} + +void km_free_ndev_resource_management(void **handle) +{ + if (*handle) { + free(*handle); + NT_LOG(DBG, FILTER, + "Free NIC DEV CAM and TCAM record manager\n"); + } + *handle = NULL; +} + +int km_add_match_elem(struct km_flow_def_s *km, uint32_t e_word[4], + uint32_t e_mask[4], uint32_t word_len, + enum frame_offs_e start_id, int8_t offset) +{ +#ifdef FLOW_DEBUG + char *s = ntlog_helper_str_alloc("MATCH: "); + + for (unsigned int i = 0; i < word_len; i++) + ntlog_helper_str_add(s, "%08x, ", e_word[i]); + NT_LOG(DBG, FILTER, "%s", s); + ntlog_helper_str_reset(s, "MASK : "); + for (unsigned int i = 0; i < word_len; i++) + ntlog_helper_str_add(s, "%08x, ", e_mask[i]); + NT_LOG(DBG, FILTER, "%s", s); + ntlog_helper_str_free(s); +#endif + + /* valid word_len 1,2,4 */ + if (word_len == 3) { + word_len = 4; + e_word[3] = 0; + e_mask[3] = 0; + } + if (word_len < 1 || word_len > 4) { + assert(0); + return -1; + } + + for (unsigned int i = 0; i < word_len; i++) { + km->match[km->num_ftype_elem].e_word[i] = e_word[i]; + km->match[km->num_ftype_elem].e_mask[i] = e_mask[i]; + } + + km->match[km->num_ftype_elem].word_len = word_len; + km->match[km->num_ftype_elem].rel_offs = offset; + km->match[km->num_ftype_elem].extr_start_offs_id = start_id; + + /* + * Determine here if this flow may better be put into TCAM + * Otherwise it will go into CAM + * This is dependent on a cam_masks list defined above + */ + km->match[km->num_ftype_elem].masked_for_tcam = 1; + for (unsigned int msk = 0; msk < NUM_CAM_MASKS; msk++) { + if (word_len == cam_masks[msk].word_len) { + int match = 1; + + for (unsigned int wd = 0; wd < word_len; wd++) { + if (e_mask[wd] != cam_masks[msk].key_mask[wd]) { + match = 0; + break; + } + } + if (match) { + /* Can go into CAM */ + km->match[km->num_ftype_elem].masked_for_tcam = + 0; + } + } + } + + km->num_ftype_elem++; + return 0; +} + +void km_set_info(struct km_flow_def_s *km, int on) +{ + km->info_set = !!on; +} + +static int get_word(struct km_flow_def_s *km, uint32_t size, int marked[]) +{ + for (int i = 0; i < km->num_ftype_elem; i++) { + if (!marked[i] && + !(km->match[i].extr_start_offs_id & SWX_INFO) && + km->match[i].word_len == size) + return i; + } + return -1; +} + +#ifdef FLOW_DEBUG +static const char *get_prot_offset_descr(int idx) +{ + switch (idx) { + case DYN_SOF: + return "SOF"; + case DYN_L2: + return "L2 header"; + case DYN_FIRST_VLAN: + return "First VLAN"; + case DYN_MPLS: + return "First MPLS"; + case DYN_L3: + return "L3 header"; + case DYN_ID_IPV4_6: + return "ID field IPv4/6"; + case DYN_FINAL_IP_DST: + return "Final IP dest"; + case DYN_L4: + return "L4 header"; + case DYN_L4_PAYLOAD: + return "L4 payload"; + case DYN_TUN_PAYLOAD: + return "Tunnel payload"; + case DYN_TUN_L2: + return "Tunnel L2 header"; + case DYN_TUN_VLAN: + return "First tunneled VLAN"; + case DYN_TUN_MPLS: + return "First tunneled MPLS"; + case DYN_TUN_L3: + return "Tunnel L3 header"; + case DYN_TUN_ID_IPV4_6: + return "Tunnel ID field IPv4/6"; + case DYN_TUN_FINAL_IP_DST: + return "Tunnel final IP dest"; + case DYN_TUN_L4: + return "Tunnel L4 header"; + case DYN_TUN_L4_PAYLOAD: + return "Tunnel L4 payload"; + case SB_VNI: + return "VNI"; + case SB_MAC_PORT: + return "In Port"; + case SB_KCC_ID: + return "KCC ID"; + default: + break; + } + return ""; +} +#endif + +#define MAX_QWORDS 2 +#define MAX_SWORDS 2 + +int km_key_create(struct km_flow_def_s *km, uint32_t port_id) +{ + /* + * Create combined extractor mappings + * if key fields may be changed to cover un-mappable otherwise? + * split into cam and tcam and use synergy mode when available + * + */ + int match_marked[MAX_MATCH_FIELDS]; + int idx = 0; + int next = 0; + int m_idx; + int size; + + memset(match_marked, 0, sizeof(match_marked)); + + /* build QWords */ + for (int qwords = 0; qwords < MAX_QWORDS; qwords++) { + size = 4; + m_idx = get_word(km, size, match_marked); + if (m_idx < 0) { + size = 2; + m_idx = get_word(km, size, match_marked); + + if (m_idx < 0) { + size = 1; + m_idx = get_word(km, 1, match_marked); + } + } + if (m_idx < 0) { + /* no more defined */ + break; + } + + match_marked[m_idx] = 1; + + /* build match map list and set final extractor to use */ + km->match_map[next] = &km->match[m_idx]; + km->match[m_idx].extr = KM_USE_EXTRACTOR_QWORD; + + /* build final entry words and mask array */ + for (int i = 0; i < size; i++) { + km->entry_word[idx + i] = km->match[m_idx].e_word[i]; + km->entry_mask[idx + i] = km->match[m_idx].e_mask[i]; + } + + idx += size; + next++; + } + + m_idx = get_word(km, 4, match_marked); + if (m_idx >= 0) { + /* cannot match more QWords */ + return -1; + } + + /* + * On km v6+ we have DWORDs here instead. However, we only use them as SWORDs for now + * No match would be able to exploit these as DWORDs because of maximum length of 12 words + * in CAM + * The last 2 words are taken by KCC-ID/SWX and Color. You could have one or none QWORDs + * where then both these DWORDs were possible in 10 words, but we don't have such use case + * built in yet + */ + /* build SWords */ + for (int swords = 0; swords < MAX_SWORDS; swords++) { + m_idx = get_word(km, 1, match_marked); + if (m_idx < 0) { + /* no more defined */ + break; + } + + match_marked[m_idx] = 1; + /* build match map list and set final extractor to use */ + km->match_map[next] = &km->match[m_idx]; + km->match[m_idx].extr = KM_USE_EXTRACTOR_SWORD; + + /* build final entry words and mask array */ + km->entry_word[idx] = km->match[m_idx].e_word[0]; + km->entry_mask[idx] = km->match[m_idx].e_mask[0]; + idx++; + next++; + } + + /* + * Make sure we took them all + */ + m_idx = get_word(km, 1, match_marked); + if (m_idx >= 0) { + /* cannot match more SWords */ + return -1; + } + + /* + * Handle SWX words specially + */ + int swx_found = 0; + + for (int i = 0; i < km->num_ftype_elem; i++) { + if (km->match[i].extr_start_offs_id & SWX_INFO) { + km->match_map[next] = &km->match[i]; + km->match[i].extr = KM_USE_EXTRACTOR_SWORD; + /* build final entry words and mask array */ + km->entry_word[idx] = km->match[i].e_word[0]; + km->entry_mask[idx] = km->match[i].e_mask[0]; + idx++; + next++; + swx_found = 1; + } + } + + assert(next == km->num_ftype_elem); + + km->key_word_size = idx; + km->port_id = port_id; + + km->target = KM_CAM; + /* + * Finally decide if we want to put this match->action into the TCAM + * When SWX word used we need to put it into CAM always, no matter what mask pattern + * Later, when synergy mode is applied, we can do a split + */ + if (!swx_found && km->key_word_size <= 6) { + for (int i = 0; i < km->num_ftype_elem; i++) { + if (km->match_map[i]->masked_for_tcam) { + /* At least one */ + km->target = KM_TCAM; + } + } + } + + NT_LOG(DBG, FILTER, "This flow goes into %s\n", + (km->target == KM_TCAM) ? "TCAM" : "CAM"); + + if (km->target == KM_TCAM) { + if (km->key_word_size > 10) { + /* do not support SWX in TCAM */ + return -1; + } + /* + * adjust for unsupported key word size in TCAM + */ + if ((km->key_word_size == 5 || km->key_word_size == 7 || + km->key_word_size == 9)) { + km->entry_mask[km->key_word_size] = 0; + km->key_word_size++; + } + + /* + * 1. the fact that the length of a key cannot change among the same used banks + * + * calculate possible start indexes + * unfortunately restrictions in TCAM lookup + * makes it hard to handle key lengths larger than 6 + * when other sizes should be possible too + */ + switch (km->key_word_size) { + case 1: + for (int i = 0; i < 4; i++) + km->start_offsets[0] = 8 + i; + km->num_start_offsets = 4; + break; + case 2: + km->start_offsets[0] = 6; + km->num_start_offsets = 1; + break; + case 3: + km->start_offsets[0] = 0; + km->num_start_offsets = 1; + /* enlarge to 6 */ + km->entry_mask[km->key_word_size++] = 0; + km->entry_mask[km->key_word_size++] = 0; + km->entry_mask[km->key_word_size++] = 0; + break; + case 4: + km->start_offsets[0] = 0; + km->num_start_offsets = 1; + /* enlarge to 6 */ + km->entry_mask[km->key_word_size++] = 0; + km->entry_mask[km->key_word_size++] = 0; + break; + case 6: + km->start_offsets[0] = 0; + km->num_start_offsets = 1; + break; + + default: + NT_LOG(DBG, FILTER, + "Final Key word size too large: %i\n", + km->key_word_size); + return -1; + } + +#ifdef FLOW_DEBUG + char *s = ntlog_helper_str_alloc("TCAM offs: "); + + for (int i = 0; i < km->num_start_offsets; i++) + ntlog_helper_str_add(s, "%i,", km->start_offsets[i]); + NT_LOG(DBG, FILTER, "%s", s); + ntlog_helper_str_free(s); +#endif + } + +#ifdef FLOW_DEBUG + for (int i = 0; i < km->num_ftype_elem; i++) { + NT_LOG(DBG, FILTER, + "size %i -> Extr: %s, offset id: %s, rel offset: %i\n", + km->match_map[i]->word_len, + (km->match_map[i]->extr_start_offs_id & SWX_INFO) ? + "SIDEBAND" : + km->match_map[i]->extr == KM_USE_EXTRACTOR_SWORD ? + "SWORD" : + "QWORD", + get_prot_offset_descr(km->match_map[i]->extr_start_offs_id), + km->match_map[i]->rel_offs); + } + char *s = ntlog_helper_str_alloc(""); + + for (int i = 0; i < km->key_word_size; i++) + ntlog_helper_str_add(s, "%08x,", km->entry_word[i]); + + NT_LOG(DBG, FILTER, "%s", s); + + ntlog_helper_str_reset(s, ""); + for (int i = 0; i < km->key_word_size; i++) + ntlog_helper_str_add(s, "%08x,", km->entry_mask[i]); + + NT_LOG(DBG, FILTER, "%s", s); + ntlog_helper_str_free(s); +#endif + + return 0; +} + +int km_key_compare(struct km_flow_def_s *km, struct km_flow_def_s *km1) +{ + if (km->target != km1->target || + km->num_ftype_elem != km1->num_ftype_elem || + km->key_word_size != km1->key_word_size || + km->info_set != km1->info_set) + return 0; + + /* + * before KCC-CAM: + * if port is added to match, then we can have different ports in CAT + * that reuses this flow type + */ + int port_match_included = 0, kcc_swx_used = 0; + + for (int i = 0; i < km->num_ftype_elem; i++) { + if (km->match[i].extr_start_offs_id == SB_MAC_PORT) { + port_match_included = 1; + break; + } else if (km->match_map[i]->extr_start_offs_id == SB_KCC_ID) { + kcc_swx_used = 1; + break; + } + } + + /* + * If not using KCC and if port match is not included in CAM, + * we need to have same port_id to reuse + */ + if (!kcc_swx_used && !port_match_included && + km->port_id != km1->port_id) + return 0; + + for (int i = 0; i < km->num_ftype_elem; i++) { + /* using same extractor types in same sequence */ + if (km->match_map[i]->extr_start_offs_id != km1->match_map[i]->extr_start_offs_id || + km->match_map[i]->rel_offs != km1->match_map[i]->rel_offs || + km->match_map[i]->extr != km1->match_map[i]->extr || + km->match_map[i]->word_len != km1->match_map[i]->word_len) + return 0; + } + + if (km->target == KM_CAM) { + /* in CAM must exactly match on all masks */ + for (int i = 0; i < km->key_word_size; i++) { + if (km->entry_mask[i] != km1->entry_mask[i]) + return 0; + } + + /* Would be set later if not reusing from km1 */ + km->cam_paired = km1->cam_paired; + } else if (km->target == KM_TCAM) { + /* + * If TCAM, we must make sure Recipe Key Mask does not + * mask out enable bits in masks + * Note: it is important that km1 is the original creator + * of the KM Recipe, since it contains its true masks + */ + for (int i = 0; i < km->key_word_size; i++) { + if ((km->entry_mask[i] & km1->entry_mask[i]) != + km->entry_mask[i]) + return 0; + } + + km->tcam_start_bank = km1->tcam_start_bank; + km->tcam_record = -1; /* needs to be found later */ + } else { + NT_LOG(DBG, FILTER, + "ERROR - KM target not defined or supported\n"); + return 0; + } + + /* + * Check for a flow clash. If already programmed return with -1 + */ + int double_match = 1; + + for (int i = 0; i < km->key_word_size; i++) { + if ((km->entry_word[i] & km->entry_mask[i]) != + (km1->entry_word[i] & km1->entry_mask[i])) { + double_match = 0; + break; + } + } + + if (double_match) + return -1; + + /* + * Note that TCAM and CAM may reuse same RCP and flow type + * when this happens, CAM entry wins on overlap + */ + + /* Use same KM Recipe and same flow type - return flow type */ + return km1->flow_type; +} + +int km_rcp_set(struct km_flow_def_s *km, int index) +{ + int qw = 0; + int sw = 0; + int swx = 0; + + hw_mod_km_rcp_set(km->be, HW_KM_RCP_PRESET_ALL, index, 0, 0); + + /* set extractor words, offs, contrib */ + for (int i = 0; i < km->num_ftype_elem; i++) { + switch (km->match_map[i]->extr) { + case KM_USE_EXTRACTOR_SWORD: + if (km->match_map[i]->extr_start_offs_id & SWX_INFO) { + if (km->target == KM_CAM && swx == 0) { + /* SWX */ + if (km->match_map[i] + ->extr_start_offs_id == + SB_VNI) { + NT_LOG(DBG, FILTER, + "Set KM SWX sel A - VNI\n"); + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_SWX_CCH, + index, 0, 1); + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_SWX_SEL_A, + index, 0, + SWX_SEL_ALL32); + } else if (km->match_map[i] + ->extr_start_offs_id == + SB_MAC_PORT) { + NT_LOG(DBG, FILTER, + "Set KM SWX sel A - PTC + MAC\n"); + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_SWX_SEL_A, + index, 0, + SWX_SEL_ALL32); + } else if (km->match_map[i] + ->extr_start_offs_id == + SB_KCC_ID) { + NT_LOG(DBG, FILTER, + "Set KM SWX sel A - KCC ID\n"); + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_SWX_CCH, + index, 0, 1); + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_SWX_SEL_A, + index, 0, + SWX_SEL_ALL32); + } else { + return -1; + } + } else { + return -1; + } + swx++; + } else { + if (sw == 0) { + /* DW8 */ + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_DW8_DYN, + index, 0, + km->match_map[i] + ->extr_start_offs_id); + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_DW8_OFS, + index, 0, + km->match_map[i]->rel_offs); + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_DW8_SEL_A, + index, 0, + DW8_SEL_FIRST32); + NT_LOG(DBG, FILTER, + "Set KM DW8 sel A: dyn: %i, offs: %i\n", + km->match_map[i] + ->extr_start_offs_id, + km->match_map[i]->rel_offs); + } else if (sw == 1) { + /* DW10 */ + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_DW10_DYN, + index, 0, + km->match_map[i] + ->extr_start_offs_id); + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_DW10_OFS, + index, 0, + km->match_map[i]->rel_offs); + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_DW10_SEL_A, + index, 0, + DW10_SEL_FIRST32); + NT_LOG(DBG, FILTER, + "Set KM DW10 sel A: dyn: %i, offs: %i\n", + km->match_map[i] + ->extr_start_offs_id, + km->match_map[i]->rel_offs); + } else { + return -1; + } + sw++; + } + break; + + case KM_USE_EXTRACTOR_QWORD: + if (qw == 0) { + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_QW0_DYN, + index, 0, + km->match_map[i]->extr_start_offs_id); + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_QW0_OFS, + index, 0, + km->match_map[i]->rel_offs); + switch (km->match_map[i]->word_len) { + case 1: + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_QW0_SEL_A, + index, 0, + QW0_SEL_FIRST32); + break; + case 2: + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_QW0_SEL_A, + index, 0, + QW0_SEL_FIRST64); + break; + case 4: + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_QW0_SEL_A, + index, 0, + QW0_SEL_ALL128); + break; + default: + return -1; + } + NT_LOG(DBG, FILTER, + "Set KM QW0 sel A: dyn: %i, offs: %i, size: %i\n", + km->match_map[i]->extr_start_offs_id, + km->match_map[i]->rel_offs, + km->match_map[i]->word_len); + } else if (qw == 1) { + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_QW4_DYN, + index, 0, + km->match_map[i]->extr_start_offs_id); + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_QW4_OFS, + index, 0, + km->match_map[i]->rel_offs); + switch (km->match_map[i]->word_len) { + case 1: + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_QW4_SEL_A, + index, 0, + QW4_SEL_FIRST32); + break; + case 2: + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_QW4_SEL_A, + index, 0, + QW4_SEL_FIRST64); + break; + case 4: + hw_mod_km_rcp_set(km->be, + HW_KM_RCP_QW4_SEL_A, + index, 0, + QW4_SEL_ALL128); + break; + default: + return -1; + } + NT_LOG(DBG, FILTER, + "Set KM QW4 sel A: dyn: %i, offs: %i, size: %i\n", + km->match_map[i]->extr_start_offs_id, + km->match_map[i]->rel_offs, + km->match_map[i]->word_len); + } else { + return -1; + } + qw++; + break; + default: + return -1; + } + } + + /* set mask A */ + for (int i = 0; i < km->key_word_size; i++) { + hw_mod_km_rcp_set(km->be, HW_KM_RCP_MASK_A, index, + (km->be->km.nb_km_rcp_mask_a_word_size - 1) - + i, + km->entry_mask[i]); + NT_LOG(DBG, FILTER, "Set KM mask A: %08x\n", km->entry_mask[i]); + } + + if (km->target == KM_CAM) { + /* set info - Color */ + if (km->info_set) { + hw_mod_km_rcp_set(km->be, HW_KM_RCP_INFO_A, index, 0, + 1); + NT_LOG(DBG, FILTER, "Set KM info A\n"); + } + /* set key length A */ + hw_mod_km_rcp_set(km->be, HW_KM_RCP_EL_A, index, 0, + km->key_word_size + !!km->info_set - + 1); /* select id is -1 */ + /* set Flow Type for Key A */ + NT_LOG(DBG, FILTER, "Set KM EL A: %i\n", + km->key_word_size + !!km->info_set - 1); + + hw_mod_km_rcp_set(km->be, HW_KM_RCP_FTM_A, index, 0, + 1 << km->flow_type); + + NT_LOG(DBG, FILTER, "Set KM FTM A - ft: %i\n", km->flow_type); + + /* Set Paired - only on the CAM part though... */ + if ((uint32_t)(km->key_word_size + !!km->info_set) > + km->be->km.nb_cam_record_words) { + hw_mod_km_rcp_set(km->be, HW_KM_RCP_PAIRED, + index, 0, 1); + NT_LOG(DBG, FILTER, "Set KM CAM Paired\n"); + km->cam_paired = 1; + } + } else if (km->target == KM_TCAM) { + uint32_t bank_bm = 0; + + if (tcam_find_mapping(km) < 0) { + /* failed mapping into TCAM */ + NT_LOG(DBG, FILTER, "INFO: TCAM mapping flow failed\n"); + return -1; + } + + assert((uint32_t)(km->tcam_start_bank + km->key_word_size) <= + km->be->km.nb_tcam_banks); + + for (int i = 0; i < km->key_word_size; i++) { + bank_bm |= (1 << (km->be->km.nb_tcam_banks - 1 - + (km->tcam_start_bank + i))); + } + + /* Set BANK_A */ + hw_mod_km_rcp_set(km->be, HW_KM_RCP_BANK_A, index, 0, bank_bm); + /* Set Kl_A */ + hw_mod_km_rcp_set(km->be, HW_KM_RCP_KL_A, index, 0, + km->key_word_size - 1); + + } else { + return -1; + } + return 0; +} + +static int cam_populate(struct km_flow_def_s *km, int bank) +{ + int res = 0; + int cnt = km->key_word_size + !!km->info_set; + + for (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt; + i++, cnt--) { + res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_W0 + i, bank, + km->record_indexes[bank], + km->entry_word[i]); + res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i, bank, + km->record_indexes[bank], + km->flow_type); + } + km->cam_dist[CAM_KM_DIST_IDX(bank)].km_owner = km; + + if (cnt) { + assert(km->cam_paired); + for (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt; + i++, cnt--) { + res |= hw_mod_km_cam_set(km->be, + HW_KM_CAM_W0 + i, + bank, + km->record_indexes[bank] + 1, + km->entry_word[km->be->km.nb_cam_record_words + + i]); + res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i, + bank, + km->record_indexes[bank] + 1, + km->flow_type); + } + km->cam_dist[CAM_KM_DIST_IDX(bank) + 1].km_owner = km; + } + + res |= hw_mod_km_cam_flush(km->be, bank, km->record_indexes[bank], + km->cam_paired ? 2 : 1); + + return res; +} + +static int cam_reset_entry(struct km_flow_def_s *km, int bank) +{ + int res = 0; + int cnt = km->key_word_size + !!km->info_set; + + for (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt; + i++, cnt--) { + res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_W0 + i, bank, + km->record_indexes[bank], 0); + res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i, bank, + km->record_indexes[bank], 0); + } + km->cam_dist[CAM_KM_DIST_IDX(bank)].km_owner = NULL; + + if (cnt) { + assert(km->cam_paired); + for (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt; + i++, cnt--) { + res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_W0 + i, bank, + km->record_indexes[bank] + 1, + 0); + res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i, + bank, + km->record_indexes[bank] + 1, + 0); + } + km->cam_dist[CAM_KM_DIST_IDX(bank) + 1].km_owner = NULL; + } + res |= hw_mod_km_cam_flush(km->be, bank, km->record_indexes[bank], + km->cam_paired ? 2 : 1); + return res; +} + +static int move_cuckoo_index(struct km_flow_def_s *km) +{ + assert(km->cam_dist[CAM_KM_DIST_IDX(km->bank_used)].km_owner); + + for (uint32_t bank = 0; bank < km->be->km.nb_cam_banks; bank++) { + /* It will not select itself */ + if (km->cam_dist[CAM_KM_DIST_IDX(bank)].km_owner == NULL) { + if (km->cam_paired) { + if (km->cam_dist[CAM_KM_DIST_IDX(bank) + 1] + .km_owner != NULL) + continue; + } + + /* + * Populate in new position + */ + int res = cam_populate(km, bank); + + if (res) { + NT_LOG(DBG, FILTER, + "Error: failed to write to KM CAM in cuckoo move\n"); + return 0; + } + + /* + * Reset/free entry in old bank + * HW flushes are really not needed, the old addresses are always taken over + * by the caller + * If you change this code in future updates, this may no longer be true + * then! + */ + km->cam_dist[CAM_KM_DIST_IDX(km->bank_used)].km_owner = + NULL; + if (km->cam_paired) + km->cam_dist[CAM_KM_DIST_IDX(km->bank_used) + 1] + .km_owner = NULL; + + NT_LOG(DBG, FILTER, + "KM Cuckoo hash moved from bank %i to bank %i (%04X => %04X)\n", + km->bank_used, bank, + CAM_KM_DIST_IDX(km->bank_used), + CAM_KM_DIST_IDX(bank)); + km->bank_used = bank; + (*km->cuckoo_moves)++; + return 1; + } + } + return 0; +} + +static int move_cuckoo_index_level(struct km_flow_def_s *km_parent, + int bank_idx, int levels, + int cam_adr_list_len) +{ + struct km_flow_def_s *km = km_parent->cam_dist[bank_idx].km_owner; + + assert(levels <= CUCKOO_MOVE_MAX_DEPTH); + + /* + * Only move if same pairness + * Can be extended later to handle both move of paired and single entries + */ + if (!km || km_parent->cam_paired != km->cam_paired) + return 0; + + if (move_cuckoo_index(km)) + return 1; + if (levels <= 1) + return 0; + + assert(cam_adr_list_len < CUCKOO_MOVE_MAX_DEPTH); + + cam_addr_reserved_stack[cam_adr_list_len++] = bank_idx; + + for (uint32_t i = 0; i < km->be->km.nb_cam_banks; i++) { + int reserved = 0; + int new_idx = CAM_KM_DIST_IDX(i); + + for (int i_reserved = 0; i_reserved < cam_adr_list_len; + i_reserved++) { + if (cam_addr_reserved_stack[i_reserved] == new_idx) { + reserved = 1; + break; + } + } + if (reserved) + continue; + + int res = move_cuckoo_index_level(km, new_idx, levels - 1, + cam_adr_list_len); + if (res) { + if (move_cuckoo_index(km)) + return 1; + + else + assert(0); + } + } + + return 0; +} + +static int km_write_data_to_cam(struct km_flow_def_s *km) +{ + int res = 0; + int val[MAX_BANKS]; + + assert(km->be->km.nb_cam_banks <= MAX_BANKS); + assert(km->cam_dist); + + /* word list without info set */ + gethash(km->hsh, km->entry_word, val); + + for (uint32_t i = 0; i < km->be->km.nb_cam_banks; i++) { + /* if paired we start always on an even address - reset bit 0 */ + km->record_indexes[i] = (km->cam_paired) ? val[i] & ~1 : val[i]; + } + NT_LOG(DBG, FILTER, "KM HASH [%03X, %03X, %03X]\n", + km->record_indexes[0], km->record_indexes[1], + km->record_indexes[2]); + + if (km->info_set) { + km->entry_word[km->key_word_size] = + km->info; /* finally set info */ + } + + int bank = -1; + /* + * first step, see if any of the banks are free + */ + for (uint32_t i_bank = 0; i_bank < km->be->km.nb_cam_banks; i_bank++) { + if (km->cam_dist[CAM_KM_DIST_IDX(i_bank)].km_owner == NULL) { + if (km->cam_paired == 0 || + (km->cam_dist[CAM_KM_DIST_IDX(i_bank) + 1] + .km_owner == NULL)) { + bank = i_bank; + break; + } + } + } + + if (bank < 0) { + /* + * Second step - cuckoo move existing flows if possible + */ + for (uint32_t i_bank = 0; i_bank < km->be->km.nb_cam_banks; + i_bank++) { + if (move_cuckoo_index_level(km, CAM_KM_DIST_IDX(i_bank), + 4, 0)) { + bank = i_bank; + break; + } + } + } + if (bank < 0) + return -1; + + /* populate CAM */ + NT_LOG(DBG, FILTER, "KM Bank = %i (addr %04X)\n", bank, + CAM_KM_DIST_IDX(bank)); + res = cam_populate(km, bank); + if (res == 0) { + km->flushed_to_target = 1; + km->bank_used = bank; + } + + return res; +} + +/* + * TCAM + */ +static int tcam_find_free_record(struct km_flow_def_s *km, int start_bank) +{ + for (uint32_t rec = 0; rec < km->be->km.nb_tcam_bank_width; rec++) { + if (km->tcam_dist[TCAM_DIST_IDX(start_bank, rec)].km_owner == + NULL) { + int pass = 1; + + for (int ii = 1; ii < km->key_word_size; ii++) { + if (km->tcam_dist[TCAM_DIST_IDX(start_bank + ii, + rec)] + .km_owner != NULL) { + pass = 0; + break; + } + } + if (pass) { + km->tcam_record = rec; + return 1; + } + } + } + + return 0; +} + +static int tcam_find_mapping(struct km_flow_def_s *km) +{ + /* Search record and start index for this flow */ + for (int bs_idx = 0; bs_idx < km->num_start_offsets; bs_idx++) { + if (tcam_find_free_record(km, km->start_offsets[bs_idx])) { + km->tcam_start_bank = km->start_offsets[bs_idx]; + NT_LOG(DBG, FILTER, + "Found space in TCAM start bank %i, record %i\n", + km->tcam_start_bank, km->tcam_record); + return 0; + } + } + return -1; +} + +static int tcam_write_word(struct km_flow_def_s *km, int bank, int record, + uint32_t word, uint32_t mask) +{ + int err = 0; + uint32_t all_recs[3]; + + int rec_val = record / 32; + int rec_bit_shft = record % 32; + uint32_t rec_bit = (1 << rec_bit_shft); + + assert((km->be->km.nb_tcam_bank_width + 31) / 32 <= 3); + + for (int byte = 0; byte < 4; byte++) { + uint8_t a = (uint8_t)((word >> (24 - (byte * 8))) & 0xff); + uint8_t a_m = (uint8_t)((mask >> (24 - (byte * 8))) & 0xff); + /* calculate important value bits */ + a = a & a_m; + +#ifdef FLOW_DEBUG + if (a_m == 0) { + NT_LOG(DBG, FILTER, + "bank %i, byte %i, All values, rec_val %i rec bit %08x\n", + bank, byte, rec_val, rec_bit); + } +#endif + + for (int val = 0; val < 256; val++) { + err |= hw_mod_km_tcam_get(km->be, HW_KM_TCAM_T, bank, + byte, val, all_recs); + if ((val & a_m) == a) { + all_recs[rec_val] |= rec_bit; +#ifdef FLOW_DEBUG + if (a_m) { + NT_LOG(DBG, FILTER, + "bank %i, byte %i, val %i(%02x), " + "rec_val %i rec bit %08x\n", + bank, byte, val, val, rec_val, + rec_bit); + } +#endif + } else { + all_recs[rec_val] &= ~rec_bit; + } + err |= hw_mod_km_tcam_set(km->be, HW_KM_TCAM_T, bank, + byte, val, all_recs); + if (err) + break; + } + } + /* flush bank */ + err |= hw_mod_km_tcam_flush(km->be, bank, ALL_BANK_ENTRIES); + if (err == 0) { + assert(km->tcam_dist[TCAM_DIST_IDX(bank, record)].km_owner == + NULL); + km->tcam_dist[TCAM_DIST_IDX(bank, record)].km_owner = km; + } + return err; +} + +static int km_write_data_to_tcam(struct km_flow_def_s *km) +{ + int err = 0; + + if (km->tcam_record < 0) { + tcam_find_free_record(km, km->tcam_start_bank); + if (km->tcam_record < 0) { + NT_LOG(DBG, FILTER, + "FAILED to find space in TCAM for flow\n"); + return -1; + } + NT_LOG(DBG, FILTER, + "Reused RCP: Found space in TCAM start bank %i, record %i\n", + km->tcam_start_bank, km->tcam_record); + } + + /* Write KM_TCI */ + err |= hw_mod_km_tci_set(km->be, HW_KM_TCI_COLOR, km->tcam_start_bank, + km->tcam_record, km->info); + err |= hw_mod_km_tci_set(km->be, HW_KM_TCI_FT, km->tcam_start_bank, + km->tcam_record, km->flow_type); + err |= hw_mod_km_tci_flush(km->be, km->tcam_start_bank, km->tcam_record, + 1); + +#ifdef FLOW_DEBUG + km->be->iface->set_debug_mode(km->be->be_dev, + FLOW_BACKEND_DEBUG_MODE_NONE); +#endif + + for (int i = 0; i < km->key_word_size && !err; i++) { + err = tcam_write_word(km, km->tcam_start_bank + i, + km->tcam_record, km->entry_word[i], + km->entry_mask[i]); + } +#ifdef FLOW_DEBUG + km->be->iface->set_debug_mode(km->be->be_dev, + FLOW_BACKEND_DEBUG_MODE_WRITE); +#endif + + if (err == 0) + km->flushed_to_target = 1; + + return err; +} + +static int tcam_reset_bank(struct km_flow_def_s *km, int bank, int record) +{ + int err = 0; + uint32_t all_recs[3]; + + int rec_val = record / 32; + int rec_bit_shft = record % 32; + uint32_t rec_bit = (1 << rec_bit_shft); + + assert((km->be->km.nb_tcam_bank_width + 31) / 32 <= 3); + + for (int byte = 0; byte < 4; byte++) { + for (int val = 0; val < 256; val++) { + err = hw_mod_km_tcam_get(km->be, HW_KM_TCAM_T, bank, + byte, val, all_recs); + if (err) + break; + all_recs[rec_val] &= ~rec_bit; + err = hw_mod_km_tcam_set(km->be, HW_KM_TCAM_T, bank, + byte, val, all_recs); + if (err) + break; + } + } + if (err) + return err; + + /* flush bank */ + err = hw_mod_km_tcam_flush(km->be, bank, ALL_BANK_ENTRIES); + km->tcam_dist[TCAM_DIST_IDX(bank, record)].km_owner = NULL; + + NT_LOG(DBG, FILTER, "Reset TCAM bank %i, rec_val %i rec bit %08x\n", + bank, rec_val, rec_bit); + + return err; +} + +static int tcam_reset_entry(struct km_flow_def_s *km) +{ + int err = 0; + + if (km->tcam_start_bank < 0 || km->tcam_record < 0) { + NT_LOG(DBG, FILTER, "FAILED to find space in TCAM for flow\n"); + return -1; + } + + /* Write KM_TCI */ + hw_mod_km_tci_set(km->be, HW_KM_TCI_COLOR, km->tcam_start_bank, + km->tcam_record, 0); + hw_mod_km_tci_set(km->be, HW_KM_TCI_FT, km->tcam_start_bank, + km->tcam_record, 0); + hw_mod_km_tci_flush(km->be, km->tcam_start_bank, km->tcam_record, 1); + +#ifdef FLOW_DEBUG + km->be->iface->set_debug_mode(km->be->be_dev, + FLOW_BACKEND_DEBUG_MODE_NONE); +#endif + + for (int i = 0; i < km->key_word_size && !err; i++) { + err = tcam_reset_bank(km, km->tcam_start_bank + i, + km->tcam_record); + } +#ifdef FLOW_DEBUG + km->be->iface->set_debug_mode(km->be->be_dev, + FLOW_BACKEND_DEBUG_MODE_WRITE); +#endif + + return err; +} + +int km_refer_data_match_entry(struct km_flow_def_s *km, + struct km_flow_def_s *km1) +{ + int res = 0; + + km->root = km1->root ? km1->root : km1; + while (km1->reference) + km1 = km1->reference; + km1->reference = km; + + km->info = km1->info; + + switch (km->target) { + case KM_CAM: + km->cam_paired = km1->cam_paired; + km->bank_used = km1->bank_used; + km->flushed_to_target = km1->flushed_to_target; + break; + case KM_TCAM: + km->tcam_start_bank = km1->tcam_start_bank; + km->tcam_record = km1->tcam_record; + km->flushed_to_target = km1->flushed_to_target; + break; + case KM_SYNERGY: + default: + res = -1; + break; + } + + return res; +} + +int km_write_data_match_entry(struct km_flow_def_s *km, uint32_t color) +{ + int res = -1; + + km->info = color; + NT_LOG(DBG, FILTER, "Write Data entry Color: %08x\n", color); + + switch (km->target) { + case KM_CAM: + res = km_write_data_to_cam(km); + break; + case KM_TCAM: + res = km_write_data_to_tcam(km); + break; + case KM_SYNERGY: + default: + break; + } + return res; +} + +int km_clear_data_match_entry(struct km_flow_def_s *km) +{ + int res = 0; + + if (km->root) { + struct km_flow_def_s *km1 = km->root; + + while (km1->reference != km) + km1 = km1->reference; + + km1->reference = km->reference; + + km->flushed_to_target = 0; + km->bank_used = 0; + } else if (km->reference) { + km->reference->root = NULL; + + switch (km->target) { + case KM_CAM: + km->cam_dist[CAM_KM_DIST_IDX(km->bank_used)].km_owner = + km->reference; + if (km->key_word_size + !!km->info_set > 1) { + assert(km->cam_paired); + km->cam_dist[CAM_KM_DIST_IDX(km->bank_used) + 1] + .km_owner = km->reference; + } + break; + case KM_TCAM: + for (int i = 0; i < km->key_word_size; i++) { + km->tcam_dist[TCAM_DIST_IDX(km->tcam_start_bank + i, + km->tcam_record)].km_owner = km->reference; + } + break; + case KM_SYNERGY: + default: + res = -1; + break; + } + + km->flushed_to_target = 0; + km->bank_used = 0; + } else if (km->flushed_to_target) { + switch (km->target) { + case KM_CAM: + res = cam_reset_entry(km, km->bank_used); + break; + case KM_TCAM: + res = tcam_reset_entry(km); + break; + case KM_SYNERGY: + default: + res = -1; + break; + } + km->flushed_to_target = 0; + km->bank_used = 0; + } + + return res; +} diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c new file mode 100644 index 0000000000..17717da8e2 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c @@ -0,0 +1,787 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include /* htons, htonl, ntohs */ +#include +#include "stream_binary_flow_api.h" + +#include "flow_api_backend.h" +#include "flow_api_engine.h" + +#define MAX_HW_VIRT_PORTS 127 /* 255 reserved */ +#define VIRTUAL_TUNNEL_PORT_OFFSET 72 + +struct tunnel_s { + struct tunnel_cfg_s cfg; + struct tunnel_cfg_s cfg_mask; + uint32_t flow_stat_id; + uint8_t vport; + int refcnt; + struct tunnel_s *next; /* linked list of defined tunnels */ +}; + +int is_virtual_port(uint8_t virt_port) +{ + return !!(virt_port >= VIRTUAL_TUNNEL_PORT_OFFSET && + virt_port < MAX_HW_VIRT_PORTS); +} + +/* + * New function for use with OVS 2.17.2 + */ +static struct tunnel_s *tunnels; + +static uint8_t vport[MAX_HW_VIRT_PORTS - VIRTUAL_TUNNEL_PORT_OFFSET + 1]; + +uint8_t flow_tunnel_alloc_virt_port(void) +{ + for (uint8_t i = VIRTUAL_TUNNEL_PORT_OFFSET; i < MAX_HW_VIRT_PORTS; + i++) { + if (!vport[i - VIRTUAL_TUNNEL_PORT_OFFSET]) { + vport[i - VIRTUAL_TUNNEL_PORT_OFFSET] = 1; + return i; + } + } + + /* no more virtual ports */ + return 255; +} + +uint8_t flow_tunnel_free_virt_port(uint8_t virt_port) +{ + if (virt_port >= VIRTUAL_TUNNEL_PORT_OFFSET && + virt_port < MAX_HW_VIRT_PORTS) { + vport[virt_port - VIRTUAL_TUNNEL_PORT_OFFSET] = 0; + return 0; + } + return -1; +} + +#define check(_v1, _v2, _msk1, _msk2) ({ \ + __typeof__(_v1) (v1) = (_v1); \ + __typeof__(_v2) (v2) = (_v2); \ + __typeof__(_msk1) (msk1) = (_msk1); \ + __typeof__(_msk2) (msk2) = (_msk2); \ + (((v1) & (msk1) & (msk2)) == ((v2) & (msk1) & (msk2))); \ +}) + +#define check_tun_v4_equal(_tun_cfg, _tun_msk, _tun1_cfg, _tun1_msk) ({ \ + __typeof__(_tun_cfg) (tun_cfg) = (_tun_cfg); \ + __typeof__(_tun_msk) (tun_msk) = (_tun_msk); \ + __typeof__(_tun1_cfg) (tun1_cfg) = (_tun1_cfg); \ + __typeof__(_tun1_msk) (tun1_msk) = (_tun1_msk); \ + (check((tun_cfg)->v4.src_ip, (tun1_cfg)->v4.src_ip, \ + (tun_msk)->v4.src_ip, (tun1_msk)->v4.src_ip) && \ + check((tun_cfg)->v4.dst_ip, (tun1_cfg)->v4.dst_ip, \ + (tun_msk)->v4.dst_ip, (tun1_msk)->v4.dst_ip) && \ + check((tun_cfg)->s_port, (tun1_cfg)->s_port, (tun_msk)->s_port, \ + (tun1_msk)->s_port) && \ + check((tun_cfg)->d_port, (tun1_cfg)->d_port, (tun_msk)->d_port, \ + (tun1_msk)->d_port)); \ +}) + +#define check_tun_v6_equal(_tun_cfg, _tun_msk, _tun1_cfg, _tun1_msk) ({ \ + __typeof__(_tun_cfg) (tun_cfg) = (_tun_cfg); \ + __typeof__(_tun_msk) (tun_msk) = (_tun_msk); \ + __typeof__(_tun1_cfg) (tun1_cfg) = (_tun1_cfg); \ + __typeof__(_tun1_msk) (tun1_msk) = (_tun1_msk); \ + (check((tun_cfg)->v6_long.src_ip[0], (tun1_cfg)->v6_long.src_ip[0], \ + (tun_msk)->v6_long.src_ip[0], (tun1_msk)->v6_long.src_ip[0]) && \ + check((tun_cfg)->v6_long.src_ip[1], (tun1_cfg)->v6_long.src_ip[1], \ + (tun_msk)->v6_long.src_ip[1], (tun1_msk)->v6_long.src_ip[1]) && \ + check((tun_cfg)->v6_long.dst_ip[0], (tun1_cfg)->v6_long.dst_ip[0], \ + (tun_msk)->v6_long.dst_ip[0], (tun1_msk)->v6_long.dst_ip[0]) && \ + check((tun_cfg)->v6_long.dst_ip[1], (tun1_cfg)->v6_long.dst_ip[1], \ + (tun_msk)->v6_long.dst_ip[1], (tun1_msk)->v6_long.dst_ip[1]) && \ + check((tun_cfg)->s_port, (tun1_cfg)->s_port, (tun_msk)->s_port, \ + (tun1_msk)->s_port) && \ + check((tun_cfg)->d_port, (tun1_cfg)->d_port, (tun_msk)->d_port, \ + (tun1_msk)->d_port)); \ +}) + +static int check_tun_match(struct tunnel_s *tun, + const struct tunnel_cfg_s *tnlcfg, + const struct tunnel_cfg_s *tnlcfg_mask) +{ + if (tun->cfg.tun_type == tnlcfg->tun_type) { + if (tun->cfg.ipversion == 4) { + return check_tun_v4_equal(&tun->cfg, &tun->cfg_mask, + tnlcfg, tnlcfg_mask); + } else { + return check_tun_v6_equal(&tun->cfg, &tun->cfg_mask, + tnlcfg, tnlcfg_mask); + } + } + return 0; +} + +static struct tunnel_s *tunnel_get(const struct tunnel_cfg_s *tnlcfg, + const struct tunnel_cfg_s *tnlcfg_mask, + int tun_set) +{ + struct tunnel_s *tun = tunnels; + + while (tun) { + if (tun->flow_stat_id != (uint32_t)-1) { + /* This tun is already defined and set */ + if (tun_set) { + /* + * A tunnel full match definition - search for duplicate + */ + if (memcmp(&tun->cfg, tnlcfg, + sizeof(struct tunnel_cfg_s)) == 0 && + memcmp(&tun->cfg_mask, tnlcfg_mask, + sizeof(struct tunnel_cfg_s)) == 0) + break; + } else { + /* + * A tunnel match search + */ + if (check_tun_match(tun, tnlcfg, tnlcfg_mask)) + break; + } + + } else if (tun_set) { + /* + * Check if this is a pre-configured tunnel for this one to be set + * try match them + */ + if (check_tun_match(tun, tnlcfg, tnlcfg_mask)) { + /* + * Change the tun into the defining one - flow_stat_id is set later + */ + memcpy(&tun->cfg, tnlcfg, + sizeof(struct tunnel_cfg_s)); + memcpy(&tun->cfg_mask, tnlcfg_mask, + sizeof(struct tunnel_cfg_s)); + + break; + } + + } /* else ignore - both unset */ + tun = tun->next; + } + + /* + * If not found, create and add it to db + */ + if (!tun) { + uint8_t vport = flow_tunnel_alloc_virt_port(); + + NT_LOG(DBG, FILTER, "Create NEW tunnel allocate vport %i\n", + vport); + + if (vport < 0xff) { + tun = calloc(1, sizeof(struct tunnel_s)); + memcpy(&tun->cfg, tnlcfg, sizeof(struct tunnel_cfg_s)); + memcpy(&tun->cfg_mask, tnlcfg_mask, + sizeof(struct tunnel_cfg_s)); + + /* flow_stat_id is set later from flow code */ + tun->flow_stat_id = (uint32_t)-1; + tun->vport = vport; + tun->refcnt = 1; + + tun->next = tunnels; + tunnels = tun; + } + } else { + tun->refcnt++; + NT_LOG(DBG, FILTER, "Found tunnel has vport %i - ref %i\n", + tun->vport, tun->refcnt); + } + + return tun; +} + +int tunnel_release(struct tunnel_s *tnl) +{ + struct tunnel_s *tun = tunnels, *prev = NULL; + + NT_LOG(DBG, FILTER, "release tunnel vport %i, ref cnt %i..\n", + tnl->vport, tnl->refcnt); + /* find tunnel in list */ + while (tun) { + if (tun == tnl) + break; + prev = tun; + tun = tun->next; + } + + if (!tun) { + NT_LOG(DBG, FILTER, + "ERROR: Tunnel not found in tunnel release!\n"); + return -1; + } + + /* if last ref, take out of list */ + if (--tun->refcnt == 0) { + if (prev) + prev->next = tun->next; + else + tunnels = tun->next; + flow_tunnel_free_virt_port(tun->vport); + + NT_LOG(DBG, FILTER, + "tunnel ref count == 0 remove tunnel vport %i\n", + tun->vport); + free(tun); + } + + return 0; +} + +struct tunnel_s *tunnel_parse(const struct flow_elem *elem, int *idx, + uint32_t *vni) +{ + int eidx = *idx; + struct tunnel_cfg_s tnlcfg; + struct tunnel_cfg_s tnlcfg_mask; + struct tunnel_s *rtnl = NULL; + + if (elem) { + eidx++; + memset(&tnlcfg, 0, sizeof(struct tunnel_cfg_s)); + int valid = 1; + enum flow_elem_type last_type = FLOW_ELEM_TYPE_END; + + tnlcfg.d_port = 0xffff; + tnlcfg.tun_type = -1; + + if (vni) + *vni = (uint32_t)-1; + + while (elem[eidx].type != FLOW_ELEM_TYPE_END && + elem[eidx].type >= last_type && valid) { + switch (elem[eidx].type) { + case FLOW_ELEM_TYPE_ANY: + case FLOW_ELEM_TYPE_ETH: + /* Ignore */ + break; + case FLOW_ELEM_TYPE_IPV4: { + const struct flow_elem_ipv4 *ipv4 = + (const struct flow_elem_ipv4 *)elem[eidx] + .spec; + const struct flow_elem_ipv4 *ipv4_mask = + (const struct flow_elem_ipv4 *)elem[eidx] + .mask; + + tnlcfg.v4.src_ip = ipv4->hdr.src_ip; + tnlcfg.v4.dst_ip = ipv4->hdr.dst_ip; + tnlcfg_mask.v4.src_ip = ipv4_mask->hdr.src_ip; + tnlcfg_mask.v4.dst_ip = ipv4_mask->hdr.dst_ip; + + tnlcfg.ipversion = 4; + } + break; + case FLOW_ELEM_TYPE_IPV6: { + const struct flow_elem_ipv6 *ipv6 = + (const struct flow_elem_ipv6 *)elem[eidx] + .spec; + const struct flow_elem_ipv6 *ipv6_mask = + (const struct flow_elem_ipv6 *)elem[eidx] + .mask; + + memcpy(tnlcfg.v6.src_ip, ipv6->hdr.src_addr, + sizeof(tnlcfg.v6.src_ip)); + memcpy(tnlcfg.v6.dst_ip, ipv6->hdr.dst_addr, + sizeof(tnlcfg.v6.dst_ip)); + memcpy(tnlcfg_mask.v6.src_ip, + ipv6_mask->hdr.src_addr, + sizeof(tnlcfg.v6.src_ip)); + memcpy(tnlcfg_mask.v6.dst_ip, + ipv6_mask->hdr.dst_addr, + sizeof(tnlcfg.v6.dst_ip)); + + tnlcfg.ipversion = 6; + } + break; + + case FLOW_ELEM_TYPE_UDP: { + const struct flow_elem_udp *udp = + (const struct flow_elem_udp *)elem[eidx] + .spec; + const struct flow_elem_udp *udp_mask = + (const struct flow_elem_udp *)elem[eidx] + .mask; + + tnlcfg.s_port = udp->hdr.src_port; + tnlcfg.d_port = udp->hdr.dst_port; + tnlcfg_mask.s_port = udp_mask->hdr.src_port; + tnlcfg_mask.d_port = udp_mask->hdr.dst_port; + } + break; + + case FLOW_ELEM_TYPE_VXLAN: { + const struct flow_elem_vxlan *vxlan = + (const struct flow_elem_vxlan *) + elem[eidx] + .spec; + if (vni) + *vni = (uint32_t)(((uint32_t) + vxlan->vni[0] + << 16) | + ((uint32_t) + vxlan->vni[1] + << 8) | + ((uint32_t)vxlan + ->vni[2])); + + tnlcfg.tun_type = FLOW_ELEM_TYPE_VXLAN; + } + break; + default: + valid = 0; + break; + } + + last_type = elem[eidx].type; + eidx++; + } + + /* + * vxlan ports : 4789 or 8472 + */ + if (tnlcfg.tun_type < 0 && + (tnlcfg.d_port == 0xb512 || tnlcfg.d_port == 0x1821)) + tnlcfg.tun_type = FLOW_ELEM_TYPE_VXLAN; + + if (!valid || tnlcfg.ipversion == 0 || tnlcfg.tun_type < 0 || + tnlcfg.d_port == 0xffff) { + NT_LOG(DBG, FILTER, "Invalid tunnel received\n"); + return NULL; + } + + /* search/add to DB */ + rtnl = tunnel_get(&tnlcfg, &tnlcfg_mask, + vni ? 0 : + 1); /* if vni == NULL it is a tun set command */ + +#ifdef FLOW_DEBUG + if (rtnl) { + if (vni) + NT_LOG(DBG, FILTER, + "MATCH A TUNNEL DEFINITION - PRESET " + "(PREALLOC VPORT) IF NOT FOUND:\n"); + else + NT_LOG(DBG, FILTER, + "SET A TUNNEL DEFINITION:\n"); + struct in_addr addr, mask; + char buf[64]; + + addr.s_addr = rtnl->cfg.v4.src_ip; + sprintf(buf, "%s", inet_ntoa(addr)); + mask.s_addr = rtnl->cfg_mask.v4.src_ip; + NT_LOG(DBG, FILTER, " tun src IP: %s / %s\n", buf, + inet_ntoa(mask)); + addr.s_addr = rtnl->cfg.v4.dst_ip; + sprintf(buf, "%s", inet_ntoa(addr)); + mask.s_addr = rtnl->cfg_mask.v4.dst_ip; + NT_LOG(DBG, FILTER, " tun dst IP: %s / %s\n", buf, + inet_ntoa(mask)); + NT_LOG(DBG, FILTER, " tun tp_src: %i / %04x\n", + htons(rtnl->cfg.s_port), + htons(rtnl->cfg_mask.s_port)); + NT_LOG(DBG, FILTER, " tun tp_dst: %i / %04x\n", + htons(rtnl->cfg.d_port), + htons(rtnl->cfg_mask.d_port)); + NT_LOG(DBG, FILTER, " tun ipver: %i\n", + rtnl->cfg.ipversion); + NT_LOG(DBG, FILTER, " tun flow_stat_id: %i\n", + rtnl->flow_stat_id); + NT_LOG(DBG, FILTER, " tun vport: %i\n", + rtnl->vport); + NT_LOG(DBG, FILTER, " tun refcnt: %i\n", + rtnl->refcnt); + } +#endif + + *idx = eidx; /* pointing to next or END */ + } + + return rtnl; +} + +uint8_t get_tunnel_vport(struct tunnel_s *rtnl) +{ + return rtnl->vport; +} + +void tunnel_set_flow_stat_id(struct tunnel_s *rtnl, uint32_t flow_stat_id) +{ + rtnl->flow_stat_id = flow_stat_id; +} + +int tunnel_get_definition(struct tunnel_cfg_s *tuncfg, uint32_t flow_stat_id, + uint8_t vport) +{ + struct tunnel_s *tun = tunnels; + + while (tun) { + if (tun->vport == vport && (flow_stat_id == tun->flow_stat_id || + flow_stat_id == (uint32_t)-1)) { + memcpy(tuncfg, &tun->cfg, sizeof(struct tunnel_cfg_s)); + return 0; + } + tun = tun->next; + } + + return -1; +} + +static be16_t ip_checksum_sum(const be16_t *data, unsigned int size, + be16_t seed) +{ + unsigned int sum = seed; + unsigned int idx; + + for (idx = 0; idx < size / 2; idx++) + sum += (unsigned int)(data[idx]); + if (size & 1) + sum += (unsigned char)data[idx]; + /* unfold */ + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + return (be16_t)sum; +} + +static void copy_unmasked(uint8_t *result, const struct flow_elem *elem, + uint8_t size) +{ + for (uint8_t i = 0; i < size; i++) + result[i] = ((const uint8_t *)elem->spec)[i]; +} + +int flow_tunnel_create_vxlan_hdr(struct flow_api_backend_s *be, + struct nic_flow_def *fd, + const struct flow_elem *elem) +{ + uint32_t eidx = 0; + uint8_t size; + struct ipv4_hdr_s *tun_ipv4 = NULL; + uint16_t *tun_hdr_eth_type_p = NULL; + + if (elem) { + while (elem[eidx].type != FLOW_ELEM_TYPE_END) { + switch (elem[eidx].type) { + case FLOW_ELEM_TYPE_ETH: { + NT_LOG(DBG, FILTER, + "Tunnel: RTE_FLOW_ITEM_TYPE_ETH\n"); + struct flow_elem_eth eth; + + size = sizeof(struct flow_elem_eth); + + copy_unmasked((uint8_t *)ð, &elem[eidx], + size); + + memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len], + ð, size); + + /* + * Save a pointer to the tun header ethtype field + * (needed later in the IPv4 and IPv6 flow elem cases) + */ + tun_hdr_eth_type_p = + (uint16_t *)&fd->tun_hdr.d + .hdr8[fd->tun_hdr.len + 12]; + +#ifdef FLOW_DEBUG + NT_LOG(DBG, FILTER, + "dmac : %02x:%02x:%02x:%02x:%02x:%02x\n", + eth.d_addr.addr_b[0], + eth.d_addr.addr_b[1], + eth.d_addr.addr_b[2], + eth.d_addr.addr_b[3], + eth.d_addr.addr_b[5], + eth.d_addr.addr_b[5]); + NT_LOG(DBG, FILTER, + "smac : %02x:%02x:%02x:%02x:%02x:%02x\n", + eth.s_addr.addr_b[0], + eth.s_addr.addr_b[1], + eth.s_addr.addr_b[2], + eth.s_addr.addr_b[3], + eth.s_addr.addr_b[5], + eth.s_addr.addr_b[5]); + NT_LOG(DBG, FILTER, "type : %04x\n", + ntohs(eth.ether_type)); +#endif + fd->tun_hdr.len = + (uint8_t)(fd->tun_hdr.len + size); + } + break; + /* VLAN is not supported */ + + case FLOW_ELEM_TYPE_IPV4: { + NT_LOG(DBG, FILTER, + "Tunnel: RTE_FLOW_ITEM_TYPE_IPV4\n"); + struct flow_elem_ipv4 ipv4; + + size = sizeof(struct flow_elem_ipv4); + + copy_unmasked((uint8_t *)&ipv4, &elem[eidx], + size); + + if (ipv4.hdr.version_ihl != 0x45) + ipv4.hdr.version_ihl = 0x45; + + if (ipv4.hdr.ttl == 0) + ipv4.hdr.ttl = 64; + + if (ipv4.hdr.next_proto_id != + 17) /* must be UDP */ + ipv4.hdr.next_proto_id = 17; + + ipv4.hdr.frag_offset = + htons(1 << 14); /* DF flag */ + + size = sizeof(struct ipv4_hdr_s); + memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len], + &ipv4.hdr, size); + + /* Set the tun header ethtype field to IPv4 (if empty) */ + if (tun_hdr_eth_type_p && + (*tun_hdr_eth_type_p == 0)) { + *tun_hdr_eth_type_p = + htons(0x0800); /* IPv4 */ + } + + tun_ipv4 = (struct ipv4_hdr_s *)&fd->tun_hdr.d + .hdr8[fd->tun_hdr.len]; + + NT_LOG(DBG, FILTER, "v_ihl : %02x\n", + tun_ipv4->version_ihl); + NT_LOG(DBG, FILTER, "tos : %02x\n", + tun_ipv4->tos); + NT_LOG(DBG, FILTER, "len : %d\n", + ntohs(tun_ipv4->length)); + NT_LOG(DBG, FILTER, "id : %02x\n", + tun_ipv4->id); + NT_LOG(DBG, FILTER, "fl/frg : %04x\n", + ntohs(tun_ipv4->frag_offset)); + NT_LOG(DBG, FILTER, "ttl : %02x\n", + tun_ipv4->ttl); + NT_LOG(DBG, FILTER, "prot : %02x\n", + tun_ipv4->next_proto_id); + NT_LOG(DBG, FILTER, "chksum : %04x\n", + ntohs(tun_ipv4->hdr_csum)); + NT_LOG(DBG, FILTER, "src : %d.%d.%d.%d\n", + (tun_ipv4->src_ip & 0xff), + ((tun_ipv4->src_ip >> 8) & 0xff), + ((tun_ipv4->src_ip >> 16) & 0xff), + ((tun_ipv4->src_ip >> 24) & 0xff)); + NT_LOG(DBG, FILTER, "dst : %d.%d.%d.%d\n", + (tun_ipv4->dst_ip & 0xff), + ((tun_ipv4->dst_ip >> 8) & 0xff), + ((tun_ipv4->dst_ip >> 16) & 0xff), + ((tun_ipv4->dst_ip >> 24) & 0xff)); + + fd->tun_hdr.len = + (uint8_t)(fd->tun_hdr.len + size); + fd->tun_hdr.ip_version = 4; + } + break; + + case FLOW_ELEM_TYPE_IPV6: { + if (be->roa.ver < 6) { + NT_LOG(ERR, FILTER, + "Tunnel flow element type IPv6 requires ROA version 6 or higher (current version=%d)\n", + be->roa.ver); + return -1; + } + + NT_LOG(DBG, FILTER, + "Tunnel: RTE_FLOW_ITEM_TYPE_IPV6\n"); + struct flow_elem_ipv6 ipv6; + + size = sizeof(struct flow_elem_ipv6); + + copy_unmasked((uint8_t *)&ipv6, &elem[eidx], + size); + + /* + * Make sure the version field (the 4 most significant bits of + * "vtc_flow") is set to 6 + */ + if ((ipv6.hdr.vtc_flow & htonl(0x60000000)) == + 0) { + ipv6.hdr.vtc_flow |= htonl(0x60000000); /* Version = 6 */ + } + + if (ipv6.hdr.proto != 17) /* must be UDP */ + ipv6.hdr.proto = 17; + + if (ipv6.hdr.hop_limits == 0) + ipv6.hdr.hop_limits = 64; + + size = sizeof(struct ipv6_hdr_s); + memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len], + &ipv6.hdr, size); + + /* Set the tun header ethtype field to IPv6 (if empty) */ + if (tun_hdr_eth_type_p && + (*tun_hdr_eth_type_p == 0)) { + *tun_hdr_eth_type_p = + htons(0x86DD); /* IPv6 */ + } + + NT_LOG(DBG, FILTER, "vtc_flow : %08x\n", + ntohl(ipv6.hdr.vtc_flow)); + NT_LOG(DBG, FILTER, "payload_len : %04x\n", + ntohs(ipv6.hdr.payload_len)); + NT_LOG(DBG, FILTER, "proto : %02x\n", + ipv6.hdr.proto); + NT_LOG(DBG, FILTER, "hop_limits : %02x\n", + ipv6.hdr.hop_limits); + NT_LOG(DBG, FILTER, + "src : %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", + ipv6.hdr.src_addr[0], + ipv6.hdr.src_addr[1], + ipv6.hdr.src_addr[2], + ipv6.hdr.src_addr[3], + ipv6.hdr.src_addr[4], + ipv6.hdr.src_addr[5], + ipv6.hdr.src_addr[6], + ipv6.hdr.src_addr[7], + ipv6.hdr.src_addr[8], + ipv6.hdr.src_addr[9], + ipv6.hdr.src_addr[10], + ipv6.hdr.src_addr[11], + ipv6.hdr.src_addr[12], + ipv6.hdr.src_addr[13], + ipv6.hdr.src_addr[14], + ipv6.hdr.src_addr[15]); + NT_LOG(DBG, FILTER, + "dst : %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", + ipv6.hdr.dst_addr[0], + ipv6.hdr.dst_addr[1], + ipv6.hdr.dst_addr[2], + ipv6.hdr.dst_addr[3], + ipv6.hdr.dst_addr[4], + ipv6.hdr.dst_addr[5], + ipv6.hdr.dst_addr[6], + ipv6.hdr.dst_addr[7], + ipv6.hdr.dst_addr[8], + ipv6.hdr.dst_addr[9], + ipv6.hdr.dst_addr[10], + ipv6.hdr.dst_addr[11], + ipv6.hdr.dst_addr[12], + ipv6.hdr.dst_addr[13], + ipv6.hdr.dst_addr[14], + ipv6.hdr.dst_addr[15]); + + fd->tun_hdr.len = + (uint8_t)(fd->tun_hdr.len + size); + fd->tun_hdr.ip_version = 6; + } + break; + + case FLOW_ELEM_TYPE_UDP: { + NT_LOG(DBG, FILTER, + "Tunnel: RTE_FLOW_ITEM_TYPE_UDP\n"); + struct flow_elem_udp udp; + + size = sizeof(struct flow_elem_udp); + + copy_unmasked((uint8_t *)&udp, &elem[eidx], + size); + + udp.hdr.cksum = + 0; /* set always the UDP checksum to 0 */ + + size = sizeof(struct udp_hdr_s); + memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len], + &udp.hdr, size); + + NT_LOG(DBG, FILTER, "src p : %d\n", + ntohs(udp.hdr.src_port)); + NT_LOG(DBG, FILTER, "dst p : %d\n", + ntohs(udp.hdr.dst_port)); + NT_LOG(DBG, FILTER, "len : %d\n", + ntohs(udp.hdr.len)); + NT_LOG(DBG, FILTER, "chksum : %04x\n", + ntohs(udp.hdr.cksum)); + + fd->tun_hdr.len = + (uint8_t)(fd->tun_hdr.len + size); + } + break; + + case FLOW_ELEM_TYPE_VXLAN: { + struct flow_elem_vxlan vxlan_m; + + size = sizeof(struct flow_elem_vxlan); + + copy_unmasked((uint8_t *)&vxlan_m, &elem[eidx], + size); + + vxlan_m.flags = + 0x08; /* set always I-flag - valid VNI */ + + NT_LOG(DBG, FILTER, + "Tunnel: RTE_FLOW_ITEM_TYPE_VXLAN - vni %u\n", + (vxlan_m.vni[0] << 16) + + (vxlan_m.vni[1] << 8) + + vxlan_m.vni[2]); + + memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len], + &vxlan_m, size); + + NT_LOG(DBG, FILTER, "flags : %02x\n", + vxlan_m.flags); + NT_LOG(DBG, FILTER, "vni : %d\n", + (vxlan_m.vni[0] << 16) + + (vxlan_m.vni[1] << 8) + + vxlan_m.vni[2]); + + fd->tun_hdr.len = + (uint8_t)(fd->tun_hdr.len + size); + } + break; + + case FLOW_ELEM_TYPE_PORT_ID: { + const struct flow_elem_port_id *port = + (const struct flow_elem_port_id *) + elem[eidx] + .spec; + fd->tun_hdr.user_port_id = port->id; + } + break; + + case FLOW_ELEM_TYPE_VOID: { + NT_LOG(DBG, FILTER, + "Tunnel: RTE_FLOW_ITEM_TYPE_VOID (ignoring)\n"); + } + break; + + default: + NT_LOG(INF, FILTER, + "unsupported Tunnel flow element type %u\n", + elem[eidx].type); + return -1; + } + + eidx++; + } + } + + if (tun_ipv4) { + tun_ipv4->hdr_csum = 0; + tun_ipv4->length = 0; + fd->tun_hdr.ip_csum_precalc = ntohs(ip_checksum_sum((const be16_t *)&fd->tun_hdr.d + .hdr8[14], + (unsigned int)sizeof(struct ipv4_hdr_s), + (be16_t)htons((uint16_t)(fd->tun_hdr.len - sizeof(struct flow_elem_eth))))); + + NT_LOG(DBG, FILTER, + "chksum precalc: %04x, precalc hdr len %u\n", + fd->tun_hdr.ip_csum_precalc, + fd->tun_hdr.len - sizeof(struct flow_elem_eth)); + } + + return 0; +} diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c new file mode 100644 index 0000000000..5a62343718 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c @@ -0,0 +1,1789 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include "flow_api_backend.h" + +#define _MOD_ "CAT" +#define _VER_ be->cat.ver + +static int hw_mod_cat_kce_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int km_if_id, + int start_idx, int count); +static int hw_mod_cat_kcs_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int km_if_id, + int start_idx, int count); +static int hw_mod_cat_fte_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int km_if_id, + int start_idx, int count); + +bool hw_mod_cat_present(struct flow_api_backend_s *be) +{ + return be->iface->get_cat_present(be->be_dev); +} + +int hw_mod_cat_alloc(struct flow_api_backend_s *be) +{ + _VER_ = be->iface->get_cat_version(be->be_dev); + NT_LOG(DBG, FILTER, "CAT MODULE VERSION %i.%i\n", VER_MAJOR(_VER_), + VER_MINOR(_VER_)); + + int nb = be->iface->get_nb_cat_funcs(be->be_dev); + + if (nb <= 0) + return error_resource_count(__func__, "cat_funcs", _MOD_, _VER_); + be->cat.nb_cat_funcs = (uint32_t)nb; + + nb = be->iface->get_nb_km_flow_types(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "km_flow_types", _MOD_, _VER_); + be->cat.nb_flow_types = (uint32_t)nb; + + nb = be->iface->get_nb_pm_ext(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "pm_ext", _MOD_, _VER_); + be->cat.nb_pm_ext = (uint32_t)nb; + + nb = be->iface->get_nb_len(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "len", _MOD_, _VER_); + be->cat.nb_len = (uint32_t)nb; + + nb = be->iface->get_kcc_size(be->be_dev); + if (nb < 0) + return error_resource_count(__func__, "kcc_size", _MOD_, _VER_); + be->cat.kcc_size = (uint32_t)nb; + + nb = be->iface->get_kcc_banks(be->be_dev); + if (nb < 0) + return error_resource_count(__func__, "kcc_banks", _MOD_, _VER_); + be->cat.kcc_banks = (uint32_t)nb; + + nb = be->iface->get_nb_cat_km_if_cnt(be->be_dev); + if (nb < 0) + return error_resource_count(__func__, "km_if_count", _MOD_, _VER_); + be->cat.km_if_count = (uint32_t)nb; + + int idx = be->iface->get_nb_cat_km_if_m0(be->be_dev); + + be->cat.km_if_m0 = idx; + + idx = be->iface->get_nb_cat_km_if_m1(be->be_dev); + be->cat.km_if_m1 = idx; + + if (be->cat.kcc_banks) + be->cat.kcc_records = be->cat.kcc_size / be->cat.kcc_banks; + else + be->cat.kcc_records = 0; + + be->cat.kcc_id_bit_size = 10; + + switch (_VER_) { + case 18: + be->cat.cts_num = 11; + if (!callocate_mod(CAST_COMMON(&be->cat), 12, + &be->cat.v18.cfn, + be->cat.nb_cat_funcs, + sizeof(struct cat_v18_cfn_s), + &be->cat.v18.kce, + (be->cat.nb_cat_funcs / 8), + sizeof(struct cat_v18_kce_s), + &be->cat.v18.kcs, + be->cat.nb_cat_funcs, + sizeof(struct cat_v18_kcs_s), + &be->cat.v18.fte, + (be->cat.nb_cat_funcs / 8) * be->cat.nb_flow_types * 2, + sizeof(struct cat_v18_fte_s), + &be->cat.v18.cte, + be->cat.nb_cat_funcs, + sizeof(struct cat_v18_cte_s), + &be->cat.v18.cts, + be->cat.nb_cat_funcs * ((be->cat.cts_num + 1) / 2), + sizeof(struct cat_v18_cts_s), + &be->cat.v18.cot, + be->max_categories, + sizeof(struct cat_v18_cot_s), + &be->cat.v18.cct, + be->max_categories * 4, + sizeof(struct cat_v18_cct_s), + &be->cat.v18.exo, + be->cat.nb_pm_ext, + sizeof(struct cat_v18_exo_s), + &be->cat.v18.rck, + be->cat.nb_pm_ext * 64, + sizeof(struct cat_v18_rck_s), + &be->cat.v18.len, + be->cat.nb_len, + sizeof(struct cat_v18_len_s), + &be->cat.v18.kcc_cam, + be->cat.kcc_size, + sizeof(struct cat_v18_kcc_s))) + return -1; + + break; + /* end case 18 */ + case 21: + be->cat.cts_num = 11; + if (!callocate_mod(CAST_COMMON(&be->cat), 12, + &be->cat.v21.cfn, + be->cat.nb_cat_funcs, + sizeof(struct cat_v21_cfn_s), + &be->cat.v21.kce, + (be->cat.nb_cat_funcs / 8), + sizeof(struct cat_v21_kce_s), + &be->cat.v21.kcs, + be->cat.nb_cat_funcs, + sizeof(struct cat_v21_kcs_s), + &be->cat.v21.fte, + (be->cat.nb_cat_funcs / 8) * be->cat.nb_flow_types * 4, + sizeof(struct cat_v21_fte_s), + &be->cat.v21.cte, + be->cat.nb_cat_funcs, + sizeof(struct cat_v18_cte_s), + &be->cat.v21.cts, + be->cat.nb_cat_funcs * ((be->cat.cts_num + 1) / 2), + sizeof(struct cat_v18_cts_s), + &be->cat.v21.cot, + be->max_categories, + sizeof(struct cat_v18_cot_s), + &be->cat.v21.cct, + be->max_categories * 4, + sizeof(struct cat_v18_cct_s), + &be->cat.v21.exo, + be->cat.nb_pm_ext, + sizeof(struct cat_v18_exo_s), + &be->cat.v21.rck, + be->cat.nb_pm_ext * 64, + sizeof(struct cat_v18_rck_s), + &be->cat.v21.len, + be->cat.nb_len, + sizeof(struct cat_v18_len_s), + &be->cat.v21.kcc_cam, + be->cat.kcc_size, + sizeof(struct cat_v18_kcc_s))) + return -1; + + break; + /* end case 21 */ + case 22: + be->cat.cts_num = 12; + if (!callocate_mod(CAST_COMMON(&be->cat), 14, + &be->cat.v22.cfn, + be->cat.nb_cat_funcs, + sizeof(struct cat_v21_cfn_s), + &be->cat.v22.kce, + (be->cat.nb_cat_funcs / 8), + sizeof(struct cat_v21_kce_s), + &be->cat.v22.kcs, + be->cat.nb_cat_funcs, + sizeof(struct cat_v21_kcs_s), + &be->cat.v22.fte, + (be->cat.nb_cat_funcs / 8) * be->cat.nb_flow_types * 4, + sizeof(struct cat_v21_fte_s), + &be->cat.v22.cte, + be->cat.nb_cat_funcs, + sizeof(struct cat_v22_cte_s), + &be->cat.v22.cts, + be->cat.nb_cat_funcs * ((be->cat.cts_num + 1) / 2), + sizeof(struct cat_v18_cts_s), + &be->cat.v22.cot, + be->max_categories, + sizeof(struct cat_v18_cot_s), + &be->cat.v22.cct, + be->max_categories * 4, + sizeof(struct cat_v18_cct_s), + &be->cat.v22.exo, + be->cat.nb_pm_ext, + sizeof(struct cat_v18_exo_s), + &be->cat.v22.rck, + be->cat.nb_pm_ext * 64, + sizeof(struct cat_v18_rck_s), + &be->cat.v22.len, + be->cat.nb_len, + sizeof(struct cat_v18_len_s), + &be->cat.v22.kcc_cam, + be->cat.kcc_size, + sizeof(struct cat_v18_kcc_s), + &be->cat.v22.cce, + 4, + sizeof(struct cat_v22_cce_s), + &be->cat.v22.ccs, + 1024, + sizeof(struct cat_v22_ccs_s))) + return -1; + + break; + /* end case 22 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +void hw_mod_cat_free(struct flow_api_backend_s *be) +{ + if (be->cat.base) { + free(be->cat.base); + be->cat.base = NULL; + } +} + +static int cfn_reset(struct flow_api_backend_s *be, int i) +{ + int err = hw_mod_cat_cfn_set(be, HW_CAT_CFN_PRESET_ALL, i, 0, 0); + + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_ISL, i, 0, + 0xffffffff); /* accept both ISL or not ISL */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_CFP, i, 0, + 0xffffffff); /* accept both CFP or not CFP */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_MAC, i, 0, + 0xffffffff); /* accept all MACs */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_L2, i, 0, + 0xffffffff); /* accept all L2 prot */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_VNTAG, i, 0, + 0xffffffff); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_VLAN, i, 0, + 0xffffffff); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_MPLS, i, 0, + 0xffffffff); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_L3, i, 0, + 0xffffffff); /* accept all L3 prot */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_FRAG, i, 0, + 0xffffffff); /* accept all fragments */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_IP_PROT, i, 0, + 0xffffffff); /* IP prot check disabled */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_L4, i, 0, + 0xffffffff); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TUNNEL, i, 0, + 0xffffffff); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_L2, i, 0, + 0xffffffff); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_VLAN, i, 0, + 0xffffffff); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_MPLS, i, 0, + 0xffffffff); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_L3, i, 0, + 0xffffffff); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_FRAG, i, 0, + 0xffffffff); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_IP_PROT, i, 0, + 0xffffffff); /* inner IP prot check disabled */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_L4, i, 0, + 0xffffffff); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_CV, i, 0, 3); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_FCS, i, 0, 3); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TRUNC, i, 0, + 0xffffffff); /* accept all truncations */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_L3_CS, i, 0, 3); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_L4_CS, i, 0, 3); /* accept all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_PM_OR_INV, i, 0, 1); /* */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_LC_INV, i, 0, 1); /* */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_KM0_OR, i, 0, + 0xffffffff); /* or all */ + if (_VER_ >= 21) { + hw_mod_cat_cfn_set(be, HW_CAT_CFN_KM1_OR, i, 0, + 0xffffffff); /* or all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TNL_L3_CS, i, 0, + 0xffffffff); /* or all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TNL_L4_CS, i, 0, + 0xffffffff); /* or all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TTL_EXP, i, 0, + 0xffffffff); /* or all */ + hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TNL_TTL_EXP, i, 0, + 0xffffffff); /* or all */ + } + return err; +} + +int hw_mod_cat_reset(struct flow_api_backend_s *be) +{ + /* Zero entire cache area */ + ZERO_MOD_CACHE(&be->cat); + + NT_LOG(DBG, FILTER, "INIT CAT CFN\n"); + if (hw_mod_cat_cfn_flush(be, 0, ALL_ENTRIES)) + return -1; + + if (_VER_ <= 18) { + NT_LOG(DBG, FILTER, "INIT CAT KCE\n"); + if (hw_mod_cat_kce_flush(be, KM_FLM_IF_FIRST, 0, 0, + ALL_ENTRIES)) + return -1; + + NT_LOG(DBG, FILTER, "INIT CAT KCS\n"); + if (hw_mod_cat_kcs_flush(be, KM_FLM_IF_FIRST, 0, 0, + ALL_ENTRIES)) + return -1; + + NT_LOG(DBG, FILTER, "INIT CAT FTE\n"); + if (hw_mod_cat_fte_flush(be, KM_FLM_IF_FIRST, 0, 0, + ALL_ENTRIES)) + return -1; + } else { + NT_LOG(DBG, FILTER, "INIT CAT KCE 0\n"); + if (hw_mod_cat_kce_flush(be, KM_FLM_IF_FIRST, be->cat.km_if_m0, + 0, ALL_ENTRIES)) + return -1; + + NT_LOG(DBG, FILTER, "INIT CAT KCS 0\n"); + if (hw_mod_cat_kcs_flush(be, KM_FLM_IF_FIRST, be->cat.km_if_m0, + 0, ALL_ENTRIES)) + return -1; + + NT_LOG(DBG, FILTER, "INIT CAT FTE 0\n"); + if (hw_mod_cat_fte_flush(be, KM_FLM_IF_FIRST, be->cat.km_if_m0, + 0, ALL_ENTRIES)) + return -1; + + if (be->cat.km_if_count > 1) { + NT_LOG(DBG, FILTER, "INIT CAT KCE 1\n"); + if (hw_mod_cat_kce_flush(be, KM_FLM_IF_SECOND, + be->cat.km_if_m1, 0, + ALL_ENTRIES)) + return -1; + + NT_LOG(DBG, FILTER, "INIT CAT KCS 1\n"); + if (hw_mod_cat_kcs_flush(be, KM_FLM_IF_SECOND, + be->cat.km_if_m1, 0, + ALL_ENTRIES)) + return -1; + + NT_LOG(DBG, FILTER, "INIT CAT FTE 1\n"); + if (hw_mod_cat_fte_flush(be, KM_FLM_IF_SECOND, + be->cat.km_if_m1, 0, + ALL_ENTRIES)) + return -1; + } + } + + NT_LOG(DBG, FILTER, "INIT CAT CTE\n"); + if (hw_mod_cat_cte_flush(be, 0, ALL_ENTRIES)) + return -1; + + NT_LOG(DBG, FILTER, "INIT CAT CTS\n"); + if (hw_mod_cat_cts_flush(be, 0, ALL_ENTRIES)) + return -1; + + NT_LOG(DBG, FILTER, "INIT CAT COT\n"); + if (hw_mod_cat_cot_flush(be, 0, ALL_ENTRIES)) + return -1; + + NT_LOG(DBG, FILTER, "INIT CAT CCT\n"); + if (hw_mod_cat_cct_flush(be, 0, ALL_ENTRIES)) + return -1; + + NT_LOG(DBG, FILTER, "INIT CAT EXO\n"); + if (hw_mod_cat_exo_flush(be, 0, ALL_ENTRIES)) + return -1; + + NT_LOG(DBG, FILTER, "INIT CAT RCK\n"); + if (hw_mod_cat_rck_flush(be, 0, ALL_ENTRIES)) + return -1; + + NT_LOG(DBG, FILTER, "INIT CAT LEN\n"); + if (hw_mod_cat_len_flush(be, 0, ALL_ENTRIES)) + return -1; + + if (be->cat.kcc_size) { + NT_LOG(DBG, FILTER, "INIT CAT KCC\n"); + if (hw_mod_cat_kcc_flush(be, 0, ALL_ENTRIES)) + return -1; + } + + if (_VER_ > 21) { + NT_LOG(DBG, FILTER, "INIT CAT CCE\n"); + if (hw_mod_cat_cce_flush(be, 0, ALL_ENTRIES)) + return -1; + NT_LOG(DBG, FILTER, "INIT CAT CCS\n"); + if (hw_mod_cat_ccs_flush(be, 0, ALL_ENTRIES)) + return -1; + } + + return 0; +} + +int hw_mod_cat_cfn_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + switch (count) { + case ALL_ENTRIES: + if (start_idx != 0) + return error_index_too_large(__func__); + return be->iface->cat_cfn_flush(be->be_dev, &be->cat, start_idx, + be->cat.nb_cat_funcs); + + default: + if ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs) + return error_index_too_large(__func__); + return be->iface->cat_cfn_flush(be->be_dev, &be->cat, start_idx, + count); + } +} + +static int hw_mod_cat_cfn_mod(struct flow_api_backend_s *be, + enum hw_cat_e field, int index, int word_off, + uint32_t *value, int get) +{ + int rv = 0; + if ((unsigned int)index >= be->cat.nb_cat_funcs) + return error_index_too_large(__func__); + switch (_VER_) { + case 18: + switch (field) { + case HW_CAT_CFN_SET_ALL_DEFAULTS: + if (get) + return error_unsup_field(__func__); + return cfn_reset(be, index); + case HW_CAT_CFN_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->cat.v18.cfn[index], (uint8_t)*value, + sizeof(struct cat_v18_cfn_s)); + break; + case HW_CAT_CFN_COMPARE: + rv = do_compare_indexes(be->cat.v18.cfn, + sizeof(struct cat_v18_cfn_s), index, word_off, + be->cat.nb_cat_funcs, get, __func__); + if (rv != 0) + return rv; + break; + case HW_CAT_CFN_FIND: + rv = find_equal_index(be->cat.v18.cfn, + sizeof(struct cat_v18_cfn_s), index, word_off, + be->cat.nb_cat_funcs, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_CAT_CFN_ENABLE: + get_set(&be->cat.v18.cfn[index].enable, value, get); + break; + case HW_CAT_CFN_INV: + get_set(&be->cat.v18.cfn[index].inv, value, get); + break; + case HW_CAT_CFN_PTC_INV: + get_set(&be->cat.v18.cfn[index].ptc_inv, value, get); + break; + case HW_CAT_CFN_PTC_ISL: + get_set(&be->cat.v18.cfn[index].ptc_isl, value, get); + break; + case HW_CAT_CFN_PTC_CFP: + get_set(&be->cat.v18.cfn[index].ptc_cfp, value, get); + break; + case HW_CAT_CFN_PTC_MAC: + get_set(&be->cat.v18.cfn[index].ptc_mac, value, get); + break; + case HW_CAT_CFN_PTC_L2: + get_set(&be->cat.v18.cfn[index].ptc_l2, value, get); + break; + case HW_CAT_CFN_PTC_VNTAG: + get_set(&be->cat.v18.cfn[index].ptc_vntag, value, get); + break; + case HW_CAT_CFN_PTC_VLAN: + get_set(&be->cat.v18.cfn[index].ptc_vlan, value, get); + break; + case HW_CAT_CFN_PTC_MPLS: + get_set(&be->cat.v18.cfn[index].ptc_mpls, value, get); + break; + case HW_CAT_CFN_PTC_L3: + get_set(&be->cat.v18.cfn[index].ptc_l3, value, get); + break; + case HW_CAT_CFN_PTC_FRAG: + get_set(&be->cat.v18.cfn[index].ptc_frag, value, get); + break; + case HW_CAT_CFN_PTC_IP_PROT: + get_set(&be->cat.v18.cfn[index].ptc_ip_prot, value, get); + break; + case HW_CAT_CFN_PTC_L4: + get_set(&be->cat.v18.cfn[index].ptc_l4, value, get); + break; + case HW_CAT_CFN_PTC_TUNNEL: + get_set(&be->cat.v18.cfn[index].ptc_tunnel, value, get); + break; + case HW_CAT_CFN_PTC_TNL_L2: + get_set(&be->cat.v18.cfn[index].ptc_tnl_l2, value, get); + break; + case HW_CAT_CFN_PTC_TNL_VLAN: + get_set(&be->cat.v18.cfn[index].ptc_tnl_vlan, value, get); + break; + case HW_CAT_CFN_PTC_TNL_MPLS: + get_set(&be->cat.v18.cfn[index].ptc_tnl_mpls, value, get); + break; + case HW_CAT_CFN_PTC_TNL_L3: + get_set(&be->cat.v18.cfn[index].ptc_tnl_l3, value, get); + break; + case HW_CAT_CFN_PTC_TNL_FRAG: + get_set(&be->cat.v18.cfn[index].ptc_tnl_frag, value, get); + break; + case HW_CAT_CFN_PTC_TNL_IP_PROT: + get_set(&be->cat.v18.cfn[index].ptc_tnl_ip_prot, value, get); + break; + case HW_CAT_CFN_PTC_TNL_L4: + get_set(&be->cat.v18.cfn[index].ptc_tnl_l4, value, get); + break; + case HW_CAT_CFN_ERR_INV: + get_set(&be->cat.v18.cfn[index].err_inv, value, get); + break; + case HW_CAT_CFN_ERR_CV: + get_set(&be->cat.v18.cfn[index].err_cv, value, get); + break; + case HW_CAT_CFN_ERR_FCS: + get_set(&be->cat.v18.cfn[index].err_fcs, value, get); + break; + case HW_CAT_CFN_ERR_TRUNC: + get_set(&be->cat.v18.cfn[index].err_trunc, value, get); + break; + case HW_CAT_CFN_ERR_L3_CS: + get_set(&be->cat.v18.cfn[index].err_l3_cs, value, get); + break; + case HW_CAT_CFN_ERR_L4_CS: + get_set(&be->cat.v18.cfn[index].err_l4_cs, value, get); + break; + case HW_CAT_CFN_MAC_PORT: + get_set(&be->cat.v18.cfn[index].mac_port, value, get); + break; + case HW_CAT_CFN_PM_CMP: + if (word_off > 1) + return error_word_off_too_large(__func__); + get_set(&be->cat.v18.cfn[index].pm_cmp[word_off], value, get); + break; + case HW_CAT_CFN_PM_DCT: + get_set(&be->cat.v18.cfn[index].pm_dct, value, get); + break; + case HW_CAT_CFN_PM_EXT_INV: + get_set(&be->cat.v18.cfn[index].pm_ext_inv, value, get); + break; + case HW_CAT_CFN_PM_CMB: + get_set(&be->cat.v18.cfn[index].pm_cmb, value, get); + break; + case HW_CAT_CFN_PM_AND_INV: + get_set(&be->cat.v18.cfn[index].pm_and_inv, value, get); + break; + case HW_CAT_CFN_PM_OR_INV: + get_set(&be->cat.v18.cfn[index].pm_or_inv, value, get); + break; + case HW_CAT_CFN_PM_INV: + get_set(&be->cat.v18.cfn[index].pm_inv, value, get); + break; + case HW_CAT_CFN_LC: + get_set(&be->cat.v18.cfn[index].lc, value, get); + break; + case HW_CAT_CFN_LC_INV: + get_set(&be->cat.v18.cfn[index].lc_inv, value, get); + break; + case HW_CAT_CFN_KM0_OR: + get_set(&be->cat.v18.cfn[index].km_or, value, get); + break; + default: + return error_unsup_field(__func__); + } + break; + /* end case 18 */ + case 21: + case 22: + switch (field) { + case HW_CAT_CFN_SET_ALL_DEFAULTS: + if (get) + return error_unsup_field(__func__); + return cfn_reset(be, index); + case HW_CAT_CFN_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->cat.v21.cfn[index], (uint8_t)*value, + sizeof(struct cat_v21_cfn_s)); + break; + case HW_CAT_CFN_COMPARE: + rv = do_compare_indexes(be->cat.v21.cfn, + sizeof(struct cat_v21_cfn_s), index, word_off, + be->cat.nb_cat_funcs, get, __func__); + if (rv != 0) + return rv; + break; + case HW_CAT_CFN_FIND: + rv = find_equal_index(be->cat.v21.cfn, + sizeof(struct cat_v21_cfn_s), index, word_off, + be->cat.nb_cat_funcs, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_CAT_CFN_COPY_FROM: + if (get) + return error_unsup_field(__func__); + memcpy(&be->cat.v21.cfn[index], + &be->cat.v21.cfn[*value], + sizeof(struct cat_v21_cfn_s)); + break; + case HW_CAT_CFN_ENABLE: + get_set(&be->cat.v21.cfn[index].enable, value, get); + break; + case HW_CAT_CFN_INV: + get_set(&be->cat.v21.cfn[index].inv, value, get); + break; + case HW_CAT_CFN_PTC_INV: + get_set(&be->cat.v21.cfn[index].ptc_inv, value, get); + break; + case HW_CAT_CFN_PTC_ISL: + get_set(&be->cat.v21.cfn[index].ptc_isl, value, get); + break; + case HW_CAT_CFN_PTC_CFP: + get_set(&be->cat.v21.cfn[index].ptc_cfp, value, get); + break; + case HW_CAT_CFN_PTC_MAC: + get_set(&be->cat.v21.cfn[index].ptc_mac, value, get); + break; + case HW_CAT_CFN_PTC_L2: + get_set(&be->cat.v21.cfn[index].ptc_l2, value, get); + break; + case HW_CAT_CFN_PTC_VNTAG: + get_set(&be->cat.v21.cfn[index].ptc_vntag, value, get); + break; + case HW_CAT_CFN_PTC_VLAN: + get_set(&be->cat.v21.cfn[index].ptc_vlan, value, get); + break; + case HW_CAT_CFN_PTC_MPLS: + get_set(&be->cat.v21.cfn[index].ptc_mpls, value, get); + break; + case HW_CAT_CFN_PTC_L3: + get_set(&be->cat.v21.cfn[index].ptc_l3, value, get); + break; + case HW_CAT_CFN_PTC_FRAG: + get_set(&be->cat.v21.cfn[index].ptc_frag, value, get); + break; + case HW_CAT_CFN_PTC_IP_PROT: + get_set(&be->cat.v21.cfn[index].ptc_ip_prot, value, get); + break; + case HW_CAT_CFN_PTC_L4: + get_set(&be->cat.v21.cfn[index].ptc_l4, value, get); + break; + case HW_CAT_CFN_PTC_TUNNEL: + get_set(&be->cat.v21.cfn[index].ptc_tunnel, value, get); + break; + case HW_CAT_CFN_PTC_TNL_L2: + get_set(&be->cat.v21.cfn[index].ptc_tnl_l2, value, get); + break; + case HW_CAT_CFN_PTC_TNL_VLAN: + get_set(&be->cat.v21.cfn[index].ptc_tnl_vlan, value, get); + break; + case HW_CAT_CFN_PTC_TNL_MPLS: + get_set(&be->cat.v21.cfn[index].ptc_tnl_mpls, value, get); + break; + case HW_CAT_CFN_PTC_TNL_L3: + get_set(&be->cat.v21.cfn[index].ptc_tnl_l3, value, get); + break; + case HW_CAT_CFN_PTC_TNL_FRAG: + get_set(&be->cat.v21.cfn[index].ptc_tnl_frag, value, get); + break; + case HW_CAT_CFN_PTC_TNL_IP_PROT: + get_set(&be->cat.v21.cfn[index].ptc_tnl_ip_prot, value, get); + break; + case HW_CAT_CFN_PTC_TNL_L4: + get_set(&be->cat.v21.cfn[index].ptc_tnl_l4, value, get); + break; + case HW_CAT_CFN_ERR_INV: + get_set(&be->cat.v21.cfn[index].err_inv, value, get); + break; + case HW_CAT_CFN_ERR_CV: + get_set(&be->cat.v21.cfn[index].err_cv, value, get); + break; + case HW_CAT_CFN_ERR_FCS: + get_set(&be->cat.v21.cfn[index].err_fcs, value, get); + break; + case HW_CAT_CFN_ERR_TRUNC: + get_set(&be->cat.v21.cfn[index].err_trunc, value, get); + break; + case HW_CAT_CFN_ERR_L3_CS: + get_set(&be->cat.v21.cfn[index].err_l3_cs, value, get); + break; + case HW_CAT_CFN_ERR_L4_CS: + get_set(&be->cat.v21.cfn[index].err_l4_cs, value, get); + break; + case HW_CAT_CFN_ERR_TNL_L3_CS: + get_set(&be->cat.v21.cfn[index].err_tnl_l3_cs, value, get); + break; + case HW_CAT_CFN_ERR_TNL_L4_CS: + get_set(&be->cat.v21.cfn[index].err_tnl_l4_cs, value, get); + break; + case HW_CAT_CFN_ERR_TTL_EXP: + get_set(&be->cat.v21.cfn[index].err_ttl_exp, value, get); + break; + case HW_CAT_CFN_ERR_TNL_TTL_EXP: + get_set(&be->cat.v21.cfn[index].err_tnl_ttl_exp, value, get); + break; + case HW_CAT_CFN_MAC_PORT: + get_set(&be->cat.v21.cfn[index].mac_port, value, get); + break; + case HW_CAT_CFN_PM_CMP: + if (word_off > 1) + return error_word_off_too_large(__func__); + get_set(&be->cat.v21.cfn[index].pm_cmp[word_off], value, get); + break; + case HW_CAT_CFN_PM_DCT: + get_set(&be->cat.v21.cfn[index].pm_dct, value, get); + break; + case HW_CAT_CFN_PM_EXT_INV: + get_set(&be->cat.v21.cfn[index].pm_ext_inv, value, get); + break; + case HW_CAT_CFN_PM_CMB: + get_set(&be->cat.v21.cfn[index].pm_cmb, value, get); + break; + case HW_CAT_CFN_PM_AND_INV: + get_set(&be->cat.v21.cfn[index].pm_and_inv, value, get); + break; + case HW_CAT_CFN_PM_OR_INV: + get_set(&be->cat.v21.cfn[index].pm_or_inv, value, get); + break; + case HW_CAT_CFN_PM_INV: + get_set(&be->cat.v21.cfn[index].pm_inv, value, get); + break; + case HW_CAT_CFN_LC: + get_set(&be->cat.v21.cfn[index].lc, value, get); + break; + case HW_CAT_CFN_LC_INV: + get_set(&be->cat.v21.cfn[index].lc_inv, value, get); + break; + case HW_CAT_CFN_KM0_OR: + get_set(&be->cat.v21.cfn[index].km0_or, value, get); + break; + case HW_CAT_CFN_KM1_OR: + get_set(&be->cat.v21.cfn[index].km1_or, value, get); + break; + default: + return error_unsup_field(__func__); + } + break; + /* end case 21/22 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + return 0; +} + +int hw_mod_cat_cfn_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, int word_off, uint32_t value) +{ + return hw_mod_cat_cfn_mod(be, field, index, word_off, &value, 0); +} + +int hw_mod_cat_cfn_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, int word_off, uint32_t *value) +{ + return hw_mod_cat_cfn_mod(be, field, index, word_off, value, 1); +} + +static inline int +find_km_flm_module_interface_index(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int km_if_id) +{ + int km_if_idx; + + if (_VER_ == 18) { + km_if_idx = 0; + } else { + if (if_num == KM_FLM_IF_SECOND) { + if (be->cat.km_if_m1 == km_if_id) + km_if_idx = 1; + else + return error_unsup_field(__func__); + } else { + if (be->cat.km_if_m0 == km_if_id) + km_if_idx = 0; + else if (be->cat.km_if_m1 == km_if_id) + km_if_idx = 1; + else + return error_unsup_field(__func__); + } + } + return km_if_idx; +} + +/* + * KCE + */ + +static int hw_mod_cat_kce_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int km_if_id, + int start_idx, int count) +{ + /* writes 8 bits - one for each cfn - at a time */ + if (count == ALL_ENTRIES) + count = be->cat.nb_cat_funcs / 8; + if ((unsigned int)(start_idx + count) > (be->cat.nb_cat_funcs / 8)) + return error_index_too_large(__func__); + /* find KM module */ + int km_if_idx; + + km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id); + if (km_if_idx < 0) + return km_if_idx; + + return be->iface->cat_kce_flush(be->be_dev, &be->cat, km_if_idx, + start_idx, count); +} + +int hw_mod_cat_kce_km_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int start_idx, + int count) +{ + return hw_mod_cat_kce_flush(be, if_num, 0, start_idx, count); +} + +int hw_mod_cat_kce_flm_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int start_idx, + int count) +{ + return hw_mod_cat_kce_flush(be, if_num, 1, start_idx, count); +} + +static int hw_mod_cat_kce_mod(struct flow_api_backend_s *be, + enum hw_cat_e field, + enum km_flm_if_select_e if_num, int km_if_id, + int index, uint32_t *value, int get) +{ + if ((unsigned int)index >= (be->cat.nb_cat_funcs / 8)) + return error_index_too_large(__func__); + + /* find KM module */ + int km_if_idx; + + km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id); + if (km_if_idx < 0) + return km_if_idx; + + switch (_VER_) { + case 18: + switch (field) { + case HW_CAT_KCE_ENABLE_BM: + get_set(&be->cat.v18.kce[index].enable_bm, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 18 */ + case 21: + case 22: + switch (field) { + case HW_CAT_KCE_ENABLE_BM: + get_set(&be->cat.v21.kce[index].enable_bm[km_if_idx], + value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 21/22 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_cat_kce_km_set(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t value) +{ + return hw_mod_cat_kce_mod(be, field, if_num, 0, index, &value, 0); +} + +int hw_mod_cat_kce_km_get(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t *value) +{ + return hw_mod_cat_kce_mod(be, field, if_num, 0, index, value, 1); +} + +int hw_mod_cat_kce_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t value) +{ + return hw_mod_cat_kce_mod(be, field, if_num, 1, index, &value, 0); +} + +int hw_mod_cat_kce_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t *value) +{ + return hw_mod_cat_kce_mod(be, field, if_num, 1, index, value, 1); +} + +/* + * KCS + */ +static int hw_mod_cat_kcs_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int km_if_id, + int start_idx, int count) +{ + if (count == ALL_ENTRIES) + count = be->cat.nb_cat_funcs; + if ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs) + return error_index_too_large(__func__); + + /* find KM module */ + int km_if_idx; + + km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id); + if (km_if_idx < 0) + return km_if_idx; + + return be->iface->cat_kcs_flush(be->be_dev, &be->cat, km_if_idx, + start_idx, count); +} + +int hw_mod_cat_kcs_km_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int start_idx, + int count) +{ + return hw_mod_cat_kcs_flush(be, if_num, 0, start_idx, count); +} + +int hw_mod_cat_kcs_flm_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int start_idx, + int count) +{ + return hw_mod_cat_kcs_flush(be, if_num, 1, start_idx, count); +} + +static int hw_mod_cat_kcs_mod(struct flow_api_backend_s *be, + enum hw_cat_e field, + enum km_flm_if_select_e if_num, int km_if_id, + int index, uint32_t *value, int get) +{ + if ((unsigned int)index >= be->cat.nb_cat_funcs) + return error_index_too_large(__func__); + /* find KM module */ + int km_if_idx; + + km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id); + if (km_if_idx < 0) + return km_if_idx; + + switch (_VER_) { + case 18: + switch (field) { + case HW_CAT_KCS_CATEGORY: + get_set(&be->cat.v18.kcs[index].category, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 18 */ + case 21: + case 22: + switch (field) { + case HW_CAT_KCS_CATEGORY: + get_set(&be->cat.v21.kcs[index].category[km_if_idx], + value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 21/22 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_cat_kcs_km_set(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t value) +{ + return hw_mod_cat_kcs_mod(be, field, if_num, 0, index, &value, 0); +} + +int hw_mod_cat_kcs_km_get(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t *value) +{ + return hw_mod_cat_kcs_mod(be, field, if_num, 0, index, value, 1); +} + +int hw_mod_cat_kcs_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t value) +{ + return hw_mod_cat_kcs_mod(be, field, if_num, 1, index, &value, 0); +} + +int hw_mod_cat_kcs_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t *value) +{ + return hw_mod_cat_kcs_mod(be, field, if_num, 1, index, value, 1); +} + +/* + * FTE + */ +static int hw_mod_cat_fte_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int km_if_id, + int start_idx, int count) +{ + const uint32_t key_cnt = (_VER_ >= 20) ? 4 : 2; + + if (count == ALL_ENTRIES) + count = be->cat.nb_cat_funcs / 8 * be->cat.nb_flow_types * + key_cnt; + if ((unsigned int)(start_idx + count) > + (be->cat.nb_cat_funcs / 8 * be->cat.nb_flow_types * key_cnt)) + return error_index_too_large(__func__); + + /* find KM module */ + int km_if_idx; + + km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id); + if (km_if_idx < 0) + return km_if_idx; + + return be->iface->cat_fte_flush(be->be_dev, &be->cat, km_if_idx, + start_idx, count); +} + +int hw_mod_cat_fte_km_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int start_idx, + int count) +{ + return hw_mod_cat_fte_flush(be, if_num, 0, start_idx, count); +} + +int hw_mod_cat_fte_flm_flush(struct flow_api_backend_s *be, + enum km_flm_if_select_e if_num, int start_idx, + int count) +{ + return hw_mod_cat_fte_flush(be, if_num, 1, start_idx, count); +} + +static int hw_mod_cat_fte_mod(struct flow_api_backend_s *be, + enum hw_cat_e field, + enum km_flm_if_select_e if_num, int km_if_id, + int index, uint32_t *value, int get) +{ + const uint32_t key_cnt = (_VER_ >= 20) ? 4 : 2; + + if ((unsigned int)index >= + (be->cat.nb_cat_funcs / 8 * be->cat.nb_flow_types * key_cnt)) + return error_index_too_large(__func__); + /* find KM module */ + int km_if_idx; + + km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id); + if (km_if_idx < 0) + return km_if_idx; + + switch (_VER_) { + case 18: + switch (field) { + case HW_CAT_FTE_ENABLE_BM: + get_set(&be->cat.v18.fte[index].enable_bm, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 18 */ + case 21: + case 22: + switch (field) { + case HW_CAT_FTE_ENABLE_BM: + get_set(&be->cat.v21.fte[index].enable_bm[km_if_idx], + value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 21/22 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_cat_fte_km_set(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t value) +{ + return hw_mod_cat_fte_mod(be, field, if_num, 0, index, &value, 0); +} + +int hw_mod_cat_fte_km_get(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t *value) +{ + return hw_mod_cat_fte_mod(be, field, if_num, 0, index, value, 1); +} + +int hw_mod_cat_fte_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t value) +{ + return hw_mod_cat_fte_mod(be, field, if_num, 1, index, &value, 0); +} + +int hw_mod_cat_fte_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field, + enum km_flm_if_select_e if_num, int index, + uint32_t *value) +{ + return hw_mod_cat_fte_mod(be, field, if_num, 1, index, value, 1); +} + +int hw_mod_cat_cte_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->cat.nb_cat_funcs; + if ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs) + return error_index_too_large(__func__); + return be->iface->cat_cte_flush(be->be_dev, &be->cat, start_idx, count); +} + +static int hw_mod_cat_cte_mod(struct flow_api_backend_s *be, + enum hw_cat_e field, int index, uint32_t *value, + int get) +{ + if ((unsigned int)index >= be->cat.nb_cat_funcs) + return error_index_too_large(__func__); + switch (_VER_) { + case 18: + case 21: + case 22: + switch (field) { + case HW_CAT_CTE_ENABLE_BM: + get_set(&be->cat.v18.cte[index].enable_bm, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 18/21/22 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_cat_cte_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value) +{ + return hw_mod_cat_cte_mod(be, field, index, &value, 0); +} + +int hw_mod_cat_cte_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value) +{ + return hw_mod_cat_cte_mod(be, field, index, value, 1); +} + +int hw_mod_cat_cts_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + int addr_size = (_VER_ < 15) ? 8 : ((be->cat.cts_num + 1) / 2); + + if (count == ALL_ENTRIES) + count = be->cat.nb_cat_funcs * addr_size; + if ((unsigned int)(start_idx + count) > + (be->cat.nb_cat_funcs * addr_size)) + return error_index_too_large(__func__); + return be->iface->cat_cts_flush(be->be_dev, &be->cat, start_idx, count); +} + +static int hw_mod_cat_cts_mod(struct flow_api_backend_s *be, + enum hw_cat_e field, int index, uint32_t *value, + int get) +{ + int addr_size = (be->cat.cts_num + 1) / 2; + + if ((unsigned int)index >= (be->cat.nb_cat_funcs * addr_size)) + return error_index_too_large(__func__); + + switch (_VER_) { + case 18: + case 21: + case 22: + switch (field) { + case HW_CAT_CTS_CAT_A: + get_set(&be->cat.v18.cts[index].cat_a, value, get); + break; + case HW_CAT_CTS_CAT_B: + get_set(&be->cat.v18.cts[index].cat_b, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 18/21/22 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_cat_cts_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value) +{ + return hw_mod_cat_cts_mod(be, field, index, &value, 0); +} + +int hw_mod_cat_cts_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value) +{ + return hw_mod_cat_cts_mod(be, field, index, value, 1); +} + +int hw_mod_cat_cot_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->max_categories; + if ((unsigned int)(start_idx + count) > be->max_categories) + return error_index_too_large(__func__); + return be->iface->cat_cot_flush(be->be_dev, &be->cat, start_idx, count); +} + +static int hw_mod_cat_cot_mod(struct flow_api_backend_s *be, + enum hw_cat_e field, int index, uint32_t *value, + int get) +{ + int rv = 0; + if ((unsigned int)index >= be->max_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 18: + case 21: + case 22: + switch (field) { + case HW_CAT_COT_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->cat.v18.cot[index], (uint8_t)*value, + sizeof(struct cat_v18_cot_s)); + break; + case HW_CAT_COT_COMPARE: + rv = do_compare_indexes(be->cat.v18.cot, + sizeof(struct cat_v18_cot_s), index, *value, + be->max_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_CAT_COT_FIND: + rv = find_equal_index(be->cat.v18.cot, + sizeof(struct cat_v18_cot_s), index, *value, + be->max_categories, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_CAT_COT_COLOR: + get_set(&be->cat.v18.cot[index].color, value, get); + break; + case HW_CAT_COT_KM: + get_set(&be->cat.v18.cot[index].km, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 18/21/22 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_cat_cot_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value) +{ + return hw_mod_cat_cot_mod(be, field, index, &value, 0); +} + +int hw_mod_cat_cot_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value) +{ + return hw_mod_cat_cot_mod(be, field, index, value, 1); +} + +int hw_mod_cat_cct_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->cat.nb_cat_funcs * 4; + if ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs * 4) + return error_index_too_large(__func__); + return be->iface->cat_cct_flush(be->be_dev, &be->cat, start_idx, count); +} + +static int hw_mod_cat_cct_mod(struct flow_api_backend_s *be, + enum hw_cat_e field, int index, uint32_t *value, + int get) +{ + if ((unsigned int)index >= be->cat.nb_cat_funcs * 4) + return error_index_too_large(__func__); + switch (_VER_) { + case 18: + case 21: + case 22: + switch (field) { + case HW_CAT_CCT_COLOR: + get_set(&be->cat.v18.cct[index].color, value, get); + break; + case HW_CAT_CCT_KM: + get_set(&be->cat.v18.cct[index].km, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 18/21/22 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_cat_cct_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value) +{ + return hw_mod_cat_cct_mod(be, field, index, &value, 0); +} + +int hw_mod_cat_cct_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value) +{ + return hw_mod_cat_cct_mod(be, field, index, value, 1); +} + +int hw_mod_cat_kcc_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->cat.kcc_size; + if ((unsigned int)(start_idx + count) > be->cat.kcc_size) + return error_index_too_large(__func__); + return be->iface->cat_kcc_flush(be->be_dev, &be->cat, start_idx, count); +} + +static int hw_mod_cat_kcc_mod(struct flow_api_backend_s *be, + enum hw_cat_e field, int index, int word_off, + uint32_t *value, int get) +{ + if ((unsigned int)index >= be->cat.kcc_size) + return error_index_too_large(__func__); + switch (_VER_) { + case 18: + case 21: + case 22: + switch (field) { + case HW_CAT_KCC_KEY: + if (word_off > 1) + return error_word_off_too_large(__func__); + get_set(&be->cat.v18.kcc_cam[index].key[word_off], value, + get); + break; + + case HW_CAT_KCC_CATEGORY: + get_set(&be->cat.v18.kcc_cam[index].category, value, get); + break; + + case HW_CAT_KCC_ID: + get_set(&be->cat.v18.kcc_cam[index].id, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 18/21/22 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_cat_kcc_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, int word_off, uint32_t value) +{ + return hw_mod_cat_kcc_mod(be, field, index, word_off, &value, 0); +} + +int hw_mod_cat_kcc_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, int word_off, uint32_t *value) +{ + return hw_mod_cat_kcc_mod(be, field, index, word_off, value, 1); +} + +int hw_mod_cat_exo_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->cat.nb_pm_ext; + if ((unsigned int)(start_idx + count) > be->cat.nb_pm_ext) + return error_index_too_large(__func__); + return be->iface->cat_exo_flush(be->be_dev, &be->cat, start_idx, count); +} + +static int hw_mod_cat_exo_mod(struct flow_api_backend_s *be, + enum hw_cat_e field, int index, uint32_t *value, + int get) +{ + if ((unsigned int)index >= be->cat.nb_pm_ext) + return error_index_too_large(__func__); + switch (_VER_) { + case 18: + case 21: + case 22: + switch (field) { + case HW_CAT_EXO_DYN: + get_set(&be->cat.v18.exo[index].dyn, value, get); + break; + case HW_CAT_EXO_OFS: + get_set_signed(&be->cat.v18.exo[index].ofs, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 18/21/22 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_cat_exo_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value) +{ + return hw_mod_cat_exo_mod(be, field, index, &value, 0); +} + +int hw_mod_cat_exo_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value) +{ + return hw_mod_cat_exo_mod(be, field, index, value, 1); +} + +int hw_mod_cat_rck_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->cat.nb_pm_ext * 64; + if ((unsigned int)(start_idx + count) > (be->cat.nb_pm_ext * 64)) + return error_index_too_large(__func__); + return be->iface->cat_rck_flush(be->be_dev, &be->cat, start_idx, count); +} + +static int hw_mod_cat_rck_mod(struct flow_api_backend_s *be, + enum hw_cat_e field, int index, uint32_t *value, + int get) +{ + if ((unsigned int)index >= (be->cat.nb_pm_ext * 64)) + return error_index_too_large(__func__); + switch (_VER_) { + case 18: + case 21: + case 22: + switch (field) { + case HW_CAT_RCK_DATA: + get_set(&be->cat.v18.rck[index].rck_data, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 18/21/22 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_cat_rck_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value) +{ + return hw_mod_cat_rck_mod(be, field, index, &value, 0); +} + +int hw_mod_cat_rck_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value) +{ + return hw_mod_cat_rck_mod(be, field, index, value, 1); +} + +int hw_mod_cat_len_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->cat.nb_len; + if ((unsigned int)(start_idx + count) > be->cat.nb_len) + return error_index_too_large(__func__); + return be->iface->cat_len_flush(be->be_dev, &be->cat, start_idx, count); +} + +static int hw_mod_cat_len_mod(struct flow_api_backend_s *be, + enum hw_cat_e field, int index, uint32_t *value, + int get) +{ + if ((unsigned int)index >= be->cat.nb_len) + return error_index_too_large(__func__); + switch (_VER_) { + case 18: + case 21: + case 22: + switch (field) { + case HW_CAT_LEN_LOWER: + get_set(&be->cat.v18.len[index].lower, value, get); + break; + case HW_CAT_LEN_UPPER: + get_set(&be->cat.v18.len[index].upper, value, get); + break; + case HW_CAT_LEN_DYN1: + get_set(&be->cat.v18.len[index].dyn1, value, get); + break; + case HW_CAT_LEN_DYN2: + get_set(&be->cat.v18.len[index].dyn2, value, get); + break; + case HW_CAT_LEN_INV: + get_set(&be->cat.v18.len[index].inv, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 18/21/22 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_cat_len_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value) +{ + return hw_mod_cat_len_mod(be, field, index, &value, 0); +} + +int hw_mod_cat_len_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value) +{ + return hw_mod_cat_len_mod(be, field, index, value, 1); +} + +int hw_mod_cat_cce_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = 4; + if ((unsigned int)(start_idx + count) > 4) + return error_index_too_large(__func__); + return be->iface->cat_cce_flush(be->be_dev, &be->cat, start_idx, count); +} + +static int hw_mod_cat_cce_mod(struct flow_api_backend_s *be, + enum hw_cat_e field, int index, uint32_t *value, + int get) +{ + if ((unsigned int)index >= be->cat.nb_len) + return error_index_too_large(__func__); + switch (_VER_) { + case 22: + switch (field) { + case HW_CAT_CCE_IMM: + get_set(&be->cat.v22.cce[index].imm, value, get); + break; + case HW_CAT_CCE_IND: + get_set(&be->cat.v22.cce[index].ind, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 22 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_cat_cce_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value) +{ + return hw_mod_cat_cce_mod(be, field, index, &value, 0); +} + +int hw_mod_cat_cce_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value) +{ + return hw_mod_cat_cce_mod(be, field, index, value, 1); +} + +int hw_mod_cat_ccs_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = 1024; + if ((unsigned int)(start_idx + count) > 1024) + return error_index_too_large(__func__); + return be->iface->cat_ccs_flush(be->be_dev, &be->cat, start_idx, count); +} + +static int hw_mod_cat_ccs_mod(struct flow_api_backend_s *be, + enum hw_cat_e field, int index, uint32_t *value, + int get) +{ + if ((unsigned int)index >= be->cat.nb_len) + return error_index_too_large(__func__); + switch (_VER_) { + case 22: + switch (field) { + case HW_CAT_CCS_COR_EN: + get_set(&be->cat.v22.ccs[index].cor_en, value, get); + break; + case HW_CAT_CCS_COR: + get_set(&be->cat.v22.ccs[index].cor, value, get); + break; + case HW_CAT_CCS_HSH_EN: + get_set(&be->cat.v22.ccs[index].hsh_en, value, get); + break; + case HW_CAT_CCS_HSH: + get_set(&be->cat.v22.ccs[index].hsh, value, get); + break; + case HW_CAT_CCS_QSL_EN: + get_set(&be->cat.v22.ccs[index].qsl_en, value, get); + break; + case HW_CAT_CCS_QSL: + get_set(&be->cat.v22.ccs[index].qsl, value, get); + break; + case HW_CAT_CCS_IPF_EN: + get_set(&be->cat.v22.ccs[index].ipf_en, value, get); + break; + case HW_CAT_CCS_IPF: + get_set(&be->cat.v22.ccs[index].ipf, value, get); + break; + case HW_CAT_CCS_SLC_EN: + get_set(&be->cat.v22.ccs[index].slc_en, value, get); + break; + case HW_CAT_CCS_SLC: + get_set(&be->cat.v22.ccs[index].slc, value, get); + break; + case HW_CAT_CCS_PDB_EN: + get_set(&be->cat.v22.ccs[index].pdb_en, value, get); + break; + case HW_CAT_CCS_PDB: + get_set(&be->cat.v22.ccs[index].pdb, value, get); + break; + case HW_CAT_CCS_MSK_EN: + get_set(&be->cat.v22.ccs[index].msk_en, value, get); + break; + case HW_CAT_CCS_MSK: + get_set(&be->cat.v22.ccs[index].msk, value, get); + break; + case HW_CAT_CCS_HST_EN: + get_set(&be->cat.v22.ccs[index].hst_en, value, get); + break; + case HW_CAT_CCS_HST: + get_set(&be->cat.v22.ccs[index].hst, value, get); + break; + case HW_CAT_CCS_EPP_EN: + get_set(&be->cat.v22.ccs[index].epp_en, value, get); + break; + case HW_CAT_CCS_EPP: + get_set(&be->cat.v22.ccs[index].epp, value, get); + break; + case HW_CAT_CCS_TPE_EN: + get_set(&be->cat.v22.ccs[index].tpe_en, value, get); + break; + case HW_CAT_CCS_TPE: + get_set(&be->cat.v22.ccs[index].tpe, value, get); + break; + case HW_CAT_CCS_RRB_EN: + get_set(&be->cat.v22.ccs[index].rrb_en, value, get); + break; + case HW_CAT_CCS_RRB: + get_set(&be->cat.v22.ccs[index].rrb, value, get); + break; + case HW_CAT_CCS_SB0_TYPE: + get_set(&be->cat.v22.ccs[index].sb0_type, value, get); + break; + case HW_CAT_CCS_SB0_DATA: + get_set(&be->cat.v22.ccs[index].sb0_data, value, get); + break; + case HW_CAT_CCS_SB1_TYPE: + get_set(&be->cat.v22.ccs[index].sb1_type, value, get); + break; + case HW_CAT_CCS_SB1_DATA: + get_set(&be->cat.v22.ccs[index].sb1_data, value, get); + break; + case HW_CAT_CCS_SB2_TYPE: + get_set(&be->cat.v22.ccs[index].sb2_type, value, get); + break; + case HW_CAT_CCS_SB2_DATA: + get_set(&be->cat.v22.ccs[index].sb2_data, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 22 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_cat_ccs_set(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t value) +{ + return hw_mod_cat_ccs_mod(be, field, index, &value, 0); +} + +int hw_mod_cat_ccs_get(struct flow_api_backend_s *be, enum hw_cat_e field, + int index, uint32_t *value) +{ + return hw_mod_cat_ccs_mod(be, field, index, value, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h new file mode 100644 index 0000000000..3dc4a0aac7 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_CAT_V18_H_ +#define _HW_MOD_CAT_V18_H_ + +struct cat_v18_cfn_s { + uint32_t enable; + uint32_t inv; + /* protocol checks */ + uint32_t ptc_inv; + uint32_t ptc_isl; + uint32_t ptc_cfp; + uint32_t ptc_mac; + uint32_t ptc_l2; + uint32_t ptc_vntag; + uint32_t ptc_vlan; + uint32_t ptc_mpls; + uint32_t ptc_l3; + uint32_t ptc_frag; + uint32_t ptc_ip_prot; + uint32_t ptc_l4; + uint32_t ptc_tunnel; + uint32_t ptc_tnl_l2; + uint32_t ptc_tnl_vlan; + uint32_t ptc_tnl_mpls; + uint32_t ptc_tnl_l3; + uint32_t ptc_tnl_frag; + uint32_t ptc_tnl_ip_prot; + uint32_t ptc_tnl_l4; + /* error checks */ + uint32_t err_inv; + uint32_t err_cv; + uint32_t err_fcs; + uint32_t err_trunc; + uint32_t err_l3_cs; + uint32_t err_l4_cs; + /* in port */ + uint32_t mac_port; + /* pattern matcher */ + uint32_t pm_cmp[2]; + uint32_t pm_dct; + uint32_t pm_ext_inv; + uint32_t pm_cmb; + uint32_t pm_and_inv; + uint32_t pm_or_inv; + uint32_t pm_inv; + uint32_t lc; + uint32_t lc_inv; + uint32_t km_or; +}; + +struct cat_v18_kce_s { + uint32_t enable_bm; +}; + +struct cat_v18_kcs_s { + uint32_t category; +}; + +struct cat_v18_fte_s { + uint32_t enable_bm; +}; + +struct cat_v18_cte_s { + union { + uint32_t enable_bm; + struct { + uint32_t col : 1; + uint32_t cor : 1; + uint32_t hsh : 1; + uint32_t qsl : 1; + uint32_t ipf : 1; + uint32_t slc : 1; + uint32_t pdb : 1; + uint32_t msk : 1; + uint32_t hst : 1; + uint32_t epp : 1; + uint32_t tpe : 1; + } b; + }; +}; + +struct cat_v18_cts_s { + uint32_t cat_a; + uint32_t cat_b; +}; + +struct cat_v18_cot_s { + uint32_t color; + uint32_t km; +}; + +struct cat_v18_cct_s { + uint32_t color; + uint32_t km; +}; + +struct cat_v18_exo_s { + uint32_t dyn; + int32_t ofs; +}; + +struct cat_v18_rck_s { + uint32_t rck_data; +}; + +struct cat_v18_len_s { + uint32_t lower; + uint32_t upper; + uint32_t dyn1; + uint32_t dyn2; + uint32_t inv; +}; + +struct cat_v18_kcc_s { + uint32_t key[2]; + uint32_t category; + uint32_t id; +}; + +struct hw_mod_cat_v18_s { + struct cat_v18_cfn_s *cfn; + struct cat_v18_kce_s *kce; + struct cat_v18_kcs_s *kcs; + struct cat_v18_fte_s *fte; + struct cat_v18_cte_s *cte; + struct cat_v18_cts_s *cts; + struct cat_v18_cot_s *cot; + struct cat_v18_cct_s *cct; + struct cat_v18_exo_s *exo; + struct cat_v18_rck_s *rck; + struct cat_v18_len_s *len; + struct cat_v18_kcc_s *kcc_cam; +}; + +#endif /* _HW_MOD_CAT_V18_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h new file mode 100644 index 0000000000..fa69ec11f3 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_CAT_V21_H_ +#define _HW_MOD_CAT_V21_H_ + +#include "hw_mod_cat_v18.h" + +struct cat_v21_cfn_s { + uint32_t enable; + uint32_t inv; + /* protocol checks */ + uint32_t ptc_inv; + uint32_t ptc_isl; + uint32_t ptc_cfp; + uint32_t ptc_mac; + uint32_t ptc_l2; + uint32_t ptc_vntag; + uint32_t ptc_vlan; + uint32_t ptc_mpls; + uint32_t ptc_l3; + uint32_t ptc_frag; + uint32_t ptc_ip_prot; + uint32_t ptc_l4; + uint32_t ptc_tunnel; + uint32_t ptc_tnl_l2; + uint32_t ptc_tnl_vlan; + uint32_t ptc_tnl_mpls; + uint32_t ptc_tnl_l3; + uint32_t ptc_tnl_frag; + uint32_t ptc_tnl_ip_prot; + uint32_t ptc_tnl_l4; + /* error checks */ + uint32_t err_inv; + uint32_t err_cv; + uint32_t err_fcs; + uint32_t err_trunc; + uint32_t err_l3_cs; + uint32_t err_l4_cs; + uint32_t err_tnl_l3_cs; + uint32_t err_tnl_l4_cs; + uint32_t err_ttl_exp; + uint32_t err_tnl_ttl_exp; + /* in port */ + uint32_t mac_port; + /* pattern matcher */ + uint32_t pm_cmp[2]; + uint32_t pm_dct; + uint32_t pm_ext_inv; + uint32_t pm_cmb; + uint32_t pm_and_inv; + uint32_t pm_or_inv; + uint32_t pm_inv; + uint32_t lc; + uint32_t lc_inv; + uint32_t km0_or; + uint32_t km1_or; +}; + +struct cat_v21_kce_s { + uint32_t enable_bm[2]; +}; + +struct cat_v21_kcs_s { + uint32_t category[2]; +}; + +struct cat_v21_fte_s { + uint32_t enable_bm[2]; +}; + +struct hw_mod_cat_v21_s { + struct cat_v21_cfn_s *cfn; + struct cat_v21_kce_s *kce; + struct cat_v21_kcs_s *kcs; + struct cat_v21_fte_s *fte; + struct cat_v18_cte_s *cte; + struct cat_v18_cts_s *cts; + struct cat_v18_cot_s *cot; + struct cat_v18_cct_s *cct; + struct cat_v18_exo_s *exo; + struct cat_v18_rck_s *rck; + struct cat_v18_len_s *len; + struct cat_v18_kcc_s *kcc_cam; +}; + +#endif /* _HW_MOD_CAT_V21_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h new file mode 100644 index 0000000000..fa7dc6f441 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_CAT_V22_H_ +#define _HW_MOD_CAT_V22_H_ + +#include "hw_mod_cat_v21.h" + +struct cat_v22_cte_s { + union { + uint32_t enable_bm; + struct { + uint32_t col : 1; + uint32_t cor : 1; + uint32_t hsh : 1; + uint32_t qsl : 1; + uint32_t ipf : 1; + uint32_t slc : 1; + uint32_t pdb : 1; + uint32_t msk : 1; + uint32_t hst : 1; + uint32_t epp : 1; + uint32_t tpe : 1; + uint32_t rrb : 1; + } b; + }; +}; + +struct cat_v22_cce_s { + uint32_t imm; + uint32_t ind; +}; + +struct cat_v22_ccs_s { + uint32_t cor_en; + uint32_t cor; + uint32_t hsh_en; + uint32_t hsh; + uint32_t qsl_en; + uint32_t qsl; + uint32_t ipf_en; + uint32_t ipf; + uint32_t slc_en; + uint32_t slc; + uint32_t pdb_en; + uint32_t pdb; + uint32_t msk_en; + uint32_t msk; + uint32_t hst_en; + uint32_t hst; + uint32_t epp_en; + uint32_t epp; + uint32_t tpe_en; + uint32_t tpe; + uint32_t rrb_en; + uint32_t rrb; + uint32_t sb0_type; + uint32_t sb0_data; + uint32_t sb1_type; + uint32_t sb1_data; + uint32_t sb2_type; + uint32_t sb2_data; +}; + +struct hw_mod_cat_v22_s { + struct cat_v21_cfn_s *cfn; + struct cat_v21_kce_s *kce; /* KCE 0/1 */ + struct cat_v21_kcs_s *kcs; /* KCS 0/1 */ + struct cat_v21_fte_s *fte; /* FTE 0/1 */ + struct cat_v22_cte_s *cte; + struct cat_v18_cts_s *cts; + struct cat_v18_cot_s *cot; + struct cat_v18_cct_s *cct; + struct cat_v18_exo_s *exo; + struct cat_v18_rck_s *rck; + struct cat_v18_len_s *len; + struct cat_v18_kcc_s *kcc_cam; + struct cat_v22_cce_s *cce; + struct cat_v22_ccs_s *ccs; +}; + +#endif /* _HW_MOD_CAT_V22_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c new file mode 100644 index 0000000000..404add5fe6 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c @@ -0,0 +1,1099 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include "flow_api_backend.h" + +#define _MOD_ "FLM" +#define _VER_ be->flm.ver + +bool hw_mod_flm_present(struct flow_api_backend_s *be) +{ + return be->iface->get_flm_present(be->be_dev); +} + +int hw_mod_flm_alloc(struct flow_api_backend_s *be) +{ + int nb; + + _VER_ = be->iface->get_flm_version(be->be_dev); + NT_LOG(DBG, FILTER, "FLM MODULE VERSION %i.%i\n", VER_MAJOR(_VER_), + VER_MINOR(_VER_)); + + nb = be->iface->get_nb_flm_categories(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "flm_categories", _MOD_, _VER_); + be->flm.nb_categories = (uint32_t)nb; + + nb = be->iface->get_nb_flm_size_mb(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "flm_size_mb", _MOD_, _VER_); + be->flm.nb_size_mb = (uint32_t)nb; + + nb = be->iface->get_nb_flm_entry_size(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "flm_entry_size", _MOD_, _VER_); + be->flm.nb_entry_size = (uint32_t)nb; + + nb = be->iface->get_nb_flm_variant(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "flm_variant", _MOD_, _VER_); + be->flm.nb_variant = (uint32_t)nb; + + nb = be->iface->get_nb_flm_prios(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "flm_prios", _MOD_, _VER_); + be->flm.nb_prios = (uint32_t)nb; + + nb = be->iface->get_nb_flm_pst_profiles(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "flm_variant", _MOD_, _VER_); + be->flm.nb_pst_profiles = (uint32_t)nb; + + switch (_VER_) { + case 17: + if (!callocate_mod(CAST_COMMON(&be->flm), 26, + &be->flm.v17.control, 1, + sizeof(struct flm_v17_control_s), + &be->flm.v17.status, 1, + sizeof(struct flm_v17_status_s), + &be->flm.v17.timeout, 1, + sizeof(struct flm_v17_timeout_s), + &be->flm.v17.scrub, 1, + sizeof(struct flm_v17_scrub_s), + &be->flm.v17.load_bin, 1, + sizeof(struct flm_v17_load_bin_s), + &be->flm.v17.load_pps, 1, + sizeof(struct flm_v17_load_pps_s), + &be->flm.v17.load_lps, 1, + sizeof(struct flm_v17_load_lps_s), + &be->flm.v17.load_aps, 1, + sizeof(struct flm_v17_load_aps_s), + &be->flm.v17.prio, 1, + sizeof(struct flm_v17_prio_s), + &be->flm.v17.pst, be->flm.nb_pst_profiles, + sizeof(struct flm_v17_pst_s), + &be->flm.v17.rcp, be->flm.nb_categories, + sizeof(struct flm_v17_rcp_s), + &be->flm.v17.buf_ctrl, 1, + sizeof(struct flm_v17_buf_ctrl_s), + &be->flm.v17.lrn_done, 1, + sizeof(struct flm_v17_stat_lrn_done_s), + &be->flm.v17.lrn_ignore, 1, + sizeof(struct flm_v17_stat_lrn_ignore_s), + &be->flm.v17.lrn_fail, 1, + sizeof(struct flm_v17_stat_lrn_fail_s), + &be->flm.v17.unl_done, 1, + sizeof(struct flm_v17_stat_unl_done_s), + &be->flm.v17.unl_ignore, 1, + sizeof(struct flm_v17_stat_unl_ignore_s), + &be->flm.v17.rel_done, 1, + sizeof(struct flm_v17_stat_rel_done_s), + &be->flm.v17.rel_ignore, 1, + sizeof(struct flm_v17_stat_rel_ignore_s), + &be->flm.v17.aul_done, 1, + sizeof(struct flm_v17_stat_aul_done_s), + &be->flm.v17.aul_ignore, 1, + sizeof(struct flm_v17_stat_aul_ignore_s), + &be->flm.v17.aul_fail, 1, + sizeof(struct flm_v17_stat_aul_fail_s), + &be->flm.v17.tul_done, 1, + sizeof(struct flm_v17_stat_tul_done_s), + &be->flm.v17.flows, 1, + sizeof(struct flm_v17_stat_flows_s), + &be->flm.v17.prb_done, 1, + sizeof(struct flm_v17_stat_prb_done_s), + &be->flm.v17.prb_ignore, 1, + sizeof(struct flm_v17_stat_prb_ignore_s))) + return -1; + break; + + case 20: + if (!callocate_mod(CAST_COMMON(&be->flm), 38, + &be->flm.v17.control, 1, + sizeof(struct flm_v17_control_s), + &be->flm.v17.status, 1, + sizeof(struct flm_v17_status_s), + &be->flm.v17.timeout, 1, + sizeof(struct flm_v17_timeout_s), + &be->flm.v17.scrub, 1, + sizeof(struct flm_v17_scrub_s), + &be->flm.v17.load_bin, 1, + sizeof(struct flm_v17_load_bin_s), + &be->flm.v17.load_pps, 1, + sizeof(struct flm_v17_load_pps_s), + &be->flm.v17.load_lps, 1, + sizeof(struct flm_v17_load_lps_s), + &be->flm.v17.load_aps, 1, + sizeof(struct flm_v17_load_aps_s), + &be->flm.v17.prio, 1, + sizeof(struct flm_v17_prio_s), + &be->flm.v17.pst, be->flm.nb_pst_profiles, + sizeof(struct flm_v17_pst_s), + &be->flm.v17.rcp, be->flm.nb_categories, + sizeof(struct flm_v17_rcp_s), + &be->flm.v17.buf_ctrl, 1, + sizeof(struct flm_v17_buf_ctrl_s), + &be->flm.v17.lrn_done, 1, + sizeof(struct flm_v17_stat_lrn_done_s), + &be->flm.v17.lrn_ignore, 1, + sizeof(struct flm_v17_stat_lrn_ignore_s), + &be->flm.v17.lrn_fail, 1, + sizeof(struct flm_v17_stat_lrn_fail_s), + &be->flm.v17.unl_done, 1, + sizeof(struct flm_v17_stat_unl_done_s), + &be->flm.v17.unl_ignore, 1, + sizeof(struct flm_v17_stat_unl_ignore_s), + &be->flm.v17.rel_done, 1, + sizeof(struct flm_v17_stat_rel_done_s), + &be->flm.v17.rel_ignore, 1, + sizeof(struct flm_v17_stat_rel_ignore_s), + &be->flm.v17.aul_done, 1, + sizeof(struct flm_v17_stat_aul_done_s), + &be->flm.v17.aul_ignore, 1, + sizeof(struct flm_v17_stat_aul_ignore_s), + &be->flm.v17.aul_fail, 1, + sizeof(struct flm_v17_stat_aul_fail_s), + &be->flm.v17.tul_done, 1, + sizeof(struct flm_v17_stat_tul_done_s), + &be->flm.v17.flows, 1, + sizeof(struct flm_v17_stat_flows_s), + &be->flm.v17.prb_done, 1, + sizeof(struct flm_v17_stat_prb_done_s), + &be->flm.v17.prb_ignore, 1, + sizeof(struct flm_v17_stat_prb_ignore_s), + &be->flm.v20.sta_done, 1, + sizeof(struct flm_v20_stat_sta_done_s), + &be->flm.v20.inf_done, 1, + sizeof(struct flm_v20_stat_inf_done_s), + &be->flm.v20.inf_skip, 1, + sizeof(struct flm_v20_stat_inf_skip_s), + &be->flm.v20.pck_hit, 1, + sizeof(struct flm_v20_stat_pck_hit_s), + &be->flm.v20.pck_miss, 1, + sizeof(struct flm_v20_stat_pck_miss_s), + &be->flm.v20.pck_unh, 1, + sizeof(struct flm_v20_stat_pck_unh_s), + &be->flm.v20.pck_dis, 1, + sizeof(struct flm_v20_stat_pck_dis_s), + &be->flm.v20.csh_hit, 1, + sizeof(struct flm_v20_stat_csh_hit_s), + &be->flm.v20.csh_miss, 1, + sizeof(struct flm_v20_stat_csh_miss_s), + &be->flm.v20.csh_unh, 1, + sizeof(struct flm_v20_stat_csh_unh_s), + &be->flm.v20.cuc_start, 1, + sizeof(struct flm_v20_stat_cuc_start_s), + &be->flm.v20.cuc_move, 1, + sizeof(struct flm_v20_stat_cuc_move_s))) + return -1; + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +void hw_mod_flm_free(struct flow_api_backend_s *be) +{ + if (be->flm.base) { + free(be->flm.base); + be->flm.base = NULL; + } +} + +int hw_mod_flm_reset(struct flow_api_backend_s *be) +{ + /* Zero entire cache area */ + ZERO_MOD_CACHE(&be->flm); + + NT_LOG(DBG, FILTER, "INIT FLM\n"); + hw_mod_flm_control_set(be, HW_FLM_CONTROL_SPLIT_SDRAM_USAGE, 0x10); + + hw_mod_flm_control_flush(be); + hw_mod_flm_timeout_flush(be); + hw_mod_flm_scrub_flush(be); + hw_mod_flm_rcp_flush(be, 0, ALL_ENTRIES); + + return 0; +} + +int hw_mod_flm_control_flush(struct flow_api_backend_s *be) +{ + return be->iface->flm_control_flush(be->be_dev, &be->flm); +} + +static int hw_mod_flm_control_mod(struct flow_api_backend_s *be, + enum hw_flm_e field, uint32_t *value, int get) +{ + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_CONTROL_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(be->flm.v17.control, (uint8_t)*value, + sizeof(struct flm_v17_control_s)); + break; + case HW_FLM_CONTROL_ENABLE: + get_set(&be->flm.v17.control->enable, value, get); + break; + case HW_FLM_CONTROL_INIT: + get_set(&be->flm.v17.control->init, value, get); + break; + case HW_FLM_CONTROL_LDS: + get_set(&be->flm.v17.control->lds, value, get); + break; + case HW_FLM_CONTROL_LFS: + get_set(&be->flm.v17.control->lfs, value, get); + break; + case HW_FLM_CONTROL_LIS: + get_set(&be->flm.v17.control->lis, value, get); + break; + case HW_FLM_CONTROL_UDS: + get_set(&be->flm.v17.control->uds, value, get); + break; + case HW_FLM_CONTROL_UIS: + get_set(&be->flm.v17.control->uis, value, get); + break; + case HW_FLM_CONTROL_RDS: + get_set(&be->flm.v17.control->rds, value, get); + break; + case HW_FLM_CONTROL_RIS: + get_set(&be->flm.v17.control->ris, value, get); + break; + case HW_FLM_CONTROL_PDS: + get_set(&be->flm.v17.control->pds, value, get); + break; + case HW_FLM_CONTROL_PIS: + get_set(&be->flm.v17.control->pis, value, get); + break; + case HW_FLM_CONTROL_CRCWR: + get_set(&be->flm.v17.control->crcwr, value, get); + break; + case HW_FLM_CONTROL_CRCRD: + get_set(&be->flm.v17.control->crcrd, value, get); + break; + case HW_FLM_CONTROL_RBL: + get_set(&be->flm.v17.control->rbl, value, get); + break; + case HW_FLM_CONTROL_EAB: + get_set(&be->flm.v17.control->eab, value, get); + break; + case HW_FLM_CONTROL_SPLIT_SDRAM_USAGE: + get_set(&be->flm.v17.control->split_sdram_usage, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_flm_control_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value) +{ + return hw_mod_flm_control_mod(be, field, &value, 0); +} + +int hw_mod_flm_control_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value) +{ + return hw_mod_flm_control_mod(be, field, value, 1); +} + +int hw_mod_flm_status_flush(struct flow_api_backend_s *be) +{ + return be->iface->flm_status_flush(be->be_dev, &be->flm); +} + +int hw_mod_flm_status_update(struct flow_api_backend_s *be) +{ + return be->iface->flm_status_update(be->be_dev, &be->flm); +} + +static int hw_mod_flm_status_mod(struct flow_api_backend_s *be, + enum hw_flm_e field, uint32_t *value, int get) +{ + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_STATUS_CALIBDONE: + get_set(&be->flm.v17.status->calibdone, value, get); + break; + case HW_FLM_STATUS_INITDONE: + get_set(&be->flm.v17.status->initdone, value, get); + break; + case HW_FLM_STATUS_IDLE: + get_set(&be->flm.v17.status->idle, value, get); + break; + case HW_FLM_STATUS_CRITICAL: + get_set(&be->flm.v17.status->critical, value, get); + break; + case HW_FLM_STATUS_PANIC: + get_set(&be->flm.v17.status->panic, value, get); + break; + case HW_FLM_STATUS_CRCERR: + get_set(&be->flm.v17.status->crcerr, value, get); + break; + case HW_FLM_STATUS_EFT_BP: + get_set(&be->flm.v17.status->eft_bp, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_flm_status_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value) +{ + return hw_mod_flm_status_mod(be, field, &value, 0); +} + +int hw_mod_flm_status_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value) +{ + return hw_mod_flm_status_mod(be, field, value, 1); +} + +int hw_mod_flm_timeout_flush(struct flow_api_backend_s *be) +{ + return be->iface->flm_timeout_flush(be->be_dev, &be->flm); +} + +static int hw_mod_flm_timeout_mod(struct flow_api_backend_s *be, + enum hw_flm_e field, uint32_t *value, int get) +{ + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_TIMEOUT_T: + get_set(&be->flm.v17.timeout->t, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_flm_timeout_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value) +{ + return hw_mod_flm_timeout_mod(be, field, &value, 0); +} + +int hw_mod_flm_timeout_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value) +{ + return hw_mod_flm_timeout_mod(be, field, value, 1); +} + +int hw_mod_flm_scrub_flush(struct flow_api_backend_s *be) +{ + return be->iface->flm_scrub_flush(be->be_dev, &be->flm); +} + +static int hw_mod_flm_scrub_mod(struct flow_api_backend_s *be, + enum hw_flm_e field, uint32_t *value, int get) +{ + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_SCRUB_I: + get_set(&be->flm.v17.scrub->i, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_flm_scrub_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value) +{ + return hw_mod_flm_scrub_mod(be, field, &value, 0); +} + +int hw_mod_flm_scrub_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value) +{ + return hw_mod_flm_scrub_mod(be, field, value, 1); +} + +int hw_mod_flm_load_bin_flush(struct flow_api_backend_s *be) +{ + return be->iface->flm_load_bin_flush(be->be_dev, &be->flm); +} + +static int hw_mod_flm_load_bin_mod(struct flow_api_backend_s *be, + enum hw_flm_e field, uint32_t *value, + int get) +{ + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_LOAD_BIN: + get_set(&be->flm.v17.load_bin->bin, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_flm_load_bin_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value) +{ + return hw_mod_flm_load_bin_mod(be, field, &value, 0); +} + +int hw_mod_flm_load_bin_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value) +{ + return hw_mod_flm_load_bin_mod(be, field, value, 1); +} + +int hw_mod_flm_load_pps_flush(struct flow_api_backend_s *be) +{ + return be->iface->flm_load_pps_flush(be->be_dev, &be->flm); +} + +static int hw_mod_flm_load_pps_mod(struct flow_api_backend_s *be, + enum hw_flm_e field, uint32_t *value, + int get) +{ + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_LOAD_PPS: + get_set(&be->flm.v17.load_pps->pps, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_flm_load_pps_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value) +{ + return hw_mod_flm_load_pps_mod(be, field, &value, 0); +} + +int hw_mod_flm_load_pps_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value) +{ + return hw_mod_flm_load_pps_mod(be, field, value, 1); +} + +int hw_mod_flm_load_lps_flush(struct flow_api_backend_s *be) +{ + return be->iface->flm_load_lps_flush(be->be_dev, &be->flm); +} + +static int hw_mod_flm_load_lps_mod(struct flow_api_backend_s *be, + enum hw_flm_e field, uint32_t *value, + int get) +{ + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_LOAD_LPS: + get_set(&be->flm.v17.load_lps->lps, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_flm_load_lps_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value) +{ + return hw_mod_flm_load_lps_mod(be, field, &value, 0); +} + +int hw_mod_flm_load_lps_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value) +{ + return hw_mod_flm_load_lps_mod(be, field, value, 1); +} + +int hw_mod_flm_load_aps_flush(struct flow_api_backend_s *be) +{ + return be->iface->flm_load_aps_flush(be->be_dev, &be->flm); +} + +static int hw_mod_flm_load_aps_mod(struct flow_api_backend_s *be, + enum hw_flm_e field, uint32_t *value, + int get) +{ + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_LOAD_APS: + get_set(&be->flm.v17.load_aps->aps, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_flm_load_aps_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value) +{ + return hw_mod_flm_load_aps_mod(be, field, &value, 0); +} + +int hw_mod_flm_load_aps_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value) +{ + return hw_mod_flm_load_aps_mod(be, field, value, 1); +} + +int hw_mod_flm_prio_flush(struct flow_api_backend_s *be) +{ + return be->iface->flm_prio_flush(be->be_dev, &be->flm); +} + +static int hw_mod_flm_prio_mod(struct flow_api_backend_s *be, + enum hw_flm_e field, uint32_t *value, int get) +{ + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_PRIO_LIMIT0: + get_set(&be->flm.v17.prio->limit0, value, get); + break; + case HW_FLM_PRIO_FT0: + get_set(&be->flm.v17.prio->ft0, value, get); + break; + case HW_FLM_PRIO_LIMIT1: + get_set(&be->flm.v17.prio->limit1, value, get); + break; + case HW_FLM_PRIO_FT1: + get_set(&be->flm.v17.prio->ft1, value, get); + break; + case HW_FLM_PRIO_LIMIT2: + get_set(&be->flm.v17.prio->limit2, value, get); + break; + case HW_FLM_PRIO_FT2: + get_set(&be->flm.v17.prio->ft2, value, get); + break; + case HW_FLM_PRIO_LIMIT3: + get_set(&be->flm.v17.prio->limit3, value, get); + break; + case HW_FLM_PRIO_FT3: + get_set(&be->flm.v17.prio->ft3, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_flm_prio_set(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t value) +{ + return hw_mod_flm_prio_mod(be, field, &value, 0); +} + +int hw_mod_flm_prio_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value) +{ + return hw_mod_flm_prio_mod(be, field, value, 1); +} + +int hw_mod_flm_pst_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->flm.nb_pst_profiles; + if ((unsigned int)(start_idx + count) > be->flm.nb_pst_profiles) + return error_index_too_large(__func__); + return be->iface->flm_pst_flush(be->be_dev, &be->flm, start_idx, count); +} + +static int hw_mod_flm_pst_mod(struct flow_api_backend_s *be, + enum hw_flm_e field, int index, uint32_t *value, + int get) +{ + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_PST_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->flm.v17.pst[index], (uint8_t)*value, + sizeof(struct flm_v17_pst_s)); + break; + case HW_FLM_PST_BP: + get_set(&be->flm.v17.pst[index].bp, value, get); + break; + case HW_FLM_PST_PP: + get_set(&be->flm.v17.pst[index].pp, value, get); + break; + case HW_FLM_PST_TP: + get_set(&be->flm.v17.pst[index].tp, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_flm_pst_set(struct flow_api_backend_s *be, enum hw_flm_e field, + int index, uint32_t value) +{ + return hw_mod_flm_pst_mod(be, field, index, &value, 0); +} + +int hw_mod_flm_pst_get(struct flow_api_backend_s *be, enum hw_flm_e field, + int index, uint32_t *value) +{ + return hw_mod_flm_pst_mod(be, field, index, value, 1); +} + +int hw_mod_flm_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->flm.nb_categories; + if ((unsigned int)(start_idx + count) > be->flm.nb_categories) + return error_index_too_large(__func__); + return be->iface->flm_rcp_flush(be->be_dev, &be->flm, start_idx, count); +} + +static int hw_mod_flm_rcp_mod(struct flow_api_backend_s *be, + enum hw_flm_e field, int index, uint32_t *value, + int get) +{ + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_RCP_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->flm.v17.rcp[index], (uint8_t)*value, + sizeof(struct flm_v17_rcp_s)); + break; + case HW_FLM_RCP_LOOKUP: + get_set(&be->flm.v17.rcp[index].lookup, value, get); + break; + case HW_FLM_RCP_QW0_DYN: + get_set(&be->flm.v17.rcp[index].qw0_dyn, value, get); + break; + case HW_FLM_RCP_QW0_OFS: + get_set(&be->flm.v17.rcp[index].qw0_ofs, value, get); + break; + case HW_FLM_RCP_QW0_SEL: + get_set(&be->flm.v17.rcp[index].qw0_sel, value, get); + break; + case HW_FLM_RCP_QW4_DYN: + get_set(&be->flm.v17.rcp[index].qw4_dyn, value, get); + break; + case HW_FLM_RCP_QW4_OFS: + get_set(&be->flm.v17.rcp[index].qw4_ofs, value, get); + break; + case HW_FLM_RCP_SW8_DYN: + get_set(&be->flm.v17.rcp[index].sw8_dyn, value, get); + break; + case HW_FLM_RCP_SW8_OFS: + get_set(&be->flm.v17.rcp[index].sw8_ofs, value, get); + break; + case HW_FLM_RCP_SW8_SEL: + get_set(&be->flm.v17.rcp[index].sw8_sel, value, get); + break; + case HW_FLM_RCP_SW9_DYN: + get_set(&be->flm.v17.rcp[index].sw9_dyn, value, get); + break; + case HW_FLM_RCP_SW9_OFS: + get_set(&be->flm.v17.rcp[index].sw9_ofs, value, get); + break; + case HW_FLM_RCP_MASK: + if (get) { + memcpy(value, be->flm.v17.rcp[index].mask, + sizeof(((struct flm_v17_rcp_s *)0) + ->mask)); + } else { + memcpy(be->flm.v17.rcp[index].mask, value, + sizeof(((struct flm_v17_rcp_s *)0) + ->mask)); + } + break; + case HW_FLM_RCP_KID: + get_set(&be->flm.v17.rcp[index].kid, value, get); + break; + case HW_FLM_RCP_OPN: + get_set(&be->flm.v17.rcp[index].opn, value, get); + break; + case HW_FLM_RCP_IPN: + get_set(&be->flm.v17.rcp[index].ipn, value, get); + break; + case HW_FLM_RCP_BYT_DYN: + get_set(&be->flm.v17.rcp[index].byt_dyn, value, get); + break; + case HW_FLM_RCP_BYT_OFS: + get_set(&be->flm.v17.rcp[index].byt_ofs, value, get); + break; + case HW_FLM_RCP_TXPLM: + get_set(&be->flm.v17.rcp[index].txplm, value, get); + break; + case HW_FLM_RCP_AUTO_IPV4_MASK: + get_set(&be->flm.v17.rcp[index].auto_ipv4_mask, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_flm_rcp_set_mask(struct flow_api_backend_s *be, enum hw_flm_e field, + int index, uint32_t *value) +{ + if (field != HW_FLM_RCP_MASK) + return error_unsup_ver(__func__, _MOD_, _VER_); + return hw_mod_flm_rcp_mod(be, field, index, value, 0); +} + +int hw_mod_flm_rcp_set(struct flow_api_backend_s *be, enum hw_flm_e field, + int index, uint32_t value) +{ + if (field == HW_FLM_RCP_MASK) + return error_unsup_ver(__func__, _MOD_, _VER_); + return hw_mod_flm_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_flm_rcp_get(struct flow_api_backend_s *be, enum hw_flm_e field, + int index, uint32_t *value) +{ + return hw_mod_flm_rcp_mod(be, field, index, value, 1); +} + +int hw_mod_flm_buf_ctrl_update(struct flow_api_backend_s *be) +{ + return be->iface->flm_buf_ctrl_update(be->be_dev, &be->flm); +} + +static int hw_mod_flm_buf_ctrl_mod_get(struct flow_api_backend_s *be, + enum hw_flm_e field, uint32_t *value) +{ + int get = 1; /* Only get supported */ + + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_BUF_CTRL_LRN_FREE: + get_set(&be->flm.v17.buf_ctrl->lrn_free, value, get); + break; + case HW_FLM_BUF_CTRL_INF_AVAIL: + get_set(&be->flm.v17.buf_ctrl->inf_avail, value, get); + break; + case HW_FLM_BUF_CTRL_STA_AVAIL: + get_set(&be->flm.v17.buf_ctrl->sta_avail, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_flm_buf_ctrl_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value) +{ + return hw_mod_flm_buf_ctrl_mod_get(be, field, value); +} + +int hw_mod_flm_stat_update(struct flow_api_backend_s *be) +{ + return be->iface->flm_stat_update(be->be_dev, &be->flm); +} + +int hw_mod_flm_stat_get(struct flow_api_backend_s *be, enum hw_flm_e field, + uint32_t *value) +{ + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_STAT_LRN_DONE: + *value = be->flm.v17.lrn_done->cnt; + break; + case HW_FLM_STAT_LRN_IGNORE: + *value = be->flm.v17.lrn_ignore->cnt; + break; + case HW_FLM_STAT_LRN_FAIL: + *value = be->flm.v17.lrn_fail->cnt; + break; + case HW_FLM_STAT_UNL_DONE: + *value = be->flm.v17.unl_done->cnt; + break; + case HW_FLM_STAT_UNL_IGNORE: + *value = be->flm.v17.unl_ignore->cnt; + break; + case HW_FLM_STAT_REL_DONE: + *value = be->flm.v17.rel_done->cnt; + break; + case HW_FLM_STAT_REL_IGNORE: + *value = be->flm.v17.rel_ignore->cnt; + break; + case HW_FLM_STAT_PRB_DONE: + *value = be->flm.v17.prb_done->cnt; + break; + case HW_FLM_STAT_PRB_IGNORE: + *value = be->flm.v17.prb_ignore->cnt; + break; + case HW_FLM_STAT_AUL_DONE: + *value = be->flm.v17.aul_done->cnt; + break; + case HW_FLM_STAT_AUL_IGNORE: + *value = be->flm.v17.aul_ignore->cnt; + break; + case HW_FLM_STAT_AUL_FAIL: + *value = be->flm.v17.aul_fail->cnt; + break; + case HW_FLM_STAT_TUL_DONE: + *value = be->flm.v17.tul_done->cnt; + break; + case HW_FLM_STAT_FLOWS: + *value = be->flm.v17.flows->cnt; + break; + + default: { + if (_VER_ < 18) + return error_unsup_field(__func__); + + switch (field) { + case HW_FLM_STAT_STA_DONE: + *value = be->flm.v20.sta_done->cnt; + break; + case HW_FLM_STAT_INF_DONE: + *value = be->flm.v20.inf_done->cnt; + break; + case HW_FLM_STAT_INF_SKIP: + *value = be->flm.v20.inf_skip->cnt; + break; + case HW_FLM_STAT_PCK_HIT: + *value = be->flm.v20.pck_hit->cnt; + break; + case HW_FLM_STAT_PCK_MISS: + *value = be->flm.v20.pck_miss->cnt; + break; + case HW_FLM_STAT_PCK_UNH: + *value = be->flm.v20.pck_unh->cnt; + break; + case HW_FLM_STAT_PCK_DIS: + *value = be->flm.v20.pck_dis->cnt; + break; + case HW_FLM_STAT_CSH_HIT: + *value = be->flm.v20.csh_hit->cnt; + break; + case HW_FLM_STAT_CSH_MISS: + *value = be->flm.v20.csh_miss->cnt; + break; + case HW_FLM_STAT_CSH_UNH: + *value = be->flm.v20.csh_unh->cnt; + break; + case HW_FLM_STAT_CUC_START: + *value = be->flm.v20.cuc_start->cnt; + break; + case HW_FLM_STAT_CUC_MOVE: + *value = be->flm.v20.cuc_move->cnt; + break; + + default: + return error_unsup_field(__func__); + } + } + break; + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_flm_lrn_data_set_flush(struct flow_api_backend_s *be, + enum hw_flm_e field, const uint32_t *value) +{ + int ret = 0; + + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_FLOW_LRN_DATA_V17: + ret = be->iface->flm_lrn_data_flush(be->be_dev, + &be->flm, value, + sizeof(struct flm_v17_lrn_data_s) / + sizeof(uint32_t)); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return ret; +} + +int hw_mod_flm_inf_data_update_get(struct flow_api_backend_s *be, + enum hw_flm_e field, uint32_t *value, + uint32_t word_cnt) +{ + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_FLOW_INF_DATA_V17: + be->iface->flm_inf_data_update(be->be_dev, &be->flm, + value, word_cnt); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_flm_sta_data_update_get(struct flow_api_backend_s *be, + enum hw_flm_e field, uint32_t *value) +{ + switch (_VER_) { + case 17: + case 20: + switch (field) { + case HW_FLM_FLOW_STA_DATA_V17: + be->iface->flm_sta_data_update(be->be_dev, + &be->flm, value, + sizeof(struct flm_v17_sta_data_s) / + sizeof(uint32_t)); + break; + + default: + return error_unsup_field(__func__); + } + break; + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h new file mode 100644 index 0000000000..311e39ba36 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h @@ -0,0 +1,274 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_FLM_V17_H_ +#define _HW_MOD_FLM_V17_H_ + +struct flm_v17_mbr_idx_overlay { + uint64_t a : 28; + uint64_t b : 28; + uint64_t pad : 4; +}; + +#define FLM_V17_MBR_ID1(mbr_id_ptr) \ + (((struct flm_v17_mbr_idx_overlay *)(mbr_id_ptr))->a) +#define FLM_V17_MBR_ID2(mbr_id_ptr) \ + (((struct flm_v17_mbr_idx_overlay *)(mbr_id_ptr))->b) +#define FLM_V17_MBR_ID3(mbr_id_ptr) \ + (((struct flm_v17_mbr_idx_overlay *)((mbr_id_ptr) + 7))->a) +#define FLM_V17_MBR_ID4(mbr_id_ptr) \ + (((struct flm_v17_mbr_idx_overlay *)((mbr_id_ptr) + 7))->b) + +struct flm_v17_control_s { + uint32_t enable; + uint32_t init; + uint32_t lds; + uint32_t lfs; + uint32_t lis; + uint32_t uds; + uint32_t uis; + uint32_t rds; + uint32_t ris; + uint32_t pds; + uint32_t pis; + uint32_t crcwr; + uint32_t crcrd; + uint32_t rbl; + uint32_t eab; + uint32_t split_sdram_usage; +}; + +struct flm_v17_status_s { + uint32_t calibdone; + uint32_t initdone; + uint32_t idle; + uint32_t critical; + uint32_t panic; + uint32_t crcerr; + uint32_t eft_bp; +}; + +struct flm_v17_timeout_s { + uint32_t t; +}; + +struct flm_v17_scrub_s { + uint32_t i; +}; + +struct flm_v17_load_bin_s { + uint32_t bin; +}; + +struct flm_v17_load_pps_s { + uint32_t pps; +}; + +struct flm_v17_load_lps_s { + uint32_t lps; +}; + +struct flm_v17_load_aps_s { + uint32_t aps; +}; + +struct flm_v17_prio_s { + uint32_t limit0; + uint32_t ft0; + uint32_t limit1; + uint32_t ft1; + uint32_t limit2; + uint32_t ft2; + uint32_t limit3; + uint32_t ft3; +}; + +struct flm_v17_pst_s { + uint32_t bp; + uint32_t pp; + uint32_t tp; +}; + +struct flm_v17_rcp_s { + uint32_t lookup; + uint32_t qw0_dyn; + uint32_t qw0_ofs; + uint32_t qw0_sel; + uint32_t qw4_dyn; + uint32_t qw4_ofs; + uint32_t sw8_dyn; + uint32_t sw8_ofs; + uint32_t sw8_sel; + uint32_t sw9_dyn; + uint32_t sw9_ofs; + uint32_t mask[10]; + uint32_t kid; + uint32_t opn; + uint32_t ipn; + uint32_t byt_dyn; + uint32_t byt_ofs; + uint32_t txplm; + uint32_t auto_ipv4_mask; +}; + +struct flm_v17_buf_ctrl_s { + uint32_t lrn_free; + uint32_t inf_avail; + uint32_t sta_avail; +}; + +#pragma pack(1) +struct flm_v17_lrn_data_s { + uint32_t sw9; /* 31:0 (32) */ + uint32_t sw8; /* 63:32 (32) */ + uint32_t qw4[4]; /* 191:64 (128) */ + uint32_t qw0[4]; /* 319:192 (128) */ + uint8_t prot; /* 327:320 (8) */ + uint8_t kid; /* 335:328 (8) */ + uint32_t nat_ip; /* 367:336 (32) */ + uint32_t teid; /* 399:368 (32) */ + uint16_t nat_port; /* 415:400 (16) */ + uint16_t rate; /* 431:416 (16) */ + uint16_t size; /* 447:432 (16) */ + uint32_t color; /* 479:448 (32) */ + uint32_t adj; /* 511:480 (32) */ + uint8_t id[9]; /* 583:512 (72) */ + uint16_t fill : 12; /* 595:584 (12) */ + uint16_t ft : 4; /* 599:596 (4) */ + uint8_t ft_mbr : 4; /* 603:600 (4) */ + uint8_t ft_miss : 4; /* 607:604 (5) */ + + /* 635:608, 663:636, 691:664, 719:692 (4 x 28) Get/set with macros FLM_V17_MBR_IDx */ + uint8_t mbr_idx[14]; + uint32_t vol_idx : 3; /* 722:720 (3) */ + uint32_t stat_prof : 4; /* 726:723 (4) */ + uint32_t prio : 2; /* 728:727 (2) */ + uint32_t ent : 1; /* 729:729 (1) */ + uint32_t op : 4; /* 733:730 (4) */ + uint32_t dscp : 6; /* 739:734 (6) */ + uint32_t qfi : 6; /* 745:740 (6) */ + uint32_t rqi : 1; /* 746:746 (1) */ + uint32_t nat_en : 1; /* 747:747 (1) */ + uint32_t pad0 : 4; /* 751:748 (4) */ + uint16_t pad1 : 15; /* 752:766 (15) */ + uint16_t eor : 1; /* 767:767 (1) */ +}; + +struct flm_v17_inf_data_s { + uint64_t bytes; + uint64_t packets; + uint64_t ts; + uint64_t id0; /* id0 and id1 results in a 72-bit int */ + uint32_t id1 : 8; + uint32_t cause : 3; + uint32_t pad : 20; + uint32_t eor : 1; +}; + +struct flm_v17_sta_data_s { + uint64_t id0; /* id0 and id1 results in a 72-bit int */ + uint32_t id1 : 8; + uint32_t lds : 1; + uint32_t lfs : 1; + uint32_t lis : 1; + uint32_t uds : 1; + uint32_t uis : 1; + uint32_t rds : 1; + uint32_t ris : 1; + uint32_t pds : 1; + uint32_t pis : 1; + uint32_t pad : 14; + uint32_t eor : 1; +}; + +#pragma pack() +struct flm_v17_stat_lrn_done_s { + uint32_t cnt; +}; + +struct flm_v17_stat_lrn_ignore_s { + uint32_t cnt; +}; + +struct flm_v17_stat_lrn_fail_s { + uint32_t cnt; +}; + +struct flm_v17_stat_unl_done_s { + uint32_t cnt; +}; + +struct flm_v17_stat_unl_ignore_s { + uint32_t cnt; +}; + +struct flm_v17_stat_rel_done_s { + uint32_t cnt; +}; + +struct flm_v17_stat_rel_ignore_s { + uint32_t cnt; +}; + +struct flm_v17_stat_aul_done_s { + uint32_t cnt; +}; + +struct flm_v17_stat_aul_ignore_s { + uint32_t cnt; +}; + +struct flm_v17_stat_aul_fail_s { + uint32_t cnt; +}; + +struct flm_v17_stat_tul_done_s { + uint32_t cnt; +}; + +struct flm_v17_stat_flows_s { + uint32_t cnt; +}; + +struct flm_v17_stat_prb_done_s { + uint32_t cnt; +}; + +struct flm_v17_stat_prb_ignore_s { + uint32_t cnt; +}; + +struct hw_mod_flm_v17_s { + struct flm_v17_control_s *control; + struct flm_v17_status_s *status; + struct flm_v17_timeout_s *timeout; + struct flm_v17_scrub_s *scrub; + struct flm_v17_load_bin_s *load_bin; + struct flm_v17_load_pps_s *load_pps; + struct flm_v17_load_lps_s *load_lps; + struct flm_v17_load_aps_s *load_aps; + struct flm_v17_prio_s *prio; + struct flm_v17_pst_s *pst; + struct flm_v17_rcp_s *rcp; + struct flm_v17_buf_ctrl_s *buf_ctrl; + /* lrn_data is not handled by struct */ + /* inf_data is not handled by struct */ + /* sta_data is not handled by struct */ + struct flm_v17_stat_lrn_done_s *lrn_done; + struct flm_v17_stat_lrn_ignore_s *lrn_ignore; + struct flm_v17_stat_lrn_fail_s *lrn_fail; + struct flm_v17_stat_unl_done_s *unl_done; + struct flm_v17_stat_unl_ignore_s *unl_ignore; + struct flm_v17_stat_rel_done_s *rel_done; + struct flm_v17_stat_rel_ignore_s *rel_ignore; + struct flm_v17_stat_aul_done_s *aul_done; + struct flm_v17_stat_aul_ignore_s *aul_ignore; + struct flm_v17_stat_aul_fail_s *aul_fail; + struct flm_v17_stat_tul_done_s *tul_done; + struct flm_v17_stat_flows_s *flows; + struct flm_v17_stat_prb_done_s *prb_done; + struct flm_v17_stat_prb_ignore_s *prb_ignore; +}; + +#endif /* _HW_MOD_FLM_V17_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h new file mode 100644 index 0000000000..e33d4353c3 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_FLM_V20_H_ +#define _HW_MOD_FLM_V20_H_ + +struct flm_v20_stat_sta_done_s { + uint32_t cnt; +}; + +struct flm_v20_stat_inf_done_s { + uint32_t cnt; +}; + +struct flm_v20_stat_inf_skip_s { + uint32_t cnt; +}; + +struct flm_v20_stat_pck_hit_s { + uint32_t cnt; +}; + +struct flm_v20_stat_pck_miss_s { + uint32_t cnt; +}; + +struct flm_v20_stat_pck_unh_s { + uint32_t cnt; +}; + +struct flm_v20_stat_pck_dis_s { + uint32_t cnt; +}; + +struct flm_v20_stat_csh_hit_s { + uint32_t cnt; +}; + +struct flm_v20_stat_csh_miss_s { + uint32_t cnt; +}; + +struct flm_v20_stat_csh_unh_s { + uint32_t cnt; +}; + +struct flm_v20_stat_cuc_start_s { + uint32_t cnt; +}; + +struct flm_v20_stat_cuc_move_s { + uint32_t cnt; +}; + +struct hw_mod_flm_v20_s { + struct flm_v17_control_s *control; + struct flm_v17_status_s *status; + struct flm_v17_timeout_s *timeout; + struct flm_v17_scrub_s *scrub; + struct flm_v17_load_bin_s *load_bin; + struct flm_v17_load_pps_s *load_pps; + struct flm_v17_load_lps_s *load_lps; + struct flm_v17_load_aps_s *load_aps; + struct flm_v17_prio_s *prio; + struct flm_v17_pst_s *pst; + struct flm_v17_rcp_s *rcp; + struct flm_v17_buf_ctrl_s *buf_ctrl; + /* + * lrn_data is not handled by struct + * inf_data is not handled by struct + * sta_data is not handled by struct + */ + struct flm_v17_stat_lrn_done_s *lrn_done; + struct flm_v17_stat_lrn_ignore_s *lrn_ignore; + struct flm_v17_stat_lrn_fail_s *lrn_fail; + struct flm_v17_stat_unl_done_s *unl_done; + struct flm_v17_stat_unl_ignore_s *unl_ignore; + struct flm_v17_stat_rel_done_s *rel_done; + struct flm_v17_stat_rel_ignore_s *rel_ignore; + struct flm_v17_stat_aul_done_s *aul_done; + struct flm_v17_stat_aul_ignore_s *aul_ignore; + struct flm_v17_stat_aul_fail_s *aul_fail; + struct flm_v17_stat_tul_done_s *tul_done; + struct flm_v17_stat_flows_s *flows; + struct flm_v17_stat_prb_done_s *prb_done; + struct flm_v17_stat_prb_ignore_s *prb_ignore; + struct flm_v20_stat_sta_done_s *sta_done; + struct flm_v20_stat_inf_done_s *inf_done; + struct flm_v20_stat_inf_skip_s *inf_skip; + struct flm_v20_stat_pck_hit_s *pck_hit; + struct flm_v20_stat_pck_miss_s *pck_miss; + struct flm_v20_stat_pck_unh_s *pck_unh; + struct flm_v20_stat_pck_dis_s *pck_dis; + struct flm_v20_stat_csh_hit_s *csh_hit; + struct flm_v20_stat_csh_miss_s *csh_miss; + struct flm_v20_stat_csh_unh_s *csh_unh; + struct flm_v20_stat_cuc_start_s *cuc_start; + struct flm_v20_stat_cuc_move_s *cuc_move; +}; + +#endif /* _HW_MOD_FLM_V20_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c new file mode 100644 index 0000000000..1b8896d5c2 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include "flow_api_backend.h" + +#define _MOD_ "HSH" +#define _VER_ be->hsh.ver + +#define HSH_RCP_ENTRIES_V4 16 +#define HSH_RCP_ENTRIES_V5 32 +#define HSH_RCP_MAC_PORT_MASK_SIZE 4 +#define HSH_RCP_WORD_MASK_SIZE 10 + +bool hw_mod_hsh_present(struct flow_api_backend_s *be) +{ + return be->iface->get_hsh_present(be->be_dev); +} + +int hw_mod_hsh_alloc(struct flow_api_backend_s *be) +{ + _VER_ = be->iface->get_hsh_version(be->be_dev); + NT_LOG(DBG, FILTER, "HSH MODULE VERSION %i.%i\n", VER_MAJOR(_VER_), + VER_MINOR(_VER_)); + + switch (_VER_) { + case 5: + be->hsh.nb_rcp = HSH_RCP_ENTRIES_V5; + if (!callocate_mod(CAST_COMMON(&be->hsh), 1, + &be->hsh.v5.rcp, + be->hsh.nb_rcp, + sizeof(struct hsh_v5_rcp_s))) + return -1; + break; + /* end case 5 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + return 0; +} + +void hw_mod_hsh_free(struct flow_api_backend_s *be) +{ + if (be->hsh.base) { + free(be->hsh.base); + be->hsh.base = NULL; + } +} + +int hw_mod_hsh_reset(struct flow_api_backend_s *be) +{ + /* Zero entire cache area */ + ZERO_MOD_CACHE(&be->hsh); + + NT_LOG(DBG, FILTER, "INIT HSH RCP\n"); + return hw_mod_hsh_rcp_flush(be, 0, be->hsh.nb_rcp); +} + +int hw_mod_hsh_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->hsh.nb_rcp; + if ((start_idx + count) > (int)be->hsh.nb_rcp) + return error_index_too_large(__func__); + return be->iface->hsh_rcp_flush(be->be_dev, &be->hsh, start_idx, count); +} + +static int hw_mod_hsh_rcp_mod(struct flow_api_backend_s *be, + enum hw_hsh_e field, uint32_t index, + uint32_t word_off, uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->hsh.nb_rcp) + return error_index_too_large(__func__); + switch (_VER_) { + case 5: + switch (field) { + case HW_HSH_RCP_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->hsh.v5.rcp[index], (uint8_t)*value, + sizeof(struct hsh_v5_rcp_s)); + break; + case HW_HSH_RCP_COMPARE: + rv = do_compare_indexes(be->hsh.v5.rcp, + sizeof(struct hsh_v5_rcp_s), index, word_off, + be->hsh.nb_rcp, get, __func__); + if (rv != 0) + return rv; + break; + case HW_HSH_RCP_FIND: + rv = find_equal_index(be->hsh.v5.rcp, + sizeof(struct hsh_v5_rcp_s), index, word_off, + be->hsh.nb_rcp, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_HSH_RCP_LOAD_DIST_TYPE: + get_set(&be->hsh.v5.rcp[index].load_dist_type, value, get); + break; + case HW_HSH_RCP_MAC_PORT_MASK: + if (word_off > HSH_RCP_MAC_PORT_MASK_SIZE) + return error_word_off_too_large(__func__); + get_set(&be->hsh.v5.rcp[index].mac_port_mask[word_off], + value, get); + break; + case HW_HSH_RCP_SORT: + get_set(&be->hsh.v5.rcp[index].sort, value, get); + break; + case HW_HSH_RCP_QW0_PE: + get_set(&be->hsh.v5.rcp[index].qw0_pe, value, get); + break; + case HW_HSH_RCP_QW0_OFS: + get_set_signed(&be->hsh.v5.rcp[index].qw0_ofs, value, get); + break; + case HW_HSH_RCP_QW4_PE: + get_set(&be->hsh.v5.rcp[index].qw4_pe, value, get); + break; + case HW_HSH_RCP_QW4_OFS: + get_set_signed(&be->hsh.v5.rcp[index].qw4_ofs, value, get); + break; + case HW_HSH_RCP_W8_PE: + get_set(&be->hsh.v5.rcp[index].w8_pe, value, get); + break; + case HW_HSH_RCP_W8_OFS: + get_set_signed(&be->hsh.v5.rcp[index].w8_ofs, value, get); + break; + case HW_HSH_RCP_W8_SORT: + get_set(&be->hsh.v5.rcp[index].w8_sort, value, get); + break; + case HW_HSH_RCP_W9_PE: + get_set(&be->hsh.v5.rcp[index].w9_pe, value, get); + break; + case HW_HSH_RCP_W9_OFS: + get_set_signed(&be->hsh.v5.rcp[index].w9_ofs, value, get); + break; + case HW_HSH_RCP_W9_SORT: + get_set(&be->hsh.v5.rcp[index].w9_sort, value, get); + break; + case HW_HSH_RCP_W9_P: + get_set(&be->hsh.v5.rcp[index].w9_p, value, get); + break; + case HW_HSH_RCP_P_MASK: + get_set(&be->hsh.v5.rcp[index].p_mask, value, get); + break; + case HW_HSH_RCP_WORD_MASK: + if (word_off > HSH_RCP_WORD_MASK_SIZE) + return error_word_off_too_large(__func__); + get_set(&be->hsh.v5.rcp[index].word_mask[word_off], + value, get); + break; + case HW_HSH_RCP_SEED: + get_set(&be->hsh.v5.rcp[index].seed, value, get); + break; + case HW_HSH_RCP_TNL_P: + get_set(&be->hsh.v5.rcp[index].tnl_p, value, get); + break; + case HW_HSH_RCP_HSH_VALID: + get_set(&be->hsh.v5.rcp[index].hsh_valid, value, get); + break; + case HW_HSH_RCP_HSH_TYPE: + get_set(&be->hsh.v5.rcp[index].hsh_type, value, get); + break; + case HW_HSH_RCP_AUTO_IPV4_MASK: + get_set(&be->hsh.v5.rcp[index].auto_ipv4_mask, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 5 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_hsh_rcp_set(struct flow_api_backend_s *be, enum hw_hsh_e field, + uint32_t index, uint32_t word_off, uint32_t value) +{ + return hw_mod_hsh_rcp_mod(be, field, index, word_off, &value, 0); +} + +int hw_mod_hsh_rcp_get(struct flow_api_backend_s *be, enum hw_hsh_e field, + uint32_t index, uint32_t word_off, uint32_t *value) +{ + return hw_mod_hsh_rcp_mod(be, field, index, word_off, value, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h new file mode 100644 index 0000000000..8588750ff0 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_HSH_V5_H_ +#define _HW_MOD_HSH_V5_H_ + +struct hsh_v5_rcp_s { + uint32_t load_dist_type; + uint32_t mac_port_mask[4]; + uint32_t sort; + uint32_t qw0_pe; + int32_t qw0_ofs; + uint32_t qw4_pe; + int32_t qw4_ofs; + uint32_t w8_pe; + int32_t w8_ofs; + uint32_t w8_sort; + uint32_t w9_pe; + int32_t w9_ofs; + uint32_t w9_sort; + uint32_t w9_p; + uint32_t p_mask; + uint32_t word_mask[10]; + uint32_t seed; + uint32_t tnl_p; + uint32_t hsh_valid; + uint32_t hsh_type; + uint32_t auto_ipv4_mask; +}; + +struct hw_mod_hsh_v5_s { + struct hsh_v5_rcp_s *rcp; +}; + +#endif /* _HW_MOD_HSH_V5_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c new file mode 100644 index 0000000000..751c7b3ffe --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include "flow_api_backend.h" + +#define _MOD_ "HST" +#define _VER_ be->hst.ver + +bool hw_mod_hst_present(struct flow_api_backend_s *be) +{ + return be->iface->get_hst_present(be->be_dev); +} + +int hw_mod_hst_alloc(struct flow_api_backend_s *be) +{ + int nb; + + _VER_ = be->iface->get_hst_version(be->be_dev); + NT_LOG(DBG, FILTER, "HST MODULE VERSION %i.%i\n", VER_MAJOR(_VER_), + VER_MINOR(_VER_)); + + nb = be->iface->get_nb_hst_categories(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "hst_categories", _MOD_, _VER_); + be->hst.nb_hst_rcp_categories = (uint32_t)nb; + + switch (_VER_) { + case 2: + if (!callocate_mod(CAST_COMMON(&be->hst), 1, + &be->hst.v2.rcp, + be->hst.nb_hst_rcp_categories, + sizeof(struct hst_v2_rcp_s))) + return -1; + break; + /* end case 2 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +void hw_mod_hst_free(struct flow_api_backend_s *be) +{ + if (be->hst.base) { + free(be->hst.base); + be->hst.base = NULL; + } +} + +int hw_mod_hst_reset(struct flow_api_backend_s *be) +{ + /* Zero entire cache area */ + ZERO_MOD_CACHE(&be->hst); + + NT_LOG(DBG, FILTER, "INIT HST RCP\n"); + return hw_mod_hst_rcp_flush(be, 0, ALL_ENTRIES); +} + +int hw_mod_hst_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->hst.nb_hst_rcp_categories; + if ((unsigned int)(start_idx + count) > be->hst.nb_hst_rcp_categories) + return error_index_too_large(__func__); + return be->iface->hst_rcp_flush(be->be_dev, &be->hst, start_idx, count); +} + +static int hw_mod_hst_rcp_mod(struct flow_api_backend_s *be, + enum hw_hst_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->hst.nb_hst_rcp_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 2: + switch (field) { + case HW_HST_RCP_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->hst.v2.rcp[index], (uint8_t)*value, + sizeof(struct hst_v2_rcp_s)); + break; + case HW_HST_RCP_FIND: + find_equal_index(be->hst.v2.rcp, + sizeof(struct hst_v2_rcp_s), index, *value, + be->hst.nb_hst_rcp_categories, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_HST_RCP_COMPARE: + rv = do_compare_indexes(be->hst.v2.rcp, + sizeof(struct hst_v2_rcp_s), index, *value, + be->hst.nb_hst_rcp_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_HST_RCP_STRIP_MODE: + get_set(&be->hst.v2.rcp[index].strip_mode, value, get); + break; + case HW_HST_RCP_START_DYN: + get_set(&be->hst.v2.rcp[index].start_dyn, value, get); + break; + case HW_HST_RCP_START_OFS: + get_set(&be->hst.v2.rcp[index].start_ofs, value, get); + break; + case HW_HST_RCP_END_DYN: + get_set(&be->hst.v2.rcp[index].end_dyn, value, get); + break; + case HW_HST_RCP_END_OFS: + get_set(&be->hst.v2.rcp[index].end_ofs, value, get); + break; + case HW_HST_RCP_MODIF0_CMD: + get_set(&be->hst.v2.rcp[index].modif0_cmd, value, get); + break; + case HW_HST_RCP_MODIF0_DYN: + get_set(&be->hst.v2.rcp[index].modif0_dyn, value, get); + break; + case HW_HST_RCP_MODIF0_OFS: + get_set(&be->hst.v2.rcp[index].modif0_ofs, value, get); + break; + case HW_HST_RCP_MODIF0_VALUE: + get_set(&be->hst.v2.rcp[index].modif0_value, value, get); + break; + case HW_HST_RCP_MODIF1_CMD: + get_set(&be->hst.v2.rcp[index].modif1_cmd, value, get); + break; + case HW_HST_RCP_MODIF1_DYN: + get_set(&be->hst.v2.rcp[index].modif1_dyn, value, get); + break; + case HW_HST_RCP_MODIF1_OFS: + get_set(&be->hst.v2.rcp[index].modif1_ofs, value, get); + break; + case HW_HST_RCP_MODIF1_VALUE: + get_set(&be->hst.v2.rcp[index].modif1_value, value, get); + break; + case HW_HST_RCP_MODIF2_CMD: + get_set(&be->hst.v2.rcp[index].modif2_cmd, value, get); + break; + case HW_HST_RCP_MODIF2_DYN: + get_set(&be->hst.v2.rcp[index].modif2_dyn, value, get); + break; + case HW_HST_RCP_MODIF2_OFS: + get_set(&be->hst.v2.rcp[index].modif2_ofs, value, get); + break; + case HW_HST_RCP_MODIF2_VALUE: + get_set(&be->hst.v2.rcp[index].modif2_value, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 2 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_hst_rcp_set(struct flow_api_backend_s *be, enum hw_hst_e field, + int index, uint32_t value) +{ + return hw_mod_hst_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_hst_rcp_get(struct flow_api_backend_s *be, enum hw_hst_e field, + int index, uint32_t *value) +{ + return hw_mod_hst_rcp_mod(be, field, index, value, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h new file mode 100644 index 0000000000..230c70b56d --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_HST_V2_H_ +#define _HW_MOD_HST_V2_H_ + +struct hst_v2_rcp_s { + uint32_t strip_mode; + uint32_t start_dyn; + uint32_t start_ofs; + uint32_t end_dyn; + uint32_t end_ofs; + uint32_t modif0_cmd; + uint32_t modif0_dyn; + uint32_t modif0_ofs; + uint32_t modif0_value; + uint32_t modif1_cmd; + uint32_t modif1_dyn; + uint32_t modif1_ofs; + uint32_t modif1_value; + uint32_t modif2_cmd; + uint32_t modif2_dyn; + uint32_t modif2_ofs; + uint32_t modif2_value; +}; + +struct hw_mod_hst_v2_s { + struct hst_v2_rcp_s *rcp; +}; + +#endif /* _HW_MOD_HST_V2_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c new file mode 100644 index 0000000000..c8e3593637 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c @@ -0,0 +1,271 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include "flow_api_backend.h" + +#define _MOD_ "IOA" +#define _VER_ be->ioa.ver + +bool hw_mod_ioa_present(struct flow_api_backend_s *be) +{ + return be->iface->get_ioa_present(be->be_dev); +} + +int hw_mod_ioa_alloc(struct flow_api_backend_s *be) +{ + _VER_ = be->iface->get_ioa_version(be->be_dev); + NT_LOG(DBG, FILTER, "IOA MODULE VERSION %i.%i\n", VER_MAJOR(_VER_), + VER_MINOR(_VER_)); + + int nb = be->iface->get_nb_ioa_categories(be->be_dev); + + if (nb <= 0) + return error_resource_count(__func__, "ioa_categories", _MOD_, _VER_); + be->ioa.nb_rcp_categories = (uint32_t)nb; + + /* NOTE: ROA number of categories are called here. FPGA uses a cross-indexing here - bad! */ + nb = be->iface->get_nb_roa_categories(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "roa_epp_entries", _MOD_, _VER_); + be->ioa.nb_roa_epp_entries = (uint32_t)nb; + + switch (_VER_) { + case 4: + if (!callocate_mod(CAST_COMMON(&be->ioa), 3, + &be->ioa.v4.rcp, be->ioa.nb_rcp_categories, + sizeof(struct ioa_v4_rcp_s), + &be->ioa.v4.tpid, 1, + sizeof(struct ioa_v4_special_tpid_s), + &be->ioa.v4.roa_epp, be->ioa.nb_roa_epp_entries, + sizeof(struct ioa_v4_roa_epp_s))) + return -1; + break; + /* end case 4 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + return 0; +} + +void hw_mod_ioa_free(struct flow_api_backend_s *be) +{ + if (be->ioa.base) { + free(be->ioa.base); + be->ioa.base = NULL; + } +} + +int hw_mod_ioa_reset(struct flow_api_backend_s *be) +{ + /* Zero entire cache area */ + ZERO_MOD_CACHE(&be->ioa); + + NT_LOG(DBG, FILTER, "INIT IOA RCP\n"); + hw_mod_ioa_rcp_flush(be, 0, ALL_ENTRIES); + NT_LOG(DBG, FILTER, "INIT IOA SPECIAL TPID\n"); + hw_mod_ioa_config_set(be, HW_IOA_CONFIG_CUST_TPID_0, 0x8200); + hw_mod_ioa_config_set(be, HW_IOA_CONFIG_CUST_TPID_1, 0x8300); + hw_mod_ioa_config_flush(be); + NT_LOG(DBG, FILTER, "INIT IOA ROA EPP\n"); + hw_mod_ioa_roa_epp_flush(be, 0, ALL_ENTRIES); + return 0; +} + +int hw_mod_ioa_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->ioa.nb_rcp_categories; + if ((unsigned int)(start_idx + count) > be->ioa.nb_rcp_categories) + return error_index_too_large(__func__); + return be->iface->ioa_rcp_flush(be->be_dev, &be->ioa, start_idx, count); +} + +static int hw_mod_ioa_rcp_mod(struct flow_api_backend_s *be, + enum hw_ioa_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->ioa.nb_rcp_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 4: + switch (field) { + case HW_IOA_RCP_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->ioa.v4.rcp[index], (uint8_t)*value, + sizeof(struct ioa_v4_rcp_s)); + break; + case HW_IOA_RCP_FIND: + rv = find_equal_index(be->ioa.v4.rcp, + sizeof(struct ioa_v4_rcp_s), index, *value, + be->ioa.nb_rcp_categories, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_IOA_RCP_COMPARE: + rv = do_compare_indexes(be->ioa.v4.rcp, + sizeof(struct ioa_v4_rcp_s), index, *value, + be->ioa.nb_rcp_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_IOA_RCP_TUNNEL_POP: + get_set(&be->ioa.v4.rcp[index].tunnel_pop, value, get); + break; + case HW_IOA_RCP_VLAN_POP: + get_set(&be->ioa.v4.rcp[index].vlan_pop, value, get); + break; + case HW_IOA_RCP_VLAN_PUSH: + get_set(&be->ioa.v4.rcp[index].vlan_push, value, get); + break; + case HW_IOA_RCP_VLAN_VID: + get_set(&be->ioa.v4.rcp[index].vlan_vid, value, get); + break; + case HW_IOA_RCP_VLAN_DEI: + get_set(&be->ioa.v4.rcp[index].vlan_dei, value, get); + break; + case HW_IOA_RCP_VLAN_PCP: + get_set(&be->ioa.v4.rcp[index].vlan_pcp, value, get); + break; + case HW_IOA_RCP_VLAN_TPID_SEL: + get_set(&be->ioa.v4.rcp[index].vlan_tpid_sel, value, get); + break; + case HW_IOA_RCP_QUEUE_OVERRIDE_EN: + get_set(&be->ioa.v4.rcp[index].queue_override_en, value, get); + break; + case HW_IOA_RCP_QUEUE_ID: + get_set(&be->ioa.v4.rcp[index].queue_id, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 4 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_ioa_rcp_set(struct flow_api_backend_s *be, enum hw_ioa_e field, + uint32_t index, uint32_t value) +{ + return hw_mod_ioa_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_ioa_rcp_get(struct flow_api_backend_s *be, enum hw_ioa_e field, + uint32_t index, uint32_t *value) +{ + return hw_mod_ioa_rcp_mod(be, field, index, value, 1); +} + +int hw_mod_ioa_config_flush(struct flow_api_backend_s *be) +{ + return be->iface->ioa_special_tpid_flush(be->be_dev, &be->ioa); +} + +int hw_mod_ioa_config_set(struct flow_api_backend_s *be, enum hw_ioa_e field, + uint32_t value) +{ + switch (_VER_) { + case 4: + switch (field) { + case HW_IOA_CONFIG_CUST_TPID_0: + be->ioa.v4.tpid->cust_tpid_0 = value; + break; + case HW_IOA_CONFIG_CUST_TPID_1: + be->ioa.v4.tpid->cust_tpid_1 = value; + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 4 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_ioa_roa_epp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->ioa.nb_roa_epp_entries; + if ((unsigned int)(start_idx + count) > be->ioa.nb_roa_epp_entries) + return error_index_too_large(__func__); + return be->iface->ioa_roa_epp_flush(be->be_dev, &be->ioa, start_idx, + count); +} + +static int hw_mod_ioa_roa_epp_mod(struct flow_api_backend_s *be, + enum hw_ioa_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->ioa.nb_roa_epp_entries) + return error_index_too_large(__func__); + switch (_VER_) { + case 4: + switch (field) { + case HW_IOA_ROA_EPP_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->ioa.v4.roa_epp[index], (uint8_t)*value, + sizeof(struct ioa_v4_roa_epp_s)); + break; + case HW_IOA_ROA_EPP_FIND: + rv = find_equal_index(be->ioa.v4.roa_epp, + sizeof(struct ioa_v4_roa_epp_s), index, *value, + be->ioa.nb_roa_epp_entries, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_IOA_ROA_EPP_COMPARE: + rv = do_compare_indexes(be->ioa.v4.roa_epp, + sizeof(struct ioa_v4_roa_epp_s), index, *value, + be->ioa.nb_roa_epp_entries, get, __func__); + if (rv != 0) + return rv; + break; + case HW_IOA_ROA_EPP_PUSH_TUNNEL: + get_set(&be->ioa.v4.roa_epp[index].push_tunnel, value, get); + break; + case HW_IOA_ROA_EPP_TX_PORT: + get_set(&be->ioa.v4.roa_epp[index].tx_port, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 4 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_ioa_roa_epp_set(struct flow_api_backend_s *be, enum hw_ioa_e field, + uint32_t index, uint32_t value) +{ + return hw_mod_ioa_roa_epp_mod(be, field, index, &value, 0); +} + +int hw_mod_ioa_roa_epp_get(struct flow_api_backend_s *be, enum hw_ioa_e field, + uint32_t index, uint32_t *value) +{ + return hw_mod_ioa_roa_epp_mod(be, field, index, value, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h new file mode 100644 index 0000000000..309b53ff76 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_IOA_V4_H_ +#define _HW_MOD_IOA_V4_H_ + +struct ioa_v4_rcp_s { + uint32_t tunnel_pop; + uint32_t vlan_pop; + uint32_t vlan_push; + uint32_t vlan_vid; + uint32_t vlan_dei; + uint32_t vlan_pcp; + uint32_t vlan_tpid_sel; + uint32_t queue_override_en; + uint32_t queue_id; +}; + +struct ioa_v4_special_tpid_s { + uint32_t cust_tpid_0; + uint32_t cust_tpid_1; +}; + +struct ioa_v4_roa_epp_s { + uint32_t push_tunnel; + uint32_t tx_port; +}; + +struct hw_mod_ioa_v4_s { + struct ioa_v4_rcp_s *rcp; + struct ioa_v4_special_tpid_s *tpid; + struct ioa_v4_roa_epp_s *roa_epp; +}; + +#endif /* _HW_MOD_IOA_V4_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c new file mode 100644 index 0000000000..a91f0e0a7d --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c @@ -0,0 +1,629 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include "flow_api_backend.h" + +#define _MOD_ "KM" +#define _VER_ be->km.ver + +#define KM_TCQ_ENTRIES 2048 +#define KM_RCP_MASK_A_SIZE 11 +#define KM_RCP_MASK_D_A_SIZE \ + 12 /* Mask for double size word extractors for DW8/DW10 */ +#define KM_RCP_MASK_B_SIZE 6 + +bool hw_mod_km_present(struct flow_api_backend_s *be) +{ + return be->iface->get_km_present(be->be_dev); +} + +int hw_mod_km_alloc(struct flow_api_backend_s *be) +{ + int nb; + + _VER_ = be->iface->get_km_version(be->be_dev); + NT_LOG(DBG, FILTER, "KM MODULE VERSION %i.%i\n", VER_MAJOR(_VER_), + VER_MINOR(_VER_)); + + nb = be->iface->get_nb_km_categories(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "km_categories", _MOD_, _VER_); + be->km.nb_categories = (uint32_t)nb; + + nb = be->iface->get_nb_km_cam_banks(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "cam_banks", _MOD_, _VER_); + be->km.nb_cam_banks = (uint32_t)nb; + + nb = be->iface->get_nb_km_cam_records(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "cam_records", _MOD_, _VER_); + be->km.nb_cam_records = (uint32_t)nb; + + nb = be->iface->get_nb_km_cam_record_words(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "cam_record_words", _MOD_, _VER_); + be->km.nb_cam_record_words = (uint32_t)nb; + + nb = be->iface->get_nb_km_tcam_banks(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "tcam_banks", _MOD_, _VER_); + be->km.nb_tcam_banks = (uint32_t)nb; + + nb = be->iface->get_nb_km_tcam_bank_width(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "tcam_bank_width", _MOD_, _VER_); + be->km.nb_tcam_bank_width = (uint32_t)nb; + + switch (_VER_) { + case 7: + be->km.nb_km_rcp_mask_a_word_size = 12; + be->km.nb_km_rcp_mask_b_word_size = 6; + if (!callocate_mod(CAST_COMMON(&be->km), 5, + &be->km.v7.rcp, + be->km.nb_categories, + sizeof(struct km_v7_rcp_s), + &be->km.v7.cam, + be->km.nb_cam_banks * be->km.nb_cam_records, + sizeof(struct km_v7_cam_s), + &be->km.v7.tcam, + be->km.nb_tcam_banks * 4 * 256, + sizeof(struct km_v7_tcam_s), + &be->km.v7.tci, + be->km.nb_tcam_banks * be->km.nb_tcam_bank_width, + sizeof(struct km_v7_tci_s), + &be->km.v7.tcq, + KM_TCQ_ENTRIES, + sizeof(struct km_v7_tcq_s))) + return -1; + break; + /* end case 7 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +void hw_mod_km_free(struct flow_api_backend_s *be) +{ + if (be->km.base) { + free(be->km.base); + be->km.base = NULL; + } +} + +int hw_mod_km_reset(struct flow_api_backend_s *be) +{ + uint32_t tcam_v_set[3] = { 0x00000000, 0x00000000, 0x00000000 }; + /* int err = 0; */ + + /* Zero entire cache area */ + ZERO_MOD_CACHE(&be->km); + + NT_LOG(DBG, FILTER, "INIT KM RCP\n"); + hw_mod_km_rcp_flush(be, 0, ALL_ENTRIES); + + /* init CAM - all zero */ + NT_LOG(DBG, FILTER, "INIT KM CAM\n"); + hw_mod_km_cam_flush(be, 0, 0, ALL_ENTRIES); + + /* init TCAM - all zero */ + NT_LOG(DBG, FILTER, "INIT KM TCAM\n"); + for (unsigned int i = 0; i < be->km.nb_tcam_banks; i++) { + /* + * TCAM entries are cache controlled, thus need to hard reset initially to sync + * cache with HW + */ + hw_mod_km_tcam_set(be, HW_KM_TCAM_BANK_RESET, i, 0, 0, + tcam_v_set); + } + hw_mod_km_tcam_flush(be, 0, ALL_ENTRIES); + + /* init TCI - all zero */ + NT_LOG(DBG, FILTER, "INIT KM TCI\n"); + hw_mod_km_tci_flush(be, 0, 0, ALL_ENTRIES); + + NT_LOG(DBG, FILTER, "INIT KM TCQ\n"); + for (unsigned int i = 0; i < be->km.nb_tcam_bank_width; i++) + hw_mod_km_tcq_flush(be, 0, i, be->km.nb_tcam_banks); + + return 0; +} + +int hw_mod_km_rcp_flush(struct flow_api_backend_s *be, int start_idx, int count) +{ + if (count == ALL_ENTRIES) + count = be->km.nb_categories; + if ((unsigned int)(start_idx + count) > be->km.nb_categories) + return error_index_too_large(__func__); + return be->iface->km_rcp_flush(be->be_dev, &be->km, start_idx, count); +} + +static int hw_mod_km_rcp_mod(struct flow_api_backend_s *be, enum hw_km_e field, + int index, int word_off, uint32_t *value, int get) +{ + if ((unsigned int)index >= be->km.nb_categories) + return error_index_too_large(__func__); + + switch (_VER_) { + case 7: + switch (field) { + case HW_KM_RCP_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->km.v7.rcp[index], (uint8_t)*value, + sizeof(struct km_v7_rcp_s)); + break; + case HW_KM_RCP_QW0_DYN: + get_set(&be->km.v7.rcp[index].qw0_dyn, value, get); + break; + case HW_KM_RCP_QW0_OFS: + get_set_signed(&be->km.v7.rcp[index].qw0_ofs, value, get); + break; + case HW_KM_RCP_QW0_SEL_A: + get_set(&be->km.v7.rcp[index].qw0_sel_a, value, get); + break; + case HW_KM_RCP_QW0_SEL_B: + get_set(&be->km.v7.rcp[index].qw0_sel_b, value, get); + break; + case HW_KM_RCP_QW4_DYN: + get_set(&be->km.v7.rcp[index].qw4_dyn, value, get); + break; + case HW_KM_RCP_QW4_OFS: + get_set_signed(&be->km.v7.rcp[index].qw4_ofs, value, get); + break; + case HW_KM_RCP_QW4_SEL_A: + get_set(&be->km.v7.rcp[index].qw4_sel_a, value, get); + break; + case HW_KM_RCP_QW4_SEL_B: + get_set(&be->km.v7.rcp[index].qw4_sel_b, value, get); + break; + case HW_KM_RCP_DW8_DYN: + get_set(&be->km.v7.rcp[index].dw8_dyn, value, get); + break; + case HW_KM_RCP_DW8_OFS: + get_set_signed(&be->km.v7.rcp[index].dw8_ofs, value, get); + break; + case HW_KM_RCP_DW8_SEL_A: + get_set(&be->km.v7.rcp[index].dw8_sel_a, value, get); + break; + case HW_KM_RCP_DW8_SEL_B: + get_set(&be->km.v7.rcp[index].dw8_sel_b, value, get); + break; + case HW_KM_RCP_DW10_DYN: + get_set(&be->km.v7.rcp[index].dw10_dyn, value, get); + break; + case HW_KM_RCP_DW10_OFS: + get_set_signed(&be->km.v7.rcp[index].dw10_ofs, value, get); + break; + case HW_KM_RCP_DW10_SEL_A: + get_set(&be->km.v7.rcp[index].dw10_sel_a, value, get); + break; + case HW_KM_RCP_DW10_SEL_B: + get_set(&be->km.v7.rcp[index].dw10_sel_b, value, get); + break; + case HW_KM_RCP_SWX_CCH: + get_set(&be->km.v7.rcp[index].swx_cch, value, get); + break; + case HW_KM_RCP_SWX_SEL_A: + get_set(&be->km.v7.rcp[index].swx_sel_a, value, get); + break; + case HW_KM_RCP_SWX_SEL_B: + get_set(&be->km.v7.rcp[index].swx_sel_b, value, get); + break; + case HW_KM_RCP_MASK_A: + if (word_off > KM_RCP_MASK_D_A_SIZE) + return error_word_off_too_large(__func__); + get_set(&be->km.v7.rcp[index].mask_d_a[word_off], value, get); + break; + case HW_KM_RCP_MASK_B: + if (word_off > KM_RCP_MASK_B_SIZE) + return error_word_off_too_large(__func__); + get_set(&be->km.v7.rcp[index].mask_b[word_off], value, get); + break; + case HW_KM_RCP_DUAL: + get_set(&be->km.v7.rcp[index].dual, value, get); + break; + case HW_KM_RCP_PAIRED: + get_set(&be->km.v7.rcp[index].paired, value, get); + break; + case HW_KM_RCP_EL_A: + get_set(&be->km.v7.rcp[index].el_a, value, get); + break; + case HW_KM_RCP_EL_B: + get_set(&be->km.v7.rcp[index].el_b, value, get); + break; + case HW_KM_RCP_INFO_A: + get_set(&be->km.v7.rcp[index].info_a, value, get); + break; + case HW_KM_RCP_INFO_B: + get_set(&be->km.v7.rcp[index].info_b, value, get); + break; + case HW_KM_RCP_FTM_A: + get_set(&be->km.v7.rcp[index].ftm_a, value, get); + break; + case HW_KM_RCP_FTM_B: + get_set(&be->km.v7.rcp[index].ftm_b, value, get); + break; + case HW_KM_RCP_BANK_A: + get_set(&be->km.v7.rcp[index].bank_a, value, get); + break; + case HW_KM_RCP_BANK_B: + get_set(&be->km.v7.rcp[index].bank_b, value, get); + break; + case HW_KM_RCP_KL_A: + get_set(&be->km.v7.rcp[index].kl_a, value, get); + break; + case HW_KM_RCP_KL_B: + get_set(&be->km.v7.rcp[index].kl_b, value, get); + break; + case HW_KM_RCP_KEYWAY_A: + get_set(&be->km.v7.rcp[index].keyway_a, value, get); + break; + case HW_KM_RCP_KEYWAY_B: + get_set(&be->km.v7.rcp[index].keyway_b, value, get); + break; + case HW_KM_RCP_SYNERGY_MODE: + get_set(&be->km.v7.rcp[index].synergy_mode, value, get); + break; + case HW_KM_RCP_DW0_B_DYN: + get_set(&be->km.v7.rcp[index].dw0_b_dyn, value, get); + break; + case HW_KM_RCP_DW0_B_OFS: + get_set_signed(&be->km.v7.rcp[index].dw0_b_ofs, value, get); + break; + case HW_KM_RCP_DW2_B_DYN: + get_set(&be->km.v7.rcp[index].dw2_b_dyn, value, get); + break; + case HW_KM_RCP_DW2_B_OFS: + get_set_signed(&be->km.v7.rcp[index].dw2_b_ofs, value, get); + break; + case HW_KM_RCP_SW4_B_DYN: + get_set(&be->km.v7.rcp[index].sw4_b_dyn, value, get); + break; + case HW_KM_RCP_SW4_B_OFS: + get_set_signed(&be->km.v7.rcp[index].sw4_b_ofs, value, get); + break; + case HW_KM_RCP_SW5_B_DYN: + get_set(&be->km.v7.rcp[index].sw5_b_dyn, value, get); + break; + case HW_KM_RCP_SW5_B_OFS: + get_set_signed(&be->km.v7.rcp[index].sw5_b_ofs, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 7 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_km_rcp_set(struct flow_api_backend_s *be, enum hw_km_e field, + int index, int word_off, uint32_t value) +{ + return hw_mod_km_rcp_mod(be, field, index, word_off, &value, 0); +} + +int hw_mod_km_rcp_get(struct flow_api_backend_s *be, enum hw_km_e field, + int index, int word_off, uint32_t *value) +{ + return hw_mod_km_rcp_mod(be, field, index, word_off, value, 1); +} + +int hw_mod_km_cam_flush(struct flow_api_backend_s *be, int start_bank, + int start_record, int count) +{ + if (count == ALL_ENTRIES) + count = be->km.nb_cam_records * be->km.nb_cam_banks; + + unsigned int end = + start_bank * be->km.nb_cam_records + start_record + count; + if (end > (be->km.nb_cam_banks * be->km.nb_cam_records)) + return error_index_too_large(__func__); + + return be->iface->km_cam_flush(be->be_dev, &be->km, start_bank, + start_record, count); +} + +static int hw_mod_km_cam_mod(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t *value, int get) +{ + if ((unsigned int)bank >= be->km.nb_cam_banks) + return error_index_too_large(__func__); + if ((unsigned int)record >= be->km.nb_cam_records) + return error_index_too_large(__func__); + + unsigned int index = bank * be->km.nb_cam_records + record; + + switch (_VER_) { + case 7: + switch (field) { + case HW_KM_CAM_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->km.v7.cam[index], (uint8_t)*value, + sizeof(struct km_v7_cam_s)); + break; + case HW_KM_CAM_W0: + get_set(&be->km.v7.cam[index].w0, value, get); + break; + case HW_KM_CAM_W1: + get_set(&be->km.v7.cam[index].w1, value, get); + break; + case HW_KM_CAM_W2: + get_set(&be->km.v7.cam[index].w2, value, get); + break; + case HW_KM_CAM_W3: + get_set(&be->km.v7.cam[index].w3, value, get); + break; + case HW_KM_CAM_W4: + get_set(&be->km.v7.cam[index].w4, value, get); + break; + case HW_KM_CAM_W5: + get_set(&be->km.v7.cam[index].w5, value, get); + break; + case HW_KM_CAM_FT0: + get_set(&be->km.v7.cam[index].ft0, value, get); + break; + case HW_KM_CAM_FT1: + get_set(&be->km.v7.cam[index].ft1, value, get); + break; + case HW_KM_CAM_FT2: + get_set(&be->km.v7.cam[index].ft2, value, get); + break; + case HW_KM_CAM_FT3: + get_set(&be->km.v7.cam[index].ft3, value, get); + break; + case HW_KM_CAM_FT4: + get_set(&be->km.v7.cam[index].ft4, value, get); + break; + case HW_KM_CAM_FT5: + get_set(&be->km.v7.cam[index].ft5, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 7 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + return 0; +} + +int hw_mod_km_cam_set(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t value) +{ + return hw_mod_km_cam_mod(be, field, bank, record, &value, 0); +} + +int hw_mod_km_cam_get(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t *value) +{ + return hw_mod_km_cam_mod(be, field, bank, record, value, 1); +} + +int hw_mod_km_tcam_flush(struct flow_api_backend_s *be, int start_bank, + int count) +{ + if (count == ALL_ENTRIES) + count = be->km.nb_tcam_banks * 4 * 256; + else if (count == ALL_BANK_ENTRIES) + count = 4 * 256; + + unsigned int end = start_bank * 4 * 256 + count; + + if (end > (be->km.nb_tcam_banks * 4 * 256)) + return error_index_too_large(__func__); + + return be->iface->km_tcam_flush(be->be_dev, &be->km, start_bank, 0, 0, + count); +} + +static int hw_mod_km_tcam_mod(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int byte, int byte_val, + uint32_t *value_set, int get) +{ + unsigned int start_index = bank * 4 * 256 + (int)byte * 256 + byte_val; + + if (start_index >= (be->km.nb_tcam_banks * 4 * 256)) + return error_index_too_large(__func__); + + switch (_VER_) { + case 7: + switch (field) { + case HW_KM_TCAM_BANK_RESET: + if (get) + return error_unsup_field(__func__); + { + int start_idx = bank * 4 * 256; + + for (int i = 0; i < 4 * 256; i++) { + be->km.v7.tcam[start_idx + i].t[0] = + value_set[0]; + be->km.v7.tcam[start_idx + i].t[1] = + value_set[1]; + be->km.v7.tcam[start_idx + i].t[2] = + value_set[2]; + be->km.v7.tcam[start_idx + i].dirty = 1; + } + } + break; + case HW_KM_TCAM_T: { + int index = bank * 4 * 256 + byte * 256 + byte_val; + + if (get) { + value_set[0] = be->km.v7.tcam[index].t[0]; + value_set[1] = be->km.v7.tcam[index].t[1]; + value_set[2] = be->km.v7.tcam[index].t[2]; + } else { + /* only change if any bits has to be changed */ + if (be->km.v7.tcam[index].t[0] != + value_set[0] || + be->km.v7.tcam[index].t[1] != + value_set[1] || + be->km.v7.tcam[index].t[2] != + value_set[2]) { + be->km.v7.tcam[index].t[0] = + value_set[0]; + be->km.v7.tcam[index].t[1] = + value_set[1]; + be->km.v7.tcam[index].t[2] = + value_set[2]; + be->km.v7.tcam[index].dirty = 1; + } + } + } + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 7 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + return 0; +} + +int hw_mod_km_tcam_set(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int byte, int byte_val, uint32_t *value_set) +{ + return hw_mod_km_tcam_mod(be, field, bank, byte, byte_val, value_set, + 0); +} + +int hw_mod_km_tcam_get(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int byte, int byte_val, uint32_t *value_set) +{ + return hw_mod_km_tcam_mod(be, field, bank, byte, byte_val, value_set, + 1); +} + +int hw_mod_km_tci_flush(struct flow_api_backend_s *be, int start_bank, + int start_record, int count) +{ + if (count == ALL_ENTRIES) + count = be->km.nb_tcam_banks * be->km.nb_tcam_bank_width; + + unsigned int end = (int)start_bank * be->km.nb_tcam_bank_width + + start_record + count; + + if (end > (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width)) + return error_index_too_large(__func__); + + return be->iface->km_tci_flush(be->be_dev, &be->km, start_bank, + start_record, count); +} + +static int hw_mod_km_tci_mod(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t *value, int get) +{ + unsigned int index = bank * be->km.nb_tcam_bank_width + record; + + if (index >= (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width)) + return error_index_too_large(__func__); + + switch (_VER_) { + case 7: + switch (field) { + case HW_KM_TCI_COLOR: + get_set(&be->km.v7.tci[index].color, value, get); + break; + case HW_KM_TCI_FT: + get_set(&be->km.v7.tci[index].ft, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 7 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + return 0; +} + +int hw_mod_km_tci_set(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t value) +{ + return hw_mod_km_tci_mod(be, field, bank, record, &value, 0); +} + +int hw_mod_km_tci_get(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t *value) +{ + return hw_mod_km_tci_mod(be, field, bank, record, value, 1); +} + +int hw_mod_km_tcq_flush(struct flow_api_backend_s *be, int start_bank, + int start_record, int count) +{ + if (count == ALL_ENTRIES) + count = be->km.nb_tcam_banks * be->km.nb_tcam_bank_width; + + unsigned int end = (int)start_bank * be->km.nb_tcam_bank_width + + start_record + count; + + if (end > (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width)) + return error_index_too_large(__func__); + + return be->iface->km_tcq_flush(be->be_dev, &be->km, start_bank, + start_record, count); +} + +static int hw_mod_km_tcq_mod(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t *value, int get) +{ + unsigned int index = bank * be->km.nb_tcam_bank_width + record; + + if (index >= (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width)) + return error_index_too_large(__func__); + + switch (_VER_) { + case 7: + switch (field) { + case HW_KM_TCQ_BANK_MASK: + get_set(&be->km.v7.tcq[index].bank_mask, value, get); + break; + case HW_KM_TCQ_QUAL: + get_set(&be->km.v7.tcq[index].qual, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 7 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + return 0; +} + +int hw_mod_km_tcq_set(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t *value) +{ + return hw_mod_km_tcq_mod(be, field, bank, record, value, 0); +} + +int hw_mod_km_tcq_get(struct flow_api_backend_s *be, enum hw_km_e field, + int bank, int record, uint32_t *value) +{ + return hw_mod_km_tcq_mod(be, field, bank, record, value, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h new file mode 100644 index 0000000000..798a175609 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_KM_V7_H_ +#define _HW_MOD_KM_V7_H_ + +struct km_v7_rcp_s { + uint32_t qw0_dyn; + int32_t qw0_ofs; + uint32_t qw0_sel_a; + uint32_t qw0_sel_b; + uint32_t qw4_dyn; + int32_t qw4_ofs; + uint32_t qw4_sel_a; + uint32_t qw4_sel_b; + uint32_t dw8_dyn; + int32_t dw8_ofs; + uint32_t dw8_sel_a; + uint32_t dw8_sel_b; + uint32_t dw10_dyn; + int32_t dw10_ofs; + uint32_t dw10_sel_a; + uint32_t dw10_sel_b; + uint32_t swx_cch; + uint32_t swx_sel_a; + uint32_t swx_sel_b; + uint32_t mask_d_a[12]; + uint32_t mask_b[6]; + uint32_t dual; + uint32_t paired; + uint32_t el_a; + uint32_t el_b; + uint32_t info_a; + uint32_t info_b; + uint32_t ftm_a; + uint32_t ftm_b; + uint32_t bank_a; + uint32_t bank_b; + uint32_t kl_a; + uint32_t kl_b; + uint32_t keyway_a; + uint32_t keyway_b; + uint32_t synergy_mode; + uint32_t dw0_b_dyn; + int32_t dw0_b_ofs; + uint32_t dw2_b_dyn; + int32_t dw2_b_ofs; + uint32_t sw4_b_dyn; + int32_t sw4_b_ofs; + uint32_t sw5_b_dyn; + int32_t sw5_b_ofs; +}; + +struct km_v7_cam_s { + uint32_t w0; + uint32_t w1; + uint32_t w2; + uint32_t w3; + uint32_t w4; + uint32_t w5; + uint32_t ft0; + uint32_t ft1; + uint32_t ft2; + uint32_t ft3; + uint32_t ft4; + uint32_t ft5; +}; + +struct km_v7_tcam_s { + uint32_t t[3]; + uint32_t dirty; +}; + +struct km_v7_tci_s { + uint32_t color; + uint32_t ft; +}; + +struct km_v7_tcq_s { + uint32_t bank_mask; + uint32_t qual; +}; + +struct hw_mod_km_v7_s { + struct km_v7_rcp_s *rcp; + struct km_v7_cam_s *cam; + struct km_v7_tcam_s *tcam; + struct km_v7_tci_s *tci; + struct km_v7_tcq_s *tcq; +}; + +#endif /* _HW_MOD_KM_V7_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c new file mode 100644 index 0000000000..8d0d70cae2 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c @@ -0,0 +1,219 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include "flow_api_backend.h" + +#define _MOD_ "PDB" +#define _VER_ be->pdb.ver + +bool hw_mod_pdb_present(struct flow_api_backend_s *be) +{ + return be->iface->get_pdb_present(be->be_dev); +} + +int hw_mod_pdb_alloc(struct flow_api_backend_s *be) +{ + int nb; + + _VER_ = be->iface->get_pdb_version(be->be_dev); + NT_LOG(DBG, FILTER, "PDB MODULE VERSION %i.%i\n", VER_MAJOR(_VER_), + VER_MINOR(_VER_)); + + nb = be->iface->get_nb_pdb_categories(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "pdb_categories", _MOD_, _VER_); + be->pdb.nb_pdb_rcp_categories = (uint32_t)nb; + + switch (_VER_) { + case 9: + if (!callocate_mod(CAST_COMMON(&be->pdb), 2, + &be->pdb.v9.rcp, + be->pdb.nb_pdb_rcp_categories, + sizeof(struct pdb_v9_rcp_s), + &be->pdb.v9.config, + 1, + sizeof(struct pdb_v9_config_s))) + return -1; + break; + /* end case 9 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + return 0; +} + +void hw_mod_pdb_free(struct flow_api_backend_s *be) +{ + if (be->pdb.base) { + free(be->pdb.base); + be->pdb.base = NULL; + } +} + +int hw_mod_pdb_reset(struct flow_api_backend_s *be) +{ + int err = 0; + /* Zero entire cache area */ + ZERO_MOD_CACHE(&be->pdb); + + NT_LOG(DBG, FILTER, "INIT PDB RCP\n"); + err |= hw_mod_pdb_rcp_flush(be, 0, ALL_ENTRIES); + + NT_LOG(DBG, FILTER, "INIT PDB CONFIG\n"); + err |= hw_mod_pdb_config_flush(be); + return err; +} + +int hw_mod_pdb_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->pdb.nb_pdb_rcp_categories; + if ((unsigned int)(start_idx + count) > be->pdb.nb_pdb_rcp_categories) + return error_index_too_large(__func__); + return be->iface->pdb_rcp_flush(be->be_dev, &be->pdb, start_idx, count); +} + +static int hw_mod_pdb_rcp_mod(struct flow_api_backend_s *be, + enum hw_pdb_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->pdb.nb_pdb_rcp_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 9: + switch (field) { + case HW_PDB_RCP_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->pdb.v9.rcp[index], (uint8_t)*value, + sizeof(struct pdb_v9_rcp_s)); + break; + case HW_PDB_RCP_FIND: + rv = find_equal_index(be->pdb.v9.rcp, + sizeof(struct pdb_v9_rcp_s), index, *value, + be->pdb.nb_pdb_rcp_categories, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_PDB_RCP_COMPARE: + rv = do_compare_indexes(be->pdb.v9.rcp, + sizeof(struct pdb_v9_rcp_s), index, *value, + be->pdb.nb_pdb_rcp_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_PDB_RCP_DESCRIPTOR: + get_set(&be->pdb.v9.rcp[index].descriptor, value, get); + break; + case HW_PDB_RCP_DESC_LEN: + get_set(&be->pdb.v9.rcp[index].desc_len, value, get); + break; + case HW_PDB_RCP_TX_PORT: + get_set(&be->pdb.v9.rcp[index].tx_port, value, get); + break; + case HW_PDB_RCP_TX_IGNORE: + get_set(&be->pdb.v9.rcp[index].tx_ignore, value, get); + break; + case HW_PDB_RCP_TX_NOW: + get_set(&be->pdb.v9.rcp[index].tx_now, value, get); + break; + case HW_PDB_RCP_CRC_OVERWRITE: + get_set(&be->pdb.v9.rcp[index].crc_overwrite, value, get); + break; + case HW_PDB_RCP_ALIGN: + get_set(&be->pdb.v9.rcp[index].align, value, get); + break; + case HW_PDB_RCP_OFS0_DYN: + get_set(&be->pdb.v9.rcp[index].ofs0_dyn, value, get); + break; + case HW_PDB_RCP_OFS0_REL: + get_set_signed(&be->pdb.v9.rcp[index].ofs0_rel, value, get); + break; + case HW_PDB_RCP_OFS1_DYN: + get_set(&be->pdb.v9.rcp[index].ofs1_dyn, value, get); + break; + case HW_PDB_RCP_OFS1_REL: + get_set_signed(&be->pdb.v9.rcp[index].ofs1_rel, value, get); + break; + case HW_PDB_RCP_OFS2_DYN: + get_set(&be->pdb.v9.rcp[index].ofs2_dyn, value, get); + break; + case HW_PDB_RCP_OFS2_REL: + get_set_signed(&be->pdb.v9.rcp[index].ofs2_rel, value, get); + break; + case HW_PDB_RCP_IP_PROT_TNL: + get_set(&be->pdb.v9.rcp[index].ip_prot_tnl, value, get); + break; + case HW_PDB_RCP_PPC_HSH: + get_set(&be->pdb.v9.rcp[index].ppc_hsh, value, get); + break; + case HW_PDB_RCP_DUPLICATE_EN: + get_set(&be->pdb.v9.rcp[index].duplicate_en, value, get); + break; + case HW_PDB_RCP_DUPLICATE_BIT: + get_set(&be->pdb.v9.rcp[index].duplicate_bit, value, get); + break; + case HW_PDB_RCP_PCAP_KEEP_FCS: + get_set(&be->pdb.v9.rcp[index].pcap_keep_fcs, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 9 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_pdb_rcp_set(struct flow_api_backend_s *be, enum hw_pdb_e field, + uint32_t index, uint32_t value) +{ + return hw_mod_pdb_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_pdb_rcp_get(struct flow_api_backend_s *be, enum hw_pdb_e field, + uint32_t index, uint32_t *value) +{ + return hw_mod_pdb_rcp_mod(be, field, index, value, 1); +} + +int hw_mod_pdb_config_flush(struct flow_api_backend_s *be) +{ + return be->iface->pdb_config_flush(be->be_dev, &be->pdb); +} + +int hw_mod_pdb_config_set(struct flow_api_backend_s *be, enum hw_pdb_e field, + uint32_t value) +{ + switch (_VER_) { + case 9: + switch (field) { + case HW_PDB_CONFIG_TS_FORMAT: + be->pdb.v9.config->ts_format = value; + break; + case HW_PDB_CONFIG_PORT_OFS: + be->pdb.v9.config->port_ofs = value; + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 9 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h new file mode 100644 index 0000000000..b14c10bc53 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_PDB_V9_H_ +#define _HW_MOD_PDB_V9_H_ + +struct pdb_v9_rcp_s { + uint32_t descriptor; + uint32_t desc_len; + uint32_t tx_port; + uint32_t tx_ignore; + uint32_t tx_now; + uint32_t crc_overwrite; + uint32_t align; + uint32_t ofs0_dyn; + int32_t ofs0_rel; + uint32_t ofs1_dyn; + int32_t ofs1_rel; + uint32_t ofs2_dyn; + int32_t ofs2_rel; + uint32_t ip_prot_tnl; + uint32_t ppc_hsh; + uint32_t duplicate_en; + uint32_t duplicate_bit; + uint32_t pcap_keep_fcs; /* only field added to v9 cmp to v7/8 */ +}; + +struct pdb_v9_config_s { + uint32_t ts_format; + uint32_t port_ofs; +}; + +struct hw_mod_pdb_v9_s { + struct pdb_v9_rcp_s *rcp; + struct pdb_v9_config_s *config; +}; + +#endif /* _HW_MOD_PDB_V9_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c new file mode 100644 index 0000000000..86d23ea683 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c @@ -0,0 +1,348 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include "flow_api_backend.h" + +#define _MOD_ "QSL" +#define _VER_ be->qsl.ver + +#define QSL_QEN_ENTRIES 32 +#define QSL_QNMQ_ENTRIES 256 + +bool hw_mod_qsl_present(struct flow_api_backend_s *be) +{ + return be->iface->get_qsl_present(be->be_dev); +} + +int hw_mod_qsl_alloc(struct flow_api_backend_s *be) +{ + int nb; + + _VER_ = be->iface->get_qsl_version(be->be_dev); + NT_LOG(DBG, FILTER, "QSL MODULE VERSION %i.%i\n", VER_MAJOR(_VER_), + VER_MINOR(_VER_)); + + nb = be->iface->get_nb_qsl_categories(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "qsl_categories", _MOD_, _VER_); + be->qsl.nb_rcp_categories = (uint32_t)nb; + + nb = be->iface->get_nb_qsl_qst_entries(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "qsl_qst_entries", _MOD_, _VER_); + be->qsl.nb_qst_entries = (uint32_t)nb; + + switch (_VER_) { + case 7: + if (!callocate_mod(CAST_COMMON(&be->qsl), 4, + &be->qsl.v7.rcp, + be->qsl.nb_rcp_categories, + sizeof(struct qsl_v7_rcp_s), + &be->qsl.v7.qst, + be->qsl.nb_qst_entries, + sizeof(struct qsl_v7_qst_s), + &be->qsl.v7.qen, + QSL_QEN_ENTRIES, + sizeof(struct qsl_v7_qen_s), + &be->qsl.v7.unmq, + QSL_QNMQ_ENTRIES, + sizeof(struct qsl_v7_unmq_s))) + return -1; + break; + /* end case 7 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + return 0; +} + +void hw_mod_qsl_free(struct flow_api_backend_s *be) +{ + if (be->qsl.base) { + free(be->qsl.base); + be->qsl.base = NULL; + } +} + +int hw_mod_qsl_reset(struct flow_api_backend_s *be) +{ + /* Zero entire cache area */ + ZERO_MOD_CACHE(&be->qsl); + + NT_LOG(DBG, FILTER, "INIT QSL RCP\n"); + hw_mod_qsl_rcp_flush(be, 0, ALL_ENTRIES); + + NT_LOG(DBG, FILTER, "INIT QSL QST\n"); + hw_mod_qsl_qst_flush(be, 0, ALL_ENTRIES); + + NT_LOG(DBG, FILTER, "INIT QSL QEN\n"); + hw_mod_qsl_qen_flush(be, 0, ALL_ENTRIES); + + NT_LOG(DBG, FILTER, "INIT QSL UNMQ\n"); + be->iface->qsl_unmq_flush(be->be_dev, &be->qsl, 0, 256); + + return 0; +} + +int hw_mod_qsl_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->qsl.nb_rcp_categories; + if ((unsigned int)(start_idx + count) > be->qsl.nb_rcp_categories) + return error_index_too_large(__func__); + return be->iface->qsl_rcp_flush(be->be_dev, &be->qsl, start_idx, count); +} + +static int hw_mod_qsl_rcp_mod(struct flow_api_backend_s *be, + enum hw_qsl_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->qsl.nb_rcp_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 7: + switch (field) { + case HW_QSL_RCP_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->qsl.v7.rcp[index], (uint8_t)*value, + sizeof(struct qsl_v7_rcp_s)); + break; + case HW_QSL_RCP_FIND: + rv = find_equal_index(be->qsl.v7.rcp, + sizeof(struct qsl_v7_rcp_s), index, *value, + be->qsl.nb_rcp_categories, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_QSL_RCP_COMPARE: + rv = do_compare_indexes(be->qsl.v7.rcp, + sizeof(struct qsl_v7_rcp_s), index, *value, + be->qsl.nb_rcp_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_QSL_RCP_DISCARD: + get_set(&be->qsl.v7.rcp[index].discard, value, get); + break; + case HW_QSL_RCP_DROP: + get_set(&be->qsl.v7.rcp[index].drop, value, get); + break; + case HW_QSL_RCP_TBL_LO: + get_set(&be->qsl.v7.rcp[index].tbl_lo, value, get); + break; + case HW_QSL_RCP_TBL_HI: + get_set(&be->qsl.v7.rcp[index].tbl_hi, value, get); + break; + case HW_QSL_RCP_TBL_IDX: + get_set(&be->qsl.v7.rcp[index].tbl_idx, value, get); + break; + case HW_QSL_RCP_TBL_MSK: + get_set(&be->qsl.v7.rcp[index].tbl_msk, value, get); + break; + case HW_QSL_RCP_LR: + get_set(&be->qsl.v7.rcp[index].lr, value, get); + break; + case HW_QSL_RCP_TSA: + get_set(&be->qsl.v7.rcp[index].tsa, value, get); + break; + case HW_QSL_RCP_VLI: + get_set(&be->qsl.v7.rcp[index].vli, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 7 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_qsl_rcp_set(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t value) +{ + return hw_mod_qsl_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_qsl_rcp_get(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t *value) +{ + return hw_mod_qsl_rcp_mod(be, field, index, value, 1); +} + +int hw_mod_qsl_qst_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->qsl.nb_qst_entries; + if ((unsigned int)(start_idx + count) > be->qsl.nb_qst_entries) + return error_index_too_large(__func__); + return be->iface->qsl_qst_flush(be->be_dev, &be->qsl, start_idx, count); +} + +static int hw_mod_qsl_qst_mod(struct flow_api_backend_s *be, + enum hw_qsl_e field, uint32_t index, + uint32_t *value, int get) +{ + if (index >= be->qsl.nb_qst_entries) + return error_index_too_large(__func__); + switch (_VER_) { + case 7: + switch (field) { + case HW_QSL_QST_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->qsl.v7.qst[index], (uint8_t)*value, + sizeof(struct qsl_v7_qst_s)); + break; + case HW_QSL_QST_QUEUE: + get_set(&be->qsl.v7.qst[index].queue, value, get); + break; + case HW_QSL_QST_EN: + get_set(&be->qsl.v7.qst[index].en, value, get); + break; + case HW_QSL_QST_TX_PORT: + get_set(&be->qsl.v7.qst[index].tx_port, value, get); + break; + case HW_QSL_QST_LRE: + get_set(&be->qsl.v7.qst[index].lre, value, get); + break; + case HW_QSL_QST_TCI: + get_set(&be->qsl.v7.qst[index].tci, value, get); + break; + case HW_QSL_QST_VEN: + get_set(&be->qsl.v7.qst[index].ven, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 7 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_qsl_qst_set(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t value) +{ + return hw_mod_qsl_qst_mod(be, field, index, &value, 0); +} + +int hw_mod_qsl_qst_get(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t *value) +{ + return hw_mod_qsl_qst_mod(be, field, index, value, 1); +} + +int hw_mod_qsl_qen_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = QSL_QEN_ENTRIES; + if ((start_idx + count) > QSL_QEN_ENTRIES) + return error_index_too_large(__func__); + return be->iface->qsl_qen_flush(be->be_dev, &be->qsl, start_idx, count); +} + +static int hw_mod_qsl_qen_mod(struct flow_api_backend_s *be, + enum hw_qsl_e field, uint32_t index, + uint32_t *value, int get) +{ + if (index >= QSL_QEN_ENTRIES) + return error_index_too_large(__func__); + switch (_VER_) { + case 7: + switch (field) { + case HW_QSL_QEN_EN: + get_set(&be->qsl.v7.qen[index].en, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 7 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_qsl_qen_set(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t value) +{ + return hw_mod_qsl_qen_mod(be, field, index, &value, 0); +} + +int hw_mod_qsl_qen_get(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t *value) +{ + return hw_mod_qsl_qen_mod(be, field, index, value, 1); +} + +int hw_mod_qsl_unmq_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = QSL_QNMQ_ENTRIES; + if ((start_idx + count) > QSL_QNMQ_ENTRIES) + return error_index_too_large(__func__); + return be->iface->qsl_unmq_flush(be->be_dev, &be->qsl, start_idx, + count); +} + +static int hw_mod_qsl_unmq_mod(struct flow_api_backend_s *be, + enum hw_qsl_e field, uint32_t index, + uint32_t *value, int get) +{ + if (index >= QSL_QNMQ_ENTRIES) + return error_index_too_large(__func__); + switch (_VER_) { + case 7: + switch (field) { + case HW_QSL_UNMQ_DEST_QUEUE: + get_set(&be->qsl.v7.unmq[index].dest_queue, value, get); + break; + case HW_QSL_UNMQ_EN: + get_set(&be->qsl.v7.unmq[index].en, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 7 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_qsl_unmq_set(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t value) +{ + return hw_mod_qsl_unmq_mod(be, field, index, &value, 0); +} + +int hw_mod_qsl_unmq_get(struct flow_api_backend_s *be, enum hw_qsl_e field, + uint32_t index, uint32_t *value) +{ + return hw_mod_qsl_unmq_mod(be, field, index, value, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h new file mode 100644 index 0000000000..747da4bc43 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_QSL_V7_H_ +#define _HW_MOD_QSL_V7_H_ + +struct qsl_v7_rcp_s { + uint32_t discard; + uint32_t drop; + uint32_t tbl_lo; + uint32_t tbl_hi; + uint32_t tbl_idx; + uint32_t tbl_msk; + uint32_t lr; + uint32_t tsa; + uint32_t vli; +}; + +struct qsl_v7_qst_s { + uint32_t queue; + uint32_t en; + uint32_t tx_port; + uint32_t lre; + uint32_t tci; + uint32_t ven; +}; + +struct qsl_v7_qen_s { + uint32_t en; +}; + +struct qsl_v7_unmq_s { + uint32_t dest_queue; + uint32_t en; +}; + +struct hw_mod_qsl_v7_s { + struct qsl_v7_rcp_s *rcp; + struct qsl_v7_qst_s *qst; + struct qsl_v7_qen_s *qen; + struct qsl_v7_unmq_s *unmq; +}; + +#endif /* _HW_MOD_QSL_V7_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c new file mode 100644 index 0000000000..7f1d695a90 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include "flow_api_backend.h" + +#define _MOD_ "RMC" +#define _VER_ be->rmc.ver + +bool hw_mod_rmc_present(struct flow_api_backend_s *be) +{ + return be->iface->get_rmc_present(be->be_dev); +} + +int hw_mod_rmc_alloc(struct flow_api_backend_s *be) +{ + _VER_ = be->iface->get_rmc_version(be->be_dev); + NT_LOG(DBG, FILTER, "RMC MODULE VERSION %i.%i\n", VER_MAJOR(_VER_), + VER_MINOR(_VER_)); + + switch (_VER_) { + case 0x10003: + if (!callocate_mod(CAST_COMMON(&be->rmc), 1, + &be->rmc.v1_3.ctrl, 1, sizeof(struct rmc_v1_3_ctrl_s))) + return -1; + break; + /* end case 1_3 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +void hw_mod_rmc_free(struct flow_api_backend_s *be) +{ + if (be->rmc.base) { + free(be->rmc.base); + be->rmc.base = NULL; + } +} + +int hw_mod_rmc_reset(struct flow_api_backend_s *be) +{ + /* Zero entire cache area */ + ZERO_MOD_CACHE(&be->rmc); + + NT_LOG(DBG, FILTER, "INIT RMC CTRL\n"); + /* disable block stat, block keep alive */ + hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_STATT, 1); + hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_KEEPA, 1); + hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_MAC_PORT, + 0xff); /* initially block all ports */ + hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_STATT, 1); + hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_RPP_SLICE, 0xf); + return hw_mod_rmc_ctrl_flush(be); +} + +int hw_mod_rmc_ctrl_flush(struct flow_api_backend_s *be) +{ + return be->iface->rmc_ctrl_flush(be->be_dev, &be->rmc); +} + +static int hw_mod_rmc_ctrl_mod(struct flow_api_backend_s *be, + enum hw_rmc_e field, uint32_t *value, int get) +{ + switch (_VER_) { + case 0x10003: + switch (field) { + case HW_RMC_BLOCK_STATT: + get_set(&be->rmc.v1_3.ctrl->block_statt, value, get); + break; + case HW_RMC_BLOCK_KEEPA: + get_set(&be->rmc.v1_3.ctrl->block_keepa, value, get); + break; + case HW_RMC_BLOCK_RPP_SLICE: + get_set(&be->rmc.v1_3.ctrl->block_rpp_slice, value, get); + break; + case HW_RMC_BLOCK_MAC_PORT: + get_set(&be->rmc.v1_3.ctrl->block_mac_port, value, get); + break; + case HW_RMC_LAG_PHY_ODD_EVEN: + get_set(&be->rmc.v1_3.ctrl->lag_phy_odd_even, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 1.3 */ + + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_rmc_ctrl_set(struct flow_api_backend_s *be, enum hw_rmc_e field, + uint32_t value) +{ + return hw_mod_rmc_ctrl_mod(be, field, &value, 0); +} + +int hw_mod_rmc_ctrl_get(struct flow_api_backend_s *be, enum hw_rmc_e field, + uint32_t *value) +{ + return hw_mod_rmc_ctrl_mod(be, field, value, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h new file mode 100644 index 0000000000..8f90695821 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_RMC_V1_3_H_ +#define _HW_MOD_RMC_V1_3_H_ + +struct rmc_v1_3_ctrl_s { + uint32_t block_statt; + uint32_t block_keepa; + uint32_t block_rpp_slice; + uint32_t block_mac_port; + uint32_t lag_phy_odd_even; +}; + +struct hw_mod_rmc_v1_3_s { + struct rmc_v1_3_ctrl_s *ctrl; +}; + +#endif /* _HW_MOD_RMC_V1_3_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c new file mode 100644 index 0000000000..933caf9fd5 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c @@ -0,0 +1,358 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include "flow_api_backend.h" + +#define _MOD_ "ROA" +#define _VER_ be->roa.ver + +#define ROA_LAGCFG_ENTRIES 512 + +bool hw_mod_roa_present(struct flow_api_backend_s *be) +{ + return be->iface->get_roa_present(be->be_dev); +} + +int hw_mod_roa_alloc(struct flow_api_backend_s *be) +{ + int nb; + + _VER_ = be->iface->get_roa_version(be->be_dev); + NT_LOG(DBG, FILTER, "ROA MODULE VERSION %i.%i\n", VER_MAJOR(_VER_), + VER_MINOR(_VER_)); + + nb = be->iface->get_nb_roa_categories(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "roa_categories", _MOD_, _VER_); + be->roa.nb_tun_categories = (uint32_t)nb; + + be->roa.nb_tun_categories /= 4; + + switch (_VER_) { + case 6: + be->roa.nb_lag_entries = ROA_LAGCFG_ENTRIES; + if (!callocate_mod(CAST_COMMON(&be->roa), 4, + &be->roa.v6.tunhdr, + be->roa.nb_tun_categories, + sizeof(struct roa_v6_tunhdr_s), + &be->roa.v6.tuncfg, + be->roa.nb_tun_categories, + sizeof(struct roa_v6_tuncfg_s), + &be->roa.v6.config, + 1, + sizeof(struct roa_v6_config_s), + &be->roa.v6.lagcfg, + be->roa.nb_lag_entries, + sizeof(struct roa_v6_lagcfg_s))) + return -1; + break; + /* end case 6 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + return 0; +} + +void hw_mod_roa_free(struct flow_api_backend_s *be) +{ + if (be->roa.base) { + free(be->roa.base); + be->roa.base = NULL; + } +} + +int hw_mod_roa_reset(struct flow_api_backend_s *be) +{ + int err = 0; + + /* Zero entire cache area */ + ZERO_MOD_CACHE(&be->roa); + + NT_LOG(DBG, FILTER, "INIT ROA TUNHDR\n"); + err = hw_mod_roa_tunhdr_flush(be, 0, ALL_ENTRIES); + + NT_LOG(DBG, FILTER, "INIT ROA TUNCFG\n"); + hw_mod_roa_tuncfg_flush(be, 0, ALL_ENTRIES); + + NT_LOG(DBG, FILTER, "INIT ROA CONFIG\n"); + hw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_RECIRCULATE, 1); + hw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_NORMAL_PCKS, 1); + hw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_TXPORT0, 1); + hw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_TXPORT1, 1); + hw_mod_roa_config_flush(be); + + NT_LOG(DBG, FILTER, "INIT ROA LAGCFG\n"); + hw_mod_roa_lagcfg_flush(be, 0, ALL_ENTRIES); + + return err; +} + +int hw_mod_roa_tunhdr_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->roa.nb_tun_categories; + if ((unsigned int)(start_idx + count) > be->roa.nb_tun_categories) + return error_index_too_large(__func__); + return be->iface->roa_tunhdr_flush(be->be_dev, &be->roa, start_idx, + count); +} + +static int hw_mod_roa_tunhdr_mod(struct flow_api_backend_s *be, + enum hw_roa_e field, uint32_t index, + uint32_t word_off, uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->roa.nb_tun_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 6: + switch (field) { + case HW_ROA_TUNHDR_COMPARE: + rv = do_compare_indexes(be->roa.v6.tunhdr, + sizeof(struct roa_v6_tunhdr_s), index, word_off, + be->roa.nb_tun_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_ROA_TUNHDR: + get_set(&be->roa.v6.tunhdr[index].tunnel_hdr[word_off], + value, get); + break; + default: + return error_unsup_field(__func__); + } + break; + /* end case 6 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_roa_tunhdr_set(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t index, uint32_t word_off, uint32_t value) +{ + return hw_mod_roa_tunhdr_mod(be, field, index, word_off, &value, 0); +} + +int hw_mod_roa_tunhdr_get(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t index, uint32_t word_off, uint32_t *value) +{ + return hw_mod_roa_tunhdr_mod(be, field, index, word_off, value, 1); +} + +int hw_mod_roa_tuncfg_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->roa.nb_tun_categories; + if ((unsigned int)(start_idx + count) > be->roa.nb_tun_categories) + return error_index_too_large(__func__); + return be->iface->roa_tuncfg_flush(be->be_dev, &be->roa, start_idx, + count); +} + +static int hw_mod_roa_tuncfg_mod(struct flow_api_backend_s *be, + enum hw_roa_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->roa.nb_tun_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 6: + switch (field) { + case HW_ROA_TUNCFG_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->roa.v6.tuncfg[index], (uint8_t)*value, + sizeof(struct roa_v6_tuncfg_s)); + break; + case HW_ROA_TUNCFG_FIND: + rv = find_equal_index(be->roa.v6.tuncfg, + sizeof(struct roa_v6_tuncfg_s), index, *value, + be->roa.nb_tun_categories, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_ROA_TUNCFG_COMPARE: + rv = do_compare_indexes(be->roa.v6.tuncfg, + sizeof(struct roa_v6_tuncfg_s), index, *value, + be->roa.nb_tun_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_ROA_TUNCFG_TUN_LEN: + get_set(&be->roa.v6.tuncfg[index].tun_len, value, get); + break; + case HW_ROA_TUNCFG_TUN_TYPE: + get_set(&be->roa.v6.tuncfg[index].tun_type, value, get); + break; + case HW_ROA_TUNCFG_TUN_VLAN: + get_set(&be->roa.v6.tuncfg[index].tun_vlan, value, get); + break; + case HW_ROA_TUNCFG_IP_TYPE: + get_set(&be->roa.v6.tuncfg[index].ip_type, value, get); + break; + case HW_ROA_TUNCFG_IPCS_UPD: + get_set(&be->roa.v6.tuncfg[index].ipcs_upd, value, get); + break; + case HW_ROA_TUNCFG_IPCS_PRECALC: + get_set(&be->roa.v6.tuncfg[index].ipcs_precalc, value, get); + break; + case HW_ROA_TUNCFG_IPTL_UPD: + get_set(&be->roa.v6.tuncfg[index].iptl_upd, value, get); + break; + case HW_ROA_TUNCFG_IPTL_PRECALC: + get_set(&be->roa.v6.tuncfg[index].iptl_precalc, value, get); + break; + case HW_ROA_TUNCFG_VXLAN_UDP_LEN_UPD: + get_set(&be->roa.v6.tuncfg[index].vxlan_udp_len_upd, + value, get); + break; + case HW_ROA_TUNCFG_TX_LAG_IX: + get_set(&be->roa.v6.tuncfg[index].tx_lag_ix, value, get); + break; + case HW_ROA_TUNCFG_RECIRCULATE: + get_set(&be->roa.v6.tuncfg[index].recirculate, value, get); + break; + case HW_ROA_TUNCFG_PUSH_TUNNEL: + get_set(&be->roa.v6.tuncfg[index].push_tunnel, value, get); + break; + case HW_ROA_TUNCFG_RECIRC_PORT: + get_set(&be->roa.v6.tuncfg[index].recirc_port, value, get); + break; + case HW_ROA_TUNCFG_RECIRC_BYPASS: + get_set(&be->roa.v6.tuncfg[index].recirc_bypass, value, get); + break; + default: + return error_unsup_field(__func__); + } + break; + /* end case 6 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_roa_tuncfg_set(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t index, uint32_t value) +{ + return hw_mod_roa_tuncfg_mod(be, field, index, &value, 0); +} + +int hw_mod_roa_tuncfg_get(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t index, uint32_t *value) +{ + return hw_mod_roa_tuncfg_mod(be, field, index, value, 1); +} + +int hw_mod_roa_config_flush(struct flow_api_backend_s *be) +{ + return be->iface->roa_config_flush(be->be_dev, &be->roa); +} + +static int hw_mod_roa_config_mod(struct flow_api_backend_s *be, + enum hw_roa_e field, uint32_t *value, int get) +{ + switch (_VER_) { + case 6: + switch (field) { + case HW_ROA_CONFIG_FWD_RECIRCULATE: + get_set(&be->roa.v6.config->fwd_recirculate, value, get); + break; + case HW_ROA_CONFIG_FWD_NORMAL_PCKS: + get_set(&be->roa.v6.config->fwd_normal_pcks, value, get); + break; + case HW_ROA_CONFIG_FWD_TXPORT0: + get_set(&be->roa.v6.config->fwd_txport0, value, get); + break; + case HW_ROA_CONFIG_FWD_TXPORT1: + get_set(&be->roa.v6.config->fwd_txport1, value, get); + break; + case HW_ROA_CONFIG_FWD_CELLBUILDER_PCKS: + get_set(&be->roa.v6.config->fwd_cellbuilder_pcks, value, get); + break; + case HW_ROA_CONFIG_FWD_NON_NORMAL_PCKS: + get_set(&be->roa.v6.config->fwd_non_normal_pcks, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 6 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_roa_config_set(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t value) +{ + return hw_mod_roa_config_mod(be, field, &value, 0); +} + +int hw_mod_roa_config_get(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t *value) +{ + return hw_mod_roa_config_mod(be, field, value, 1); +} + +int hw_mod_roa_lagcfg_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->roa.nb_lag_entries; + if ((unsigned int)(start_idx + count) > be->roa.nb_lag_entries) + return error_index_too_large(__func__); + return be->iface->roa_lagcfg_flush(be->be_dev, &be->roa, start_idx, + count); +} + +static int hw_mod_roa_lagcfg_mod(struct flow_api_backend_s *be, + enum hw_roa_e field, uint32_t index, + uint32_t *value, int get) +{ + if (index >= be->roa.nb_lag_entries) + return error_index_too_large(__func__); + switch (_VER_) { + case 6: + switch (field) { + case HW_ROA_LAGCFG_TXPHY_PORT: + get_set(&be->roa.v6.lagcfg[index].txphy_port, value, get); + break; + default: + return error_unsup_field(__func__); + } + break; + /* end case 6 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_roa_lagcfg_set(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t index, uint32_t value) +{ + return hw_mod_roa_lagcfg_mod(be, field, index, &value, 0); +} + +int hw_mod_roa_lagcfg_get(struct flow_api_backend_s *be, enum hw_roa_e field, + uint32_t index, uint32_t *value) +{ + return hw_mod_roa_lagcfg_mod(be, field, index, value, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h new file mode 100644 index 0000000000..9930c52428 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_ROA_V6_H_ +#define _HW_MOD_ROA_V6_H_ + +struct roa_v6_tunhdr_s { + uint32_t tunnel_hdr[4 * 4]; +}; + +struct roa_v6_tuncfg_s { + uint32_t tun_len; + uint32_t tun_type; + uint32_t tun_vlan; + uint32_t ip_type; + uint32_t ipcs_upd; + uint32_t ipcs_precalc; + uint32_t iptl_upd; + uint32_t iptl_precalc; + uint32_t vxlan_udp_len_upd; + uint32_t tx_lag_ix; + uint32_t recirculate; + uint32_t push_tunnel; + uint32_t recirc_port; + uint32_t recirc_bypass; +}; + +struct roa_v6_config_s { + uint32_t fwd_recirculate; + uint32_t fwd_normal_pcks; + uint32_t fwd_txport0; + uint32_t fwd_txport1; + uint32_t fwd_cellbuilder_pcks; + uint32_t fwd_non_normal_pcks; +}; + +struct roa_v6_lagcfg_s { + uint32_t txphy_port; +}; + +struct hw_mod_roa_v6_s { + struct roa_v6_tunhdr_s *tunhdr; + struct roa_v6_tuncfg_s *tuncfg; + struct roa_v6_config_s *config; + struct roa_v6_lagcfg_s *lagcfg; +}; + +#endif /* _HW_MOD_ROA_V6_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c new file mode 100644 index 0000000000..ca65db7232 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include "flow_api_backend.h" + +#define _MOD_ "SLC" +#define _VER_ be->slc.ver + +bool hw_mod_slc_present(struct flow_api_backend_s *be) +{ + return be->iface->get_slc_present(be->be_dev); +} + +int hw_mod_slc_alloc(struct flow_api_backend_s *be) +{ + _VER_ = be->iface->get_slc_version(be->be_dev); + NT_LOG(DBG, FILTER, "SLC MODULE VERSION %i.%i\n", VER_MAJOR(_VER_), + VER_MINOR(_VER_)); + + switch (_VER_) { + case 1: + if (!callocate_mod(CAST_COMMON(&be->slc), 1, + &be->slc.v1.rcp, + be->max_categories, + sizeof(struct slc_v1_rcp_s))) + return -1; + break; + /* end case 1 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +void hw_mod_slc_free(struct flow_api_backend_s *be) +{ + if (be->slc.base) { + free(be->slc.base); + be->slc.base = NULL; + } +} + +int hw_mod_slc_reset(struct flow_api_backend_s *be) +{ + /* Zero entire cache area */ + ZERO_MOD_CACHE(&be->slc); + + NT_LOG(DBG, FILTER, "INIT SLC RCP\n"); + return hw_mod_slc_rcp_flush(be, 0, be->max_categories); +} + +int hw_mod_slc_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->max_categories; + if ((unsigned int)(start_idx + count) > be->max_categories) + return error_index_too_large(__func__); + return be->iface->slc_rcp_flush(be->be_dev, &be->slc, start_idx, count); +} + +static int hw_mod_slc_rcp_mod(struct flow_api_backend_s *be, + enum hw_slc_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->max_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 1: + switch (field) { + case HW_SLC_RCP_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->slc.v1.rcp[index], (uint8_t)*value, + sizeof(struct hw_mod_slc_v1_s)); + break; + case HW_SLC_RCP_FIND: + rv = find_equal_index(be->slc.v1.rcp, + sizeof(struct hw_mod_slc_v1_s), index, *value, + be->max_categories, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_SLC_RCP_COMPARE: + rv = do_compare_indexes(be->slc.v1.rcp, + sizeof(struct hw_mod_slc_v1_s), index, *value, + be->max_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_SLC_RCP_SLC_EN: + get_set(&be->slc.v1.rcp[index].tail_slc_en, value, get); + break; + case HW_SLC_RCP_DYN: + get_set(&be->slc.v1.rcp[index].tail_dyn, value, get); + break; + case HW_SLC_RCP_OFS: + get_set_signed(&be->slc.v1.rcp[index].tail_ofs, value, get); + break; + case HW_SLC_RCP_PCAP: + get_set(&be->slc.v1.rcp[index].pcap, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 1 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_slc_rcp_set(struct flow_api_backend_s *be, enum hw_slc_e field, + uint32_t index, uint32_t value) +{ + return hw_mod_slc_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_slc_rcp_get(struct flow_api_backend_s *be, enum hw_slc_e field, + uint32_t index, uint32_t *value) +{ + return hw_mod_slc_rcp_mod(be, field, index, value, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c new file mode 100644 index 0000000000..9f40563e8a --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include "flow_api_backend.h" + +#define _MOD_ "SLC_LR" +#define _VER_ be->slc_lr.ver + +bool hw_mod_slc_lr_present(struct flow_api_backend_s *be) +{ + return be->iface->get_slc_lr_present(be->be_dev); +} + +int hw_mod_slc_lr_alloc(struct flow_api_backend_s *be) +{ + _VER_ = be->iface->get_slc_lr_version(be->be_dev); + NT_LOG(DBG, FILTER, "SLC LR MODULE VERSION %i.%i\n", VER_MAJOR(_VER_), + VER_MINOR(_VER_)); + + switch (_VER_) { + case 2: + if (!callocate_mod(CAST_COMMON(&be->slc_lr), 1, + &be->slc_lr.v2.rcp, + be->max_categories, + sizeof(struct slc_lr_v2_rcp_s))) + return -1; + break; + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +void hw_mod_slc_lr_free(struct flow_api_backend_s *be) +{ + if (be->slc_lr.base) { + free(be->slc_lr.base); + be->slc_lr.base = NULL; + } +} + +int hw_mod_slc_lr_reset(struct flow_api_backend_s *be) +{ + /* Zero entire cache area */ + ZERO_MOD_CACHE(&be->slc_lr); + + NT_LOG(DBG, FILTER, "INIT SLC LR RCP\n"); + return hw_mod_slc_lr_rcp_flush(be, 0, be->max_categories); +} + +int hw_mod_slc_lr_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->max_categories; + if ((unsigned int)(start_idx + count) > be->max_categories) + return error_index_too_large(__func__); + return be->iface->slc_lr_rcp_flush(be->be_dev, &be->slc_lr, start_idx, + count); +} + +static int hw_mod_slc_lr_rcp_mod(struct flow_api_backend_s *be, + enum hw_slc_lr_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->max_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 2: + switch (field) { + case HW_SLC_LR_RCP_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->slc_lr.v2.rcp[index], (uint8_t)*value, + sizeof(struct hw_mod_slc_lr_v2_s)); + break; + case HW_SLC_LR_RCP_FIND: + rv = find_equal_index(be->slc_lr.v2.rcp, + sizeof(struct hw_mod_slc_lr_v2_s), index, *value, + be->max_categories, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_SLC_LR_RCP_COMPARE: + rv = do_compare_indexes(be->slc_lr.v2.rcp, + sizeof(struct hw_mod_slc_lr_v2_s), index, *value, + be->max_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_SLC_LR_RCP_SLC_EN: + get_set(&be->slc_lr.v2.rcp[index].tail_slc_en, value, get); + break; + case HW_SLC_LR_RCP_DYN: + get_set(&be->slc_lr.v2.rcp[index].tail_dyn, value, get); + break; + case HW_SLC_LR_RCP_OFS: + get_set_signed(&be->slc_lr.v2.rcp[index].tail_ofs, + value, get); + break; + case HW_SLC_LR_RCP_PCAP: + get_set(&be->slc_lr.v2.rcp[index].pcap, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_slc_lr_rcp_set(struct flow_api_backend_s *be, enum hw_slc_lr_e field, + uint32_t index, uint32_t value) +{ + return hw_mod_slc_lr_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_slc_lr_rcp_get(struct flow_api_backend_s *be, enum hw_slc_lr_e field, + uint32_t index, uint32_t *value) +{ + return hw_mod_slc_lr_rcp_mod(be, field, index, value, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h new file mode 100644 index 0000000000..d03b206e6d --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_SLC_LR_V2_H_ +#define _HW_MOD_SLC_LR_V2_H_ + +struct slc_lr_v2_rcp_s { + uint32_t tail_slc_en; + uint32_t tail_dyn; + int32_t tail_ofs; + uint32_t pcap; +}; + +struct hw_mod_slc_lr_v2_s { + struct slc_lr_v2_rcp_s *rcp; +}; + +#endif /* _HW_MOD_SLC_V2_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h new file mode 100644 index 0000000000..01f60bfb18 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_SLC_V1_H_ +#define _HW_MOD_SLC_V1_H_ + +struct slc_v1_rcp_s { + uint32_t tail_slc_en; + uint32_t tail_dyn; + int32_t tail_ofs; + uint32_t pcap; +}; + +struct hw_mod_slc_v1_s { + struct slc_v1_rcp_s *rcp; +}; + +#endif /* _HW_MOD_SLC_V1_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c new file mode 100644 index 0000000000..dd6f06b2c4 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c @@ -0,0 +1,983 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include "flow_api_backend.h" + +#define _MOD_ "TPE" +#define _VER_ be->tpe.ver + +bool hw_mod_tpe_present(struct flow_api_backend_s *be) +{ + return be->iface->get_tpe_present(be->be_dev); +} + +int hw_mod_tpe_alloc(struct flow_api_backend_s *be) +{ + int nb; + + _VER_ = be->iface->get_tpe_version(be->be_dev); + NT_LOG(DBG, FILTER, _MOD_ " MODULE VERSION %i.%i\n", VER_MAJOR(_VER_), + VER_MINOR(_VER_)); + + nb = be->iface->get_nb_tpe_categories(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "tpe_categories", _MOD_, _VER_); + be->tpe.nb_rcp_categories = (uint32_t)nb; + + be->tpe.nb_ifr_categories = 0; + if (_VER_ > 1) { + nb = be->iface->get_nb_tpe_ifr_categories(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "tpe_ifr_categories", _MOD_, _VER_); + be->tpe.nb_ifr_categories = (uint32_t)nb; + } + + nb = be->iface->get_nb_tx_cpy_writers(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "tx_cpy_writers", _MOD_, _VER_); + be->tpe.nb_cpy_writers = (uint32_t)nb; + + nb = be->iface->get_nb_tx_rpl_depth(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "tx_rpl_depth", _MOD_, _VER_); + be->tpe.nb_rpl_depth = (uint32_t)nb; + + nb = be->iface->get_nb_tx_rpl_ext_categories(be->be_dev); + if (nb <= 0) + return error_resource_count(__func__, "tx_rpl_ext_categories", _MOD_, _VER_); + be->tpe.nb_rpl_ext_categories = (uint32_t)nb; + + switch (_VER_) { + case 1: + if (!callocate_mod(CAST_COMMON(&be->tpe), 8, + &be->tpe.v1.rpp_rcp, be->tpe.nb_rcp_categories, + sizeof(struct tpe_v1_rpp_v0_rcp_s), + &be->tpe.v1.ins_rcp, be->tpe.nb_rcp_categories, + sizeof(struct tpe_v1_ins_v1_rcp_s), + &be->tpe.v1.rpl_rcp, be->tpe.nb_rcp_categories, + sizeof(struct tpe_v1_rpl_v2_rcp_s), + &be->tpe.v1.rpl_ext, be->tpe.nb_rpl_ext_categories, + sizeof(struct tpe_v1_rpl_v2_ext_s), + &be->tpe.v1.rpl_rpl, be->tpe.nb_rpl_depth, + sizeof(struct tpe_v1_rpl_v2_rpl_s), + &be->tpe.v1.cpy_rcp, + be->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories, + sizeof(struct tpe_v1_cpy_v1_rcp_s), + &be->tpe.v1.hfu_rcp, be->tpe.nb_rcp_categories, + sizeof(struct tpe_v1_hfu_v1_rcp_s), + &be->tpe.v1.csu_rcp, be->tpe.nb_rcp_categories, + sizeof(struct tpe_v1_csu_v0_rcp_s))) + return -1; + break; + case 2: + if (!callocate_mod(CAST_COMMON(&be->tpe), 10, + &be->tpe.v2.rpp_rcp, be->tpe.nb_rcp_categories, + sizeof(struct tpe_v1_rpp_v0_rcp_s), + &be->tpe.v2.rpp_ifr_rcp, be->tpe.nb_ifr_categories, + sizeof(struct tpe_v2_rpp_v1_ifr_rcp_s), + &be->tpe.v2.ifr_rcp, be->tpe.nb_ifr_categories, + sizeof(struct tpe_v2_ifr_v1_rcp_s), + &be->tpe.v2.ins_rcp, be->tpe.nb_rcp_categories, + sizeof(struct tpe_v1_ins_v1_rcp_s), + &be->tpe.v2.rpl_rcp, be->tpe.nb_rcp_categories, + sizeof(struct tpe_v1_rpl_v2_rcp_s), + &be->tpe.v2.rpl_ext, be->tpe.nb_rpl_ext_categories, + sizeof(struct tpe_v1_rpl_v2_ext_s), + &be->tpe.v2.rpl_rpl, be->tpe.nb_rpl_depth, + sizeof(struct tpe_v1_rpl_v2_rpl_s), + &be->tpe.v2.cpy_rcp, + be->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories, + sizeof(struct tpe_v1_cpy_v1_rcp_s), + &be->tpe.v2.hfu_rcp, be->tpe.nb_rcp_categories, + sizeof(struct tpe_v1_hfu_v1_rcp_s), + &be->tpe.v2.csu_rcp, be->tpe.nb_rcp_categories, + sizeof(struct tpe_v1_csu_v0_rcp_s))) + return -1; + break; + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +void hw_mod_tpe_free(struct flow_api_backend_s *be) +{ + if (be->tpe.base) { + free(be->tpe.base); + be->tpe.base = NULL; + } +} + +int hw_mod_tpe_reset(struct flow_api_backend_s *be) +{ + int err = 0; + + /* Zero entire cache area */ + ZERO_MOD_CACHE(&be->tpe); + + NT_LOG(DBG, FILTER, "INIT TPE\n"); + err |= hw_mod_tpe_rpp_rcp_flush(be, 0, ALL_ENTRIES); + err |= hw_mod_tpe_ins_rcp_flush(be, 0, ALL_ENTRIES); + err |= hw_mod_tpe_rpl_rcp_flush(be, 0, ALL_ENTRIES); + err |= hw_mod_tpe_rpl_ext_flush(be, 0, ALL_ENTRIES); + err |= hw_mod_tpe_rpl_rpl_flush(be, 0, ALL_ENTRIES); + err |= hw_mod_tpe_cpy_rcp_flush(be, 0, ALL_ENTRIES); + err |= hw_mod_tpe_hfu_rcp_flush(be, 0, ALL_ENTRIES); + err |= hw_mod_tpe_csu_rcp_flush(be, 0, ALL_ENTRIES); + + if (_VER_ == 2) { + err |= hw_mod_tpe_rpp_ifr_rcp_flush(be, 0, ALL_ENTRIES); + err |= hw_mod_tpe_ifr_rcp_flush(be, 0, ALL_ENTRIES); + } + + return err; +} + +/* + * RPP_IFR_RCP + */ + +int hw_mod_tpe_rpp_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->tpe.nb_ifr_categories; + if ((unsigned int)(start_idx + count) > be->tpe.nb_ifr_categories) + return error_index_too_large(__func__); + return be->iface->tpe_rpp_ifr_rcp_flush(be->be_dev, &be->tpe, start_idx, + count); +} + +static int hw_mod_tpe_rpp_ifr_rcp_mod(struct flow_api_backend_s *be, + enum hw_tpe_e field, uint32_t index, + uint32_t *value, int get) +{ + if (index >= be->tpe.nb_ifr_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 2: + switch (field) { + case HW_TPE_IFR_RCP_EN: + get_set(&be->tpe.v2.rpp_ifr_rcp[index].en, value, get); + break; + + case HW_TPE_IFR_RCP_MTU: + get_set(&be->tpe.v2.rpp_ifr_rcp[index].mtu, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_tpe_rpp_ifr_rcp_set(struct flow_api_backend_s *be, + enum hw_tpe_e field, int index, uint32_t value) +{ + return hw_mod_tpe_rpp_ifr_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_tpe_rpp_ifr_rcp_get(struct flow_api_backend_s *be, + enum hw_tpe_e field, int index, uint32_t *value) +{ + return hw_mod_tpe_rpp_ifr_rcp_mod(be, field, index, value, 1); +} + +/* + * RPP_RCP + */ + +int hw_mod_tpe_rpp_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->tpe.nb_rcp_categories; + if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories) + return error_index_too_large(__func__); + return be->iface->tpe_rpp_rcp_flush(be->be_dev, &be->tpe, start_idx, + count); +} + +static int hw_mod_tpe_rpp_rcp_mod(struct flow_api_backend_s *be, + enum hw_tpe_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->tpe.nb_rcp_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 1: + case 2: + switch (field) { + case HW_TPE_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->tpe.v1.rpp_rcp[index], (uint8_t)*value, + sizeof(struct tpe_v1_rpp_v0_rcp_s)); + break; + case HW_TPE_FIND: + rv = find_equal_index(be->tpe.v1.rpp_rcp, + sizeof(struct tpe_v1_rpp_v0_rcp_s), index, *value, + be->tpe.nb_rcp_categories, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_COMPARE: + rv = do_compare_indexes(be->tpe.v1.rpp_rcp, + sizeof(struct tpe_v1_rpp_v0_rcp_s), index, *value, + be->tpe.nb_rcp_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_RPP_RCP_EXP: + get_set(&be->tpe.v1.rpp_rcp[index].exp, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_tpe_rpp_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value) +{ + return hw_mod_tpe_rpp_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_tpe_rpp_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value) +{ + return hw_mod_tpe_rpp_rcp_mod(be, field, index, value, 1); +} + +/* + * IFR_RCP + */ + +int hw_mod_tpe_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->tpe.nb_ifr_categories; + if ((unsigned int)(start_idx + count) > be->tpe.nb_ifr_categories) + return error_index_too_large(__func__); + return be->iface->tpe_ifr_rcp_flush(be->be_dev, &be->tpe, start_idx, + count); +} + +static int hw_mod_tpe_ifr_rcp_mod(struct flow_api_backend_s *be, + enum hw_tpe_e field, uint32_t index, + uint32_t *value, int get) +{ + if (index >= be->tpe.nb_ifr_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 2: + switch (field) { + case HW_TPE_IFR_RCP_EN: + get_set(&be->tpe.v2.ifr_rcp[index].en, value, get); + break; + + case HW_TPE_IFR_RCP_MTU: + get_set(&be->tpe.v2.ifr_rcp[index].mtu, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_tpe_ifr_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value) +{ + return hw_mod_tpe_ifr_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_tpe_ifr_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value) +{ + return hw_mod_tpe_ifr_rcp_mod(be, field, index, value, 1); +} + +/* + * INS_RCP + */ + +int hw_mod_tpe_ins_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->tpe.nb_rcp_categories; + if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories) + return error_index_too_large(__func__); + return be->iface->tpe_ins_rcp_flush(be->be_dev, &be->tpe, start_idx, + count); +} + +static int hw_mod_tpe_ins_rcp_mod(struct flow_api_backend_s *be, + enum hw_tpe_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->tpe.nb_rcp_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 1: + case 2: + switch (field) { + case HW_TPE_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->tpe.v1.ins_rcp[index], (uint8_t)*value, + sizeof(struct tpe_v1_ins_v1_rcp_s)); + break; + case HW_TPE_FIND: + rv = find_equal_index(be->tpe.v1.ins_rcp, + sizeof(struct tpe_v1_ins_v1_rcp_s), index, *value, + be->tpe.nb_rcp_categories, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_COMPARE: + rv = do_compare_indexes(be->tpe.v1.ins_rcp, + sizeof(struct tpe_v1_ins_v1_rcp_s), index, *value, + be->tpe.nb_rcp_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_INS_RCP_DYN: + get_set(&be->tpe.v1.ins_rcp[index].dyn, value, get); + break; + case HW_TPE_INS_RCP_OFS: + get_set(&be->tpe.v1.ins_rcp[index].ofs, value, get); + break; + case HW_TPE_INS_RCP_LEN: + get_set(&be->tpe.v1.ins_rcp[index].len, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 1 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_tpe_ins_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value) +{ + return hw_mod_tpe_ins_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_tpe_ins_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value) +{ + return hw_mod_tpe_ins_rcp_mod(be, field, index, value, 1); +} + +/* + * RPL_RCP + */ + +int hw_mod_tpe_rpl_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->tpe.nb_rcp_categories; + if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories) + return error_index_too_large(__func__); + return be->iface->tpe_rpl_rcp_flush(be->be_dev, &be->tpe, start_idx, + count); +} + +static int hw_mod_tpe_rpl_rcp_mod(struct flow_api_backend_s *be, + enum hw_tpe_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->tpe.nb_rcp_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 1: + case 2: + switch (field) { + case HW_TPE_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->tpe.v1.rpl_rcp[index], (uint8_t)*value, + sizeof(struct tpe_v1_rpl_v2_rcp_s)); + break; + case HW_TPE_FIND: + rv = find_equal_index(be->tpe.v1.rpl_rcp, + sizeof(struct tpe_v1_rpl_v2_rcp_s), index, *value, + be->tpe.nb_rcp_categories, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_COMPARE: + rv = do_compare_indexes(be->tpe.v1.rpl_rcp, + sizeof(struct tpe_v1_rpl_v2_rcp_s), index, *value, + be->tpe.nb_rcp_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_RPL_RCP_DYN: + get_set(&be->tpe.v1.rpl_rcp[index].dyn, value, get); + break; + case HW_TPE_RPL_RCP_OFS: + get_set(&be->tpe.v1.rpl_rcp[index].ofs, value, get); + break; + case HW_TPE_RPL_RCP_LEN: + get_set(&be->tpe.v1.rpl_rcp[index].len, value, get); + break; + case HW_TPE_RPL_RCP_RPL_PTR: + get_set(&be->tpe.v1.rpl_rcp[index].rpl_ptr, value, get); + break; + case HW_TPE_RPL_RCP_EXT_PRIO: + get_set(&be->tpe.v1.rpl_rcp[index].ext_prio, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 1 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_tpe_rpl_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value) +{ + return hw_mod_tpe_rpl_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_tpe_rpl_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value) +{ + return hw_mod_tpe_rpl_rcp_mod(be, field, index, value, 1); +} + +/* + * RPL_EXT + */ + +int hw_mod_tpe_rpl_ext_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->tpe.nb_rpl_ext_categories; + if ((unsigned int)(start_idx + count) > be->tpe.nb_rpl_ext_categories) + return error_index_too_large(__func__); + return be->iface->tpe_rpl_ext_flush(be->be_dev, &be->tpe, start_idx, + count); +} + +static int hw_mod_tpe_rpl_ext_mod(struct flow_api_backend_s *be, + enum hw_tpe_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->tpe.nb_rpl_ext_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 1: + case 2: + switch (field) { + case HW_TPE_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->tpe.v1.rpl_ext[index], (uint8_t)*value, + sizeof(struct tpe_v1_rpl_v2_ext_s)); + break; + case HW_TPE_FIND: + rv = find_equal_index(be->tpe.v1.rpl_ext, + sizeof(struct tpe_v1_rpl_v2_ext_s), index, *value, + be->tpe.nb_rpl_ext_categories, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_COMPARE: + rv = do_compare_indexes(be->tpe.v1.rpl_ext, + sizeof(struct tpe_v1_rpl_v2_ext_s), index, *value, + be->tpe.nb_rpl_ext_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_RPL_EXT_RPL_PTR: + get_set(&be->tpe.v1.rpl_ext[index].rpl_ptr, value, get); + break; + case HW_TPE_RPL_EXT_META_RPL_LEN: + get_set(&be->tpe.v1.rpl_ext[index].meta_rpl_len, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 1 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_tpe_rpl_ext_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value) +{ + return hw_mod_tpe_rpl_ext_mod(be, field, index, &value, 0); +} + +int hw_mod_tpe_rpl_ext_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value) +{ + return hw_mod_tpe_rpl_ext_mod(be, field, index, value, 1); +} + +/* + * RPL_RPL + */ + +int hw_mod_tpe_rpl_rpl_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->tpe.nb_rpl_depth; + if ((unsigned int)(start_idx + count) > be->tpe.nb_rpl_depth) + return error_index_too_large(__func__); + return be->iface->tpe_rpl_rpl_flush(be->be_dev, &be->tpe, start_idx, + count); +} + +static int hw_mod_tpe_rpl_rpl_mod(struct flow_api_backend_s *be, + enum hw_tpe_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->tpe.nb_rpl_depth) + return error_index_too_large(__func__); + switch (_VER_) { + case 1: + case 2: + switch (field) { + case HW_TPE_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->tpe.v1.rpl_rpl[index], (uint8_t)*value, + sizeof(struct tpe_v1_rpl_v2_rpl_s)); + break; + case HW_TPE_FIND: + rv = find_equal_index(be->tpe.v1.rpl_rpl, + sizeof(struct tpe_v1_rpl_v2_rpl_s), index, *value, + be->tpe.nb_rpl_depth, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_COMPARE: + rv = do_compare_indexes(be->tpe.v1.rpl_rpl, + sizeof(struct tpe_v1_rpl_v2_rpl_s), index, *value, + be->tpe.nb_rpl_depth, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_RPL_RPL_VALUE: + if (get) + memcpy(value, be->tpe.v1.rpl_rpl[index].value, + sizeof(uint32_t) * 4); + else + memcpy(be->tpe.v1.rpl_rpl[index].value, value, + sizeof(uint32_t) * 4); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 1 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_tpe_rpl_rpl_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value) +{ + return hw_mod_tpe_rpl_rpl_mod(be, field, index, value, 0); +} + +int hw_mod_tpe_rpl_rpl_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value) +{ + return hw_mod_tpe_rpl_rpl_mod(be, field, index, value, 1); +} + +/* + * CPY_RCP + */ + +int hw_mod_tpe_cpy_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + const uint32_t cpy_size = + be->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories; + if (count == ALL_ENTRIES) + count = cpy_size; + if ((unsigned int)(start_idx + count) > cpy_size) + return error_index_too_large(__func__); + return be->iface->tpe_cpy_rcp_flush(be->be_dev, &be->tpe, start_idx, + count); +} + +static int hw_mod_tpe_cpy_rcp_mod(struct flow_api_backend_s *be, + enum hw_tpe_e field, uint32_t index, + uint32_t *value, int get) +{ + const uint32_t cpy_size = + be->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories; + int rv = 0; + if (index >= cpy_size) + return error_index_too_large(__func__); + switch (_VER_) { + case 1: + case 2: + switch (field) { + case HW_TPE_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->tpe.v1.cpy_rcp[index], (uint8_t)*value, + sizeof(struct tpe_v1_cpy_v1_rcp_s)); + break; + case HW_TPE_FIND: + rv = find_equal_index(be->tpe.v1.cpy_rcp, + sizeof(struct tpe_v1_cpy_v1_rcp_s), index, *value, + cpy_size, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_COMPARE: + rv = do_compare_indexes(be->tpe.v1.cpy_rcp, + sizeof(struct tpe_v1_cpy_v1_rcp_s), index, *value, + cpy_size, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_CPY_RCP_READER_SELECT: + get_set(&be->tpe.v1.cpy_rcp[index].reader_select, value, get); + break; + case HW_TPE_CPY_RCP_DYN: + get_set(&be->tpe.v1.cpy_rcp[index].dyn, value, get); + break; + case HW_TPE_CPY_RCP_OFS: + get_set(&be->tpe.v1.cpy_rcp[index].ofs, value, get); + break; + case HW_TPE_CPY_RCP_LEN: + get_set(&be->tpe.v1.cpy_rcp[index].len, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 1 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_tpe_cpy_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value) +{ + return hw_mod_tpe_cpy_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_tpe_cpy_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value) +{ + return hw_mod_tpe_cpy_rcp_mod(be, field, index, value, 1); +} + +/* + * HFU_RCP + */ + +int hw_mod_tpe_hfu_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->tpe.nb_rcp_categories; + if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories) + return error_index_too_large(__func__); + return be->iface->tpe_hfu_rcp_flush(be->be_dev, &be->tpe, start_idx, + count); +} + +static int hw_mod_tpe_hfu_rcp_mod(struct flow_api_backend_s *be, + enum hw_tpe_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->tpe.nb_rcp_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 1: + case 2: + switch (field) { + case HW_TPE_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->tpe.v1.hfu_rcp[index], (uint8_t)*value, + sizeof(struct tpe_v1_hfu_v1_rcp_s)); + break; + case HW_TPE_FIND: + rv = find_equal_index(be->tpe.v1.hfu_rcp, + sizeof(struct tpe_v1_hfu_v1_rcp_s), index, *value, + be->tpe.nb_rcp_categories, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_COMPARE: + rv = do_compare_indexes(be->tpe.v1.hfu_rcp, + sizeof(struct tpe_v1_hfu_v1_rcp_s), index, *value, + be->tpe.nb_rcp_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_HFU_RCP_LEN_A_WR: + get_set(&be->tpe.v1.hfu_rcp[index].len_a_wr, value, get); + break; + case HW_TPE_HFU_RCP_LEN_A_OUTER_L4_LEN: + get_set(&be->tpe.v1.hfu_rcp[index].len_a_outer_l4_len, + value, get); + break; + case HW_TPE_HFU_RCP_LEN_A_POS_DYN: + get_set(&be->tpe.v1.hfu_rcp[index].len_a_pos_dyn, value, get); + break; + case HW_TPE_HFU_RCP_LEN_A_POS_OFS: + get_set(&be->tpe.v1.hfu_rcp[index].len_a_pos_ofs, value, get); + break; + case HW_TPE_HFU_RCP_LEN_A_ADD_DYN: + get_set(&be->tpe.v1.hfu_rcp[index].len_a_add_dyn, value, get); + break; + case HW_TPE_HFU_RCP_LEN_A_ADD_OFS: + get_set(&be->tpe.v1.hfu_rcp[index].len_a_add_ofs, value, get); + break; + case HW_TPE_HFU_RCP_LEN_A_SUB_DYN: + get_set(&be->tpe.v1.hfu_rcp[index].len_a_sub_dyn, value, get); + break; + + case HW_TPE_HFU_RCP_LEN_B_WR: + get_set(&be->tpe.v1.hfu_rcp[index].len_b_wr, value, get); + break; + case HW_TPE_HFU_RCP_LEN_B_POS_DYN: + get_set(&be->tpe.v1.hfu_rcp[index].len_b_pos_dyn, value, get); + break; + case HW_TPE_HFU_RCP_LEN_B_POS_OFS: + get_set(&be->tpe.v1.hfu_rcp[index].len_b_pos_ofs, value, get); + break; + case HW_TPE_HFU_RCP_LEN_B_ADD_DYN: + get_set(&be->tpe.v1.hfu_rcp[index].len_b_add_dyn, value, get); + break; + case HW_TPE_HFU_RCP_LEN_B_ADD_OFS: + get_set(&be->tpe.v1.hfu_rcp[index].len_b_add_ofs, value, get); + break; + case HW_TPE_HFU_RCP_LEN_B_SUB_DYN: + get_set(&be->tpe.v1.hfu_rcp[index].len_b_sub_dyn, value, get); + break; + + case HW_TPE_HFU_RCP_LEN_C_WR: + get_set(&be->tpe.v1.hfu_rcp[index].len_c_wr, value, get); + break; + case HW_TPE_HFU_RCP_LEN_C_POS_DYN: + get_set(&be->tpe.v1.hfu_rcp[index].len_c_pos_dyn, value, get); + break; + case HW_TPE_HFU_RCP_LEN_C_POS_OFS: + get_set(&be->tpe.v1.hfu_rcp[index].len_c_pos_ofs, value, get); + break; + case HW_TPE_HFU_RCP_LEN_C_ADD_DYN: + get_set(&be->tpe.v1.hfu_rcp[index].len_c_add_dyn, value, get); + break; + case HW_TPE_HFU_RCP_LEN_C_ADD_OFS: + get_set(&be->tpe.v1.hfu_rcp[index].len_c_add_ofs, value, get); + break; + case HW_TPE_HFU_RCP_LEN_C_SUB_DYN: + get_set(&be->tpe.v1.hfu_rcp[index].len_c_sub_dyn, value, get); + break; + + case HW_TPE_HFU_RCP_TTL_WR: + get_set(&be->tpe.v1.hfu_rcp[index].ttl_wr, value, get); + break; + case HW_TPE_HFU_RCP_TTL_POS_DYN: + get_set(&be->tpe.v1.hfu_rcp[index].ttl_pos_dyn, value, get); + break; + case HW_TPE_HFU_RCP_TTL_POS_OFS: + get_set(&be->tpe.v1.hfu_rcp[index].ttl_pos_ofs, value, get); + break; + + case HW_TPE_HFU_RCP_CS_INF: + get_set(&be->tpe.v1.hfu_rcp[index].cs_inf, value, get); + break; + case HW_TPE_HFU_RCP_L3_PRT: + get_set(&be->tpe.v1.hfu_rcp[index].l3_prt, value, get); + break; + case HW_TPE_HFU_RCP_L3_FRAG: + get_set(&be->tpe.v1.hfu_rcp[index].l3_frag, value, get); + break; + case HW_TPE_HFU_RCP_TUNNEL: + get_set(&be->tpe.v1.hfu_rcp[index].tunnel, value, get); + break; + case HW_TPE_HFU_RCP_L4_PRT: + get_set(&be->tpe.v1.hfu_rcp[index].l4_prt, value, get); + break; + case HW_TPE_HFU_RCP_OUTER_L3_OFS: + get_set(&be->tpe.v1.hfu_rcp[index].outer_l3_ofs, value, get); + break; + case HW_TPE_HFU_RCP_OUTER_L4_OFS: + get_set(&be->tpe.v1.hfu_rcp[index].outer_l4_ofs, value, get); + break; + case HW_TPE_HFU_RCP_INNER_L3_OFS: + get_set(&be->tpe.v1.hfu_rcp[index].inner_l3_ofs, value, get); + break; + case HW_TPE_HFU_RCP_INNER_L4_OFS: + get_set(&be->tpe.v1.hfu_rcp[index].inner_l4_ofs, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 1 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_tpe_hfu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value) +{ + return hw_mod_tpe_hfu_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_tpe_hfu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value) +{ + return hw_mod_tpe_hfu_rcp_mod(be, field, index, value, 1); +} + +/* + * CSU_RCP + */ + +int hw_mod_tpe_csu_rcp_flush(struct flow_api_backend_s *be, int start_idx, + int count) +{ + if (count == ALL_ENTRIES) + count = be->tpe.nb_rcp_categories; + if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories) + return error_index_too_large(__func__); + return be->iface->tpe_csu_rcp_flush(be->be_dev, &be->tpe, start_idx, + count); +} + +static int hw_mod_tpe_csu_rcp_mod(struct flow_api_backend_s *be, + enum hw_tpe_e field, uint32_t index, + uint32_t *value, int get) +{ + int rv = 0; + if (index >= be->tpe.nb_rcp_categories) + return error_index_too_large(__func__); + switch (_VER_) { + case 1: + case 2: + switch (field) { + case HW_TPE_PRESET_ALL: + if (get) + return error_unsup_field(__func__); + memset(&be->tpe.v1.csu_rcp[index], (uint8_t)*value, + sizeof(struct tpe_v1_csu_v0_rcp_s)); + break; + case HW_TPE_FIND: + rv = find_equal_index(be->tpe.v1.csu_rcp, + sizeof(struct tpe_v1_csu_v0_rcp_s), index, *value, + be->tpe.nb_rcp_categories, value, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_COMPARE: + rv = do_compare_indexes(be->tpe.v1.csu_rcp, + sizeof(struct tpe_v1_csu_v0_rcp_s), index, *value, + be->tpe.nb_rcp_categories, get, __func__); + if (rv != 0) + return rv; + break; + case HW_TPE_CSU_RCP_OUTER_L3_CMD: + get_set(&be->tpe.v1.csu_rcp[index].ol3_cmd, value, get); + break; + case HW_TPE_CSU_RCP_OUTER_L4_CMD: + get_set(&be->tpe.v1.csu_rcp[index].ol4_cmd, value, get); + break; + case HW_TPE_CSU_RCP_INNER_L3_CMD: + get_set(&be->tpe.v1.csu_rcp[index].il3_cmd, value, get); + break; + case HW_TPE_CSU_RCP_INNER_L4_CMD: + get_set(&be->tpe.v1.csu_rcp[index].il4_cmd, value, get); + break; + + default: + return error_unsup_field(__func__); + } + break; + /* end case 1 */ + default: + return error_unsup_ver(__func__, _MOD_, _VER_); + } + + return 0; +} + +int hw_mod_tpe_csu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t value) +{ + return hw_mod_tpe_csu_rcp_mod(be, field, index, &value, 0); +} + +int hw_mod_tpe_csu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field, + int index, uint32_t *value) +{ + return hw_mod_tpe_csu_rcp_mod(be, field, index, value, 1); +} diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h new file mode 100644 index 0000000000..dacd819659 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_TPE_V1_H_ +#define _HW_MOD_TPE_V1_H_ + +struct tpe_v1_rpp_v0_rcp_s { + uint32_t exp; +}; + +struct tpe_v1_ins_v1_rcp_s { + uint32_t dyn; + uint32_t ofs; + uint32_t len; +}; + +struct tpe_v1_rpl_v2_rcp_s { + uint32_t dyn; + uint32_t ofs; + uint32_t len; + uint32_t rpl_ptr; + uint32_t ext_prio; +}; + +struct tpe_v1_rpl_v2_ext_s { + uint32_t rpl_ptr; + uint32_t meta_rpl_len; /* SW only */ +}; + +struct tpe_v1_rpl_v2_rpl_s { + uint32_t value[4]; +}; + +struct tpe_v1_cpy_v1_rcp_s { + uint32_t reader_select; + uint32_t dyn; + uint32_t ofs; + uint32_t len; +}; + +struct tpe_v1_hfu_v1_rcp_s { + uint32_t len_a_wr; + uint32_t len_a_outer_l4_len; + uint32_t len_a_pos_dyn; + uint32_t len_a_pos_ofs; + uint32_t len_a_add_dyn; + uint32_t len_a_add_ofs; + uint32_t len_a_sub_dyn; + + uint32_t len_b_wr; + uint32_t len_b_pos_dyn; + uint32_t len_b_pos_ofs; + uint32_t len_b_add_dyn; + uint32_t len_b_add_ofs; + uint32_t len_b_sub_dyn; + + uint32_t len_c_wr; + uint32_t len_c_pos_dyn; + uint32_t len_c_pos_ofs; + uint32_t len_c_add_dyn; + uint32_t len_c_add_ofs; + uint32_t len_c_sub_dyn; + + uint32_t ttl_wr; + uint32_t ttl_pos_dyn; + uint32_t ttl_pos_ofs; + + uint32_t cs_inf; + uint32_t l3_prt; + uint32_t l3_frag; + uint32_t tunnel; + uint32_t l4_prt; + uint32_t outer_l3_ofs; + uint32_t outer_l4_ofs; + uint32_t inner_l3_ofs; + uint32_t inner_l4_ofs; +}; + +struct tpe_v1_csu_v0_rcp_s { + uint32_t ol3_cmd; + uint32_t ol4_cmd; + uint32_t il3_cmd; + uint32_t il4_cmd; +}; + +struct hw_mod_tpe_v1_s { + struct tpe_v1_rpp_v0_rcp_s *rpp_rcp; + + struct tpe_v1_ins_v1_rcp_s *ins_rcp; + + struct tpe_v1_rpl_v2_rcp_s *rpl_rcp; + struct tpe_v1_rpl_v2_ext_s *rpl_ext; + struct tpe_v1_rpl_v2_rpl_s *rpl_rpl; + + struct tpe_v1_cpy_v1_rcp_s *cpy_rcp; + + struct tpe_v1_hfu_v1_rcp_s *hfu_rcp; + + struct tpe_v1_csu_v0_rcp_s *csu_rcp; +}; + +#endif /* _HW_MOD_TPE_V1_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h new file mode 100644 index 0000000000..c56cad8d89 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _HW_MOD_TPE_V2_H_ +#define _HW_MOD_TPE_V2_H_ + +struct tpe_v2_rpp_v1_ifr_rcp_s { + uint32_t en; + uint32_t mtu; +}; + +struct tpe_v2_ifr_v1_rcp_s { + uint32_t en; + uint32_t mtu; +}; + +struct hw_mod_tpe_v2_s { + struct tpe_v1_rpp_v0_rcp_s *rpp_rcp; + + struct tpe_v1_ins_v1_rcp_s *ins_rcp; + + struct tpe_v1_rpl_v2_rcp_s *rpl_rcp; + struct tpe_v1_rpl_v2_ext_s *rpl_ext; + struct tpe_v1_rpl_v2_rpl_s *rpl_rpl; + + struct tpe_v1_cpy_v1_rcp_s *cpy_rcp; + + struct tpe_v1_hfu_v1_rcp_s *hfu_rcp; + + struct tpe_v1_csu_v0_rcp_s *csu_rcp; + + struct tpe_v2_rpp_v1_ifr_rcp_s *rpp_ifr_rcp; + struct tpe_v2_ifr_v1_rcp_s *ifr_rcp; +}; + +#endif /* _HW_MOD_TPE_V2_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h b/drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h new file mode 100644 index 0000000000..eae8f176a8 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h @@ -0,0 +1,697 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _STREAM_BINARY_FLOW_API_H_ +#define _STREAM_BINARY_FLOW_API_H_ + +#include /* uint16_t, uint32_t, uint64_t */ +#include /* snprintf */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint16_t be16_t; /* 16-bit big-endian */ +typedef uint32_t be32_t; /* 32-bit big-endian */ +typedef uint64_t be64_t; /* 64-bit big-endian */ + +/* + * Flow frontend for binary programming interface + */ + +#define FLOW_MAX_QUEUES 128 + +#define RAW_ENCAP_DECAP_ELEMS_MAX 16 + +/* + * Partial flow mark and special flow marks + */ +#define FLOW_MARK_LACP 0x7fffffff +#define FLOW_MARK_MAX 0x7ffffffe +/* + * Flow eth dev profile determines how the FPGA module resources are + * managed and what features are available + */ +enum flow_eth_dev_profile { + FLOW_ETH_DEV_PROFILE_VSWITCH = 0, + FLOW_ETH_DEV_PROFILE_INLINE = 1, +}; + +/* + * Flow rule attributes + */ +struct flow_attr { + uint32_t group; /* Priority group. */ + uint32_t priority; /* Rule priority level within group. */ + uint16_t forced_vlan_vid; /* Forced VLAN VID that filter must match. Ignored if 0. */ + uint8_t caller_id; /* Unique ID of caller application. */ +}; + +struct flow_queue_id_s { + int id; + int hw_id; +}; + +/* NT Private rte flow items. */ + +/* NT Private rte flow actions. */ + +enum flow_elem_type { + FLOW_ELEM_TYPE_END, + FLOW_ELEM_TYPE_ANY, + FLOW_ELEM_TYPE_ETH, + FLOW_ELEM_TYPE_VLAN, + FLOW_ELEM_TYPE_IPV4, + FLOW_ELEM_TYPE_IPV6, + FLOW_ELEM_TYPE_SCTP, + FLOW_ELEM_TYPE_TCP, + FLOW_ELEM_TYPE_UDP, + FLOW_ELEM_TYPE_ICMP, + FLOW_ELEM_TYPE_VXLAN, + FLOW_ELEM_TYPE_GTP, + FLOW_ELEM_TYPE_PORT_ID, + FLOW_ELEM_TYPE_TAG, + FLOW_ELEM_TYPE_VOID, + + /* + * Not associated with a RTE_ITEM..., but rather an restoration API device specific + * extension + */ + FLOW_ELEM_TYPE_TUNNEL +}; + +enum flow_action_type { /* conf structure */ + FLOW_ACTION_TYPE_END, /* -none- : End tag for action list */ + FLOW_ACTION_TYPE_POP_VLAN, /* -none- : Pops outer vlan tag */ + FLOW_ACTION_TYPE_PUSH_VLAN, /* struct flow_action_push_vlan : Push VLAN TAG */ + FLOW_ACTION_TYPE_SET_VLAN_VID, /* struct flow_action_set_vlan_vid : Set VLAN VID */ + FLOW_ACTION_TYPE_SET_VLAN_PCP, /* struct flow_action_set_vlan_pcp : Set VLAN PCP */ + /* -none- : Decapsulate outer most VXLAN tunnel from matched flow */ + FLOW_ACTION_TYPE_VXLAN_DECAP, + FLOW_ACTION_TYPE_VXLAN_ENCAP, /* struct flow_action_vxlan_encap */ + FLOW_ACTION_TYPE_DROP, /* -none- : Drop packets of this flow */ + FLOW_ACTION_TYPE_COUNT, /* struct flow_action_count : Used for "query" flow function */ + FLOW_ACTION_TYPE_MARK, /* struct flow_action_mark : Used to tag a flow in HW with a MARK */ + FLOW_ACTION_TYPE_SET_TAG, /* struct flow_action_tag : Used to tag a flow in HW with a TAG */ + /* struct flow_action_port_id : Destination port ID - HW port ID */ + FLOW_ACTION_TYPE_PORT_ID, + FLOW_ACTION_TYPE_RSS, /* struct flow_action_rss : */ + FLOW_ACTION_TYPE_QUEUE, /* struct flow_action_queue : */ + FLOW_ACTION_TYPE_JUMP, /* struct flow_action_jump : */ + /* struct flow_action_meter : Used to set MBR record ids in FLM learn records */ + FLOW_ACTION_TYPE_METER, + FLOW_ACTION_TYPE_RAW_ENCAP, /* struct flow_action_raw_encap : */ + FLOW_ACTION_TYPE_RAW_DECAP, /* struct flow_action_raw_decap : */ + FLOW_ACTION_TYPE_MODIFY_FIELD, /* struct flow_action_modify_field : */ + + /* + * -none- : not associated with a RTE_ACTION..., but rather an restoration API device + * specific extension + */ + FLOW_ACTION_TYPE_TUNNEL_SET +}; + +#pragma pack(1) +struct ether_addr_s { + uint8_t addr_b[6]; +}; + +#pragma pack() + +static inline void flow_ether_format_addr(char *buf, uint16_t size, + const struct ether_addr_s *eth_addr) +{ + snprintf(buf, size, "%02X:%02X:%02X:%02X:%02X:%02X", + eth_addr->addr_b[0], eth_addr->addr_b[1], eth_addr->addr_b[2], + eth_addr->addr_b[3], eth_addr->addr_b[4], eth_addr->addr_b[5]); +} + +/* + * IPv4 Header + */ +#pragma pack(1) +struct ipv4_hdr_s { + uint8_t version_ihl; + uint8_t tos; + be16_t length; + be16_t id; + be16_t frag_offset; + uint8_t ttl; + uint8_t next_proto_id; + be16_t hdr_csum; + be32_t src_ip; + be32_t dst_ip; +}; + +#pragma pack() +/* + * IPv6 Header + */ +#pragma pack(1) +struct ipv6_hdr_s { + be32_t vtc_flow; /* IP version, traffic class & flow label */ + be16_t payload_len; /* IP packet length - includes ip header */ + uint8_t proto; + uint8_t hop_limits; + uint8_t src_addr[16]; + uint8_t dst_addr[16]; +}; + +#pragma pack() + +/* + * SCTP Header + */ +#pragma pack(1) +struct sctp_hdr_s { + be16_t src_port; + be16_t dst_port; + be32_t tag; /* Validation tag */ + be32_t cksum; +}; + +#pragma pack() + +/* + * TCP Header + */ +#pragma pack(1) +struct tcp_hdr_s { + be16_t src_port; + be16_t dst_port; + be32_t sent_seq; + be32_t recv_ack; + uint8_t data_off; + uint8_t tcp_flags; + be16_t rx_win; + be16_t cksum; + be16_t tcp_urp; +}; + +#pragma pack() + +/* + * UDP Header + */ +#pragma pack(1) +struct udp_hdr_s { + be16_t src_port; + be16_t dst_port; + be16_t len; + be16_t cksum; +}; + +#pragma pack() + +/* + * ICMP Header + */ +#pragma pack(1) +struct icmp_hdr_s { + uint8_t type; + uint8_t code; + be16_t cksum; + be16_t ident; + be16_t seq_nb; +}; + +#pragma pack() +/* + * FLOW_ELEM_TYPE_ETH specification + */ +#pragma pack(1) +struct flow_elem_eth { + struct ether_addr_s d_addr; /* DMAC */ + struct ether_addr_s s_addr; /* SMAC */ + be16_t ether_type; /* Frame type */ +}; + +#pragma pack() + +/* + * FLOW_ELEM_TYPE_VLAN specification + */ +#pragma pack(1) +struct flow_elem_vlan { + be16_t tci; /* Tag control information */ + be16_t inner_type; /* Inner EtherType or TPID */ +}; + +#pragma pack() + +/* + * FLOW_ELEM_TYPE_IPV4 specification + */ +struct flow_elem_ipv4 { + struct ipv4_hdr_s hdr; +}; + +/* + * FLOW_ELEM_TYPE_IPV6 specification + */ +struct flow_elem_ipv6 { + struct ipv6_hdr_s hdr; +}; + +/* + * FLOW_ELEM_TYPE_SCTP specification + */ +struct flow_elem_sctp { + struct sctp_hdr_s hdr; +}; + +/* + * FLOW_ELEM_TYPE_TCP specification + */ +struct flow_elem_tcp { + struct tcp_hdr_s hdr; +}; + +/* + * FLOW_ELEM_TYPE_UDP specification + */ +struct flow_elem_udp { + struct udp_hdr_s hdr; +}; + +/* + * FLOW_ELEM_TYPE_ICMP specification + */ +struct flow_elem_icmp { + struct icmp_hdr_s hdr; +}; + +/* + * FLOW_ELEM_TYPE_GTP specification + */ +#pragma pack(1) +struct flow_elem_gtp { + uint8_t v_pt_rsv_flags; + uint8_t msg_type; + be16_t msg_len; + be32_t teid; +}; + +#pragma pack() + +/* + * FLOW_ELEM_TYPE_VXLAN specification (RFC 7348) + */ +#pragma pack(1) +struct flow_elem_vxlan { + uint8_t flags; /* Normally 0x08 (I flag) */ + uint8_t rsvd0[3]; + uint8_t vni[3]; + uint8_t rsvd1; +}; + +#pragma pack() +/* + * FLOW_ELEM_TYPE_PORT_ID specification + */ +struct flow_elem_port_id { + uint32_t id; /* HW port no */ +}; + +/* + * FLOW_ELEM_TYPE_TAG specification + */ +struct flow_elem_tag { + uint32_t data; + uint8_t index; +}; + +/* + * FLOW_ELEM_TYPE_ANY specification + */ +struct flow_elem_any { + uint32_t num; /**< Number of layers covered. */ +}; + +struct flow_elem { + enum flow_elem_type type; /* element type */ + const void *spec; /* Pointer to element specification structure */ + const void *mask; /* Bitmask applied to spec - same type */ +}; + +/* + * FLOW_ACTION_TYPE_RSS + */ +enum flow_hash_function { + FLOW_HASH_FUNCTION_DEFAULT = 0, + FLOW_HASH_FUNCTION_TOEPLITZ, /* Unsupported in current supported FPGA */ + FLOW_HASH_FUNCTION_SIMPLE_XOR /* Simple XOR - not supported */ +}; + +struct flow_action_rss { + enum flow_hash_function func; + uint32_t level; /* only level 0 supported */ + /* Specific RSS hash types (see like DPDK ETH_RSS_*) */ + uint64_t types; + uint32_t key_len; /* Not supported yet - Hash key length in bytes */ + uint32_t queue_num; /* Number of entries in queue */ + const uint8_t *key; /* Not supported yet - Hash key */ + const uint16_t *queue; /* Queue indices to use */ +}; + +/* + * FLOW_ACTION_TYPE_PUSH_VLAN + * Push a new vlan TAG + */ +struct flow_action_push_vlan { + be16_t ethertype; +}; + +/* + * FLOW_ACTION_TYPE_SET_VLAN_VID + */ +struct flow_action_set_vlan_vid { + be16_t vlan_vid; +}; + +/* + * FLOW_ACTION_TYPE_SET_VLAN_PCP + */ +struct flow_action_set_vlan_pcp { + uint8_t vlan_pcp; /* < VLAN priority. */ +}; + +/* + * FLOW_ACTION_TYPE_VXLAN_ENCAP specification + * Valid flow definition: + * + * - ETH / IPV4 / UDP / VXLAN / END + * - ETH / IPV6 / UDP / VXLAN / END + * - ETH / VLAN / IPV4 / UDP / VXLAN / END + * + */ +struct flow_action_vxlan_encap { + /* Encapsulating vxlan tunnel definition */ + struct flow_elem *vxlan_tunnel; +}; + +/* + * FLOW_ACTION_TYPE_COUNT specification + */ +struct flow_action_count { + uint32_t id; /* HW port no */ +}; + +/* + * FLOW_ACTION_TYPE_COUNT specification (query) + */ +struct flow_query_count { + uint32_t reset : 1; + uint32_t hits_set : 1; + uint32_t bytes_set : 1; + + uint32_t tcp_flags : 9; + + uint32_t reserved : 20; + uint64_t hits; + uint64_t bytes; +}; + +/* + * FLOW_ACTION_TYPE_MARK specification + */ +struct flow_action_mark { + uint32_t id; /* mark flow with this ID */ +}; + +/* + * FLOW_ACTION_TYPE_TAG specification + */ +struct flow_action_tag { + uint32_t data; /* tag flow with this value */ + uint32_t mask; /* bit-mask applied to "data" */ + uint8_t index; /* index of tag to set */ +}; + +/* + * FLOW_ACTION_TYPE_PORT_ID specification + */ +struct flow_action_port_id { + uint32_t rte_flags; /* not used but to be binary compatible with rte flow */ + uint32_t id; +}; + +/* + * FLOW_ACTION_TYPE_QUEUE + */ +struct flow_action_queue { + uint16_t index; +}; + +/* + * FLOW_ACTION_TYPE_JUMP + */ +struct flow_action_jump { + uint32_t group; +}; + +/* + * FLOW_ACTION_TYPE_METER + */ +struct flow_action_meter { + uint32_t mtr_id; +}; + +/* + * FLOW_ACTION_TYPE_RAW_ENCAP + */ +struct flow_action_raw_encap { + uint8_t *data; + uint8_t *preserve; + size_t size; + struct flow_elem items[RAW_ENCAP_DECAP_ELEMS_MAX]; + int item_count; +}; + +/* + * FLOW_ACTION_TYPE_RAW_DECAP + */ +struct flow_action_raw_decap { + uint8_t *data; + size_t size; + struct flow_elem items[RAW_ENCAP_DECAP_ELEMS_MAX]; + int item_count; +}; + +/* + * Field IDs for MODIFY_FIELD action. + */ +enum flow_field_id { + FLOW_FIELD_START = 0, /* Start of a packet. */ + FLOW_FIELD_MAC_DST, /* Destination MAC Address. */ + FLOW_FIELD_MAC_SRC, /* Source MAC Address. */ + FLOW_FIELD_VLAN_TYPE, /* 802.1Q Tag Identifier. */ + FLOW_FIELD_VLAN_ID, /* 802.1Q VLAN Identifier. */ + FLOW_FIELD_MAC_TYPE, /* EtherType. */ + FLOW_FIELD_IPV4_DSCP, /* IPv4 DSCP. */ + FLOW_FIELD_IPV4_TTL, /* IPv4 Time To Live. */ + FLOW_FIELD_IPV4_SRC, /* IPv4 Source Address. */ + FLOW_FIELD_IPV4_DST, /* IPv4 Destination Address. */ + FLOW_FIELD_IPV6_DSCP, /* IPv6 DSCP. */ + FLOW_FIELD_IPV6_HOPLIMIT, /* IPv6 Hop Limit. */ + FLOW_FIELD_IPV6_SRC, /* IPv6 Source Address. */ + FLOW_FIELD_IPV6_DST, /* IPv6 Destination Address. */ + FLOW_FIELD_TCP_PORT_SRC, /* TCP Source Port Number. */ + FLOW_FIELD_TCP_PORT_DST, /* TCP Destination Port Number. */ + FLOW_FIELD_TCP_SEQ_NUM, /* TCP Sequence Number. */ + FLOW_FIELD_TCP_ACK_NUM, /* TCP Acknowledgment Number. */ + FLOW_FIELD_TCP_FLAGS, /* TCP Flags. */ + FLOW_FIELD_UDP_PORT_SRC, /* UDP Source Port Number. */ + FLOW_FIELD_UDP_PORT_DST, /* UDP Destination Port Number. */ + FLOW_FIELD_VXLAN_VNI, /* VXLAN Network Identifier. */ + FLOW_FIELD_GENEVE_VNI, /* GENEVE Network Identifier. */ + FLOW_FIELD_GTP_TEID, /* GTP Tunnel Endpoint Identifier. */ + FLOW_FIELD_TAG, /* Tag value. */ + FLOW_FIELD_MARK, /* Mark value. */ + FLOW_FIELD_META, /* Metadata value. */ + FLOW_FIELD_POINTER, /* Memory pointer. */ + FLOW_FIELD_VALUE, /* Immediate value. */ + FLOW_FIELD_IPV4_ECN, /* IPv4 ECN. */ + FLOW_FIELD_IPV6_ECN, /* IPv6 ECN. */ + FLOW_FIELD_GTP_PSC_QFI, /* GTP QFI. */ + FLOW_FIELD_METER_COLOR, /* Meter color marker. */ +}; + +/* + * Field description for MODIFY_FIELD action. + */ +struct flow_action_modify_data { + enum flow_field_id field; /* Field or memory type ID. */ + union { + struct { + /* Encapsulation level or tag index. */ + uint32_t level; + /* Number of bits to skip from a field. */ + uint32_t offset; + }; + /* + * Immediate value for FLOW_FIELD_VALUE, presented in the + * same byte order and length as in relevant rte_flow_item_xxx. + */ + uint8_t value[16]; + /* + * Memory address for FLOW_FIELD_POINTER, memory layout + * should be the same as for relevant field in the + * rte_flow_item_xxx structure. + */ + void *pvalue; + }; +}; + +/* + * Operation types for MODIFY_FIELD action. + */ +enum flow_modify_op { + FLOW_MODIFY_SET = 0, + FLOW_MODIFY_ADD, + FLOW_MODIFY_SUB, +}; + +/* + * FLOW_ACTION_TYPE_MODIFY_FIELD + */ +struct flow_action_modify_field { + enum flow_modify_op operation; + struct flow_action_modify_data dst; + struct flow_action_modify_data src; + uint32_t width; +}; + +struct flow_action { + enum flow_action_type type; + const void *conf; +}; + +enum flow_error_e { FLOW_ERROR_NONE, FLOW_ERROR_SUCCESS, FLOW_ERROR_GENERAL }; + +struct flow_error { + enum flow_error_e type; + const char *message; +}; + +enum flow_lag_cmd { + FLOW_LAG_SET_ENTRY, + FLOW_LAG_SET_ALL, + FLOW_LAG_SET_BALANCE, +}; + +/* + * Tunnel definition for DPDK RTE tunnel helper function support + */ +struct tunnel_cfg_s { + union { + struct { + uint32_t src_ip; /* BE */ + uint32_t dst_ip; /* BE */ + } v4; + struct { + uint8_t src_ip[16]; + uint8_t dst_ip[16]; + } v6; + struct { + uint64_t src_ip[2]; + uint64_t dst_ip[2]; + } v6_long; + }; + int ipversion; + uint16_t s_port; /* BE */ + uint16_t d_port; /* BE */ + int tun_type; +}; + +struct flow_eth_dev; /* port device */ +struct flow_handle; + +/* + * Device Management API + */ +int flow_reset_nic_dev(uint8_t adapter_no); + +struct flow_eth_dev *flow_get_eth_dev(uint8_t adapter_no, uint8_t hw_port_no, + uint32_t port_id, int alloc_queues, + struct flow_queue_id_s queue_ids[], + int *rss_target_id, + enum flow_eth_dev_profile flow_profile, + uint32_t exception_path); + +int flow_eth_dev_add_queue(struct flow_eth_dev *eth_dev, + struct flow_queue_id_s *queue_id); + +int flow_delete_eth_dev(struct flow_eth_dev *eth_dev); + +int flow_get_tunnel_definition(struct tunnel_cfg_s *tun, uint32_t flow_stat_id, + uint8_t vport); + +/* + * NT Flow API + */ +int flow_validate(struct flow_eth_dev *dev, const struct flow_elem item[], + const struct flow_action action[], struct flow_error *error); + +struct flow_handle *flow_create(struct flow_eth_dev *dev, + const struct flow_attr *attr, + const struct flow_elem item[], + const struct flow_action action[], + struct flow_error *error); + +int flow_destroy(struct flow_eth_dev *dev, struct flow_handle *flow, + struct flow_error *error); + +int flow_flush(struct flow_eth_dev *dev, struct flow_error *error); + +int flow_query(struct flow_eth_dev *dev, struct flow_handle *flow, + const struct flow_action *action, void **data, uint32_t *length, + struct flow_error *error); + +/* + * NT Flow FLM Meter API + */ +int flow_mtr_supported(struct flow_eth_dev *dev); + +uint64_t flow_mtr_meter_policy_n_max(void); + +int flow_mtr_set_profile(struct flow_eth_dev *dev, uint32_t profile_id, + uint64_t bucket_rate_a, uint64_t bucket_size_a, + uint64_t bucket_rate_b, uint64_t bucket_size_b); + +int flow_mtr_set_policy(struct flow_eth_dev *dev, uint32_t policy_id, int drop); + +int flow_mtr_create_meter(struct flow_eth_dev *dev, uint32_t mtr_id, + uint32_t profile_id, uint32_t policy_id, + uint64_t stats_mask); + +int flow_mtr_destroy_meter(struct flow_eth_dev *dev, uint32_t mtr_id); + +int flm_mtr_adjust_stats(struct flow_eth_dev *dev, uint32_t mtr_id, + uint32_t adjust_value); + +uint32_t flow_mtr_meters_supported(void); + +uint32_t flm_mtr_update_stats(struct flow_eth_dev *dev); +void flm_mtr_read_stats(struct flow_eth_dev *dev, uint32_t id, + uint64_t *stats_mask, uint64_t *green_pkt, + uint64_t *green_bytes, int clear); + +/* + * Config API + */ +int lag_set_port_group(uint8_t adapter_no, uint32_t port_mask); + +int lag_set_port_block(uint8_t adapter_no, uint32_t port_mask); + +int lag_set_config(uint8_t adapter_no, enum flow_lag_cmd cmd, uint32_t index, + uint32_t value); + +int flow_set_mtu_inline(struct flow_eth_dev *dev, uint32_t port, uint16_t mtu); + +#ifdef __cplusplus +} +#endif + +#endif /* _STREAM_BINARY_FLOW_API_H_ */ From patchwork Mon Aug 21 13:54:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mykola Kostenok X-Patchwork-Id: 130581 X-Patchwork-Delegate: thomas@monjalon.net 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 2173B430C1; Mon, 21 Aug 2023 15:55:09 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id BEF3943266; Mon, 21 Aug 2023 15:54:44 +0200 (CEST) Received: from egress-ip33a.ess.de.barracuda.com (egress-ip33a.ess.de.barracuda.com [18.185.115.192]) by mails.dpdk.org (Postfix) with ESMTP id 1E72F40DF5 for ; Mon, 21 Aug 2023 15:54:40 +0200 (CEST) Received: from EUR03-AM7-obe.outbound.protection.outlook.com (mail-am7eur03lp2240.outbound.protection.outlook.com [104.47.51.240]) by mx-outbound13-194.eu-central-1a.ess.aws.cudaops.com (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 21 Aug 2023 13:54:38 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=gKiXJ2ad+ZO1h31Ed0ctAMRW84uD5UXvPNfPG5Op3YpffQefPg7lKsr/BLHSQt/naNymdifle+Wlym6f4mYANADwVoYDfpYdXrsNWC4jpkRDom2yyGXe5gTlivpBOtKSMboRg5CXjTKirNZo14+WzYV7qvC1iliDLxbbIMOwWVV4by9FtKEtrL/cVEeu6xI5QyxJ1WdLw8bKOghXYop+yj1e9ja0Z+L3qfb15Hk2T8C0X+pV//UpU0a93EyZIJBTUgpuUlMMK2gWlaGCdAa6boIsDqP2KYG2TyOHolHT9KFsY0y+Ei+fLs4EtzME133IShEOHObL/K68RzHDZ0HK0w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=uhkXwXgFU8z/lqBQpQlGdODYShTVl2PX6nma0/iZZUg=; b=gLEPQqmJJxBgSUIzUpfVMx9OZWT2Yzx6PFisKYQ3TsHs3ifjSDIshCfPK0gtluB51WaIUkZ7O46Ypvh/F/cul6Vz7qw3P1Uc0vPBJNXJVaU4oMykAvP79SIB8T/x937s7HtO4TbDA5d9nETyPhAsPAGsT7JYy1KJS6wIbBR0rLSFQe8LXV6XDuPtwVwQZOTsjHvhPXdEZOZ1d+N8NlOljw8/zL9YBxtO6mgBlPw6bd4NhH8p1rmZfbaZar1MyY950F1hW1wP7aaHdj9GPqvSHNDFsjGhjvIgOxhZrABnhtdSrzv2gMG68VM9k68bVTKCKRK/QLwFzNFtJT5kVZu+BQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=fail (sender ip is 178.72.21.4) smtp.rcpttodomain=dpdk.org smtp.mailfrom=napatech.com; dmarc=fail (p=none sp=none pct=100) action=none header.from=napatech.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=napatech.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=uhkXwXgFU8z/lqBQpQlGdODYShTVl2PX6nma0/iZZUg=; b=gF93EBWQzl55swzt4FNORi9COe/wURluj73X0es0/xjaXX8e82/eIsFQrpglT/oE3GF8JklZDExpGL/xEW/gIX3fIyMKVM7t/vSpo6V/ZTE5X6lDQJ++6ZSVZmnvCrV06BtFUavOAwZpPOBEubHIGAoQNqqC1D2iGRvis2/Nqyk= Received: from DB8PR04CA0021.eurprd04.prod.outlook.com (2603:10a6:10:110::31) by DBAP190MB0951.EURP190.PROD.OUTLOOK.COM (2603:10a6:10:1a3::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.20; Mon, 21 Aug 2023 13:54:30 +0000 Received: from DU2PEPF0001E9C5.eurprd03.prod.outlook.com (2603:10a6:10:110:cafe::c9) by DB8PR04CA0021.outlook.office365.com (2603:10a6:10:110::31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.20 via Frontend Transport; Mon, 21 Aug 2023 13:54:30 +0000 X-MS-Exchange-Authentication-Results: spf=fail (sender IP is 178.72.21.4) smtp.mailfrom=napatech.com; dkim=none (message not signed) header.d=none;dmarc=fail action=none header.from=napatech.com; Received-SPF: Fail (protection.outlook.com: domain of napatech.com does not designate 178.72.21.4 as permitted sender) receiver=protection.outlook.com; client-ip=178.72.21.4; helo=localhost.localdomain.com; Received: from localhost.localdomain.com (178.72.21.4) by DU2PEPF0001E9C5.mail.protection.outlook.com (10.167.8.74) with Microsoft SMTP Server id 15.20.6699.14 via Frontend Transport; Mon, 21 Aug 2023 13:54:30 +0000 From: Mykola Kostenok To: dev@dpdk.org, mko-plv@napatech.com Cc: ckm@napatech.com Subject: [PATCH v6 6/8] net/ntnic: adds flow logic Date: Mon, 21 Aug 2023 15:54:24 +0200 Message-Id: <20230821135426.1478754-6-mko-plv@napatech.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20230821135426.1478754-1-mko-plv@napatech.com> References: <20230816132552.2483752-1-mko-plv@napatech.com> <20230821135426.1478754-1-mko-plv@napatech.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU2PEPF0001E9C5:EE_|DBAP190MB0951:EE_ X-MS-Office365-Filtering-Correlation-Id: b942c229-c85f-4a88-15e2-08dba24e244a X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: HowQpRjmUKuAjVJMeBQIyCFJ92LZeMSeoFyqRZavust3XRv+6n9Ll+Gq0/dV3r0sIoYHgwxGbX5UUcmLgiCe9oG1St9dSJ+t7+/y7NQW69tga1w26MCqwIuLu5vpTSTJQtRkRWY0Jqir75qdilb7VA6ealIgagAPZmsRAfj1lvHzyqiD7NajO9laNU64NAeTJw59cICxNxqPVcV/Enb7SJOZbg5PdrsWjx1g8tLqv9Mio5nw9QCS1COBpquw3cMlb8wWrxkOvgrndZybneL8uHBXSMV+EtBNIjImvfcZDFP6CyY5P+839fSzobg3yziQLRaEh6251rZQnp7jocnn0B210h5aCv/+jBE4QiA3H2oDXsYspaw9bIE42ixlUDWox132wPVUr5Hob/3W8kol6mhefyf20VRWn7p8Tywh9abPUJ6s43CSF6zU8JstNbPD7XGbtAFPMlKvU02SqcCWhd9a07/n2EReW24BjzUhzf/VzOeNEujuNBM0ul4ZjQQ+5HDUvxZK6SAPHusSPi/jSJIoIow2r7QneggkklkVb85iNgbw7dQmSUAC4oTQEFrNrBum0ClxYw8qEk32Oq1Gqo7tQvAC8VuBeUAmSTPPDuL+Z0YW4lR/Dg9FChy1YFzhozy+Qa/eWWVo3uRJuXt/FbKaeKI/fgn1yQFAc0V3CzyyCamfB88mxiZ2XfWM4sKW+pUtKbxuo1Pgm20Guv4C/bmOpCNA9JgP4IzH2Z+Rn6HBzVySWtmApzoosS+aMjXvyW0bvAUzBXuqSjAtAVsquKD5vrXZqrTy/R+U+DXMujg= X-Forefront-Antispam-Report: CIP:178.72.21.4; CTRY:DK; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:localhost.localdomain.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230031)(6069001)(39830400003)(136003)(396003)(376002)(346002)(186009)(1800799009)(451199024)(82310400011)(46966006)(36840700001)(36756003)(40480700001)(86362001)(9316004)(356005)(81166007)(316002)(478600001)(70586007)(70206006)(36736006)(41300700001)(6512007)(6486002)(34020700004)(6666004)(26005)(36860700001)(6506007)(2616005)(107886003)(336012)(956004)(8676002)(1076003)(4326008)(8936002)(118246002)(5660300002)(47076005)(2906002)(30864003)(83380400001)(36900700001)(559001)(579004)(309714004); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: ldWLss1ErD7GyC1eVu2pMZF4QRdSvhnHwibAQNj0KA/sK9b6VKuUOgsaLTC1i9OWXnbJrMdrdZVma00fSaf0Uwdkx/OU9EwLz3z77BIq+ECHW3oA67i5aH8og3yemsXqp3DQKZ5Gaq4/dQsInSJ+s1KBi9oeOCrffKx3wppbw/ZJtzdHKdj/5Ii3Dkj2DgYpGQJawhZcQdhgIjVqbK8TlfzZbEAyDco9X+wgKMSTVrAM2muHP0kQvPDsHhxuA2qBzjWnLHRvkIDfCZKrHTbhNxfv5P559RTjXTeOKi1reBT1e6QhfB/sAkX6mFscEZrHnrMq4qao3EaWY6IYHKmYJjHM+sgnOkEiFnvZlTDGDSPF9ewa/eXHF+dsTe/zI6QE8n6vKJzqOAhMExXa9UxJf4naEqDDBAEmPVLrSXaXgS8pWz16ko9TZnOx0k2oxzwPmkAssGe/vSD5nl9xk+uXmcowg5/KrpxPgORdW6bcpd5YVDbHp6JptnovNk30P5rmfZTfEM3urBpcJp4q4o6tmyb1+fFzwsw9QA98v6fz7lSt2+0csl0LLFFUphUeLz1iGaaVMyMkBzznwmvR3kB1OEeYCbLSNlN71Cq9MZqYG/Zu26SpCX4z70odSCSW8sC20AvzAeVVmDvy03gPGoNGlCxWiZ1CzV33i2aQlsGGUy4jWpGjgywLV8ls78Ifp23AgstW52Go0p0mmy8g6t5EBMt4K50XtpIecnWntiNKyll8I7Q7DoKrjqOopP4MYgRohYfz1fUedAhkBqUKBewfAvTZzIzeitUGBbEZ+0fjg5A= X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Aug 2023 13:54:30.1322 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: b942c229-c85f-4a88-15e2-08dba24e244a X-MS-Exchange-CrossTenant-Id: c4540d0b-728a-4233-9da5-9ea30c7ec3ed X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=c4540d0b-728a-4233-9da5-9ea30c7ec3ed; Ip=[178.72.21.4]; Helo=[localhost.localdomain.com] X-MS-Exchange-CrossTenant-AuthSource: DU2PEPF0001E9C5.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBAP190MB0951 X-BESS-ID: 1692626078-303522-12318-18267-1 X-BESS-VER: 2019.1_20230817.1828 X-BESS-Apparent-Source-IP: 104.47.51.240 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKVsaGxmbmRkB2BlA4xcAgydIwOS kxJcnIMtXMwsDA3MTAJDnR2CDNMtUkJU2pNhYAYdwcSUMAAAA= X-BESS-Outbound-Spam-Score: 0.00 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.250292 [from cloudscan20-109.eu-central-1b.ess.aws.cudaops.com] Rule breakdown below pts rule name description ---- ---------------------- -------------------------------- 0.00 LARGE_BODY_SHORTCUT META: X-BESS-Outbound-Spam-Status: SCORE=0.00 using account:ESS113687 scores of KILL_LEVEL=7.0 tests=LARGE_BODY_SHORTCUT X-BESS-BRTS-Status: 1 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 From: Christian Koue Muf This logic layer takes rte_flow style patterns and actions as input, and programs the FPGA accordingly. Signed-off-by: Christian Koue Muf Reviewed-by: Mykola Kostenok --- v2: * Fixed WARNING:TYPO_SPELLING --- drivers/net/ntnic/adapter/nt4ga_adapter.c | 13 + drivers/net/ntnic/adapter/nt4ga_stat.c | 20 +- drivers/net/ntnic/meson.build | 4 + drivers/net/ntnic/nthw/flow_api/flow_api.c | 1306 +++++ drivers/net/ntnic/nthw/flow_api/flow_api.h | 291 + .../nthw/flow_api/flow_api_profile_inline.c | 5118 +++++++++++++++++ .../nthw/flow_api/flow_api_profile_inline.h | 56 + .../net/ntnic/nthw/flow_filter/flow_backend.c | 3205 +++++++++++ .../net/ntnic/nthw/flow_filter/flow_backend.h | 15 + .../net/ntnic/nthw/flow_filter/flow_filter.c | 39 + .../net/ntnic/nthw/flow_filter/flow_filter.h | 16 + 11 files changed, 10078 insertions(+), 5 deletions(-) create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api.c create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api.h create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.c create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_backend.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_backend.h create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_filter.c create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_filter.h diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.c b/drivers/net/ntnic/adapter/nt4ga_adapter.c index 259aae2831..f9493202c3 100644 --- a/drivers/net/ntnic/adapter/nt4ga_adapter.c +++ b/drivers/net/ntnic/adapter/nt4ga_adapter.c @@ -10,6 +10,8 @@ #include "nt4ga_pci_ta_tg.h" #include "nt4ga_link_100g.h" +#include "flow_filter.h" + /* Sensors includes */ #include "board_sensors.h" #include "avr_sensors.h" @@ -306,6 +308,17 @@ int nt4ga_adapter_init(struct adapter_info_s *p_adapter_info) n_nim_ports = fpga_info->n_nims; assert(n_nim_ports >= 1); + /* Nt4ga Init Filter */ + nt4ga_filter_t *p_filter = &p_adapter_info->nt4ga_filter; + + res = flow_filter_init(p_fpga, &p_filter->mp_flow_device, + p_adapter_info->adapter_no); + if (res != 0) { + NT_LOG(ERR, ETHDEV, "%s: Cannot initialize filter\n", + p_adapter_id_str); + return res; + } + /* * HIF/PCI TA/TG */ diff --git a/drivers/net/ntnic/adapter/nt4ga_stat.c b/drivers/net/ntnic/adapter/nt4ga_stat.c index b61c73ea12..2c822c6b97 100644 --- a/drivers/net/ntnic/adapter/nt4ga_stat.c +++ b/drivers/net/ntnic/adapter/nt4ga_stat.c @@ -7,6 +7,7 @@ #include "nthw_drv.h" #include "nthw_fpga.h" #include "nt4ga_adapter.h" +#include "flow_filter.h" #define NO_FLAGS 0 @@ -16,12 +17,13 @@ static inline uint64_t timestamp2ns(uint64_t ts) return ((ts >> 32) * 1000000000) + (ts & 0xffffffff); } -static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat, +static int nt4ga_stat_collect_cap_v1_stats(struct adapter_info_s *p_adapter_info, + nt4ga_stat_t *p_nt4ga_stat, uint32_t *p_stat_dma_virtual); static int nt4ga_stat_collect_virt_v1_stats(nt4ga_stat_t *p_nt4ga_stat, uint32_t *p_stat_dma_virtual); -int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info _unused, +int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info, nt4ga_stat_t *p_nt4ga_stat) { nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat; @@ -39,7 +41,7 @@ int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info _unused, } else { p_nt4ga_stat->last_timestamp = timestamp2ns(*p_nthw_stat->mp_timestamp); - nt4ga_stat_collect_cap_v1_stats(p_nt4ga_stat, + nt4ga_stat_collect_cap_v1_stats(p_adapter_info, p_nt4ga_stat, p_nt4ga_stat->p_stat_dma_virtual); } return 0; @@ -198,7 +200,9 @@ int nt4ga_stat_setup(struct adapter_info_s *p_adapter_info) return -1; } - p_nt4ga_stat->flm_stat_ver = 0; + struct flow_nic_dev *ndev = + p_adapter_info->nt4ga_filter.mp_flow_device; + p_nt4ga_stat->flm_stat_ver = ndev->be.flm.ver; p_nt4ga_stat->mp_stat_structs_flm = calloc(1, sizeof(struct flm_counters_v1)); @@ -394,10 +398,12 @@ static int nt4ga_stat_collect_virt_v1_stats(nt4ga_stat_t *p_nt4ga_stat, } /* Called with stat mutex locked */ -static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat, +static int nt4ga_stat_collect_cap_v1_stats(struct adapter_info_s *p_adapter_info, + nt4ga_stat_t *p_nt4ga_stat, uint32_t *p_stat_dma_virtual) { nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat; + struct flow_nic_dev *ndev = p_adapter_info->nt4ga_filter.mp_flow_device; const int n_rx_ports = p_nt4ga_stat->mn_rx_ports; const int n_tx_ports = p_nt4ga_stat->mn_tx_ports; @@ -701,5 +707,9 @@ static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat, p_nt4ga_stat->a_port_tx_drops_total[p] += new_drop_events_sum; } + /* _update and get FLM stats */ + flow_get_flm_stats(ndev, (uint64_t *)p_nt4ga_stat->mp_stat_structs_flm, + sizeof(struct flm_counters_v1) / sizeof(uint64_t)); + return 0; } diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build index b816021b11..0b5ca13e48 100644 --- a/drivers/net/ntnic/meson.build +++ b/drivers/net/ntnic/meson.build @@ -67,8 +67,10 @@ sources = files( 'nthw/core/nthw_spim.c', 'nthw/core/nthw_spis.c', 'nthw/core/nthw_tsm.c', + 'nthw/flow_api/flow_api.c', 'nthw/flow_api/flow_api_actions.c', 'nthw/flow_api/flow_api_backend.c', + 'nthw/flow_api/flow_api_profile_inline.c', 'nthw/flow_api/flow_engine/flow_group.c', 'nthw/flow_api/flow_engine/flow_hasher.c', 'nthw/flow_api/flow_engine/flow_kcc.c', @@ -87,6 +89,8 @@ sources = files( 'nthw/flow_api/hw_mod/hw_mod_slc.c', 'nthw/flow_api/hw_mod/hw_mod_slc_lr.c', 'nthw/flow_api/hw_mod/hw_mod_tpe.c', + 'nthw/flow_filter/flow_backend.c', + 'nthw/flow_filter/flow_filter.c', 'nthw/flow_filter/flow_nthw_cat.c', 'nthw/flow_filter/flow_nthw_csu.c', 'nthw/flow_filter/flow_nthw_flm.c', diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api.c b/drivers/net/ntnic/nthw/flow_api/flow_api.c new file mode 100644 index 0000000000..2598e1e27b --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_api.c @@ -0,0 +1,1306 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include +#include +#include +#include /* htons, htonl, ntohs */ + +#include "ntlog.h" + +#include "flow_api.h" + +#include "flow_api_nic_setup.h" +#include "stream_binary_flow_api.h" +#include "flow_api_actions.h" +#include "flow_api_backend.h" +#include "flow_api_engine.h" + +#include "flow_api_profile_inline.h" + +#define SCATTER_GATHER + +const char *dbg_res_descr[] = { + /* RES_QUEUE */ "RES_QUEUE", + /* RES_CAT_CFN */ "RES_CAT_CFN", + /* RES_CAT_COT */ "RES_CAT_COT", + /* RES_CAT_EXO */ "RES_CAT_EXO", + /* RES_CAT_LEN */ "RES_CAT_LEN", + /* RES_KM_FLOW_TYPE */ "RES_KM_FLOW_TYPE", + /* RES_KM_CATEGORY */ "RES_KM_CATEGORY", + /* RES_HSH_RCP */ "RES_HSH_RCP", + /* RES_PDB_RCP */ "RES_PDB_RCP", + /* RES_QSL_RCP */ "RES_QSL_RCP", + /* RES_QSL_LTX */ "RES_QSL_LTX", + /* RES_QSL_QST */ "RES_QSL_QST", + /* RES_SLC_RCP */ "RES_SLC_RCP", + /* RES_IOA_RCP */ "RES_IOA_RCP", + /* RES_ROA_RCP */ "RES_ROA_RCP", + /* RES_FLM_FLOW_TYPE */ "RES_FLM_FLOW_TYPE", + /* RES_FLM_RCP */ "RES_FLM_RCP", + /* RES_HST_RCP */ "RES_HST_RCP", + /* RES_TPE_RCP */ "RES_TPE_RCP", + /* RES_TPE_EXT */ "RES_TPE_EXT", + /* RES_TPE_RPL */ "RES_TPE_RPL", + /* RES_COUNT */ "RES_COUNT", + /* RES_INVALID */ "RES_INVALID" +}; + +static struct flow_nic_dev *dev_base; +static pthread_mutex_t base_mtx = PTHREAD_MUTEX_INITIALIZER; + +/* + * ***************************************************************************** + * Error handling + * ***************************************************************************** + */ + +static const struct { + const char *message; +} err_msg[] = { + /* 00 */ { "Operation successfully completed" }, + /* 01 */ { "Operation failed" }, + /* 02 */ { "Memory allocation failed" }, + /* 03 */ { "Too many output destinations" }, + /* 04 */ { "Too many output queues for RSS" }, + /* 05 */ { "The VLAN TPID specified is not supported" }, + /* 06 */ { "The VxLan Push header specified is not accepted" }, + /* 07 */ + { "While interpreting VxLan Pop action, could not find a destination port" }, + /* 08 */ { "Failed in creating a HW-internal VTEP port" }, + /* 09 */ { "Too many VLAN tag matches" }, + /* 10 */ { "IPv6 invalid header specified" }, + /* 11 */ { "Too many tunnel ports. HW limit reached" }, + /* 12 */ { "Unknown or unsupported flow match element received" }, + /* 13 */ { "Match failed because of HW limitations" }, + /* 14 */ { "Match failed because of HW resource limitations" }, + /* 15 */ { "Match failed because of too complex element definitions" }, + /* 16 */ { "Action failed. To too many output destinations" }, + /* 17 */ { "Action Output failed, due to HW resource exhaustion" }, + /* 18 */ + { "Push Tunnel Header action cannot output to multiple destination queues" }, + /* 19 */ { "Inline action HW resource exhaustion" }, + /* 20 */ { "Action retransmit/recirculate HW resource exhaustion" }, + /* 21 */ { "Flow counter HW resource exhaustion" }, + /* 22 */ { "Internal HW resource exhaustion to handle Actions" }, + /* 23 */ { "Internal HW QSL compare failed" }, + /* 24 */ { "Internal CAT CFN reuse failed" }, + /* 25 */ { "Match variations too complex" }, + /* 26 */ { "Match failed because of CAM/TCAM full" }, + /* 27 */ { "Internal creation of a tunnel end point port failed" }, + /* 28 */ { "Unknown or unsupported flow action received" }, + /* 29 */ { "Removing flow failed" }, + /* 30 */ + { "No output queue specified. Ignore this flow offload and uses default queue" }, + /* 31 */ { "No output queue found" }, + /* 32 */ { "Unsupported EtherType or rejected caused by offload policy" }, + /* 33 */ + { "Destination port specified is invalid or not reachable from this NIC" }, + /* 34 */ { "Partial offload is not supported in this configuration" }, + /* 35 */ { "Match failed because of CAT CAM exhausted" }, + /* 36 */ + { "Match failed because of CAT CAM Key clashed with an existing KCC Key" }, + /* 37 */ { "Match failed because of CAT CAM write failed" }, + /* 38 */ { "Partial flow mark too big for device" }, +}; + +void flow_nic_set_error(enum flow_nic_err_msg_e msg, struct flow_error *error) +{ + assert(msg < ERR_MSG_NO_MSG); + if (error) { + error->message = err_msg[msg].message; + error->type = (msg == ERR_SUCCESS) ? FLOW_ERROR_SUCCESS : + FLOW_ERROR_GENERAL; + } +} + +/* + * ***************************************************************************** + * Resources + * ***************************************************************************** + */ + +int flow_nic_alloc_resource(struct flow_nic_dev *ndev, enum res_type_e res_type, + uint32_t alignment) +{ + for (unsigned int i = 0; i < ndev->res[res_type].resource_count; + i += alignment) { + if (!flow_nic_is_resource_used(ndev, res_type, i)) { + flow_nic_mark_resource_used(ndev, res_type, i); + ndev->res[res_type].ref[i] = 1; + return i; + } + } + return -1; +} + +int flow_nic_alloc_resource_index(struct flow_nic_dev *ndev, int idx, + enum res_type_e res_type) +{ + if (!flow_nic_is_resource_used(ndev, res_type, idx)) { + flow_nic_mark_resource_used(ndev, res_type, idx); + ndev->res[res_type].ref[idx] = 1; + return 0; + } + return -1; +} + +int flow_nic_alloc_resource_contig(struct flow_nic_dev *ndev, + enum res_type_e res_type, unsigned int num, + uint32_t alignment) +{ + unsigned int idx_offs; + + for (unsigned int res_idx = 0; + res_idx < ndev->res[res_type].resource_count - (num - 1); + res_idx += alignment) { + if (!flow_nic_is_resource_used(ndev, res_type, res_idx)) { + for (idx_offs = 1; idx_offs < num; idx_offs++) { + if (flow_nic_is_resource_used(ndev, res_type, + res_idx + idx_offs)) + break; + } + if (idx_offs < num) + continue; + + /* found a contiguous number of "num" res_type elements - allocate them */ + for (idx_offs = 0; idx_offs < num; idx_offs++) { + flow_nic_mark_resource_used(ndev, res_type, + res_idx + idx_offs); + ndev->res[res_type].ref[res_idx + idx_offs] = 1; + } + return res_idx; + } + } + return -1; +} + +void flow_nic_free_resource(struct flow_nic_dev *ndev, enum res_type_e res_type, + int idx) +{ + flow_nic_mark_resource_unused(ndev, res_type, idx); +} + +int flow_nic_ref_resource(struct flow_nic_dev *ndev, enum res_type_e res_type, + int index) +{ + NT_LOG(DBG, FILTER, + "Reference resource %s idx %i (before ref cnt %i)\n", + dbg_res_descr[res_type], index, ndev->res[res_type].ref[index]); + assert(flow_nic_is_resource_used(ndev, res_type, index)); + if (ndev->res[res_type].ref[index] == (uint32_t)-1) + return -1; + ndev->res[res_type].ref[index]++; + return 0; +} + +int flow_nic_deref_resource(struct flow_nic_dev *ndev, enum res_type_e res_type, + int index) +{ + NT_LOG(DBG, FILTER, + "De-reference resource %s idx %i (before ref cnt %i)\n", + dbg_res_descr[res_type], index, ndev->res[res_type].ref[index]); + assert(flow_nic_is_resource_used(ndev, res_type, index)); + assert(ndev->res[res_type].ref[index]); + /* deref */ + ndev->res[res_type].ref[index]--; + if (!ndev->res[res_type].ref[index]) + flow_nic_free_resource(ndev, res_type, index); + return !!ndev->res[res_type] + .ref[index]; /* if 0 resource has been freed */ +} + +int flow_nic_find_next_used_resource(struct flow_nic_dev *ndev, + enum res_type_e res_type, int idx_start) +{ + for (unsigned int i = idx_start; i < ndev->res[res_type].resource_count; + i++) { + if (flow_nic_is_resource_used(ndev, res_type, i)) + return i; + } + return -1; +} + +/* + * Allocate a number flow resources. + * + * Arguments: + * ndev : device + * res_type : resource type + * fh : flow handle + * count : number of (contiguous) resources to be allocated + * alignment : start index alignment + * 1: the allocation can start at any index + * 2: the allocation must start at index modulus 2 (0, 2, 4, 6, ...) + * 3: the allocation must start at index modulus 3 (0, 3, 6, 9, ...) + * etc. + * Returns: + * 0 : success + * -1 : failure + */ +int flow_nic_allocate_fh_resource(struct flow_nic_dev *ndev, + enum res_type_e res_type, + struct flow_handle *fh, uint32_t count, + uint32_t alignment) +{ + if (count > 1) { + /* Contiguous */ + fh->resource[res_type].index = + flow_nic_alloc_resource_contig(ndev, res_type, count, alignment); + } else { + fh->resource[res_type].index = + flow_nic_alloc_resource(ndev, res_type, alignment); + } + + if (fh->resource[res_type].index < 0) + return -1; + fh->resource[res_type].count = count; + return 0; +} + +int flow_nic_allocate_fh_resource_index(struct flow_nic_dev *ndev, + enum res_type_e res_type, int idx, + struct flow_handle *fh) +{ + int err = flow_nic_alloc_resource_index(ndev, idx, res_type); + + if (err) + return err; + + fh->resource[res_type].index = idx; + if (fh->resource[res_type].index < 0) + return -1; + fh->resource[res_type].count = 1; + return 0; +} + +/* + * ***************************************************************************** + * Hash + * ***************************************************************************** + */ + +int flow_nic_set_hasher(struct flow_nic_dev *ndev, int hsh_idx, + enum flow_nic_hash_e algorithm) +{ + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_PRESET_ALL, hsh_idx, 0, 0); + switch (algorithm) { + case HASH_ALGO_5TUPLE: + /* need to create an IPv6 hashing and enable the adaptive ip mask bit */ + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_LOAD_DIST_TYPE, + hsh_idx, 0, 2); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW0_PE, hsh_idx, 0, + DYN_FINAL_IP_DST); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW0_OFS, hsh_idx, 0, + -16); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW4_PE, hsh_idx, 0, + DYN_FINAL_IP_DST); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW4_OFS, hsh_idx, 0, + 0); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W8_PE, hsh_idx, 0, + DYN_L4); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W8_OFS, hsh_idx, 0, 0); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W9_PE, hsh_idx, 0, 0); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W9_OFS, hsh_idx, 0, 0); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W9_P, hsh_idx, 0, 0); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_P_MASK, hsh_idx, 0, 1); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 0, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 1, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 2, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 3, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 4, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 5, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 6, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 7, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 8, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 9, + 0); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_SEED, hsh_idx, 0, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_VALID, hsh_idx, 0, + 1); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_TYPE, hsh_idx, 0, + HASH_5TUPLE); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_AUTO_IPV4_MASK, + hsh_idx, 0, 1); + + NT_LOG(DBG, FILTER, + "Set IPv6 5-tuple hasher with adaptive IPv4 hashing\n"); + break; + default: + case HASH_ALGO_ROUND_ROBIN: + /* zero is round-robin */ + break; + } + + return 0; +} + +int flow_nic_set_hasher_fields(struct flow_nic_dev *ndev, int hsh_idx, + struct nt_eth_rss f) +{ + uint64_t fields = f.fields; + + int res = 0; + + res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_PRESET_ALL, hsh_idx, 0, + 0); + res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_LOAD_DIST_TYPE, hsh_idx, + 0, 2); + switch (fields) { + case NT_ETH_RSS_C_VLAN: + /* + * Here we are using 1st VLAN to point C-VLAN which is only try for the single VLAN + * provider + */ + res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W8_PE, hsh_idx, + 0, DYN_FIRST_VLAN); + res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W8_OFS, hsh_idx, + 0, 0); + res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, + hsh_idx, 8, 0xffffffff); + res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_TYPE, + hsh_idx, 0, HASH_LAST_VLAN_ID); + if (res) { + NT_LOG(ERR, FILTER, + "VLAN hasher is not set hardware communication problem has " + "occurred. The cardware could be in inconsistent state. Rerun.\n"); + return -1; + } + NT_LOG(DBG, FILTER, "Set VLAN hasher.\n"); + return 0; + case NT_ETH_RSS_LEVEL_OUTERMOST | NT_ETH_RSS_L3_DST_ONLY | NT_ETH_RSS_IP: + /* need to create an IPv6 hashing and enable the adaptive ip mask bit */ + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW4_PE, hsh_idx, 0, + DYN_FINAL_IP_DST); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW4_OFS, hsh_idx, 0, + 0); + + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 4, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 5, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 6, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 7, + 0xffffffff); + + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_TYPE, hsh_idx, 0, + HASH_OUTER_DST_IP); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_AUTO_IPV4_MASK, + hsh_idx, 0, 1); + if (res) { + NT_LOG(ERR, FILTER, + "Outer dst IP hasher is not set hardware communication problem has " + "occurred. The cardware could be in inconsistent state. Rerun.\n"); + return -1; + } + NT_LOG(DBG, FILTER, "Set outer dst IP hasher.\n"); + return 0; + case NT_ETH_RSS_LEVEL_INNERMOST | NT_ETH_RSS_L3_SRC_ONLY | NT_ETH_RSS_IP: + /* need to create an IPv6 hashing and enable the adaptive ip mask bit */ + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW0_PE, hsh_idx, 0, + DYN_TUN_FINAL_IP_DST); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW0_OFS, hsh_idx, 0, + -16); + + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 0, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 1, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 2, + 0xffffffff); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 3, + 0xffffffff); + + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_TYPE, hsh_idx, 0, + HASH_INNER_SRC_IP); + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_AUTO_IPV4_MASK, + hsh_idx, 0, 1); + if (res) { + NT_LOG(ERR, FILTER, + "Inner (depth = 1) src IP hasher is not set hardware communication " + "problem has occurred. The cardware could be in inconsistent state. " + "Rerun.\n"); + return -1; + } + NT_LOG(DBG, FILTER, "Set outer dst IP hasher.\n"); + return 0; + default: + NT_LOG(ERR, FILTER, + "RSS bit flags can't be set up. " + "Flags combination is not supported."); + return -1; + } +} + +/* + * ***************************************************************************** + * Nic port/adapter lookup + * ***************************************************************************** + */ + +struct flow_eth_dev *nic_and_port_to_eth_dev(uint8_t adapter_no, uint8_t port) +{ + struct flow_nic_dev *nic_dev = dev_base; + + while (nic_dev) { + if (nic_dev->adapter_no == adapter_no) + break; + nic_dev = nic_dev->next; + } + + if (!nic_dev) + return NULL; + + struct flow_eth_dev *dev = nic_dev->eth_base; + + while (dev) { + if (port == dev->port) + return dev; + dev = dev->next; + } + + return NULL; +} + +struct flow_nic_dev *get_nic_dev_from_adapter_no(uint8_t adapter_no) +{ + struct flow_nic_dev *ndev = dev_base; + + while (ndev) { + if (adapter_no == ndev->adapter_no) + break; + ndev = ndev->next; + } + return ndev; +} + +/* + * ***************************************************************************** + * LAG control implementation + * ***************************************************************************** + */ + +int lag_set_port_group(uint8_t adapter_no, uint32_t port_mask) +{ + pthread_mutex_lock(&base_mtx); + struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no); + + if (!ndev) { + /* Error invalid nic device */ + pthread_mutex_unlock(&base_mtx); + return -1; + } + /* + * Sets each 2 ports for each bit N as Lag. Ports N*2+N*2+1 are merged together + * and reported as N*2 incoming port + */ + hw_mod_rmc_ctrl_set(&ndev->be, HW_RMC_LAG_PHY_ODD_EVEN, port_mask); + hw_mod_rmc_ctrl_flush(&ndev->be); + pthread_mutex_unlock(&base_mtx); + return 0; +} + +int lag_set_port_block(uint8_t adapter_no, uint32_t port_mask) +{ + pthread_mutex_lock(&base_mtx); + struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no); + + if (!ndev) { + /* Error invalid nic device */ + pthread_mutex_unlock(&base_mtx); + return -1; + } + /* Blocks for traffic from port */ + hw_mod_rmc_ctrl_set(&ndev->be, HW_RMC_BLOCK_MAC_PORT, port_mask); + hw_mod_rmc_ctrl_flush(&ndev->be); + pthread_mutex_unlock(&base_mtx); + return 0; +} + +static void write_lag_entry(struct flow_api_backend_s *be, uint32_t index, + uint32_t value) +{ + hw_mod_roa_lagcfg_set(be, HW_ROA_LAGCFG_TXPHY_PORT, index, value); + hw_mod_roa_lagcfg_flush(be, index, 1); +} + +int lag_set_config(uint8_t adapter_no, enum flow_lag_cmd cmd, uint32_t index, + uint32_t value) +{ + pthread_mutex_lock(&base_mtx); + struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no); + + if (!ndev) { + /* Error invalid nic device */ + pthread_mutex_unlock(&base_mtx); + return -1; + } + + switch (cmd) { + case FLOW_LAG_SET_ENTRY: + write_lag_entry(&ndev->be, index, value); + break; + + case FLOW_LAG_SET_ALL: + index &= 3; + for (unsigned int i = 0; i < ndev->be.roa.nb_lag_entries; + i += 4) + write_lag_entry(&ndev->be, i + index, value); + break; + + case FLOW_LAG_SET_BALANCE: + /* + * This function will balance the output port + * value: The balance of the distribution: + * port P0 / P1 + * 0: 0 / 100 port 0 is disabled + * 25: 25 / 75 + * 50: 50 / 50 + * 75: 75 / 25 + * 100: 100/ 0 port 1 is disabled + */ + { + /* Clamp the balance to 100% output on port 1 */ + if (value > 100) + value = 100; + double balance = ((double)value / 100.0); + double block_count = + (double)ndev->be.roa.nb_lag_entries / 4.0; + + int output_port = 1; + int port0_output_block_count = + (int)(block_count * balance); + + for (int block = 0; block < block_count; block++) { + /* When the target port0 balance is reached. */ + if (block >= port0_output_block_count) + output_port = 2; + /* Write an entire hash block to a given output port. */ + for (int idx = 0; idx < 4; idx++) { + write_lag_entry(&ndev->be, + block * 4 + idx, + output_port); + } /* for each index in hash block */ + } /* for each hash block */ + } + + break; + default: + pthread_mutex_unlock(&base_mtx); + return -1; + } + + pthread_mutex_unlock(&base_mtx); + return 0; +} + +/* + * ***************************************************************************** + * Flow API + * ***************************************************************************** + */ + +int flow_validate(struct flow_eth_dev *dev, const struct flow_elem item[], + const struct flow_action action[], struct flow_error *error) +{ + if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) { + NT_LOG(ERR, FILTER, "vSwitch profile not supported"); + return -1; + } + return flow_validate_profile_inline(dev, item, action, error); +} + +struct flow_handle *flow_create(struct flow_eth_dev *dev, + const struct flow_attr *attr, + const struct flow_elem item[], + const struct flow_action action[], + struct flow_error *error) +{ + if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) { + NT_LOG(ERR, FILTER, "vSwitch profile not supported"); + return NULL; + } + return flow_create_profile_inline(dev, attr, item, action, error); +} + +int flow_destroy(struct flow_eth_dev *dev, struct flow_handle *flow, + struct flow_error *error) +{ + if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) { + NT_LOG(ERR, FILTER, "vSwitch profile not supported"); + return -1; + } + return flow_destroy_profile_inline(dev, flow, error); +} + +int flow_flush(struct flow_eth_dev *dev, struct flow_error *error) +{ + if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) { + NT_LOG(ERR, FILTER, "vSwitch profile not supported"); + return -1; + } + return flow_flush_profile_inline(dev, error); +} + +int flow_query(struct flow_eth_dev *dev, struct flow_handle *flow, + const struct flow_action *action, void **data, uint32_t *length, + struct flow_error *error) +{ + if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) { + NT_LOG(ERR, FILTER, "vSwitch profile not supported"); + return -1; + } + return flow_query_profile_inline(dev, flow, action, data, length, + error); +} + +/* + * ***************************************************************************** + * Device Management API + * ***************************************************************************** + */ + +static void nic_insert_eth_port_dev(struct flow_nic_dev *ndev, + struct flow_eth_dev *dev) +{ + dev->next = ndev->eth_base; + ndev->eth_base = dev; +} + +static int nic_remove_eth_port_dev(struct flow_nic_dev *ndev, + struct flow_eth_dev *eth_dev) +{ + struct flow_eth_dev *dev = ndev->eth_base, *prev = NULL; + + while (dev) { + if (dev == eth_dev) { + if (prev) + prev->next = dev->next; + + else + ndev->eth_base = dev->next; + return 0; + } + prev = dev; + dev = dev->next; + } + return -1; +} + +static void flow_ndev_reset(struct flow_nic_dev *ndev) +{ + /* Delete all eth-port devices created on this NIC device */ + while (ndev->eth_base) + flow_delete_eth_dev(ndev->eth_base); + + /* Error check */ + while (ndev->flow_base) { + NT_LOG(ERR, FILTER, + "ERROR : Flows still defined but all eth-ports deleted. Flow %p\n", + ndev->flow_base); + + if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) { + NT_LOG(ERR, FILTER, "vSwitch profile not supported"); + return; + } + flow_destroy_profile_inline(ndev->flow_base->dev, + ndev->flow_base, NULL); + } + + if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) { + NT_LOG(ERR, FILTER, "vSwitch profile not supported"); + return; + } + done_flow_management_of_ndev_profile_inline(ndev); + + km_free_ndev_resource_management(&ndev->km_res_handle); + kcc_free_ndev_resource_management(&ndev->kcc_res_handle); + +#ifdef FLOW_DEBUG + /* + * free all resources default allocated, initially for this NIC DEV + * Is not really needed since the bitmap will be freed in a sec. Therefore + * only in debug mode + */ + + /* Check if all resources has been released */ + NT_LOG(DBG, FILTER, "Delete NIC DEV Adaptor %i\n", ndev->adapter_no); + for (unsigned int i = 0; i < RES_COUNT; i++) { + int err = 0; +#if defined(FLOW_DEBUG) + NT_LOG(DBG, FILTER, "RES state for: %s\n", dbg_res_descr[i]); +#endif + for (unsigned int ii = 0; ii < ndev->res[i].resource_count; + ii++) { + int ref = ndev->res[i].ref[ii]; + int used = flow_nic_is_resource_used(ndev, i, ii); + + if (ref || used) { + NT_LOG(DBG, FILTER, + " [%i]: ref cnt %i, used %i\n", ii, ref, + used); + err = 1; + } + } + if (err) + NT_LOG(DBG, FILTER, + "ERROR - some resources not freed\n"); + } +#endif +} + +int flow_reset_nic_dev(uint8_t adapter_no) +{ + struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no); + + if (!ndev) + return -1; + flow_ndev_reset(ndev); + flow_api_backend_reset(&ndev->be); + return 0; +} + +/* + * adapter_no physical adapter no + * port_no local port no + * alloc_rx_queues number of rx-queues to allocate for this eth_dev + */ +struct flow_eth_dev *flow_get_eth_dev(uint8_t adapter_no, uint8_t port_no, + uint32_t port_id, int alloc_rx_queues, + struct flow_queue_id_s queue_ids[], + int *rss_target_id, + enum flow_eth_dev_profile flow_profile, + uint32_t exception_path) +{ + int i; + struct flow_eth_dev *eth_dev = NULL; + + NT_LOG(DBG, FILTER, + "Get eth-port adapter %i, port %i, port_id %u, rx queues %i, profile %i\n", + adapter_no, port_no, port_id, alloc_rx_queues, flow_profile); + + if (MAX_OUTPUT_DEST < FLOW_MAX_QUEUES) { + assert(0); + NT_LOG(ERR, FILTER, + "ERROR: Internal array for multiple queues too small for API\n"); + } + + pthread_mutex_lock(&base_mtx); + struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no); + + if (!ndev) { + /* Error - no flow api found on specified adapter */ + NT_LOG(ERR, FILTER, + "ERROR: no flow interface registered for adapter %d\n", + adapter_no); + pthread_mutex_unlock(&base_mtx); + return NULL; + } + + if (ndev->ports < ((uint16_t)port_no + 1)) { + NT_LOG(ERR, FILTER, + "ERROR: port exceeds supported port range for adapter\n"); + pthread_mutex_unlock(&base_mtx); + return NULL; + } + + if ((alloc_rx_queues - 1) > + FLOW_MAX_QUEUES) { /* 0th is exception so +1 */ + NT_LOG(ERR, FILTER, + "ERROR: Exceeds supported number of rx queues per eth device\n"); + pthread_mutex_unlock(&base_mtx); + return NULL; + } + + /* don't accept multiple eth_dev's on same NIC and same port */ + eth_dev = nic_and_port_to_eth_dev(adapter_no, port_no); + if (eth_dev) { + NT_LOG(DBG, FILTER, + "Re-opening existing NIC port device: NIC DEV: %i Port %i\n", + adapter_no, port_no); + pthread_mutex_unlock(&base_mtx); + flow_delete_eth_dev(eth_dev); + eth_dev = NULL; + } + + eth_dev = calloc(1, sizeof(struct flow_eth_dev)); + if (!eth_dev) { + NT_LOG(ERR, FILTER, "ERROR: calloc failed\n"); + goto err_exit1; + } + + pthread_mutex_lock(&ndev->mtx); + + eth_dev->ndev = ndev; + eth_dev->port = port_no; + eth_dev->port_id = port_id; + +#ifdef FLOW_DEBUG + ndev->be.iface->set_debug_mode(ndev->be.be_dev, + FLOW_BACKEND_DEBUG_MODE_WRITE); +#endif + + /* First time then NIC is initialized */ + if (!ndev->flow_mgnt_prepared) { + ndev->flow_profile = flow_profile; + /* Initialize modules if needed - recipe 0 is used as no-match and must be setup */ + if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) { + NT_LOG(ERR, FILTER, "vSwitch profile not supported"); + goto err_exit0; + } else if (initialize_flow_management_of_ndev_profile_inline(ndev) + != 0) { + goto err_exit0; + } + } else { + /* check if same flow type is requested, otherwise fail */ + if (ndev->flow_profile != flow_profile) { + NT_LOG(ERR, FILTER, + "ERROR: Different flow types requested on same NIC device. " + "Not supported.\n"); + goto err_exit0; + } + } + + /* Allocate the requested queues in HW for this dev */ + + for (i = 0; i < alloc_rx_queues; i++) { +#ifdef SCATTER_GATHER + eth_dev->rx_queue[i] = queue_ids[i]; +#else + int queue_id = flow_nic_alloc_resource(ndev, RES_QUEUE, 1); + + if (queue_id < 0) { + NT_LOG(ERR, FILTER, + "ERROR: no more free queue IDs in NIC\n"); + goto err_exit0; + } + + eth_dev->rx_queue[eth_dev->num_queues].id = (uint8_t)queue_id; + eth_dev->rx_queue[eth_dev->num_queues].hw_id = + ndev->be.iface->alloc_rx_queue(ndev->be.be_dev, + eth_dev->rx_queue[eth_dev->num_queues].id); + if (eth_dev->rx_queue[eth_dev->num_queues].hw_id < 0) { + NT_LOG(ERR, FILTER, + "ERROR: could not allocate a new queue\n"); + goto err_exit0; + } + + if (queue_ids) { + queue_ids[eth_dev->num_queues] = + eth_dev->rx_queue[eth_dev->num_queues]; + } +#endif + if (i == 0 && (flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH || + (flow_profile == FLOW_ETH_DEV_PROFILE_INLINE && + exception_path))) { + /* + * Init QSL UNM - unmatched - redirects otherwise discarded packets in QSL + */ + if (hw_mod_qsl_unmq_set(&ndev->be, + HW_QSL_UNMQ_DEST_QUEUE, + eth_dev->port, + eth_dev->rx_queue[0].hw_id) < 0) + goto err_exit0; + if (hw_mod_qsl_unmq_set(&ndev->be, HW_QSL_UNMQ_EN, + eth_dev->port, 1) < 0) + goto err_exit0; + if (hw_mod_qsl_unmq_flush(&ndev->be, eth_dev->port, 1) < + 0) + goto err_exit0; + } + + eth_dev->num_queues++; + } + + eth_dev->rss_target_id = -1; + + if (flow_profile == FLOW_ETH_DEV_PROFILE_INLINE) { + for (i = 0; i < eth_dev->num_queues; i++) { + uint32_t qen_value = 0; + uint32_t queue_id = + (uint32_t)eth_dev->rx_queue[i].hw_id; + + hw_mod_qsl_qen_get(&ndev->be, HW_QSL_QEN_EN, + queue_id / 4, &qen_value); + hw_mod_qsl_qen_set(&ndev->be, HW_QSL_QEN_EN, + queue_id / 4, + qen_value | (1 << (queue_id % 4))); + hw_mod_qsl_qen_flush(&ndev->be, queue_id / 4, 1); + } + } + + *rss_target_id = eth_dev->rss_target_id; + +#ifdef FLOW_DEBUG + ndev->be.iface->set_debug_mode(ndev->be.be_dev, + FLOW_BACKEND_DEBUG_MODE_NONE); +#endif + + nic_insert_eth_port_dev(ndev, eth_dev); + + pthread_mutex_unlock(&ndev->mtx); + pthread_mutex_unlock(&base_mtx); + return eth_dev; + +err_exit0: + pthread_mutex_unlock(&ndev->mtx); + pthread_mutex_unlock(&base_mtx); + +err_exit1: + if (eth_dev) + free(eth_dev); + +#ifdef FLOW_DEBUG + ndev->be.iface->set_debug_mode(ndev->be.be_dev, + FLOW_BACKEND_DEBUG_MODE_NONE); +#endif + + NT_LOG(DBG, FILTER, "ERR in %s\n", __func__); + return NULL; /* Error exit */ +} + +int flow_eth_dev_add_queue(struct flow_eth_dev *eth_dev, + struct flow_queue_id_s *queue_id) +{ + uint32_t qen_value = 0; + + eth_dev->rx_queue[eth_dev->num_queues].id = queue_id->id; + eth_dev->rx_queue[eth_dev->num_queues].hw_id = queue_id->hw_id; + eth_dev->num_queues += 1; + + hw_mod_qsl_qen_get(ð_dev->ndev->be, HW_QSL_QEN_EN, + queue_id->hw_id / 4, &qen_value); + hw_mod_qsl_qen_set(ð_dev->ndev->be, HW_QSL_QEN_EN, + queue_id->hw_id / 4, + qen_value | (1 << (queue_id->hw_id % 4))); + hw_mod_qsl_qen_flush(ð_dev->ndev->be, queue_id->hw_id / 4, 1); + + return 0; +} + +int flow_delete_eth_dev(struct flow_eth_dev *eth_dev) +{ + struct flow_nic_dev *ndev = eth_dev->ndev; + + if (!ndev) { + /* Error invalid nic device */ + return -1; + } + + NT_LOG(DBG, FILTER, "Delete eth-port device %p, port %i\n", eth_dev, + eth_dev->port); + +#ifdef FLOW_DEBUG + ndev->be.iface->set_debug_mode(ndev->be.be_dev, + FLOW_BACKEND_DEBUG_MODE_WRITE); +#endif + + /* delete all created flows from this device */ + pthread_mutex_lock(&ndev->mtx); + + struct flow_handle *flow = ndev->flow_base; + + while (flow) { + if (flow->dev == eth_dev) { + struct flow_handle *flow_next = flow->next; + + if (ndev->flow_profile == + FLOW_ETH_DEV_PROFILE_VSWITCH) { + NT_LOG(ERR, FILTER, "vSwitch profile not supported"); + return -1; + } + flow_destroy_locked_profile_inline(eth_dev, + flow, NULL); + flow = flow_next; + } else { + flow = flow->next; + } + } + + /* + * remove unmatched queue if setup in QSL + * remove exception queue setting in QSL UNM + */ + hw_mod_qsl_unmq_set(&ndev->be, HW_QSL_UNMQ_DEST_QUEUE, eth_dev->port, + 0); + hw_mod_qsl_unmq_set(&ndev->be, HW_QSL_UNMQ_EN, eth_dev->port, 0); + hw_mod_qsl_unmq_flush(&ndev->be, eth_dev->port, 1); + + if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_INLINE) { + for (int i = 0; i < eth_dev->num_queues; ++i) { + uint32_t qen_value = 0; + uint32_t queue_id = + (uint32_t)eth_dev->rx_queue[i].hw_id; + + hw_mod_qsl_qen_get(&ndev->be, HW_QSL_QEN_EN, + queue_id / 4, &qen_value); + hw_mod_qsl_qen_set(&ndev->be, HW_QSL_QEN_EN, + queue_id / 4, + qen_value & ~(1U << (queue_id % 4))); + hw_mod_qsl_qen_flush(&ndev->be, queue_id / 4, 1); + } + } + +#ifdef FLOW_DEBUG + ndev->be.iface->set_debug_mode(ndev->be.be_dev, + FLOW_BACKEND_DEBUG_MODE_NONE); +#endif + +#ifndef SCATTER_GATHER + /* free rx queues */ + for (int i = 0; i < eth_dev->num_queues; i++) { + ndev->be.iface->free_rx_queue(ndev->be.be_dev, + eth_dev->rx_queue[i].hw_id); + flow_nic_deref_resource(ndev, RES_QUEUE, + eth_dev->rx_queue[i].id); + } +#endif + + /* take eth_dev out of ndev list */ + if (nic_remove_eth_port_dev(ndev, eth_dev) != 0) + NT_LOG(ERR, FILTER, "ERROR : eth_dev %p not found\n", eth_dev); + + pthread_mutex_unlock(&ndev->mtx); + + /* free eth_dev */ + free(eth_dev); + return 0; +} + +int flow_get_tunnel_definition(struct tunnel_cfg_s *tun, uint32_t flow_stat_id, + uint8_t vport) +{ + return tunnel_get_definition(tun, flow_stat_id, vport); +} + +/* + * ***************************** Flow API NIC Setup *************************************** + * Flow backend creation function - register and initialize common backend API to FPA modules + * ****************************************************************************************** + */ + +static int init_resource_elements(struct flow_nic_dev *ndev, + enum res_type_e res_type, uint32_t count) +{ + assert(ndev->res[res_type].alloc_bm == NULL); + /* allocate bitmap and ref counter */ + ndev->res[res_type].alloc_bm = + calloc(1, BIT_CONTAINER_8_ALIGN(count) + count * sizeof(uint32_t)); + if (ndev->res[res_type].alloc_bm) { + ndev->res[res_type].ref = + (uint32_t *)&ndev->res[res_type] + .alloc_bm[BIT_CONTAINER_8_ALIGN(count)]; + ndev->res[res_type].resource_count = count; + return 0; + } + return -1; +} + +static void done_resource_elements(struct flow_nic_dev *ndev, + enum res_type_e res_type) +{ + assert(ndev); + if (ndev->res[res_type].alloc_bm) + free(ndev->res[res_type].alloc_bm); +} + +static void list_insert_flow_nic(struct flow_nic_dev *ndev) +{ + pthread_mutex_lock(&base_mtx); + ndev->next = dev_base; + dev_base = ndev; + pthread_mutex_unlock(&base_mtx); +} + +static int list_remove_flow_nic(struct flow_nic_dev *ndev) +{ + pthread_mutex_lock(&base_mtx); + struct flow_nic_dev *nic_dev = dev_base, *prev = NULL; + + while (nic_dev) { + if (nic_dev == ndev) { + if (prev) + prev->next = nic_dev->next; + else + dev_base = nic_dev->next; + pthread_mutex_unlock(&base_mtx); + return 0; + } + prev = nic_dev; + nic_dev = nic_dev->next; + } + + pthread_mutex_unlock(&base_mtx); + return -1; +} + +struct flow_nic_dev *flow_api_create(uint8_t adapter_no, + const struct flow_api_backend_ops *be_if, + void *be_dev) +{ + if (!be_if || be_if->version != 1) { + NT_LOG(DBG, FILTER, "ERR: %s\n", __func__); + return NULL; + } + + struct flow_nic_dev *ndev = calloc(1, sizeof(struct flow_nic_dev)); + + if (!ndev) { + NT_LOG(ERR, FILTER, "ERROR: calloc failed\n"); + return NULL; + } + + /* + * To dump module initialization writes use + * FLOW_BACKEND_DEBUG_MODE_WRITE + * then remember to set it ...NONE afterwards again + */ + be_if->set_debug_mode(be_dev, FLOW_BACKEND_DEBUG_MODE_NONE); + + if (flow_api_backend_init(&ndev->be, be_if, be_dev) != 0) + goto err_exit; + ndev->adapter_no = adapter_no; + + ndev->ports = (uint16_t)((ndev->be.num_rx_ports > 256) ? + 256 : + ndev->be.num_rx_ports); + + /* + * Free resources in NIC must be managed by this module + * Get resource sizes and create resource manager elements + */ + if (init_resource_elements(ndev, RES_QUEUE, ndev->be.max_queues)) + goto err_exit; + if (init_resource_elements(ndev, RES_CAT_CFN, + ndev->be.cat.nb_cat_funcs)) + goto err_exit; + if (init_resource_elements(ndev, RES_CAT_COT, ndev->be.max_categories)) + goto err_exit; + if (init_resource_elements(ndev, RES_CAT_EXO, ndev->be.cat.nb_pm_ext)) + goto err_exit; + if (init_resource_elements(ndev, RES_CAT_LEN, ndev->be.cat.nb_len)) + goto err_exit; + if (init_resource_elements(ndev, RES_KM_FLOW_TYPE, + ndev->be.cat.nb_flow_types)) + goto err_exit; + if (init_resource_elements(ndev, RES_KM_CATEGORY, + ndev->be.km.nb_categories)) + goto err_exit; + if (init_resource_elements(ndev, RES_HSH_RCP, ndev->be.hsh.nb_rcp)) + goto err_exit; + if (init_resource_elements(ndev, RES_PDB_RCP, + ndev->be.pdb.nb_pdb_rcp_categories)) + goto err_exit; + if (init_resource_elements(ndev, RES_QSL_RCP, + ndev->be.qsl.nb_rcp_categories)) + goto err_exit; + if (init_resource_elements(ndev, RES_QSL_QST, + ndev->be.qsl.nb_qst_entries)) + goto err_exit; + if (init_resource_elements(ndev, RES_SLC_RCP, ndev->be.max_categories)) + goto err_exit; + if (init_resource_elements(ndev, RES_IOA_RCP, + ndev->be.ioa.nb_rcp_categories)) + goto err_exit; + if (init_resource_elements(ndev, RES_ROA_RCP, + ndev->be.roa.nb_tun_categories)) + goto err_exit; + if (init_resource_elements(ndev, RES_FLM_FLOW_TYPE, + ndev->be.cat.nb_flow_types)) + goto err_exit; + if (init_resource_elements(ndev, RES_FLM_RCP, + ndev->be.flm.nb_categories)) + goto err_exit; + if (init_resource_elements(ndev, RES_HST_RCP, + ndev->be.hst.nb_hst_rcp_categories)) + goto err_exit; + if (init_resource_elements(ndev, RES_TPE_RCP, + ndev->be.tpe.nb_rcp_categories)) + goto err_exit; + if (init_resource_elements(ndev, RES_TPE_EXT, + ndev->be.tpe.nb_rpl_ext_categories)) + goto err_exit; + if (init_resource_elements(ndev, RES_TPE_RPL, + ndev->be.tpe.nb_rpl_depth)) + goto err_exit; + + /* may need IPF, COR */ + + /* check all defined has been initialized */ + for (int i = 0; i < RES_COUNT; i++) + assert(ndev->res[i].alloc_bm); + + pthread_mutex_init(&ndev->mtx, NULL); + list_insert_flow_nic(ndev); + + return ndev; + +err_exit: + if (ndev) + flow_api_done(ndev); + NT_LOG(DBG, FILTER, "ERR: %s\n", __func__); + return NULL; +} + +int flow_api_done(struct flow_nic_dev *ndev) +{ + NT_LOG(DBG, FILTER, "FLOW API DONE\n"); + if (ndev) { + flow_ndev_reset(ndev); + + /* delete resource management allocations for this ndev */ + for (int i = 0; i < RES_COUNT; i++) + done_resource_elements(ndev, i); + + flow_api_backend_done(&ndev->be); + list_remove_flow_nic(ndev); + free(ndev); + } + return 0; +} + +void *flow_api_get_be_dev(struct flow_nic_dev *ndev) +{ + if (!ndev) { + NT_LOG(DBG, FILTER, "ERR: %s\n", __func__); + return NULL; + } + return ndev->be.be_dev; +} + +int flow_get_num_queues(uint8_t adapter_no, uint8_t port_no) +{ + struct flow_eth_dev *eth_dev = + nic_and_port_to_eth_dev(adapter_no, port_no); + return eth_dev->num_queues; +} + +int flow_get_hw_id(uint8_t adapter_no, uint8_t port_no, uint8_t queue_no) +{ + struct flow_eth_dev *eth_dev = + nic_and_port_to_eth_dev(adapter_no, port_no); + return eth_dev->rx_queue[queue_no].hw_id; +} + +int flow_get_flm_stats(struct flow_nic_dev *ndev, uint64_t *data, uint64_t size) +{ + if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_INLINE) + return flow_get_flm_stats_profile_inline(ndev, data, size); + return -1; +} diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api.h b/drivers/net/ntnic/nthw/flow_api/flow_api.h new file mode 100644 index 0000000000..9dbaac49e8 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_api.h @@ -0,0 +1,291 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _FLOW_API_H_ +#define _FLOW_API_H_ + +#include + +#include "ntlog.h" +#include "stream_binary_flow_api.h" + +#include "flow_api_actions.h" +#include "flow_api_backend.h" +#include "flow_api_engine.h" + +/* + * **************************************************** + * Flow NIC and Eth port device management + * **************************************************** + */ + +struct hw_mod_resource_s { + uint8_t *alloc_bm; /* allocation bitmap */ + uint32_t *ref; /* reference counter for each resource element */ + uint32_t resource_count; /* number of total available entries */ +}; + +/* + * Set of definitions to be used to map desirable fields for RSS + * hash functions. Supposed to be used with dpdk, so the values + * correspond to dpdk definitions, but we avoid dependency to + * dpdk headers here. + */ + +#define NT_ETH_RSS_IPV4 (UINT64_C(1) << 2) +#define NT_ETH_RSS_FRAG_IPV4 (UINT64_C(1) << 3) +#define NT_ETH_RSS_NONFRAG_IPV4_OTHER (UINT64_C(1) << 7) +#define NT_ETH_RSS_IPV6 (UINT64_C(1) << 8) +#define NT_ETH_RSS_FRAG_IPV6 (UINT64_C(1) << 9) +#define NT_ETH_RSS_NONFRAG_IPV6_OTHER (UINT64_C(1) << 13) +#define NT_ETH_RSS_IPV6_EX (UINT64_C(1) << 15) +#define NT_ETH_RSS_C_VLAN (UINT64_C(1) << 26) +#define NT_ETH_RSS_L3_DST_ONLY (UINT64_C(1) << 62) +#define NT_ETH_RSS_L3_SRC_ONLY (UINT64_C(1) << 63) + +#define NT_ETH_RSS_IP \ + (NT_ETH_RSS_IPV4 | NT_ETH_RSS_FRAG_IPV4 | \ + NT_ETH_RSS_NONFRAG_IPV4_OTHER | NT_ETH_RSS_IPV6 | \ + NT_ETH_RSS_FRAG_IPV6 | NT_ETH_RSS_NONFRAG_IPV6_OTHER | \ + NT_ETH_RSS_IPV6_EX) + +/* + * level 1, requests RSS to be performed on the outermost packet + * encapsulation level. + */ +#define NT_ETH_RSS_LEVEL_OUTERMOST (UINT64_C(1) << 50) + +/* + * level 2, requests RSS to be performed on the specified inner packet + * encapsulation level, from outermost to innermost (lower to higher values). + */ +#define NT_ETH_RSS_LEVEL_INNERMOST (UINT64_C(2) << 50) + +/* + * Struct wrapping unsigned 64 bit integer carry RSS hash option bits + * to avoid occasional incorrect usage interfacing with higher level + * framework (e.g. DPDK) + */ +struct nt_eth_rss { + uint64_t fields; +}; + +struct flow_eth_dev { + struct flow_nic_dev *ndev; /* NIC that owns this port device */ + uint8_t port; /* NIC port id */ + uint32_t port_id; /* App assigned port_id - may be DPDK port_id */ + + struct flow_queue_id_s + rx_queue[FLOW_MAX_QUEUES + 1]; /* 0th for exception */ + int num_queues; /* VSWITCH has exceptions sent on queue 0 per design */ + + int rss_target_id; /* QSL_HSH index if RSS needed QSL v6+ */ + struct flow_eth_dev *next; +}; + +enum flow_nic_hash_e { + HASH_ALGO_ROUND_ROBIN = 0, + HASH_ALGO_5TUPLE, +}; + +/* registered NIC backends */ +struct flow_nic_dev { + uint8_t adapter_no; /* physical adapter no in the host system */ + uint16_t ports; /* number of in-ports addressable on this NIC */ + enum flow_eth_dev_profile + flow_profile; /* flow profile this NIC is initially prepared for */ + int flow_mgnt_prepared; + + struct hw_mod_resource_s + res[RES_COUNT]; /* raw NIC resource allocation table */ + void *flm_res_handle; + void *km_res_handle; + void *kcc_res_handle; + + void *flm_mtr_handle; + void *ft_res_handle; + void *mtr_stat_handle; + void *group_handle; + + /* statistics */ + uint32_t flow_stat_id_map[MAX_COLOR_FLOW_STATS]; + + struct flow_handle + *flow_base; /* linked list of all flows created on this NIC */ + struct flow_handle * + flow_base_flm; /* linked list of all FLM flows created on this NIC */ + + struct flow_api_backend_s be; /* NIC backend API */ + struct flow_eth_dev * + eth_base; /* linked list of created eth-port devices on this NIC */ + pthread_mutex_t mtx; + + int default_qsl_drop_index; /* pre allocated default QSL Drop */ + int default_qsl_discard_index; /* pre allocated default QSL Discard */ + /* RSS hash function settings bitfields correspond to data used for hashing */ + struct nt_eth_rss + rss_hash_config; + struct flow_nic_dev *next; /* next NIC linked list */ +}; + +/* + * **************************************************** + * Error + * **************************************************** + */ + +enum flow_nic_err_msg_e { + ERR_SUCCESS = 0, + ERR_FAILED = 1, + ERR_MEMORY = 2, + ERR_OUTPUT_TOO_MANY = 3, + ERR_RSS_TOO_MANY_QUEUES = 4, + ERR_VLAN_TYPE_NOT_SUPPORTED = 5, + ERR_VXLAN_HEADER_NOT_ACCEPTED = 6, + ERR_VXLAN_POP_INVALID_RECIRC_PORT = 7, + ERR_VXLAN_POP_FAILED_CREATING_VTEP = 8, + ERR_MATCH_VLAN_TOO_MANY = 9, + ERR_MATCH_INVALID_IPV6_HDR = 10, + ERR_MATCH_TOO_MANY_TUNNEL_PORTS = 11, + ERR_MATCH_INVALID_OR_UNSUPPORTED_ELEM = 12, + ERR_MATCH_FAILED_BY_HW_LIMITS = 13, + ERR_MATCH_RESOURCE_EXHAUSTION = 14, + ERR_MATCH_FAILED_TOO_COMPLEX = 15, + ERR_ACTION_REPLICATION_FAILED = 16, + ERR_ACTION_OUTPUT_RESOURCE_EXHAUSTION = 17, + ERR_ACTION_TUNNEL_HEADER_PUSH_OUTPUT_LIMIT = 18, + ERR_ACTION_INLINE_MOD_RESOURCE_EXHAUSTION = 19, + ERR_ACTION_RETRANSMIT_RESOURCE_EXHAUSTION = 20, + ERR_ACTION_FLOW_COUNTER_EXHAUSTION = 21, + ERR_ACTION_INTERNAL_RESOURCE_EXHAUSTION = 22, + ERR_INTERNAL_QSL_COMPARE_FAILED = 23, + ERR_INTERNAL_CAT_FUNC_REUSE_FAILED = 24, + ERR_MATCH_ENTROPY_FAILED = 25, + ERR_MATCH_CAM_EXHAUSTED = 26, + ERR_INTERNAL_VIRTUAL_PORT_CREATION_FAILED = 27, + ERR_ACTION_UNSUPPORTED = 28, + ERR_REMOVE_FLOW_FAILED = 29, + ERR_ACTION_NO_OUTPUT_DEFINED_USE_DEFAULT = 30, + ERR_ACTION_NO_OUTPUT_QUEUE_FOUND = 31, + ERR_MATCH_UNSUPPORTED_ETHER_TYPE = 32, + ERR_OUTPUT_INVALID = 33, + ERR_MATCH_PARTIAL_OFFLOAD_NOT_SUPPORTED = 34, + ERR_MATCH_CAT_CAM_EXHAUSTED = 35, + ERR_MATCH_KCC_KEY_CLASH = 36, + ERR_MATCH_CAT_CAM_FAILED = 37, + ERR_PARTIAL_FLOW_MARK_TOO_BIG = 38, + ERR_FLOW_PRIORITY_VALUE_INVALID = 39, + ERR_MSG_NO_MSG +}; + +void flow_nic_set_error(enum flow_nic_err_msg_e msg, struct flow_error *error); + +/* + * **************************************************** + * Resources + * **************************************************** + */ + +extern const char *dbg_res_descr[]; + +#define flow_nic_set_bit(arr, x) \ + do { \ + uint8_t *_temp_arr = (arr); \ + size_t _temp_x = (x); \ + _temp_arr[_temp_x / 8] = (uint8_t)(_temp_arr[_temp_x / 8] | \ + (uint8_t)(1 << (_temp_x % 8))); \ + } while (0) + + + +#define flow_nic_unset_bit(arr, x) \ + do { \ + size_t _temp_x = (x); \ + arr[_temp_x / 8] &= (uint8_t)~(1 << (_temp_x % 8)); \ + } while (0) + +#define flow_nic_is_bit_set(arr, x) \ + ({ \ + size_t _temp_x = (x); \ + (arr[_temp_x / 8] & (uint8_t)(1 << (_temp_x % 8))); \ + }) + +#define flow_nic_mark_resource_used(_ndev, res_type, index) \ + do { \ + struct flow_nic_dev *_temp_ndev = (_ndev); \ + __typeof__(res_type) _temp_res_type = (res_type); \ + size_t _temp_index = (index); \ + NT_LOG(DBG, FILTER, "mark resource used: %s idx %zu\n", \ + dbg_res_descr[_temp_res_type], _temp_index); \ + assert(flow_nic_is_bit_set(_temp_ndev->res[_temp_res_type].alloc_bm, _temp_index) \ + == 0); \ + flow_nic_set_bit(_temp_ndev->res[_temp_res_type].alloc_bm, _temp_index); \ + } while (0) + + + +#define flow_nic_mark_resource_unused(_ndev, res_type, index) \ + do { \ + __typeof__(res_type) _temp_res_type = (res_type); \ + size_t _temp_index = (index); \ + NT_LOG(DBG, FILTER, "mark resource unused: %s idx %zu\n", \ + dbg_res_descr[_temp_res_type], _temp_index); \ + flow_nic_unset_bit((_ndev)->res[_temp_res_type].alloc_bm, _temp_index); \ + } while (0) + + +#define flow_nic_is_resource_used(_ndev, res_type, index) \ + (!!flow_nic_is_bit_set((_ndev)->res[res_type].alloc_bm, index)) + +int flow_nic_alloc_resource(struct flow_nic_dev *ndev, enum res_type_e res_type, + uint32_t alignment); +int flow_nic_alloc_resource_index(struct flow_nic_dev *ndev, int idx, + enum res_type_e res_type); +int flow_nic_alloc_resource_contig(struct flow_nic_dev *ndev, + enum res_type_e res_type, unsigned int num, + uint32_t alignment); +void flow_nic_free_resource(struct flow_nic_dev *ndev, enum res_type_e res_type, + int idx); + +int flow_nic_ref_resource(struct flow_nic_dev *ndev, enum res_type_e res_type, + int index); +int flow_nic_deref_resource(struct flow_nic_dev *ndev, enum res_type_e res_type, + int index); +int flow_nic_find_next_used_resource(struct flow_nic_dev *ndev, + enum res_type_e res_type, int idx_start); + +int flow_nic_allocate_fh_resource(struct flow_nic_dev *ndev, + enum res_type_e res_type, + struct flow_handle *fh, uint32_t count, + uint32_t alignment); +int flow_nic_allocate_fh_resource_index(struct flow_nic_dev *ndev, + enum res_type_e res_type, int idx, + struct flow_handle *fh); + +/* + * **************************************************** + * Other + * **************************************************** + */ + +struct flow_eth_dev *nic_and_port_to_eth_dev(uint8_t adapter_no, uint8_t port); +struct flow_nic_dev *get_nic_dev_from_adapter_no(uint8_t adapter_no); + +int flow_nic_set_hasher(struct flow_nic_dev *ndev, int hsh_idx, + enum flow_nic_hash_e algorithm); +int flow_nic_set_hasher_fields(struct flow_nic_dev *ndev, int hsh_idx, + struct nt_eth_rss fields); + +int lag_set_config(uint8_t adapter_no, enum flow_lag_cmd cmd, uint32_t index, + uint32_t value); +int lag_set_port_block(uint8_t adapter_no, uint32_t port_mask); +int lag_set_port_group(uint8_t adapter_no, uint32_t port_mask); + +int flow_get_num_queues(uint8_t adapter_no, uint8_t port_no); +int flow_get_hw_id(uint8_t adapter_no, uint8_t port_no, uint8_t queue_no); + +int flow_get_flm_stats(struct flow_nic_dev *ndev, uint64_t *data, + uint64_t size); + +#endif diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.c b/drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.c new file mode 100644 index 0000000000..fa9240cb7b --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.c @@ -0,0 +1,5118 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include +#include +#include /* sleep() */ +#include /* htons, htonl, ntohs */ +#include + +#include + +#include "ntlog.h" + +#include "flow_api_nic_setup.h" +#include "stream_binary_flow_api.h" +#include "flow_api.h" +#include "flow_api_actions.h" +#include "flow_api_backend.h" +#include "flow_api_engine.h" +#include "flow_api_profile_inline.h" + +#include + +#define UNUSED __rte_unused + +/* + * lookup refers to key A/B/C/D, and can have values 0, 1, 2, and 3. + */ +static int set_flow_type_km(struct flow_nic_dev *ndev, int cfn_index, + int flow_type, int lookup, int enable) +{ + const int max_lookups = 4; + const int cat_funcs = (int)ndev->be.cat.nb_cat_funcs / 8; + + int fte_index = + (8 * flow_type + cfn_index / cat_funcs) * max_lookups + lookup; + int fte_field = cfn_index % cat_funcs; + + uint32_t current_bm = 0; + uint32_t fte_field_bm = 1 << fte_field; + + hw_mod_cat_fte_km_get(&ndev->be, HW_CAT_FTE_ENABLE_BM, KM_FLM_IF_FIRST, + fte_index, ¤t_bm); + + uint32_t final_bm = enable ? (fte_field_bm | current_bm) : + (~fte_field_bm & current_bm); + + if (current_bm != final_bm) { + hw_mod_cat_fte_km_set(&ndev->be, HW_CAT_FTE_ENABLE_BM, + KM_FLM_IF_FIRST, fte_index, final_bm); + hw_mod_cat_fte_km_flush(&ndev->be, KM_FLM_IF_FIRST, fte_index, + 1); + } + + return 0; +} + +/* + * lookup refers to key A/B/C/D, and can have values 0, 1, 2, and 3. + */ +static int set_flow_type_flm(struct flow_nic_dev *ndev, int cfn_index, + int flow_type, int lookup, int enable) +{ + const int max_lookups = 4; + const int cat_funcs = (int)ndev->be.cat.nb_cat_funcs / 8; + + int fte_index = + (8 * flow_type + cfn_index / cat_funcs) * max_lookups + lookup; + int fte_field = cfn_index % cat_funcs; + + uint32_t current_bm = 0; + uint32_t fte_field_bm = 1 << fte_field; + + hw_mod_cat_fte_flm_get(&ndev->be, HW_CAT_FTE_ENABLE_BM, KM_FLM_IF_FIRST, + fte_index, ¤t_bm); + + uint32_t final_bm = enable ? (fte_field_bm | current_bm) : + (~fte_field_bm & current_bm); + + if (current_bm != final_bm) { + hw_mod_cat_fte_flm_set(&ndev->be, HW_CAT_FTE_ENABLE_BM, + KM_FLM_IF_FIRST, fte_index, final_bm); + hw_mod_cat_fte_flm_flush(&ndev->be, KM_FLM_IF_FIRST, fte_index, + 1); + } + + return 0; +} + +static int rx_queue_idx_to_hw_id(struct flow_eth_dev *dev, int id) +{ + for (int i = 0; i < dev->num_queues; ++i) { + if (dev->rx_queue[i].id == id) + return dev->rx_queue[i].hw_id; + } + return -1; +} + +/* + * Flow Matcher functionality + */ + +static int flm_sdram_calibrate(struct flow_nic_dev *ndev) +{ + int success = 0; + + hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_PRESET_ALL, 0x0); + hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_SPLIT_SDRAM_USAGE, + 0x10); + hw_mod_flm_control_flush(&ndev->be); + + /* Wait for ddr4 calibration/init done */ + for (uint32_t i = 0; i < 1000000; ++i) { + uint32_t value = 0; + + hw_mod_flm_status_update(&ndev->be); + hw_mod_flm_status_get(&ndev->be, HW_FLM_STATUS_CALIBDONE, + &value); + if (value) { + success = 1; + break; + } + usleep(1); + } + + if (!success) { + /* "Flow matcher initialization failed - SDRAM calibration failed"; */ + return -1; + } + + /* Set the flow scrubber and timeout settings */ + hw_mod_flm_timeout_set(&ndev->be, HW_FLM_TIMEOUT_T, 0); + hw_mod_flm_timeout_flush(&ndev->be); + + hw_mod_flm_scrub_set(&ndev->be, HW_FLM_SCRUB_I, 100); + hw_mod_flm_scrub_flush(&ndev->be); + + return 0; +} + +static int flm_sdram_reset(struct flow_nic_dev *ndev, int enable) +{ + int success = 0; + + /* + * Make sure no lookup is performed during init, i.e. + * disable every category and disable FLM + */ + hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_ENABLE, 0x0); + hw_mod_flm_control_flush(&ndev->be); + + for (uint32_t i = 1; i < ndev->be.flm.nb_categories; ++i) + hw_mod_flm_rcp_set(&ndev->be, HW_FLM_RCP_PRESET_ALL, i, 0x0); + hw_mod_flm_rcp_flush(&ndev->be, 1, ndev->be.flm.nb_categories - 1); + + /* Wait for FLM to enter Idle state */ + for (uint32_t i = 0; i < 1000000; ++i) { + uint32_t value = 0; + + hw_mod_flm_status_update(&ndev->be); + hw_mod_flm_status_get(&ndev->be, HW_FLM_STATUS_IDLE, &value); + if (value) { + success = 1; + break; + } + usleep(1); + } + + if (!success) { + /* "Flow matcher initialization failed - never idle"; */ + return -1; + } + + success = 0; + + /* Start SDRAM initialization */ + hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_INIT, 0x1); + hw_mod_flm_control_flush(&ndev->be); + + for (uint32_t i = 0; i < 1000000; ++i) { + uint32_t value = 0; + + hw_mod_flm_status_update(&ndev->be); + hw_mod_flm_status_get(&ndev->be, HW_FLM_STATUS_INITDONE, + &value); + if (value) { + success = 1; + break; + } + usleep(1); + } + + if (!success) { + /* "Flow matcher initialization failed - SDRAM initialization incomplete"; */ + return -1; + } + + /* Set the INIT value back to zero to clear the bit in the SW register cache */ + hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_INIT, 0x0); + hw_mod_flm_control_flush(&ndev->be); + + /* Enable FLM */ + hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_ENABLE, enable); + hw_mod_flm_control_flush(&ndev->be); + + return 0; +} + +#define FLM_FLOW_RCP_MAX 32 +#define FLM_FLOW_FT_MAX 16 + +struct flm_flow_ft_ident_s { + union { + struct { + uint64_t in_use : 1; + uint64_t drop : 1; + uint64_t ltx_en : 1; + uint64_t ltx_port : 1; + uint64_t queue_en : 1; + uint64_t queue : 8; + uint64_t encap_len : 8; + uint64_t encap_vlans : 2; + uint64_t encap_ip : 1; + uint64_t decap_end : 5; + uint64_t jump_to_group : 8; + uint64_t pad : 27; + }; + uint64_t data; + }; +}; + +struct flm_flow_key_def_s { + union { + struct { + uint64_t qw0_dyn : 7; + uint64_t qw0_ofs : 8; + uint64_t qw4_dyn : 7; + uint64_t qw4_ofs : 8; + uint64_t sw8_dyn : 7; + uint64_t sw8_ofs : 8; + uint64_t sw9_dyn : 7; + uint64_t sw9_ofs : 8; + uint64_t outer_proto : 1; + uint64_t inner_proto : 1; + uint64_t pad : 2; + }; + uint64_t data; + }; +}; + +static struct flm_flow_ft_ident_s flow_def_to_ft_ident(struct nic_flow_def *fd) +{ + struct flm_flow_ft_ident_s ft_ident; + + assert(sizeof(struct flm_flow_ft_ident_s) == sizeof(uint64_t)); + + memset(&ft_ident, 0x0, sizeof(struct flm_flow_ft_ident_s)); + ft_ident.in_use = 1; + + if (fd->dst_num_avail == 0) { + ft_ident.drop = 1; + } else { + for (int i = 0; i < fd->dst_num_avail; ++i) { + if (fd->dst_id[i].type == PORT_PHY) { + ft_ident.ltx_en = 1; + ft_ident.ltx_port = fd->dst_id[i].id; + } else if (fd->dst_id[i].type == PORT_VIRT) { + ft_ident.queue_en = 1; + ft_ident.queue = fd->dst_id[i].id; + } + } + } + + if (fd->tun_hdr.len > 0) { + ft_ident.encap_len = fd->tun_hdr.len; + ft_ident.encap_vlans = fd->tun_hdr.nb_vlans & 0x3; + ft_ident.encap_ip = fd->tun_hdr.ip_version == 4 ? 0 : 1; + } + + ft_ident.decap_end = fd->header_strip_end_dyn & 0x1f; + + if (fd->jump_to_group != UINT32_MAX) + ft_ident.jump_to_group = fd->jump_to_group & 0xff; + + return ft_ident; +} + +static inline void set_key_def_qw(struct flm_flow_key_def_s *key_def, + unsigned int qw, unsigned int dyn, + unsigned int ofs) +{ + assert(qw < 2); + if (qw == 0) { + key_def->qw0_dyn = dyn & 0x7f; + key_def->qw0_ofs = ofs & 0xff; + } else { + key_def->qw4_dyn = dyn & 0x7f; + key_def->qw4_ofs = ofs & 0xff; + } +} + +static inline void set_key_def_sw(struct flm_flow_key_def_s *key_def, + unsigned int sw, unsigned int dyn, + unsigned int ofs) +{ + assert(sw < 2); + if (sw == 0) { + key_def->sw8_dyn = dyn & 0x7f; + key_def->sw8_ofs = ofs & 0xff; + } else { + key_def->sw9_dyn = dyn & 0x7f; + key_def->sw9_ofs = ofs & 0xff; + } +} + +struct flm_flow_group_s { + int cfn_group0; + int km_ft_group0; + struct flow_handle *fh_group0; + + struct flm_flow_key_def_s key_def; + + int miss_enabled; + + struct flm_flow_group_ft_s { + struct flm_flow_ft_ident_s ident; + struct flow_handle *fh; + } ft[FLM_FLOW_FT_MAX]; + + uint32_t cashed_ft_index; +}; + +struct flm_flow_handle_s { + struct flm_flow_group_s groups[FLM_FLOW_RCP_MAX]; +}; + +static void flm_flow_handle_create(void **handle) +{ + struct flm_flow_handle_s *flm_handle; + + if (!*handle) + *handle = calloc(1, sizeof(struct flm_flow_handle_s)); + + else + memset(*handle, 0x0, sizeof(struct flm_flow_handle_s)); + + flm_handle = (struct flm_flow_handle_s *)*handle; + + for (int i = 0; i < FLM_FLOW_RCP_MAX; ++i) { + flm_handle->groups[i].cfn_group0 = -1; + flm_handle->groups[i].fh_group0 = NULL; + } +} + +static void flm_flow_handle_remove(void **handle) +{ + free(*handle); + *handle = NULL; +} + +static int flm_flow_setup_group(struct flow_eth_dev *dev, uint32_t group_index, + int cfn, int km_ft, struct flow_handle *fh) +{ + struct flm_flow_handle_s *flm_handle = + (struct flm_flow_handle_s *)dev->ndev->flm_res_handle; + struct flm_flow_group_s *flm_group; + + if (group_index >= FLM_FLOW_RCP_MAX) { + NT_LOG(ERR, FILTER, + "FLM: Invalid index for FLM programming: Group=%d\n", + (int)group_index); + return -1; + } + + flm_group = &flm_handle->groups[group_index]; + + flm_group->cfn_group0 = cfn; + flm_group->km_ft_group0 = km_ft; + flm_group->fh_group0 = fh; + flm_group->miss_enabled = 0; + + return 0; +} + +static int flm_flow_destroy_group(struct flow_eth_dev *dev, + uint32_t group_index) +{ + struct flm_flow_handle_s *flm_handle = + (struct flm_flow_handle_s *)dev->ndev->flm_res_handle; + struct flm_flow_group_s *flm_group; + + if (group_index >= FLM_FLOW_RCP_MAX) { + NT_LOG(ERR, FILTER, + "FLM: Invalid index for FLM programming: Group=%d\n", + (int)group_index); + return -1; + } + + flm_group = &flm_handle->groups[group_index]; + + memset(flm_group, 0x0, sizeof(struct flm_flow_group_s)); + flm_group->cfn_group0 = -1; + + return 0; +} + +static int flm_flow_get_group_miss_fh(struct flow_eth_dev *dev, + uint32_t group_index, + struct flow_handle **fh_miss) +{ + struct flm_flow_handle_s *flm_handle = + (struct flm_flow_handle_s *)dev->ndev->flm_res_handle; + + if (group_index >= FLM_FLOW_RCP_MAX) { + NT_LOG(ERR, FILTER, + "FLM: Invalid index for FLM programming: Group=%d\n", + (int)group_index); + return -1; + } + + *fh_miss = flm_handle->groups[group_index].fh_group0; + + return 0; +} + +static int flm_flow_setup_rcp(struct flow_eth_dev *dev, + struct flm_flow_key_def_s *key_def, + uint32_t *packet_mask, uint32_t group_index) +{ + if (group_index >= FLM_FLOW_RCP_MAX) { + NT_LOG(ERR, FILTER, + "FLM: Invalid index for FLM programming: Group=%d\n", + (int)group_index); + return -1; + } + + uint32_t flm_mask[10] = { + packet_mask[0], /* SW9 */ + packet_mask[1], /* SW8 */ + packet_mask[5], packet_mask[4], + packet_mask[3], packet_mask[2], /* QW4 */ + packet_mask[9], packet_mask[8], + packet_mask[7], packet_mask[6], /* QW0 */ + }; + + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_LOOKUP, group_index, 1); + + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_QW0_DYN, group_index, + key_def->qw0_dyn); + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_QW0_OFS, group_index, + key_def->qw0_ofs); + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_QW0_SEL, group_index, 0); + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_QW4_DYN, group_index, + key_def->qw4_dyn); + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_QW4_OFS, group_index, + key_def->qw4_ofs); + + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_SW8_DYN, group_index, + key_def->sw8_dyn); + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_SW8_OFS, group_index, + key_def->sw8_ofs); + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_SW8_SEL, group_index, 0); + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_SW9_DYN, group_index, + key_def->sw9_dyn); + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_SW9_OFS, group_index, + key_def->sw9_ofs); + + hw_mod_flm_rcp_set_mask(&dev->ndev->be, HW_FLM_RCP_MASK, group_index, + flm_mask); + + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_KID, group_index, + group_index + 2); + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_OPN, group_index, + key_def->outer_proto); + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_IPN, group_index, + key_def->inner_proto); + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_BYT_DYN, group_index, 0); + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_BYT_OFS, group_index, + -20); + + hw_mod_flm_rcp_flush(&dev->ndev->be, group_index, 1); + + return 0; +} + +static int flm_flow_destroy_rcp(struct flow_eth_dev *dev, uint32_t group_index) +{ + struct flm_flow_handle_s *flm_handle = + (struct flm_flow_handle_s *)dev->ndev->flm_res_handle; + struct flm_flow_group_s *flm_group; + + if (group_index >= FLM_FLOW_RCP_MAX) { + NT_LOG(ERR, FILTER, + "FLM: Invalid index for FLM programming: Group=%d\n", + (int)group_index); + return -1; + } + + flm_group = &flm_handle->groups[group_index]; + + hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_PRESET_ALL, group_index, + 0); + hw_mod_flm_rcp_flush(&dev->ndev->be, group_index, 1); + + if (flm_group->miss_enabled) { + uint32_t bm = 0; + + /* Change group 0 FLM RCP selection to point to 0 */ + hw_mod_cat_kcs_flm_set(&dev->ndev->be, HW_CAT_KCS_CATEGORY, + KM_FLM_IF_FIRST, flm_group->cfn_group0, + 0); + hw_mod_cat_kcs_flm_flush(&dev->ndev->be, KM_FLM_IF_FIRST, + flm_group->cfn_group0, 1); + + /* Change group 0 FT MISS to FT UNHANDLED */ + set_flow_type_flm(dev->ndev, flm_group->cfn_group0, 0, 2, 0); + set_flow_type_flm(dev->ndev, flm_group->cfn_group0, 1, 2, 1); + + /* Finally, disable FLM for group 0 */ + hw_mod_cat_kce_flm_get(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM, + KM_FLM_IF_FIRST, + flm_group->cfn_group0 / 8, &bm); + hw_mod_cat_kce_flm_set(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM, + KM_FLM_IF_FIRST, flm_group->cfn_group0 / 8, + bm & ~(1 << (flm_group->cfn_group0 % 8))); + hw_mod_cat_kce_flm_flush(&dev->ndev->be, KM_FLM_IF_FIRST, + flm_group->cfn_group0 / 8, 1); + + memset(&flm_group->key_def, 0x0, + sizeof(struct flm_flow_key_def_s)); + flm_group->miss_enabled = 0; + } + + return 0; +} + +static int flm_flow_learn_prepare(struct flow_eth_dev *dev, + struct flow_handle *fh, uint32_t group_index, + struct flm_flow_key_def_s *key_def, + uint32_t *packet_mask, + /* Return values */ + uint32_t *kid, uint32_t *ft, int *cfn_to_copy, + int *cfn_to_copy_km_ft, + struct flow_handle **fh_existing) +{ + struct flm_flow_handle_s *flm_handle = + (struct flm_flow_handle_s *)dev->ndev->flm_res_handle; + struct flm_flow_group_s *flm_group; + struct flm_flow_ft_ident_s temp_ft_ident; + struct nic_flow_def *fd = fh->fd; + + if (group_index >= FLM_FLOW_RCP_MAX) { + NT_LOG(ERR, FILTER, + "FLM: Invalid index for FLM programming: Group=%d\n", + (int)group_index); + return -1; + } + + flm_group = &flm_handle->groups[group_index]; + + if (flm_group->cfn_group0 < 0) { + NT_LOG(ERR, FILTER, + "FLM: Attempt to program to a unset CFN: Group=%d\n", + (int)group_index); + return -1; + } + + if (!flm_group->miss_enabled) { + uint32_t bm = 0; + + if (flow_nic_allocate_fh_resource_index(dev->ndev, RES_FLM_RCP, + (int)group_index, fh)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not get FLM RCP resource\n"); + return -1; + } + + /* Change group 0 FLM RCP selection to point to "group_index" */ + hw_mod_cat_kcs_flm_set(&dev->ndev->be, HW_CAT_KCS_CATEGORY, + KM_FLM_IF_FIRST, flm_group->cfn_group0, + group_index); + hw_mod_cat_kcs_flm_flush(&dev->ndev->be, KM_FLM_IF_FIRST, + flm_group->cfn_group0, 1); + + /* Setup FLM RCP "group_index" */ + flm_flow_setup_rcp(dev, key_def, packet_mask, group_index); + + /* + * Change group 0 FT UNHANDLED to FT MISS + * Note: Once this step is done, the filter is invalid until the KCE step is done + */ + set_flow_type_flm(dev->ndev, flm_group->cfn_group0, 1, 2, 0); + set_flow_type_flm(dev->ndev, flm_group->cfn_group0, 0, 2, 1); + + /* Finally, enable FLM for group 0 */ + hw_mod_cat_kce_flm_get(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM, + KM_FLM_IF_FIRST, + flm_group->cfn_group0 / 8, &bm); + hw_mod_cat_kce_flm_set(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM, + KM_FLM_IF_FIRST, + flm_group->cfn_group0 / 8, + bm | (1 << (flm_group->cfn_group0 % 8))); + hw_mod_cat_kce_flm_flush(&dev->ndev->be, KM_FLM_IF_FIRST, + flm_group->cfn_group0 / 8, 1); + + flm_group->key_def.data = key_def->data; + flm_group->miss_enabled = 1; + } + + if (flm_group->key_def.data != key_def->data) { + NT_LOG(ERR, FILTER, + "FLM: Attempt to program 2 different types of flows into group=%d\n", + (int)group_index); + return -1; + } + + /* Create action set */ + memset(&temp_ft_ident, 0x0, sizeof(struct flm_flow_ft_ident_s)); + temp_ft_ident.in_use = 1; + + if (fd->dst_num_avail == 0) { + temp_ft_ident.drop = 1; + } else { + for (int i = 0; i < fd->dst_num_avail; ++i) { + if (fd->dst_id[i].type == PORT_PHY) { + temp_ft_ident.ltx_en = 1; + temp_ft_ident.ltx_port = fd->dst_id[i].id; + } else if (fd->dst_id[i].type == PORT_VIRT) { + temp_ft_ident.queue_en = 1; + temp_ft_ident.queue = fd->dst_id[i].id; + } + } + } + + /* Set encap/decap data */ + if (fd->tun_hdr.len > 0) { + temp_ft_ident.encap_len = fd->tun_hdr.len; + temp_ft_ident.encap_vlans = fd->tun_hdr.nb_vlans & 0x3; + temp_ft_ident.encap_ip = fd->tun_hdr.ip_version == 4 ? 0 : 1; + } + + temp_ft_ident.decap_end = fd->header_strip_end_dyn & 0x1f; + + /* Find ft ident or create a new one */ + uint32_t ft_index = 0; + + if (flm_group->cashed_ft_index > 0 && + flm_group->ft[flm_group->cashed_ft_index].ident.data == + temp_ft_ident.data) { + ft_index = flm_group->cashed_ft_index; + *fh_existing = flm_group->ft[ft_index].fh; + } else { + for (ft_index = 2; ft_index < FLM_FLOW_FT_MAX; ++ft_index) { + struct flm_flow_ft_ident_s *ft_ident = + &flm_group->ft[ft_index].ident; + if (ft_ident->data == 0) { + ft_ident->data = temp_ft_ident.data; + *cfn_to_copy = flm_group->cfn_group0; + *cfn_to_copy_km_ft = flm_group->km_ft_group0; + flm_group->ft[ft_index].fh = fh; + fh->flm_group_index = (uint8_t)group_index; + fh->flm_ft_index = (uint8_t)ft_index; + break; + } else if (ft_ident->data == temp_ft_ident.data) { + *fh_existing = flm_group->ft[ft_index].fh; + break; + } + } + + if (ft_index >= FLM_FLOW_FT_MAX) { + NT_LOG(ERR, FILTER, "FLM: FT resource not available\n"); + return -1; + } + + flm_group->cashed_ft_index = ft_index; + } + + /* Set return values */ + *kid = group_index + 2; + *ft = ft_index; + + return 0; +} + +static int flow_flm_destroy_owner(struct flow_eth_dev *dev, + struct flow_handle *fh) +{ + int error = 0; + + struct flm_flow_handle_s *flm_handle = + (struct flm_flow_handle_s *)dev->ndev->flm_res_handle; + struct flm_flow_group_s *flm_group = + &flm_handle->groups[fh->flm_group_index]; + + memset(&flm_group->ft[fh->flm_ft_index], 0x0, + sizeof(struct flm_flow_group_ft_s)); + + error |= set_flow_type_flm(dev->ndev, fh->resource[RES_CAT_CFN].index, + flm_group->km_ft_group0, 0, 0); + error |= set_flow_type_flm(dev->ndev, fh->resource[RES_CAT_CFN].index, + (int)fh->flm_ft_index, 2, 0); + + return error; +} + +#define FLM_MTR_PROFILE_SIZE 0x100000 + +struct flm_flow_mtr_handle_s { + struct dual_buckets_s { + uint16_t rate_a; + uint16_t rate_b; + uint16_t size_a; + uint16_t size_b; + } dual_buckets[FLM_MTR_PROFILE_SIZE]; +}; + +int flow_mtr_supported(struct flow_eth_dev *dev) +{ + return hw_mod_flm_present(&dev->ndev->be) && + dev->ndev->be.flm.nb_variant == 2; +} + +uint64_t flow_mtr_meter_policy_n_max(void) +{ + return FLM_MTR_PROFILE_SIZE; +} + +static inline uint64_t convert_to_bucket_size_units(uint64_t value) +{ + /* Assumes a 40-bit int as input */ + uint64_t lo_bits = (value & 0xfffff) * 1000000000; + uint64_t hi_bits = ((value >> 20) & 0xfffff) * 1000000000; + uint64_t round_up = + (hi_bits & 0xfffff) || (lo_bits & 0xffffffffff) ? 1 : 0; + return (hi_bits >> 20) + (lo_bits >> 40) + round_up; +} + +int flow_mtr_set_profile(struct flow_eth_dev *dev, uint32_t profile_id, + uint64_t bucket_rate_a, uint64_t bucket_size_a, + uint64_t bucket_rate_b, uint64_t bucket_size_b) +{ + struct flow_nic_dev *ndev = dev->ndev; + struct flm_flow_mtr_handle_s *handle = + (struct flm_flow_mtr_handle_s *)ndev->flm_mtr_handle; + struct dual_buckets_s *buckets = &handle->dual_buckets[profile_id]; + + uint64_t bucket_rate_shift_a = 0; + uint64_t bucket_rate_shift_b = 0; + + uint64_t bucket_size_shift_a = 0; + uint64_t bucket_size_shift_b = 0; + + /* Round rates up to nearest 128 bytes/sec and shift to 128 bytes/sec units */ + bucket_rate_a = (bucket_rate_a & 0x7f) ? (bucket_rate_a >> 7) + 1 : + (bucket_rate_a >> 7); + bucket_rate_b = (bucket_rate_b & 0x7f) ? (bucket_rate_b >> 7) + 1 : + (bucket_rate_b >> 7); + + /* Round rate down to max rate supported */ + if (bucket_rate_a > 0x7ff8000) + bucket_rate_a = 0x7ff8000; + if (bucket_rate_b > 0x7ff8000) + bucket_rate_b = 0x7ff8000; + + /* Find shift to convert into 12-bit int */ + while ((bucket_rate_a >> bucket_rate_shift_a) > 0xfff) + bucket_rate_shift_a += 1; + while ((bucket_rate_b >> bucket_rate_shift_b) > 0xfff) + bucket_rate_shift_b += 1; + + /* Store in format [11:0] shift-left [15:12] */ + buckets->rate_a = (bucket_rate_a >> bucket_rate_shift_a) | + (bucket_rate_shift_a << 12); + buckets->rate_b = (bucket_rate_b >> bucket_rate_shift_b) | + (bucket_rate_shift_b << 12); + + /* Round size down to 38-bit int */ + if (bucket_size_a > 0x3fffffffff) + bucket_size_a = 0x3fffffffff; + if (bucket_size_b > 0x3fffffffff) + bucket_size_b = 0x3fffffffff; + + /* Convert size to units of 2^40 / 10^9. Output is a 28-bit int. */ + bucket_size_a = convert_to_bucket_size_units(bucket_size_a); + bucket_size_b = convert_to_bucket_size_units(bucket_size_b); + + /* Round rate down to max rate supported */ + if (bucket_size_a > 0x7ff8000) + bucket_size_a = 0x7ff8000; + if (bucket_size_b > 0x7ff8000) + bucket_size_b = 0x7ff8000; + + /* Find shift to convert into 12-bit int */ + while ((bucket_size_a >> bucket_size_shift_a) > 0xfff) + bucket_size_shift_a += 1; + while ((bucket_size_b >> bucket_size_shift_b) > 0xfff) + bucket_size_shift_b += 1; + + /* Store in format [11:0] shift-left [15:12] */ + buckets->size_a = (bucket_size_a >> bucket_size_shift_a) | + (bucket_size_shift_a << 12); + buckets->size_b = (bucket_size_b >> bucket_size_shift_b) | + (bucket_size_shift_b << 12); + + return 0; +} + +int flow_mtr_set_policy(UNUSED struct flow_eth_dev *dev, + UNUSED uint32_t policy_id, UNUSED int drop) +{ + return 0; +} + +#define FLM_MTR_STAT_SIZE 0x1000000 +#define WORDS_PER_INF_DATA \ + (sizeof(struct flm_v17_inf_data_s) / sizeof(uint32_t)) +#define MAX_INF_DATA_RECORDS_PER_READ 20 +#define UINT64_MSB ((uint64_t)1 << 63) + +/* 2^23 bytes ~ 8MB */ +#define FLM_PERIODIC_STATS_BYTE_LIMIT 8 +/* 2^16 pkt ~ 64K pkt */ +#define FLM_PERIODIC_STATS_PKT_LIMIT 5 +/* 2^38 ns ~ 275 sec */ +#define FLM_PERIODIC_STATS_BYTE_TIMEOUT 23 + +uint32_t flow_mtr_meters_supported(void) +{ + return FLM_MTR_STAT_SIZE; +} + +struct mtr_stat_s { + struct dual_buckets_s *buckets; + + volatile atomic_uint_fast64_t n_pkt; + volatile atomic_uint_fast64_t n_bytes; + uint64_t n_pkt_base; + uint64_t n_bytes_base; + volatile atomic_uint_fast64_t stats_mask; +}; + +#define WORDS_PER_LEARN_DATA sizeof(struct flm_v17_lrn_data_s) +#define FLM_PROG_MAX_RETRY 100 + +static uint32_t flm_read_inf_rec_locked(struct flow_eth_dev *dev, + uint32_t *data); + +static int flow_flm_apply(struct flow_eth_dev *dev, + struct flm_v17_lrn_data_s *learn_record) +{ + uint32_t lrn_ready; + uint32_t retry = 0; + uint32_t data[WORDS_PER_INF_DATA * MAX_INF_DATA_RECORDS_PER_READ]; + + hw_mod_flm_buf_ctrl_get(&dev->ndev->be, HW_FLM_BUF_CTRL_LRN_FREE, + &lrn_ready); + if (lrn_ready < WORDS_PER_LEARN_DATA) { + hw_mod_flm_buf_ctrl_update(&dev->ndev->be); + hw_mod_flm_buf_ctrl_get(&dev->ndev->be, + HW_FLM_BUF_CTRL_LRN_FREE, &lrn_ready); + while (lrn_ready < WORDS_PER_LEARN_DATA) { + ++retry; + if (retry > FLM_PROG_MAX_RETRY) + return 1; + + flm_read_inf_rec_locked(dev, data); + + hw_mod_flm_buf_ctrl_update(&dev->ndev->be); + hw_mod_flm_buf_ctrl_get(&dev->ndev->be, + HW_FLM_BUF_CTRL_LRN_FREE, + &lrn_ready); + } + } + + int res = hw_mod_flm_lrn_data_set_flush(&dev->ndev->be, + HW_FLM_FLOW_LRN_DATA_V17, + (uint32_t *)learn_record); + return res; +} + +int flow_mtr_create_meter(struct flow_eth_dev *dev, uint32_t mtr_id, + uint32_t profile_id, UNUSED uint32_t policy_id, + uint64_t stats_mask) +{ + pthread_mutex_lock(&dev->ndev->mtx); + + struct flm_flow_mtr_handle_s *handle = + (struct flm_flow_mtr_handle_s *)dev->ndev->flm_mtr_handle; + struct dual_buckets_s *buckets = &handle->dual_buckets[profile_id]; + + struct flm_v17_lrn_data_s learn_record; + + memset(&learn_record, 0x0, sizeof(struct flm_v17_lrn_data_s)); + + learn_record.sw9 = mtr_id + 1; + learn_record.kid = 1; + + learn_record.rate = buckets->rate_a; + learn_record.size = buckets->size_a; + learn_record.fill = buckets->size_a & 0x0fff; + + learn_record.ft_mbr = 15; /* FT to assign if MBR has been exceeded */ + + learn_record.ent = 1; + learn_record.op = 1; + learn_record.eor = 1; + + learn_record.id[0] = mtr_id & 0xff; + learn_record.id[1] = (mtr_id >> 8) & 0xff; + learn_record.id[2] = (mtr_id >> 16) & 0xff; + learn_record.id[3] = (mtr_id >> 24) & 0xff; + learn_record.id[8] = 1U << 7; + + if (stats_mask) + learn_record.vol_idx = 1; + + int res = flow_flm_apply(dev, &learn_record); + + if (res == 0) { + struct mtr_stat_s *mtr_stat = dev->ndev->mtr_stat_handle; + + mtr_stat[mtr_id].buckets = buckets; + atomic_store(&mtr_stat[mtr_id].stats_mask, stats_mask); + } + + pthread_mutex_unlock(&dev->ndev->mtx); + + return res; +} + +int flow_mtr_destroy_meter(struct flow_eth_dev *dev, uint32_t mtr_id) +{ + pthread_mutex_lock(&dev->ndev->mtx); + + struct flm_v17_lrn_data_s learn_record; + + memset(&learn_record, 0x0, sizeof(struct flm_v17_lrn_data_s)); + + learn_record.sw9 = mtr_id + 1; + learn_record.kid = 1; + + learn_record.ent = 1; + learn_record.op = 0; + learn_record.eor = 1; + + learn_record.id[0] = mtr_id & 0xff; + learn_record.id[1] = (mtr_id >> 8) & 0xff; + learn_record.id[2] = (mtr_id >> 16) & 0xff; + learn_record.id[3] = (mtr_id >> 24) & 0xff; + learn_record.id[8] = 1U << 7; + + /* Clear statistics so stats_mask prevents updates of counters on deleted meters */ + struct mtr_stat_s *mtr_stat = dev->ndev->mtr_stat_handle; + + atomic_store(&mtr_stat[mtr_id].stats_mask, 0); + atomic_store(&mtr_stat[mtr_id].n_bytes, 0); + atomic_store(&mtr_stat[mtr_id].n_pkt, 0); + mtr_stat[mtr_id].n_bytes_base = 0; + mtr_stat[mtr_id].n_pkt_base = 0; + mtr_stat[mtr_id].buckets = NULL; + + int res = flow_flm_apply(dev, &learn_record); + + pthread_mutex_unlock(&dev->ndev->mtx); + + return res; +} + +int flm_mtr_adjust_stats(struct flow_eth_dev *dev, uint32_t mtr_id, + uint32_t adjust_value) +{ + pthread_mutex_lock(&dev->ndev->mtx); + + struct mtr_stat_s *mtr_stat = + &((struct mtr_stat_s *)dev->ndev->mtr_stat_handle)[mtr_id]; + + struct flm_v17_lrn_data_s learn_record; + + memset(&learn_record, 0x0, sizeof(struct flm_v17_lrn_data_s)); + + learn_record.sw9 = mtr_id + 1; + learn_record.kid = 1; + + learn_record.rate = mtr_stat->buckets->rate_a; + learn_record.size = mtr_stat->buckets->size_a; + learn_record.adj = adjust_value; + + learn_record.ft_mbr = 15; + + learn_record.ent = 1; + learn_record.op = 2; + learn_record.eor = 1; + + if (atomic_load(&mtr_stat->stats_mask)) + learn_record.vol_idx = 1; + + int res = flow_flm_apply(dev, &learn_record); + + pthread_mutex_unlock(&dev->ndev->mtx); + + return res; +} + +static uint32_t flm_read_inf_rec_locked(struct flow_eth_dev *dev, + uint32_t *data) +{ + uint32_t inf_cnt = 0; + + hw_mod_flm_buf_ctrl_get(&dev->ndev->be, HW_FLM_BUF_CTRL_INF_AVAIL, + &inf_cnt); + if (inf_cnt < WORDS_PER_INF_DATA) { + hw_mod_flm_buf_ctrl_update(&dev->ndev->be); + hw_mod_flm_buf_ctrl_get(&dev->ndev->be, + HW_FLM_BUF_CTRL_INF_AVAIL, &inf_cnt); + } + + uint32_t records_to_read = inf_cnt / WORDS_PER_INF_DATA; + + if (records_to_read == 0) + return 0; + if (records_to_read > MAX_INF_DATA_RECORDS_PER_READ) + records_to_read = MAX_INF_DATA_RECORDS_PER_READ; + + hw_mod_flm_inf_data_update_get(&dev->ndev->be, HW_FLM_FLOW_INF_DATA_V17, + data, + records_to_read * WORDS_PER_INF_DATA); + + return records_to_read; +} + +uint32_t flm_mtr_update_stats(struct flow_eth_dev *dev) +{ + uint32_t data[WORDS_PER_INF_DATA * MAX_INF_DATA_RECORDS_PER_READ]; + + pthread_mutex_lock(&dev->ndev->mtx); + uint32_t records = flm_read_inf_rec_locked(dev, data); + + pthread_mutex_unlock(&dev->ndev->mtx); + + struct mtr_stat_s *mtr_stat = dev->ndev->mtr_stat_handle; + + for (uint32_t i = 0; i < records; ++i) { + uint32_t *p_record = &data[i * WORDS_PER_INF_DATA]; + + /* Check that received record hold valid meter statistics */ + if ((p_record[6] < flow_mtr_meters_supported() && + p_record[7] == 0 && (p_record[8] >> 31) == 1)) { + uint32_t id = p_record[6]; + + /* Don't update a deleted meter */ + uint64_t stats_mask = + atomic_load(&mtr_stat[id].stats_mask); + if (stats_mask) { + uint64_t nb = ((uint64_t)p_record[1] << 32) | + p_record[0]; + uint64_t np = ((uint64_t)p_record[3] << 32) | + p_record[2]; + + atomic_store(&mtr_stat[id].n_pkt, + np | UINT64_MSB); + atomic_store(&mtr_stat[id].n_bytes, nb); + atomic_store(&mtr_stat[id].n_pkt, np); + } + } + } + + return records; +} + +void flm_mtr_read_stats(struct flow_eth_dev *dev, uint32_t id, + uint64_t *stats_mask, uint64_t *green_pkt, + uint64_t *green_bytes, int clear) +{ + struct mtr_stat_s *mtr_stat = dev->ndev->mtr_stat_handle; + *stats_mask = atomic_load(&mtr_stat[id].stats_mask); + if (*stats_mask) { + uint64_t pkt_1; + uint64_t pkt_2; + uint64_t nb; + + do { + do { + pkt_1 = atomic_load(&mtr_stat[id].n_pkt); + } while (pkt_1 & UINT64_MSB); + nb = atomic_load(&mtr_stat[id].n_bytes); + pkt_2 = atomic_load(&mtr_stat[id].n_pkt); + } while (pkt_1 != pkt_2); + + *green_pkt = pkt_1 - mtr_stat[id].n_pkt_base; + *green_bytes = nb - mtr_stat[id].n_bytes_base; + if (clear) { + mtr_stat[id].n_pkt_base = pkt_1; + mtr_stat[id].n_bytes_base = nb; + } + } +} + +static inline uint8_t convert_port_to_ifr_mtu_recipe(uint32_t port) +{ + return port + 1; +} + +static uint8_t get_port_from_port_id(struct flow_nic_dev *ndev, + uint32_t port_id) +{ + struct flow_eth_dev *dev = ndev->eth_base; + + while (dev) { + if (dev->port_id == port_id) + return dev->port; + dev = dev->next; + } + + return UINT8_MAX; +} + +static void nic_insert_flow(struct flow_nic_dev *ndev, struct flow_handle *fh) +{ + if (ndev->flow_base) + ndev->flow_base->prev = fh; + fh->next = ndev->flow_base; + fh->prev = NULL; + ndev->flow_base = fh; +} + +static void nic_remove_flow(struct flow_nic_dev *ndev, struct flow_handle *fh) +{ + struct flow_handle *next = fh->next; + struct flow_handle *prev = fh->prev; + + if (next && prev) { + prev->next = next; + next->prev = prev; + } else if (next) { + ndev->flow_base = next; + next->prev = NULL; + } else if (prev) { + prev->next = NULL; + } else if (ndev->flow_base == fh) { + ndev->flow_base = NULL; + } +} + +static void nic_insert_flow_flm(struct flow_nic_dev *ndev, + struct flow_handle *fh) +{ + if (ndev->flow_base_flm) + ndev->flow_base_flm->prev = fh; + fh->next = ndev->flow_base_flm; + fh->prev = NULL; + ndev->flow_base_flm = fh; +} + +static void nic_remove_flow_flm(struct flow_nic_dev *ndev, + struct flow_handle *fh_flm) +{ + struct flow_handle *next = fh_flm->next; + struct flow_handle *prev = fh_flm->prev; + + if (next && prev) { + prev->next = next; + next->prev = prev; + } else if (next) { + ndev->flow_base_flm = next; + next->prev = NULL; + } else if (prev) { + prev->next = NULL; + } else if (ndev->flow_base_flm == fh_flm) { + ndev->flow_base_flm = NULL; + } +} + +static int flow_elem_type_vlan(const struct flow_elem elem[], int eidx, uint16_t implicit_vlan_vid, + struct flow_error *error, struct nic_flow_def *fd, unsigned int sw_counter, + uint32_t *packet_data, uint32_t *packet_mask, struct flm_flow_key_def_s *key_def) +{ + const struct flow_elem_vlan *vlan_spec = (const struct flow_elem_vlan *)elem[eidx].spec; + const struct flow_elem_vlan *vlan_mask = (const struct flow_elem_vlan *)elem[eidx].mask; + + if (vlan_spec != NULL && vlan_mask != NULL) { + if (vlan_mask->tci) { + if (implicit_vlan_vid > 0) { + NT_LOG(ERR, FILTER, "Multiple VLANs not supported " + "for implicit VLAN patterns.\n"); + flow_nic_set_error(ERR_MATCH_INVALID_OR_UNSUPPORTED_ELEM, error); + free(fd); + return 1; + } + + if (sw_counter >= 2) { + NT_LOG(ERR, FILTER, "Key size too big. Out of SW resources.\n"); + flow_nic_set_error(ERR_FAILED, error); + free(fd); + return 1; + } + + uint32_t *sw_data = &packet_data[1 - sw_counter]; + uint32_t *sw_mask = &packet_mask[1 - sw_counter]; + + sw_mask[0] = ntohs(vlan_mask->tci); + sw_data[0] = ntohs(vlan_spec->tci) & sw_mask[0]; + + km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, DYN_FIRST_VLAN, 0); + set_key_def_sw(key_def, sw_counter, DYN_FIRST_VLAN, 0); + sw_counter += 1; + } + } + + fd->vlans += 1; + return 0; +} + +static int flow_elem_type_ipv4(const struct flow_elem elem[], int eidx, struct flow_error *error, + struct nic_flow_def *fd, unsigned int qw_counter, unsigned int sw_counter, + uint32_t *packet_data, uint32_t *packet_mask, struct flm_flow_key_def_s *key_def, + uint32_t any_count) +{ + const struct flow_elem_ipv4 *ipv4_spec = (const struct flow_elem_ipv4 *)elem[eidx].spec; + const struct flow_elem_ipv4 *ipv4_mask = (const struct flow_elem_ipv4 *)elem[eidx].mask; + + if (ipv4_spec != NULL && ipv4_mask != NULL) { + if (ipv4_spec->hdr.frag_offset == 0xffff && ipv4_mask->hdr.frag_offset == 0xffff) + fd->fragmentation = 0xfe; + + if (qw_counter < 2 && (ipv4_mask->hdr.src_ip || ipv4_mask->hdr.dst_ip)) { + uint32_t *qw_data = &packet_data[2 + 4 - qw_counter * 4]; + uint32_t *qw_mask = &packet_mask[2 + 4 - qw_counter * 4]; + + qw_mask[0] = ntohl(ipv4_mask->hdr.src_ip); + qw_mask[1] = ntohl(ipv4_mask->hdr.dst_ip); + + qw_data[0] = ntohl(ipv4_spec->hdr.src_ip) & qw_mask[0]; + qw_data[1] = ntohl(ipv4_spec->hdr.dst_ip) & qw_mask[1]; + + km_add_match_elem(&fd->km, &qw_data[0], &qw_mask[0], 2, DYN_L3, 12); + set_key_def_qw(key_def, qw_counter, DYN_L3, 12); + qw_counter += 1; + } else { + if (2 - sw_counter < ((ipv4_mask->hdr.src_ip ? 1U : 0U) + + (ipv4_mask->hdr.dst_ip ? 1U : 0U))) { + NT_LOG(ERR, FILTER, "Key size too big. Out of SW resources.\n"); + flow_nic_set_error(ERR_FAILED, error); + free(fd); + return 1; + } + + if (ipv4_mask->hdr.src_ip) { + uint32_t *sw_data = &packet_data[1 - sw_counter]; + uint32_t *sw_mask = &packet_mask[1 - sw_counter]; + + sw_mask[0] = ntohl(ipv4_mask->hdr.src_ip); + sw_data[0] = ntohl(ipv4_spec->hdr.src_ip) & sw_mask[0]; + + km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, DYN_L3, 12); + set_key_def_sw(key_def, sw_counter, DYN_L3, 12); + sw_counter += 1; + } + + if (ipv4_mask->hdr.dst_ip) { + uint32_t *sw_data = &packet_data[1 - sw_counter]; + uint32_t *sw_mask = &packet_mask[1 - sw_counter]; + + sw_mask[0] = ntohl(ipv4_mask->hdr.dst_ip); + sw_data[0] = ntohl(ipv4_spec->hdr.dst_ip) & sw_mask[0]; + + km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, DYN_L3, 16); + set_key_def_sw(key_def, sw_counter, DYN_L3, 16); + sw_counter += 1; + } + } + } + + if (any_count > 0 || fd->l3_prot != -1) + fd->tunnel_l3_prot = PROT_TUN_L3_IPV4; + else + fd->l3_prot = PROT_L3_IPV4; + return 0; +} + +static int flow_elem_type_ipv6(const struct flow_elem elem[], int eidx, struct flow_error *error, + struct nic_flow_def *fd, unsigned int qw_counter, uint32_t *packet_data, + uint32_t *packet_mask, struct flm_flow_key_def_s *key_def, uint32_t any_count) +{ + const struct flow_elem_ipv6 *ipv6_spec = (const struct flow_elem_ipv6 *)elem[eidx].spec; + const struct flow_elem_ipv6 *ipv6_mask = (const struct flow_elem_ipv6 *)elem[eidx].mask; + + if (ipv6_spec != NULL && ipv6_mask != NULL) { + if (is_non_zero(ipv6_spec->hdr.src_addr, 16)) { + if (qw_counter >= 2) { + NT_LOG(ERR, FILTER, "Key size too big. Out of QW resources.\n"); + flow_nic_set_error(ERR_FAILED, error); + free(fd); + return 1; + } + + uint32_t *qw_data = &packet_data[2 + 4 - qw_counter * 4]; + uint32_t *qw_mask = &packet_mask[2 + 4 - qw_counter * 4]; + + memcpy(&qw_data[0], ipv6_spec->hdr.src_addr, 16); + memcpy(&qw_mask[0], ipv6_mask->hdr.src_addr, 16); + + qw_data[0] = ntohl(qw_data[0]); + qw_data[1] = ntohl(qw_data[1]); + qw_data[2] = ntohl(qw_data[2]); + qw_data[3] = ntohl(qw_data[3]); + + qw_mask[0] = ntohl(qw_mask[0]); + qw_mask[1] = ntohl(qw_mask[1]); + qw_mask[2] = ntohl(qw_mask[2]); + qw_mask[3] = ntohl(qw_mask[3]); + + qw_data[0] &= qw_mask[0]; + qw_data[1] &= qw_mask[1]; + qw_data[2] &= qw_mask[2]; + qw_data[3] &= qw_mask[3]; + + km_add_match_elem(&fd->km, &qw_data[0], &qw_mask[0], 4, DYN_L3, 8); + set_key_def_qw(key_def, qw_counter, DYN_L3, 8); + qw_counter += 1; + } + + if (is_non_zero(ipv6_spec->hdr.dst_addr, 16)) { + if (qw_counter >= 2) { + NT_LOG(ERR, FILTER, "Key size too big. Out of QW resources.\n"); + flow_nic_set_error(ERR_FAILED, error); + free(fd); + return 1; + } + + uint32_t *qw_data = &packet_data[2 + 4 - qw_counter * 4]; + uint32_t *qw_mask = &packet_mask[2 + 4 - qw_counter * 4]; + + memcpy(&qw_data[0], ipv6_spec->hdr.dst_addr, 16); + memcpy(&qw_mask[0], ipv6_mask->hdr.dst_addr, 16); + + qw_data[0] = ntohl(qw_data[0]); + qw_data[1] = ntohl(qw_data[1]); + qw_data[2] = ntohl(qw_data[2]); + qw_data[3] = ntohl(qw_data[3]); + + qw_mask[0] = ntohl(qw_mask[0]); + qw_mask[1] = ntohl(qw_mask[1]); + qw_mask[2] = ntohl(qw_mask[2]); + qw_mask[3] = ntohl(qw_mask[3]); + qw_data[0] &= qw_mask[0]; + qw_data[1] &= qw_mask[1]; + qw_data[2] &= qw_mask[2]; + qw_data[3] &= qw_mask[3]; + + km_add_match_elem(&fd->km, &qw_data[0], &qw_mask[0], 4, DYN_L3, 24); + set_key_def_qw(key_def, qw_counter, DYN_L3, 24); + qw_counter += 1; + } + } + + if (any_count > 0 || fd->l3_prot != -1) + fd->tunnel_l3_prot = PROT_TUN_L3_IPV6; + else + fd->l3_prot = PROT_L3_IPV6; + return 0; +} + +static int flow_elem_type_upd(const struct flow_elem elem[], int eidx, struct flow_error *error, + struct nic_flow_def *fd, unsigned int sw_counter, uint32_t *packet_data, + uint32_t *packet_mask, struct flm_flow_key_def_s *key_def, uint32_t any_count) +{ + const struct flow_elem_udp *udp_spec = (const struct flow_elem_udp *)elem[eidx].spec; + const struct flow_elem_udp *udp_mask = (const struct flow_elem_udp *)elem[eidx].mask; + + if (udp_spec != NULL && udp_mask != NULL) { + if (udp_mask->hdr.src_port || udp_mask->hdr.dst_port) { + if (sw_counter >= 2) { + NT_LOG(ERR, FILTER, "Key size too big. Out of SW resources.\n"); + flow_nic_set_error(ERR_FAILED, error); + free(fd); + return 1; + } + + uint32_t *sw_data = &packet_data[1 - sw_counter]; + uint32_t *sw_mask = &packet_mask[1 - sw_counter]; + + sw_mask[0] = (ntohs(udp_mask->hdr.src_port) << 16) | + ntohs(udp_mask->hdr.dst_port); + sw_data[0] = ((ntohs(udp_spec->hdr.src_port) << 16) | + ntohs(udp_spec->hdr.dst_port)) & sw_mask[0]; + + km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, DYN_L4, 0); + set_key_def_sw(key_def, sw_counter, DYN_L4, 0); + sw_counter += 1; + } + } + + if (any_count > 0 || fd->l4_prot != -1) { + fd->tunnel_l4_prot = PROT_TUN_L4_UDP; + key_def->inner_proto = 1; + } else { + fd->l4_prot = PROT_L4_UDP; + key_def->outer_proto = 1; + } + return 0; +} + +static int flow_elem_type_sctp(const struct flow_elem elem[], int eidx, struct flow_error *error, + struct nic_flow_def *fd, unsigned int sw_counter, uint32_t *packet_data, + uint32_t *packet_mask, struct flm_flow_key_def_s *key_def, uint32_t any_count) +{ + const struct flow_elem_sctp *sctp_spec = (const struct flow_elem_sctp *)elem[eidx].spec; + const struct flow_elem_sctp *sctp_mask = (const struct flow_elem_sctp *)elem[eidx].mask; + + if (sctp_spec != NULL && sctp_mask != NULL) { + if (sctp_mask->hdr.src_port || sctp_mask->hdr.dst_port) { + if (sw_counter >= 2) { + NT_LOG(ERR, FILTER, "Key size too big. Out of SW resources.\n"); + flow_nic_set_error(ERR_FAILED, error); + free(fd); + return 1; + } + + uint32_t *sw_data = &packet_data[1 - sw_counter]; + uint32_t *sw_mask = &packet_mask[1 - sw_counter]; + + sw_mask[0] = (ntohs(sctp_mask->hdr.src_port) << 16) | + ntohs(sctp_mask->hdr.dst_port); + sw_data[0] = ((ntohs(sctp_spec->hdr.src_port) << 16) | + ntohs(sctp_spec->hdr.dst_port)) & sw_mask[0]; + + km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, DYN_L4, 0); + set_key_def_sw(key_def, sw_counter, DYN_L4, 0); + sw_counter += 1; + } + } + + if (any_count > 0 || fd->l4_prot != -1) { + fd->tunnel_l4_prot = PROT_TUN_L4_SCTP; + key_def->inner_proto = 1; + } else { + fd->l4_prot = PROT_L4_SCTP; + key_def->outer_proto = 1; + } + return 0; +} + +static int flow_elem_type_tcp(const struct flow_elem elem[], int eidx, struct flow_error *error, + struct nic_flow_def *fd, unsigned int sw_counter, uint32_t *packet_data, + uint32_t *packet_mask, struct flm_flow_key_def_s *key_def, uint32_t any_count) +{ + const struct flow_elem_tcp *tcp_spec = (const struct flow_elem_tcp *)elem[eidx].spec; + const struct flow_elem_tcp *tcp_mask = (const struct flow_elem_tcp *)elem[eidx].mask; + + if (tcp_spec != NULL && tcp_mask != NULL) { + if (tcp_mask->hdr.src_port || tcp_mask->hdr.dst_port) { + if (sw_counter >= 2) { + NT_LOG(ERR, FILTER, "Key size too big. Out of SW resources.\n"); + flow_nic_set_error(ERR_FAILED, error); + free(fd); + return 1; + } + + uint32_t *sw_data = &packet_data[1 - sw_counter]; + uint32_t *sw_mask = &packet_mask[1 - sw_counter]; + + sw_mask[0] = (ntohs(tcp_mask->hdr.src_port) << 16) | + ntohs(tcp_mask->hdr.dst_port); + sw_data[0] = ((ntohs(tcp_spec->hdr.src_port) << 16) | + ntohs(tcp_spec->hdr.dst_port)) & sw_mask[0]; + + km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, DYN_L4, 0); + set_key_def_sw(key_def, sw_counter, DYN_L4, 0); + sw_counter += 1; + } + } + + if (any_count > 0 || fd->l4_prot != -1) { + fd->tunnel_l4_prot = PROT_TUN_L4_TCP; + key_def->inner_proto = 1; + } else { + fd->l4_prot = PROT_L4_TCP; + key_def->outer_proto = 1; + } + return 0; +} + +static int flow_elem_type_gtp(const struct flow_elem elem[], int eidx, struct flow_error *error, + struct nic_flow_def *fd, unsigned int sw_counter, uint32_t *packet_data, + uint32_t *packet_mask, struct flm_flow_key_def_s *key_def) +{ + const struct flow_elem_gtp *gtp_spec = (const struct flow_elem_gtp *)elem[eidx].spec; + const struct flow_elem_gtp *gtp_mask = (const struct flow_elem_gtp *)elem[eidx].mask; + + if (gtp_spec != NULL && gtp_mask != NULL) { + if (gtp_mask->teid) { + if (sw_counter >= 2) { + NT_LOG(ERR, FILTER, "Key size too big. Out of SW resources.\n"); + flow_nic_set_error(ERR_FAILED, error); + free(fd); + return 1; + } + + uint32_t *sw_data = &packet_data[1 - sw_counter]; + uint32_t *sw_mask = &packet_mask[1 - sw_counter]; + + sw_mask[0] = ntohl(gtp_mask->teid); + sw_data[0] = ntohl(gtp_spec->teid) & sw_mask[0]; + + km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, DYN_L4_PAYLOAD, 4); + set_key_def_sw(key_def, sw_counter, DYN_L4_PAYLOAD, 4); + sw_counter += 1; + } + } + + fd->tunnel_prot = PROT_TUN_GTPV1U; + return 0; +} + +static struct nic_flow_def *interpret_flow_elements(struct flow_eth_dev *dev, + const struct flow_elem elem[], const struct flow_action action[], + struct flow_error *error, uint16_t implicit_vlan_vid, + uint32_t *in_port_id, uint32_t *num_dest_port, + uint32_t *num_queues, uint32_t *packet_data, + uint32_t *packet_mask, struct flm_flow_key_def_s *key_def) +{ + uint32_t any_count = 0; + int mtr_count = 0; + + unsigned int encap_decap_order = 0; + + unsigned int qw_counter = 0; + unsigned int sw_counter = 0; + + uint64_t modify_field_use_flags = 0x0; + + *in_port_id = UINT32_MAX; + *num_dest_port = 0; + *num_queues = 0; + + memset(packet_data, 0x0, sizeof(uint32_t) * 10); + memset(packet_mask, 0x0, sizeof(uint32_t) * 10); + key_def->data = 0; + + if (action == NULL || elem == NULL) { + flow_nic_set_error(ERR_FAILED, error); + NT_LOG(ERR, FILTER, "Flow items / actions missing\n"); + return NULL; + } + + struct nic_flow_def *fd = calloc(1, sizeof(struct nic_flow_def)); + + if (!fd) { + flow_nic_set_error(ERR_MEMORY, error); + NT_LOG(ERR, FILTER, "ERR Memory\n"); + return NULL; + } + + /* Set default values for fd */ + fd->full_offload = -1; + fd->in_port_override = -1; + fd->mark = UINT32_MAX; + fd->jump_to_group = UINT32_MAX; + + fd->l2_prot = -1; + fd->l3_prot = -1; + fd->l4_prot = -1; + fd->vlans = 0; + fd->tunnel_prot = -1; + fd->tunnel_l3_prot = -1; + fd->tunnel_l4_prot = -1; + fd->fragmentation = -1; + + NT_LOG(DBG, FILTER, + ">>>>> [Dev %p] Nic %i, Port %i: fd %p - FLOW Interpretation <<<<<\n", + dev, dev->ndev->adapter_no, dev->port, fd); + + /* + * Gather flow match + actions and convert into internal flow definition structure + * (struct nic_flow_def_s) + * This is the 1st step in the flow creation - validate, convert and prepare + */ + for (int aidx = 0; action[aidx].type != FLOW_ACTION_TYPE_END; ++aidx) { + switch (action[aidx].type) { + case FLOW_ACTION_TYPE_PORT_ID: + NT_LOG(DBG, FILTER, + "Dev:%p: FLOW_ACTION_TYPE_PORT_ID\n", dev); + if (action[aidx].conf) { + uint32_t port_id = + ((const struct flow_action_port_id *) + action[aidx] + .conf) + ->id; + uint8_t port = get_port_from_port_id(dev->ndev, + port_id); + + if (fd->dst_num_avail == MAX_OUTPUT_DEST) { + /* ERROR too many output destinations */ + NT_LOG(ERR, FILTER, + "Too many output destinations\n"); + flow_nic_set_error(ERR_OUTPUT_TOO_MANY, + error); + free(fd); + return NULL; + } + + if (port >= dev->ndev->be.num_phy_ports) { + /* ERROR phy port out of range */ + NT_LOG(ERR, FILTER, + "Phy port out of range\n"); + flow_nic_set_error(ERR_OUTPUT_INVALID, + error); + free(fd); + return NULL; + } + + /* New destination port to add */ + fd->dst_id[fd->dst_num_avail].owning_port_id = + port_id; + fd->dst_id[fd->dst_num_avail].type = PORT_PHY; + fd->dst_id[fd->dst_num_avail].id = (int)port; + fd->dst_id[fd->dst_num_avail].active = 1; + fd->dst_num_avail++; + + if (fd->flm_mtu_fragmentation_recipe == 0) { + fd->flm_mtu_fragmentation_recipe = + convert_port_to_ifr_mtu_recipe(port); + } + + if (fd->full_offload < 0) + fd->full_offload = 1; + + *num_dest_port += 1; + + NT_LOG(DBG, FILTER, "Phy port ID: %i\n", + (int)port); + } + break; + + case FLOW_ACTION_TYPE_QUEUE: + NT_LOG(DBG, FILTER, "Dev:%p: FLOW_ACTION_TYPE_QUEUE\n", + dev); + if (action[aidx].conf) { + const struct flow_action_queue *queue = + (const struct flow_action_queue *) + action[aidx] + .conf; + + int hw_id = rx_queue_idx_to_hw_id(dev, + queue->index); + + fd->dst_id[fd->dst_num_avail].owning_port_id = + dev->port; + fd->dst_id[fd->dst_num_avail].id = hw_id; + fd->dst_id[fd->dst_num_avail].type = PORT_VIRT; + fd->dst_id[fd->dst_num_avail].active = 1; + fd->dst_num_avail++; + + NT_LOG(DBG, FILTER, + "Dev:%p: FLOW_ACTION_TYPE_QUEUE port %u, queue index: %u, hw id %u\n", + dev, dev->port, queue->index, hw_id); + + fd->full_offload = 0; + *num_queues += 1; + } + break; + + case FLOW_ACTION_TYPE_RSS: + NT_LOG(DBG, FILTER, "Dev:%p: FLOW_ACTION_TYPE_RSS\n", + dev); + if (action[aidx].conf) { + const struct flow_action_rss *rss = + (const struct flow_action_rss *) + action[aidx] + .conf; + + for (uint32_t i = 0; i < rss->queue_num; ++i) { + int hw_id = rx_queue_idx_to_hw_id(dev, rss->queue[i]); + + fd->dst_id[fd->dst_num_avail] + .owning_port_id = dev->port; + fd->dst_id[fd->dst_num_avail].id = + hw_id; + fd->dst_id[fd->dst_num_avail].type = + PORT_VIRT; + fd->dst_id[fd->dst_num_avail].active = + 1; + fd->dst_num_avail++; + } + + fd->full_offload = 0; + *num_queues += rss->queue_num; + } + break; + + case FLOW_ACTION_TYPE_MARK: + NT_LOG(DBG, FILTER, "Dev:%p: FLOW_ACTION_TYPE_MARK\n", + dev); + if (action[aidx].conf) { + fd->mark = ((const struct flow_action_mark *) + action[aidx] + .conf) + ->id; + NT_LOG(DBG, FILTER, "Mark: %i\n", fd->mark); + } + break; + + case FLOW_ACTION_TYPE_JUMP: + NT_LOG(DBG, FILTER, "Dev:%p: FLOW_ACTION_TYPE_JUMP\n", + dev); + if (action[aidx].conf) { + const struct flow_action_jump *jump = + (const struct flow_action_jump *) + action[aidx] + .conf; + fd->jump_to_group = jump->group; + NT_LOG(DBG, FILTER, + "Dev:%p: FLOW_ACTION_TYPE_JUMP: group %u\n", + dev, jump->group); + } + break; + + case FLOW_ACTION_TYPE_DROP: + NT_LOG(DBG, FILTER, "Dev:%p: FLOW_ACTION_TYPE_DROP\n", + dev); + if (action[aidx].conf) { + fd->dst_id[fd->dst_num_avail].owning_port_id = + 0; + fd->dst_id[fd->dst_num_avail].id = 0; + fd->dst_id[fd->dst_num_avail].type = PORT_NONE; + fd->dst_num_avail++; + } + break; + + case FLOW_ACTION_TYPE_METER: + NT_LOG(DBG, FILTER, "Dev:%p: FLOW_ACTION_TYPE_METER\n", + dev); + if (action[aidx].conf) { + const struct flow_action_meter *meter = + (const struct flow_action_meter *) + action[aidx] + .conf; + if (mtr_count >= MAX_FLM_MTRS_SUPPORTED) { + NT_LOG(ERR, FILTER, + "ERROR: - Number of METER actions exceeds %d.\n", + MAX_FLM_MTRS_SUPPORTED); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, + error); + free(fd); + return NULL; + } + fd->mtr_ids[mtr_count++] = meter->mtr_id + 1; + } + break; + + case FLOW_ACTION_TYPE_RAW_ENCAP: + NT_LOG(DBG, FILTER, + "Dev:%p: FLOW_ACTION_TYPE_RAW_ENCAP\n", dev); + if (action[aidx].conf) { + const struct flow_action_raw_encap *encap = + (const struct flow_action_raw_encap *) + action[aidx] + .conf; + const struct flow_elem *items = encap->items; + + if (encap_decap_order != 1) { + NT_LOG(ERR, FILTER, + "ERROR: - RAW_ENCAP must follow RAW_DECAP.\n"); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, + error); + free(fd); + return NULL; + } + + if (encap->size == 0 || encap->size > 255 || + encap->item_count < 2) { + NT_LOG(ERR, FILTER, + "ERROR: - RAW_ENCAP data/size invalid.\n"); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, + error); + free(fd); + return NULL; + } + + encap_decap_order = 2; + + fd->tun_hdr.len = (uint8_t)encap->size; + memcpy(fd->tun_hdr.d.hdr8, encap->data, + fd->tun_hdr.len); + + while (items->type != FLOW_ELEM_TYPE_END) { + switch (items->type) { + case FLOW_ELEM_TYPE_ETH: + fd->tun_hdr.l2_len = 14; + break; + case FLOW_ELEM_TYPE_VLAN: + fd->tun_hdr.nb_vlans += 1; + fd->tun_hdr.l2_len += 4; + break; + case FLOW_ELEM_TYPE_IPV4: + fd->tun_hdr.ip_version = 4; + fd->tun_hdr.l3_len = sizeof(struct ipv4_hdr_s); + fd->tun_hdr.new_outer = 1; + break; + case FLOW_ELEM_TYPE_IPV6: + fd->tun_hdr.ip_version = 6; + fd->tun_hdr.l3_len = sizeof(struct ipv6_hdr_s); + fd->tun_hdr.new_outer = 1; + break; + case FLOW_ELEM_TYPE_SCTP: + fd->tun_hdr.l4_len = sizeof(struct sctp_hdr_s); + break; + case FLOW_ELEM_TYPE_TCP: + fd->tun_hdr.l4_len = sizeof(struct tcp_hdr_s); + break; + case FLOW_ELEM_TYPE_UDP: + fd->tun_hdr.l4_len = sizeof(struct udp_hdr_s); + break; + case FLOW_ELEM_TYPE_ICMP: + fd->tun_hdr.l4_len = sizeof(struct icmp_hdr_s); + break; + default: + break; + } + items++; + } + + if (fd->tun_hdr.nb_vlans > 3) { + NT_LOG(ERR, FILTER, + "ERROR: - Encapsulation with %d vlans not supported.\n", + (int)fd->tun_hdr.nb_vlans); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, + error); + free(fd); + return NULL; + } + + /* Convert encap data to 128-bit little endian */ + for (size_t i = 0; i < (encap->size + 15) / 16; + ++i) { + uint8_t *data = + fd->tun_hdr.d.hdr8 + i * 16; + for (unsigned int j = 0; j < 8; ++j) { + uint8_t t = data[j]; + + data[j] = data[15 - j]; + data[15 - j] = t; + } + } + } + break; + + case FLOW_ACTION_TYPE_RAW_DECAP: + NT_LOG(DBG, FILTER, + "Dev:%p: FLOW_ACTION_TYPE_RAW_DECAP\n", dev); + if (action[aidx].conf) { + const struct flow_action_raw_decap *decap = + (const struct flow_action_raw_decap *) + action[aidx] + .conf; + + if (encap_decap_order != 0) { + NT_LOG(ERR, FILTER, + "ERROR: - RAW_ENCAP must follow RAW_DECAP.\n"); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, + error); + free(fd); + return NULL; + } + + if (decap->item_count < 2) { + NT_LOG(ERR, FILTER, + "ERROR: - RAW_DECAP must decap something.\n"); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, + error); + free(fd); + return NULL; + } + + encap_decap_order = 1; + + fd->header_strip_start_dyn = 2; + fd->header_strip_start_ofs = 2; + + switch (decap->items[decap->item_count - 2] + .type) { + case FLOW_ELEM_TYPE_ETH: + case FLOW_ELEM_TYPE_VLAN: + fd->header_strip_end_dyn = 4; + fd->header_strip_end_ofs = 0; + break; + case FLOW_ELEM_TYPE_IPV4: + case FLOW_ELEM_TYPE_IPV6: + fd->header_strip_end_dyn = 7; + fd->header_strip_end_ofs = 0; + fd->header_strip_removed_outer_ip = 1; + break; + case FLOW_ELEM_TYPE_SCTP: + case FLOW_ELEM_TYPE_TCP: + case FLOW_ELEM_TYPE_UDP: + case FLOW_ELEM_TYPE_ICMP: + fd->header_strip_end_dyn = 8; + fd->header_strip_end_ofs = 0; + fd->header_strip_removed_outer_ip = 1; + break; + case FLOW_ELEM_TYPE_GTP: + fd->header_strip_end_dyn = 13; + fd->header_strip_end_ofs = 0; + fd->header_strip_removed_outer_ip = 1; + break; + default: + fd->header_strip_end_dyn = 1; + fd->header_strip_end_ofs = 0; + fd->header_strip_removed_outer_ip = 1; + break; + } + } + break; + + case FLOW_ACTION_TYPE_MODIFY_FIELD: + NT_LOG(DBG, FILTER, + "Dev:%p: FLOW_ACTION_TYPE_MODIFY_FIELD\n", dev); + { + const struct flow_action_modify_field *modify_field = + (const struct flow_action_modify_field *) + action[aidx] + .conf; + uint64_t modify_field_use_flag = 0; + + if (modify_field->src.field != + FLOW_FIELD_VALUE) { + NT_LOG(ERR, FILTER, + "MODIFY_FIELD only src type VALUE is supported.\n"); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, + error); + free(fd); + return NULL; + } + + if (modify_field->dst.level > 2) { + NT_LOG(ERR, FILTER, + "MODIFY_FIELD only dst level 0, 1, and 2 is supported.\n"); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, + error); + free(fd); + return NULL; + } + + if (modify_field->dst.field == + FLOW_FIELD_IPV4_TTL || + modify_field->dst.field == + FLOW_FIELD_IPV6_HOPLIMIT) { + if (modify_field->operation != + FLOW_MODIFY_SUB) { + NT_LOG(ERR, FILTER, + "MODIFY_FIELD only operation SUB is supported for TTL/HOPLIMIT.\n"); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, + error); + free(fd); + return NULL; + } + + if (fd->ttl_sub_enable) { + NT_LOG(ERR, FILTER, + "MODIFY_FIELD TTL/HOPLIMIT resource already in use.\n"); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, + error); + free(fd); + return NULL; + } + + fd->ttl_sub_enable = 1; + fd->ttl_sub_ipv4 = + (modify_field->dst.field == + FLOW_FIELD_IPV4_TTL) ? + 1 : + 0; + fd->ttl_sub_outer = + (modify_field->dst.level <= 1) ? + 1 : + 0; + } else { + if (modify_field->operation != + FLOW_MODIFY_SET) { + NT_LOG(ERR, FILTER, + "MODIFY_FIELD only operation SET " + "is supported in general.\n"); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, + error); + free(fd); + return NULL; + } + + if (fd->modify_field_count >= + dev->ndev->be.tpe.nb_cpy_writers) { + NT_LOG(ERR, FILTER, + "MODIFY_FIELD exceeded maximum of %u" + " MODIFY_FIELD actions.\n", + dev->ndev->be.tpe + .nb_cpy_writers); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, + error); + free(fd); + return NULL; + } + + switch (modify_field->dst.field) { + case FLOW_FIELD_IPV4_DSCP: + fd->modify_field + [fd->modify_field_count] + .select = + CPY_SELECT_DSCP_IPV4; + fd->modify_field + [fd->modify_field_count] + .dyn = DYN_L3; + fd->modify_field + [fd->modify_field_count] + .ofs = 1; + fd->modify_field + [fd->modify_field_count] + .len = 1; + break; + case FLOW_FIELD_IPV6_DSCP: + fd->modify_field + [fd->modify_field_count] + .select = + CPY_SELECT_DSCP_IPV6; + fd->modify_field + [fd->modify_field_count] + .dyn = DYN_L3; + fd->modify_field + [fd->modify_field_count] + .ofs = 0; + fd->modify_field + /* + * len=2 is needed because IPv6 DSCP overlaps 2 + * bytes. + */ + [fd->modify_field_count] + .len = 2; + break; + case FLOW_FIELD_GTP_PSC_QFI: + fd->modify_field + [fd->modify_field_count] + .select = + CPY_SELECT_RQI_QFI; + fd->modify_field + [fd->modify_field_count] + .dyn = + DYN_L4_PAYLOAD; + fd->modify_field + [fd->modify_field_count] + .ofs = 14; + fd->modify_field + [fd->modify_field_count] + .len = 1; + break; + case FLOW_FIELD_IPV4_SRC: + fd->modify_field + [fd->modify_field_count] + .select = + CPY_SELECT_IPV4; + fd->modify_field + [fd->modify_field_count] + .dyn = DYN_L3; + fd->modify_field + [fd->modify_field_count] + .ofs = 12; + fd->modify_field + [fd->modify_field_count] + .len = 4; + break; + case FLOW_FIELD_IPV4_DST: + fd->modify_field + [fd->modify_field_count] + .select = + CPY_SELECT_IPV4; + fd->modify_field + [fd->modify_field_count] + .dyn = DYN_L3; + fd->modify_field + [fd->modify_field_count] + .ofs = 16; + fd->modify_field + [fd->modify_field_count] + .len = 4; + break; + case FLOW_FIELD_TCP_PORT_SRC: + /* fallthrough */ + case FLOW_FIELD_UDP_PORT_SRC: + fd->modify_field + [fd->modify_field_count] + .select = + CPY_SELECT_PORT; + fd->modify_field + [fd->modify_field_count] + .dyn = DYN_L4; + fd->modify_field + [fd->modify_field_count] + .ofs = 0; + fd->modify_field + [fd->modify_field_count] + .len = 2; + break; + case FLOW_FIELD_TCP_PORT_DST: + /* fallthrough */ + case FLOW_FIELD_UDP_PORT_DST: + fd->modify_field + [fd->modify_field_count] + .select = + CPY_SELECT_PORT; + fd->modify_field + [fd->modify_field_count] + .dyn = DYN_L4; + fd->modify_field + [fd->modify_field_count] + .ofs = 2; + fd->modify_field + [fd->modify_field_count] + .len = 2; + break; + case FLOW_FIELD_GTP_TEID: + fd->modify_field + [fd->modify_field_count] + .select = + CPY_SELECT_TEID; + fd->modify_field + [fd->modify_field_count] + .dyn = + DYN_L4_PAYLOAD; + fd->modify_field + [fd->modify_field_count] + .ofs = 4; + fd->modify_field + [fd->modify_field_count] + .len = 4; + break; + default: + NT_LOG(ERR, FILTER, + "MODIFY_FIELD dst type is not supported.\n"); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, + error); + free(fd); + return NULL; + } + + modify_field_use_flag = + 1 + << fd->modify_field + [fd->modify_field_count] + .select; + if (modify_field_use_flag & + modify_field_use_flags) { + NT_LOG(ERR, FILTER, + "MODIFY_FIELD dst type hardware " + "resource already used.\n"); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, + error); + free(fd); + return NULL; + } + + memcpy(fd->modify_field + [fd->modify_field_count] + .value8, + modify_field->src.value, 16); + + fd->modify_field[fd->modify_field_count] + .level = + modify_field->dst.level; + + modify_field_use_flags |= + modify_field_use_flag; + fd->modify_field_count += 1; + } + } + break; + + default: + NT_LOG(ERR, FILTER, + "Invalid or unsupported flow action received - %i\n", + action[aidx].type); + flow_nic_set_error(ERR_ACTION_UNSUPPORTED, error); + free(fd); + return NULL; + } + } + + if (!(encap_decap_order == 0 || encap_decap_order == 2)) { + NT_LOG(ERR, FILTER, "Invalid encap/decap actions\n"); + free(fd); + return NULL; + } + + if (implicit_vlan_vid > 0) { + uint32_t *sw_data = &packet_data[1 - sw_counter]; + uint32_t *sw_mask = &packet_mask[1 - sw_counter]; + + sw_mask[0] = 0x0fff; + sw_data[0] = implicit_vlan_vid & sw_mask[0]; + + km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, + DYN_FIRST_VLAN, 0); + set_key_def_sw(key_def, sw_counter, DYN_FIRST_VLAN, 0); + sw_counter += 1; + + fd->vlans += 1; + } + + /* + * All Actions interpreted + */ + for (int eidx = 0; elem[eidx].type != FLOW_ELEM_TYPE_END; ++eidx) { + switch (elem[eidx].type) { + case FLOW_ELEM_TYPE_ANY: + NT_LOG(DBG, FILTER, + "Adap %i, Port %i: FLOW_ELEM_TYPE_ANY\n", + dev->ndev->adapter_no, dev->port); + { + const struct flow_elem_any *any_spec = + (const struct flow_elem_any *)elem[eidx] + .spec; + const struct flow_elem_any *any_mask = + (const struct flow_elem_any *)elem[eidx] + .mask; + + if (any_spec && any_mask) { + any_count += any_spec->num & + any_mask->num; + } + } + break; + + case FLOW_ELEM_TYPE_ETH: + NT_LOG(DBG, FILTER, + "Adap %i, Port %i: FLOW_ELEM_TYPE_ETH\n", + dev->ndev->adapter_no, dev->port); + { + const struct flow_elem_eth *eth_spec = + (const struct flow_elem_eth *)elem[eidx] + .spec; + const struct flow_elem_eth *eth_mask = + (const struct flow_elem_eth *)elem[eidx] + .mask; + + if (any_count > 0) { + NT_LOG(ERR, FILTER, + "Tunneled L2 ethernet not supported\n"); + flow_nic_set_error(ERR_FAILED, error); + free(fd); + return NULL; + } + + if (qw_counter >= 2) { + NT_LOG(ERR, FILTER, + "Key size too big. Out of QW resources.\n"); + flow_nic_set_error(ERR_FAILED, error); + free(fd); + return NULL; + } + + if (eth_spec != NULL && eth_mask != NULL) { + if (is_non_zero(eth_mask->d_addr.addr_b, + 6) || + is_non_zero(eth_mask->s_addr.addr_b, + 6)) { + uint32_t *qw_data = + &packet_data[2 + 4 - + qw_counter * + 4]; + uint32_t *qw_mask = + &packet_mask[2 + 4 - + qw_counter * + 4]; + + qw_data[0] = + ((eth_spec->d_addr + .addr_b[0] & + eth_mask->d_addr + .addr_b[0]) + << 24) + + ((eth_spec->d_addr + .addr_b[1] & + eth_mask->d_addr + .addr_b[1]) + << 16) + + ((eth_spec->d_addr + .addr_b[2] & + eth_mask->d_addr + .addr_b[2]) + << 8) + + (eth_spec->d_addr + .addr_b[3] & + eth_mask->d_addr + .addr_b[3]); + + qw_data[1] = + ((eth_spec->d_addr + .addr_b[4] & + eth_mask->d_addr + .addr_b[4]) + << 24) + + ((eth_spec->d_addr + .addr_b[5] & + eth_mask->d_addr + .addr_b[5]) + << 16) + + ((eth_spec->s_addr + .addr_b[0] & + eth_mask->s_addr + .addr_b[0]) + << 8) + + (eth_spec->s_addr + .addr_b[1] & + eth_mask->s_addr + .addr_b[1]); + + qw_data[2] = + ((eth_spec->s_addr + .addr_b[2] & + eth_mask->s_addr + .addr_b[2]) + << 24) + + ((eth_spec->s_addr + .addr_b[3] & + eth_mask->s_addr + .addr_b[3]) + << 16) + + ((eth_spec->s_addr + .addr_b[4] & + eth_mask->s_addr + .addr_b[4]) + << 8) + + (eth_spec->s_addr + .addr_b[5] & + eth_mask->s_addr + .addr_b[5]); + + qw_mask[0] = (eth_mask->d_addr + .addr_b[0] + << 24) + + (eth_mask->d_addr + .addr_b[1] + << 16) + + (eth_mask->d_addr + .addr_b[2] + << 8) + + eth_mask->d_addr + .addr_b[3]; + + qw_mask[1] = (eth_mask->d_addr + .addr_b[4] + << 24) + + (eth_mask->d_addr + .addr_b[5] + << 16) + + (eth_mask->s_addr + .addr_b[0] + << 8) + + eth_mask->s_addr + .addr_b[1]; + + qw_mask[2] = (eth_mask->s_addr + .addr_b[2] + << 24) + + (eth_mask->s_addr + .addr_b[3] + << 16) + + (eth_mask->s_addr + .addr_b[4] + << 8) + + eth_mask->s_addr + .addr_b[5]; + + km_add_match_elem(&fd->km, + &qw_data[(size_t)(qw_counter * + 4)], + &qw_mask[(size_t)(qw_counter * + 4)], + 3, DYN_L2, 0); + set_key_def_qw(key_def, + qw_counter, + DYN_L2, 0); + qw_counter += 1; + } + } + + fd->l2_prot = PROT_L2_ETH2; + } + break; + + case FLOW_ELEM_TYPE_VLAN: + NT_LOG(DBG, FILTER, + "Adap %i, Port %i: FLOW_ELEM_TYPE_VLAN\n", + dev->ndev->adapter_no, dev->port); + { + if (flow_elem_type_vlan(elem, eidx, implicit_vlan_vid, error, fd, + sw_counter, packet_data, packet_mask, key_def)) + return NULL; + } + break; + + case FLOW_ELEM_TYPE_IPV4: + NT_LOG(DBG, FILTER, + "Adap %i, Port %i: FLOW_ELEM_TYPE_IPV4\n", + dev->ndev->adapter_no, dev->port); + { + if (flow_elem_type_ipv4(elem, eidx, error, fd, qw_counter, + sw_counter, packet_data, packet_mask, key_def, any_count)) + return NULL; + } + break; + + case FLOW_ELEM_TYPE_IPV6: + NT_LOG(DBG, FILTER, + "Adap %i, Port %i: FLOW_ELEM_TYPE_IPV6\n", + dev->ndev->adapter_no, dev->port); + { + if (flow_elem_type_ipv6(elem, eidx, error, fd, qw_counter, + packet_data, packet_mask, key_def, any_count)) + return NULL; + } + break; + + case FLOW_ELEM_TYPE_UDP: + NT_LOG(DBG, FILTER, + "Adap %i, Port %i: FLOW_ELEM_TYPE_UDP\n", + dev->ndev->adapter_no, dev->port); + { + if (flow_elem_type_upd(elem, eidx, error, fd, sw_counter, + packet_data, packet_mask, key_def, any_count)) + return NULL; + } + break; + + case FLOW_ELEM_TYPE_SCTP: + NT_LOG(DBG, FILTER, + "Adap %i,Port %i:FLOW_ELEM_TYPE_SCTP\n", + dev->ndev->adapter_no, dev->port); + { + if (flow_elem_type_sctp(elem, eidx, error, fd, sw_counter, + packet_data, packet_mask, key_def, any_count)) + return NULL; + } + break; + + case FLOW_ELEM_TYPE_TCP: + NT_LOG(DBG, FILTER, + "Adap %i, Port %i: FLOW_ELEM_TYPE_TCP\n", + dev->ndev->adapter_no, dev->port); + { + if (flow_elem_type_tcp(elem, eidx, error, fd, sw_counter, + packet_data, packet_mask, key_def, any_count)) + return NULL; + } + break; + + case FLOW_ELEM_TYPE_GTP: + NT_LOG(DBG, FILTER, + "Adap %i, Port %i: FLOW_ELEM_TYPE_GTP\n", + dev->ndev->adapter_no, dev->port); + { + if (flow_elem_type_gtp(elem, eidx, error, fd, sw_counter, + packet_data, packet_mask, key_def)) + return NULL; + } + break; + + case FLOW_ELEM_TYPE_PORT_ID: + NT_LOG(DBG, FILTER, + "Adap %i, Port %i: FLOW_ELEM_TYPE_PORT_ID\n", + dev->ndev->adapter_no, dev->port); + if (elem[eidx].spec) { + *in_port_id = + ((const struct flow_elem_port_id *) + elem[eidx] + .spec) + ->id; + } + break; + + case FLOW_ELEM_TYPE_VOID: + NT_LOG(DBG, FILTER, + "Adap %i, Port %i: FLOW_ELEM_TYPE_VOID\n", + dev->ndev->adapter_no, dev->port); + break; + + default: + NT_LOG(ERR, FILTER, + "Invalid or unsupported flow request: %d\n", + (int)elem[eidx].type); + flow_nic_set_error(ERR_MATCH_INVALID_OR_UNSUPPORTED_ELEM, + error); + free(fd); + return NULL; + } + } + + return fd; +} + +static int reset_cat_function_setup(struct flow_eth_dev *dev, int cfn) +{ + /* CFN */ + { + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PRESET_ALL, cfn, + 0, 0); + hw_mod_cat_cfn_flush(&dev->ndev->be, cfn, 1); + } + + /* KM */ + { + uint32_t bm = 0; + + hw_mod_cat_kce_km_get(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM, + KM_FLM_IF_FIRST, cfn / 8, &bm); + hw_mod_cat_kce_km_set(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM, + KM_FLM_IF_FIRST, cfn / 8, + bm & ~(1 << (cfn % 8))); + hw_mod_cat_kcs_km_set(&dev->ndev->be, HW_CAT_KCS_CATEGORY, + KM_FLM_IF_FIRST, cfn, 0); + + hw_mod_cat_kce_km_flush(&dev->ndev->be, KM_FLM_IF_FIRST, + cfn / 8, 1); + hw_mod_cat_kcs_km_flush(&dev->ndev->be, KM_FLM_IF_FIRST, cfn, + 1); + + for (unsigned int ft = 0; ft < dev->ndev->be.cat.nb_flow_types; + ft++) { + set_flow_type_km(dev->ndev, cfn, ft, 0, 0); + set_flow_type_km(dev->ndev, cfn, ft, 1, 0); + set_flow_type_km(dev->ndev, cfn, ft, 2, 0); + set_flow_type_km(dev->ndev, cfn, ft, 3, 0); + } + } + + /* FLM */ + { + uint32_t bm = 0; + + hw_mod_cat_kce_flm_get(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM, + KM_FLM_IF_FIRST, cfn / 8, &bm); + hw_mod_cat_kce_flm_set(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM, + KM_FLM_IF_FIRST, cfn / 8, + bm & ~(1 << (cfn % 8))); + hw_mod_cat_kcs_flm_set(&dev->ndev->be, HW_CAT_KCS_CATEGORY, + KM_FLM_IF_FIRST, cfn, 0); + + hw_mod_cat_kce_flm_flush(&dev->ndev->be, KM_FLM_IF_FIRST, + cfn / 8, 1); + hw_mod_cat_kcs_flm_flush(&dev->ndev->be, KM_FLM_IF_FIRST, cfn, + 1); + + for (unsigned int ft = 0; ft < dev->ndev->be.cat.nb_flow_types; + ft++) { + set_flow_type_flm(dev->ndev, cfn, ft, 0, 0); + set_flow_type_flm(dev->ndev, cfn, ft, 1, 0); + set_flow_type_flm(dev->ndev, cfn, ft, 2, 0); + set_flow_type_flm(dev->ndev, cfn, ft, 3, 0); + } + } + + /* CTE / CTS */ + { + uint32_t cte = 0; + + hw_mod_cat_cte_get(&dev->ndev->be, HW_CAT_CTE_ENABLE_BM, cfn, + &cte); + + if (cte) { + const int cts_offset = + ((int)dev->ndev->be.cat.cts_num + 1) / 2; + + hw_mod_cat_cte_set(&dev->ndev->be, HW_CAT_CTE_ENABLE_BM, + cfn, 0); + hw_mod_cat_cte_flush(&dev->ndev->be, cfn, 1); + + for (int cte_type = 0; cte_type < cts_offset; + ++cte_type) { + hw_mod_cat_cts_set(&dev->ndev->be, + HW_CAT_CTS_CAT_A, + cts_offset * cfn + cte_type, + 0); + hw_mod_cat_cts_set(&dev->ndev->be, + HW_CAT_CTS_CAT_B, + cts_offset * cfn + cte_type, + 0); + } + + hw_mod_cat_cts_flush(&dev->ndev->be, cts_offset * cfn, + cts_offset); + } + } + + return 0; +} + +static int convert_fd_to_flm(struct flow_handle *fh, struct nic_flow_def *fd, + const uint32_t *packet_data, uint32_t flm_key_id, + uint16_t rpl_ext_ptr, uint32_t priority) +{ + if (fh->type != FLOW_HANDLE_TYPE_FLM) + return -1; + + switch (fd->l4_prot) { + case PROT_L4_TCP: + fh->flm_prot = 6; + break; + case PROT_L4_UDP: + fh->flm_prot = 17; + break; + case PROT_L4_SCTP: + fh->flm_prot = 132; + break; + case PROT_L4_ICMP: + fh->flm_prot = 1; + break; + default: + switch (fd->tunnel_l4_prot) { + case PROT_TUN_L4_TCP: + fh->flm_prot = 6; + break; + case PROT_TUN_L4_UDP: + fh->flm_prot = 17; + break; + case PROT_TUN_L4_SCTP: + fh->flm_prot = 132; + break; + case PROT_TUN_L4_ICMP: + fh->flm_prot = 1; + break; + default: + fh->flm_prot = 0; + break; + } + break; + } + + memcpy(fh->flm_data, packet_data, sizeof(uint32_t) * 10); + + fh->flm_kid = flm_key_id; + fh->flm_rpl_ext_ptr = rpl_ext_ptr; + fh->flm_prio = (uint8_t)priority; + + for (unsigned int i = 0; i < fd->modify_field_count; ++i) { + switch (fd->modify_field[i].select) { + case CPY_SELECT_DSCP_IPV4: + /* fallthrough */ + case CPY_SELECT_DSCP_IPV6: + fh->flm_dscp = fd->modify_field[i].value8[0]; + break; + case CPY_SELECT_RQI_QFI: + fh->flm_rqi = (fd->modify_field[i].value8[0] >> 6) & + 0x1; + fh->flm_qfi = fd->modify_field[i].value8[0] & 0x3f; + break; + case CPY_SELECT_IPV4: + fh->flm_nat_ipv4 = + ntohl(fd->modify_field[i].value32[0]); + break; + case CPY_SELECT_PORT: + fh->flm_nat_port = + ntohs(fd->modify_field[i].value16[0]); + break; + case CPY_SELECT_TEID: + fh->flm_teid = ntohl(fd->modify_field[i].value32[0]); + break; + } + } + + fh->flm_mtu_fragmentation_recipe = fd->flm_mtu_fragmentation_recipe; + + return 0; +} + +static int flm_flow_programming(struct flow_eth_dev *dev, + struct flow_handle *fh, uint32_t *mtr_ids, + uint32_t flm_ft, uint32_t flm_op) +{ + struct flm_v17_lrn_data_s learn_record; + + if (fh->type != FLOW_HANDLE_TYPE_FLM) + return -1; + + memset(&learn_record, 0x0, sizeof(struct flm_v17_lrn_data_s)); + + learn_record.qw0[0] = fh->flm_data[9]; + learn_record.qw0[1] = fh->flm_data[8]; + learn_record.qw0[2] = fh->flm_data[7]; + learn_record.qw0[3] = fh->flm_data[6]; + learn_record.qw4[0] = fh->flm_data[5]; + learn_record.qw4[1] = fh->flm_data[4]; + learn_record.qw4[2] = fh->flm_data[3]; + learn_record.qw4[3] = fh->flm_data[2]; + learn_record.sw8 = fh->flm_data[1]; + learn_record.sw9 = fh->flm_data[0]; + learn_record.prot = fh->flm_prot; + + if (mtr_ids) { + FLM_V17_MBR_ID1(learn_record.mbr_idx) = mtr_ids[0]; + FLM_V17_MBR_ID2(learn_record.mbr_idx) = mtr_ids[1]; + FLM_V17_MBR_ID3(learn_record.mbr_idx) = mtr_ids[2]; + FLM_V17_MBR_ID4(learn_record.mbr_idx) = mtr_ids[3]; + + /* Last non-zero mtr is used for statistics */ + uint8_t mbrs = 0; + + while (mbrs < MAX_FLM_MTRS_SUPPORTED && mtr_ids[mbrs] != 0) + ++mbrs; + learn_record.vol_idx = mbrs; + } + + learn_record.nat_ip = fh->flm_nat_ipv4; + learn_record.nat_port = fh->flm_nat_port; + learn_record.nat_en = fh->flm_nat_ipv4 || fh->flm_nat_port ? 1 : 0; + + learn_record.dscp = fh->flm_dscp; + learn_record.teid = fh->flm_teid; + learn_record.qfi = fh->flm_qfi; + learn_record.rqi = fh->flm_rqi; + learn_record.color = fh->flm_rpl_ext_ptr & + 0x3ff; /* Lower 10 bits used for RPL EXT PTR */ + learn_record.color |= (fh->flm_mtu_fragmentation_recipe & 0xf) + << 10; /* Bit [13:10] used for MTU recipe */ + + learn_record.ent = 0; + learn_record.op = flm_op & 0xf; + learn_record.prio = fh->flm_prio & 0x3; + learn_record.ft = flm_ft; + learn_record.kid = fh->flm_kid; + learn_record.eor = 1; + + int res = flow_flm_apply(dev, &learn_record); + return res; +} + +static int km_ft_handler(int *setup_km_ft, int *setup_km_rcp, int *setup_km, + struct flow_handle *found_flow, int identical_flow_found, struct flow_eth_dev *dev, + struct nic_flow_def *fd, struct flow_error *error, struct flow_handle *fh, + struct flow_handle *flow) +{ + if (!identical_flow_found) { + /* Find existing KM FT that can be reused */ + { + int found_ft = 0, found_zero = 0; + + struct flm_flow_ft_ident_s *ft_idents = + (struct flm_flow_ft_ident_s *)dev->ndev->ft_res_handle; + struct flm_flow_ft_ident_s ft_ident = flow_def_to_ft_ident(fd); + + for (int i = 1; i < FLM_FLOW_FT_MAX; ++i) { + if (ft_ident.data == ft_idents[i].data) { + found_ft = i; + break; + } else if (found_zero == 0 && ft_idents[i].data == 0) { + found_zero = i; + } + } + + if (found_ft) { + if (flow_nic_ref_resource(dev->ndev, RES_KM_FLOW_TYPE, found_ft)) { + NT_LOG(ERR, FILTER, "ERROR: Could not reference " + "KM FLOW TYPE resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error); + return 1; + } + + fh->resource[RES_KM_FLOW_TYPE].count = 1; + fh->resource[RES_KM_FLOW_TYPE].index = found_ft; + fh->resource[RES_KM_FLOW_TYPE].referenced = 1; + } else if (found_zero) { + if (flow_nic_allocate_fh_resource_index(dev->ndev, RES_KM_FLOW_TYPE, + found_zero, fh)) { + NT_LOG(ERR, FILTER, "ERROR: Could not get " + "KM FLOW TYPE resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error); + return 1; + } + + ft_idents[found_zero].data = ft_ident.data; + } else { + NT_LOG(ERR, FILTER, "ERROR: Could not get KM FLOW TYPE resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error); + return 1; + } + } + /* Attach resources to KM entry */ + km_attach_ndev_resource_management(&fd->km, &dev->ndev->km_res_handle); + fd->km.flow_type = fh->resource[RES_KM_FLOW_TYPE].index; + + /* _update existing KM RCP or allocate a new RCP */ + if (found_flow != NULL) { + if (flow_nic_ref_resource(dev->ndev, RES_KM_CATEGORY, found_flow + ->resource[RES_KM_CATEGORY].index)) { + NT_LOG(ERR, FILTER, "ERROR: Could not reference " + "KM CATEGORY resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error); + return 1; + } + + fh->resource[RES_KM_CATEGORY].count = 1; + fh->resource[RES_KM_CATEGORY].index = + found_flow->resource[RES_KM_CATEGORY].index; + fh->resource[RES_KM_CATEGORY].referenced = 1; + + if (fd->km.target == KM_CAM) { + uint32_t ft_a_mask = 0; + + hw_mod_km_rcp_get(&dev->ndev->be, HW_KM_RCP_FTM_A, + fh->resource[RES_KM_CATEGORY].index, 0, &ft_a_mask); + hw_mod_km_rcp_set(&dev->ndev->be, HW_KM_RCP_FTM_A, + fh->resource[RES_KM_CATEGORY].index, 0, + ft_a_mask | (1 << fd->km.flow_type)); + } + } else { + if (flow_nic_allocate_fh_resource(dev->ndev, RES_KM_CATEGORY, fh, 1, 1)) { + NT_LOG(ERR, FILTER, "ERROR: Could not get KM CATEGORY resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error); + return 1; + } + + /* Note: km_rcp_set clears existing RCPs */ + km_rcp_set(&fd->km, fh->resource[RES_KM_CATEGORY].index); + } + + /* Set filter setup variables */ + *setup_km = 1; + *setup_km_ft = fh->resource[RES_KM_FLOW_TYPE].index; + *setup_km_rcp = fh->resource[RES_KM_CATEGORY].index; + + /* _flush KM RCP and entry */ + hw_mod_km_rcp_flush(&dev->ndev->be, fh->resource[RES_KM_CATEGORY].index, 1); + + km_write_data_match_entry(&fd->km, 0); + } else { + if (flow_nic_ref_resource(dev->ndev, RES_KM_FLOW_TYPE, + found_flow->resource[RES_KM_FLOW_TYPE].index)) { + NT_LOG(ERR, FILTER, "ERROR: Could not reference KM FLOW TYPE resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error); + return 1; + } + + fh->resource[RES_KM_FLOW_TYPE].count = 1; + fh->resource[RES_KM_FLOW_TYPE].index = found_flow->resource[RES_KM_FLOW_TYPE].index; + fh->resource[RES_KM_FLOW_TYPE].referenced = 1; + + if (flow_nic_ref_resource(dev->ndev, RES_KM_CATEGORY, + found_flow->resource[RES_KM_CATEGORY].index)) { + NT_LOG(ERR, FILTER, "ERROR: Could not reference KM CATEGORY resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error); + return 1; + } + + fh->resource[RES_KM_CATEGORY].count = 1; + fh->resource[RES_KM_CATEGORY].index = found_flow->resource[RES_KM_CATEGORY].index; + fh->resource[RES_KM_CATEGORY].referenced = 1; + + km_attach_ndev_resource_management(&fd->km, &dev->ndev->km_res_handle); + fd->km.flow_type = fh->resource[RES_KM_FLOW_TYPE].index; + + km_refer_data_match_entry(&fd->km, &found_flow->fd->km); + + *setup_km = 1; + *setup_km_ft = flow->resource[RES_KM_FLOW_TYPE].index; + *setup_km_rcp = flow->resource[RES_KM_CATEGORY].index; + } + return 0; +} + +/* + * Tunneling invalidates dynamic offsets, so change them to static + * offsets starting at beginning of L2. + */ +static void align_tun_offset(struct nic_flow_def *fd, const uint32_t eth_length, int i, + uint32_t *ofs, uint32_t select, const uint32_t l2_length, const uint32_t l3_length, + const uint32_t l4_length, uint32_t *dyn) +{ + if (fd->tun_hdr.len > eth_length) { + if (!fd->tun_hdr.new_outer || fd->modify_field[i].level > 1) { + ofs += fd->tun_hdr.len - eth_length; + } else { + switch (select) { + case CPY_SELECT_IPV4: + case CPY_SELECT_DSCP_IPV4: + case CPY_SELECT_DSCP_IPV6: + *ofs += l2_length; + break; + case CPY_SELECT_PORT: + *ofs += l2_length + l3_length; + break; + case CPY_SELECT_TEID: + case CPY_SELECT_RQI_QFI: + *ofs += l2_length + l3_length + l4_length; + break; + } + *dyn = 1; + } + } +} + +static struct flow_handle * +create_flow_filter(struct flow_eth_dev *dev, struct nic_flow_def *fd, + const struct flow_attr *attr, struct flow_error *error, + uint32_t port_id, uint32_t num_dest_port, + uint32_t num_queues, uint32_t *packet_data, + uint32_t *packet_mask, struct flm_flow_key_def_s *key_def) +{ + uint32_t qsl_size = num_dest_port > num_queues ? num_dest_port : + num_queues; + uint32_t flm_key_id = 0; + uint32_t flm_ft = 0; + uint16_t flm_rpl_ext_ptr = 0; + + struct flow_handle *fh_flm = NULL; + struct flow_handle *fh = calloc(1, sizeof(struct flow_handle)); + + if (!fh) { + NT_LOG(ERR, FILTER, "ERR memory\n"); + flow_nic_set_error(ERR_MEMORY, error); + return NULL; + } + + fh->type = FLOW_HANDLE_TYPE_FLOW; + fh->port_id = port_id; + fh->dev = dev; + fh->fd = fd; + + int setup_cat_cfn = 0; + int setup_cat_cot = 0; + int setup_cat_cts = 0; + int setup_qsl_rcp = 0; + + int setup_flm = 0; + int setup_flm_ft = 0; + + int setup_km = 0; + int setup_km_ft = 0; + int setup_km_rcp = 0; + + int setup_default_ft = 0; + + int setup_hst = 0; + int setup_tpe = 0; + int setup_tpe_encap_data = 0; + + int free_fd = 0; + + const int empty_pattern = + fd->l2_prot < 0 && fd->l3_prot < 0 && fd->l4_prot < 0 && + fd->vlans == 0 && fd->tunnel_prot < 0 && + fd->tunnel_l3_prot < 0 && fd->tunnel_l4_prot < 0; + + if (attr->group > 0 && empty_pattern) { + /* + * Group 0 default filter actions + */ + struct flow_handle *fh_miss = NULL; + + if (flm_flow_get_group_miss_fh(dev, attr->group, &fh_miss)) { + /* Error was printed to log by flm_flow_get_group_miss_fh */ + flow_nic_set_error(ERR_FAILED, error); + free(fh); + return NULL; + } + + if (fh_miss == NULL) { + NT_LOG(ERR, FILTER, + "ERROR: Could not setup default action for uninitialized group\n"); + flow_nic_set_error(ERR_FAILED, error); + free(fh); + return NULL; + } + + if (qsl_size > 0 && + flow_nic_allocate_fh_resource(dev->ndev, RES_QSL_QST, fh, + qsl_size, 1)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not get QSL QST resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + free(fh); + return NULL; + } + + if (flow_nic_ref_resource(dev->ndev, RES_QSL_RCP, + fh_miss->resource[RES_QSL_RCP].index)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not reference QSL RCP resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + free(fh); + return NULL; + } + + fh->resource[RES_QSL_RCP].count = 1; + fh->resource[RES_QSL_RCP].index = + fh_miss->resource[RES_QSL_RCP].index; + fh->resource[RES_QSL_RCP].referenced = 1; + + nic_insert_flow(dev->ndev, fh); + + setup_qsl_rcp = 1; + } else if (attr->group > 0) { + /* + * FLM programming + */ + struct flow_handle *fh_existing = NULL; + int cfn_to_copy = -1; + + if (attr->priority >= dev->ndev->be.flm.nb_prios) { + NT_LOG(ERR, FILTER, + "ERROR: Priority value of FLM flow exceeds %u" + "\n", + dev->ndev->be.flm.nb_prios); + flow_nic_set_error(ERR_FLOW_PRIORITY_VALUE_INVALID, + error); + free(fh); + return NULL; + } + + if (flm_flow_learn_prepare(dev, fh, attr->group, key_def, + packet_mask, &flm_key_id, &flm_ft, + &cfn_to_copy, &setup_km_ft, + &fh_existing)) { + /* Error was printed to log by flm_flow_learn_prepare */ + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + free(fh); + return NULL; + } + + setup_tpe_encap_data = (fd->tun_hdr.len > 0); + setup_tpe = + (fd->modify_field_count > 0 || fd->ttl_sub_enable > 0); + + /* Create HIT filter for new FLM FT */ + if (cfn_to_copy >= 0) { + uint32_t value = 0; + + nic_insert_flow(dev->ndev, fh); + + setup_qsl_rcp = 1; + setup_cat_cot = 1; + setup_cat_cts = 1; + + setup_default_ft = 1; + + setup_flm = 1; + setup_flm_ft = (int)flm_ft; + + setup_tpe |= setup_tpe_encap_data; + + if (fd->header_strip_start_dyn != fd->header_strip_end_dyn || + fd->header_strip_start_ofs != fd->header_strip_end_ofs) + setup_hst = 1; + + if (flow_nic_allocate_fh_resource(dev->ndev, + RES_CAT_CFN, + fh, 1, 1)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not get CAT CFN resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + + if (flow_nic_allocate_fh_resource(dev->ndev, + RES_CAT_COT, + fh, 1, 1)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not get CAT COT resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + + if (flow_nic_allocate_fh_resource(dev->ndev, + RES_QSL_RCP, + fh, 1, 1)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not get QSL RCP resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + + if (qsl_size > 0 && + flow_nic_allocate_fh_resource(dev->ndev, + RES_QSL_QST, + fh, qsl_size, 1)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not get QSL QST resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + + NT_LOG(DBG, FILTER, + "FLM: Creating new CFN %d as a copy of CFN %d with FT %d\n", + fh->resource[RES_CAT_CFN].index, cfn_to_copy, + setup_flm_ft); + + /* Copy parts from base MISS filter */ + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_COPY_FROM, + fh->resource[RES_CAT_CFN].index, 0, + cfn_to_copy); + hw_mod_cat_cfn_flush(&dev->ndev->be, + fh->resource[RES_CAT_CFN].index, + 1); + + hw_mod_cat_kcs_km_get(&dev->ndev->be, + HW_CAT_KCS_CATEGORY, + KM_FLM_IF_FIRST, cfn_to_copy, + &value); + if (value > 0) { + setup_km = 1; + setup_km_rcp = (int)value; + } + + hw_mod_cat_kcs_flm_get(&dev->ndev->be, + HW_CAT_KCS_CATEGORY, + KM_FLM_IF_FIRST, cfn_to_copy, + &value); + hw_mod_cat_kcs_flm_set(&dev->ndev->be, + HW_CAT_KCS_CATEGORY, + KM_FLM_IF_FIRST, + fh->resource[RES_CAT_CFN].index, + value); + hw_mod_cat_kcs_flm_flush(&dev->ndev->be, + KM_FLM_IF_FIRST, + fh->resource[RES_CAT_CFN].index, + 1); + + fh_flm = calloc(1, sizeof(struct flow_handle)); + if (!fh_flm) { + flow_nic_set_error(ERR_MEMORY, error); + return NULL; + } + + nic_insert_flow_flm(dev->ndev, fh_flm); + + fh_flm->type = FLOW_HANDLE_TYPE_FLM; + fh_flm->dev = dev; + fh_flm->flm_owner = fh; + } else { + /* Reuse allocated memory */ + fh_flm = fh; + fh = fh_existing; + + nic_insert_flow_flm(dev->ndev, fh_flm); + + fh_flm->type = FLOW_HANDLE_TYPE_FLM; + fh_flm->dev = dev; + fh_flm->flm_owner = fh_existing; + + free_fd = 1; + } + + fh_flm->flm_owner->flm_ref_count += 1; + } else { + /* + * Filter creation + */ + nic_insert_flow(dev->ndev, fh); + + setup_cat_cfn = 1; + setup_cat_cts = 1; + setup_qsl_rcp = 1; + + if (fd->km.num_ftype_elem) { + struct flow_handle *flow = dev->ndev->flow_base, + *found_flow = NULL; + int identical_flow_found = 0; + + /* Compute new KM key */ + if (km_key_create(&fd->km, fh->port_id)) { + NT_LOG(ERR, FILTER, "KM creation failed\n"); + flow_nic_set_error(ERR_MATCH_FAILED_BY_HW_LIMITS, + error); + return NULL; + } + + fd->km.be = &dev->ndev->be; + + /* Find existing KM key that can be reused */ + while (flow) { + if (flow->type == FLOW_HANDLE_TYPE_FLOW && + flow->fd->km + .flow_type && /* This check also skips self */ + flow->resource[RES_KM_CATEGORY].count) { + int res = km_key_compare(&fd->km, + &flow->fd->km); + if (res < 0) { + identical_flow_found = 1; + found_flow = flow; + break; + } else if (res > 0 && + !flow->resource[RES_KM_CATEGORY] + .referenced && + found_flow == NULL) + found_flow = flow; + } + flow = flow->next; + } + if (km_ft_handler(&setup_km_ft, &setup_km_rcp, &setup_km, + found_flow, identical_flow_found, dev, fd, error, fh, flow)) + return NULL; + } + + setup_default_ft = 1; + + if (flow_nic_allocate_fh_resource(dev->ndev, RES_CAT_CFN, + fh, 1, 1)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not get CAT CFN resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + + if (flow_nic_allocate_fh_resource(dev->ndev, RES_QSL_RCP, fh, 1, + 1)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not get QSL RCP resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + + if (qsl_size > 0 && + flow_nic_allocate_fh_resource(dev->ndev, RES_QSL_QST, + fh, qsl_size, 1)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not get QSL QST resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + + /* Check if filter is set up for FLM */ + if (fd->jump_to_group != UINT32_MAX) { + flm_flow_setup_group(dev, fd->jump_to_group, + fh->resource[RES_CAT_CFN].index, + fh->resource[RES_KM_FLOW_TYPE].index, + fh); + } + } + + /* + * Setup QSL + */ + if (setup_qsl_rcp) { + if (qsl_size == 0) { + /* Create drop filter */ + hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_DISCARD, + fh->resource[RES_QSL_RCP].index, + 0x0); + hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_DROP, + fh->resource[RES_QSL_RCP].index, + 0x3); + hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_LR, + fh->resource[RES_QSL_RCP].index, + 0x0); + + hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_TBL_LO, + fh->resource[RES_QSL_RCP].index, 0); + hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_TBL_HI, + fh->resource[RES_QSL_RCP].index, 0); + + hw_mod_qsl_rcp_flush(&dev->ndev->be, + fh->resource[RES_QSL_RCP].index, + 1); + } else { + const int table_start = fh->resource[RES_QSL_QST].index; + const int table_end = table_start + + fh->resource[RES_QSL_QST].count - + 1; + + /* Use 0x0 for pure retransmit */ + hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_DISCARD, + fh->resource[RES_QSL_RCP].index, + 0x0); + hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_DROP, + fh->resource[RES_QSL_RCP].index, + 0x0); + hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_LR, + fh->resource[RES_QSL_RCP].index, + num_dest_port > 0 ? 0x3 : 0x0); + + hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_TBL_LO, + fh->resource[RES_QSL_RCP].index, + table_start); + hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_TBL_HI, + fh->resource[RES_QSL_RCP].index, + table_end); + + hw_mod_qsl_rcp_flush(&dev->ndev->be, + fh->resource[RES_QSL_RCP].index, + 1); + + /* Setup QSL QST/QEN */ + if (num_dest_port > 0 && num_queues > 0) { + int ports[num_dest_port]; + int queues[num_queues]; + + int port_index = 0; + int queue_index = 0; + + for (int i = 0; i < fd->dst_num_avail; ++i) { + if (fd->dst_id[i].type == PORT_PHY) { + ports[port_index++] = + fd->dst_id[i].id; + } else if (fd->dst_id[i].type == + PORT_VIRT) { + queues[queue_index++] = + fd->dst_id[i].id; + } + } + + for (int i = 0; i < fd->dst_num_avail; ++i) { + hw_mod_qsl_qst_set(&dev->ndev->be, + HW_QSL_QST_TX_PORT, + table_start + i, + ports[i % num_dest_port]); + hw_mod_qsl_qst_set(&dev->ndev->be, + HW_QSL_QST_LRE, + table_start + i, 1); + + hw_mod_qsl_qst_set(&dev->ndev->be, + HW_QSL_QST_QUEUE, + table_start + i, + queues[i % num_queues]); + hw_mod_qsl_qst_set(&dev->ndev->be, + HW_QSL_QST_EN, + table_start + i, 1); + } + } else if (num_dest_port > 0) { + for (int i = 0; i < fd->dst_num_avail; ++i) { + hw_mod_qsl_qst_set(&dev->ndev->be, + HW_QSL_QST_TX_PORT, + table_start + i, + fd->dst_id[i].id); + hw_mod_qsl_qst_set(&dev->ndev->be, + HW_QSL_QST_LRE, + table_start + i, 1); + } + } else if (num_queues > 0) { + for (int i = 0; i < fd->dst_num_avail; ++i) { + hw_mod_qsl_qst_set(&dev->ndev->be, + HW_QSL_QST_QUEUE, + table_start + i, + fd->dst_id[i].id); + hw_mod_qsl_qst_set(&dev->ndev->be, + HW_QSL_QST_EN, + table_start + i, 1); + } + } + + hw_mod_qsl_qst_flush(&dev->ndev->be, table_start, + fd->dst_num_avail); + } + } + + /* + * Setup CAT KM functionality + */ + if (setup_km) { + uint32_t bm = 0; + + /* Enable KM match FS for key A */ + set_flow_type_km(dev->ndev, fh->resource[RES_CAT_CFN].index, + setup_km_ft, 0, 1); + + /* KM function select */ + hw_mod_cat_kcs_km_set(&dev->ndev->be, HW_CAT_KCS_CATEGORY, + KM_FLM_IF_FIRST, + fh->resource[RES_CAT_CFN].index, + setup_km_rcp); + hw_mod_cat_kcs_km_flush(&dev->ndev->be, KM_FLM_IF_FIRST, + fh->resource[RES_CAT_CFN].index, 1); + + /* KM function enable */ + hw_mod_cat_kce_km_get(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM, + KM_FLM_IF_FIRST, + fh->resource[RES_CAT_CFN].index / 8, &bm); + hw_mod_cat_kce_km_set(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM, + KM_FLM_IF_FIRST, fh->resource[RES_CAT_CFN].index / 8, + bm | (1 << (fh->resource[RES_CAT_CFN].index % 8))); + hw_mod_cat_kce_km_flush(&dev->ndev->be, KM_FLM_IF_FIRST, + fh->resource[RES_CAT_CFN].index / 8, 1); + } else if (setup_default_ft) { + /* Enable "no KM match" FT for key A */ + set_flow_type_km(dev->ndev, fh->resource[RES_CAT_CFN].index, + 0, 0, 1); + } + + /* + * Setup CAT FLM functionality + */ + if (setup_flm) { + uint32_t bm = 0; + + /* Enable KM match FT for key A, and FLM match FT for key C */ + set_flow_type_flm(dev->ndev, fh->resource[RES_CAT_CFN].index, + setup_km_ft, 0, 1); /* KM FT A */ + set_flow_type_flm(dev->ndev, fh->resource[RES_CAT_CFN].index, + setup_flm_ft, 2, 1); /* FLM FT C */ + + /* FLM function enable */ + hw_mod_cat_kce_flm_get(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM, + KM_FLM_IF_FIRST, + fh->resource[RES_CAT_CFN].index / 8, + &bm); + hw_mod_cat_kce_flm_set(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM, + KM_FLM_IF_FIRST, fh->resource[RES_CAT_CFN].index / 8, + bm | (1 << (fh->resource[RES_CAT_CFN].index % 8))); + hw_mod_cat_kce_flm_flush(&dev->ndev->be, KM_FLM_IF_FIRST, + fh->resource[RES_CAT_CFN].index / 8, + 1); + } else if (setup_default_ft) { + /* Enable KM for key A and UNHANDLED for key C */ + set_flow_type_flm(dev->ndev, fh->resource[RES_CAT_CFN].index, + setup_km_ft, 0, 1); + set_flow_type_flm(dev->ndev, fh->resource[RES_CAT_CFN].index, 1, + 2, 1); + } + + /* + * Setup HST + */ + if (setup_hst) { + int hst_index = -1; + + for (int i = 1; + i < (int)dev->ndev->res[RES_HST_RCP].resource_count; ++i) { + uint32_t values[] = { 0, 0, 0, 0, 0 }; + + if (!flow_nic_is_resource_used(dev->ndev, RES_HST_RCP, + i)) + continue; + + hw_mod_hst_rcp_get(&dev->ndev->be, + HW_HST_RCP_STRIP_MODE, i, + &values[0]); + hw_mod_hst_rcp_get(&dev->ndev->be, HW_HST_RCP_START_DYN, + i, &values[1]); + hw_mod_hst_rcp_get(&dev->ndev->be, HW_HST_RCP_START_OFS, + i, &values[2]); + hw_mod_hst_rcp_get(&dev->ndev->be, HW_HST_RCP_END_DYN, + i, &values[3]); + hw_mod_hst_rcp_get(&dev->ndev->be, HW_HST_RCP_END_OFS, + i, &values[4]); + + if ((int)values[0] == 1 && + (int)values[1] == fd->header_strip_start_dyn && + (int)values[2] == fd->header_strip_start_ofs && + (int)values[3] == fd->header_strip_end_dyn && + (int)values[4] == fd->header_strip_end_ofs) { + hst_index = i; + break; + } + } + + if (hst_index >= 0) { + if (flow_nic_ref_resource(dev->ndev, RES_HST_RCP, + hst_index)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not reference HST RCP resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + + fh->resource[RES_HST_RCP].count = 1; + fh->resource[RES_HST_RCP].index = hst_index; + fh->resource[RES_HST_RCP].referenced = 1; + } else { + if (flow_nic_allocate_fh_resource(dev->ndev, + RES_HST_RCP, + fh, 1, 1)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not get HST RCP resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + + hw_mod_hst_rcp_set(&dev->ndev->be, + HW_HST_RCP_STRIP_MODE, + fh->resource[RES_HST_RCP].index, 1); + hw_mod_hst_rcp_set(&dev->ndev->be, HW_HST_RCP_START_DYN, + fh->resource[RES_HST_RCP].index, + fd->header_strip_start_dyn); + hw_mod_hst_rcp_set(&dev->ndev->be, HW_HST_RCP_START_OFS, + fh->resource[RES_HST_RCP].index, + fd->header_strip_start_ofs); + hw_mod_hst_rcp_set(&dev->ndev->be, HW_HST_RCP_END_DYN, + fh->resource[RES_HST_RCP].index, + fd->header_strip_end_dyn); + hw_mod_hst_rcp_set(&dev->ndev->be, HW_HST_RCP_END_OFS, + fh->resource[RES_HST_RCP].index, + fd->header_strip_end_ofs); + + hw_mod_hst_rcp_set(&dev->ndev->be, + HW_HST_RCP_MODIF0_CMD, + fh->resource[RES_HST_RCP].index, + fd->header_strip_removed_outer_ip ? 7 : 6); + hw_mod_hst_rcp_set(&dev->ndev->be, + HW_HST_RCP_MODIF0_DYN, + fh->resource[RES_HST_RCP].index, 2); + hw_mod_hst_rcp_set(&dev->ndev->be, + HW_HST_RCP_MODIF0_OFS, + fh->resource[RES_HST_RCP].index, 0); + + hw_mod_hst_rcp_flush(&dev->ndev->be, + fh->resource[RES_HST_RCP].index, 1); + } + } + + /* + * Setup TPE + */ + if (setup_tpe_encap_data) { + int ext_rpl_index = -1; + int rpl_rpl_index = -1; + int rpl_rpl_length = -1; + + /* Find existing RPL */ + for (int i = 1; + i < (int)dev->ndev->res[RES_TPE_EXT].resource_count; ++i) { + int found = 1; + uint32_t len; + uint32_t ptr; + + if (!flow_nic_is_resource_used(dev->ndev, RES_TPE_EXT, + i)) + continue; + + hw_mod_tpe_rpl_ext_get(&dev->ndev->be, + HW_TPE_RPL_EXT_META_RPL_LEN, i, + &len); + if (len != fd->tun_hdr.len) + continue; + + hw_mod_tpe_rpl_ext_get(&dev->ndev->be, + HW_TPE_RPL_EXT_RPL_PTR, i, &ptr); + + for (uint32_t ptr_it = 0; ptr_it < (len + 15) / 16; + ++ptr_it) { + uint32_t data[4]; + + hw_mod_tpe_rpl_rpl_get(&dev->ndev->be, + HW_TPE_RPL_RPL_VALUE, + ptr + ptr_it, data); + + if (fd->tun_hdr.d.hdr32[ptr_it * 4 + 0] != + data[0] || + fd->tun_hdr.d.hdr32[ptr_it * 4 + 1] != + data[1] || + fd->tun_hdr.d.hdr32[ptr_it * 4 + 2] != + data[2] || + fd->tun_hdr.d.hdr32[ptr_it * 4 + 3] != + data[3]) { + found = 0; + break; + } + } + + if (found) { + ext_rpl_index = i; + rpl_rpl_index = (int)ptr; + rpl_rpl_length = (int)len; + break; + } + } + + /* Set RPL data */ + if (ext_rpl_index >= 0) { + if (flow_nic_ref_resource(dev->ndev, RES_TPE_EXT, + ext_rpl_index)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not reference TPE EXT resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + + for (int i = 0; i < (rpl_rpl_length + 15) / 16; ++i) { + if (flow_nic_ref_resource(dev->ndev, + RES_TPE_RPL, + rpl_rpl_index + i)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not reference TPE RPL resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + } + } else { + ext_rpl_index = flow_nic_alloc_resource(dev->ndev, + RES_TPE_EXT, 1); + if (ext_rpl_index < 0) { + NT_LOG(ERR, FILTER, + "ERROR: Could not get TPE EXT resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + + rpl_rpl_length = ((int)fd->tun_hdr.len + 15) / 16; + rpl_rpl_index = flow_nic_alloc_resource_contig(dev->ndev, + RES_TPE_RPL, + rpl_rpl_length, + 1); + if (rpl_rpl_index < 0) { + NT_LOG(ERR, FILTER, + "ERROR: Could not get TPE RPL resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + + /* Program new encap header data */ + hw_mod_tpe_rpl_ext_set(&dev->ndev->be, + HW_TPE_RPL_EXT_RPL_PTR, + ext_rpl_index, rpl_rpl_index); + hw_mod_tpe_rpl_ext_set(&dev->ndev->be, + HW_TPE_RPL_EXT_META_RPL_LEN, + ext_rpl_index, fd->tun_hdr.len); + hw_mod_tpe_rpl_ext_flush(&dev->ndev->be, ext_rpl_index, + 1); + + for (int i = 0; i < rpl_rpl_length; ++i) { + hw_mod_tpe_rpl_rpl_set(&dev->ndev->be, + HW_TPE_RPL_RPL_VALUE, + rpl_rpl_index + i, + fd->tun_hdr.d.hdr32 + i * 4); + } + hw_mod_tpe_rpl_rpl_flush(&dev->ndev->be, rpl_rpl_index, + rpl_rpl_length); + } + + flm_rpl_ext_ptr = ext_rpl_index; + } + + if (setup_tpe) { + const uint32_t eth_length = 14; + const uint32_t l2_length = fd->tun_hdr.l2_len; + const uint32_t l3_length = fd->tun_hdr.l3_len; + const uint32_t l4_length = fd->tun_hdr.l4_len; + const uint32_t fcs_length = 4; + + int tpe_index = -1; + + /* Find existing RCP */ + for (int i = 1; + i < (int)dev->ndev->res[RES_TPE_RCP].resource_count; ++i) { + uint32_t value; + + if (!flow_nic_is_resource_used(dev->ndev, RES_TPE_RCP, + i)) + continue; + + hw_mod_tpe_rpl_rcp_get(&dev->ndev->be, + HW_TPE_RPL_RCP_LEN, i, &value); + if (value != fd->tun_hdr.len) + continue; + hw_mod_tpe_rpl_rcp_get(&dev->ndev->be, + HW_TPE_RPL_RCP_DYN, i, &value); + if (value != 1) + continue; + hw_mod_tpe_rpl_rcp_get(&dev->ndev->be, + HW_TPE_RPL_RCP_OFS, i, &value); + if (value != 0) + continue; + hw_mod_tpe_hfu_rcp_get(&dev->ndev->be, + HW_TPE_HFU_RCP_L3_PRT, i, + &value); + if (value != (fd->tun_hdr.ip_version == 4 ? 1 : 2)) + continue; + hw_mod_tpe_hfu_rcp_get(&dev->ndev->be, + HW_TPE_HFU_RCP_OUTER_L3_OFS, i, + &value); + if (value != l2_length) + continue; + + tpe_index = i; + break; + } + + /* Set RCP data */ + if (tpe_index >= 0) { + if (flow_nic_ref_resource(dev->ndev, RES_TPE_RCP, + tpe_index)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not reference TPE RCP resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + + fh->resource[RES_TPE_RCP].count = 1; + fh->resource[RES_TPE_RCP].index = tpe_index; + fh->resource[RES_TPE_RCP].referenced = 1; + } else { + if (flow_nic_allocate_fh_resource(dev->ndev, + RES_TPE_RCP, + fh, 1, 1)) { + NT_LOG(ERR, FILTER, + "ERROR: Could not get TPE RCP resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, + error); + return NULL; + } + + /* Extend packet if needed. */ + if (fd->tun_hdr.len > eth_length) { + /* Extend FPGA packet buffer */ + hw_mod_tpe_rpp_rcp_set(&dev->ndev->be, + HW_TPE_RPP_RCP_EXP, + fh->resource[RES_TPE_RCP].index, + fd->tun_hdr.len - eth_length); + hw_mod_tpe_rpp_rcp_flush(&dev->ndev->be, + fh->resource[RES_TPE_RCP].index, + 1); + + /* + * Insert 0's into packet + * After this step DYN offsets are shifted by encap length, + * so only DYN offset 1 and 18 should be used + */ + hw_mod_tpe_ins_rcp_set(&dev->ndev->be, + HW_TPE_INS_RCP_DYN, + fh->resource[RES_TPE_RCP].index, 1); + hw_mod_tpe_ins_rcp_set(&dev->ndev->be, + HW_TPE_INS_RCP_OFS, + fh->resource[RES_TPE_RCP].index, 0); + hw_mod_tpe_ins_rcp_set(&dev->ndev->be, + HW_TPE_INS_RCP_LEN, + fh->resource[RES_TPE_RCP].index, + fd->tun_hdr.len - eth_length); + hw_mod_tpe_ins_rcp_flush(&dev->ndev->be, + fh->resource[RES_TPE_RCP].index, + 1); + } + + if (fd->tun_hdr.len > 0) { + /* Write header data to beginning of packet */ + hw_mod_tpe_rpl_rcp_set(&dev->ndev->be, + HW_TPE_RPL_RCP_DYN, + fh->resource[RES_TPE_RCP].index, + 1); + hw_mod_tpe_rpl_rcp_set(&dev->ndev->be, + HW_TPE_RPL_RCP_OFS, + fh->resource[RES_TPE_RCP].index, + 0); + hw_mod_tpe_rpl_rcp_set(&dev->ndev->be, + HW_TPE_RPL_RCP_LEN, + fh->resource[RES_TPE_RCP].index, + fd->tun_hdr.len); + hw_mod_tpe_rpl_rcp_set(&dev->ndev->be, + HW_TPE_RPL_RCP_RPL_PTR, + fh->resource[RES_TPE_RCP].index, + 0); + hw_mod_tpe_rpl_rcp_set(&dev->ndev->be, + HW_TPE_RPL_RCP_EXT_PRIO, + fh->resource[RES_TPE_RCP].index, + 1); + hw_mod_tpe_rpl_rcp_flush(&dev->ndev->be, + fh->resource[RES_TPE_RCP].index, + 1); + } + + for (unsigned int i = 0; i < fd->modify_field_count; + ++i) { + uint32_t select = fd->modify_field[i].select; + uint32_t dyn = fd->modify_field[i].dyn; + uint32_t ofs = fd->modify_field[i].ofs; + uint32_t len = fd->modify_field[i].len; + + align_tun_offset(fd, eth_length, i, &ofs, select, l2_length, + l3_length, l4_length, &dyn); + + hw_mod_tpe_cpy_rcp_set(&dev->ndev->be, + HW_TPE_CPY_RCP_READER_SELECT, + fh->resource[RES_TPE_RCP].index + + 16 * i, + select); + hw_mod_tpe_cpy_rcp_set(&dev->ndev->be, + HW_TPE_CPY_RCP_DYN, + fh->resource[RES_TPE_RCP].index + + 16 * i, + dyn); + hw_mod_tpe_cpy_rcp_set(&dev->ndev->be, + HW_TPE_CPY_RCP_OFS, + fh->resource[RES_TPE_RCP].index + + 16 * i, + ofs); + hw_mod_tpe_cpy_rcp_set(&dev->ndev->be, + HW_TPE_CPY_RCP_LEN, + fh->resource[RES_TPE_RCP].index + + 16 * i, + len); + hw_mod_tpe_cpy_rcp_flush(&dev->ndev->be, + fh->resource[RES_TPE_RCP].index + + 16 * i, + 1); + } + + if (fd->tun_hdr.new_outer) { + /* + * UDP length + * dyn_ofs[ADD_DYN] - dyn_ofs[SUB_DYN] + ADD_OFS + */ + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_A_WR, + fh->resource[RES_TPE_RCP].index, + 1); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_A_OUTER_L4_LEN, + fh->resource[RES_TPE_RCP].index, + 1); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_A_POS_DYN, + fh->resource[RES_TPE_RCP].index, + 1); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_A_POS_OFS, + fh->resource[RES_TPE_RCP].index, + l2_length + l3_length + 4); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_A_ADD_DYN, + fh->resource[RES_TPE_RCP].index, + 18); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_A_ADD_OFS, + fh->resource[RES_TPE_RCP].index, + -(l2_length + l3_length + fcs_length)); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_A_SUB_DYN, + fh->resource[RES_TPE_RCP].index, + 1); + + /* IPv4/IPv6 length */ + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_B_WR, + fh->resource[RES_TPE_RCP].index, + 1); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_B_POS_DYN, + fh->resource[RES_TPE_RCP].index, + 1); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_B_POS_OFS, + fh->resource[RES_TPE_RCP].index, + l2_length + + (fd->tun_hdr.ip_version == 4 ? 2 : 4)); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_B_ADD_DYN, + fh->resource[RES_TPE_RCP].index, + 18); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_B_ADD_OFS, + fh->resource[RES_TPE_RCP].index, + -(l2_length + + (fd->tun_hdr.ip_version == 4 ? + 0 : l3_length) + fcs_length)); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_B_SUB_DYN, + fh->resource[RES_TPE_RCP].index, + 1); + + /* GTP length */ + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_C_WR, + fh->resource[RES_TPE_RCP].index, + 1); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_C_POS_DYN, + fh->resource[RES_TPE_RCP].index, + 1); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_C_POS_OFS, + fh->resource[RES_TPE_RCP].index, + l2_length + l3_length + l4_length + 2); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_C_ADD_DYN, + fh->resource[RES_TPE_RCP].index, + 18); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_C_ADD_OFS, + fh->resource[RES_TPE_RCP].index, + -(l2_length + l3_length + l4_length + + 8 + fcs_length)); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_LEN_C_SUB_DYN, + fh->resource[RES_TPE_RCP].index, + 1); + + /* _update TTL */ + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_TTL_WR, + fh->resource[RES_TPE_RCP].index, + fd->ttl_sub_enable); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_TTL_POS_DYN, + fh->resource[RES_TPE_RCP].index, + fd->ttl_sub_outer ? 1 : DYN_L3); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_TTL_POS_OFS, + fh->resource[RES_TPE_RCP].index, + (fd->ttl_sub_outer ? + l2_length : + fd->tun_hdr.len - eth_length) + + (fd->ttl_sub_ipv4 ? 8 : 7)); + + /* _update FPGA DYN offsets */ + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_CS_INF, + fh->resource[RES_TPE_RCP].index, + 1); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_L3_PRT, + fh->resource[RES_TPE_RCP].index, + (fd->tun_hdr.ip_version == 4 ? 1 : 2)); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_L3_FRAG, + fh->resource[RES_TPE_RCP].index, + 0); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_TUNNEL, + fh->resource[RES_TPE_RCP].index, + 6); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_L4_PRT, + fh->resource[RES_TPE_RCP].index, + 2); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_OUTER_L3_OFS, + fh->resource[RES_TPE_RCP].index, + l2_length); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_OUTER_L4_OFS, + fh->resource[RES_TPE_RCP].index, + l2_length + l3_length); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_INNER_L3_OFS, + fh->resource[RES_TPE_RCP].index, + fd->tun_hdr.len - eth_length); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_INNER_L4_OFS, + fh->resource[RES_TPE_RCP].index, + fd->tun_hdr.len - eth_length); + + hw_mod_tpe_hfu_rcp_flush(&dev->ndev->be, + fh->resource[RES_TPE_RCP].index, + 1); + } else { + /* _update TTL */ + if (fd->ttl_sub_enable) { + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_TTL_WR, + fh->resource[RES_TPE_RCP].index, + fd->ttl_sub_enable); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_TTL_POS_DYN, + fh->resource[RES_TPE_RCP].index, + fd->ttl_sub_outer ? DYN_L3 : + DYN_TUN_L3); + if (fd->tun_hdr.len == 0) { + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_TTL_POS_OFS, + fh->resource[RES_TPE_RCP] + .index, + fd->ttl_sub_ipv4 ? 8 : 7); + } else { + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_TTL_POS_OFS, + fh->resource[RES_TPE_RCP] + .index, + (fd->tun_hdr.len - + eth_length) + + (fd->ttl_sub_ipv4 ? + 8 : 7)); + } + } else { + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_TTL_WR, + fh->resource[RES_TPE_RCP].index, + 0); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_TTL_POS_DYN, + fh->resource[RES_TPE_RCP].index, + 0); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_TTL_POS_OFS, + fh->resource[RES_TPE_RCP].index, + 0); + } + + /* _update FPGA DYN offsets */ + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_CS_INF, + fh->resource[RES_TPE_RCP].index, + 0); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_L3_PRT, + fh->resource[RES_TPE_RCP].index, + 0); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_L3_FRAG, + fh->resource[RES_TPE_RCP].index, + 0); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_TUNNEL, + fh->resource[RES_TPE_RCP].index, + 0); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_L4_PRT, + fh->resource[RES_TPE_RCP].index, + 0); + if (fd->tun_hdr.len == 0) { + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_OUTER_L3_OFS, + fh->resource[RES_TPE_RCP].index, + 0); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_OUTER_L4_OFS, + fh->resource[RES_TPE_RCP].index, + 0); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_INNER_L3_OFS, + fh->resource[RES_TPE_RCP].index, + 0); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_INNER_L4_OFS, + fh->resource[RES_TPE_RCP].index, + 0); + } else { + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_OUTER_L3_OFS, + fh->resource[RES_TPE_RCP].index, + fd->tun_hdr.len - eth_length); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_OUTER_L4_OFS, + fh->resource[RES_TPE_RCP].index, + fd->tun_hdr.len - eth_length); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_INNER_L3_OFS, + fh->resource[RES_TPE_RCP].index, + fd->tun_hdr.len - eth_length); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_HFU_RCP_INNER_L4_OFS, + fh->resource[RES_TPE_RCP].index, + fd->tun_hdr.len - eth_length); + } + + hw_mod_tpe_hfu_rcp_flush(&dev->ndev->be, + fh->resource[RES_TPE_RCP].index, + 1); + } + + /* Calculate valid outer and inner checksums */ + hw_mod_tpe_csu_rcp_set(&dev->ndev->be, + HW_TPE_CSU_RCP_OUTER_L3_CMD, + fh->resource[RES_TPE_RCP].index, + 3); + hw_mod_tpe_csu_rcp_set(&dev->ndev->be, + HW_TPE_CSU_RCP_OUTER_L4_CMD, + fh->resource[RES_TPE_RCP].index, + 3); + hw_mod_tpe_csu_rcp_set(&dev->ndev->be, + HW_TPE_CSU_RCP_INNER_L3_CMD, + fh->resource[RES_TPE_RCP].index, + 3); + hw_mod_tpe_csu_rcp_set(&dev->ndev->be, + HW_TPE_CSU_RCP_INNER_L4_CMD, + fh->resource[RES_TPE_RCP].index, + 3); + hw_mod_tpe_csu_rcp_flush(&dev->ndev->be, + fh->resource[RES_TPE_RCP].index, + 1); + } + } + + /* + * Setup CAT Color Table functionality + */ + if (setup_cat_cot) { + hw_mod_cat_cot_set(&dev->ndev->be, HW_CAT_COT_COLOR, + fh->resource[RES_CAT_COT].index, 0); + hw_mod_cat_cot_set(&dev->ndev->be, HW_CAT_COT_KM, + fh->resource[RES_CAT_COT].index, 0x4); + hw_mod_cat_cot_flush(&dev->ndev->be, + fh->resource[RES_CAT_COT].index, 1); + } + + /* + * Setup CAT action functionality + */ + if (setup_cat_cts) { + /* Setup CAT CTS */ + const int offset = ((int)dev->ndev->be.cat.cts_num + 1) / 2; + + hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_A, + offset * fh->resource[RES_CAT_CFN].index + 0, + fh->resource[RES_CAT_COT].index); + hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_B, + offset * fh->resource[RES_CAT_CFN].index + 0, + 0); + hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_A, + offset * fh->resource[RES_CAT_CFN].index + 1, + 0); + hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_B, + offset * fh->resource[RES_CAT_CFN].index + 1, + fh->resource[RES_QSL_RCP].index); + hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_A, + offset * fh->resource[RES_CAT_CFN].index + 2, + 0); + hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_B, + offset * fh->resource[RES_CAT_CFN].index + 2, + 0); + hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_A, + offset * fh->resource[RES_CAT_CFN].index + 3, + 0); + hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_B, + offset * fh->resource[RES_CAT_CFN].index + 3, + 0); + hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_A, + offset * fh->resource[RES_CAT_CFN].index + 4, + fh->resource[RES_HST_RCP].index); + hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_B, + offset * fh->resource[RES_CAT_CFN].index + 4, + 0); + hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_A, + offset * fh->resource[RES_CAT_CFN].index + 5, + fh->resource[RES_TPE_RCP].index); + hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_B, + offset * fh->resource[RES_CAT_CFN].index + 5, + 0); + + hw_mod_cat_cts_flush(&dev->ndev->be, + offset * fh->resource[RES_CAT_CFN].index, + 6); + hw_mod_cat_cts_flush(&dev->ndev->be, + offset * fh->resource[RES_CAT_CFN].index, + 6); + + /* Setup CAT CTE */ + hw_mod_cat_cte_set(&dev->ndev->be, + HW_CAT_CTE_ENABLE_BM, + fh->resource[RES_CAT_CFN].index, + (fh->resource[RES_CAT_COT].index ? 0x001 : 0) | 0x004 | + (fh->resource[RES_QSL_RCP].index ? 0x008 : 0) | + 0x040 | + (fh->resource[RES_HST_RCP].index ? 0x100 : 0) | + (fh->resource[RES_TPE_RCP].index ? 0x400 : 0)); + hw_mod_cat_cte_flush(&dev->ndev->be, + fh->resource[RES_CAT_CFN].index, 1); + } + + /* + * Setup CAT CFN + * + * Once CAT CFN has been programmed traffic will start match the filter, + * so CAT CFN must be the last thing to be programmed. + */ + if (setup_cat_cfn) { + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_SET_ALL_DEFAULTS, + fh->resource[RES_CAT_CFN].index, 0, 0x0); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ENABLE, + fh->resource[RES_CAT_CFN].index, 0, 0x1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_INV, + fh->resource[RES_CAT_CFN].index, 0, 0x0); + + /* Protocol checks */ + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_INV, + fh->resource[RES_CAT_CFN].index, 0, 0x0); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_ISL, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_CFP, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_MAC, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_L2, + fh->resource[RES_CAT_CFN].index, 0, + fd->l2_prot != -1 ? (1 << fd->l2_prot) : -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_VNTAG, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_VLAN, + fh->resource[RES_CAT_CFN].index, 0, + (0xf << fd->vlans) & 0xf); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_MPLS, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_L3, + fh->resource[RES_CAT_CFN].index, 0, + fd->l3_prot != -1 ? (1 << fd->l3_prot) : -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_FRAG, + fh->resource[RES_CAT_CFN].index, 0, + fd->fragmentation); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_IP_PROT, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_L4, + fh->resource[RES_CAT_CFN].index, 0, + fd->l4_prot != -1 ? (1 << fd->l4_prot) : -1); + hw_mod_cat_cfn_set(&dev->ndev->be, + HW_CAT_CFN_PTC_TUNNEL, + fh->resource[RES_CAT_CFN].index, 0, + fd->tunnel_prot != -1 ? (1 << fd->tunnel_prot) : -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_TNL_L2, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_TNL_VLAN, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_TNL_MPLS, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_TNL_L3, + fh->resource[RES_CAT_CFN].index, 0, + fd->tunnel_l3_prot != -1 ? + (1 << fd->tunnel_l3_prot) : -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_TNL_FRAG, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_TNL_IP_PROT, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_TNL_L4, + fh->resource[RES_CAT_CFN].index, 0, + fd->tunnel_l4_prot != -1 ? + (1 << fd->tunnel_l4_prot) : -1); + + /* Error checks */ + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_INV, + fh->resource[RES_CAT_CFN].index, 0, 0x0); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_CV, + fh->resource[RES_CAT_CFN].index, 0, 0x1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_FCS, + fh->resource[RES_CAT_CFN].index, 0, 0x1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_TRUNC, + fh->resource[RES_CAT_CFN].index, 0, 0x1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_L3_CS, + fh->resource[RES_CAT_CFN].index, 0, 0x1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_L4_CS, + fh->resource[RES_CAT_CFN].index, 0, 0x1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_TNL_L3_CS, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_TNL_L4_CS, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, + HW_CAT_CFN_ERR_TTL_EXP, + fh->resource[RES_CAT_CFN].index, 0, + (fd->ttl_sub_enable && fd->ttl_sub_outer) ? -1 : 0x1); + hw_mod_cat_cfn_set(&dev->ndev->be, + HW_CAT_CFN_ERR_TNL_TTL_EXP, + fh->resource[RES_CAT_CFN].index, 0, + (fd->ttl_sub_enable && !fd->ttl_sub_outer) ? -1 : 0x1); + + /* MAC port check */ + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_MAC_PORT, + fh->resource[RES_CAT_CFN].index, 0, + 1 << fh->port_id); + + /* Pattern match checks */ + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PM_CMP, + fh->resource[RES_CAT_CFN].index, 0, 0x0); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PM_DCT, + fh->resource[RES_CAT_CFN].index, 0, 0x0); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PM_EXT_INV, + fh->resource[RES_CAT_CFN].index, 0, 0x0); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PM_CMB, + fh->resource[RES_CAT_CFN].index, 0, 0x0); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PM_AND_INV, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PM_OR_INV, + fh->resource[RES_CAT_CFN].index, 0, -1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PM_INV, + fh->resource[RES_CAT_CFN].index, 0, -1); + + /* Length checks */ + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_LC, + fh->resource[RES_CAT_CFN].index, 0, 0x0); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_LC_INV, + fh->resource[RES_CAT_CFN].index, 0, -1); + + /* KM and FLM */ + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_KM0_OR, + fh->resource[RES_CAT_CFN].index, 0, 0x1); + hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_KM1_OR, + fh->resource[RES_CAT_CFN].index, 0, 0x3); + + hw_mod_cat_cfn_flush(&dev->ndev->be, + fh->resource[RES_CAT_CFN].index, 1); + } + + /* Program FLM flow */ + if (fh_flm) { + convert_fd_to_flm(fh_flm, fd, packet_data, flm_key_id, + flm_rpl_ext_ptr, attr->priority); + flm_flow_programming(dev, fh_flm, fd->mtr_ids, flm_ft, 1); + } + + if (free_fd) + free(fd); + + return (fh_flm) ? fh_flm : fh; +} + +/* + * Public functions + */ + +int initialize_flow_management_of_ndev_profile_inline(struct flow_nic_dev *ndev) +{ + if (!ndev->flow_mgnt_prepared) { + /* Check static arrays are big enough */ + assert(ndev->be.tpe.nb_cpy_writers <= + MAX_CPY_WRITERS_SUPPORTED); + + /* KM Flow Type 0 is reserved */ + flow_nic_mark_resource_used(ndev, RES_KM_FLOW_TYPE, 0); + flow_nic_mark_resource_used(ndev, RES_KM_CATEGORY, 0); + + /* FLM Flow Type 0 and 1 is reserved */ + flow_nic_mark_resource_used(ndev, RES_FLM_FLOW_TYPE, 0); + flow_nic_mark_resource_used(ndev, RES_FLM_FLOW_TYPE, 1); + flow_nic_mark_resource_used(ndev, RES_FLM_RCP, 0); + + /* CAT CFN 0 is reserved as a low priority catch all filter */ + hw_mod_cat_cfn_set(&ndev->be, HW_CAT_CFN_SET_ALL_DEFAULTS, + 0, 0, 0); + hw_mod_cat_cfn_flush(&ndev->be, 0, 1); + flow_nic_mark_resource_used(ndev, RES_CAT_CFN, 0); + + /* Initialize QSL with unmatched recipe index 0 - discard */ + if (hw_mod_qsl_rcp_set(&ndev->be, HW_QSL_RCP_DISCARD, 0, 0x1) < 0) + goto err_exit0; + if (hw_mod_qsl_rcp_flush(&ndev->be, 0, 1) < 0) + goto err_exit0; + + flow_nic_mark_resource_used(ndev, RES_QSL_RCP, 0); + + /* Initialize QST with default index 0 */ + if (hw_mod_qsl_qst_set(&ndev->be, HW_QSL_QST_PRESET_ALL, 0, + 0x0) < 0) + goto err_exit0; + if (hw_mod_qsl_qst_flush(&ndev->be, 0, 1) < 0) + goto err_exit0; + + flow_nic_mark_resource_used(ndev, RES_QSL_QST, 0); + + /* HST & TPE index 0 is reserved */ + flow_nic_mark_resource_used(ndev, RES_HST_RCP, 0); + flow_nic_mark_resource_used(ndev, RES_TPE_RCP, 0); + flow_nic_mark_resource_used(ndev, RES_TPE_EXT, 0); + flow_nic_mark_resource_used(ndev, RES_TPE_RPL, 0); + + /* PDB setup Direct Virtio Scatter-Gather descriptor of 12 bytes for its recipe 0 */ + if (hw_mod_pdb_rcp_set(&ndev->be, HW_PDB_RCP_DESCRIPTOR, 0, 7) < + 0) + goto err_exit0; + if (hw_mod_pdb_rcp_set(&ndev->be, HW_PDB_RCP_DESC_LEN, 0, 6) < + 0) + goto err_exit0; + + if (hw_mod_pdb_rcp_flush(&ndev->be, 0, 1) < 0) + goto err_exit0; + + flow_nic_mark_resource_used(ndev, RES_PDB_RCP, 0); + + /* Set default hasher recipe to 5-tuple */ + flow_nic_set_hasher(ndev, 0, HASH_ALGO_5TUPLE); + hw_mod_hsh_rcp_flush(&ndev->be, 0, 1); + + flow_nic_mark_resource_used(ndev, RES_HSH_RCP, 0); + + /* + * COT - set color to 0 for unmatched - color encoding must not have CAO enabled for + * this entry + */ + hw_mod_cat_cot_set(&ndev->be, HW_CAT_COT_PRESET_ALL, 0, 0); + if (hw_mod_cat_cot_flush(&ndev->be, 0, 1) < 0) + goto err_exit0; + + flow_nic_mark_resource_used(ndev, RES_CAT_COT, 0); + + /* Unblock MAC and MAC statistics on this NIC */ + if (hw_mod_rmc_ctrl_set(&ndev->be, HW_RMC_BLOCK_STATT, 0) < 0) + goto err_exit0; + /* block keep alive - not needed */ + if (hw_mod_rmc_ctrl_set(&ndev->be, HW_RMC_BLOCK_KEEPA, 1) < 0) + goto err_exit0; + /* + * Unblock all MAC ports + */ + if (hw_mod_rmc_ctrl_set(&ndev->be, HW_RMC_BLOCK_MAC_PORT, 0) < 0) + goto err_exit0; + + /* + * unblock RPP slices + */ + hw_mod_rmc_ctrl_set(&ndev->be, HW_RMC_BLOCK_RPP_SLICE, 0); + + if (hw_mod_rmc_ctrl_flush(&ndev->be) < 0) + goto err_exit0; + + /* FLM */ + if (flm_sdram_calibrate(ndev) < 0) + goto err_exit0; + if (flm_sdram_reset(ndev, 1) < 0) + goto err_exit0; + flm_flow_handle_create(&ndev->flm_res_handle); + + hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_LDS, + 0); /* Learn done status */ + hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_LFS, + 0); /* Learn fail status */ + hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_LIS, + 0); /* Learn ignore status */ + hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_UDS, + 0); /* Unlearn done status */ + hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_UIS, + 0); /* Unlearn ignore status */ + hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_RDS, + 0); /* Relearn done status */ + hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_RIS, + 0); /* Relearn ignore status */ + hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_RBL, 4); + hw_mod_flm_control_flush(&ndev->be); + + hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_LIMIT0, + 0); /* Drop at 100% FIFO fill level */ + hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_FT0, 1); + hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_LIMIT1, + 6); /* Drop at 37,5% FIFO fill level */ + hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_FT1, 1); + hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_LIMIT2, + 4); /* Drop at 25% FIFO fill level */ + hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_FT2, 1); + hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_LIMIT3, + 2); /* Drop at 12,5% FIFO fill level */ + hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_FT3, 1); + hw_mod_flm_prio_flush(&ndev->be); + + for (uint32_t i = 0; i < ndev->be.flm.nb_pst_profiles; ++i) { + hw_mod_flm_pst_set(&ndev->be, HW_FLM_PST_BP, i, + FLM_PERIODIC_STATS_BYTE_LIMIT); + hw_mod_flm_pst_set(&ndev->be, HW_FLM_PST_PP, i, + FLM_PERIODIC_STATS_PKT_LIMIT); + hw_mod_flm_pst_set(&ndev->be, HW_FLM_PST_TP, i, + FLM_PERIODIC_STATS_BYTE_TIMEOUT); + } + hw_mod_flm_pst_flush(&ndev->be, 0, ALL_ENTRIES); + + hw_mod_flm_stat_update(&ndev->be); + + ndev->flm_mtr_handle = + calloc(1, sizeof(struct flm_flow_mtr_handle_s)); + ndev->ft_res_handle = + calloc(FLM_FLOW_FT_MAX, sizeof(struct flm_flow_ft_ident_s)); + ndev->mtr_stat_handle = + calloc(FLM_MTR_STAT_SIZE, sizeof(struct mtr_stat_s)); + + if (ndev->flm_mtr_handle == NULL || + ndev->ft_res_handle == NULL || + ndev->mtr_stat_handle == NULL) + goto err_exit0; + + struct mtr_stat_s *mtr_stat = ndev->mtr_stat_handle; + + for (uint32_t i = 0; i < FLM_MTR_STAT_SIZE; ++i) { + atomic_init(&mtr_stat[i].n_pkt, 0); + atomic_init(&mtr_stat[i].n_bytes, 0); + atomic_init(&mtr_stat[i].stats_mask, 0); + } + + if (flow_group_handle_create(&ndev->group_handle, + FLM_FLOW_RCP_MAX)) + goto err_exit0; + + ndev->flow_mgnt_prepared = 1; + } + return 0; + +err_exit0: + done_flow_management_of_ndev_profile_inline(ndev); + return -1; +} + +int done_flow_management_of_ndev_profile_inline(struct flow_nic_dev *ndev) +{ +#ifdef FLOW_DEBUG + ndev->be.iface->set_debug_mode(ndev->be.be_dev, + FLOW_BACKEND_DEBUG_MODE_WRITE); +#endif + + if (ndev->flow_mgnt_prepared) { + flm_sdram_reset(ndev, 0); + flm_flow_handle_remove(&ndev->flm_res_handle); + + flow_nic_free_resource(ndev, RES_KM_FLOW_TYPE, 0); + flow_nic_free_resource(ndev, RES_KM_CATEGORY, 0); + + hw_mod_flm_rcp_set(&ndev->be, HW_FLM_RCP_PRESET_ALL, 0, 0); + hw_mod_flm_rcp_flush(&ndev->be, 0, 1); + flow_nic_free_resource(ndev, RES_FLM_FLOW_TYPE, 0); + flow_nic_free_resource(ndev, RES_FLM_FLOW_TYPE, 1); + flow_nic_free_resource(ndev, RES_FLM_RCP, 0); + + free(ndev->flm_mtr_handle); + free(ndev->ft_res_handle); + free(ndev->mtr_stat_handle); + flow_group_handle_destroy(&ndev->group_handle); + + hw_mod_cat_cfn_set(&ndev->be, HW_CAT_CFN_PRESET_ALL, 0, 0, 0); + hw_mod_cat_cfn_flush(&ndev->be, 0, 1); + flow_nic_free_resource(ndev, RES_CAT_CFN, 0); + + hw_mod_qsl_rcp_set(&ndev->be, HW_QSL_RCP_PRESET_ALL, 0, 0); + hw_mod_qsl_rcp_flush(&ndev->be, 0, 1); + flow_nic_free_resource(ndev, RES_QSL_RCP, 0); + + hw_mod_hst_rcp_set(&ndev->be, HW_HST_RCP_PRESET_ALL, 0, 0); + hw_mod_hst_rcp_flush(&ndev->be, 0, 1); + flow_nic_free_resource(ndev, RES_HST_RCP, 0); + + hw_mod_tpe_reset(&ndev->be); + flow_nic_free_resource(ndev, RES_TPE_RCP, 0); + flow_nic_free_resource(ndev, RES_TPE_EXT, 0); + flow_nic_free_resource(ndev, RES_TPE_RPL, 0); + + hw_mod_pdb_rcp_set(&ndev->be, HW_PDB_RCP_PRESET_ALL, 0, 0); + hw_mod_pdb_rcp_flush(&ndev->be, 0, 1); + flow_nic_free_resource(ndev, RES_PDB_RCP, 0); + + hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_PRESET_ALL, 0, 0, 0); + hw_mod_hsh_rcp_flush(&ndev->be, 0, 1); + flow_nic_free_resource(ndev, RES_HSH_RCP, 0); + + hw_mod_cat_cot_set(&ndev->be, HW_CAT_COT_PRESET_ALL, 0, 0); + hw_mod_cat_cot_flush(&ndev->be, 0, 1); + flow_nic_free_resource(ndev, RES_CAT_COT, 0); + +#ifdef FLOW_DEBUG + ndev->be.iface->set_debug_mode(ndev->be.be_dev, + FLOW_BACKEND_DEBUG_MODE_NONE); +#endif + + ndev->flow_mgnt_prepared = 0; + } + + return 0; +} + +int flow_validate_profile_inline(struct flow_eth_dev *dev, + const struct flow_elem elem[], + const struct flow_action action[], + struct flow_error *error) +{ + uint32_t port_id = 0; + uint32_t num_dest_port = 0; + uint32_t num_queues = 0; + + uint32_t packet_data[10]; + uint32_t packet_mask[10]; + struct flm_flow_key_def_s key_def; + + flow_nic_set_error(ERR_SUCCESS, error); + + pthread_mutex_lock(&dev->ndev->mtx); + struct nic_flow_def *fd = interpret_flow_elements(dev, elem, action, + error, 0, &port_id, + &num_dest_port, &num_queues, + packet_data, packet_mask, + &key_def); + pthread_mutex_unlock(&dev->ndev->mtx); + + if (!fd) + return -1; + + free(fd); + return 0; +} + +struct flow_handle *flow_create_profile_inline(struct flow_eth_dev *dev, + const struct flow_attr *attr, const struct flow_elem elem[], + const struct flow_action action[], struct flow_error *error) +{ + struct flow_handle *fh = NULL; + + uint32_t port_id = UINT32_MAX; + uint32_t num_dest_port; + uint32_t num_queues; + + uint32_t packet_data[10]; + uint32_t packet_mask[10]; + struct flm_flow_key_def_s key_def; + + struct flow_attr attr_local; + + memcpy(&attr_local, attr, sizeof(struct flow_attr)); + if (attr_local.group > 0) + attr_local.forced_vlan_vid = 0; + + flow_nic_set_error(ERR_SUCCESS, error); + + pthread_mutex_lock(&dev->ndev->mtx); + + struct nic_flow_def *fd = interpret_flow_elements(dev, elem, action, error, + attr_local.forced_vlan_vid, + &port_id, &num_dest_port, + &num_queues, packet_data, + packet_mask, &key_def); + if (!fd) + goto err_exit; + + /* Translate group IDs */ + if (fd->jump_to_group != UINT32_MAX && + flow_group_translate_get(dev->ndev->group_handle, + attr_local.caller_id, fd->jump_to_group, + &fd->jump_to_group)) { + NT_LOG(ERR, FILTER, "ERROR: Could not get group resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error); + goto err_exit; + } + if (attr_local.group > 0 && + flow_group_translate_get(dev->ndev->group_handle, + attr_local.caller_id, attr_local.group, + &attr_local.group)) { + NT_LOG(ERR, FILTER, "ERROR: Could not get group resource\n"); + flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error); + goto err_exit; + } + + if (port_id == UINT32_MAX) + port_id = dev->port_id; + + /* Create and flush filter to NIC */ + fh = create_flow_filter(dev, fd, &attr_local, error, port_id, + num_dest_port, num_queues, packet_data, + packet_mask, &key_def); + if (!fh) + goto err_exit; + + NT_LOG(DBG, FILTER, + "New FlOW: fh (flow handle) %p, fd (flow definition) %p\n", fh, + fd); + NT_LOG(DBG, FILTER, + ">>>>> [Dev %p] Nic %i, Port %i: fh %p fd %p - implementation <<<<<\n", + dev, dev->ndev->adapter_no, dev->port, fh, fd); + + pthread_mutex_unlock(&dev->ndev->mtx); + + return fh; + +err_exit: + if (fh) + flow_destroy_locked_profile_inline(dev, fh, NULL); + + pthread_mutex_unlock(&dev->ndev->mtx); + + NT_LOG(ERR, FILTER, "ERR: %s\n", __func__); + return NULL; +} + +int flow_destroy_locked_profile_inline(struct flow_eth_dev *dev, + struct flow_handle *fh, + struct flow_error *error) +{ + assert(dev); + assert(fh); + + int err = 0; + + flow_nic_set_error(ERR_SUCCESS, error); + + /* take flow out of ndev list - may not have been put there yet */ + if (fh->type == FLOW_HANDLE_TYPE_FLM) + nic_remove_flow_flm(dev->ndev, fh); + + else + nic_remove_flow(dev->ndev, fh); + +#ifdef FLOW_DEBUG + dev->ndev->be.iface->set_debug_mode(dev->ndev->be.be_dev, + FLOW_BACKEND_DEBUG_MODE_WRITE); +#endif + + if (fh->type == FLOW_HANDLE_TYPE_FLM) { + err |= flm_flow_programming(dev, fh, NULL, 0, 0); + + if (fh->flm_rpl_ext_ptr > 0 && + flow_nic_deref_resource(dev->ndev, RES_TPE_EXT, + (int)fh->flm_rpl_ext_ptr) == 0) { + uint32_t ptr = 0; + uint32_t len = 0; + + hw_mod_tpe_rpl_ext_get(&dev->ndev->be, + HW_TPE_RPL_EXT_RPL_PTR, + (int)fh->flm_rpl_ext_ptr, &ptr); + hw_mod_tpe_rpl_ext_get(&dev->ndev->be, + HW_TPE_RPL_EXT_META_RPL_LEN, + (int)fh->flm_rpl_ext_ptr, &len); + + hw_mod_tpe_rpl_ext_set(&dev->ndev->be, + HW_TPE_PRESET_ALL, + (int)fh->flm_rpl_ext_ptr, 0); + hw_mod_tpe_rpl_ext_flush(&dev->ndev->be, + (int)fh->flm_rpl_ext_ptr, 1); + + for (uint32_t ii = 0; ii < (len + 15) / 16; ii++) { + if (flow_nic_deref_resource(dev->ndev, + RES_TPE_RPL, + (int)(ptr + ii)) == 0) { + uint32_t rpl_zero[] = { 0, 0, 0, 0 }; + + hw_mod_tpe_rpl_rpl_set(&dev->ndev->be, + HW_TPE_PRESET_ALL, + (int)(ptr + ii), + rpl_zero); + hw_mod_tpe_rpl_rpl_flush(&dev->ndev->be, + (int)(ptr + ii), + 1); + } + } + } + + flow_group_translate_release(dev->ndev->group_handle, + fh->flm_owner->flm_group_index); + + fh->flm_owner->flm_ref_count -= 1; + if (fh->flm_owner->flm_ref_count == 0) { + err |= flow_flm_destroy_owner(dev, fh->flm_owner); + err |= flow_destroy_locked_profile_inline(dev, + fh->flm_owner, + error); + } + } else { + NT_LOG(DBG, FILTER, "removing flow :%p\n", fh); + + if (fh->fd) { + if (fh->fd->km.num_ftype_elem) + km_clear_data_match_entry(&fh->fd->km); + + if (fh->fd->jump_to_group != UINT32_MAX) { + err |= flm_flow_destroy_group(dev, + fh->fd->jump_to_group); + flow_group_translate_release(dev->ndev->group_handle, + fh->fd->jump_to_group); + } + } + + for (int res_type = 0; res_type < RES_COUNT; res_type++) { + if (fh->resource[res_type].count < 1) + continue; + + for (int ii = 0; ii < fh->resource[res_type].count; + ii++) { + /* If last ref count of this resource, free it */ + if (flow_nic_deref_resource(dev->ndev, + res_type, + fh->resource[res_type].index + + ii) == 0) { + /* Free resource up in NIC */ + switch (res_type) { + case RES_CAT_CFN: + assert(ii == 0); + err |= reset_cat_function_setup(dev, + fh->resource[RES_CAT_CFN] + .index + ii); + break; + + case RES_QSL_QST: + hw_mod_qsl_qst_set(&dev->ndev->be, + HW_QSL_QST_PRESET_ALL, + fh->resource[RES_QSL_QST] + .index + ii, + 0); + hw_mod_qsl_qst_flush(&dev->ndev->be, + fh->resource[RES_QSL_QST] + .index + ii, + 1); + break; + + case RES_QSL_RCP: + hw_mod_qsl_rcp_set(&dev->ndev->be, + HW_QSL_RCP_PRESET_ALL, + fh->resource[RES_QSL_RCP] + .index + ii, + 0); + hw_mod_qsl_rcp_flush(&dev->ndev->be, + fh->resource[RES_QSL_RCP] + .index + ii, + 1); + break; + + case RES_CAT_COT: + hw_mod_cat_cot_set(&dev->ndev->be, + HW_CAT_COT_PRESET_ALL, + fh->resource[res_type] + .index + ii, + 0); + hw_mod_cat_cot_flush(&dev->ndev->be, + fh->resource[res_type] + .index + ii, + 1); + break; + + case RES_KM_CATEGORY: + assert(ii == 0); + hw_mod_km_rcp_set(&dev->ndev->be, + HW_KM_RCP_PRESET_ALL, + fh->resource[res_type] + .index + ii, + 0, 0); + hw_mod_km_rcp_flush(&dev->ndev->be, + fh->resource[res_type] + .index + ii, + 1); + break; + + case RES_KM_FLOW_TYPE: { + struct flm_flow_ft_ident_s *ft_idents = + (struct flm_flow_ft_ident_s + *)dev->ndev + ->ft_res_handle; + ft_idents[fh->resource[res_type] + .index + + ii] + .data = 0; + } + break; + + case RES_FLM_RCP: + assert(ii == 0); + err |= flm_flow_destroy_rcp(dev, + fh->resource[res_type] + .index + ii); + break; + + case RES_FLM_FLOW_TYPE: + /* Nothing needed */ + break; + + case RES_HSH_RCP: + hw_mod_hsh_rcp_set(&dev->ndev->be, + HW_HSH_RCP_PRESET_ALL, + fh->resource[res_type] + .index + ii, + 0, 0); + hw_mod_hsh_rcp_flush(&dev->ndev->be, + fh->resource[res_type] + .index + + ii, + 1); + break; + + case RES_PDB_RCP: + hw_mod_pdb_rcp_set(&dev->ndev->be, + HW_PDB_RCP_PRESET_ALL, + fh->resource[res_type] + .index + ii, + 0); + hw_mod_pdb_rcp_flush(&dev->ndev->be, + fh->resource[res_type] + .index + ii, + 1); + break; + + case RES_HST_RCP: + hw_mod_hst_rcp_set(&dev->ndev->be, + HW_HST_RCP_PRESET_ALL, + fh->resource[res_type] + .index + ii, + 0); + hw_mod_hst_rcp_flush(&dev->ndev->be, + fh->resource[res_type] + .index + ii, + 1); + break; + + case RES_TPE_RCP: + hw_mod_tpe_rpp_rcp_set(&dev->ndev->be, + HW_TPE_PRESET_ALL, + fh->resource[res_type] + .index + ii, + 0); + hw_mod_tpe_rpp_rcp_flush(&dev->ndev->be, + fh->resource[res_type] + .index + ii, + 1); + hw_mod_tpe_ins_rcp_set(&dev->ndev->be, + HW_TPE_PRESET_ALL, + fh->resource[res_type] + .index + ii, + 0); + hw_mod_tpe_ins_rcp_flush(&dev->ndev->be, + fh->resource[res_type] + .index + ii, + 1); + hw_mod_tpe_rpl_rcp_set(&dev->ndev->be, + HW_TPE_PRESET_ALL, + fh->resource[res_type] + .index + ii, + 0); + hw_mod_tpe_rpl_rcp_flush(&dev->ndev->be, + fh->resource[res_type] + .index + ii, + 1); + hw_mod_tpe_rpl_ext_set(&dev->ndev->be, + HW_TPE_PRESET_ALL, + fh->resource[res_type] + .index + ii, + 0); + hw_mod_tpe_rpl_ext_flush(&dev->ndev->be, + fh->resource[res_type] + .index + ii, + 1); + hw_mod_tpe_cpy_rcp_set(&dev->ndev->be, + HW_TPE_PRESET_ALL, + fh->resource[res_type] + .index + ii, + 0); + hw_mod_tpe_cpy_rcp_flush(&dev->ndev->be, + fh->resource[res_type] + .index + ii, + 1); + hw_mod_tpe_hfu_rcp_set(&dev->ndev->be, + HW_TPE_PRESET_ALL, + fh->resource[res_type] + .index + ii, + 0); + hw_mod_tpe_hfu_rcp_flush(&dev->ndev->be, + fh->resource[res_type] + .index + ii, + 1); + hw_mod_tpe_csu_rcp_set(&dev->ndev->be, + HW_TPE_PRESET_ALL, + fh->resource[res_type] + .index + ii, + 0); + hw_mod_tpe_csu_rcp_flush(&dev->ndev->be, + fh->resource[res_type] + .index + ii, + 1); + break; + + case RES_TPE_EXT: + /* Nothing needed */ + break; + + case RES_TPE_RPL: + /* Nothing needed */ + break; + + default: + err |= -1; + break; + } + } + } + } + free(fh->fd); + } + + if (err) { + NT_LOG(ERR, FILTER, "FAILED removing flow: %p\n", fh); + flow_nic_set_error(ERR_REMOVE_FLOW_FAILED, error); + } + + free(fh); + +#ifdef FLOW_DEBUG + dev->ndev->be.iface->set_debug_mode(dev->ndev->be.be_dev, + FLOW_BACKEND_DEBUG_MODE_NONE); +#endif + + return err; +} + +int flow_destroy_profile_inline(struct flow_eth_dev *dev, + struct flow_handle *flow, + struct flow_error *error) +{ + int err = 0; + + flow_nic_set_error(ERR_SUCCESS, error); + + pthread_mutex_lock(&dev->ndev->mtx); + if (flow) { + /* Delete this flow */ + err = flow_destroy_locked_profile_inline(dev, flow, error); + } else { + /* Delete all created flows from this eth device */ + flow = dev->ndev->flow_base; + + while (flow && !err) { + if (flow->dev == dev) { + struct flow_handle *flow_next = flow->next; + + err = flow_destroy_locked_profile_inline(dev, + flow, + NULL); + flow = flow_next; + } else { + flow = flow->next; + } + } + + /* Delete all created FLM flows from this eth device */ + flow = dev->ndev->flow_base_flm; + + while (flow && !err) { + if (flow->dev == dev) { + struct flow_handle *flow_next = flow->next; + + err = flow_destroy_locked_profile_inline(dev, + flow, + NULL); + flow = flow_next; + } else { + flow = flow->next; + } + } + } + + pthread_mutex_unlock(&dev->ndev->mtx); + + return err; +} + +int flow_flush_profile_inline(UNUSED struct flow_eth_dev *dev, + struct flow_error *error) +{ + NT_LOG(ERR, FILTER, "ERROR: Not implemented yet\n"); + error->type = FLOW_ERROR_GENERAL; + error->message = "rte_flow_flush is not supported"; + return -1; +} + +int flow_query_profile_inline(UNUSED struct flow_eth_dev *dev, + UNUSED struct flow_handle *flow, + UNUSED const struct flow_action *action, + void **data, uint32_t *length, + struct flow_error *error) +{ + NT_LOG(ERR, FILTER, "ERROR: Not implemented yet\n"); + + *length = 0; + *data = NULL; + error->type = FLOW_ERROR_GENERAL; + error->message = "rte_flow_query is not supported"; + return -1; +} + +int flow_get_flm_stats_profile_inline(struct flow_nic_dev *ndev, uint64_t *data, + uint64_t size) +{ + const enum hw_flm_e fields[] = { + HW_FLM_STAT_FLOWS, HW_FLM_STAT_LRN_DONE, + HW_FLM_STAT_LRN_IGNORE, HW_FLM_STAT_LRN_FAIL, + HW_FLM_STAT_UNL_DONE, HW_FLM_STAT_UNL_IGNORE, + HW_FLM_STAT_AUL_DONE, HW_FLM_STAT_AUL_IGNORE, + HW_FLM_STAT_AUL_FAIL, HW_FLM_STAT_TUL_DONE, + HW_FLM_STAT_REL_DONE, HW_FLM_STAT_REL_IGNORE, + HW_FLM_STAT_PRB_DONE, HW_FLM_STAT_PRB_IGNORE, + + HW_FLM_STAT_STA_DONE, HW_FLM_STAT_INF_DONE, + HW_FLM_STAT_INF_SKIP, HW_FLM_STAT_PCK_HIT, + HW_FLM_STAT_PCK_MISS, HW_FLM_STAT_PCK_UNH, + HW_FLM_STAT_PCK_DIS, HW_FLM_STAT_CSH_HIT, + HW_FLM_STAT_CSH_MISS, HW_FLM_STAT_CSH_UNH, + HW_FLM_STAT_CUC_START, HW_FLM_STAT_CUC_MOVE, + }; + + const uint64_t fields_cnt = sizeof(fields) / sizeof(enum hw_flm_e); + + if (size < fields_cnt) + return -1; + + hw_mod_flm_stat_update(&ndev->be); + + for (uint64_t i = 0; i < fields_cnt; ++i) { + uint32_t value = 0; + + hw_mod_flm_stat_get(&ndev->be, fields[i], &value); + data[i] = (fields[i] == HW_FLM_STAT_FLOWS) ? value : + data[i] + value; + if (ndev->be.flm.ver < 18 && + fields[i] == HW_FLM_STAT_PRB_IGNORE) + break; + } + + return 0; +} + +int flow_set_mtu_inline(struct flow_eth_dev *dev, uint32_t port, uint16_t mtu) +{ + if (port >= 255) + return -1; + + int err = 0; + uint8_t ifr_mtu_recipe = convert_port_to_ifr_mtu_recipe(port); + struct flow_nic_dev *ndev = dev->ndev; + + err |= hw_mod_tpe_rpp_ifr_rcp_set(&ndev->be, HW_TPE_IFR_RCP_EN, + ifr_mtu_recipe, 1); + err |= hw_mod_tpe_rpp_ifr_rcp_set(&ndev->be, HW_TPE_IFR_RCP_MTU, + ifr_mtu_recipe, mtu); + err |= hw_mod_tpe_ifr_rcp_set(&ndev->be, HW_TPE_IFR_RCP_EN, + ifr_mtu_recipe, 1); + err |= hw_mod_tpe_ifr_rcp_set(&ndev->be, HW_TPE_IFR_RCP_MTU, + ifr_mtu_recipe, mtu); + + if (err == 0) { + err |= hw_mod_tpe_rpp_ifr_rcp_flush(&ndev->be, ifr_mtu_recipe, + 1); + err |= hw_mod_tpe_ifr_rcp_flush(&ndev->be, ifr_mtu_recipe, 1); + } + + return err; +} diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.h b/drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.h new file mode 100644 index 0000000000..330cc39db6 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _FLOW_API_PROFILE_INLINE_H_ +#define _FLOW_API_PROFILE_INLINE_H_ + +#include "stream_binary_flow_api.h" +#include "flow_api.h" + +/* + * Management + */ + +int done_flow_management_of_ndev_profile_inline(struct flow_nic_dev *ndev); + +int initialize_flow_management_of_ndev_profile_inline(struct flow_nic_dev *ndev); + +/* + * Flow functionality + */ + +int flow_destroy_locked_profile_inline(struct flow_eth_dev *dev, + struct flow_handle *flow, + struct flow_error *error); + +int flow_validate_profile_inline(struct flow_eth_dev *dev, + const struct flow_elem elem[], + const struct flow_action action[], + struct flow_error *error); + +struct flow_handle *flow_create_profile_inline(struct flow_eth_dev *dev, + const struct flow_attr *attr, + const struct flow_elem elem[], const struct flow_action action[], + struct flow_error *error); + +int flow_destroy_profile_inline(struct flow_eth_dev *dev, + struct flow_handle *flow, + struct flow_error *error); + +int flow_flush_profile_inline(struct flow_eth_dev *dev, + struct flow_error *error); + +int flow_query_profile_inline(struct flow_eth_dev *dev, + struct flow_handle *flow, + const struct flow_action *action, void **data, + uint32_t *length, struct flow_error *error); + +/* + * Stats + */ + +int flow_get_flm_stats_profile_inline(struct flow_nic_dev *ndev, uint64_t *data, + uint64_t size); + +#endif /* _FLOW_API_PROFILE_INLINE_H_ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_backend.c b/drivers/net/ntnic/nthw/flow_filter/flow_backend.c new file mode 100644 index 0000000000..1214b32666 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_backend.c @@ -0,0 +1,3205 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nthw_drv.h" + +#include "flow_nthw_info.h" +#include "flow_nthw_ifr.h" +#include "flow_nthw_cat.h" +#include "flow_nthw_csu.h" +#include "flow_nthw_km.h" +#include "flow_nthw_flm.h" +#include "flow_nthw_hfu.h" +#include "flow_nthw_hsh.h" +#include "flow_nthw_hst.h" +#include "flow_nthw_qsl.h" +#include "flow_nthw_slc.h" +#include "flow_nthw_slc_lr.h" +#include "flow_nthw_pdb.h" +#include "flow_nthw_ioa.h" +#include "flow_nthw_rpp_lr.h" +#include "flow_nthw_roa.h" +#include "flow_nthw_rmc.h" +#include "flow_nthw_tx_cpy.h" +#include "flow_nthw_tx_ins.h" +#include "flow_nthw_tx_rpl.h" +#include "flow_backend.h" +#include "flow_api_backend.h" + +#include /* printf */ + +#if !defined(MAX_PHYS_ADAPTERS) +#define MAX_PHYS_ADAPTERS (8) +#endif + +/* + * Binary Flow API backend implementation into ntservice driver + * + * General note on this backend implementation: + * Maybe use shadow class to combine multiple writes. However, this backend is only for dev/testing + */ + +static struct backend_dev_s { + uint8_t adapter_no; + enum debug_mode_e dmode; + struct info_nthw *p_info_nthw; + struct cat_nthw *p_cat_nthw; + struct km_nthw *p_km_nthw; + struct flm_nthw *p_flm_nthw; + struct hsh_nthw *p_hsh_nthw; + struct hst_nthw *p_hst_nthw; + struct qsl_nthw *p_qsl_nthw; + struct slc_nthw *p_slc_nthw; + struct slc_lr_nthw *p_slc_lr_nthw; + struct pdb_nthw *p_pdb_nthw; + struct ioa_nthw *p_ioa_nthw; + struct roa_nthw *p_roa_nthw; + struct rmc_nthw *p_rmc_nthw; + struct hfu_nthw *p_hfu_nthw; /* TPE module */ + struct rpp_lr_nthw *p_rpp_lr_nthw; /* TPE module */ + struct tx_cpy_nthw *p_tx_cpy_nthw; /* TPE module */ + struct tx_ins_nthw *p_tx_ins_nthw; /* TPE module */ + struct tx_rpl_nthw *p_tx_rpl_nthw; /* TPE module */ + struct csu_nthw *p_csu_nthw; /* TPE module */ + struct ifr_nthw *p_ifr_nthw; /* TPE module */ +} be_devs[MAX_PHYS_ADAPTERS]; + +#define _CHECK_DEBUG_ON(be, mod, inst) \ + int __debug__ = 0; \ + if (((be)->dmode & FLOW_BACKEND_DEBUG_MODE_WRITE) || (mod)->debug) \ + do { \ + mod##_nthw_set_debug_mode(inst, 0xFF); \ + __debug__ = 1; \ + } while (0) + +#define _CHECK_DEBUG_OFF(mod, inst) \ + do { \ + if (__debug__) \ + mod##_nthw_set_debug_mode(inst, 0); \ + } while (0) + +static int set_debug_mode(void *be_dev, enum debug_mode_e mode) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + be->dmode = mode; + return 0; +} + +/* + * ***************** INFO ******************* + */ + +static int get_nb_phy_ports(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_phy_ports(be->p_info_nthw); +} + +static int get_nb_rx_ports(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_rx_ports(be->p_info_nthw); +} + +static int get_ltx_avail(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_ltx_avail(be->p_info_nthw); +} + +static int get_nb_cat_funcs(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_cat_funcs(be->p_info_nthw); +} + +static int get_nb_categories(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_categories(be->p_info_nthw); +} + +static int get_nb_cat_km_if_cnt(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_cat_km_if_cnt(be->p_info_nthw); +} + +static int get_nb_cat_km_if_m0(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_cat_km_if_m0(be->p_info_nthw); +} + +static int get_nb_cat_km_if_m1(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_cat_km_if_m1(be->p_info_nthw); +} + +static int get_nb_queues(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_queues(be->p_info_nthw); +} + +static int get_nb_km_flow_types(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_km_flow_types(be->p_info_nthw); +} + +static int get_nb_pm_ext(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_pm_ext(be->p_info_nthw); +} + +static int get_nb_len(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_len(be->p_info_nthw); +} + +static int get_kcc_size(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_kcc_size(be->p_info_nthw); +} + +static int get_kcc_banks(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_kcc_banks(be->p_info_nthw); +} + +static int get_nb_km_categories(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_km_categories(be->p_info_nthw); +} + +static int get_nb_km_cam_banks(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_km_cam_banks(be->p_info_nthw); +} + +static int get_nb_km_cam_record_words(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_km_cam_record_words(be->p_info_nthw); +} + +static int get_nb_km_cam_records(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_km_cam_records(be->p_info_nthw); +} + +static int get_nb_km_tcam_banks(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_km_tcam_banks(be->p_info_nthw); +} + +static int get_nb_km_tcam_bank_width(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_km_tcam_bank_width(be->p_info_nthw); +} + +static int get_nb_flm_categories(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_flm_categories(be->p_info_nthw); +} + +static int get_nb_flm_size_mb(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_flm_size_mb(be->p_info_nthw); +} + +static int get_nb_flm_entry_size(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_flm_entry_size(be->p_info_nthw); +} + +static int get_nb_flm_variant(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_flm_variant(be->p_info_nthw); +} + +static int get_nb_flm_prios(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_flm_prios(be->p_info_nthw); +} + +static int get_nb_flm_pst_profiles(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_flm_pst_profiles(be->p_info_nthw); +} + +static int get_nb_hst_categories(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_hst_categories(be->p_info_nthw); +} + +static int get_nb_qsl_categories(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_qsl_categories(be->p_info_nthw); +} + +static int get_nb_qsl_qst_entries(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_qsl_qst_entries(be->p_info_nthw); +} + +static int get_nb_pdb_categories(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_pdb_categories(be->p_info_nthw); +} + +static int get_nb_ioa_categories(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_ioa_categories(be->p_info_nthw); +} + +static int get_nb_roa_categories(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_roa_categories(be->p_info_nthw); +} + +static int get_nb_tpe_categories(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_tpe_categories(be->p_info_nthw); +} + +static int get_nb_tx_cpy_writers(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_tx_cpy_writers(be->p_info_nthw); +} + +static int get_nb_tx_cpy_mask_mem(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_tx_cpy_mask_mem(be->p_info_nthw); +} + +static int get_nb_tx_rpl_depth(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_tx_rpl_depth(be->p_info_nthw); +} + +static int get_nb_tx_rpl_ext_categories(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_tx_rpl_ext_categories(be->p_info_nthw); +} + +static int get_nb_tpe_ifr_categories(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return info_nthw_get_nb_tpe_ifr_categories(be->p_info_nthw); +} + +/* + * ***************** CAT ******************* + */ + +static bool cat_get_present(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return be->p_cat_nthw != NULL; +} + +static uint32_t cat_get_version(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return (uint32_t)((module_get_major_version(be->p_cat_nthw->m_cat) << 16) | + (module_get_minor_version(be->p_cat_nthw->m_cat) & + 0xffff)); +} + +static int cat_cfn_flush(void *be_dev, const struct cat_func_s *cat, + int cat_func, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw); + + if (cat->ver == 18) { + r(be->p_cat_nthw, 1U); + for (int i = 0; i < cnt; i++) { + cat_nthw_cfn_select(be->p_cat_nthw, cat_func); + cat_nthw_cfn_enable(be->p_cat_nthw, + cat->v18.cfn[cat_func].enable); + cat_nthw_cfn_inv(be->p_cat_nthw, + cat->v18.cfn[cat_func].inv); + cat_nthw_cfn_ptc_inv(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_inv); + cat_nthw_cfn_ptc_isl(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_isl); + cat_nthw_cfn_ptc_cfp(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_cfp); + cat_nthw_cfn_ptc_mac(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_mac); + cat_nthw_cfn_ptc_l2(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_l2); + cat_nthw_cfn_ptc_vn_tag(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_vntag); + cat_nthw_cfn_ptc_vlan(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_vlan); + cat_nthw_cfn_ptc_mpls(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_mpls); + cat_nthw_cfn_ptc_l3(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_l3); + cat_nthw_cfn_ptc_frag(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_frag); + cat_nthw_cfn_ptc_ip_prot(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_ip_prot); + cat_nthw_cfn_ptc_l4(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_l4); + cat_nthw_cfn_ptc_tunnel(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_tunnel); + cat_nthw_cfn_ptc_tnl_l2(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_tnl_l2); + cat_nthw_cfn_ptc_tnl_vlan(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_tnl_vlan); + cat_nthw_cfn_ptc_tnl_mpls(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_tnl_mpls); + cat_nthw_cfn_ptc_tnl_l3(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_tnl_l3); + cat_nthw_cfn_ptc_tnl_frag(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_tnl_frag); + cat_nthw_cfn_ptc_tnl_ip_prot(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_tnl_ip_prot); + cat_nthw_cfn_ptc_tnl_l4(be->p_cat_nthw, + cat->v18.cfn[cat_func].ptc_tnl_l4); + + cat_nthw_cfn_err_inv(be->p_cat_nthw, + cat->v18.cfn[cat_func].err_inv); + cat_nthw_cfn_err_cv(be->p_cat_nthw, + cat->v18.cfn[cat_func].err_cv); + cat_nthw_cfn_err_fcs(be->p_cat_nthw, + cat->v18.cfn[cat_func].err_fcs); + cat_nthw_cfn_err_trunc(be->p_cat_nthw, + cat->v18.cfn[cat_func].err_trunc); + cat_nthw_cfn_err_l3_cs(be->p_cat_nthw, + cat->v18.cfn[cat_func].err_l3_cs); + cat_nthw_cfn_err_l4_cs(be->p_cat_nthw, + cat->v18.cfn[cat_func].err_l4_cs); + + cat_nthw_cfn_mac_port(be->p_cat_nthw, + cat->v18.cfn[cat_func].mac_port); + + cat_nthw_cfn_pm_cmp(be->p_cat_nthw, + cat->v18.cfn[cat_func].pm_cmp); + cat_nthw_cfn_pm_dct(be->p_cat_nthw, + cat->v18.cfn[cat_func].pm_dct); + cat_nthw_cfn_pm_ext_inv(be->p_cat_nthw, + cat->v18.cfn[cat_func].pm_ext_inv); + cat_nthw_cfn_pm_cmb(be->p_cat_nthw, + cat->v18.cfn[cat_func].pm_cmb); + cat_nthw_cfn_pm_and_inv(be->p_cat_nthw, + cat->v18.cfn[cat_func].pm_and_inv); + cat_nthw_cfn_pm_or_inv(be->p_cat_nthw, + cat->v18.cfn[cat_func].pm_or_inv); + cat_nthw_cfn_pm_inv(be->p_cat_nthw, + cat->v18.cfn[cat_func].pm_inv); + + cat_nthw_cfn_lc(be->p_cat_nthw, cat->v18.cfn[cat_func].lc); + cat_nthw_cfn_lc_inv(be->p_cat_nthw, + cat->v18.cfn[cat_func].lc_inv); + cat_nthw_cfn_km0_or(be->p_cat_nthw, + cat->v18.cfn[cat_func].km_or); + cat_nthw_cfn_flush(be->p_cat_nthw); + cat_func++; + } + } else if (cat->ver == 21 || cat->ver == 22) { + r(be->p_cat_nthw, 1U); + for (int i = 0; i < cnt; i++) { + cat_nthw_cfn_select(be->p_cat_nthw, cat_func); + cat_nthw_cfn_enable(be->p_cat_nthw, + cat->v21.cfn[cat_func].enable); + cat_nthw_cfn_inv(be->p_cat_nthw, + cat->v21.cfn[cat_func].inv); + cat_nthw_cfn_ptc_inv(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_inv); + cat_nthw_cfn_ptc_isl(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_isl); + cat_nthw_cfn_ptc_cfp(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_cfp); + cat_nthw_cfn_ptc_mac(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_mac); + cat_nthw_cfn_ptc_l2(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_l2); + cat_nthw_cfn_ptc_vn_tag(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_vntag); + cat_nthw_cfn_ptc_vlan(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_vlan); + cat_nthw_cfn_ptc_mpls(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_mpls); + cat_nthw_cfn_ptc_l3(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_l3); + cat_nthw_cfn_ptc_frag(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_frag); + cat_nthw_cfn_ptc_ip_prot(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_ip_prot); + cat_nthw_cfn_ptc_l4(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_l4); + cat_nthw_cfn_ptc_tunnel(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_tunnel); + cat_nthw_cfn_ptc_tnl_l2(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_tnl_l2); + cat_nthw_cfn_ptc_tnl_vlan(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_tnl_vlan); + cat_nthw_cfn_ptc_tnl_mpls(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_tnl_mpls); + cat_nthw_cfn_ptc_tnl_l3(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_tnl_l3); + cat_nthw_cfn_ptc_tnl_frag(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_tnl_frag); + cat_nthw_cfn_ptc_tnl_ip_prot(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_tnl_ip_prot); + cat_nthw_cfn_ptc_tnl_l4(be->p_cat_nthw, + cat->v21.cfn[cat_func].ptc_tnl_l4); + + cat_nthw_cfn_err_inv(be->p_cat_nthw, + cat->v21.cfn[cat_func].err_inv); + cat_nthw_cfn_err_cv(be->p_cat_nthw, + cat->v21.cfn[cat_func].err_cv); + cat_nthw_cfn_err_fcs(be->p_cat_nthw, + cat->v21.cfn[cat_func].err_fcs); + cat_nthw_cfn_err_trunc(be->p_cat_nthw, + cat->v21.cfn[cat_func].err_trunc); + cat_nthw_cfn_err_l3_cs(be->p_cat_nthw, + cat->v21.cfn[cat_func].err_l3_cs); + cat_nthw_cfn_err_l4_cs(be->p_cat_nthw, + cat->v21.cfn[cat_func].err_l4_cs); + cat_nthw_cfn_err_tnl_l3_cs(be->p_cat_nthw, + cat->v21.cfn[cat_func].err_tnl_l3_cs); + cat_nthw_cfn_err_tnl_l4_cs(be->p_cat_nthw, + cat->v21.cfn[cat_func].err_tnl_l4_cs); + cat_nthw_cfn_err_ttl_exp(be->p_cat_nthw, + cat->v21.cfn[cat_func].err_ttl_exp); + cat_nthw_cfn_err_tnl_ttl_exp(be->p_cat_nthw, + cat->v21.cfn[cat_func].err_tnl_ttl_exp); + + cat_nthw_cfn_mac_port(be->p_cat_nthw, + cat->v21.cfn[cat_func].mac_port); + + cat_nthw_cfn_pm_cmp(be->p_cat_nthw, + cat->v21.cfn[cat_func].pm_cmp); + cat_nthw_cfn_pm_dct(be->p_cat_nthw, + cat->v21.cfn[cat_func].pm_dct); + cat_nthw_cfn_pm_ext_inv(be->p_cat_nthw, + cat->v21.cfn[cat_func].pm_ext_inv); + cat_nthw_cfn_pm_cmb(be->p_cat_nthw, + cat->v21.cfn[cat_func].pm_cmb); + cat_nthw_cfn_pm_and_inv(be->p_cat_nthw, + cat->v21.cfn[cat_func].pm_and_inv); + cat_nthw_cfn_pm_or_inv(be->p_cat_nthw, + cat->v21.cfn[cat_func].pm_or_inv); + cat_nthw_cfn_pm_inv(be->p_cat_nthw, + cat->v21.cfn[cat_func].pm_inv); + + cat_nthw_cfn_lc(be->p_cat_nthw, cat->v21.cfn[cat_func].lc); + cat_nthw_cfn_lc_inv(be->p_cat_nthw, + cat->v21.cfn[cat_func].lc_inv); + cat_nthw_cfn_km0_or(be->p_cat_nthw, + cat->v21.cfn[cat_func].km0_or); + if (be->p_cat_nthw->m_km_if_cnt > 1) { + cat_nthw_cfn_km1_or(be->p_cat_nthw, + cat->v21.cfn[cat_func].km1_or); + } + cat_nthw_cfn_flush(be->p_cat_nthw); + cat_func++; + } + } + + _CHECK_DEBUG_OFF(cat, be->p_cat_nthw); + return 0; +} + +static int cat_kce_flush(void *be_dev, const struct cat_func_s *cat, + int km_if_idx, int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw); + + if (cat->ver == 18) { + cat_nthw_kce_cnt(be->p_cat_nthw, 0, 1U); + for (int i = 0; i < cnt; i++) { + cat_nthw_kce_select(be->p_cat_nthw, 0, index + i); + cat_nthw_kce_enable(be->p_cat_nthw, 0, + cat->v18.kce[index + i].enable_bm); + cat_nthw_kce_flush(be->p_cat_nthw, 0); + } + } else if (cat->ver == 21 || cat->ver == 22) { + cat_nthw_kce_cnt(be->p_cat_nthw, km_if_idx, 1U); + for (int i = 0; i < cnt; i++) { + cat_nthw_kce_select(be->p_cat_nthw, km_if_idx, index + i); + cat_nthw_kce_enable(be->p_cat_nthw, km_if_idx, + cat->v21.kce[index + i].enable_bm[km_if_idx]); + cat_nthw_kce_flush(be->p_cat_nthw, km_if_idx); + } + } + + _CHECK_DEBUG_OFF(cat, be->p_cat_nthw); + return 0; +} + +static int cat_kcs_flush(void *be_dev, const struct cat_func_s *cat, + int km_if_idx, int cat_func, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw); + + if (cat->ver == 18) { + cat_nthw_kcs_cnt(be->p_cat_nthw, 0, 1U); + for (int i = 0; i < cnt; i++) { + cat_nthw_kcs_select(be->p_cat_nthw, 0, cat_func); + cat_nthw_kcs_category(be->p_cat_nthw, 0, + cat->v18.kcs[cat_func].category); + cat_nthw_kcs_flush(be->p_cat_nthw, 0); + cat_func++; + } + } else if (cat->ver == 21 || cat->ver == 22) { + cat_nthw_kcs_cnt(be->p_cat_nthw, km_if_idx, 1U); + for (int i = 0; i < cnt; i++) { + cat_nthw_kcs_select(be->p_cat_nthw, km_if_idx, cat_func); + cat_nthw_kcs_category(be->p_cat_nthw, km_if_idx, + cat->v21.kcs[cat_func].category[km_if_idx]); + cat_nthw_kcs_flush(be->p_cat_nthw, km_if_idx); + cat_func++; + } + } + + _CHECK_DEBUG_OFF(cat, be->p_cat_nthw); + return 0; +} + +static int cat_fte_flush(void *be_dev, const struct cat_func_s *cat, + int km_if_idx, int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw); + + if (cat->ver == 18) { + cat_nthw_fte_cnt(be->p_cat_nthw, 0, 1); + for (int i = 0; i < cnt; i++) { + cat_nthw_fte_select(be->p_cat_nthw, 0, index + i); + cat_nthw_fte_enable(be->p_cat_nthw, 0, + cat->v18.fte[index + i].enable_bm); + cat_nthw_fte_flush(be->p_cat_nthw, 0); + } + } else if (cat->ver == 21 || cat->ver == 22) { + cat_nthw_fte_cnt(be->p_cat_nthw, km_if_idx, 1); + for (int i = 0; i < cnt; i++) { + cat_nthw_fte_select(be->p_cat_nthw, km_if_idx, index + i); + cat_nthw_fte_enable(be->p_cat_nthw, km_if_idx, + cat->v21.fte[index + i].enable_bm[km_if_idx]); + cat_nthw_fte_flush(be->p_cat_nthw, km_if_idx); + } + } + + _CHECK_DEBUG_OFF(cat, be->p_cat_nthw); + return 0; +} + +static int cat_cte_flush(void *be_dev, const struct cat_func_s *cat, + int cat_func, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw); + + if (cat->ver == 18 || cat->ver == 21) { + cat_nthw_cte_cnt(be->p_cat_nthw, 1); + for (int i = 0; i < cnt; i++) { + cat_nthw_cte_select(be->p_cat_nthw, cat_func); + cat_nthw_cte_enable_col(be->p_cat_nthw, + cat->v18.cte[cat_func].b.col); + cat_nthw_cte_enable_cor(be->p_cat_nthw, + cat->v18.cte[cat_func].b.cor); + cat_nthw_cte_enable_hsh(be->p_cat_nthw, + cat->v18.cte[cat_func].b.hsh); + cat_nthw_cte_enable_qsl(be->p_cat_nthw, + cat->v18.cte[cat_func].b.qsl); + cat_nthw_cte_enable_ipf(be->p_cat_nthw, + cat->v18.cte[cat_func].b.ipf); + cat_nthw_cte_enable_slc(be->p_cat_nthw, + cat->v18.cte[cat_func].b.slc); + cat_nthw_cte_enable_pdb(be->p_cat_nthw, + cat->v18.cte[cat_func].b.pdb); + cat_nthw_cte_enable_msk(be->p_cat_nthw, + cat->v18.cte[cat_func].b.msk); + cat_nthw_cte_enable_hst(be->p_cat_nthw, + cat->v18.cte[cat_func].b.hst); + cat_nthw_cte_enable_epp(be->p_cat_nthw, + cat->v18.cte[cat_func].b.epp); + cat_nthw_cte_enable_tpe(be->p_cat_nthw, + cat->v18.cte[cat_func].b.tpe); + + cat_nthw_cte_flush(be->p_cat_nthw); + cat_func++; + } + } else if (cat->ver == 22) { + cat_nthw_cte_cnt(be->p_cat_nthw, 1); + for (int i = 0; i < cnt; i++) { + cat_nthw_cte_select(be->p_cat_nthw, cat_func); + cat_nthw_cte_enable_col(be->p_cat_nthw, + cat->v22.cte[cat_func].b.col); + cat_nthw_cte_enable_cor(be->p_cat_nthw, + cat->v22.cte[cat_func].b.cor); + cat_nthw_cte_enable_hsh(be->p_cat_nthw, + cat->v22.cte[cat_func].b.hsh); + cat_nthw_cte_enable_qsl(be->p_cat_nthw, + cat->v22.cte[cat_func].b.qsl); + cat_nthw_cte_enable_ipf(be->p_cat_nthw, + cat->v22.cte[cat_func].b.ipf); + cat_nthw_cte_enable_slc(be->p_cat_nthw, + cat->v22.cte[cat_func].b.slc); + cat_nthw_cte_enable_pdb(be->p_cat_nthw, + cat->v22.cte[cat_func].b.pdb); + cat_nthw_cte_enable_msk(be->p_cat_nthw, + cat->v22.cte[cat_func].b.msk); + cat_nthw_cte_enable_hst(be->p_cat_nthw, + cat->v22.cte[cat_func].b.hst); + cat_nthw_cte_enable_epp(be->p_cat_nthw, + cat->v22.cte[cat_func].b.epp); + cat_nthw_cte_enable_tpe(be->p_cat_nthw, + cat->v22.cte[cat_func].b.tpe); + cat_nthw_cte_enable_tpe(be->p_cat_nthw, + cat->v22.cte[cat_func].b.rrb); + + cat_nthw_cte_flush(be->p_cat_nthw); + cat_func++; + } + } + + _CHECK_DEBUG_OFF(cat, be->p_cat_nthw); + return 0; +} + +static int cat_cts_flush(void *be_dev, const struct cat_func_s *cat, int index, + int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw); + + if (cat->ver == 18 || cat->ver == 21 || cat->ver == 22) { + cat_nthw_cts_cnt(be->p_cat_nthw, 1); + for (int i = 0; i < cnt; i++) { + cat_nthw_cts_select(be->p_cat_nthw, index + i); + cat_nthw_cts_cat_a(be->p_cat_nthw, + cat->v18.cts[index + i].cat_a); + cat_nthw_cts_cat_b(be->p_cat_nthw, + cat->v18.cts[index + i].cat_b); + cat_nthw_cts_flush(be->p_cat_nthw); + } + } + + _CHECK_DEBUG_OFF(cat, be->p_cat_nthw); + return 0; +} + +static int cat_cot_flush(void *be_dev, const struct cat_func_s *cat, + int cat_func, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw); + + if (cat->ver == 18 || cat->ver == 21 || cat->ver == 22) { + cat_nthw_cot_cnt(be->p_cat_nthw, 1); + for (int i = 0; i < cnt; i++) { + cat_nthw_cot_select(be->p_cat_nthw, cat_func + i); + cat_nthw_cot_color(be->p_cat_nthw, + cat->v18.cot[cat_func + i].color); + cat_nthw_cot_km(be->p_cat_nthw, + cat->v18.cot[cat_func + i].km); + cat_nthw_cot_flush(be->p_cat_nthw); + } + } + + _CHECK_DEBUG_OFF(cat, be->p_cat_nthw); + return 0; +} + +static int cat_cct_flush(void *be_dev, const struct cat_func_s *cat, int index, + int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw); + + if (cat->ver == 18 || cat->ver == 21 || cat->ver == 22) { + cat_nthw_cct_cnt(be->p_cat_nthw, 1); + for (int i = 0; i < cnt; i++) { + cat_nthw_cct_select(be->p_cat_nthw, index + i); + cat_nthw_cct_color(be->p_cat_nthw, + cat->v18.cct[index + i].color); + cat_nthw_cct_km(be->p_cat_nthw, cat->v18.cct[index + i].km); + cat_nthw_cct_flush(be->p_cat_nthw); + } + } + + _CHECK_DEBUG_OFF(cat, be->p_cat_nthw); + return 0; +} + +static int cat_exo_flush(void *be_dev, const struct cat_func_s *cat, + int ext_index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw); + + if (cat->ver == 18 || cat->ver == 21 || cat->ver == 22) { + cat_nthw_exo_cnt(be->p_cat_nthw, 1); + for (int i = 0; i < cnt; i++) { + cat_nthw_exo_select(be->p_cat_nthw, ext_index + i); + cat_nthw_exo_dyn(be->p_cat_nthw, + cat->v18.exo[ext_index + i].dyn); + cat_nthw_exo_ofs(be->p_cat_nthw, + cat->v18.exo[ext_index + i].ofs); + cat_nthw_exo_flush(be->p_cat_nthw); + } + } + + _CHECK_DEBUG_OFF(cat, be->p_cat_nthw); + return 0; +} + +static int cat_rck_flush(void *be_dev, const struct cat_func_s *cat, int index, + int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw); + + if (cat->ver == 18 || cat->ver == 21 || cat->ver == 22) { + cat_nthw_rck_cnt(be->p_cat_nthw, 1); + for (int i = 0; i < cnt; i++) { + cat_nthw_rck_select(be->p_cat_nthw, index + i); + cat_nthw_rck_data(be->p_cat_nthw, + cat->v18.rck[index + i].rck_data); + cat_nthw_rck_flush(be->p_cat_nthw); + } + } + + _CHECK_DEBUG_OFF(cat, be->p_cat_nthw); + return 0; +} + +static int cat_len_flush(void *be_dev, const struct cat_func_s *cat, + int len_index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw); + + if (cat->ver == 18 || cat->ver == 21 || cat->ver == 22) { + cat_nthw_len_cnt(be->p_cat_nthw, 1); + for (int i = 0; i < cnt; i++) { + cat_nthw_len_select(be->p_cat_nthw, len_index + i); + cat_nthw_len_lower(be->p_cat_nthw, + cat->v18.len[len_index + i].lower); + cat_nthw_len_upper(be->p_cat_nthw, + cat->v18.len[len_index + i].upper); + cat_nthw_len_dyn1(be->p_cat_nthw, + cat->v18.len[len_index + i].dyn1); + cat_nthw_len_dyn2(be->p_cat_nthw, + cat->v18.len[len_index + i].dyn2); + cat_nthw_len_inv(be->p_cat_nthw, + cat->v18.len[len_index + i].inv); + cat_nthw_len_flush(be->p_cat_nthw); + } + } + + _CHECK_DEBUG_OFF(cat, be->p_cat_nthw); + return 0; +} + +static int cat_kcc_flush(void *be_dev, const struct cat_func_s *cat, + int len_index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw); + + if (cat->ver == 18 || cat->ver == 21 || cat->ver == 22) { + cat_nthw_kcc_cnt(be->p_cat_nthw, 1); + for (int i = 0; i < cnt; i++) { + cat_nthw_kcc_select(be->p_cat_nthw, len_index + i); + cat_nthw_kcc_key(be->p_cat_nthw, + cat->v18.kcc_cam[len_index + i].key); + cat_nthw_kcc_category(be->p_cat_nthw, + cat->v18.kcc_cam[len_index + i].category); + cat_nthw_kcc_id(be->p_cat_nthw, + cat->v18.kcc_cam[len_index + i].id); + cat_nthw_kcc_flush(be->p_cat_nthw); + } + } + + _CHECK_DEBUG_OFF(cat, be->p_cat_nthw); + return 0; +} + +static int cat_cce_flush(void *be_dev, const struct cat_func_s *cat, + int len_index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw); + + if (cat->ver == 22) { + cat_nthw_cce_cnt(be->p_cat_nthw, 1); + for (int i = 0; i < cnt; i++) { + cat_nthw_cce_select(be->p_cat_nthw, len_index + i); + cat_nthw_cce_data_imm(be->p_cat_nthw, + cat->v22.cce[len_index + i].imm); + cat_nthw_cce_data_ind(be->p_cat_nthw, + cat->v22.cce[len_index + i].ind); + cat_nthw_cce_flush(be->p_cat_nthw); + } + } + + _CHECK_DEBUG_OFF(cat, be->p_cat_nthw); + return 0; +} + +static int cat_ccs_flush(void *be_dev, const struct cat_func_s *cat, + int len_index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw); + + if (cat->ver == 22) { + cat_nthw_ccs_cnt(be->p_cat_nthw, 1); + for (int i = 0; i < cnt; i++) { + cat_nthw_ccs_select(be->p_cat_nthw, len_index + i); + cat_nthw_ccs_data_cor_en(be->p_cat_nthw, + cat->v22.ccs[len_index + i].cor_en); + cat_nthw_ccs_data_cor(be->p_cat_nthw, + cat->v22.ccs[len_index + i].cor); + cat_nthw_ccs_data_hsh_en(be->p_cat_nthw, + cat->v22.ccs[len_index + i].hsh_en); + cat_nthw_ccs_data_hsh(be->p_cat_nthw, + cat->v22.ccs[len_index + i].hsh); + cat_nthw_ccs_data_qsl_en(be->p_cat_nthw, + cat->v22.ccs[len_index + i].qsl_en); + cat_nthw_ccs_data_qsl(be->p_cat_nthw, + cat->v22.ccs[len_index + i].qsl); + cat_nthw_ccs_data_ipf_en(be->p_cat_nthw, + cat->v22.ccs[len_index + i].ipf_en); + cat_nthw_ccs_data_ipf(be->p_cat_nthw, + cat->v22.ccs[len_index + i].ipf); + cat_nthw_ccs_data_slc_en(be->p_cat_nthw, + cat->v22.ccs[len_index + i].slc_en); + cat_nthw_ccs_data_slc(be->p_cat_nthw, + cat->v22.ccs[len_index + i].slc); + cat_nthw_ccs_data_pdb_en(be->p_cat_nthw, + cat->v22.ccs[len_index + i].pdb_en); + cat_nthw_ccs_data_pdb(be->p_cat_nthw, + cat->v22.ccs[len_index + i].pdb); + cat_nthw_ccs_data_msk_en(be->p_cat_nthw, + cat->v22.ccs[len_index + i].msk_en); + cat_nthw_ccs_data_msk(be->p_cat_nthw, + cat->v22.ccs[len_index + i].msk); + cat_nthw_ccs_data_hst_en(be->p_cat_nthw, + cat->v22.ccs[len_index + i].hst_en); + cat_nthw_ccs_data_hst(be->p_cat_nthw, + cat->v22.ccs[len_index + i].hst); + cat_nthw_ccs_data_epp_en(be->p_cat_nthw, + cat->v22.ccs[len_index + i].epp_en); + cat_nthw_ccs_data_epp(be->p_cat_nthw, + cat->v22.ccs[len_index + i].epp); + cat_nthw_ccs_data_tpe_en(be->p_cat_nthw, + cat->v22.ccs[len_index + i].tpe_en); + cat_nthw_ccs_data_tpe(be->p_cat_nthw, + cat->v22.ccs[len_index + i].tpe); + cat_nthw_ccs_data_rrb_en(be->p_cat_nthw, + cat->v22.ccs[len_index + i].rrb_en); + cat_nthw_ccs_data_rrb(be->p_cat_nthw, + cat->v22.ccs[len_index + i].rrb); + cat_nthw_ccs_data_sb0_type(be->p_cat_nthw, + cat->v22.ccs[len_index + i].sb0_type); + cat_nthw_ccs_data_sb0_data(be->p_cat_nthw, + cat->v22.ccs[len_index + i].sb0_data); + cat_nthw_ccs_data_sb1_type(be->p_cat_nthw, + cat->v22.ccs[len_index + i].sb1_type); + cat_nthw_ccs_data_sb1_data(be->p_cat_nthw, + cat->v22.ccs[len_index + i].sb1_data); + cat_nthw_ccs_data_sb2_type(be->p_cat_nthw, + cat->v22.ccs[len_index + i].sb2_type); + cat_nthw_ccs_data_sb2_data(be->p_cat_nthw, + cat->v22.ccs[len_index + i].sb2_data); + cat_nthw_ccs_flush(be->p_cat_nthw); + } + } + + _CHECK_DEBUG_OFF(cat, be->p_cat_nthw); + return 0; +} + +/* + * ***************** KM ******************* + */ + +static bool km_get_present(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return be->p_km_nthw != NULL; +} + +static uint32_t km_get_version(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return (uint32_t)((module_get_major_version(be->p_km_nthw->m_km) << 16) | + (module_get_minor_version(be->p_km_nthw->m_km) & 0xffff)); +} + +static int km_rcp_flush(void *be_dev, const struct km_func_s *km, int category, + int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, km, be->p_km_nthw); + + if (km->ver == 7) { + km_nthw_rcp_cnt(be->p_km_nthw, 1); + for (int i = 0; i < cnt; i++) { + km_nthw_rcp_select(be->p_km_nthw, category + i); + km_nthw_rcp_qw0_dyn(be->p_km_nthw, + km->v7.rcp[category + i].qw0_dyn); + km_nthw_rcp_qw0_ofs(be->p_km_nthw, + km->v7.rcp[category + i].qw0_ofs); + km_nthw_rcp_qw0_sel_a(be->p_km_nthw, + km->v7.rcp[category + i].qw0_sel_a); + km_nthw_rcp_qw0_sel_b(be->p_km_nthw, + km->v7.rcp[category + i].qw0_sel_b); + km_nthw_rcp_qw4_dyn(be->p_km_nthw, + km->v7.rcp[category + i].qw4_dyn); + km_nthw_rcp_qw4_ofs(be->p_km_nthw, + km->v7.rcp[category + i].qw4_ofs); + km_nthw_rcp_qw4_sel_a(be->p_km_nthw, + km->v7.rcp[category + i].qw4_sel_a); + km_nthw_rcp_qw4_sel_b(be->p_km_nthw, + km->v7.rcp[category + i].qw4_sel_b); + km_nthw_rcp_dw8_dyn(be->p_km_nthw, + km->v7.rcp[category + i].dw8_dyn); + km_nthw_rcp_dw8_ofs(be->p_km_nthw, + km->v7.rcp[category + i].dw8_ofs); + km_nthw_rcp_dw8_sel_a(be->p_km_nthw, + km->v7.rcp[category + i].dw8_sel_a); + km_nthw_rcp_dw8_sel_b(be->p_km_nthw, + km->v7.rcp[category + i].dw8_sel_b); + km_nthw_rcp_dw10_dyn(be->p_km_nthw, + km->v7.rcp[category + i].dw10_dyn); + km_nthw_rcp_dw10_ofs(be->p_km_nthw, + km->v7.rcp[category + i].dw10_ofs); + km_nthw_rcp_dw10_sel_a(be->p_km_nthw, + km->v7.rcp[category + i].dw10_sel_a); + km_nthw_rcp_dw10_sel_b(be->p_km_nthw, + km->v7.rcp[category + i].dw10_sel_b); + km_nthw_rcp_swx_cch(be->p_km_nthw, + km->v7.rcp[category + i].swx_cch); + km_nthw_rcp_swx_sel_a(be->p_km_nthw, + km->v7.rcp[category + i].swx_sel_a); + km_nthw_rcp_swx_sel_b(be->p_km_nthw, + km->v7.rcp[category + i].swx_sel_b); + km_nthw_rcp_mask_d_a(be->p_km_nthw, + km->v7.rcp[category + i].mask_d_a); + km_nthw_rcp_mask_b(be->p_km_nthw, + km->v7.rcp[category + i].mask_b); + km_nthw_rcp_dual(be->p_km_nthw, + km->v7.rcp[category + i].dual); + km_nthw_rcp_paired(be->p_km_nthw, + km->v7.rcp[category + i].paired); + km_nthw_rcp_el_a(be->p_km_nthw, + km->v7.rcp[category + i].el_a); + km_nthw_rcp_el_b(be->p_km_nthw, + km->v7.rcp[category + i].el_b); + km_nthw_rcp_info_a(be->p_km_nthw, + km->v7.rcp[category + i].info_a); + km_nthw_rcp_info_b(be->p_km_nthw, + km->v7.rcp[category + i].info_b); + km_nthw_rcp_ftm_a(be->p_km_nthw, + km->v7.rcp[category + i].ftm_a); + km_nthw_rcp_ftm_b(be->p_km_nthw, + km->v7.rcp[category + i].ftm_b); + km_nthw_rcp_bank_a(be->p_km_nthw, + km->v7.rcp[category + i].bank_a); + km_nthw_rcp_bank_b(be->p_km_nthw, + km->v7.rcp[category + i].bank_b); + km_nthw_rcp_kl_a(be->p_km_nthw, + km->v7.rcp[category + i].kl_a); + km_nthw_rcp_kl_b(be->p_km_nthw, + km->v7.rcp[category + i].kl_b); + km_nthw_rcp_keyway_a(be->p_km_nthw, + km->v7.rcp[category + i].keyway_a); + km_nthw_rcp_keyway_b(be->p_km_nthw, + km->v7.rcp[category + i].keyway_b); + km_nthw_rcp_synergy_mode(be->p_km_nthw, + km->v7.rcp[category + i].synergy_mode); + km_nthw_rcp_dw0_b_dyn(be->p_km_nthw, + km->v7.rcp[category + i].dw0_b_dyn); + km_nthw_rcp_dw0_b_ofs(be->p_km_nthw, + km->v7.rcp[category + i].dw0_b_ofs); + km_nthw_rcp_dw2_b_dyn(be->p_km_nthw, + km->v7.rcp[category + i].dw2_b_dyn); + km_nthw_rcp_dw2_b_ofs(be->p_km_nthw, + km->v7.rcp[category + i].dw2_b_ofs); + km_nthw_rcp_sw4_b_dyn(be->p_km_nthw, + km->v7.rcp[category + i].sw4_b_dyn); + km_nthw_rcp_sw4_b_ofs(be->p_km_nthw, + km->v7.rcp[category + i].sw4_b_ofs); + km_nthw_rcp_sw5_b_dyn(be->p_km_nthw, + km->v7.rcp[category + i].sw5_b_dyn); + km_nthw_rcp_sw5_b_ofs(be->p_km_nthw, + km->v7.rcp[category + i].sw5_b_ofs); + km_nthw_rcp_flush(be->p_km_nthw); + } + } + + _CHECK_DEBUG_OFF(km, be->p_km_nthw); + return 0; +} + +static int km_cam_flush(void *be_dev, const struct km_func_s *km, int bank, + int record, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, km, be->p_km_nthw); + + if (km->ver == 7) { + km_nthw_cam_cnt(be->p_km_nthw, 1); + for (int i = 0; i < cnt; i++) { + km_nthw_cam_select(be->p_km_nthw, + (bank << 11) + record + i); + km_nthw_cam_w0(be->p_km_nthw, + km->v7.cam[(bank << 11) + record + i].w0); + km_nthw_cam_w1(be->p_km_nthw, + km->v7.cam[(bank << 11) + record + i].w1); + km_nthw_cam_w2(be->p_km_nthw, + km->v7.cam[(bank << 11) + record + i].w2); + km_nthw_cam_w3(be->p_km_nthw, + km->v7.cam[(bank << 11) + record + i].w3); + km_nthw_cam_w4(be->p_km_nthw, + km->v7.cam[(bank << 11) + record + i].w4); + km_nthw_cam_w5(be->p_km_nthw, + km->v7.cam[(bank << 11) + record + i].w5); + km_nthw_cam_ft0(be->p_km_nthw, + km->v7.cam[(bank << 11) + record + i].ft0); + km_nthw_cam_ft1(be->p_km_nthw, + km->v7.cam[(bank << 11) + record + i].ft1); + km_nthw_cam_ft2(be->p_km_nthw, + km->v7.cam[(bank << 11) + record + i].ft2); + km_nthw_cam_ft3(be->p_km_nthw, + km->v7.cam[(bank << 11) + record + i].ft3); + km_nthw_cam_ft4(be->p_km_nthw, + km->v7.cam[(bank << 11) + record + i].ft4); + km_nthw_cam_ft5(be->p_km_nthw, + km->v7.cam[(bank << 11) + record + i].ft5); + km_nthw_cam_flush(be->p_km_nthw); + } + } + + _CHECK_DEBUG_OFF(km, be->p_km_nthw); + return 0; +} + +static int km_tcam_flush(void *be_dev, const struct km_func_s *km, int bank, + int byte, int value, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, km, be->p_km_nthw); + + if (km->ver == 7) { + int start_idx = bank * 4 * 256 + byte * 256 + value; + + km_nthw_tcam_cnt(be->p_km_nthw, 1); + for (int i = 0; i < cnt; i++) { + if (km->v7.tcam[start_idx + i].dirty) { + km_nthw_tcam_select(be->p_km_nthw, start_idx + i); + km_nthw_tcam_t(be->p_km_nthw, + km->v7.tcam[start_idx + i].t); + km_nthw_tcam_flush(be->p_km_nthw); + km->v7.tcam[start_idx + i].dirty = 0; + } + } + } + + _CHECK_DEBUG_OFF(km, be->p_km_nthw); + return 0; +} + +/* + * bank is the TCAM bank, index is the index within the bank (0..71) + */ +static int km_tci_flush(void *be_dev, const struct km_func_s *km, int bank, + int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, km, be->p_km_nthw); + + if (km->ver == 7) { + /* TCAM bank width in version 3 = 72 */ + km_nthw_tci_cnt(be->p_km_nthw, 1); + for (int i = 0; i < cnt; i++) { + km_nthw_tci_select(be->p_km_nthw, bank * 72 + index + i); + km_nthw_tci_color(be->p_km_nthw, + km->v7.tci[bank * 72 + index + i].color); + km_nthw_tci_ft(be->p_km_nthw, + km->v7.tci[bank * 72 + index + i].ft); + km_nthw_tci_flush(be->p_km_nthw); + } + } + + _CHECK_DEBUG_OFF(km, be->p_km_nthw); + return 0; +} + +/* + * bank is the TCAM bank, index is the index within the bank (0..71) + */ +static int km_tcq_flush(void *be_dev, const struct km_func_s *km, int bank, + int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, km, be->p_km_nthw); + + if (km->ver == 7) { + /* TCAM bank width in version 3 = 72 */ + km_nthw_tcq_cnt(be->p_km_nthw, 1); + for (int i = 0; i < cnt; i++) { + /* adr = lover 4 bits = bank, upper 7 bits = index */ + km_nthw_tcq_select(be->p_km_nthw, bank + (index << 4) + i); + km_nthw_tcq_bank_mask(be->p_km_nthw, + km->v7.tcq[bank + (index << 4) + i].bank_mask); + km_nthw_tcq_qual(be->p_km_nthw, + km->v7.tcq[bank + (index << 4) + i].qual); + km_nthw_tcq_flush(be->p_km_nthw); + } + } + + _CHECK_DEBUG_OFF(km, be->p_km_nthw); + return 0; +} + +/* + * ***************** FLM ******************* + */ + +static bool flm_get_present(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return be->p_flm_nthw != NULL; +} + +static uint32_t flm_get_version(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return (uint32_t)((module_get_major_version(be->p_flm_nthw->m_flm) << 16) | + (module_get_minor_version(be->p_flm_nthw->m_flm) & + 0xffff)); +} + +static int flm_control_flush(void *be_dev, const struct flm_func_s *flm) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + if (flm->ver >= 17) { + flm_nthw_control_enable(be->p_flm_nthw, flm->v17.control->enable); + flm_nthw_control_init(be->p_flm_nthw, flm->v17.control->init); + flm_nthw_control_lds(be->p_flm_nthw, flm->v17.control->lds); + flm_nthw_control_lfs(be->p_flm_nthw, flm->v17.control->lfs); + flm_nthw_control_lis(be->p_flm_nthw, flm->v17.control->lis); + flm_nthw_control_uds(be->p_flm_nthw, flm->v17.control->uds); + flm_nthw_control_uis(be->p_flm_nthw, flm->v17.control->uis); + flm_nthw_control_rds(be->p_flm_nthw, flm->v17.control->rds); + flm_nthw_control_ris(be->p_flm_nthw, flm->v17.control->ris); + flm_nthw_control_pds(be->p_flm_nthw, flm->v17.control->pds); + flm_nthw_control_pis(be->p_flm_nthw, flm->v17.control->pis); + flm_nthw_control_crcwr(be->p_flm_nthw, flm->v17.control->crcwr); + flm_nthw_control_crcrd(be->p_flm_nthw, flm->v17.control->crcrd); + flm_nthw_control_rbl(be->p_flm_nthw, flm->v17.control->rbl); + flm_nthw_control_eab(be->p_flm_nthw, flm->v17.control->eab); + flm_nthw_control_split_sdram_usage(be->p_flm_nthw, + flm->v17.control->split_sdram_usage); + flm_nthw_control_flush(be->p_flm_nthw); + } + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return 0; +} + +static int flm_status_flush(void *be_dev, const struct flm_func_s *flm) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + if (flm->ver >= 17) { + /* CALIBDONE, INITDONE, IDLE, and EFT_BP is read only */ + flm_nthw_status_critical(be->p_flm_nthw, &flm->v17.status->critical, + 0); + flm_nthw_status_panic(be->p_flm_nthw, &flm->v17.status->panic, 0); + flm_nthw_status_crcerr(be->p_flm_nthw, &flm->v17.status->crcerr, 0); + flm_nthw_status_flush(be->p_flm_nthw); + } + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return 0; +} + +static int flm_status_update(void *be_dev, const struct flm_func_s *flm) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + if (flm->ver >= 17) { + flm_nthw_status_update(be->p_flm_nthw); + flm_nthw_status_calibdone(be->p_flm_nthw, + &flm->v17.status->calibdone, 1); + flm_nthw_status_initdone(be->p_flm_nthw, &flm->v17.status->initdone, + 1); + flm_nthw_status_idle(be->p_flm_nthw, &flm->v17.status->idle, 1); + flm_nthw_status_critical(be->p_flm_nthw, &flm->v17.status->critical, + 1); + flm_nthw_status_panic(be->p_flm_nthw, &flm->v17.status->panic, 1); + flm_nthw_status_crcerr(be->p_flm_nthw, &flm->v17.status->crcerr, 1); + flm_nthw_status_eft_bp(be->p_flm_nthw, &flm->v17.status->eft_bp, 1); + } + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return 0; +} + +static int flm_timeout_flush(void *be_dev, const struct flm_func_s *flm) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + if (flm->ver >= 17) { + flm_nthw_timeout_t(be->p_flm_nthw, flm->v17.timeout->t); + flm_nthw_timeout_flush(be->p_flm_nthw); + } + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return 0; +} + +static int flm_scrub_flush(void *be_dev, const struct flm_func_s *flm) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + if (flm->ver >= 17) { + flm_nthw_scrub_i(be->p_flm_nthw, flm->v17.scrub->i); + flm_nthw_scrub_flush(be->p_flm_nthw); + } + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return 0; +} + +static int flm_load_bin_flush(void *be_dev, const struct flm_func_s *flm) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + if (flm->ver >= 17) { + flm_nthw_load_bin(be->p_flm_nthw, flm->v17.load_bin->bin); + flm_nthw_load_bin_flush(be->p_flm_nthw); + } + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return 0; +} + +static int flm_load_pps_flush(void *be_dev, const struct flm_func_s *flm) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + if (flm->ver >= 17) { + flm_nthw_load_pps(be->p_flm_nthw, flm->v17.load_pps->pps); + flm_nthw_load_pps_flush(be->p_flm_nthw); + } + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return 0; +} + +static int flm_load_lps_flush(void *be_dev, const struct flm_func_s *flm) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + if (flm->ver >= 17) { + flm_nthw_load_lps(be->p_flm_nthw, flm->v17.load_lps->lps); + flm_nthw_load_lps_flush(be->p_flm_nthw); + } + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return 0; +} + +static int flm_load_aps_flush(void *be_dev, const struct flm_func_s *flm) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + if (flm->ver >= 17) { + flm_nthw_load_aps(be->p_flm_nthw, flm->v17.load_aps->aps); + flm_nthw_load_aps_flush(be->p_flm_nthw); + } + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return 0; +} + +static int flm_prio_flush(void *be_dev, const struct flm_func_s *flm) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + if (flm->ver >= 17) { + flm_nthw_prio_limit0(be->p_flm_nthw, flm->v17.prio->limit0); + flm_nthw_prio_ft0(be->p_flm_nthw, flm->v17.prio->ft0); + flm_nthw_prio_limit1(be->p_flm_nthw, flm->v17.prio->limit1); + flm_nthw_prio_ft1(be->p_flm_nthw, flm->v17.prio->ft1); + flm_nthw_prio_limit2(be->p_flm_nthw, flm->v17.prio->limit2); + flm_nthw_prio_ft2(be->p_flm_nthw, flm->v17.prio->ft2); + flm_nthw_prio_limit3(be->p_flm_nthw, flm->v17.prio->limit3); + flm_nthw_prio_ft3(be->p_flm_nthw, flm->v17.prio->ft3); + flm_nthw_prio_flush(be->p_flm_nthw); + } + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return 0; +} + +static int flm_pst_flush(void *be_dev, const struct flm_func_s *flm, int index, + int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + if (flm->ver >= 17) { + flm_nthw_pst_cnt(be->p_flm_nthw, 1); + for (int i = 0; i < cnt; i++) { + flm_nthw_pst_select(be->p_flm_nthw, index + i); + flm_nthw_pst_bp(be->p_flm_nthw, flm->v17.pst[index + i].bp); + flm_nthw_pst_pp(be->p_flm_nthw, flm->v17.pst[index + i].pp); + flm_nthw_pst_tp(be->p_flm_nthw, flm->v17.pst[index + i].tp); + flm_nthw_pst_flush(be->p_flm_nthw); + } + } + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return 0; +} + +static int flm_rcp_flush(void *be_dev, const struct flm_func_s *flm, int index, + int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + if (flm->ver >= 17) { + flm_nthw_rcp_cnt(be->p_flm_nthw, 1); + for (int i = 0; i < cnt; i++) { + flm_nthw_rcp_select(be->p_flm_nthw, index + i); + flm_nthw_rcp_lookup(be->p_flm_nthw, + flm->v17.rcp[index + i].lookup); + flm_nthw_rcp_qw0_dyn(be->p_flm_nthw, + flm->v17.rcp[index + i].qw0_dyn); + flm_nthw_rcp_qw0_ofs(be->p_flm_nthw, + flm->v17.rcp[index + i].qw0_ofs); + flm_nthw_rcp_qw0_sel(be->p_flm_nthw, + flm->v17.rcp[index + i].qw0_sel); + flm_nthw_rcp_qw4_dyn(be->p_flm_nthw, + flm->v17.rcp[index + i].qw4_dyn); + flm_nthw_rcp_qw4_ofs(be->p_flm_nthw, + flm->v17.rcp[index + i].qw4_ofs); + flm_nthw_rcp_sw8_dyn(be->p_flm_nthw, + flm->v17.rcp[index + i].sw8_dyn); + flm_nthw_rcp_sw8_ofs(be->p_flm_nthw, + flm->v17.rcp[index + i].sw8_ofs); + flm_nthw_rcp_sw8_sel(be->p_flm_nthw, + flm->v17.rcp[index + i].sw8_sel); + flm_nthw_rcp_sw9_dyn(be->p_flm_nthw, + flm->v17.rcp[index + i].sw9_dyn); + flm_nthw_rcp_sw9_ofs(be->p_flm_nthw, + flm->v17.rcp[index + i].sw9_ofs); + flm_nthw_rcp_mask(be->p_flm_nthw, + flm->v17.rcp[index + i].mask); + flm_nthw_rcp_kid(be->p_flm_nthw, + flm->v17.rcp[index + i].kid); + flm_nthw_rcp_opn(be->p_flm_nthw, + flm->v17.rcp[index + i].opn); + flm_nthw_rcp_ipn(be->p_flm_nthw, + flm->v17.rcp[index + i].ipn); + flm_nthw_rcp_byt_dyn(be->p_flm_nthw, + flm->v17.rcp[index + i].byt_dyn); + flm_nthw_rcp_byt_ofs(be->p_flm_nthw, + flm->v17.rcp[index + i].byt_ofs); + flm_nthw_rcp_txplm(be->p_flm_nthw, + flm->v17.rcp[index + i].txplm); + flm_nthw_rcp_auto_ipv4_mask(be->p_flm_nthw, + flm->v17.rcp[index + i].auto_ipv4_mask); + flm_nthw_rcp_flush(be->p_flm_nthw); + } + } + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return 0; +} + +static int flm_buf_ctrl_update(void *be_dev, const struct flm_func_s *flm) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + if (flm->ver >= 17) { + flm_nthw_buf_ctrl_update(be->p_flm_nthw, + &flm->v17.buf_ctrl->lrn_free, + &flm->v17.buf_ctrl->inf_avail, + &flm->v17.buf_ctrl->sta_avail); + } + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return 0; +} + +static int flm_stat_update(void *be_dev, const struct flm_func_s *flm) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + if (flm->ver >= 17) { + flm_nthw_stat_lrn_done_update(be->p_flm_nthw); + flm_nthw_stat_lrn_ignore_update(be->p_flm_nthw); + flm_nthw_stat_lrn_fail_update(be->p_flm_nthw); + flm_nthw_stat_unl_done_update(be->p_flm_nthw); + flm_nthw_stat_unl_ignore_update(be->p_flm_nthw); + flm_nthw_stat_rel_done_update(be->p_flm_nthw); + flm_nthw_stat_rel_ignore_update(be->p_flm_nthw); + flm_nthw_stat_aul_done_update(be->p_flm_nthw); + flm_nthw_stat_aul_ignore_update(be->p_flm_nthw); + flm_nthw_stat_aul_fail_update(be->p_flm_nthw); + flm_nthw_stat_tul_done_update(be->p_flm_nthw); + flm_nthw_stat_flows_update(be->p_flm_nthw); + + flm_nthw_stat_lrn_done_cnt(be->p_flm_nthw, &flm->v17.lrn_done->cnt, + 1); + flm_nthw_stat_lrn_ignore_cnt(be->p_flm_nthw, + &flm->v17.lrn_ignore->cnt, 1); + flm_nthw_stat_lrn_fail_cnt(be->p_flm_nthw, &flm->v17.lrn_fail->cnt, + 1); + flm_nthw_stat_unl_done_cnt(be->p_flm_nthw, &flm->v17.unl_done->cnt, + 1); + flm_nthw_stat_unl_ignore_cnt(be->p_flm_nthw, + &flm->v17.unl_ignore->cnt, 1); + flm_nthw_stat_rel_done_cnt(be->p_flm_nthw, &flm->v17.rel_done->cnt, + 1); + flm_nthw_stat_rel_ignore_cnt(be->p_flm_nthw, + &flm->v17.rel_ignore->cnt, 1); + flm_nthw_stat_aul_done_cnt(be->p_flm_nthw, &flm->v17.aul_done->cnt, + 1); + flm_nthw_stat_aul_ignore_cnt(be->p_flm_nthw, + &flm->v17.aul_ignore->cnt, 1); + flm_nthw_stat_aul_fail_cnt(be->p_flm_nthw, &flm->v17.aul_fail->cnt, + 1); + flm_nthw_stat_tul_done_cnt(be->p_flm_nthw, &flm->v17.tul_done->cnt, + 1); + flm_nthw_stat_flows_cnt(be->p_flm_nthw, &flm->v17.flows->cnt, 1); + + flm_nthw_stat_prb_done_update(be->p_flm_nthw); + flm_nthw_stat_prb_ignore_update(be->p_flm_nthw); + flm_nthw_stat_prb_done_cnt(be->p_flm_nthw, &flm->v17.prb_done->cnt, + 1); + flm_nthw_stat_prb_ignore_cnt(be->p_flm_nthw, + &flm->v17.prb_ignore->cnt, 1); + } + if (flm->ver >= 20) { + flm_nthw_stat_sta_done_update(be->p_flm_nthw); + flm_nthw_stat_inf_done_update(be->p_flm_nthw); + flm_nthw_stat_inf_skip_update(be->p_flm_nthw); + flm_nthw_stat_pck_hit_update(be->p_flm_nthw); + flm_nthw_stat_pck_miss_update(be->p_flm_nthw); + flm_nthw_stat_pck_unh_update(be->p_flm_nthw); + flm_nthw_stat_pck_dis_update(be->p_flm_nthw); + flm_nthw_stat_csh_hit_update(be->p_flm_nthw); + flm_nthw_stat_csh_miss_update(be->p_flm_nthw); + flm_nthw_stat_csh_unh_update(be->p_flm_nthw); + flm_nthw_stat_cuc_start_update(be->p_flm_nthw); + flm_nthw_stat_cuc_move_update(be->p_flm_nthw); + + flm_nthw_stat_sta_done_cnt(be->p_flm_nthw, &flm->v20.sta_done->cnt, + 1); + flm_nthw_stat_inf_done_cnt(be->p_flm_nthw, &flm->v20.inf_done->cnt, + 1); + flm_nthw_stat_inf_skip_cnt(be->p_flm_nthw, &flm->v20.inf_skip->cnt, + 1); + flm_nthw_stat_pck_hit_cnt(be->p_flm_nthw, &flm->v20.pck_hit->cnt, 1); + flm_nthw_stat_pck_miss_cnt(be->p_flm_nthw, &flm->v20.pck_miss->cnt, + 1); + flm_nthw_stat_pck_unh_cnt(be->p_flm_nthw, &flm->v20.pck_unh->cnt, 1); + flm_nthw_stat_pck_dis_cnt(be->p_flm_nthw, &flm->v20.pck_dis->cnt, 1); + flm_nthw_stat_csh_hit_cnt(be->p_flm_nthw, &flm->v20.csh_hit->cnt, 1); + flm_nthw_stat_csh_miss_cnt(be->p_flm_nthw, &flm->v20.csh_miss->cnt, + 1); + flm_nthw_stat_csh_unh_cnt(be->p_flm_nthw, &flm->v20.csh_unh->cnt, 1); + flm_nthw_stat_cuc_start_cnt(be->p_flm_nthw, &flm->v20.cuc_start->cnt, + 1); + flm_nthw_stat_cuc_move_cnt(be->p_flm_nthw, &flm->v20.cuc_move->cnt, + 1); + } + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return 0; +} + +static int flm_lrn_data_flush(void *be_dev, const struct flm_func_s *flm, + const uint32_t *lrn_data, uint32_t size) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + int ret = flm_nthw_lrn_data_flush(be->p_flm_nthw, lrn_data, size, + &flm->v17.buf_ctrl->lrn_free, + &flm->v17.buf_ctrl->inf_avail, + &flm->v17.buf_ctrl->sta_avail); + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return ret; +} + +static int flm_inf_data_update(void *be_dev, const struct flm_func_s *flm, + uint32_t *inf_data, uint32_t size) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + int ret = flm_nthw_inf_data_update(be->p_flm_nthw, inf_data, size, + &flm->v17.buf_ctrl->lrn_free, + &flm->v17.buf_ctrl->inf_avail, + &flm->v17.buf_ctrl->sta_avail); + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return ret; +} + +static int flm_sta_data_update(void *be_dev, const struct flm_func_s *flm, + uint32_t *sta_data, uint32_t size) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw); + + int ret = flm_nthw_sta_data_update(be->p_flm_nthw, sta_data, size, + &flm->v17.buf_ctrl->lrn_free, + &flm->v17.buf_ctrl->inf_avail, + &flm->v17.buf_ctrl->sta_avail); + + _CHECK_DEBUG_OFF(flm, be->p_flm_nthw); + return ret; +} + +/* + * ***************** HSH ******************* + */ + +static bool hsh_get_present(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return be->p_hsh_nthw != NULL; +} + +static uint32_t hsh_get_version(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return (uint32_t)((module_get_major_version(be->p_hsh_nthw->m_hsh) << 16) | + (module_get_minor_version(be->p_hsh_nthw->m_hsh) & + 0xffff)); +} + +static int hsh_rcp_flush(void *be_dev, const struct hsh_func_s *hsh, + int category, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, hsh, be->p_hsh_nthw); + + if (hsh->ver == 5) { + hsh_nthw_rcp_cnt(be->p_hsh_nthw, 1); + for (int i = 0; i < cnt; i++) { + hsh_nthw_rcp_select(be->p_hsh_nthw, category + i); + hsh_nthw_rcp_load_dist_type(be->p_hsh_nthw, + hsh->v5.rcp[category + i].load_dist_type); + hsh_nthw_rcp_mac_port_mask(be->p_hsh_nthw, + hsh->v5.rcp[category + i].mac_port_mask); + hsh_nthw_rcp_sort(be->p_hsh_nthw, + hsh->v5.rcp[category + i].sort); + hsh_nthw_rcp_qw0_pe(be->p_hsh_nthw, + hsh->v5.rcp[category + i].qw0_pe); + hsh_nthw_rcp_qw0_ofs(be->p_hsh_nthw, + hsh->v5.rcp[category + i].qw0_ofs); + hsh_nthw_rcp_qw4_pe(be->p_hsh_nthw, + hsh->v5.rcp[category + i].qw4_pe); + hsh_nthw_rcp_qw4_ofs(be->p_hsh_nthw, + hsh->v5.rcp[category + i].qw4_ofs); + hsh_nthw_rcp_w8_pe(be->p_hsh_nthw, + hsh->v5.rcp[category + i].w8_pe); + hsh_nthw_rcp_w8_ofs(be->p_hsh_nthw, + hsh->v5.rcp[category + i].w8_ofs); + hsh_nthw_rcp_w8_sort(be->p_hsh_nthw, + hsh->v5.rcp[category + i].w8_sort); + hsh_nthw_rcp_w9_pe(be->p_hsh_nthw, + hsh->v5.rcp[category + i].w9_pe); + hsh_nthw_rcp_w9_ofs(be->p_hsh_nthw, + hsh->v5.rcp[category + i].w9_ofs); + hsh_nthw_rcp_w9_sort(be->p_hsh_nthw, + hsh->v5.rcp[category + i].w9_sort); + hsh_nthw_rcp_w9_p(be->p_hsh_nthw, + hsh->v5.rcp[category + i].w9_p); + hsh_nthw_rcp_p_mask(be->p_hsh_nthw, + hsh->v5.rcp[category + i].p_mask); + hsh_nthw_rcp_word_mask(be->p_hsh_nthw, + hsh->v5.rcp[category + i].word_mask); + hsh_nthw_rcp_seed(be->p_hsh_nthw, + hsh->v5.rcp[category + i].seed); + hsh_nthw_rcp_tnl_p(be->p_hsh_nthw, + hsh->v5.rcp[category + i].tnl_p); + hsh_nthw_rcp_hsh_valid(be->p_hsh_nthw, + hsh->v5.rcp[category + i].hsh_valid); + hsh_nthw_rcp_hsh_type(be->p_hsh_nthw, + hsh->v5.rcp[category + i].hsh_type); + hsh_nthw_rcp_auto_ipv4_mask(be->p_hsh_nthw, + hsh->v5.rcp[category + i].auto_ipv4_mask); + hsh_nthw_rcp_flush(be->p_hsh_nthw); + } + } + _CHECK_DEBUG_OFF(hsh, be->p_hsh_nthw); + return 0; +} + +/* + * ***************** HST ******************* + */ + +static bool hst_get_present(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return be->p_hst_nthw != NULL; +} + +static uint32_t hst_get_version(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return (uint32_t)((module_get_major_version(be->p_hst_nthw->m_hst) << 16) | + (module_get_minor_version(be->p_hst_nthw->m_hst) & + 0xffff)); +} + +static int hst_rcp_flush(void *be_dev, const struct hst_func_s *hst, + int category, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, hst, be->p_hst_nthw); + + if (hst->ver == 2) { + hst_nthw_rcp_cnt(be->p_hst_nthw, 1); + for (int i = 0; i < cnt; i++) { + hst_nthw_rcp_select(be->p_hst_nthw, category + i); + hst_nthw_rcp_strip_mode(be->p_hst_nthw, + hst->v2.rcp[category + i].strip_mode); + hst_nthw_rcp_start_dyn(be->p_hst_nthw, + hst->v2.rcp[category + i].start_dyn); + hst_nthw_rcp_start_ofs(be->p_hst_nthw, + hst->v2.rcp[category + i].start_ofs); + hst_nthw_rcp_end_dyn(be->p_hst_nthw, + hst->v2.rcp[category + i].end_dyn); + hst_nthw_rcp_end_ofs(be->p_hst_nthw, + hst->v2.rcp[category + i].end_ofs); + hst_nthw_rcp_modif0_cmd(be->p_hst_nthw, + hst->v2.rcp[category + i].modif0_cmd); + hst_nthw_rcp_modif0_dyn(be->p_hst_nthw, + hst->v2.rcp[category + i].modif0_dyn); + hst_nthw_rcp_modif0_ofs(be->p_hst_nthw, + hst->v2.rcp[category + i].modif0_ofs); + hst_nthw_rcp_modif0_value(be->p_hst_nthw, + hst->v2.rcp[category + i].modif0_value); + hst_nthw_rcp_modif1_cmd(be->p_hst_nthw, + hst->v2.rcp[category + i].modif1_cmd); + hst_nthw_rcp_modif1_dyn(be->p_hst_nthw, + hst->v2.rcp[category + i].modif1_dyn); + hst_nthw_rcp_modif1_ofs(be->p_hst_nthw, + hst->v2.rcp[category + i].modif1_ofs); + hst_nthw_rcp_modif1_value(be->p_hst_nthw, + hst->v2.rcp[category + i].modif1_value); + hst_nthw_rcp_modif2_cmd(be->p_hst_nthw, + hst->v2.rcp[category + i].modif2_cmd); + hst_nthw_rcp_modif2_dyn(be->p_hst_nthw, + hst->v2.rcp[category + i].modif2_dyn); + hst_nthw_rcp_modif2_ofs(be->p_hst_nthw, + hst->v2.rcp[category + i].modif2_ofs); + hst_nthw_rcp_modif2_value(be->p_hst_nthw, + hst->v2.rcp[category + i].modif2_value); + hst_nthw_rcp_flush(be->p_hst_nthw); + } + } + _CHECK_DEBUG_OFF(hst, be->p_hst_nthw); + return 0; +} + +/* + * ***************** QSL ******************* + */ + +static bool qsl_get_present(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return be->p_qsl_nthw != NULL; +} + +static uint32_t qsl_get_version(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return (uint32_t)((module_get_major_version(be->p_qsl_nthw->m_qsl) << 16) | + (module_get_minor_version(be->p_qsl_nthw->m_qsl) & + 0xffff)); +} + +static int qsl_rcp_flush(void *be_dev, const struct qsl_func_s *qsl, + int category, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, qsl, be->p_qsl_nthw); + + if (qsl->ver == 7) { + qsl_nthw_rcp_cnt(be->p_qsl_nthw, 1); + for (int i = 0; i < cnt; i++) { + qsl_nthw_rcp_select(be->p_qsl_nthw, category + i); + qsl_nthw_rcp_discard(be->p_qsl_nthw, + qsl->v7.rcp[category + i].discard); + qsl_nthw_rcp_drop(be->p_qsl_nthw, + qsl->v7.rcp[category + i].drop); + qsl_nthw_rcp_tbl_lo(be->p_qsl_nthw, + qsl->v7.rcp[category + i].tbl_lo); + qsl_nthw_rcp_tbl_hi(be->p_qsl_nthw, + qsl->v7.rcp[category + i].tbl_hi); + qsl_nthw_rcp_tbl_idx(be->p_qsl_nthw, + qsl->v7.rcp[category + i].tbl_idx); + qsl_nthw_rcp_tbl_msk(be->p_qsl_nthw, + qsl->v7.rcp[category + i].tbl_msk); + qsl_nthw_rcp_lr(be->p_qsl_nthw, + qsl->v7.rcp[category + i].lr); + qsl_nthw_rcp_tsa(be->p_qsl_nthw, + qsl->v7.rcp[category + i].tsa); + qsl_nthw_rcp_vli(be->p_qsl_nthw, + qsl->v7.rcp[category + i].vli); + qsl_nthw_rcp_flush(be->p_qsl_nthw); + } + } + + _CHECK_DEBUG_OFF(qsl, be->p_qsl_nthw); + return 0; +} + +static int qsl_qst_flush(void *be_dev, const struct qsl_func_s *qsl, int entry, + int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, qsl, be->p_qsl_nthw); + + if (qsl->ver == 7) { + qsl_nthw_qst_cnt(be->p_qsl_nthw, 1); + for (int i = 0; i < cnt; i++) { + qsl_nthw_qst_select(be->p_qsl_nthw, entry + i); + qsl_nthw_qst_queue(be->p_qsl_nthw, + qsl->v7.qst[entry + i].queue); + qsl_nthw_qst_en(be->p_qsl_nthw, qsl->v7.qst[entry + i].en); + + qsl_nthw_qst_tx_port(be->p_qsl_nthw, + qsl->v7.qst[entry + i].tx_port); + qsl_nthw_qst_lre(be->p_qsl_nthw, + qsl->v7.qst[entry + i].lre); + qsl_nthw_qst_tci(be->p_qsl_nthw, + qsl->v7.qst[entry + i].tci); + qsl_nthw_qst_ven(be->p_qsl_nthw, + qsl->v7.qst[entry + i].ven); + qsl_nthw_qst_flush(be->p_qsl_nthw); + } + } + + _CHECK_DEBUG_OFF(qsl, be->p_qsl_nthw); + return 0; +} + +static int qsl_qen_flush(void *be_dev, const struct qsl_func_s *qsl, int entry, + int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, qsl, be->p_qsl_nthw); + + if (qsl->ver == 7) { + qsl_nthw_qen_cnt(be->p_qsl_nthw, 1); + for (int i = 0; i < cnt; i++) { + qsl_nthw_qen_select(be->p_qsl_nthw, entry + i); + qsl_nthw_qen_en(be->p_qsl_nthw, qsl->v7.qen[entry + i].en); + qsl_nthw_qen_flush(be->p_qsl_nthw); + } + } + + _CHECK_DEBUG_OFF(qsl, be->p_qsl_nthw); + return 0; +} + +static int qsl_unmq_flush(void *be_dev, const struct qsl_func_s *qsl, int entry, + int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, qsl, be->p_qsl_nthw); + + if (qsl->ver == 7) { + qsl_nthw_unmq_cnt(be->p_qsl_nthw, 1); + for (int i = 0; i < cnt; i++) { + qsl_nthw_unmq_select(be->p_qsl_nthw, entry + i); + qsl_nthw_unmq_dest_queue(be->p_qsl_nthw, + qsl->v7.unmq[entry + i].dest_queue); + qsl_nthw_unmq_en(be->p_qsl_nthw, + qsl->v7.unmq[entry + i].en); + qsl_nthw_unmq_flush(be->p_qsl_nthw); + } + } + + _CHECK_DEBUG_OFF(qsl, be->p_qsl_nthw); + return 0; +} + +/* + * ***************** SLC ******************* + */ + +static bool slc_get_present(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return be->p_slc_nthw != NULL; +} + +static uint32_t slc_get_version(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return (uint32_t)((module_get_major_version(be->p_slc_nthw->m_slc) << 16) | + (module_get_minor_version(be->p_slc_nthw->m_slc) & + 0xffff)); +} + +static int slc_rcp_flush(void *be_dev, const struct slc_func_s *slc, + int category, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, slc, be->p_slc_nthw); + + if (slc->ver == 1) { + slc_nthw_rcp_cnt(be->p_slc_nthw, 1); + for (int i = 0; i < cnt; i++) { + slc_nthw_rcp_select(be->p_slc_nthw, category + i); + slc_nthw_rcp_tail_slc_en(be->p_slc_nthw, + slc->v1.rcp[category + i].tail_slc_en); + slc_nthw_rcp_tail_dyn(be->p_slc_nthw, + slc->v1.rcp[category + i].tail_dyn); + slc_nthw_rcp_tail_ofs(be->p_slc_nthw, + slc->v1.rcp[category + i].tail_ofs); + slc_nthw_rcp_pcap(be->p_slc_nthw, + slc->v1.rcp[category + i].pcap); + slc_nthw_rcp_flush(be->p_slc_nthw); + } + } + + _CHECK_DEBUG_OFF(slc, be->p_slc_nthw); + return 0; +} + +/* + * ***************** SLC LR ******************* + */ + +static bool slc_lr_get_present(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return be->p_slc_lr_nthw != NULL; +} + +static uint32_t slc_lr_get_version(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return (uint32_t)((module_get_major_version(be->p_slc_lr_nthw->m_slc_lr) + << 16) | + (module_get_minor_version(be->p_slc_lr_nthw->m_slc_lr) & + 0xffff)); +} + +static int slc_lr_rcp_flush(void *be_dev, const struct slc_lr_func_s *slc_lr, + int category, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, slc_lr, be->p_slc_lr_nthw); + + if (slc_lr->ver == 2) { + slc_lr_nthw_rcp_cnt(be->p_slc_lr_nthw, 1); + for (int i = 0; i < cnt; i++) { + slc_lr_nthw_rcp_select(be->p_slc_lr_nthw, category + i); + slc_lr_nthw_rcp_tail_slc_en(be->p_slc_lr_nthw, + slc_lr->v2.rcp[category + i].tail_slc_en); + slc_lr_nthw_rcp_tail_dyn(be->p_slc_lr_nthw, + slc_lr->v2.rcp[category + i].tail_dyn); + slc_lr_nthw_rcp_tail_ofs(be->p_slc_lr_nthw, + slc_lr->v2.rcp[category + i].tail_ofs); + slc_lr_nthw_rcp_pcap(be->p_slc_lr_nthw, + slc_lr->v2.rcp[category + i].pcap); + slc_lr_nthw_rcp_flush(be->p_slc_lr_nthw); + } + } + + _CHECK_DEBUG_OFF(slc_lr, be->p_slc_lr_nthw); + return 0; +} + +/* + * ***************** PDB ******************* + */ + +static bool pdb_get_present(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return be->p_pdb_nthw != NULL; +} + +static uint32_t pdb_get_version(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return (uint32_t)((module_get_major_version(be->p_pdb_nthw->m_pdb) << 16) | + (module_get_minor_version(be->p_pdb_nthw->m_pdb) & + 0xffff)); +} + +static int pdb_rcp_flush(void *be_dev, const struct pdb_func_s *pdb, + int category, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, pdb, be->p_pdb_nthw); + + if (pdb->ver == 9) { + pdb_nthw_rcp_cnt(be->p_pdb_nthw, 1); + for (int i = 0; i < cnt; i++) { + pdb_nthw_rcp_select(be->p_pdb_nthw, category + i); + pdb_nthw_rcp_descriptor(be->p_pdb_nthw, + pdb->v9.rcp[category + i].descriptor); + pdb_nthw_rcp_desc_len(be->p_pdb_nthw, + pdb->v9.rcp[category + i].desc_len); + pdb_nthw_rcp_tx_port(be->p_pdb_nthw, + pdb->v9.rcp[category + i].tx_port); + pdb_nthw_rcp_tx_ignore(be->p_pdb_nthw, + pdb->v9.rcp[category + i].tx_ignore); + pdb_nthw_rcp_tx_now(be->p_pdb_nthw, + pdb->v9.rcp[category + i].tx_now); + pdb_nthw_rcp_crc_overwrite(be->p_pdb_nthw, + pdb->v9.rcp[category + i].crc_overwrite); + pdb_nthw_rcp_align(be->p_pdb_nthw, + pdb->v9.rcp[category + i].align); + pdb_nthw_rcp_ofs0_dyn(be->p_pdb_nthw, + pdb->v9.rcp[category + i].ofs0_dyn); + pdb_nthw_rcp_ofs0_rel(be->p_pdb_nthw, + pdb->v9.rcp[category + i].ofs0_rel); + pdb_nthw_rcp_ofs1_dyn(be->p_pdb_nthw, + pdb->v9.rcp[category + i].ofs1_dyn); + pdb_nthw_rcp_ofs1_rel(be->p_pdb_nthw, + pdb->v9.rcp[category + i].ofs1_rel); + pdb_nthw_rcp_ofs2_dyn(be->p_pdb_nthw, + pdb->v9.rcp[category + i].ofs2_dyn); + pdb_nthw_rcp_ofs2_rel(be->p_pdb_nthw, + pdb->v9.rcp[category + i].ofs2_rel); + pdb_nthw_rcp_ip_prot_tnl(be->p_pdb_nthw, + pdb->v9.rcp[category + i].ip_prot_tnl); + pdb_nthw_rcp_ppc_hsh(be->p_pdb_nthw, + pdb->v9.rcp[category + i].ppc_hsh); + pdb_nthw_rcp_duplicate_en(be->p_pdb_nthw, + pdb->v9.rcp[category + i].duplicate_en); + pdb_nthw_rcp_duplicate_bit(be->p_pdb_nthw, + pdb->v9.rcp[category + i].duplicate_bit); + pdb_nthw_rcp_duplicate_bit(be->p_pdb_nthw, + pdb->v9.rcp[category + i].pcap_keep_fcs); + pdb_nthw_rcp_flush(be->p_pdb_nthw); + } + } + _CHECK_DEBUG_OFF(pdb, be->p_pdb_nthw); + return 0; +} + +static int pdb_config_flush(void *be_dev, const struct pdb_func_s *pdb) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, pdb, be->p_pdb_nthw); + + if (pdb->ver == 9) { + pdb_nthw_config_ts_format(be->p_pdb_nthw, pdb->v9.config->ts_format); + pdb_nthw_config_port_ofs(be->p_pdb_nthw, pdb->v9.config->port_ofs); + pdb_nthw_config_flush(be->p_pdb_nthw); + } + + _CHECK_DEBUG_OFF(pdb, be->p_pdb_nthw); + return 0; +} + +/* + * ***************** IOA ******************* + */ + +static bool ioa_get_present(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return be->p_ioa_nthw != NULL; +} + +static uint32_t ioa_get_version(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return (uint32_t)((module_get_major_version(be->p_ioa_nthw->m_ioa) << 16) | + (module_get_minor_version(be->p_ioa_nthw->m_ioa) & + 0xffff)); +} + +static int ioa_rcp_flush(void *be_dev, const struct ioa_func_s *ioa, + int category, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, ioa, be->p_ioa_nthw); + + if (ioa->ver == 4) { + ioa_nthw_rcp_cnt(be->p_ioa_nthw, 1); + for (int i = 0; i < cnt; i++) { + ioa_nthw_rcp_select(be->p_ioa_nthw, category + i); + ioa_nthw_rcp_tunnel_pop(be->p_ioa_nthw, + ioa->v4.rcp[category + i].tunnel_pop); + ioa_nthw_rcp_vlan_pop(be->p_ioa_nthw, + ioa->v4.rcp[category + i].vlan_pop); + ioa_nthw_rcp_vlan_push(be->p_ioa_nthw, + ioa->v4.rcp[category + i].vlan_push); + ioa_nthw_rcp_vlan_vid(be->p_ioa_nthw, + ioa->v4.rcp[category + i].vlan_vid); + ioa_nthw_rcp_vlan_dei(be->p_ioa_nthw, + ioa->v4.rcp[category + i].vlan_dei); + ioa_nthw_rcp_vlan_pcp(be->p_ioa_nthw, + ioa->v4.rcp[category + i].vlan_pcp); + ioa_nthw_rcp_vlan_tpid_sel(be->p_ioa_nthw, + ioa->v4.rcp[category + i].vlan_tpid_sel); + ioa_nthw_rcp_queue_override_en(be->p_ioa_nthw, + ioa->v4.rcp[category + i].queue_override_en); + ioa_nthw_rcp_queue_id(be->p_ioa_nthw, + ioa->v4.rcp[category + i].queue_id); + ioa_nthw_rcp_flush(be->p_ioa_nthw); + } + } + + _CHECK_DEBUG_OFF(ioa, be->p_ioa_nthw); + return 0; +} + +static int ioa_special_tpid_flush(void *be_dev, const struct ioa_func_s *ioa) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, ioa, be->p_ioa_nthw); + + if (ioa->ver == 4) { + ioa_nthw_special_vlan_tpid_cust_tpid0(be->p_ioa_nthw, + ioa->v4.tpid->cust_tpid_0); + ioa_nthw_special_vlan_tpid_cust_tpid1(be->p_ioa_nthw, + ioa->v4.tpid->cust_tpid_1); + ioa_nthw_special_vlan_tpid_flush(be->p_ioa_nthw); + } + + _CHECK_DEBUG_OFF(ioa, be->p_ioa_nthw); + return 0; +} + +static int ioa_roa_epp_flush(void *be_dev, const struct ioa_func_s *ioa, + int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, ioa, be->p_ioa_nthw); + + if (ioa->ver == 4) { + ioa_nthw_roa_epp_cnt(be->p_ioa_nthw, 1); + for (int i = 0; i < cnt; i++) { + ioa_nthw_roa_epp_select(be->p_ioa_nthw, index + i); + ioa_nthw_roa_epp_push_tunnel(be->p_ioa_nthw, + ioa->v4.roa_epp[index + i].push_tunnel); + ioa_nthw_roa_epp_tx_port(be->p_ioa_nthw, + ioa->v4.roa_epp[index + i].tx_port); + ioa_nthw_roa_epp_flush(be->p_ioa_nthw); + } + } + + _CHECK_DEBUG_OFF(ioa, be->p_ioa_nthw); + return 0; +} + +/* + * ***************** ROA ******************* + */ + +static bool roa_get_present(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return be->p_roa_nthw != NULL; +} + +static uint32_t roa_get_version(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return (uint32_t)((module_get_major_version(be->p_roa_nthw->m_roa) << 16) | + (module_get_minor_version(be->p_roa_nthw->m_roa) & + 0xffff)); +} + +static int roa_tunhdr_flush(void *be_dev, const struct roa_func_s *roa, + int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, roa, be->p_roa_nthw); + + if (roa->ver == 6) { + roa_nthw_tun_hdr_cnt(be->p_roa_nthw, 4); + for (int i = 0; i < cnt; i++) { + for (int ii = 0; ii < 4; ii++) { + roa_nthw_tun_hdr_select(be->p_roa_nthw, + index + (i * 4) + ii); + roa_nthw_tun_hdr_tunnel_hdr(be->p_roa_nthw, + &roa->v6.tunhdr[index / 4 + i] + .tunnel_hdr[ii * 4]); + roa_nthw_tun_hdr_flush(be->p_roa_nthw); + } + } + } + + _CHECK_DEBUG_OFF(roa, be->p_roa_nthw); + return 0; +} + +static int roa_tuncfg_flush(void *be_dev, const struct roa_func_s *roa, + int category, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, roa, be->p_roa_nthw); + + if (roa->ver == 6) { + roa_nthw_tun_cfg_cnt(be->p_roa_nthw, 1); + for (int i = 0; i < cnt; i++) { + roa_nthw_tun_cfg_select(be->p_roa_nthw, category + i); + roa_nthw_tun_cfg_tun_len(be->p_roa_nthw, + roa->v6.tuncfg[category + i].tun_len); + roa_nthw_tun_cfg_tun_type(be->p_roa_nthw, + roa->v6.tuncfg[category + i].tun_type); + roa_nthw_tun_cfg_tun_vlan(be->p_roa_nthw, + roa->v6.tuncfg[category + i].tun_vlan); + roa_nthw_tun_cfg_ip_type(be->p_roa_nthw, + roa->v6.tuncfg[category + i].ip_type); + roa_nthw_tun_cfg_ipcs_upd(be->p_roa_nthw, + roa->v6.tuncfg[category + i].ipcs_upd); + roa_nthw_tun_cfg_ipcs_precalc(be->p_roa_nthw, + roa->v6.tuncfg[category + i].ipcs_precalc); + roa_nthw_tun_cfg_iptl_upd(be->p_roa_nthw, + roa->v6.tuncfg[category + i].iptl_upd); + roa_nthw_tun_cfg_iptl_precalc(be->p_roa_nthw, + roa->v6.tuncfg[category + i].iptl_precalc); + roa_nthw_tun_cfg_vxlan_udp_len_upd(be->p_roa_nthw, + roa->v6.tuncfg[category + i].vxlan_udp_len_upd); + roa_nthw_tun_cfg_tx_lag_ix(be->p_roa_nthw, + roa->v6.tuncfg[category + i].tx_lag_ix); + roa_nthw_tun_cfg_recirculate(be->p_roa_nthw, + roa->v6.tuncfg[category + i].recirculate); + roa_nthw_tun_cfg_push_tunnel(be->p_roa_nthw, + roa->v6.tuncfg[category + i].push_tunnel); + roa_nthw_tun_cfg_recirc_port(be->p_roa_nthw, + roa->v6.tuncfg[category + i].recirc_port); + roa_nthw_tun_cfg_recirc_bypass(be->p_roa_nthw, + roa->v6.tuncfg[category + i].recirc_bypass); + roa_nthw_tun_cfg_flush(be->p_roa_nthw); + } + } + + _CHECK_DEBUG_OFF(roa, be->p_roa_nthw); + return 0; +} + +static int roa_config_flush(void *be_dev, const struct roa_func_s *roa) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, roa, be->p_roa_nthw); + + if (roa->ver == 6) { + roa_nthw_config_fwd_recirculate(be->p_roa_nthw, + roa->v6.config->fwd_recirculate); + roa_nthw_config_fwd_normal_pcks(be->p_roa_nthw, + roa->v6.config->fwd_normal_pcks); + roa_nthw_config_fwd_tx_port0(be->p_roa_nthw, + roa->v6.config->fwd_txport0); + roa_nthw_config_fwd_tx_port1(be->p_roa_nthw, + roa->v6.config->fwd_txport1); + roa_nthw_config_fwd_cell_builder_pcks(be->p_roa_nthw, + roa->v6.config->fwd_cellbuilder_pcks); + roa_nthw_config_fwd_non_normal_pcks(be->p_roa_nthw, + roa->v6.config->fwd_non_normal_pcks); + roa_nthw_config_flush(be->p_roa_nthw); + } + + _CHECK_DEBUG_OFF(roa, be->p_roa_nthw); + return 0; +} + +static int roa_lagcfg_flush(void *be_dev, const struct roa_func_s *roa, + int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, roa, be->p_roa_nthw); + + if (roa->ver == 6) { + roa_nthw_lag_cfg_cnt(be->p_roa_nthw, 1); + for (int i = 0; i < cnt; i++) { + roa_nthw_lag_cfg_select(be->p_roa_nthw, index + i); + roa_nthw_lag_cfg_tx_phy_port(be->p_roa_nthw, + roa->v6.lagcfg[index + i].txphy_port); + roa_nthw_lag_cfg_flush(be->p_roa_nthw); + } + } + + _CHECK_DEBUG_OFF(roa, be->p_roa_nthw); + return 0; +} + +/* + * ***************** RMC ******************* + */ + +static bool rmc_get_present(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return be->p_rmc_nthw != NULL; +} + +static uint32_t rmc_get_version(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return (uint32_t)((module_get_major_version(be->p_rmc_nthw->m_rmc) << 16) | + (module_get_minor_version(be->p_rmc_nthw->m_rmc) & + 0xffff)); +} + +static int rmc_ctrl_flush(void *be_dev, const struct rmc_func_s *rmc) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, rmc, be->p_rmc_nthw); + + if (rmc->ver == 0x10003) { + rmc_nthw_ctrl_block_statt(be->p_rmc_nthw, + rmc->v1_3.ctrl->block_statt); + rmc_nthw_ctrl_block_keep_a(be->p_rmc_nthw, + rmc->v1_3.ctrl->block_keepa); + rmc_nthw_ctrl_block_rpp_slice(be->p_rmc_nthw, + rmc->v1_3.ctrl->block_rpp_slice); + rmc_nthw_ctrl_block_mac_port(be->p_rmc_nthw, + rmc->v1_3.ctrl->block_mac_port); + rmc_nthw_ctrl_lag_phy_odd_even(be->p_rmc_nthw, + rmc->v1_3.ctrl->lag_phy_odd_even); + rmc_nthw_ctrl_flush(be->p_rmc_nthw); + } + + _CHECK_DEBUG_OFF(rmc, be->p_rmc_nthw); + return 0; +} + +/* + * ***************** TPE ******************* + */ + +static bool tpe_get_present(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + return be->p_csu_nthw != NULL && be->p_hfu_nthw != NULL && + be->p_rpp_lr_nthw != NULL && be->p_tx_cpy_nthw != NULL && + be->p_tx_ins_nthw != NULL && be->p_tx_rpl_nthw != NULL; +} + +static uint32_t tpe_get_version(void *be_dev) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + const uint32_t csu_version = + (uint32_t)((module_get_major_version(be->p_csu_nthw->m_csu) << 16) | + (module_get_minor_version(be->p_csu_nthw->m_csu) & + 0xffff)); + + const uint32_t hfu_version = + (uint32_t)((module_get_major_version(be->p_hfu_nthw->m_hfu) << 16) | + (module_get_minor_version(be->p_hfu_nthw->m_hfu) & + 0xffff)); + + const uint32_t rpp_lr_version = + (uint32_t)((module_get_major_version(be->p_rpp_lr_nthw->m_rpp_lr) + << 16) | + (module_get_minor_version(be->p_rpp_lr_nthw->m_rpp_lr) & + 0xffff)); + + const uint32_t tx_cpy_version = + (uint32_t)((module_get_major_version(be->p_tx_cpy_nthw->m_tx_cpy) + << 16) | + (module_get_minor_version(be->p_tx_cpy_nthw->m_tx_cpy) & + 0xffff)); + + const uint32_t tx_ins_version = + (uint32_t)((module_get_major_version(be->p_tx_ins_nthw->m_tx_ins) + << 16) | + (module_get_minor_version(be->p_tx_ins_nthw->m_tx_ins) & + 0xffff)); + + const uint32_t tx_rpl_version = + (uint32_t)((module_get_major_version(be->p_tx_rpl_nthw->m_tx_rpl) + << 16) | + (module_get_minor_version(be->p_tx_rpl_nthw->m_tx_rpl) & + 0xffff)); + + if (csu_version == 0 && hfu_version == 1 && rpp_lr_version == 0 && + tx_cpy_version == 1 && tx_ins_version == 1 && tx_rpl_version == 2) + return 1; + + if (csu_version == 0 && hfu_version == 1 && rpp_lr_version == 1 && + tx_cpy_version == 1 && tx_ins_version == 1 && tx_rpl_version == 2) + return 2; + + assert(false); + return 0; +} + +static int tpe_rpp_rcp_flush(void *be_dev, const struct tpe_func_s *rpp_lr, + int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, rpp_lr, be->p_rpp_lr_nthw); + + if (rpp_lr->ver >= 1) { + rpp_lr_nthw_rcp_cnt(be->p_rpp_lr_nthw, 1); + for (int i = 0; i < cnt; i++) { + rpp_lr_nthw_rcp_select(be->p_rpp_lr_nthw, index + i); + rpp_lr_nthw_rcp_exp(be->p_rpp_lr_nthw, + rpp_lr->v1.rpp_rcp[index + i].exp); + rpp_lr_nthw_rcp_flush(be->p_rpp_lr_nthw); + } + } + + _CHECK_DEBUG_OFF(rpp_lr, be->p_rpp_lr_nthw); + return 0; +} + +static int tpe_rpp_ifr_rcp_flush(void *be_dev, const struct tpe_func_s *rpp_lr, + int index, int cnt) +{ + int res = 0; + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, rpp_lr, be->p_rpp_lr_nthw); + + if (rpp_lr->ver >= 2) { + rpp_lr_nthw_ifr_rcp_cnt(be->p_rpp_lr_nthw, 1); + for (int i = 0; i < cnt; i++) { + rpp_lr_nthw_ifr_rcp_select(be->p_rpp_lr_nthw, index + i); + rpp_lr_nthw_ifr_rcp_en(be->p_rpp_lr_nthw, + rpp_lr->v2.rpp_ifr_rcp[index + i].en); + rpp_lr_nthw_ifr_rcp_mtu(be->p_rpp_lr_nthw, + rpp_lr->v2.rpp_ifr_rcp[index + i].mtu); + rpp_lr_nthw_ifr_rcp_flush(be->p_rpp_lr_nthw); + } + } else { + res = -1; + } + _CHECK_DEBUG_OFF(rpp_lr, be->p_rpp_lr_nthw); + return res; +} + +static int tpe_ifr_rcp_flush(void *be_dev, const struct tpe_func_s *ifr, + int index, int cnt) +{ + int res = 0; + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, ifr, be->p_ifr_nthw); + + if (ifr->ver >= 2) { + ifr_nthw_rcp_cnt(be->p_ifr_nthw, 1); + for (int i = 0; i < cnt; i++) { + ifr_nthw_rcp_select(be->p_ifr_nthw, index + i); + ifr_nthw_rcp_en(be->p_ifr_nthw, + ifr->v2.ifr_rcp[index + i].en); + ifr_nthw_rcp_mtu(be->p_ifr_nthw, + ifr->v2.ifr_rcp[index + i].mtu); + ifr_nthw_rcp_flush(be->p_ifr_nthw); + } + } else { + res = -1; + } + _CHECK_DEBUG_OFF(ifr, be->p_ifr_nthw); + return res; +} + +static int tpe_ins_rcp_flush(void *be_dev, const struct tpe_func_s *tx_ins, + int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, tx_ins, be->p_tx_ins_nthw); + + if (tx_ins->ver >= 1) { + tx_ins_nthw_rcp_cnt(be->p_tx_ins_nthw, 1); + for (int i = 0; i < cnt; i++) { + tx_ins_nthw_rcp_select(be->p_tx_ins_nthw, index + i); + tx_ins_nthw_rcp_dyn(be->p_tx_ins_nthw, + tx_ins->v1.ins_rcp[index + i].dyn); + tx_ins_nthw_rcp_ofs(be->p_tx_ins_nthw, + tx_ins->v1.ins_rcp[index + i].ofs); + tx_ins_nthw_rcp_len(be->p_tx_ins_nthw, + tx_ins->v1.ins_rcp[index + i].len); + tx_ins_nthw_rcp_flush(be->p_tx_ins_nthw); + } + } + + _CHECK_DEBUG_OFF(tx_ins, be->p_tx_ins_nthw); + return 0; +} + +static int tpe_rpl_rcp_flush(void *be_dev, const struct tpe_func_s *tx_rpl, + int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, tx_rpl, be->p_tx_rpl_nthw); + + if (tx_rpl->ver >= 1) { + tx_rpl_nthw_rcp_cnt(be->p_tx_rpl_nthw, 1); + for (int i = 0; i < cnt; i++) { + tx_rpl_nthw_rcp_select(be->p_tx_rpl_nthw, index + i); + tx_rpl_nthw_rcp_dyn(be->p_tx_rpl_nthw, + tx_rpl->v1.rpl_rcp[index + i].dyn); + tx_rpl_nthw_rcp_ofs(be->p_tx_rpl_nthw, + tx_rpl->v1.rpl_rcp[index + i].ofs); + tx_rpl_nthw_rcp_len(be->p_tx_rpl_nthw, + tx_rpl->v1.rpl_rcp[index + i].len); + tx_rpl_nthw_rcp_rpl_ptr(be->p_tx_rpl_nthw, + tx_rpl->v1.rpl_rcp[index + i].rpl_ptr); + tx_rpl_nthw_rcp_ext_prio(be->p_tx_rpl_nthw, + tx_rpl->v1.rpl_rcp[index + i].ext_prio); + tx_rpl_nthw_rcp_flush(be->p_tx_rpl_nthw); + } + } + + _CHECK_DEBUG_OFF(tx_rpl, be->p_tx_rpl_nthw); + return 0; +} + +static int tpe_rpl_ext_flush(void *be_dev, const struct tpe_func_s *tx_rpl, + int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, tx_rpl, be->p_tx_rpl_nthw); + + if (tx_rpl->ver >= 1) { + tx_rpl_nthw_ext_cnt(be->p_tx_rpl_nthw, 1); + for (int i = 0; i < cnt; i++) { + tx_rpl_nthw_ext_select(be->p_tx_rpl_nthw, index + i); + tx_rpl_nthw_ext_rpl_ptr(be->p_tx_rpl_nthw, + tx_rpl->v1.rpl_ext[index + i].rpl_ptr); + tx_rpl_nthw_ext_flush(be->p_tx_rpl_nthw); + } + } + + _CHECK_DEBUG_OFF(tx_rpl, be->p_tx_rpl_nthw); + return 0; +} + +static int tpe_rpl_rpl_flush(void *be_dev, const struct tpe_func_s *tx_rpl, + int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, tx_rpl, be->p_tx_rpl_nthw); + + if (tx_rpl->ver >= 1) { + tx_rpl_nthw_rpl_cnt(be->p_tx_rpl_nthw, 1); + for (int i = 0; i < cnt; i++) { + tx_rpl_nthw_rpl_select(be->p_tx_rpl_nthw, index + i); + tx_rpl_nthw_rpl_value(be->p_tx_rpl_nthw, + tx_rpl->v1.rpl_rpl[index + i].value); + tx_rpl_nthw_rpl_flush(be->p_tx_rpl_nthw); + } + } + + _CHECK_DEBUG_OFF(tx_rpl, be->p_tx_rpl_nthw); + return 0; +} + +static int tpe_cpy_rcp_flush(void *be_dev, const struct tpe_func_s *tx_cpy, + int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + unsigned int wr_index = -1; + + _CHECK_DEBUG_ON(be, tx_cpy, be->p_tx_cpy_nthw); + + if (tx_cpy->ver >= 1) { + for (int i = 0; i < cnt; i++) { + if (wr_index != + (index + i) / tx_cpy->nb_rcp_categories) { + wr_index = + (index + i) / tx_cpy->nb_rcp_categories; + tx_cpy_nthw_writer_cnt(be->p_tx_cpy_nthw, wr_index, + 1); + } + + tx_cpy_nthw_writer_select(be->p_tx_cpy_nthw, wr_index, + (index + i) % tx_cpy->nb_rcp_categories); + tx_cpy_nthw_writer_reader_select(be->p_tx_cpy_nthw, wr_index, + tx_cpy->v1.cpy_rcp[index + i].reader_select); + tx_cpy_nthw_writer_dyn(be->p_tx_cpy_nthw, wr_index, + tx_cpy->v1.cpy_rcp[index + i].dyn); + tx_cpy_nthw_writer_ofs(be->p_tx_cpy_nthw, wr_index, + tx_cpy->v1.cpy_rcp[index + i].ofs); + tx_cpy_nthw_writer_len(be->p_tx_cpy_nthw, wr_index, + tx_cpy->v1.cpy_rcp[index + i].len); + tx_cpy_nthw_writer_flush(be->p_tx_cpy_nthw, wr_index); + } + } + + _CHECK_DEBUG_OFF(tx_cpy, be->p_tx_cpy_nthw); + return 0; +} + +static int tpe_hfu_rcp_flush(void *be_dev, const struct tpe_func_s *hfu, + int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, hfu, be->p_hfu_nthw); + + if (hfu->ver >= 1) { + hfu_nthw_rcp_cnt(be->p_hfu_nthw, 1); + for (int i = 0; i < cnt; i++) { + hfu_nthw_rcp_select(be->p_hfu_nthw, index + i); + hfu_nthw_rcp_len_a_wr(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_a_wr); + hfu_nthw_rcp_len_a_ol4len(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_a_outer_l4_len); + hfu_nthw_rcp_len_a_pos_dyn(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_a_pos_dyn); + hfu_nthw_rcp_len_a_pos_ofs(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_a_pos_ofs); + hfu_nthw_rcp_len_a_add_dyn(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_a_add_dyn); + hfu_nthw_rcp_len_a_add_ofs(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_a_add_ofs); + hfu_nthw_rcp_len_a_sub_dyn(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_a_sub_dyn); + hfu_nthw_rcp_len_b_wr(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_b_wr); + hfu_nthw_rcp_len_b_pos_dyn(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_b_pos_dyn); + hfu_nthw_rcp_len_b_pos_ofs(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_b_pos_ofs); + hfu_nthw_rcp_len_b_add_dyn(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_b_add_dyn); + hfu_nthw_rcp_len_b_add_ofs(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_b_add_ofs); + hfu_nthw_rcp_len_b_sub_dyn(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_b_sub_dyn); + hfu_nthw_rcp_len_c_wr(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_c_wr); + hfu_nthw_rcp_len_c_pos_dyn(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_c_pos_dyn); + hfu_nthw_rcp_len_c_pos_ofs(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_c_pos_ofs); + hfu_nthw_rcp_len_c_add_dyn(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_c_add_dyn); + hfu_nthw_rcp_len_c_add_ofs(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_c_add_ofs); + hfu_nthw_rcp_len_c_sub_dyn(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].len_c_sub_dyn); + hfu_nthw_rcp_ttl_wr(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].ttl_wr); + hfu_nthw_rcp_ttl_pos_dyn(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].ttl_pos_dyn); + hfu_nthw_rcp_ttl_pos_ofs(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].ttl_pos_ofs); + hfu_nthw_rcp_csinf(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].cs_inf); + hfu_nthw_rcp_l3prt(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].l3_prt); + hfu_nthw_rcp_l3frag(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].l3_frag); + hfu_nthw_rcp_tunnel(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].tunnel); + hfu_nthw_rcp_l4prt(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].l4_prt); + hfu_nthw_rcp_ol3ofs(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].outer_l3_ofs); + hfu_nthw_rcp_ol4ofs(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].outer_l4_ofs); + hfu_nthw_rcp_il3ofs(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].inner_l3_ofs); + hfu_nthw_rcp_il4ofs(be->p_hfu_nthw, + hfu->v1.hfu_rcp[index + i].inner_l4_ofs); + hfu_nthw_rcp_flush(be->p_hfu_nthw); + } + } + + _CHECK_DEBUG_OFF(hfu, be->p_hfu_nthw); + return 0; +} + +static int tpe_csu_rcp_flush(void *be_dev, const struct tpe_func_s *csu, + int index, int cnt) +{ + struct backend_dev_s *be = (struct backend_dev_s *)be_dev; + + _CHECK_DEBUG_ON(be, csu, be->p_csu_nthw); + + if (csu->ver >= 1) { + csu_nthw_rcp_cnt(be->p_csu_nthw, 1); + for (int i = 0; i < cnt; i++) { + csu_nthw_rcp_select(be->p_csu_nthw, index + i); + csu_nthw_rcp_outer_l3_cmd(be->p_csu_nthw, + csu->v1.csu_rcp[index + i].ol3_cmd); + csu_nthw_rcp_outer_l4_cmd(be->p_csu_nthw, + csu->v1.csu_rcp[index + i].ol4_cmd); + csu_nthw_rcp_inner_l3_cmd(be->p_csu_nthw, + csu->v1.csu_rcp[index + i].il3_cmd); + csu_nthw_rcp_inner_l4_cmd(be->p_csu_nthw, + csu->v1.csu_rcp[index + i].il4_cmd); + csu_nthw_rcp_flush(be->p_csu_nthw); + } + } + + _CHECK_DEBUG_OFF(csu, be->p_csu_nthw); + return 0; +} + +/* + * ***************** DBS ******************* + */ + +static int alloc_rx_queue(void *be_dev, int queue_id) +{ + (void)be_dev; + (void)queue_id; + printf("ERROR alloc Rx queue\n"); + return -1; +} + +static int free_rx_queue(void *be_dev, int hw_queue) +{ + (void)be_dev; + (void)hw_queue; + printf("ERROR free Rx queue\n"); + return 0; +} + +const struct flow_api_backend_ops flow_be_iface = { + 1, + + set_debug_mode, + get_nb_phy_ports, + get_nb_rx_ports, + get_ltx_avail, + get_nb_cat_funcs, + get_nb_categories, + get_nb_cat_km_if_cnt, + get_nb_cat_km_if_m0, + get_nb_cat_km_if_m1, + get_nb_queues, + get_nb_km_flow_types, + get_nb_pm_ext, + get_nb_len, + get_kcc_size, + get_kcc_banks, + get_nb_km_categories, + get_nb_km_cam_banks, + get_nb_km_cam_record_words, + get_nb_km_cam_records, + get_nb_km_tcam_banks, + get_nb_km_tcam_bank_width, + get_nb_flm_categories, + get_nb_flm_size_mb, + get_nb_flm_entry_size, + get_nb_flm_variant, + get_nb_flm_prios, + get_nb_flm_pst_profiles, + get_nb_hst_categories, + get_nb_qsl_categories, + get_nb_qsl_qst_entries, + get_nb_pdb_categories, + get_nb_ioa_categories, + get_nb_roa_categories, + get_nb_tpe_categories, + get_nb_tx_cpy_writers, + get_nb_tx_cpy_mask_mem, + get_nb_tx_rpl_depth, + get_nb_tx_rpl_ext_categories, + get_nb_tpe_ifr_categories, + + alloc_rx_queue, + free_rx_queue, + + cat_get_present, + cat_get_version, + cat_cfn_flush, + + cat_kce_flush, + cat_kcs_flush, + cat_fte_flush, + + cat_cte_flush, + cat_cts_flush, + cat_cot_flush, + cat_cct_flush, + cat_exo_flush, + cat_rck_flush, + cat_len_flush, + cat_kcc_flush, + cat_cce_flush, + cat_ccs_flush, + + km_get_present, + km_get_version, + km_rcp_flush, + km_cam_flush, + km_tcam_flush, + km_tci_flush, + km_tcq_flush, + + flm_get_present, + flm_get_version, + flm_control_flush, + flm_status_flush, + flm_status_update, + flm_timeout_flush, + flm_scrub_flush, + flm_load_bin_flush, + flm_load_pps_flush, + flm_load_lps_flush, + flm_load_aps_flush, + flm_prio_flush, + flm_pst_flush, + flm_rcp_flush, + flm_buf_ctrl_update, + flm_stat_update, + flm_lrn_data_flush, + flm_inf_data_update, + flm_sta_data_update, + + hsh_get_present, + hsh_get_version, + hsh_rcp_flush, + + hst_get_present, + hst_get_version, + hst_rcp_flush, + + qsl_get_present, + qsl_get_version, + qsl_rcp_flush, + qsl_qst_flush, + qsl_qen_flush, + qsl_unmq_flush, + + slc_get_present, + slc_get_version, + slc_rcp_flush, + + slc_lr_get_present, + slc_lr_get_version, + slc_lr_rcp_flush, + + pdb_get_present, + pdb_get_version, + pdb_rcp_flush, + pdb_config_flush, + + ioa_get_present, + ioa_get_version, + ioa_rcp_flush, + ioa_special_tpid_flush, + ioa_roa_epp_flush, + + roa_get_present, + roa_get_version, + roa_tunhdr_flush, + roa_tuncfg_flush, + roa_config_flush, + roa_lagcfg_flush, + + rmc_get_present, + rmc_get_version, + rmc_ctrl_flush, + + tpe_get_present, + tpe_get_version, + tpe_rpp_rcp_flush, + tpe_rpp_ifr_rcp_flush, + tpe_ifr_rcp_flush, + tpe_ins_rcp_flush, + tpe_rpl_rcp_flush, + tpe_rpl_ext_flush, + tpe_rpl_rpl_flush, + tpe_cpy_rcp_flush, + tpe_hfu_rcp_flush, + tpe_csu_rcp_flush, +}; + +const struct flow_api_backend_ops *bin_flow_backend_init(nt_fpga_t *p_fpga, + void **dev) +{ + uint8_t physical_adapter_no = (uint8_t)p_fpga->p_fpga_info->adapter_no; + + struct info_nthw *pinfonthw = info_nthw_new(); + + info_nthw_init(pinfonthw, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_info_nthw = pinfonthw; + + /* Init nthw CAT */ + if (cat_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct cat_nthw *pcatnthw = cat_nthw_new(); + + cat_nthw_init(pcatnthw, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_cat_nthw = pcatnthw; + } else { + be_devs[physical_adapter_no].p_cat_nthw = NULL; + } + /* Init nthw KM */ + if (km_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct km_nthw *pkmnthw = km_nthw_new(); + + km_nthw_init(pkmnthw, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_km_nthw = pkmnthw; + } else { + be_devs[physical_adapter_no].p_km_nthw = NULL; + } + /* Init nthw FLM */ + if (flm_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct flm_nthw *pflmnthw = flm_nthw_new(); + + flm_nthw_init(pflmnthw, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_flm_nthw = pflmnthw; + } else { + be_devs[physical_adapter_no].p_flm_nthw = NULL; + } + /* Init nthw IFR */ + if (ifr_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct ifr_nthw *ifrnthw = ifr_nthw_new(); + + ifr_nthw_init(ifrnthw, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_ifr_nthw = ifrnthw; + } else { + be_devs[physical_adapter_no].p_ifr_nthw = NULL; + } + /* Init nthw HSH */ + if (hsh_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct hsh_nthw *phshnthw = hsh_nthw_new(); + + hsh_nthw_init(phshnthw, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_hsh_nthw = phshnthw; + } else { + be_devs[physical_adapter_no].p_hsh_nthw = NULL; + } + /* Init nthw HST */ + if (hst_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct hst_nthw *phstnthw = hst_nthw_new(); + + hst_nthw_init(phstnthw, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_hst_nthw = phstnthw; + } else { + be_devs[physical_adapter_no].p_hst_nthw = NULL; + } + /* Init nthw QSL */ + if (qsl_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct qsl_nthw *pqslnthw = qsl_nthw_new(); + + qsl_nthw_init(pqslnthw, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_qsl_nthw = pqslnthw; + } else { + be_devs[physical_adapter_no].p_qsl_nthw = NULL; + } + /* Init nthw SLC */ + if (slc_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct slc_nthw *pslcnthw = slc_nthw_new(); + + slc_nthw_init(pslcnthw, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_slc_nthw = pslcnthw; + } else { + be_devs[physical_adapter_no].p_slc_nthw = NULL; + } + /* Init nthw SLC LR */ + if (slc_lr_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct slc_lr_nthw *pslclrnthw = slc_lr_nthw_new(); + + slc_lr_nthw_init(pslclrnthw, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_slc_lr_nthw = pslclrnthw; + } else { + be_devs[physical_adapter_no].p_slc_lr_nthw = NULL; + } + /* Init nthw PDB */ + if (pdb_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct pdb_nthw *ppdbnthw = pdb_nthw_new(); + + pdb_nthw_init(ppdbnthw, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_pdb_nthw = ppdbnthw; + } else { + be_devs[physical_adapter_no].p_pdb_nthw = NULL; + } + /* Init nthw IOA */ + if (ioa_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct ioa_nthw *pioanthw = ioa_nthw_new(); + + ioa_nthw_init(pioanthw, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_ioa_nthw = pioanthw; + } else { + be_devs[physical_adapter_no].p_ioa_nthw = NULL; + } + /* Init nthw ROA */ + if (roa_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct roa_nthw *proanthw = roa_nthw_new(); + + roa_nthw_init(proanthw, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_roa_nthw = proanthw; + } else { + be_devs[physical_adapter_no].p_roa_nthw = NULL; + } + /* Init nthw RMC */ + if (rmc_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct rmc_nthw *prmcnthw = rmc_nthw_new(); + + rmc_nthw_init(prmcnthw, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_rmc_nthw = prmcnthw; + } else { + be_devs[physical_adapter_no].p_rmc_nthw = NULL; + } + /* Init nthw HFU */ + if (hfu_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct hfu_nthw *ptr = hfu_nthw_new(); + + hfu_nthw_init(ptr, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_hfu_nthw = ptr; + } else { + be_devs[physical_adapter_no].p_hfu_nthw = NULL; + } + /* Init nthw RPP_LR */ + if (rpp_lr_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct rpp_lr_nthw *ptr = rpp_lr_nthw_new(); + + rpp_lr_nthw_init(ptr, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_rpp_lr_nthw = ptr; + } else { + be_devs[physical_adapter_no].p_rpp_lr_nthw = NULL; + } + /* Init nthw TX_CPY */ + if (tx_cpy_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct tx_cpy_nthw *ptr = tx_cpy_nthw_new(); + + tx_cpy_nthw_init(ptr, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_tx_cpy_nthw = ptr; + } else { + be_devs[physical_adapter_no].p_tx_cpy_nthw = NULL; + } + /* Init nthw CSU */ + if (csu_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct csu_nthw *ptr = csu_nthw_new(); + + csu_nthw_init(ptr, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_csu_nthw = ptr; + } else { + be_devs[physical_adapter_no].p_csu_nthw = NULL; + } + /* Init nthw TX_INS */ + if (tx_ins_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct tx_ins_nthw *ptr = tx_ins_nthw_new(); + + tx_ins_nthw_init(ptr, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_tx_ins_nthw = ptr; + } else { + be_devs[physical_adapter_no].p_tx_ins_nthw = NULL; + } + /* Init nthw TX_RPL */ + if (tx_rpl_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) { + struct tx_rpl_nthw *ptr = tx_rpl_nthw_new(); + + tx_rpl_nthw_init(ptr, p_fpga, physical_adapter_no); + be_devs[physical_adapter_no].p_tx_rpl_nthw = ptr; + } else { + be_devs[physical_adapter_no].p_tx_rpl_nthw = NULL; + } + be_devs[physical_adapter_no].adapter_no = physical_adapter_no; + *dev = (void *)&be_devs[physical_adapter_no]; + + return &flow_be_iface; +} + +void bin_flow_backend_done(void *dev) +{ + struct backend_dev_s *be_dev = (struct backend_dev_s *)dev; + + info_nthw_delete(be_dev->p_info_nthw); + cat_nthw_delete(be_dev->p_cat_nthw); + km_nthw_delete(be_dev->p_km_nthw); + flm_nthw_delete(be_dev->p_flm_nthw); + hsh_nthw_delete(be_dev->p_hsh_nthw); + hst_nthw_delete(be_dev->p_hst_nthw); + qsl_nthw_delete(be_dev->p_qsl_nthw); + slc_nthw_delete(be_dev->p_slc_nthw); + slc_lr_nthw_delete(be_dev->p_slc_lr_nthw); + pdb_nthw_delete(be_dev->p_pdb_nthw); + ioa_nthw_delete(be_dev->p_ioa_nthw); + roa_nthw_delete(be_dev->p_roa_nthw); + rmc_nthw_delete(be_dev->p_rmc_nthw); + csu_nthw_delete(be_dev->p_csu_nthw); + hfu_nthw_delete(be_dev->p_hfu_nthw); + rpp_lr_nthw_delete(be_dev->p_rpp_lr_nthw); + tx_cpy_nthw_delete(be_dev->p_tx_cpy_nthw); + tx_ins_nthw_delete(be_dev->p_tx_ins_nthw); + tx_rpl_nthw_delete(be_dev->p_tx_rpl_nthw); +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_backend.h b/drivers/net/ntnic/nthw/flow_filter/flow_backend.h new file mode 100644 index 0000000000..17fdcada3f --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_backend.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_BACKEND_H__ +#define __FLOW_BACKEND_H__ + +#include /* uint8_t */ +#include "nthw_fpga_model.h" + +const struct flow_api_backend_ops *bin_flow_backend_init(nt_fpga_t *p_fpga, + void **be_dev); +void bin_flow_backend_done(void *be_dev); + +#endif /* __FLOW_BACKEND_H__ */ diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_filter.c b/drivers/net/ntnic/nthw/flow_filter/flow_filter.c new file mode 100644 index 0000000000..90aeb71bd7 --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_filter.c @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nthw_drv.h" +#include "flow_filter.h" +#include "flow_api_backend.h" +#include "flow_backend.h" +#include "flow_api_nic_setup.h" + +int flow_filter_init(nt_fpga_t *p_fpga, struct flow_nic_dev **p_flow_device, + int adapter_no) +{ + void *be_dev = NULL; + struct flow_nic_dev *flow_nic; + + NT_LOG(DBG, FILTER, "Initializing flow filter api\n"); + const struct flow_api_backend_ops *iface = + bin_flow_backend_init(p_fpga, &be_dev); + + flow_nic = flow_api_create((uint8_t)adapter_no, iface, be_dev); + if (!flow_nic) { + *p_flow_device = NULL; + return -1; + } + *p_flow_device = flow_nic; + return 0; +} + +int flow_filter_done(struct flow_nic_dev *dev) +{ + void *be_dev = flow_api_get_be_dev(dev); + + int res = flow_api_done(dev); + + if (be_dev) + bin_flow_backend_done(be_dev); + return res; +} diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_filter.h b/drivers/net/ntnic/nthw/flow_filter/flow_filter.h new file mode 100644 index 0000000000..8ea21a614a --- /dev/null +++ b/drivers/net/ntnic/nthw/flow_filter/flow_filter.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __FLOW_FILTER_HPP__ +#define __FLOW_FILTER_HPP__ +#undef USE_OPAE + +#include "nthw_fpga_model.h" +#include "flow_api.h" + +int flow_filter_init(nt_fpga_t *p_fpga, struct flow_nic_dev **p_flow_device, + int adapter_no); +int flow_filter_done(struct flow_nic_dev *dev); + +#endif /* __FLOW_FILTER_HPP__ */ From patchwork Mon Aug 21 13:54:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mykola Kostenok X-Patchwork-Id: 130583 X-Patchwork-Delegate: thomas@monjalon.net 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 30EC2430C1; Mon, 21 Aug 2023 15:55:40 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 3B14543274; Mon, 21 Aug 2023 15:54:48 +0200 (CEST) Received: from egress-ip33a.ess.de.barracuda.com (egress-ip33a.ess.de.barracuda.com [18.185.115.192]) by mails.dpdk.org (Postfix) with ESMTP id 00F5643269 for ; Mon, 21 Aug 2023 15:54:44 +0200 (CEST) Received: from EUR04-DB3-obe.outbound.protection.outlook.com (mail-db3eur04lp2051.outbound.protection.outlook.com [104.47.12.51]) by mx-outbound43-64.eu-central-1c.ess.aws.cudaops.com (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 21 Aug 2023 13:54:43 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=JLhQo5+duQcwG6LdHl0mh7AAVAiAwh69TSizV+joEFUqbshRpU253I5Kzml2AZIWN4SQT0bAKwoU3yBo5Ena+2szxUVLQTLKXPO2ZnqqMlIN2lw5SN73aY3NPf+HXHsMLpz5jorIq/v0n3FWpVMW3ZskDdjq386BWc1lOTFIpZ7KJ2UFUURqc67rrTWATOqBBZMuZdXRNbUY1QdVxN0Q4LaemhYutKwQ6KzzODljjJ04+wLo3S7NJWXWKdrzAGrG9PgKT0V2P3ExwAjysSRmgFlIud06u59jPtAX2w5AP6tutiqTn0mA15pwbOKLGR45CBgjC4KvHK0rufqX1ltueA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=N53NNK6CGeDsWjW5nI4r+8pZp8HyJqK5eiBOlENKrq8=; b=kOHaKfts1WJp5qzxY3+xqYJnRll+1QWDU2anIHocjaHIpn0zAS8DwmNOu5lauABRGXARLgCKHxeHtoJqO+GMTwu5JXGVuDvlvZAWa9OctVjVVxWz3dhO1pWoUWBhwrWPe6l+aE8K0+fgP2r5w+LXFq3nazRaX/hbUXNzBnqAuFxXwwmlhZhTYDem07ntA3yqQLhXuFmyre4ZEJXA+aM6jpVF7JDZ/MZRDnSE564veIrfOAuPx2qF77LTN155tuGDkFiE+h/ahGa81IPUU5JvwbOKKF20pxHNSWqEjfsG1Or1jHszAT6y0O9YSF5eI1DkxGY4bAsOivY/EqoQf+fM+g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=fail (sender ip is 178.72.21.4) smtp.rcpttodomain=dpdk.org smtp.mailfrom=napatech.com; dmarc=fail (p=none sp=none pct=100) action=none header.from=napatech.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=napatech.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=N53NNK6CGeDsWjW5nI4r+8pZp8HyJqK5eiBOlENKrq8=; b=irCifk6cU6QPfB5DPIkBRSP+ITyhNHQ8U21pGma3URQG9iUrvjVJpY2hzdG6EykRIImAADdbOYp55kbcUDFYNwzaMJm55btUJmQcPLh5KHOeb0SVzwjakmJx3iw90ttnpUErQp4bLcwO61/2BpyvryTdbMpnnb/3ncXfhKqEIOo= Received: from DB8PR04CA0002.eurprd04.prod.outlook.com (2603:10a6:10:110::12) by DBAP190MB0950.EURP190.PROD.OUTLOOK.COM (2603:10a6:10:1b0::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.20; Mon, 21 Aug 2023 13:54:30 +0000 Received: from DU2PEPF0001E9C5.eurprd03.prod.outlook.com (2603:10a6:10:110:cafe::b6) by DB8PR04CA0002.outlook.office365.com (2603:10a6:10:110::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.20 via Frontend Transport; Mon, 21 Aug 2023 13:54:30 +0000 X-MS-Exchange-Authentication-Results: spf=fail (sender IP is 178.72.21.4) smtp.mailfrom=napatech.com; dkim=none (message not signed) header.d=none;dmarc=fail action=none header.from=napatech.com; Received-SPF: Fail (protection.outlook.com: domain of napatech.com does not designate 178.72.21.4 as permitted sender) receiver=protection.outlook.com; client-ip=178.72.21.4; helo=localhost.localdomain.com; Received: from localhost.localdomain.com (178.72.21.4) by DU2PEPF0001E9C5.mail.protection.outlook.com (10.167.8.74) with Microsoft SMTP Server id 15.20.6699.14 via Frontend Transport; Mon, 21 Aug 2023 13:54:30 +0000 From: Mykola Kostenok To: dev@dpdk.org, mko-plv@napatech.com Cc: ckm@napatech.com Subject: [PATCH v6 7/8] net/ntnic: adds ethdev and makes PMD available Date: Mon, 21 Aug 2023 15:54:25 +0200 Message-Id: <20230821135426.1478754-7-mko-plv@napatech.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20230821135426.1478754-1-mko-plv@napatech.com> References: <20230816132552.2483752-1-mko-plv@napatech.com> <20230821135426.1478754-1-mko-plv@napatech.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU2PEPF0001E9C5:EE_|DBAP190MB0950:EE_ X-MS-Office365-Filtering-Correlation-Id: d9fa5495-2c11-43e9-c395-08dba24e2498 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: hfB0F5Us0df7GxS5+2KKaQfDyN7P/zEDRoGZMS301qh5NbJ66ygegFdRggbZD2kJwMYOyNs6QRhs3yAvUx5uAybvv8HOQf0clSnE6h/rnrW5HaCbt+uB/jxOazmxWC3H4s57x0AIxr4/XiOLc3ScYYw3rq+Xp3gCzpSzMjTCzG+FmKs7DHpylKDT4ctgsiChsqZ+RByzlL0WDkh9Fg4uOCG58J6PB18ipPLRjxBIX3KhICs1ipS37nRYEDLP08sTo700hX9ddarDO05PwheHEjjxSBcMVbR33kNUMMTBc1IvX3WWE0y8BSzffNjxIY1Z44/hXoSdRB+WbVocBWhOaYMxsaxoUyabuswZBqJ4fl5kqCJJfLKagNO8e/hqXZDm6oVImYi6QRWNMYprL2vKdwGVR21Pd7VNtAP+wwgM6DqjUwq3wzvFilDV1jUTXVydHVKksEq9lhO0jFR5sho/W1J0WhpHbAxLR/64bS1lfEKQNaLlF74IKvqgtQm8NVlVma5U7pgxuwv6Wnlm7/pIb3I1zrK9a2CPMBo+XTIqU+kKAaxpsDQBAkRLOV9dXuBVbPgvud3OV/1Z4z1kI5slZXqg7DZomvYb5YyN/xnqR3euDs0MvkFvFtSx+WelL7rMuO3Yx1xYktjh4Sv7reUwihwTJ5E4bx/y7JWb1H/aqiOYB47o8wmTH1sjVPM1ccQdGdW96jZ0+mDsFqwQc6Rh2ixV9ept2N9Dx+GDnh8n3HgHM6T8Mvs4UKk9qrKcj7Qra5GV199DdfUV2+GeH1TvGucTD3T1PkuAJ1EAu0cSbhJnXmd83OUgcyj7gd5DZQEfBh1YrUUG0GfvICtEVgK3gw== X-Forefront-Antispam-Report: CIP:178.72.21.4; CTRY:DK; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:localhost.localdomain.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230031)(6069001)(396003)(39830400003)(346002)(136003)(376002)(1800799009)(451199024)(82310400011)(186009)(36840700001)(46966006)(478600001)(107886003)(1076003)(956004)(336012)(6666004)(26005)(6486002)(47076005)(34020700004)(6512007)(36860700001)(2616005)(4326008)(8936002)(83380400001)(30864003)(5660300002)(118246002)(8676002)(2906002)(6506007)(316002)(41300700001)(70586007)(70206006)(356005)(36736006)(36756003)(9316004)(40480700001)(86362001)(66899024)(81166007)(21314003)(36900700001)(579004)(559001)(309714004); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: aGl/MZWNOgBGtQN4jB61wKU4aokyy3GtrmXCBWug5phG5ZywWkF1LOx0Lqyya9xY8zEWjS+zrENwNjKj6svYxGCMgV6z8q1x5gH6B08XkHufVPWM2OBhAJkqx72n2v1cNyWZn7LKx4iubdklm/mXqATjM1p8ZUqqfZ/Ww84wX1wagX5kQU2TK//Pp/7PQFTjeCbmCDS3ilLuB5Th4NVMq/h0SqBKExeRKoI7N5ulcbxnyzb+GkFgZnQuUnRlKOf/PkWGqIS7ksDO97evG+TVajeiGxOeDg3g4m5Z9t1gYCqBd5ElSvpHe3YTztG2QycoUP4JjH5BZmUlGjWFMlv9dIOzqTLwDJDo8dWX+1FyPQgcKBMwRMe0x7uZMipx5kTQwY2MstHbbzp852OdRQnsSTwP7T9wjLGmxnlPAgbsj5drP176i8TDg2hLBF5DyX2+j/IvLlnD1OlGCrn8ptO5YrOFKQovD3/mPiqIzmObXD3czstZ0ar4tnZbMlXMHtsXC8BlDzkZN5VU2kQao0BFmjHHewvuI76uJVGAfQIj2+X1ip3EfVRVCfwRy0zv59mOKXKt1mrRa7z09Ub5U5zWj5Dg5WOJd3L/hvVorBjRHh5FogvWdY8xPV6Mfes9PJiDjUKy6D6RROAja8Z8AHXs4rPR0MsNBQA5Uv+b2RdUBhj2YkYlBPGj7XBMv3ErvwUfBIduJOn8QhUaVM+mW3/H/I2CZqXuHDD1hNDpyZSDaQwk9MaofHDOEovLLS5IfQClD6jC+EK9kEHGCCV3hQ6SgjiyXRx1P6jyqi+W6bnGaaA= X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Aug 2023 13:54:30.6478 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: d9fa5495-2c11-43e9-c395-08dba24e2498 X-MS-Exchange-CrossTenant-Id: c4540d0b-728a-4233-9da5-9ea30c7ec3ed X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=c4540d0b-728a-4233-9da5-9ea30c7ec3ed; Ip=[178.72.21.4]; Helo=[localhost.localdomain.com] X-MS-Exchange-CrossTenant-AuthSource: DU2PEPF0001E9C5.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBAP190MB0950 X-BESS-ID: 1692626083-311072-12504-15887-1 X-BESS-VER: 2019.1_20230817.1828 X-BESS-Apparent-Source-IP: 104.47.12.51 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKVsbmRiYGFkB2BlDYNMkyOSnJ0C DV2MQixcTQJCkxNdE42dLAKDUtzSjN0EipNhYAi5YwakMAAAA= X-BESS-Outbound-Spam-Score: 0.00 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.250291 [from cloudscan22-232.eu-central-1b.ess.aws.cudaops.com] Rule breakdown below pts rule name description ---- ---------------------- -------------------------------- 0.00 LARGE_BODY_SHORTCUT META: X-BESS-Outbound-Spam-Status: SCORE=0.00 using account:ESS113687 scores of KILL_LEVEL=7.0 tests=LARGE_BODY_SHORTCUT X-BESS-BRTS-Status: 1 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 From: Christian Koue Muf Hooks into the DPDK API, and make the PMD available to use. Also adds documentation as .rst and .ini files. Signed-off-by: Christian Koue Muf Reviewed-by: Mykola Kostenok --- v2: * Fixed WARNING:TYPO_SPELLING * Fix supported platform list v3: * Fix Fedora 38 compilation issues v5: * Add ntnic.rst to index file --- .mailmap | 2 + MAINTAINERS | 7 + doc/guides/nics/features/ntnic.ini | 50 + doc/guides/nics/index.rst | 1 + doc/guides/nics/ntnic.rst | 235 + drivers/net/ntnic/include/ntdrv_4ga.h | 23 + drivers/net/ntnic/include/ntos_system.h | 23 + drivers/net/ntnic/meson.build | 13 + drivers/net/ntnic/ntnic_dbsconfig.c | 1670 +++++++ drivers/net/ntnic/ntnic_dbsconfig.h | 251 + drivers/net/ntnic/ntnic_ethdev.c | 4256 +++++++++++++++++ drivers/net/ntnic/ntnic_ethdev.h | 357 ++ .../net/ntnic/ntnic_filter/create_elements.h | 1190 +++++ drivers/net/ntnic/ntnic_filter/ntnic_filter.c | 656 +++ drivers/net/ntnic/ntnic_filter/ntnic_filter.h | 14 + drivers/net/ntnic/ntnic_hshconfig.c | 102 + drivers/net/ntnic/ntnic_hshconfig.h | 9 + drivers/net/ntnic/ntnic_meter.c | 811 ++++ drivers/net/ntnic/ntnic_meter.h | 10 + drivers/net/ntnic/ntnic_vdpa.c | 365 ++ drivers/net/ntnic/ntnic_vdpa.h | 21 + drivers/net/ntnic/ntnic_vf.c | 83 + drivers/net/ntnic/ntnic_vf.h | 17 + drivers/net/ntnic/ntnic_vf_vdpa.c | 1246 +++++ drivers/net/ntnic/ntnic_vf_vdpa.h | 25 + drivers/net/ntnic/ntnic_vfio.c | 321 ++ drivers/net/ntnic/ntnic_vfio.h | 31 + drivers/net/ntnic/ntnic_xstats.c | 703 +++ drivers/net/ntnic/ntnic_xstats.h | 22 + 29 files changed, 12514 insertions(+) create mode 100644 doc/guides/nics/features/ntnic.ini create mode 100644 doc/guides/nics/ntnic.rst create mode 100644 drivers/net/ntnic/include/ntdrv_4ga.h create mode 100644 drivers/net/ntnic/include/ntos_system.h create mode 100644 drivers/net/ntnic/ntnic_dbsconfig.c create mode 100644 drivers/net/ntnic/ntnic_dbsconfig.h create mode 100644 drivers/net/ntnic/ntnic_ethdev.c create mode 100644 drivers/net/ntnic/ntnic_ethdev.h create mode 100644 drivers/net/ntnic/ntnic_filter/create_elements.h create mode 100644 drivers/net/ntnic/ntnic_filter/ntnic_filter.c create mode 100644 drivers/net/ntnic/ntnic_filter/ntnic_filter.h create mode 100644 drivers/net/ntnic/ntnic_hshconfig.c create mode 100644 drivers/net/ntnic/ntnic_hshconfig.h create mode 100644 drivers/net/ntnic/ntnic_meter.c create mode 100644 drivers/net/ntnic/ntnic_meter.h create mode 100644 drivers/net/ntnic/ntnic_vdpa.c create mode 100644 drivers/net/ntnic/ntnic_vdpa.h create mode 100644 drivers/net/ntnic/ntnic_vf.c create mode 100644 drivers/net/ntnic/ntnic_vf.h create mode 100644 drivers/net/ntnic/ntnic_vf_vdpa.c create mode 100644 drivers/net/ntnic/ntnic_vf_vdpa.h create mode 100644 drivers/net/ntnic/ntnic_vfio.c create mode 100644 drivers/net/ntnic/ntnic_vfio.h create mode 100644 drivers/net/ntnic/ntnic_xstats.c create mode 100644 drivers/net/ntnic/ntnic_xstats.h diff --git a/.mailmap b/.mailmap index 864d33ee46..be8880971d 100644 --- a/.mailmap +++ b/.mailmap @@ -227,6 +227,7 @@ Chintu Hetam Choonho Son Chris Metcalf Christian Ehrhardt +Christian Koue Muf Christian Maciocco Christophe Fontaine Christophe Grosse @@ -967,6 +968,7 @@ Mukesh Dua Murphy Yang Murthy NSSR Muthurajan Jayakumar +Mykola Kostenok Nachiketa Prachanda Nagadheeraj Rottela Naga Harish K S V diff --git a/MAINTAINERS b/MAINTAINERS index 8c3f2c993f..02aca74173 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1053,6 +1053,13 @@ F: drivers/net/memif/ F: doc/guides/nics/memif.rst F: doc/guides/nics/features/memif.ini +NTNIC PMD +M: Mykola Kostenok +M: Christiam Muf +F: drivers/net/ntnic/ +F: doc/guides/nics/ntnic.rst +F: doc/guides/nics/features/ntnic.ini + Crypto Drivers -------------- diff --git a/doc/guides/nics/features/ntnic.ini b/doc/guides/nics/features/ntnic.ini new file mode 100644 index 0000000000..2583e12b1f --- /dev/null +++ b/doc/guides/nics/features/ntnic.ini @@ -0,0 +1,50 @@ +; +; Supported features of the 'ntnic' network poll mode driver. +; +; Refer to default.ini for the full list of available PMD features. +; +[Features] +Speed capabilities = Y +Link status = Y +Queue start/stop = Y +Shared Rx queue = Y +MTU update = Y +Promiscuous mode = Y +Unicast MAC filter = Y +Multicast MAC filter = Y +RSS hash = Y +RSS key update = Y +Inner RSS = Y +CRC offload = Y +L3 checksum offload = Y +L4 checksum offload = Y +Inner L3 checksum = Y +Inner L4 checksum = Y +Basic stats = Y +Extended stats = Y +FW version = Y +Linux = Y +x86-64 = Y + +[rte_flow items] +any = Y +eth = Y +gtp = Y +ipv4 = Y +ipv6 = Y +port_id = Y +sctp = Y +tcp = Y +udp = Y +vlan = Y + +[rte_flow actions] +drop = Y +jump = Y +meter = Y +modify_field = Y +port_id = Y +queue = Y +raw_decap = Y +raw_encap = Y +rss = Y diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst index 7bfcac880f..c14bc7988a 100644 --- a/doc/guides/nics/index.rst +++ b/doc/guides/nics/index.rst @@ -53,6 +53,7 @@ Network Interface Controller Drivers nfb nfp ngbe + ntnic null octeon_ep octeontx diff --git a/doc/guides/nics/ntnic.rst b/doc/guides/nics/ntnic.rst new file mode 100644 index 0000000000..85c58543dd --- /dev/null +++ b/doc/guides/nics/ntnic.rst @@ -0,0 +1,235 @@ +.. SPDX-License-Identifier: BSD-3-Clause + Copyright(c) 2023 Napatech A/S + +NTNIC Poll Mode Driver +====================== + +The NTNIC PMD provides poll mode driver support for Napatech smartNICs. + + +Design +------ + +The NTNIC PMD is designed as a pure user-space driver, and requires no special +Napatech kernel modules. + +The Napatech smartNIC presents one control PCI device (PF0). NTNIC PMD accesses +smartNIC PF0 via vfio-pci kernel driver. Access to PF0 for all purposes is +exclusive, so only one process should access it. The physical ports are located +behind PF0 as DPDK port 0 and 1. These ports can be configured with one or more +TX and RX queues each. + +Virtual ports can be added by creating VFs via SR-IOV. The vfio-pci kernel +driver is bound to the VFs. The VFs implement virtio data plane only and the VF +configuration is done by NTNIC PMD through PF0. Each VF can be configured with +one or more TX and RX queue pairs. The VF’s are numbered starting from VF 4. +The number of VFs is limited by the number of queues supported by the FPGA, +and the number of queue pairs allocated for each VF. Current FPGA supports 128 +queues in each TX and RX direction. A maximum of 63 VFs is supported (VF4-VF66). + +As the Napatech smartNICs supports sensors and monitoring beyond what is +available in the DPDK API, the PMD includes the ntconnect socket interface. +ntconnect additionally allows Napatech to implement specific customer requests +that are not supported by the DPDK API. + + +Supported NICs +-------------- + +- NT200A02 2x100G SmartNIC + + - FPGA ID 9563 (Inline Flow Management) + + +Features +-------- + +- Multiple TX and RX queues. +- Scattered and gather for TX and RX. +- RSS based on VLAN or 5-tuple. +- RSS using different combinations of fields: L3 only, L4 only or both, and + source only, destination only or both. +- Several RSS hash keys, one for each flow type. +- Default RSS operation with no hash key specification. +- VLAN filtering. +- RX VLAN stripping via raw decap. +- TX VLAN insertion via raw encap. +- Hairpin. +- HW checksum offload of RX and hairpin. +- Promiscuous mode on PF and VF. +- Flow API. +- Multiple process. +- Tunnel types: GTP. +- Tunnel HW offload: Packet type, inner/outer RSS, IP and UDP checksum + verification. +- Support for multiple rte_flow groups. +- Encapsulation and decapsulation of GTP data. +- Packet modification: NAT, TTL decrement, DSCP tagging +- Traffic mirroring. +- Jumbo frame support. +- Port and queue statistics. +- RMON statistics in extended stats. +- Flow metering, including meter policy API. +- Link state information. +- CAM and TCAM based matching. +- Exact match of 140 million flows and policies. + + +Limitations +~~~~~~~~~~~ + +Kernel versions before 5.7 are not supported. Kernel version 5.7 added vfio-pci +support for creating VFs from the PF which is required for the PMD to use +vfio-pci on the PF. This support has been back-ported to older Linux +distributions and they are also supported. If vfio-pci is not required kernel +version 4.18 is supported. + +Current NTNIC PMD implementation only supports one active adapter. + + +Configuration +------------- + +Command line arguments +~~~~~~~~~~~~~~~~~~~~~~ + +Following standard DPDK command line arguments are used by the PMD: + + -a: Used to specifically define the NT adapter by PCI ID. + --iova-mode: Must be set to ‘pa’ for Physical Address mode. + +NTNIC specific arguments can be passed to the PMD in the PCI device parameter list:: + + ... -a 0000:03:00.0[{,}] + +The NTNIC specific argument format is:: + + .=[:] + +Multiple arguments for the same device are separated by ‘,’ comma. + can be a single value or a range. + + +- ``rxqs`` parameter [int] + + Specify number of RX queues to use. + + To specify number of RX queues:: + + -a ::00.0,rxqs=4,txqs=4 + + By default, the value is set to 1. + +- ``txqs`` parameter [int] + + Specify number of TX queues to use. + + To specify number of TX queues:: + + -a ::00.0,rxqs=4,txqs=4 + + By default, the value is set to 1. + +- ``exception_path`` parameter [int] + + Enable exception path for unmatched packets to go through queue 0. + + To enable exception_path:: + + -a ::00.0,exception_path=1 + + By default, the value is set to 0. + +- ``port.link_speed`` parameter [list] + + This parameter is used to set the link speed on physical ports in the format:: + + port.link_speed=: + + To set up link speeds:: + + -a ::00.0,port.link_speed=0:10000,port.link_speed=1:25000 + + By default, set to the maximum corresponding to the NIM bit rate. + +- ``supported-fpgas`` parameter [str] + + List the supported FPGAs for a compiled NTNIC DPDK-driver. + + This parameter has two options:: + + - list. + - verbose. + + Example usages:: + + -a ::00.0,supported-fpgas=list + -a ::00.0,supported-fpgas=verbose + +- ``help`` parameter [none] + + List all available NTNIC PMD parameters. + + +Build options +~~~~~~~~~~~~~ + +- ``NT_TOOLS`` + + Define that enables the PMD ntconnect source code. + + Default: Enabled. + +- ``NT_VF_VDPA`` + + Define that enables the PMD VF VDPA source code. + + Default: Enabled. + +- ``NT_RELAY_CORE`` + + Define that enables the PMD replay core source code. The relay core is used + by Napatech's vSwitch PMD profile in an OVS environment. + + Default: Disabled. + + +Logging and Debugging +--------------------- + +NTNIC supports several groups of logging that can be enabled with ``log-level`` +parameter: + +- ETHDEV. + + Logging info from the main PMD code. i.e. code that is related to DPDK:: + + --log-level=ntnic.ethdev,8 + +- NTHW. + + Logging info from NTHW. i.e. code that is related to the FPGA and the Adapter:: + + --log-level=ntnic.nthw,8 + +- vDPA. + + Logging info from vDPA. i.e. code that is related to VFIO and vDPA:: + + --log-level=ntnic.vdpa,8 + +- FILTER. + + Logging info from filter. i.e. code that is related to the binary filter:: + + --log-level=ntnic.filter,8 + +- FPGA. + + Logging related to FPGA:: + + --log-level=ntnic.fpga,8 + +To enable logging on all levels use wildcard in the following way:: + + --log-level=ntnic.*,8 diff --git a/drivers/net/ntnic/include/ntdrv_4ga.h b/drivers/net/ntnic/include/ntdrv_4ga.h new file mode 100644 index 0000000000..e9c38fc330 --- /dev/null +++ b/drivers/net/ntnic/include/ntdrv_4ga.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTDRV_4GA_H__ +#define __NTDRV_4GA_H__ + +#include "nthw_drv.h" +#include "nt4ga_adapter.h" +#include "nthw_platform_drv.h" + +typedef struct ntdrv_4ga_s { + uint32_t pciident; + struct adapter_info_s adapter_info; + char *p_drv_name; + + volatile bool b_shutdown; + pthread_mutex_t stat_lck; + pthread_t stat_thread; + pthread_t flm_thread; +} ntdrv_4ga_t; + +#endif /* __NTDRV_4GA_H__ */ diff --git a/drivers/net/ntnic/include/ntos_system.h b/drivers/net/ntnic/include/ntos_system.h new file mode 100644 index 0000000000..0adfe86cc3 --- /dev/null +++ b/drivers/net/ntnic/include/ntos_system.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTOS_SYSTEM_H__ +#define __NTOS_SYSTEM_H__ + +#include "include/ntdrv_4ga.h" + +/* + * struct drv_s for DPDK (clone of kernel struct) + * keep it as close as possible to original kernel struct + */ +struct drv_s { + int adapter_no; + struct rte_pci_device *p_dev; + struct ntdrv_4ga_s ntdrv; + + int n_eth_dev_init_count; + int probe_finished; +}; + +#endif /* __NTOS_SYSTEM_H__ */ diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build index 0b5ca13e48..d3c3129a0c 100644 --- a/drivers/net/ntnic/meson.build +++ b/drivers/net/ntnic/meson.build @@ -33,6 +33,9 @@ includes = [ include_directories('sensors/ntavr'), ] +# deps +deps += 'vhost' + # all sources sources = files( 'adapter/nt4ga_adapter.c', @@ -119,6 +122,16 @@ sources = files( 'nthw/nthw_stat.c', 'nthw/supported/nthw_fpga_9563_055_024_0000.c', 'ntlog/ntlog.c', + 'ntnic_dbsconfig.c', + 'ntnic_ethdev.c', + 'ntnic_filter/ntnic_filter.c', + 'ntnic_hshconfig.c', + 'ntnic_meter.c', + 'ntnic_vdpa.c', + 'ntnic_vf.c', + 'ntnic_vfio.c', + 'ntnic_vf_vdpa.c', + 'ntnic_xstats.c', 'ntutil/nt_util.c', 'sensors/avr_sensors/avr_sensors.c', 'sensors/board_sensors/board_sensors.c', diff --git a/drivers/net/ntnic/ntnic_dbsconfig.c b/drivers/net/ntnic/ntnic_dbsconfig.c new file mode 100644 index 0000000000..2217c163ad --- /dev/null +++ b/drivers/net/ntnic/ntnic_dbsconfig.c @@ -0,0 +1,1670 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include + +#include "ntdrv_4ga.h" +#include "nt_util.h" +#include "ntnic_dbsconfig.h" +#include "ntnic_ethdev.h" +#include "ntlog.h" + +#define STRUCT_ALIGNMENT (4 * 1024LU) +#define MAX_VIRT_QUEUES 128 + +#define LAST_QUEUE 127 +#define DISABLE 0 +#define ENABLE 1 +#define RX_AM_DISABLE DISABLE +#define RX_AM_ENABLE ENABLE +#define RX_UW_DISABLE DISABLE +#define RX_UW_ENABLE ENABLE +#define RX_Q_DISABLE DISABLE +#define RX_Q_ENABLE ENABLE +#define RX_AM_POLL_SPEED 5 +#define RX_UW_POLL_SPEED 9 +#define HOST_ID 0 +#define INIT_QUEUE 1 + +#define TX_AM_DISABLE DISABLE +#define TX_AM_ENABLE ENABLE +#define TX_UW_DISABLE DISABLE +#define TX_UW_ENABLE ENABLE +#define TX_Q_DISABLE DISABLE +#define TX_Q_ENABLE ENABLE +#define TX_AM_POLL_SPEED 5 +#define TX_UW_POLL_SPEED 8 + +/**************************************************************************/ + +#define le64 uint64_t +#define le32 uint32_t +#define le16 uint16_t + +/**************************************************************************/ + +#define VIRTQ_AVAIL_F_NO_INTERRUPT 1 +#pragma pack(1) +struct virtq_avail { + le16 flags; + le16 idx; + le16 ring[]; /* Queue size */ +}; + +#pragma pack() +/**************************************************************************/ + +/* le32 is used here for ids for padding reasons. */ +#pragma pack(1) +struct virtq_used_elem { + /* Index of start of used descriptor chain. */ + le32 id; + /* Total length of the descriptor chain which was used (written to) */ + le32 len; +}; + +#pragma pack() + +#define VIRTQ_USED_F_NO_NOTIFY 1 + +#pragma pack(1) +struct virtq_used { + le16 flags; + le16 idx; + struct virtq_used_elem ring[]; /* Queue size */ +}; + +#pragma pack() + +struct virtq_struct_layout_s { + size_t used_offset; + size_t desc_offset; +}; + +enum nthw_virt_queue_usage { UNUSED = 0, UNMANAGED, MANAGED }; + +#define PACKED(vq_type) ((vq_type) == PACKED_RING ? 1 : 0) + +struct nthw_virt_queue { + /* Pointers to virt-queue structs */ + union { + struct { + /* SPLIT virtqueue */ + struct virtq_avail *p_avail; + struct virtq_used *p_used; + struct virtq_desc *p_desc; + /* Control variables for virt-queue structs */ + le16 am_idx; + le16 used_idx; + le16 cached_idx; + le16 tx_descr_avail_idx; + }; + struct { + /* PACKED virtqueue */ + struct pvirtq_event_suppress *driver_event; + struct pvirtq_event_suppress *device_event; + struct pvirtq_desc *desc; + struct { + le16 next; + le16 num; + } outs; + /* + * when in-order release used Tx packets from FPGA it may collapse + * into a batch. When getting new Tx buffers we may only need + * partial + */ + le16 next_avail; + le16 next_used; + le16 avail_wrap_count; + le16 used_wrap_count; + }; + }; + + /* Array with packet buffers */ + struct nthw_memory_descriptor *p_virtual_addr; + + /* Queue configuration info */ + enum nthw_virt_queue_usage usage; + uint16_t vq_type; + uint16_t in_order; + int irq_vector; + + nthw_dbs_t *mp_nthw_dbs; + uint32_t index; + le16 queue_size; + uint32_t am_enable; + uint32_t host_id; + uint32_t port; /* Only used by TX queues */ + uint32_t virtual_port; /* Only used by TX queues */ + uint32_t header; + /* + * Only used by TX queues: + * 0: VirtIO-Net header (12 bytes). + * 1: Napatech DVIO0 descriptor (12 bytes). + */ + void *avail_struct_phys_addr; + void *used_struct_phys_addr; + void *desc_struct_phys_addr; +}; + +struct pvirtq_struct_layout_s { + size_t driver_event_offset; + size_t device_event_offset; +}; + +static struct nthw_virt_queue rxvq[MAX_VIRT_QUEUES]; +static struct nthw_virt_queue txvq[MAX_VIRT_QUEUES]; + +static void dbs_init_rx_queue(nthw_dbs_t *p_nthw_dbs, uint32_t queue, + uint32_t start_idx, uint32_t start_ptr) +{ + uint32_t busy; + uint32_t init; + uint32_t dummy; + + do { + get_rx_init(p_nthw_dbs, &init, &dummy, &busy); + } while (busy != 0); + + set_rx_init(p_nthw_dbs, start_idx, start_ptr, INIT_QUEUE, queue); + + do { + get_rx_init(p_nthw_dbs, &init, &dummy, &busy); + } while (busy != 0); +} + +static void dbs_init_tx_queue(nthw_dbs_t *p_nthw_dbs, uint32_t queue, + uint32_t start_idx, uint32_t start_ptr) +{ + uint32_t busy; + uint32_t init; + uint32_t dummy; + + do { + get_tx_init(p_nthw_dbs, &init, &dummy, &busy); + } while (busy != 0); + + set_tx_init(p_nthw_dbs, start_idx, start_ptr, INIT_QUEUE, queue); + + do { + get_tx_init(p_nthw_dbs, &init, &dummy, &busy); + } while (busy != 0); +} + +int nthw_virt_queue_init(struct fpga_info_s *p_fpga_info) +{ + assert(p_fpga_info); + + nt_fpga_t *const p_fpga = p_fpga_info->mp_fpga; + nthw_dbs_t *p_nthw_dbs; + int res = 0; + uint32_t i; + + p_fpga_info->mp_nthw_dbs = NULL; + + p_nthw_dbs = nthw_dbs_new(); + if (p_nthw_dbs == NULL) + return -1; + + res = dbs_init(NULL, p_fpga, 0); /* Check that DBS exists in FPGA */ + if (res) { + free(p_nthw_dbs); + return res; + } + + res = dbs_init(p_nthw_dbs, p_fpga, 0); /* Create DBS module */ + if (res) { + free(p_nthw_dbs); + return res; + } + + p_fpga_info->mp_nthw_dbs = p_nthw_dbs; + + for (i = 0; i < MAX_VIRT_QUEUES; ++i) { + rxvq[i].usage = UNUSED; + txvq[i].usage = UNUSED; + } + + dbs_reset(p_nthw_dbs); + + for (i = 0; i < NT_DBS_RX_QUEUES_MAX; ++i) + dbs_init_rx_queue(p_nthw_dbs, i, 0, 0); + + for (i = 0; i < NT_DBS_TX_QUEUES_MAX; ++i) + dbs_init_tx_queue(p_nthw_dbs, i, 0, 0); + + set_rx_control(p_nthw_dbs, LAST_QUEUE, RX_AM_DISABLE, RX_AM_POLL_SPEED, + RX_UW_DISABLE, RX_UW_POLL_SPEED, RX_Q_DISABLE); + set_rx_control(p_nthw_dbs, LAST_QUEUE, RX_AM_ENABLE, RX_AM_POLL_SPEED, + RX_UW_ENABLE, RX_UW_POLL_SPEED, RX_Q_DISABLE); + set_rx_control(p_nthw_dbs, LAST_QUEUE, RX_AM_ENABLE, RX_AM_POLL_SPEED, + RX_UW_ENABLE, RX_UW_POLL_SPEED, RX_Q_ENABLE); + + set_tx_control(p_nthw_dbs, LAST_QUEUE, TX_AM_DISABLE, TX_AM_POLL_SPEED, + TX_UW_DISABLE, TX_UW_POLL_SPEED, TX_Q_DISABLE); + set_tx_control(p_nthw_dbs, LAST_QUEUE, TX_AM_ENABLE, TX_AM_POLL_SPEED, + TX_UW_ENABLE, TX_UW_POLL_SPEED, TX_Q_DISABLE); + set_tx_control(p_nthw_dbs, LAST_QUEUE, TX_AM_ENABLE, TX_AM_POLL_SPEED, + TX_UW_ENABLE, TX_UW_POLL_SPEED, TX_Q_ENABLE); + + return 0; +} + +static struct virtq_struct_layout_s dbs_calc_struct_layout(uint32_t queue_size) +{ + size_t avail_mem = + sizeof(struct virtq_avail) + + queue_size * + sizeof(le16); /* + sizeof(le16); ("avail->used_event" is not used) */ + size_t avail_mem_aligned = + ((avail_mem % STRUCT_ALIGNMENT) == 0) ? + avail_mem : + STRUCT_ALIGNMENT * (avail_mem / STRUCT_ALIGNMENT + 1); + + /* + sizeof(le16); ("used->avail_event" is not used) */ + size_t used_mem = + sizeof(struct virtq_used) + + queue_size * + sizeof(struct virtq_used_elem); + size_t used_mem_aligned = + ((used_mem % STRUCT_ALIGNMENT) == 0) ? + used_mem : + STRUCT_ALIGNMENT * (used_mem / STRUCT_ALIGNMENT + 1); + + struct virtq_struct_layout_s virtq_layout; + + virtq_layout.used_offset = avail_mem_aligned; + virtq_layout.desc_offset = avail_mem_aligned + used_mem_aligned; + + return virtq_layout; +} + +static void dbs_initialize_avail_struct(void *addr, uint16_t queue_size, + uint16_t initial_avail_idx) +{ + uint16_t i; + struct virtq_avail *p_avail = (struct virtq_avail *)addr; + + p_avail->flags = VIRTQ_AVAIL_F_NO_INTERRUPT; + p_avail->idx = initial_avail_idx; + for (i = 0; i < queue_size; ++i) + p_avail->ring[i] = i; +} + +static void dbs_initialize_used_struct(void *addr, uint16_t queue_size) +{ + int i; + struct virtq_used *p_used = (struct virtq_used *)addr; + + p_used->flags = 1; + p_used->idx = 0; + for (i = 0; i < queue_size; ++i) { + p_used->ring[i].id = 0; + p_used->ring[i].len = 0; + } +} + +static void dbs_initialize_descriptor_struct(void *addr, + struct nthw_memory_descriptor *packet_buffer_descriptors, + uint16_t queue_size, ule16 flgs) +{ + if (packet_buffer_descriptors) { + int i; + struct virtq_desc *p_desc = (struct virtq_desc *)addr; + + for (i = 0; i < queue_size; ++i) { + p_desc[i].addr = + (uint64_t)packet_buffer_descriptors[i].phys_addr; + p_desc[i].len = packet_buffer_descriptors[i].len; + p_desc[i].flags = flgs; + p_desc[i].next = 0; + } + } +} + +static void dbs_initialize_virt_queue_structs(void *avail_struct_addr, + void *used_struct_addr, void *desc_struct_addr, + struct nthw_memory_descriptor *packet_buffer_descriptors, + uint16_t queue_size, uint16_t initial_avail_idx, ule16 flgs) +{ + dbs_initialize_avail_struct(avail_struct_addr, queue_size, + initial_avail_idx); + dbs_initialize_used_struct(used_struct_addr, queue_size); + dbs_initialize_descriptor_struct(desc_struct_addr, + packet_buffer_descriptors, + queue_size, flgs); +} + +static le16 dbs_qsize_log2(le16 qsize) +{ + uint32_t qs = 0; + + while (qsize) { + qsize = qsize >> 1; + ++qs; + } + --qs; + return qs; +} + +struct nthw_virt_queue *nthw_setup_rx_virt_queue(nthw_dbs_t *p_nthw_dbs, + uint32_t index, uint16_t start_idx, + uint16_t start_ptr, void *avail_struct_phys_addr, void *used_struct_phys_addr, + void *desc_struct_phys_addr, uint16_t queue_size, uint32_t host_id, + uint32_t header, uint32_t vq_type, int irq_vector) +{ + uint32_t qs = dbs_qsize_log2(queue_size); + uint32_t int_enable; + uint32_t vec; + uint32_t istk; + + /* + * Setup DBS module - DSF00094 + * 3. Configure the DBS.RX_DR_DATA memory; good idea to initialize all + * DBS_RX_QUEUES entries. + */ + if (set_rx_dr_data(p_nthw_dbs, index, (uint64_t)desc_struct_phys_addr, + host_id, qs, header, PACKED(vq_type)) != 0) + return NULL; + + /* + * 4. Configure the DBS.RX_UW_DATA memory; good idea to initialize all + * DBS_RX_QUEUES entries. + * Notice: We always start out with interrupts disabled (by setting the + * "irq_vector" argument to -1). Queues that require interrupts will have + * it enabled at a later time (after we have enabled vfio interrupts in + * the kernel). + */ + int_enable = 0; + vec = 0; + istk = 0; + NT_LOG(DBG, ETHDEV, "%s: set_rx_uw_data int=0 irq_vector=%u\n", + __func__, irq_vector); + if (set_rx_uw_data(p_nthw_dbs, index, + vq_type == PACKED_RING ? (uint64_t)desc_struct_phys_addr : + (uint64_t)used_struct_phys_addr, + host_id, qs, PACKED(vq_type), int_enable, vec, istk) != 0) + return NULL; + + /* + * 2. Configure the DBS.RX_AM_DATA memory and enable the queues you plan to use; + * good idea to initialize all DBS_RX_QUEUES entries. + * Notice: We do this only for queues that don't require interrupts (i.e. if + * irq_vector < 0). Queues that require interrupts will have RX_AM_DATA enabled + * at a later time (after we have enabled vfio interrupts in the kernel). + */ + if (irq_vector < 0) { + if (set_rx_am_data(p_nthw_dbs, index, + (uint64_t)avail_struct_phys_addr, RX_AM_DISABLE, + host_id, PACKED(vq_type), + irq_vector >= 0 ? 1 : 0) != 0) + return NULL; + } + + /* + * 5. Initialize all RX queues (all DBS_RX_QUEUES of them) using the + * DBS.RX_INIT register. + */ + dbs_init_rx_queue(p_nthw_dbs, index, start_idx, start_ptr); + + /* + * 2. Configure the DBS.RX_AM_DATA memory and enable the queues you plan to use; + * good idea to initialize all DBS_RX_QUEUES entries. + */ + if (set_rx_am_data(p_nthw_dbs, index, (uint64_t)avail_struct_phys_addr, + RX_AM_ENABLE, host_id, PACKED(vq_type), + irq_vector >= 0 ? 1 : 0) != 0) + return NULL; + + /* Save queue state */ + rxvq[index].usage = UNMANAGED; + rxvq[index].mp_nthw_dbs = p_nthw_dbs; + rxvq[index].index = index; + rxvq[index].queue_size = queue_size; + rxvq[index].am_enable = (irq_vector < 0) ? RX_AM_ENABLE : RX_AM_DISABLE; + rxvq[index].host_id = host_id; + rxvq[index].avail_struct_phys_addr = avail_struct_phys_addr; + rxvq[index].used_struct_phys_addr = used_struct_phys_addr; + rxvq[index].desc_struct_phys_addr = desc_struct_phys_addr; + rxvq[index].vq_type = vq_type; + rxvq[index].in_order = 0; /* not used */ + rxvq[index].irq_vector = irq_vector; + + /* Return queue handle */ + return &rxvq[index]; +} + +static int dbs_wait_hw_queue_shutdown(struct nthw_virt_queue *vq, int rx); + +int nthw_disable_rx_virt_queue(struct nthw_virt_queue *rx_vq) +{ + if (!rx_vq) { + NT_LOG(ERR, ETHDEV, "%s: Invalid queue\n", __func__); + return -1; + } + + nthw_dbs_t *p_nthw_dbs = rx_vq->mp_nthw_dbs; + + if (rx_vq->index >= MAX_VIRT_QUEUES) + return -1; + + if (rx_vq->usage != UNMANAGED) + return -1; + + uint32_t qs = dbs_qsize_log2(rx_vq->queue_size); + + /* If ISTK is set, make sure to unset it */ + if (set_rx_uw_data(p_nthw_dbs, rx_vq->index, + rx_vq->vq_type == PACKED_RING ? + (uint64_t)rx_vq->desc_struct_phys_addr : + (uint64_t)rx_vq->used_struct_phys_addr, + rx_vq->host_id, qs, PACKED(rx_vq->vq_type), 0, 0, + 0) != 0) + return -1; + + /* Disable AM */ + rx_vq->am_enable = RX_AM_DISABLE; + if (set_rx_am_data(p_nthw_dbs, rx_vq->index, + (uint64_t)rx_vq->avail_struct_phys_addr, + rx_vq->am_enable, rx_vq->host_id, + PACKED(rx_vq->vq_type), 0) != 0) + return -1; + + /* let the FPGA finish packet processing */ + if (dbs_wait_hw_queue_shutdown(rx_vq, 1) != 0) + return -1; + + return 0; +} + +int nthw_enable_rx_virt_queue(struct nthw_virt_queue *rx_vq) +{ + uint32_t int_enable; + uint32_t vec; + uint32_t istk; + + if (!rx_vq) { + NT_LOG(ERR, ETHDEV, "%s: Invalid queue\n", __func__); + return -1; + } + + nthw_dbs_t *p_nthw_dbs = rx_vq->mp_nthw_dbs; + + if (rx_vq->index >= MAX_VIRT_QUEUES) + return -1; + + if (rx_vq->usage != UNMANAGED) + return -1; + + uint32_t qs = dbs_qsize_log2(rx_vq->queue_size); + + /* Set ISTK if */ + if (rx_vq->irq_vector >= 0 && + rx_vq->irq_vector < MAX_MSIX_VECTORS_PR_VF) { + int_enable = 1; + vec = rx_vq->irq_vector; + istk = 1; + } else { + int_enable = 0; + vec = 0; + istk = 0; + } + NT_LOG(DBG, ETHDEV, "%s: set_rx_uw_data irq_vector=%u\n", __func__, + rx_vq->irq_vector); + if (set_rx_uw_data(p_nthw_dbs, rx_vq->index, + rx_vq->vq_type == PACKED_RING ? + (uint64_t)rx_vq->desc_struct_phys_addr : + (uint64_t)rx_vq->used_struct_phys_addr, + rx_vq->host_id, qs, PACKED(rx_vq->vq_type), + int_enable, vec, istk) != 0) + return -1; + + /* Enable AM */ + rx_vq->am_enable = RX_AM_ENABLE; + if (set_rx_am_data(p_nthw_dbs, rx_vq->index, + (uint64_t)rx_vq->avail_struct_phys_addr, + rx_vq->am_enable, rx_vq->host_id, + PACKED(rx_vq->vq_type), + rx_vq->irq_vector >= 0 ? 1 : 0) != 0) + return -1; + + return 0; +} + +int nthw_disable_tx_virt_queue(struct nthw_virt_queue *tx_vq) +{ + if (!tx_vq) { + NT_LOG(ERR, ETHDEV, "%s: Invalid queue\n", __func__); + return -1; + } + + nthw_dbs_t *p_nthw_dbs = tx_vq->mp_nthw_dbs; + + if (tx_vq->index >= MAX_VIRT_QUEUES) + return -1; + + if (tx_vq->usage != UNMANAGED) + return -1; + + uint32_t qs = dbs_qsize_log2(tx_vq->queue_size); + + /* If ISTK is set, make sure to unset it */ + if (set_tx_uw_data(p_nthw_dbs, tx_vq->index, + tx_vq->vq_type == PACKED_RING ? + (uint64_t)tx_vq->desc_struct_phys_addr : + (uint64_t)tx_vq->used_struct_phys_addr, + tx_vq->host_id, qs, PACKED(tx_vq->vq_type), 0, 0, 0, + tx_vq->in_order) != 0) + return -1; + + /* Disable AM */ + tx_vq->am_enable = TX_AM_DISABLE; + if (set_tx_am_data(p_nthw_dbs, tx_vq->index, + (uint64_t)tx_vq->avail_struct_phys_addr, + tx_vq->am_enable, tx_vq->host_id, + PACKED(tx_vq->vq_type), 0) != 0) + return -1; + + /* let the FPGA finish packet processing */ + if (dbs_wait_hw_queue_shutdown(tx_vq, 0) != 0) + return -1; + + return 0; +} + +int nthw_enable_tx_virt_queue(struct nthw_virt_queue *tx_vq) +{ + uint32_t int_enable; + uint32_t vec; + uint32_t istk; + + if (!tx_vq) { + NT_LOG(ERR, ETHDEV, "%s: Invalid queue\n", __func__); + return -1; + } + + nthw_dbs_t *p_nthw_dbs = tx_vq->mp_nthw_dbs; + + if (tx_vq->index >= MAX_VIRT_QUEUES) + return -1; + + if (tx_vq->usage != UNMANAGED) + return -1; + + uint32_t qs = dbs_qsize_log2(tx_vq->queue_size); + + /* Set ISTK if irq_vector is used */ + if (tx_vq->irq_vector >= 0 && + tx_vq->irq_vector < MAX_MSIX_VECTORS_PR_VF) { + int_enable = 1; + vec = tx_vq->irq_vector; + istk = 1; /* Use sticky interrupt */ + } else { + int_enable = 0; + vec = 0; + istk = 0; + } + if (set_tx_uw_data(p_nthw_dbs, tx_vq->index, + tx_vq->vq_type == PACKED_RING ? + (uint64_t)tx_vq->desc_struct_phys_addr : + (uint64_t)tx_vq->used_struct_phys_addr, + tx_vq->host_id, qs, PACKED(tx_vq->vq_type), + int_enable, vec, istk, tx_vq->in_order) != 0) + return -1; + + /* Enable AM */ + tx_vq->am_enable = TX_AM_ENABLE; + if (set_tx_am_data(p_nthw_dbs, tx_vq->index, + (uint64_t)tx_vq->avail_struct_phys_addr, + tx_vq->am_enable, tx_vq->host_id, + PACKED(tx_vq->vq_type), + tx_vq->irq_vector >= 0 ? 1 : 0) != 0) + return -1; + + return 0; +} + +int nthw_enable_and_change_port_tx_virt_queue(struct nthw_virt_queue *tx_vq, + uint32_t outport) +{ + nthw_dbs_t *p_nthw_dbs = tx_vq->mp_nthw_dbs; + uint32_t qs = dbs_qsize_log2(tx_vq->queue_size); + + if (set_tx_dr_data(p_nthw_dbs, tx_vq->index, + (uint64_t)tx_vq->desc_struct_phys_addr, tx_vq->host_id, + qs, outport, 0, PACKED(tx_vq->vq_type)) != 0) + return -1; + return nthw_enable_tx_virt_queue(tx_vq); +} + +int nthw_set_tx_qos_config(nthw_dbs_t *p_nthw_dbs, uint32_t port, uint32_t enable, + uint32_t ir, uint32_t bs) +{ + return set_tx_qos_data(p_nthw_dbs, port, enable, ir, bs); +} + +int nthw_set_tx_qos_rate_global(nthw_dbs_t *p_nthw_dbs, uint32_t multiplier, + uint32_t divider) +{ + return set_tx_qos_rate(p_nthw_dbs, multiplier, divider); +} + +#define INDEX_PTR_NOT_VALID 0x80000000 +static int dbs_get_rx_ptr(nthw_dbs_t *p_nthw_dbs, uint32_t *p_index) +{ + uint32_t ptr; + uint32_t queue; + uint32_t valid; + + const int status = get_rx_ptr(p_nthw_dbs, &ptr, &queue, &valid); + + if (status == 0) { + if (valid) + *p_index = ptr; + else + *p_index = INDEX_PTR_NOT_VALID; + } + return status; +} + +static int dbs_get_tx_ptr(nthw_dbs_t *p_nthw_dbs, uint32_t *p_index) +{ + uint32_t ptr; + uint32_t queue; + uint32_t valid; + + const int status = get_tx_ptr(p_nthw_dbs, &ptr, &queue, &valid); + + if (status == 0) { + if (valid) + *p_index = ptr; + else + *p_index = INDEX_PTR_NOT_VALID; + } + return status; +} + +static int dbs_initialize_get_rx_ptr(nthw_dbs_t *p_nthw_dbs, uint32_t queue) +{ + return set_rx_ptr_queue(p_nthw_dbs, queue); +} + +static int dbs_initialize_get_tx_ptr(nthw_dbs_t *p_nthw_dbs, uint32_t queue) +{ + return set_tx_ptr_queue(p_nthw_dbs, queue); +} + +static int dbs_wait_on_busy(struct nthw_virt_queue *vq, uint32_t *idle, int rx) +{ + uint32_t busy; + uint32_t queue; + int err = 0; + nthw_dbs_t *p_nthw_dbs = vq->mp_nthw_dbs; + + do { + if (rx) + err = get_rx_idle(p_nthw_dbs, idle, &queue, &busy); + else + err = get_tx_idle(p_nthw_dbs, idle, &queue, &busy); + } while (!err && busy); + + return err; +} + +static int dbs_wait_hw_queue_shutdown(struct nthw_virt_queue *vq, int rx) +{ + int err = 0; + uint32_t idle = 0; + nthw_dbs_t *p_nthw_dbs = vq->mp_nthw_dbs; + + err = dbs_wait_on_busy(vq, &idle, rx); + if (err) { + if (err == -ENOTSUP) { + NT_OS_WAIT_USEC(200000); + return 0; + } + return -1; + } + + do { + if (rx) + err = set_rx_idle(p_nthw_dbs, 1, vq->index); + else + err = set_tx_idle(p_nthw_dbs, 1, vq->index); + + if (err) + return -1; + + if (dbs_wait_on_busy(vq, &idle, rx) != 0) + return -1; + + } while (idle == 0); + + return 0; +} + +static int dbs_internal_release_rx_virt_queue(struct nthw_virt_queue *rxvq) +{ + nthw_dbs_t *p_nthw_dbs = rxvq->mp_nthw_dbs; + + if (rxvq == NULL) + return -1; + + /* Clear UW */ + rxvq->used_struct_phys_addr = NULL; + if (set_rx_uw_data(p_nthw_dbs, rxvq->index, + (uint64_t)rxvq->used_struct_phys_addr, rxvq->host_id, 0, + PACKED(rxvq->vq_type), 0, 0, 0) != 0) + return -1; + + /* Disable AM */ + rxvq->am_enable = RX_AM_DISABLE; + if (set_rx_am_data(p_nthw_dbs, rxvq->index, + (uint64_t)rxvq->avail_struct_phys_addr, rxvq->am_enable, + rxvq->host_id, PACKED(rxvq->vq_type), 0) != 0) + return -1; + + /* Let the FPGA finish packet processing */ + if (dbs_wait_hw_queue_shutdown(rxvq, 1) != 0) + return -1; + + /* Clear rest of AM */ + rxvq->avail_struct_phys_addr = NULL; + rxvq->host_id = 0; + if (set_rx_am_data(p_nthw_dbs, rxvq->index, + (uint64_t)rxvq->avail_struct_phys_addr, rxvq->am_enable, + rxvq->host_id, PACKED(rxvq->vq_type), 0) != 0) + return -1; + + /* Clear DR */ + rxvq->desc_struct_phys_addr = NULL; + if (set_rx_dr_data(p_nthw_dbs, rxvq->index, + (uint64_t)rxvq->desc_struct_phys_addr, rxvq->host_id, 0, + rxvq->header, PACKED(rxvq->vq_type)) != 0) + return -1; + + /* Initialize queue */ + dbs_init_rx_queue(p_nthw_dbs, rxvq->index, 0, 0); + + /* Reset queue state */ + rxvq->usage = UNUSED; + rxvq->mp_nthw_dbs = p_nthw_dbs; + rxvq->index = 0; + rxvq->queue_size = 0; + + return 0; +} + +int nthw_release_rx_virt_queue(struct nthw_virt_queue *rxvq) +{ + if (rxvq == NULL || rxvq->usage != UNMANAGED) + return -1; + + return dbs_internal_release_rx_virt_queue(rxvq); +} + +int nthw_release_managed_rx_virt_queue(struct nthw_virt_queue *rxvq) +{ + if (rxvq == NULL || rxvq->usage != MANAGED) + return -1; + + if (rxvq->p_virtual_addr) { + free(rxvq->p_virtual_addr); + rxvq->p_virtual_addr = NULL; + } + + return dbs_internal_release_rx_virt_queue(rxvq); +} + +static int dbs_internal_release_tx_virt_queue(struct nthw_virt_queue *txvq) +{ + nthw_dbs_t *p_nthw_dbs = txvq->mp_nthw_dbs; + + if (txvq == NULL) + return -1; + + /* Clear UW */ + txvq->used_struct_phys_addr = NULL; + if (set_tx_uw_data(p_nthw_dbs, txvq->index, + (uint64_t)txvq->used_struct_phys_addr, txvq->host_id, 0, + PACKED(txvq->vq_type), 0, 0, 0, + txvq->in_order) != 0) + return -1; + + /* Disable AM */ + txvq->am_enable = TX_AM_DISABLE; + if (set_tx_am_data(p_nthw_dbs, txvq->index, + (uint64_t)txvq->avail_struct_phys_addr, txvq->am_enable, + txvq->host_id, PACKED(txvq->vq_type), 0) != 0) + return -1; + + /* Let the FPGA finish packet processing */ + if (dbs_wait_hw_queue_shutdown(txvq, 0) != 0) + return -1; + + /* Clear rest of AM */ + txvq->avail_struct_phys_addr = NULL; + txvq->host_id = 0; + if (set_tx_am_data(p_nthw_dbs, txvq->index, + (uint64_t)txvq->avail_struct_phys_addr, txvq->am_enable, + txvq->host_id, PACKED(txvq->vq_type), 0) != 0) + return -1; + + /* Clear DR */ + txvq->desc_struct_phys_addr = NULL; + txvq->port = 0; + txvq->header = 0; + if (set_tx_dr_data(p_nthw_dbs, txvq->index, + (uint64_t)txvq->desc_struct_phys_addr, txvq->host_id, 0, + txvq->port, txvq->header, + PACKED(txvq->vq_type)) != 0) + return -1; + + /* Clear QP */ + txvq->virtual_port = 0; + if (nthw_dbs_set_tx_qp_data(p_nthw_dbs, txvq->index, txvq->virtual_port) != + 0) + return -1; + + /* Initialize queue */ + dbs_init_tx_queue(p_nthw_dbs, txvq->index, 0, 0); + + /* Reset queue state */ + txvq->usage = UNUSED; + txvq->mp_nthw_dbs = p_nthw_dbs; + txvq->index = 0; + txvq->queue_size = 0; + + return 0; +} + +int nthw_release_tx_virt_queue(struct nthw_virt_queue *txvq) +{ + if (txvq == NULL || txvq->usage != UNMANAGED) + return -1; + + return dbs_internal_release_tx_virt_queue(txvq); +} + +int nthw_release_managed_tx_virt_queue(struct nthw_virt_queue *txvq) +{ + if (txvq == NULL || txvq->usage != MANAGED) + return -1; + + if (txvq->p_virtual_addr) { + free(txvq->p_virtual_addr); + txvq->p_virtual_addr = NULL; + } + + return dbs_internal_release_tx_virt_queue(txvq); +} + +struct nthw_virt_queue *nthw_setup_tx_virt_queue(nthw_dbs_t *p_nthw_dbs, + uint32_t index, uint16_t start_idx, + uint16_t start_ptr, void *avail_struct_phys_addr, void *used_struct_phys_addr, + void *desc_struct_phys_addr, uint16_t queue_size, uint32_t host_id, + uint32_t port, uint32_t virtual_port, uint32_t header, uint32_t vq_type, + int irq_vector, uint32_t in_order) +{ + uint32_t int_enable; + uint32_t vec; + uint32_t istk; + uint32_t qs = dbs_qsize_log2(queue_size); + + /* + * Setup DBS module - DSF00094 + * 3. Configure the DBS.TX_DR_DATA memory; good idea to initialize all + * DBS_TX_QUEUES entries. + */ + if (set_tx_dr_data(p_nthw_dbs, index, (uint64_t)desc_struct_phys_addr, + host_id, qs, port, header, PACKED(vq_type)) != 0) + return NULL; + + /* + * 4. Configure the DBS.TX_UW_DATA memory; good idea to initialize all + * DBS_TX_QUEUES entries. + * Notice: We always start out with interrupts disabled (by setting the + * "irq_vector" argument to -1). Queues that require interrupts will have + * it enabled at a later time (after we have enabled vfio interrupts in the + * kernel). + */ + int_enable = 0; + vec = 0; + istk = 0; + + if (set_tx_uw_data(p_nthw_dbs, index, + vq_type == PACKED_RING ? + (uint64_t)desc_struct_phys_addr : + (uint64_t)used_struct_phys_addr, + host_id, qs, PACKED(vq_type), int_enable, vec, istk, + in_order) != 0) + return NULL; + + /* + * 2. Configure the DBS.TX_AM_DATA memory and enable the queues you plan to use; + * good idea to initialize all DBS_TX_QUEUES entries. + */ + if (set_tx_am_data(p_nthw_dbs, index, (uint64_t)avail_struct_phys_addr, + TX_AM_DISABLE, host_id, PACKED(vq_type), + irq_vector >= 0 ? 1 : 0) != 0) + return NULL; + + /* + * 5. Initialize all TX queues (all DBS_TX_QUEUES of them) using the + * DBS.TX_INIT register. + */ + dbs_init_tx_queue(p_nthw_dbs, index, start_idx, start_ptr); + + if (nthw_dbs_set_tx_qp_data(p_nthw_dbs, index, virtual_port) != 0) + return NULL; + + /* + * 2. Configure the DBS.TX_AM_DATA memory and enable the queues you plan to use; + * good idea to initialize all DBS_TX_QUEUES entries. + * Notice: We do this only for queues that don't require interrupts (i.e. if + * irq_vector < 0). Queues that require interrupts will have TX_AM_DATA + * enabled at a later time (after we have enabled vfio interrupts in the + * kernel). + */ + if (irq_vector < 0) { + if (set_tx_am_data(p_nthw_dbs, index, + (uint64_t)avail_struct_phys_addr, TX_AM_ENABLE, + host_id, PACKED(vq_type), + irq_vector >= 0 ? 1 : 0) != 0) + return NULL; + } + + /* Save queue state */ + txvq[index].usage = UNMANAGED; + txvq[index].mp_nthw_dbs = p_nthw_dbs; + txvq[index].index = index; + txvq[index].queue_size = queue_size; + txvq[index].am_enable = (irq_vector < 0) ? TX_AM_ENABLE : TX_AM_DISABLE; + txvq[index].host_id = host_id; + txvq[index].port = port; + txvq[index].virtual_port = virtual_port; + txvq[index].header = header; + txvq[index].avail_struct_phys_addr = avail_struct_phys_addr; + txvq[index].used_struct_phys_addr = used_struct_phys_addr; + txvq[index].desc_struct_phys_addr = desc_struct_phys_addr; + txvq[index].vq_type = vq_type; + txvq[index].in_order = in_order; + txvq[index].irq_vector = irq_vector; + + /* Return queue handle */ + return &txvq[index]; +} + +static struct nthw_virt_queue *nthw_setup_managed_rx_virt_queue_split(nthw_dbs_t *p_nthw_dbs, + uint32_t index, uint32_t queue_size, + uint32_t host_id, uint32_t header, + struct nthw_memory_descriptor *p_virt_struct_area, + struct nthw_memory_descriptor *p_packet_buffers, int irq_vector) +{ + struct virtq_struct_layout_s virtq_struct_layout = + dbs_calc_struct_layout(queue_size); + + dbs_initialize_virt_queue_structs(p_virt_struct_area->virt_addr, + (char *)p_virt_struct_area->virt_addr + + virtq_struct_layout.used_offset, + (char *)p_virt_struct_area->virt_addr + + virtq_struct_layout.desc_offset, + p_packet_buffers, (uint16_t)queue_size, + p_packet_buffers ? (uint16_t)queue_size : 0, + VIRTQ_DESC_F_WRITE /* Rx */); + + rxvq[index].p_avail = p_virt_struct_area->virt_addr; + rxvq[index].p_used = (void *)((char *)p_virt_struct_area->virt_addr + + virtq_struct_layout.used_offset); + rxvq[index].p_desc = (void *)((char *)p_virt_struct_area->virt_addr + + virtq_struct_layout.desc_offset); + + rxvq[index].am_idx = p_packet_buffers ? (uint16_t)queue_size : 0; + rxvq[index].used_idx = 0; + rxvq[index].cached_idx = 0; + rxvq[index].p_virtual_addr = NULL; + + if (p_packet_buffers) { + rxvq[index].p_virtual_addr = + malloc(queue_size * sizeof(*p_packet_buffers)); + memcpy(rxvq[index].p_virtual_addr, p_packet_buffers, + queue_size * sizeof(*p_packet_buffers)); + } + + nthw_setup_rx_virt_queue(p_nthw_dbs, index, 0, 0, + (void *)p_virt_struct_area->phys_addr, + (char *)p_virt_struct_area->phys_addr + + virtq_struct_layout.used_offset, + (char *)p_virt_struct_area->phys_addr + + virtq_struct_layout.desc_offset, + (uint16_t)queue_size, host_id, header, + SPLIT_RING, irq_vector); + + rxvq[index].usage = MANAGED; + + return &rxvq[index]; +} + +static struct nthw_virt_queue *nthw_setup_managed_tx_virt_queue_split(nthw_dbs_t *p_nthw_dbs, + uint32_t index, uint32_t queue_size, + uint32_t host_id, uint32_t port, uint32_t virtual_port, uint32_t header, + int irq_vector, uint32_t in_order, + struct nthw_memory_descriptor *p_virt_struct_area, + struct nthw_memory_descriptor *p_packet_buffers) +{ + struct virtq_struct_layout_s virtq_struct_layout = + dbs_calc_struct_layout(queue_size); + + dbs_initialize_virt_queue_structs(p_virt_struct_area->virt_addr, + (char *)p_virt_struct_area->virt_addr + + virtq_struct_layout.used_offset, + (char *)p_virt_struct_area->virt_addr + + virtq_struct_layout.desc_offset, + p_packet_buffers, (uint16_t)queue_size, 0, 0 /* Tx */); + + txvq[index].p_avail = p_virt_struct_area->virt_addr; + txvq[index].p_used = (void *)((char *)p_virt_struct_area->virt_addr + + virtq_struct_layout.used_offset); + txvq[index].p_desc = (void *)((char *)p_virt_struct_area->virt_addr + + virtq_struct_layout.desc_offset); + txvq[index].queue_size = (le16)queue_size; + txvq[index].am_idx = 0; + txvq[index].used_idx = 0; + txvq[index].cached_idx = 0; + txvq[index].p_virtual_addr = NULL; + + txvq[index].tx_descr_avail_idx = 0; + + if (p_packet_buffers) { + txvq[index].p_virtual_addr = + malloc(queue_size * sizeof(*p_packet_buffers)); + memcpy(txvq[index].p_virtual_addr, p_packet_buffers, + queue_size * sizeof(*p_packet_buffers)); + } + + nthw_setup_tx_virt_queue(p_nthw_dbs, index, 0, 0, + (void *)p_virt_struct_area->phys_addr, + (char *)p_virt_struct_area->phys_addr + + virtq_struct_layout.used_offset, + (char *)p_virt_struct_area->phys_addr + + virtq_struct_layout.desc_offset, + (uint16_t)queue_size, host_id, port, virtual_port, + header, SPLIT_RING, irq_vector, in_order); + + txvq[index].usage = MANAGED; + + return &txvq[index]; +} + +/* + * Packed Ring + */ +static int nthw_setup_managed_virt_queue_packed(struct nthw_virt_queue *vq, + struct pvirtq_struct_layout_s *pvirtq_layout, + struct nthw_memory_descriptor *p_virt_struct_area, + struct nthw_memory_descriptor *p_packet_buffers, ule16 flags, int rx) +{ + /* page aligned */ + assert(((uintptr_t)p_virt_struct_area->phys_addr & 0xfff) == 0); + assert(p_packet_buffers); + + /* clean canvas */ + memset(p_virt_struct_area->virt_addr, 0, + sizeof(struct pvirtq_desc) * vq->queue_size + + sizeof(struct pvirtq_event_suppress) * 2 + + sizeof(int) * vq->queue_size); + + pvirtq_layout->device_event_offset = + sizeof(struct pvirtq_desc) * vq->queue_size; + pvirtq_layout->driver_event_offset = + pvirtq_layout->device_event_offset + + sizeof(struct pvirtq_event_suppress); + + vq->desc = p_virt_struct_area->virt_addr; + vq->device_event = (void *)((uintptr_t)vq->desc + + pvirtq_layout->device_event_offset); + vq->driver_event = (void *)((uintptr_t)vq->desc + + pvirtq_layout->driver_event_offset); + + vq->next_avail = 0; + vq->next_used = 0; + vq->avail_wrap_count = 1; + vq->used_wrap_count = 1; + + /* + * Only possible if FPGA always delivers in-order + * Buffer ID used is the index in the pPacketBuffers array + */ + unsigned int i; + struct pvirtq_desc *p_desc = vq->desc; + + for (i = 0; i < vq->queue_size; i++) { + if (rx) { + p_desc[i].addr = (uint64_t)p_packet_buffers[i].phys_addr; + p_desc[i].len = p_packet_buffers[i].len; + } + p_desc[i].id = i; + p_desc[i].flags = flags; + } + + if (rx) + vq->avail_wrap_count ^= + 1; /* filled up available buffers for Rx */ + else + vq->used_wrap_count ^= 1; /* pre-fill free buffer IDs */ + + if (vq->queue_size == 0) + return -1; /* don't allocate memory with size of 0 bytes */ + vq->p_virtual_addr = malloc(vq->queue_size * sizeof(*p_packet_buffers)); + if (vq->p_virtual_addr == NULL) + return -1; + + memcpy(vq->p_virtual_addr, p_packet_buffers, + vq->queue_size * sizeof(*p_packet_buffers)); + + /* Not used yet by FPGA - make sure we disable */ + vq->device_event->flags = RING_EVENT_FLAGS_DISABLE; + + return 0; +} + +static struct nthw_virt_queue *nthw_setup_managed_rx_virt_queue_packed(nthw_dbs_t *p_nthw_dbs, + uint32_t index, uint32_t queue_size, + uint32_t host_id, uint32_t header, + struct nthw_memory_descriptor *p_virt_struct_area, + struct nthw_memory_descriptor *p_packet_buffers, int irq_vector) +{ + struct pvirtq_struct_layout_s pvirtq_layout; + struct nthw_virt_queue *vq = &rxvq[index]; + /* Set size and setup packed vq ring */ + vq->queue_size = queue_size; + /* Use Avail flag bit == 1 because wrap bit is initially set to 1 - and Used is inverse */ + if (nthw_setup_managed_virt_queue_packed(vq, &pvirtq_layout, + p_virt_struct_area, p_packet_buffers, + VIRTQ_DESC_F_WRITE | VIRTQ_DESC_F_AVAIL, 1) != 0) + return NULL; + + nthw_setup_rx_virt_queue(p_nthw_dbs, index, 0x8000, + 0, /* start wrap ring counter as 1 */ + (void *)((uintptr_t)p_virt_struct_area->phys_addr + + pvirtq_layout.driver_event_offset), + (void *)((uintptr_t)p_virt_struct_area->phys_addr + + pvirtq_layout.device_event_offset), + p_virt_struct_area->phys_addr, (uint16_t)queue_size, + host_id, header, PACKED_RING, irq_vector); + + vq->usage = MANAGED; + return vq; +} + +static struct nthw_virt_queue *nthw_setup_managed_tx_virt_queue_packed(nthw_dbs_t *p_nthw_dbs, + uint32_t index, uint32_t queue_size, + uint32_t host_id, uint32_t port, uint32_t virtual_port, uint32_t header, + int irq_vector, uint32_t in_order, + struct nthw_memory_descriptor *p_virt_struct_area, + struct nthw_memory_descriptor *p_packet_buffers) +{ + struct pvirtq_struct_layout_s pvirtq_layout; + struct nthw_virt_queue *vq = &txvq[index]; + /* Set size and setup packed vq ring */ + vq->queue_size = queue_size; + if (nthw_setup_managed_virt_queue_packed(vq, &pvirtq_layout, + p_virt_struct_area, + p_packet_buffers, 0, 0) != 0) + return NULL; + + nthw_setup_tx_virt_queue(p_nthw_dbs, index, 0x8000, + 0, /* start wrap ring counter as 1 */ + (void *)((uintptr_t)p_virt_struct_area->phys_addr + + pvirtq_layout.driver_event_offset), + (void *)((uintptr_t)p_virt_struct_area->phys_addr + + pvirtq_layout.device_event_offset), + p_virt_struct_area->phys_addr, (uint16_t)queue_size, + host_id, port, virtual_port, header, PACKED_RING, + irq_vector, in_order); + + vq->usage = MANAGED; + return vq; +} + +/* + * Create a Managed Rx Virt Queue + * + * p_virt_struct_area - Memory that can be used for virtQueue structs + * p_packet_buffers - Memory that can be used for packet buffers. Array must have queue_size entries + * + * Notice: The queue will be created with interrupts disabled. + * If interrupts are required, make sure to call nthw_enable_rx_virt_queue() + * afterwards. + */ +struct nthw_virt_queue * +nthw_setup_managed_rx_virt_queue(nthw_dbs_t *p_nthw_dbs, uint32_t index, + uint32_t queue_size, uint32_t host_id, + uint32_t header, + struct nthw_memory_descriptor *p_virt_struct_area, + struct nthw_memory_descriptor *p_packet_buffers, + uint32_t vq_type, int irq_vector) +{ + switch (vq_type) { + case SPLIT_RING: + return nthw_setup_managed_rx_virt_queue_split(p_nthw_dbs, + index, queue_size, host_id, header, + p_virt_struct_area, p_packet_buffers, irq_vector); + case PACKED_RING: + return nthw_setup_managed_rx_virt_queue_packed(p_nthw_dbs, + index, queue_size, host_id, header, + p_virt_struct_area, p_packet_buffers, irq_vector); + default: + break; + } + return NULL; +} + +/* + * Create a Managed Tx Virt Queue + * + * p_virt_struct_area - Memory that can be used for virtQueue structs + * p_packet_buffers - Memory that can be used for packet buffers. Array must have queue_size entries + * + * Notice: The queue will be created with interrupts disabled. + * If interrupts are required, make sure to call nthw_enable_tx_virt_queue() + * afterwards. + */ +struct nthw_virt_queue *nthw_setup_managed_tx_virt_queue(nthw_dbs_t *p_nthw_dbs, + uint32_t index, uint32_t queue_size, + uint32_t host_id, uint32_t port, uint32_t virtual_port, uint32_t header, + struct nthw_memory_descriptor *p_virt_struct_area, + struct nthw_memory_descriptor *p_packet_buffers, uint32_t vq_type, + int irq_vector, uint32_t in_order) +{ + switch (vq_type) { + case SPLIT_RING: + return nthw_setup_managed_tx_virt_queue_split(p_nthw_dbs, index, + queue_size, host_id, port, virtual_port, + header, irq_vector, in_order, p_virt_struct_area, + p_packet_buffers); + case PACKED_RING: + return nthw_setup_managed_tx_virt_queue_packed(p_nthw_dbs, index, + queue_size, host_id, port, virtual_port, + header, irq_vector, in_order, p_virt_struct_area, + p_packet_buffers); + default: + break; + } + return NULL; +} + +/* + * Packed Ring helper macros + */ +#define avail_flag(vq) ((vq)->avail_wrap_count ? VIRTQ_DESC_F_AVAIL : 0) +#define used_flag_inv(vq) ((vq)->avail_wrap_count ? 0 : VIRTQ_DESC_F_USED) + +#define inc_avail(_vq, _num) \ + do { \ + __typeof__(_vq) (vq) = (_vq); \ + __typeof__(_num) (num) = (_num); \ + (vq)->next_avail += num; \ + if ((vq)->next_avail >= (vq)->queue_size) { \ + (vq)->next_avail -= (vq)->queue_size; \ + (vq)->avail_wrap_count ^= 1; \ + } \ + } while (0) + +#define inc_used(_vq, _num) \ + do { \ + __typeof__(_vq) (vq) = (_vq); \ + __typeof__(_num) (num) = (_num); \ + (vq)->next_used += num; \ + if ((vq)->next_used >= (vq)->queue_size) { \ + (vq)->next_used -= (vq)->queue_size; \ + (vq)->used_wrap_count ^= 1; \ + } \ + } while (0) + +uint16_t nthw_get_rx_packets(struct nthw_virt_queue *rxvq, uint16_t n, + struct nthw_received_packets *rp, uint16_t *nb_pkts) +{ + le16 segs = 0; + uint16_t pkts = 0; + + if (rxvq->vq_type == SPLIT_RING) { + le16 i; + le16 entries_ready = (le16)(rxvq->cached_idx - rxvq->used_idx); + + if (entries_ready < n) { + /* Look for more packets */ + rxvq->cached_idx = rxvq->p_used->idx; + entries_ready = (le16)(rxvq->cached_idx - rxvq->used_idx); + if (entries_ready == 0) { + *nb_pkts = 0; + return 0; + } + + if (n > entries_ready) + n = entries_ready; + } + + /* Give packets - make sure all packets are whole packets. + * Valid because queue_size is always 2^n + */ + const le16 queue_mask = (le16)(rxvq->queue_size - 1); + const ule32 buf_len = rxvq->p_desc[0].len; + + le16 used = rxvq->used_idx; + + for (i = 0; i < n; ++i) { + le32 id = rxvq->p_used->ring[used & queue_mask].id; + + rp[i].addr = rxvq->p_virtual_addr[id].virt_addr; + rp[i].len = rxvq->p_used->ring[used & queue_mask].len; + + uint32_t pkt_len = + ((struct _pkt_hdr_rx *)rp[i].addr)->cap_len; + + if (pkt_len > buf_len) { + /* segmented */ + int nbsegs = (pkt_len + buf_len - 1) / buf_len; + + if (((int)i + nbsegs) > n) { + /* don't have enough segments - break out */ + break; + } + + int ii; + + for (ii = 1; ii < nbsegs; ii++) { + ++i; + id = rxvq->p_used + ->ring[(used + ii) & + queue_mask] + .id; + rp[i].addr = + rxvq->p_virtual_addr[id].virt_addr; + rp[i].len = rxvq->p_used + ->ring[(used + ii) & + queue_mask] + .len; + } + used += nbsegs; + } else { + ++used; + } + + pkts++; + segs = i + 1; + } + + rxvq->used_idx = used; + } else if (rxvq->vq_type == PACKED_RING) { + /* This requires in-order behavior from FPGA */ + int i; + + for (i = 0; i < n; i++) { + struct pvirtq_desc *desc = &rxvq->desc[rxvq->next_used]; + + ule16 flags = desc->flags; + uint8_t avail = !!(flags & VIRTQ_DESC_F_AVAIL); + uint8_t used = !!(flags & VIRTQ_DESC_F_USED); + + if (avail != rxvq->used_wrap_count || + used != rxvq->used_wrap_count) + break; + + rp[pkts].addr = rxvq->p_virtual_addr[desc->id].virt_addr; + rp[pkts].len = desc->len; + pkts++; + + inc_used(rxvq, 1); + } + + segs = pkts; + } + + *nb_pkts = pkts; + return segs; +} + +/* + * Put buffers back into Avail Ring + */ +void nthw_release_rx_packets(struct nthw_virt_queue *rxvq, le16 n) +{ + if (rxvq->vq_type == SPLIT_RING) { + rxvq->am_idx = (le16)(rxvq->am_idx + n); + rxvq->p_avail->idx = rxvq->am_idx; + } else if (rxvq->vq_type == PACKED_RING) { + int i; + /* + * Defer flags update on first segment - due to serialization towards HW and + * when jumbo segments are added + */ + + ule16 first_flags = VIRTQ_DESC_F_WRITE | avail_flag(rxvq) | + used_flag_inv(rxvq); + struct pvirtq_desc *first_desc = &rxvq->desc[rxvq->next_avail]; + + uint32_t len = rxvq->p_virtual_addr[0].len; /* all same size */ + + /* Optimization point: use in-order release */ + + for (i = 0; i < n; i++) { + struct pvirtq_desc *desc = + &rxvq->desc[rxvq->next_avail]; + + desc->id = rxvq->next_avail; + desc->addr = + (ule64)rxvq->p_virtual_addr[desc->id].phys_addr; + desc->len = len; + if (i) + desc->flags = VIRTQ_DESC_F_WRITE | + avail_flag(rxvq) | + used_flag_inv(rxvq); + + inc_avail(rxvq, 1); + } + rte_rmb(); + first_desc->flags = first_flags; + } +} + +#define vq_log_arg(vq, format, ...) + +uint16_t nthw_get_tx_buffers(struct nthw_virt_queue *txvq, uint16_t n, + uint16_t *first_idx, struct nthw_cvirtq_desc *cvq, + struct nthw_memory_descriptor **p_virt_addr) +{ + int m = 0; + le16 queue_mask = (le16)(txvq->queue_size - + 1); /* Valid because queue_size is always 2^n */ + *p_virt_addr = txvq->p_virtual_addr; + + if (txvq->vq_type == SPLIT_RING) { + cvq->s = txvq->p_desc; + cvq->vq_type = SPLIT_RING; + + *first_idx = txvq->tx_descr_avail_idx; + + le16 entries_used = + (le16)((txvq->tx_descr_avail_idx - txvq->cached_idx) & + queue_mask); + le16 entries_ready = (le16)(txvq->queue_size - 1 - entries_used); + + vq_log_arg(txvq, + "ask %i: descrAvail %i, cachedidx %i, used: %i, ready %i used->idx %i\n", + n, txvq->tx_descr_avail_idx, txvq->cached_idx, entries_used, + entries_ready, txvq->p_used->idx); + + if (entries_ready < n) { + /* + * Look for more packets. + * Using the used_idx in the avail ring since they are held synchronous + * because of in-order + */ + txvq->cached_idx = + txvq->p_avail->ring[(txvq->p_used->idx - 1) & + queue_mask]; + + vq_log_arg(txvq, + "_update: get cachedidx %i (used_idx-1 %i)\n", + txvq->cached_idx, + (txvq->p_used->idx - 1) & queue_mask); + entries_used = (le16)((txvq->tx_descr_avail_idx - + txvq->cached_idx) & + queue_mask); + entries_ready = + (le16)(txvq->queue_size - 1 - entries_used); + vq_log_arg(txvq, "new used: %i, ready %i\n", + entries_used, entries_ready); + if (n > entries_ready) + n = entries_ready; + } + } else if (txvq->vq_type == PACKED_RING) { + int i; + + cvq->p = txvq->desc; + cvq->vq_type = PACKED_RING; + + if (txvq->outs.num) { + *first_idx = txvq->outs.next; + uint16_t num = RTE_MIN(n, txvq->outs.num); + + txvq->outs.next = (txvq->outs.next + num) & queue_mask; + txvq->outs.num -= num; + + if (n == num) + return n; + + m = num; + n -= num; + } else { + *first_idx = txvq->next_used; + } + /* iterate the ring - this requires in-order behavior from FPGA */ + for (i = 0; i < n; i++) { + struct pvirtq_desc *desc = &txvq->desc[txvq->next_used]; + + ule16 flags = desc->flags; + uint8_t avail = !!(flags & VIRTQ_DESC_F_AVAIL); + uint8_t used = !!(flags & VIRTQ_DESC_F_USED); + + if (avail != txvq->used_wrap_count || + used != txvq->used_wrap_count) { + n = i; + break; + } + + le16 incr = (desc->id - txvq->next_used) & queue_mask; + + i += incr; + inc_used(txvq, incr + 1); + } + + if (i > n) { + int outs_num = i - n; + + txvq->outs.next = (txvq->next_used - outs_num) & + queue_mask; + txvq->outs.num = outs_num; + } + + } else { + return 0; + } + return m + n; +} + +void nthw_release_tx_buffers(struct nthw_virt_queue *txvq, uint16_t n, + uint16_t n_segs[]) +{ + int i; + + if (txvq->vq_type == SPLIT_RING) { + /* Valid because queue_size is always 2^n */ + le16 queue_mask = (le16)(txvq->queue_size - 1); + + vq_log_arg(txvq, "pkts %i, avail idx %i, start at %i\n", n, + txvq->am_idx, txvq->tx_descr_avail_idx); + for (i = 0; i < n; i++) { + int idx = txvq->am_idx & queue_mask; + + txvq->p_avail->ring[idx] = txvq->tx_descr_avail_idx; + txvq->tx_descr_avail_idx = + (txvq->tx_descr_avail_idx + n_segs[i]) & queue_mask; + txvq->am_idx++; + } + /* Make sure the ring has been updated before HW reads index update */ + rte_mb(); + txvq->p_avail->idx = txvq->am_idx; + vq_log_arg(txvq, "new avail idx %i, descr_idx %i\n", + txvq->p_avail->idx, txvq->tx_descr_avail_idx); + + } else if (txvq->vq_type == PACKED_RING) { + /* + * Defer flags update on first segment - due to serialization towards HW and + * when jumbo segments are added + */ + + ule16 first_flags = avail_flag(txvq) | used_flag_inv(txvq); + struct pvirtq_desc *first_desc = &txvq->desc[txvq->next_avail]; + + for (i = 0; i < n; i++) { + struct pvirtq_desc *desc = + &txvq->desc[txvq->next_avail]; + + desc->id = txvq->next_avail; + desc->addr = + (ule64)txvq->p_virtual_addr[desc->id].phys_addr; + + if (i) + /* bitwise-or here because next flags may already have been setup */ + desc->flags |= avail_flag(txvq) | + used_flag_inv(txvq); + + inc_avail(txvq, 1); + } + /* Proper read barrier before FPGA may see first flags */ + rte_rmb(); + first_desc->flags = first_flags; + } +} + +int nthw_get_rx_queue_ptr(struct nthw_virt_queue *rxvq, uint16_t *index) +{ + uint32_t rx_ptr; + uint32_t loops = 100000; + + dbs_initialize_get_rx_ptr(rxvq->mp_nthw_dbs, rxvq->index); + do { + if (dbs_get_rx_ptr(rxvq->mp_nthw_dbs, &rx_ptr) != 0) + return -1; + if (--loops == 0) + return -1; + usleep(10); + } while (rx_ptr == INDEX_PTR_NOT_VALID); + + *index = (uint16_t)(rx_ptr & 0xffff); + return 0; +} + +int nthw_get_tx_queue_ptr(struct nthw_virt_queue *txvq, uint16_t *index) +{ + uint32_t tx_ptr; + uint32_t loops = 100000; + + dbs_initialize_get_tx_ptr(txvq->mp_nthw_dbs, txvq->index); + do { + if (dbs_get_tx_ptr(txvq->mp_nthw_dbs, &tx_ptr) != 0) + return -1; + if (--loops == 0) + return -1; + usleep(10); + } while (tx_ptr == INDEX_PTR_NOT_VALID); + + *index = (uint16_t)(tx_ptr & 0xffff); + return 0; +} diff --git a/drivers/net/ntnic/ntnic_dbsconfig.h b/drivers/net/ntnic/ntnic_dbsconfig.h new file mode 100644 index 0000000000..ceae535741 --- /dev/null +++ b/drivers/net/ntnic/ntnic_dbsconfig.h @@ -0,0 +1,251 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NTNIC_DBS_CONFIG_H +#define NTNIC_DBS_CONFIG_H + +#include +#include "nthw_drv.h" + +struct nthw_virt_queue; + +struct nthw_memory_descriptor { + void *phys_addr; + void *virt_addr; + uint32_t len; +}; + +#define ule64 uint64_t +#define ule32 uint32_t +#define ule16 uint16_t + +#define MAX_MSIX_VECTORS_PR_VF 8 + +#define SPLIT_RING 0 +#define PACKED_RING 1 +#define IN_ORDER 1 +#define NO_ORDER_REQUIRED 0 + +/* + * SPLIT : This marks a buffer as continuing via the next field. + * PACKED: This marks a buffer as continuing. (packed does not have a next field, so must be + * contiguous) In Used descriptors it must be ignored + */ +#define VIRTQ_DESC_F_NEXT 1 +/* + * SPLIT : This marks a buffer as device write-only (otherwise device read-only). + * PACKED: This marks a descriptor as device write-only (otherwise device read-only). + * PACKED: In a used descriptor, this bit is used to specify whether any data has been written by + * the device into any parts of the buffer. + */ +#define VIRTQ_DESC_F_WRITE 2 +/* + * SPLIT : This means the buffer contains a list of buffer descriptors. + * PACKED: This means the element contains a table of descriptors. + */ +#define VIRTQ_DESC_F_INDIRECT 4 + +/* + * Split Ring virtq Descriptor + */ +#pragma pack(1) +struct virtq_desc { + /* Address (guest-physical). */ + ule64 addr; + /* Length. */ + ule32 len; + /* The flags as indicated above. */ + ule16 flags; + /* Next field if flags & NEXT */ + ule16 next; +}; + +#pragma pack() + +/* + * Packed Ring special structures and defines + * + */ + +#define MAX_PACKED_RING_ELEMENTS (1 << 15) /* 32768 */ + +/* additional packed ring flags */ +#define VIRTQ_DESC_F_AVAIL (1 << 7) +#define VIRTQ_DESC_F_USED (1 << 15) + +/* descr phys address must be 16 byte aligned */ +#pragma pack(push, 16) +struct pvirtq_desc { + /* Buffer Address. */ + ule64 addr; + /* Buffer Length. */ + ule32 len; + /* Buffer ID. */ + ule16 id; + /* The flags depending on descriptor type. */ + ule16 flags; +}; + +#pragma pack(pop) + +/* Enable events */ +#define RING_EVENT_FLAGS_ENABLE 0x0 +/* Disable events */ +#define RING_EVENT_FLAGS_DISABLE 0x1 +/* + * Enable events for a specific descriptor + * (as specified by Descriptor Ring Change Event offset/Wrap Counter). + * Only valid if VIRTIO_F_RING_EVENT_IDX has been negotiated. + */ +#define RING_EVENT_FLAGS_DESC 0x2 +/* The value 0x3 is reserved */ + +struct pvirtq_event_suppress { + union { + struct { + ule16 desc_event_off : 15; /* Descriptor Ring Change Event offset */ + ule16 desc_event_wrap : 1; /* Descriptor Ring Change Event Wrap Counter */ + }; + ule16 desc; /* If desc_event_flags set to RING_EVENT_FLAGS_DESC */ + }; + + /* phys address must be 4 byte aligned */ +#pragma pack(push, 16) + union { + struct { + ule16 desc_event_flags : 2; /* Descriptor Ring Change Event Flags */ + ule16 reserved : 14; /* Reserved, set to 0 */ + }; + ule16 flags; + }; +}; + +#pragma pack(pop) + +/* + * Common virtq descr + */ +#define vq_set_next(_vq, index, nxt) \ + do { \ + __typeof__(_vq) (vq) = (_vq); \ + if ((vq)->vq_type == SPLIT_RING) \ + (vq)->s[index].next = nxt; \ + } while (0) +#define vq_add_flags(_vq, _index, _flgs) \ + do { \ + __typeof__(_vq) (vq) = (_vq); \ + __typeof__(_index) (index) = (_index); \ + __typeof__(_flgs) (flgs) = (_flgs); \ + if ((vq)->vq_type == SPLIT_RING) \ + (vq)->s[index].flags |= flgs; \ + else if ((vq)->vq_type == PACKED_RING) \ + (vq)->p[index].flags |= flgs; \ + } while (0) +#define vq_set_flags(_vq, _index, _flgs) \ + do { \ + __typeof__(_vq) (vq) = (_vq); \ + __typeof__(_index) (index) = (_index); \ + __typeof__(_flgs) (flgs) = (_flgs); \ + if ((vq)->vq_type == SPLIT_RING) \ + (vq)->s[index].flags = flgs; \ + else if ((vq)->vq_type == PACKED_RING) \ + (vq)->p[index].flags = flgs; \ + } while (0) + +struct nthw_virtq_desc_buf { + /* Address (guest-physical). */ + ule64 addr; + /* Length. */ + ule32 len; +} __rte_aligned(16); + +struct nthw_cvirtq_desc { + union { + struct nthw_virtq_desc_buf *b; /* buffer part as is common */ + struct virtq_desc *s; /* SPLIT */ + struct pvirtq_desc *p; /* PACKED */ + }; + uint16_t vq_type; +}; + +/* Setup a virt_queue for a VM */ +struct nthw_virt_queue *nthw_setup_rx_virt_queue(nthw_dbs_t *p_nthw_dbs, + uint32_t index, uint16_t start_idx, + uint16_t start_ptr, void *avail_struct_phys_addr, void *used_struct_phys_addr, + void *desc_struct_phys_addr, uint16_t queue_size, uint32_t host_id, + uint32_t header, uint32_t vq_type, int irq_vector); + +int nthw_enable_rx_virt_queue(struct nthw_virt_queue *rx_vq); +int nthw_disable_rx_virt_queue(struct nthw_virt_queue *rx_vq); +int nthw_release_rx_virt_queue(struct nthw_virt_queue *rxvq); + +struct nthw_virt_queue *nthw_setup_tx_virt_queue(nthw_dbs_t *p_nthw_dbs, + uint32_t index, uint16_t start_idx, + uint16_t start_ptr, void *avail_struct_phys_addr, void *used_struct_phys_addr, + void *desc_struct_phys_addr, uint16_t queue_size, uint32_t host_id, + uint32_t port, uint32_t virtual_port, uint32_t header, uint32_t vq_type, + int irq_vector, uint32_t in_order); + +int nthw_enable_tx_virt_queue(struct nthw_virt_queue *tx_vq); +int nthw_disable_tx_virt_queue(struct nthw_virt_queue *tx_vq); +int nthw_release_tx_virt_queue(struct nthw_virt_queue *txvq); +int nthw_enable_and_change_port_tx_virt_queue(struct nthw_virt_queue *tx_vq, + uint32_t outport); + +struct nthw_virt_queue *nthw_setup_managed_rx_virt_queue(nthw_dbs_t *p_nthw_dbs, + uint32_t index, uint32_t queue_size, + uint32_t host_id, uint32_t header, + struct nthw_memory_descriptor * + p_virt_struct_area, + struct nthw_memory_descriptor * + p_packet_buffers, + uint32_t vq_type, int irq_vector); + +int nthw_release_managed_rx_virt_queue(struct nthw_virt_queue *rxvq); + +struct nthw_virt_queue *nthw_setup_managed_tx_virt_queue(nthw_dbs_t *p_nthw_dbs, + uint32_t index, uint32_t queue_size, + uint32_t host_id, uint32_t port, uint32_t virtual_port, uint32_t header, + struct nthw_memory_descriptor * + p_virt_struct_area, + struct nthw_memory_descriptor * + p_packet_buffers, + uint32_t vq_type, int irq_vector, uint32_t in_order); + +int nthw_release_managed_tx_virt_queue(struct nthw_virt_queue *txvq); + +int nthw_set_tx_qos_config(nthw_dbs_t *p_nthw_dbs, uint32_t port, uint32_t enable, + uint32_t ir, uint32_t bs); + +int nthw_set_tx_qos_rate_global(nthw_dbs_t *p_nthw_dbs, uint32_t multiplier, + uint32_t divider); + +struct nthw_received_packets { + void *addr; + uint32_t len; +}; + +/* + * These functions handles both Split and Packed including merged buffers (jumbo) + */ +uint16_t nthw_get_rx_packets(struct nthw_virt_queue *rxvq, uint16_t n, + struct nthw_received_packets *rp, + uint16_t *nb_pkts); + +void nthw_release_rx_packets(struct nthw_virt_queue *rxvq, uint16_t n); + +uint16_t nthw_get_tx_buffers(struct nthw_virt_queue *txvq, uint16_t n, + uint16_t *first_idx, struct nthw_cvirtq_desc *cvq, + struct nthw_memory_descriptor **p_virt_addr); + +void nthw_release_tx_buffers(struct nthw_virt_queue *txvq, uint16_t n, + uint16_t n_segs[]); + +int nthw_get_rx_queue_ptr(struct nthw_virt_queue *rxvq, uint16_t *index); + +int nthw_get_tx_queue_ptr(struct nthw_virt_queue *txvq, uint16_t *index); + +int nthw_virt_queue_init(struct fpga_info_s *p_fpga_info); + +#endif diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c new file mode 100644 index 0000000000..ce07d5a8cd --- /dev/null +++ b/drivers/net/ntnic/ntnic_ethdev.c @@ -0,0 +1,4256 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include /* sleep() */ +#include +#include +#include +#include +#include +#include + +#include "ntdrv_4ga.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ntlog.h" + +#include "stream_binary_flow_api.h" +#include "nthw_fpga.h" +#include "ntnic_xstats.h" +#include "ntnic_hshconfig.h" +#include "ntnic_ethdev.h" +#include "ntnic_vdpa.h" +#include "ntnic_vf.h" +#include "ntnic_vfio.h" +#include "ntnic_meter.h" + +#include "flow_api.h" + +#ifdef NT_TOOLS +#include "ntconnect.h" +#include "ntconnect_api.h" +#include "ntconnect_modules/ntconn_modules.h" +#endif + +/* Defines: */ + +#define HW_MAX_PKT_LEN (10000) +#define MAX_MTU (HW_MAX_PKT_LEN - RTE_ETHER_HDR_LEN - RTE_ETHER_CRC_LEN) +#define MIN_MTU 46 +#define MIN_MTU_INLINE 512 + +#include "ntnic_dbsconfig.h" + +#define EXCEPTION_PATH_HID 0 + +#define MAX_TOTAL_QUEUES 128 + +#define ONE_G_SIZE 0x40000000 +#define ONE_G_MASK (ONE_G_SIZE - 1) + +#define VIRTUAL_TUNNEL_PORT_OFFSET 72 + +int lag_active; + +static struct { + struct nthw_virt_queue *vq; + int managed; + int rx; +} rel_virt_queue[MAX_REL_VQS]; + +#define MAX_RX_PACKETS 128 +#define MAX_TX_PACKETS 128 + +#if defined(RX_SRC_DUMP_PKTS_DEBUG) || defined(RX_DST_DUMP_PKTS_DEBUG) || \ + defined(TX_SRC_DUMP_PKTS_DEBUG) || defined(TX_DST_DUMP_PKTS_DEBUG) +static void dump_packet_seg(const char *text, uint8_t *data, int len) +{ + int x; + + if (text) + printf("%s (%p, len %i)", text, data, len); + for (x = 0; x < len; x++) { + if (!(x % 16)) + printf("\n%04X:", x); + printf(" %02X", *(data + x)); + } + printf("\n"); +} +#endif + +/* Global statistics: */ +extern const struct rte_flow_ops _dev_flow_ops; +struct pmd_internals *pmd_intern_base; +uint64_t rte_tsc_freq; + +/*------- Tables to store DPDK EAL log levels for nt log modules----------*/ +static int nt_log_module_logtype[NT_LOG_MODULE_COUNT] = { -1 }; +/*Register the custom module binding to EAL --log-level option here*/ +static const char *nt_log_module_eal_name[NT_LOG_MODULE_COUNT] = { + [NT_LOG_MODULE_INDEX(NT_LOG_MODULE_GENERAL)] = "pmd.net.ntnic.general", + [NT_LOG_MODULE_INDEX(NT_LOG_MODULE_NTHW)] = "pmd.net.ntnic.nthw", + [NT_LOG_MODULE_INDEX(NT_LOG_MODULE_FILTER)] = "pmd.net.ntnic.filter", + [NT_LOG_MODULE_INDEX(NT_LOG_MODULE_VDPA)] = "pmd.net.ntnic.vdpa", + [NT_LOG_MODULE_INDEX(NT_LOG_MODULE_FPGA)] = "pmd.net.ntnic.fpga", + [NT_LOG_MODULE_INDEX(NT_LOG_MODULE_NTCONNECT)] = + "pmd.net.ntnic.ntconnect", + [NT_LOG_MODULE_INDEX(NT_LOG_MODULE_ETHDEV)] = "pmd.net.ntnic.ethdev" +}; + +/*--------------------------------------------------------------------------*/ + +rte_spinlock_t hwlock = RTE_SPINLOCK_INITIALIZER; + +static void *lag_management(void *arg); +static void (*previous_handler)(int sig); +static pthread_t shutdown_tid; +int kill_pmd; + +#define ETH_DEV_NTNIC_HELP_ARG "help" +#define ETH_DEV_NTHW_PORTMASK_ARG "portmask" +#define ETH_DEV_NTHW_RXQUEUES_ARG "rxqs" +#define ETH_DEV_NTHW_TXQUEUES_ARG "txqs" +#define ETH_DEV_NTHW_PORTQUEUES_ARG "portqueues" +#define ETH_DEV_NTHW_REPRESENTOR_ARG "representor" +#define ETH_DEV_NTHW_EXCEPTION_PATH_ARG "exception_path" +#define ETH_NTNIC_LAG_PRIMARY_ARG "primary" +#define ETH_NTNIC_LAG_BACKUP_ARG "backup" +#define ETH_NTNIC_LAG_MODE_ARG "mode" +#define ETH_DEV_NTHW_LINK_SPEED_ARG "port.link_speed" +#define ETH_DEV_NTNIC_SUPPORTED_FPGAS_ARG "supported-fpgas" + +#define DVIO_VHOST_DIR_NAME "/usr/local/var/run/" + +static const char *const valid_arguments[] = { + ETH_DEV_NTNIC_HELP_ARG, + ETH_DEV_NTHW_PORTMASK_ARG, + ETH_DEV_NTHW_RXQUEUES_ARG, + ETH_DEV_NTHW_TXQUEUES_ARG, + ETH_DEV_NTHW_PORTQUEUES_ARG, + ETH_DEV_NTHW_REPRESENTOR_ARG, + ETH_DEV_NTHW_EXCEPTION_PATH_ARG, + ETH_NTNIC_LAG_PRIMARY_ARG, + ETH_NTNIC_LAG_BACKUP_ARG, + ETH_NTNIC_LAG_MODE_ARG, + ETH_DEV_NTHW_LINK_SPEED_ARG, + ETH_DEV_NTNIC_SUPPORTED_FPGAS_ARG, + NULL, +}; + +static struct rte_ether_addr eth_addr_vp[MAX_FPGA_VIRTUAL_PORTS_SUPPORTED]; + +/* Functions: */ + +/* + * The set of PCI devices this driver supports + */ +static const struct rte_pci_id nthw_pci_id_map[] = { + { RTE_PCI_DEVICE(NT_HW_PCI_VENDOR_ID, NT_HW_PCI_DEVICE_ID_NT200A02) }, + { RTE_PCI_DEVICE(NT_HW_PCI_VENDOR_ID, NT_HW_PCI_DEVICE_ID_NT50B01) }, + { + .vendor_id = 0, + }, /* sentinel */ +}; + +/* + * Store and get adapter info + */ + +static struct drv_s *g_p_drv[NUM_ADAPTER_MAX] = { NULL }; + +static void store_pdrv(struct drv_s *p_drv) +{ + if (p_drv->adapter_no > NUM_ADAPTER_MAX) { + NT_LOG(ERR, ETHDEV, + "Internal error adapter number %u out of range. Max number of adapters: %u\n", + p_drv->adapter_no, NUM_ADAPTER_MAX); + return; + } + if (g_p_drv[p_drv->adapter_no] != 0) { + NT_LOG(WRN, ETHDEV, + "Overwriting adapter structure for PCI " PCIIDENT_PRINT_STR + " with adapter structure for PCI " PCIIDENT_PRINT_STR + "\n", + PCIIDENT_TO_DOMAIN(g_p_drv[p_drv->adapter_no]->ntdrv.pciident), + PCIIDENT_TO_BUSNR(g_p_drv[p_drv->adapter_no]->ntdrv.pciident), + PCIIDENT_TO_DEVNR(g_p_drv[p_drv->adapter_no]->ntdrv.pciident), + PCIIDENT_TO_FUNCNR(g_p_drv[p_drv->adapter_no]->ntdrv.pciident), + PCIIDENT_TO_DOMAIN(p_drv->ntdrv.pciident), + PCIIDENT_TO_BUSNR(p_drv->ntdrv.pciident), + PCIIDENT_TO_DEVNR(p_drv->ntdrv.pciident), + PCIIDENT_TO_FUNCNR(p_drv->ntdrv.pciident)); + } + rte_spinlock_lock(&hwlock); + g_p_drv[p_drv->adapter_no] = p_drv; + rte_spinlock_unlock(&hwlock); +} + +static struct drv_s *get_pdrv_from_pci(struct rte_pci_addr addr) +{ + int i; + struct drv_s *p_drv = NULL; + + rte_spinlock_lock(&hwlock); + for (i = 0; i < NUM_ADAPTER_MAX; i++) { + if (g_p_drv[i]) { + if (PCIIDENT_TO_DOMAIN(g_p_drv[i]->ntdrv.pciident) == + addr.domain && + PCIIDENT_TO_BUSNR(g_p_drv[i]->ntdrv.pciident) == + addr.bus) { + p_drv = g_p_drv[i]; + break; + } + } + } + rte_spinlock_unlock(&hwlock); + return p_drv; +} + +static struct drv_s *get_pdrv_from_pciident(uint32_t pciident) +{ + struct rte_pci_addr addr; + + addr.domain = PCIIDENT_TO_DOMAIN(pciident); + addr.bus = PCIIDENT_TO_BUSNR(pciident); + addr.devid = PCIIDENT_TO_DEVNR(pciident); + addr.function = PCIIDENT_TO_FUNCNR(pciident); + return get_pdrv_from_pci(addr); +} + +int debug_adapter_show_info(uint32_t pciident, FILE *pfh) +{ + struct drv_s *p_drv = get_pdrv_from_pciident(pciident); + + return nt4ga_adapter_show_info(&p_drv->ntdrv.adapter_info, pfh); +} + +nthw_dbs_t *get_pdbs_from_pci(struct rte_pci_addr pci_addr) +{ + nthw_dbs_t *p_nthw_dbs = NULL; + struct drv_s *p_drv; + + p_drv = get_pdrv_from_pci(pci_addr); + if (p_drv) { + p_nthw_dbs = p_drv->ntdrv.adapter_info.fpga_info.mp_nthw_dbs; + } else { + NT_LOG(ERR, ETHDEV, + "Adapter DBS %p (p_drv=%p) info for adapter with PCI " PCIIDENT_PRINT_STR + " is not found\n", + p_nthw_dbs, p_drv, pci_addr.domain, pci_addr.bus, pci_addr.devid, + pci_addr.function); + } + return p_nthw_dbs; +} + +enum fpga_info_profile get_fpga_profile_from_pci(struct rte_pci_addr pci_addr) +{ + enum fpga_info_profile fpga_profile = FPGA_INFO_PROFILE_UNKNOWN; + struct drv_s *p_drv; + + p_drv = get_pdrv_from_pci(pci_addr); + if (p_drv) { + fpga_profile = p_drv->ntdrv.adapter_info.fpga_info.profile; + } else { + NT_LOG(ERR, ETHDEV, + "FPGA profile (p_drv=%p) for adapter with PCI " PCIIDENT_PRINT_STR + " is not found\n", + p_drv, pci_addr.domain, pci_addr.bus, pci_addr.devid, pci_addr.function); + } + return fpga_profile; +} + +static int string_to_u32(const char *key_str __rte_unused, + const char *value_str, void *extra_args) +{ + if (!value_str || !extra_args) + return -1; + const uint32_t value = strtol(value_str, NULL, 0); + *(uint32_t *)extra_args = value; + return 0; +} + +struct port_link_speed { + int port_id; + int link_speed; +}; + +/* Parse :, e.g 1:10000 */ +static int string_to_port_link_speed(const char *key_str __rte_unused, + const char *value_str, void *extra_args) +{ + if (!value_str || !extra_args) + return -1; + char *semicol; + const uint32_t pid = strtol(value_str, &semicol, 10); + + if (*semicol != ':') + return -1; + const uint32_t lspeed = strtol(++semicol, NULL, 10); + struct port_link_speed *pls = *(struct port_link_speed **)extra_args; + + pls->port_id = pid; + pls->link_speed = lspeed; + ++(*((struct port_link_speed **)(extra_args))); + return 0; +} + +static int dpdk_stats_collect(struct pmd_internals *internals, + struct rte_eth_stats *stats) +{ + unsigned int i; + struct drv_s *p_drv = internals->p_drv; + struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv; + nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat; + nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat; + const int if_index = internals->if_index; + uint64_t rx_total = 0; + uint64_t rx_total_b = 0; + uint64_t tx_total = 0; + uint64_t tx_total_b = 0; + uint64_t tx_err_total = 0; + + if (!p_nthw_stat || !p_nt4ga_stat || !stats || if_index < 0 || + if_index > NUM_ADAPTER_PORTS_MAX) { + NT_LOG(WRN, ETHDEV, "%s - error exit\n", __func__); + return -1; + } + + /* + * Pull the latest port statistic numbers (Rx/Tx pkts and bytes) + * Return values are in the "internals->rxq_scg[]" and "internals->txq_scg[]" arrays + */ + poll_statistics(internals); + + memset(stats, 0, sizeof(*stats)); + for (i = 0; + i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < internals->nb_rx_queues; + i++) { + stats->q_ipackets[i] = internals->rxq_scg[i].rx_pkts; + stats->q_ibytes[i] = internals->rxq_scg[i].rx_bytes; + rx_total += stats->q_ipackets[i]; + rx_total_b += stats->q_ibytes[i]; + } + + for (i = 0; + i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < internals->nb_tx_queues; + i++) { + stats->q_opackets[i] = internals->txq_scg[i].tx_pkts; + stats->q_obytes[i] = internals->txq_scg[i].tx_bytes; + stats->q_errors[i] = internals->txq_scg[i].err_pkts; + tx_total += stats->q_opackets[i]; + tx_total_b += stats->q_obytes[i]; + tx_err_total += stats->q_errors[i]; + } + + stats->imissed = internals->rx_missed; + stats->ipackets = rx_total; + stats->ibytes = rx_total_b; + stats->opackets = tx_total; + stats->obytes = tx_total_b; + stats->oerrors = tx_err_total; + + return 0; +} + +static int dpdk_stats_reset(struct pmd_internals *internals, + struct ntdrv_4ga_s *p_nt_drv, int n_intf_no) +{ + nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat; + nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat; + unsigned int i; + + if (!p_nthw_stat || !p_nt4ga_stat || n_intf_no < 0 || + n_intf_no > NUM_ADAPTER_PORTS_MAX) + return -1; + + pthread_mutex_lock(&p_nt_drv->stat_lck); + + /* Rx */ + for (i = 0; i < internals->nb_rx_queues; i++) { + internals->rxq_scg[i].rx_pkts = 0; + internals->rxq_scg[i].rx_bytes = 0; + internals->rxq_scg[i].err_pkts = 0; + } + + internals->rx_missed = 0; + + /* Tx */ + for (i = 0; i < internals->nb_tx_queues; i++) { + internals->txq_scg[i].tx_pkts = 0; + internals->txq_scg[i].tx_bytes = 0; + internals->txq_scg[i].err_pkts = 0; + } + + p_nt4ga_stat->n_totals_reset_timestamp = time(NULL); + + pthread_mutex_unlock(&p_nt_drv->stat_lck); + + return 0; +} + +/* NOTE: please note the difference between ETH_SPEED_NUM_xxx and ETH_LINK_SPEED_xxx */ +static int nt_link_speed_to_eth_speed_num(enum nt_link_speed_e nt_link_speed) +{ + int eth_speed_num = ETH_SPEED_NUM_NONE; + + switch (nt_link_speed) { + case NT_LINK_SPEED_10M: + eth_speed_num = ETH_SPEED_NUM_10M; + break; + case NT_LINK_SPEED_100M: + eth_speed_num = ETH_SPEED_NUM_100M; + break; + case NT_LINK_SPEED_1G: + eth_speed_num = ETH_SPEED_NUM_1G; + break; + case NT_LINK_SPEED_10G: + eth_speed_num = ETH_SPEED_NUM_10G; + break; + case NT_LINK_SPEED_25G: + eth_speed_num = ETH_SPEED_NUM_25G; + break; + case NT_LINK_SPEED_40G: + eth_speed_num = ETH_SPEED_NUM_40G; + break; + case NT_LINK_SPEED_50G: + eth_speed_num = ETH_SPEED_NUM_50G; + break; + case NT_LINK_SPEED_100G: + eth_speed_num = ETH_SPEED_NUM_100G; + break; + default: + eth_speed_num = ETH_SPEED_NUM_NONE; + break; + } + + return eth_speed_num; +} + +static int nt_link_duplex_to_eth_duplex(enum nt_link_duplex_e nt_link_duplex) +{ + int eth_link_duplex = 0; + + switch (nt_link_duplex) { + case NT_LINK_DUPLEX_FULL: + eth_link_duplex = ETH_LINK_FULL_DUPLEX; + break; + case NT_LINK_DUPLEX_HALF: + eth_link_duplex = ETH_LINK_HALF_DUPLEX; + break; + case NT_LINK_DUPLEX_UNKNOWN: /* fall-through */ + default: + break; + } + return eth_link_duplex; +} + +static int eth_link_update(struct rte_eth_dev *eth_dev, + int wait_to_complete __rte_unused) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + const int n_intf_no = internals->if_index; + struct adapter_info_s *p_adapter_info = + &internals->p_drv->ntdrv.adapter_info; + + if (eth_dev->data->dev_started) { + if (internals->type == PORT_TYPE_VIRTUAL || + internals->type == PORT_TYPE_OVERRIDE) { + eth_dev->data->dev_link.link_status = + ((internals->vport_comm == + VIRT_PORT_NEGOTIATED_NONE) ? + ETH_LINK_DOWN : + ETH_LINK_UP); + eth_dev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE; + eth_dev->data->dev_link.link_duplex = + ETH_LINK_FULL_DUPLEX; + return 0; + } + + const bool port_link_status = + nt4ga_port_get_link_status(p_adapter_info, n_intf_no); + eth_dev->data->dev_link.link_status = + port_link_status ? ETH_LINK_UP : ETH_LINK_DOWN; + + nt_link_speed_t port_link_speed = + nt4ga_port_get_link_speed(p_adapter_info, n_intf_no); + eth_dev->data->dev_link.link_speed = + nt_link_speed_to_eth_speed_num(port_link_speed); + + nt_link_duplex_t nt_link_duplex = + nt4ga_port_get_link_duplex(p_adapter_info, n_intf_no); + eth_dev->data->dev_link.link_duplex = + nt_link_duplex_to_eth_duplex(nt_link_duplex); + } else { + eth_dev->data->dev_link.link_status = ETH_LINK_DOWN; + eth_dev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE; + eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; + } + return 0; +} + +static int eth_stats_get(struct rte_eth_dev *eth_dev, + struct rte_eth_stats *stats) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + dpdk_stats_collect(internals, stats); + return 0; +} + +static int eth_stats_reset(struct rte_eth_dev *eth_dev) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + struct drv_s *p_drv = internals->p_drv; + struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv; + const int if_index = internals->if_index; + + dpdk_stats_reset(internals, p_nt_drv, if_index); + return 0; +} + +static uint32_t nt_link_speed_capa_to_eth_speed_capa(int nt_link_speed_capa) +{ + uint32_t eth_speed_capa = 0; + + if (nt_link_speed_capa & NT_LINK_SPEED_10M) + eth_speed_capa |= ETH_LINK_SPEED_10M; + if (nt_link_speed_capa & NT_LINK_SPEED_100M) + eth_speed_capa |= ETH_LINK_SPEED_100M; + if (nt_link_speed_capa & NT_LINK_SPEED_1G) + eth_speed_capa |= ETH_LINK_SPEED_1G; + if (nt_link_speed_capa & NT_LINK_SPEED_10G) + eth_speed_capa |= ETH_LINK_SPEED_10G; + if (nt_link_speed_capa & NT_LINK_SPEED_25G) + eth_speed_capa |= ETH_LINK_SPEED_25G; + if (nt_link_speed_capa & NT_LINK_SPEED_40G) + eth_speed_capa |= ETH_LINK_SPEED_40G; + if (nt_link_speed_capa & NT_LINK_SPEED_50G) + eth_speed_capa |= ETH_LINK_SPEED_50G; + if (nt_link_speed_capa & NT_LINK_SPEED_100G) + eth_speed_capa |= ETH_LINK_SPEED_100G; + + return eth_speed_capa; +} + +#define RTE_RSS_5TUPLE (ETH_RSS_IP | ETH_RSS_TCP | ETH_RSS_UDP) + +static int eth_dev_infos_get(struct rte_eth_dev *eth_dev, + struct rte_eth_dev_info *dev_info) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + const int n_intf_no = internals->if_index; + struct adapter_info_s *p_adapter_info = + &internals->p_drv->ntdrv.adapter_info; + + dev_info->if_index = internals->if_index; + dev_info->driver_name = internals->name; + dev_info->max_mac_addrs = NUM_MAC_ADDRS_PER_PORT; + dev_info->max_rx_pktlen = HW_MAX_PKT_LEN; + dev_info->max_mtu = MAX_MTU; + if (p_adapter_info->fpga_info.profile == FPGA_INFO_PROFILE_INLINE) + dev_info->min_mtu = MIN_MTU_INLINE; + + else + dev_info->min_mtu = MIN_MTU; + + if (internals->p_drv) { + dev_info->max_rx_queues = internals->nb_rx_queues; + dev_info->max_tx_queues = internals->nb_tx_queues; + + dev_info->min_rx_bufsize = 64; + + const uint32_t nt_port_speed_capa = + nt4ga_port_get_link_speed_capabilities(p_adapter_info, + n_intf_no); + dev_info->speed_capa = nt_link_speed_capa_to_eth_speed_capa(nt_port_speed_capa); + } + + dev_info->flow_type_rss_offloads = + RTE_RSS_5TUPLE | RTE_ETH_RSS_C_VLAN | + RTE_ETH_RSS_LEVEL_INNERMOST | RTE_ETH_RSS_L3_SRC_ONLY | + RTE_ETH_RSS_LEVEL_OUTERMOST | RTE_ETH_RSS_L3_DST_ONLY; + /* + * NT hashing algorithm doesn't use key, so it is just a fake key length to + * feet testpmd requirements. + */ + dev_info->hash_key_size = 1; + + return 0; +} + +static __rte_always_inline int +copy_virtqueue_to_mbuf(struct rte_mbuf *mbuf, struct rte_mempool *mb_pool, + struct nthw_received_packets *hw_recv, int max_segs, + uint16_t data_len) +{ + int src_pkt = 0; + /* + * 1. virtqueue packets may be segmented + * 2. the mbuf size may be too small and may need to be segmented + */ + char *data = (char *)hw_recv->addr + SG_HDR_SIZE; + char *dst = (char *)mbuf->buf_addr + RTE_PKTMBUF_HEADROOM; + + /* set packet length */ + mbuf->pkt_len = data_len - SG_HDR_SIZE; + +#ifdef RX_MERGE_SEGMENT_DEBUG + void *dbg_src_start = hw_recv->addr; + void *dbg_dst_start = dst; +#endif + + int remain = mbuf->pkt_len; + /* First cpy_size is without header */ + int cpy_size = (data_len > SG_HW_RX_PKT_BUFFER_SIZE) ? + SG_HW_RX_PKT_BUFFER_SIZE - SG_HDR_SIZE : + remain; + + struct rte_mbuf *m = mbuf; /* if mbuf segmentation is needed */ + + while (++src_pkt <= max_segs) { + /* keep track of space in dst */ + int cpto_size = rte_pktmbuf_tailroom(m); + +#ifdef RX_MERGE_SEGMENT_DEBUG + printf("src copy size %i\n", cpy_size); +#endif + + if (cpy_size > cpto_size) { + int new_cpy_size = cpto_size; + +#ifdef RX_MERGE_SEGMENT_DEBUG + printf("Seg %i: mbuf first cpy src off 0x%" PRIX64 ", dst off 0x%" PRIX64 ", size %i\n", + mbuf->nb_segs - 1, + (uint64_t)data - (uint64_t)dbg_src_start, + (uint64_t)dst - (uint64_t)dbg_dst_start, + new_cpy_size); +#endif + rte_memcpy((void *)dst, (void *)data, new_cpy_size); + m->data_len += new_cpy_size; + remain -= new_cpy_size; + cpy_size -= new_cpy_size; + + data += new_cpy_size; + + /* + * Loop if remaining data from this virtqueue seg cannot fit in one extra + * mbuf + */ + do { + m->next = rte_pktmbuf_alloc(mb_pool); + if (unlikely(!m->next)) + return -1; + m = m->next; + + /* Headroom is not needed in chained mbufs */ + rte_pktmbuf_prepend(m, rte_pktmbuf_headroom(m)); + dst = (char *)m->buf_addr; + m->data_len = 0; + m->pkt_len = 0; + +#ifdef RX_MERGE_SEGMENT_DEBUG + dbg_dst_start = dst; +#endif + cpto_size = rte_pktmbuf_tailroom(m); + + int actual_cpy_size = (cpy_size > cpto_size) ? + cpto_size : + cpy_size; +#ifdef RX_MERGE_SEGMENT_DEBUG + printf("new dst mbuf seg - size %i\n", + cpto_size); + printf("Seg %i: mbuf cpy src off 0x%" PRIX64 ", dst off 0x%" PRIX64 ", size %i\n", + mbuf->nb_segs, + (uint64_t)data - (uint64_t)dbg_src_start, + (uint64_t)dst - (uint64_t)dbg_dst_start, + actual_cpy_size); +#endif + + rte_memcpy((void *)dst, (void *)data, + actual_cpy_size); + m->pkt_len += actual_cpy_size; + m->data_len += actual_cpy_size; + + remain -= actual_cpy_size; + cpy_size -= actual_cpy_size; + + data += actual_cpy_size; + + mbuf->nb_segs++; + + } while (cpy_size && remain); + + } else { + /* all data from this virtqueue segment can fit in current mbuf */ +#ifdef RX_MERGE_SEGMENT_DEBUG + printf("Copy all into Seg %i: %i bytes, src off 0x%" PRIX64 + ", dst off 0x%" PRIX64 "\n", + mbuf->nb_segs - 1, cpy_size, + (uint64_t)data - (uint64_t)dbg_src_start, + (uint64_t)dst - (uint64_t)dbg_dst_start); +#endif + rte_memcpy((void *)dst, (void *)data, cpy_size); + m->data_len += cpy_size; + if (mbuf->nb_segs > 1) + m->pkt_len += cpy_size; + remain -= cpy_size; + } + + /* packet complete - all data from current virtqueue packet has been copied */ + if (remain == 0) + break; + /* increment dst to data end */ + dst = rte_pktmbuf_mtod_offset(m, char *, m->data_len); + /* prepare for next virtqueue segment */ + data = (char *)hw_recv[src_pkt] + .addr; /* following packets are full data */ + +#ifdef RX_MERGE_SEGMENT_DEBUG + dbg_src_start = data; +#endif + cpy_size = (remain > SG_HW_RX_PKT_BUFFER_SIZE) ? + SG_HW_RX_PKT_BUFFER_SIZE : + remain; +#ifdef RX_MERGE_SEGMENT_DEBUG + printf("next src buf\n"); +#endif + }; + + if (src_pkt > max_segs) { + NT_LOG(ERR, ETHDEV, + "Did not receive correct number of segment for a whole packet"); + return -1; + } + + return src_pkt; +} + +static uint16_t eth_dev_rx_scg(void *queue, struct rte_mbuf **bufs, + uint16_t nb_pkts) +{ + unsigned int i; + struct rte_mbuf *mbuf; + struct ntnic_rx_queue *rx_q = queue; + uint16_t num_rx = 0; + + struct nthw_received_packets hw_recv[MAX_RX_PACKETS]; + + if (kill_pmd) + return 0; + +#ifdef DEBUG_PRINT_APPROX_CPU_LOAD + dbg_print_approx_cpu_load_rx_called(rx_q->port); +#endif + + if (unlikely(nb_pkts == 0)) + return 0; + + if (nb_pkts > MAX_RX_PACKETS) + nb_pkts = MAX_RX_PACKETS; + + uint16_t whole_pkts; + uint16_t hw_recv_pkt_segs = + nthw_get_rx_packets(rx_q->vq, nb_pkts, hw_recv, &whole_pkts); + + if (!hw_recv_pkt_segs) { +#ifdef DEBUG_PRINT_APPROX_CPU_LOAD + dbg_print_approx_cpu_load_rx_done(rx_q->port, 0); +#endif + + return 0; + } + +#ifdef NT_DEBUG_STAT + dbg_rx_queue(rx_q, + hw_recv_pkt_segs); /* _update debug statistics with new rx packet count */ +#endif + + nb_pkts = whole_pkts; + +#ifdef RX_MERGE_SEGMENT_DEBUG + printf("\n---------- DPDK Rx ------------\n"); + printf("[Port %i] Pkts recv %i on hw queue index %i: tot segs %i, " + "vq buf %i, vq header size %i\n", + rx_q->port, nb_pkts, rx_q->queue.hw_id, hw_recv_pkt_segs, + SG_HW_RX_PKT_BUFFER_SIZE, SG_HDR_SIZE); +#endif + + int src_pkt = 0; /* from 0 to hw_recv_pkt_segs */ + + for (i = 0; i < nb_pkts; i++) { + bufs[i] = rte_pktmbuf_alloc(rx_q->mb_pool); + if (!bufs[i]) { + printf("ERROR - no more buffers mbuf in mempool\n"); + goto err_exit; + } + mbuf = bufs[i]; + + struct _pkt_hdr_rx *phdr = + (struct _pkt_hdr_rx *)hw_recv[src_pkt].addr; + +#ifdef RX_MERGE_SEGMENT_DEBUG + printf("\nRx pkt #%i: vq pkt len %i, segs %i -> mbuf size %i, headroom size %i\n", + i, phdr->cap_len - SG_HDR_SIZE, + (phdr->cap_len + SG_HW_RX_PKT_BUFFER_SIZE - 1) / + SG_HW_RX_PKT_BUFFER_SIZE, + rte_pktmbuf_tailroom(mbuf), rte_pktmbuf_headroom(mbuf)); +#endif + +#ifdef RX_SRC_DUMP_PKTS_DEBUG + { + int d, _segs = (phdr->cap_len + + SG_HW_RX_PKT_BUFFER_SIZE - 1) / + SG_HW_RX_PKT_BUFFER_SIZE; + int _size = phdr->cap_len; + + printf("Rx packet dump: pkt #%i hdr rx port %i, pkt len %i, segs %i\n", + i, phdr->port, phdr->cap_len - SG_HDR_SIZE, + _segs); + for (d = 0; d < _segs; d++) { + printf("Dump seg %i:\n", d); + dump_packet_seg("Vq seg:", hw_recv[src_pkt + d].addr, + _size > SG_HW_RX_PKT_BUFFER_SIZE ? + SG_HW_RX_PKT_BUFFER_SIZE : + _size); + _size -= SG_HW_RX_PKT_BUFFER_SIZE; + } + } +#endif + + if (phdr->cap_len < SG_HDR_SIZE) { + printf("Pkt len of zero received. No header!! - dropping packets\n"); + rte_pktmbuf_free(mbuf); + goto err_exit; + } + + { + if (phdr->cap_len <= SG_HW_RX_PKT_BUFFER_SIZE && + (phdr->cap_len - SG_HDR_SIZE) <= + rte_pktmbuf_tailroom(mbuf)) { +#ifdef RX_MERGE_SEGMENT_DEBUG + printf("Simple copy vq -> mbuf %p size %i\n", + rte_pktmbuf_mtod(mbuf, void *), + phdr->cap_len); +#endif + mbuf->data_len = phdr->cap_len - SG_HDR_SIZE; + rte_memcpy(rte_pktmbuf_mtod(mbuf, char *), + (char *)hw_recv[src_pkt].addr + + SG_HDR_SIZE, + mbuf->data_len); + + mbuf->pkt_len = mbuf->data_len; + src_pkt++; + } else { + int cpy_segs = copy_virtqueue_to_mbuf(mbuf, rx_q->mb_pool, + &hw_recv[src_pkt], + hw_recv_pkt_segs - src_pkt, + phdr->cap_len); + if (cpy_segs < 0) { + /* Error */ + rte_pktmbuf_free(mbuf); + goto err_exit; + } + src_pkt += cpy_segs; + } + +#ifdef RX_DST_DUMP_PKTS_DEBUG + { + struct rte_mbuf *m = mbuf; + + printf("\nRx final mbuf:\n"); + for (int ii = 0; m && ii < m->nb_segs; ii++) { + printf(" seg %i len %i\n", ii, + m->data_len); + printf(" seg dump:\n"); + dump_packet_seg("mbuf seg:", + rte_pktmbuf_mtod(m, uint8_t *), + m->data_len); + m = m->next; + } + } +#endif + + num_rx++; + + mbuf->ol_flags &= + ~(RTE_MBUF_F_RX_FDIR_ID | RTE_MBUF_F_RX_FDIR); + mbuf->port = (uint16_t)-1; + + if (phdr->color_type == 0) { + if (phdr->port >= VIRTUAL_TUNNEL_PORT_OFFSET && + ((phdr->color >> 24) == 0x02)) { + /* VNI in color of descriptor add port as well */ + mbuf->hash.fdir.hi = + ((uint32_t)phdr->color & + 0xffffff) | + ((uint32_t)phdr->port + << 24); + mbuf->hash.fdir.lo = + (uint32_t)phdr->fid; + mbuf->ol_flags |= RTE_MBUF_F_RX_FDIR_ID; + + NT_LOG(DBG, ETHDEV, + "POP'ed packet received that missed on inner match. color = %08x, port %i, tunnel-match flow stat id %i", + phdr->color, phdr->port, + phdr->fid); + } + + } else { + if (phdr->color) { + mbuf->hash.fdir.hi = + phdr->color & + (NT_MAX_COLOR_FLOW_STATS - 1); + mbuf->ol_flags |= + RTE_MBUF_F_RX_FDIR_ID | + RTE_MBUF_F_RX_FDIR; + } + } + } + } + +err_exit: + nthw_release_rx_packets(rx_q->vq, hw_recv_pkt_segs); + +#ifdef DEBUG_PRINT_APPROX_CPU_LOAD + dbg_print_approx_cpu_load_rx_done(rx_q->port, num_rx); +#endif + +#ifdef RX_MERGE_SEGMENT_DEBUG + /* + * When the application double frees a mbuf, it will become a doublet in the memory pool + * This is obvious a bug in application, but can be verified here to some extend at least + */ + uint64_t addr = (uint64_t)bufs[0]->buf_addr; + + for (int i = 1; i < num_rx; i++) { + if (bufs[i]->buf_addr == addr) { + printf("Duplicate packet addresses! num_rx %i\n", + num_rx); + for (int ii = 0; ii < num_rx; ii++) { + printf("bufs[%i]->buf_addr %p\n", ii, + bufs[ii]->buf_addr); + } + } + } +#endif + + return num_rx; +} + +int copy_mbuf_to_virtqueue(struct nthw_cvirtq_desc *cvq_desc, + uint16_t vq_descr_idx, + struct nthw_memory_descriptor *vq_bufs, int max_segs, + struct rte_mbuf *mbuf) +{ + /* + * 1. mbuf packet may be segmented + * 2. the virtqueue buffer size may be too small and may need to be segmented + */ + + char *data = rte_pktmbuf_mtod(mbuf, char *); + char *dst = (char *)vq_bufs[vq_descr_idx].virt_addr + SG_HDR_SIZE; + + int remain = mbuf->pkt_len; + int cpy_size = mbuf->data_len; + +#ifdef CPY_MBUF_TO_VQUEUE_DEBUG + printf("src copy size %i\n", cpy_size); +#endif + + struct rte_mbuf *m = mbuf; + int cpto_size = SG_HW_TX_PKT_BUFFER_SIZE - SG_HDR_SIZE; + + cvq_desc->b[vq_descr_idx].len = SG_HDR_SIZE; + + int cur_seg_num = 0; /* start from 0 */ + + while (m) { + /* Can all data in current src segment be in current dest segment */ + if (cpy_size > cpto_size) { + int new_cpy_size = cpto_size; + +#ifdef CPY_MBUF_TO_VQUEUE_DEBUG + printf("Seg %i: virtq buf first cpy src offs %u, dst offs 0x%" PRIX64 ", size %i\n", + cur_seg_num, + (uint64_t)data - rte_pktmbuf_mtod(m, uint64_t), + (uint64_t)dst - + (uint64_t)vq_bufs[vq_descr_idx].virt_addr, + new_cpy_size); +#endif + rte_memcpy((void *)dst, (void *)data, new_cpy_size); + + cvq_desc->b[vq_descr_idx].len += new_cpy_size; + + remain -= new_cpy_size; + cpy_size -= new_cpy_size; + + data += new_cpy_size; + + /* + * Loop if remaining data from this virtqueue seg cannot fit in one extra + * mbuf + */ + do { + vq_add_flags(cvq_desc, vq_descr_idx, + VIRTQ_DESC_F_NEXT); + + int next_vq_descr_idx = + VIRTQ_DESCR_IDX_NEXT(vq_descr_idx); + + vq_set_next(cvq_desc, vq_descr_idx, + next_vq_descr_idx); + + vq_descr_idx = next_vq_descr_idx; + + vq_set_flags(cvq_desc, vq_descr_idx, 0); + vq_set_next(cvq_desc, vq_descr_idx, 0); + + if (++cur_seg_num > max_segs) + break; + + dst = (char *)vq_bufs[vq_descr_idx].virt_addr; + cpto_size = SG_HW_TX_PKT_BUFFER_SIZE; + + int actual_cpy_size = (cpy_size > cpto_size) ? + cpto_size : + cpy_size; +#ifdef CPY_MBUF_TO_VQUEUE_DEBUG + printf("Tx vq buf seg %i: virtq cpy %i - offset 0x%" PRIX64 "\n", + cur_seg_num, actual_cpy_size, + (uint64_t)dst - + (uint64_t)vq_bufs[vq_descr_idx] + .virt_addr); +#endif + rte_memcpy((void *)dst, (void *)data, + actual_cpy_size); + + cvq_desc->b[vq_descr_idx].len = actual_cpy_size; + + remain -= actual_cpy_size; + cpy_size -= actual_cpy_size; + cpto_size -= actual_cpy_size; + + data += actual_cpy_size; + + } while (cpy_size && remain); + + } else { + /* All data from this segment can fit in current virtqueue buffer */ +#ifdef CPY_MBUF_TO_VQUEUE_DEBUG + printf("Tx vq buf seg %i: Copy %i bytes - offset %u\n", + cur_seg_num, cpy_size, + (uint64_t)dst - + (uint64_t)vq_bufs[vq_descr_idx].virt_addr); +#endif + + rte_memcpy((void *)dst, (void *)data, cpy_size); + + cvq_desc->b[vq_descr_idx].len += cpy_size; + + remain -= cpy_size; + cpto_size -= cpy_size; + } + + /* Packet complete - all segments from current mbuf has been copied */ + if (remain == 0) + break; + /* increment dst to data end */ + dst = (char *)vq_bufs[vq_descr_idx].virt_addr + + cvq_desc->b[vq_descr_idx].len; + + m = m->next; + if (!m) { + NT_LOG(ERR, ETHDEV, "ERROR: invalid packet size\n"); + break; + } + + /* Prepare for next mbuf segment */ + data = rte_pktmbuf_mtod(m, char *); + cpy_size = m->data_len; + }; + + cur_seg_num++; + if (cur_seg_num > max_segs) { + NT_LOG(ERR, ETHDEV, + "Did not receive correct number of segment for a whole packet"); + return -1; + } + + return cur_seg_num; +} + +static uint16_t eth_dev_tx_scg(void *queue, struct rte_mbuf **bufs, + uint16_t nb_pkts) +{ + uint16_t pkt; + uint16_t first_vq_descr_idx = 0; + + struct nthw_cvirtq_desc cvq_desc; + + struct nthw_memory_descriptor *vq_bufs; + + struct ntnic_tx_queue *tx_q = queue; + + int nb_segs = 0, i; + int pkts_sent = 0; + uint16_t nb_segs_arr[MAX_TX_PACKETS]; + + if (kill_pmd) + return 0; + + if (nb_pkts > MAX_TX_PACKETS) + nb_pkts = MAX_TX_PACKETS; + +#ifdef TX_CHAINING_DEBUG + printf("\n---------- DPDK Tx ------------\n"); +#endif + + /* + * count all segments needed to contain all packets in vq buffers + */ + for (i = 0; i < nb_pkts; i++) { + if (bufs[i]->pkt_len < 60) { + bufs[i]->pkt_len = 60; + bufs[i]->data_len = 60; + } + + /* build the num segments array for segmentation control and release function */ + int vq_segs = NUM_VQ_SEGS(bufs[i]->pkt_len); + + nb_segs_arr[i] = vq_segs; + nb_segs += vq_segs; + } + if (!nb_segs) + goto exit_out; + +#ifdef TX_CHAINING_DEBUG + printf("[Port %i] Mbufs for Tx: tot segs %i, packets %i, mbuf size %i, headroom size %i\n", + tx_q->port, nb_segs, nb_pkts, + bufs[0]->buf_len - rte_pktmbuf_headroom(bufs[0]), + rte_pktmbuf_headroom(bufs[0])); +#endif + + int got_nb_segs = + nthw_get_tx_buffers(tx_q->vq, nb_segs, &first_vq_descr_idx, + &cvq_desc /*&vq_descr,*/, &vq_bufs); + if (!got_nb_segs) { +#ifdef TX_CHAINING_DEBUG + printf("Zero segments got - back pressure from HW\n"); +#endif + goto exit_out; + } + + /* + * we may get less vq buffers than we have asked for + * calculate last whole packet that can fit into what + * we have got + */ + while (got_nb_segs < nb_segs) { + if (!--nb_pkts) + goto exit_out; + nb_segs -= NUM_VQ_SEGS(bufs[nb_pkts]->pkt_len); + if (nb_segs <= 0) + goto exit_out; + } + + /* + * nb_pkts & nb_segs, got it all, ready to copy + */ + int seg_idx = 0; + int last_seg_idx = seg_idx; + + for (pkt = 0; pkt < nb_pkts; ++pkt) { + uint16_t vq_descr_idx = VIRTQ_DESCR_IDX(seg_idx); + + vq_set_flags(&cvq_desc, vq_descr_idx, 0); + vq_set_next(&cvq_desc, vq_descr_idx, 0); + + struct _pkt_hdr_tx *hdr_tx = + (struct _pkt_hdr_tx *)vq_bufs[vq_descr_idx].virt_addr; + /* Set the header to all zeros */ + memset(hdr_tx, 0, SG_HDR_SIZE); + + /* + * Set the NT DVIO0 header fields + * + * Applicable for Vswitch only. + * For other product types the header values are "don't care" and we leave them as + * all zeros. + */ + if (tx_q->profile == FPGA_INFO_PROFILE_VSWITCH) { + hdr_tx->bypass_port = tx_q->target_id; + + /* set packet length */ + hdr_tx->cap_len = bufs[pkt]->pkt_len + SG_HDR_SIZE; + } + +#ifdef TX_CHAINING_DEBUG + printf("\nTx pkt #%i: pkt segs %i, pkt len %i -> vq buf size %i, vq header size %i\n", + pkt, bufs[pkt]->nb_segs, bufs[pkt]->pkt_len, + SG_HW_TX_PKT_BUFFER_SIZE, SG_HDR_SIZE); + +#ifdef TX_SRC_DUMP_PKTS_DEBUG + { + struct rte_mbuf *m = bufs[pkt]; + int ii; + + printf("Dump src mbuf:\n"); + for (ii = 0; ii < bufs[pkt]->nb_segs; ii++) { + printf(" seg %i len %i\n", ii, m->data_len); + printf(" seg dump:\n"); + dump_packet_seg("mbuf seg:", + rte_pktmbuf_mtod(m, uint8_t *), + m->data_len); + m = m->next; + } + } +#endif + +#endif + + if (bufs[pkt]->nb_segs == 1 && nb_segs_arr[pkt] == 1) { +#ifdef TX_CHAINING_DEBUG + printf("Simple copy %i bytes - mbuf -> vq\n", + bufs[pkt]->pkt_len); +#endif + rte_memcpy((void *)((char *)vq_bufs[vq_descr_idx].virt_addr + + SG_HDR_SIZE), + rte_pktmbuf_mtod(bufs[pkt], void *), + bufs[pkt]->pkt_len); + + cvq_desc.b[vq_descr_idx].len = + bufs[pkt]->pkt_len + SG_HDR_SIZE; + + seg_idx++; + } else { + int cpy_segs = copy_mbuf_to_virtqueue(&cvq_desc, + vq_descr_idx, vq_bufs, + nb_segs - last_seg_idx, bufs[pkt]); + if (cpy_segs < 0) + break; + seg_idx += cpy_segs; + } + +#ifdef TX_DST_DUMP_PKTS_DEBUG + int d, tot_size = 0; + + for (d = last_seg_idx; d < seg_idx; d++) + tot_size += cvq_desc.b[VIRTQ_DESCR_IDX(d)].len; + printf("\nDump final Tx vq pkt %i, size %i, tx port %i, bypass id %i, using hw queue index %i\n", + pkt, tot_size, tx_q->port, hdr_tx->bypass_port, + tx_q->queue.hw_id); + for (d = last_seg_idx; d < seg_idx; d++) { + char str[32]; + + sprintf(str, "Vq seg %i:", d - last_seg_idx); + dump_packet_seg(str, + vq_bufs[VIRTQ_DESCR_IDX(d)].virt_addr, + cvq_desc.b[VIRTQ_DESCR_IDX(d)].len); + } +#endif + + last_seg_idx = seg_idx; + rte_pktmbuf_free(bufs[pkt]); + pkts_sent++; + } + +#ifdef TX_CHAINING_DEBUG + printf("\nTx final vq setup:\n"); + for (int i = 0; i < nb_segs; i++) { + int idx = VIRTQ_DESCR_IDX(i); + + if (cvq_desc.vq_type == SPLIT_RING) { + printf("virtq descr %i, len %i, flags %04x, next %i\n", + idx, cvq_desc.b[idx].len, cvq_desc.s[idx].flags, + cvq_desc.s[idx].next); + } + } +#endif + +exit_out: + + if (pkts_sent) { +#ifdef TX_CHAINING_DEBUG + printf("Release virtq segs %i\n", nb_segs); +#endif + nthw_release_tx_buffers(tx_q->vq, pkts_sent, nb_segs_arr); + } + return pkts_sent; +} + +static int allocate_hw_virtio_queues(struct rte_eth_dev *eth_dev, int vf_num, + struct hwq_s *hwq, int num_descr, + int buf_size) +{ + int i, res; + uint32_t size; + uint64_t iova_addr; + + NT_LOG(DBG, ETHDEV, + "***** Configure IOMMU for HW queues on VF %i *****\n", vf_num); + + /* Just allocate 1MB to hold all combined descr rings */ + uint64_t tot_alloc_size = 0x100000 + buf_size * num_descr; + + void *virt = rte_malloc_socket("VirtQDescr", tot_alloc_size, + ALIGN_SIZE(tot_alloc_size), + eth_dev->data->numa_node); + if (!virt) + return -1; + + uint64_t gp_offset = (uint64_t)virt & ONE_G_MASK; + rte_iova_t hpa = rte_malloc_virt2iova(virt); + + NT_LOG(DBG, ETHDEV, + "Allocated virtio descr rings : virt %p [0x%" PRIX64 + "], hpa %p [0x%" PRIX64 "]\n", + virt, gp_offset, hpa, hpa & ONE_G_MASK); + + /* + * Same offset on both HPA and IOVA + * Make sure 1G boundary is never crossed + */ + if (((hpa & ONE_G_MASK) != gp_offset) || + (((uint64_t)virt + tot_alloc_size) & ~ONE_G_MASK) != + ((uint64_t)virt & ~ONE_G_MASK)) { + NT_LOG(ERR, ETHDEV, + "*********************************************************\n"); + NT_LOG(ERR, ETHDEV, + "ERROR, no optimal IOMMU mapping available hpa : %016lx (%016lx), gp_offset : %016lx size %u\n", + hpa, hpa & ONE_G_MASK, gp_offset, tot_alloc_size); + NT_LOG(ERR, ETHDEV, + "*********************************************************\n"); + + rte_free(virt); + + /* Just allocate 1MB to hold all combined descr rings */ + size = 0x100000; + void *virt = rte_malloc_socket("VirtQDescr", size, 4096, + eth_dev->data->numa_node); + if (!virt) + return -1; + + res = nt_vfio_dma_map(vf_num, virt, &iova_addr, size); + + NT_LOG(DBG, ETHDEV, "VFIO MMAP res %i, vf_num %i\n", res, + vf_num); + if (res != 0) + return -1; + + hwq->vf_num = vf_num; + hwq->virt_queues_ctrl.virt_addr = virt; + hwq->virt_queues_ctrl.phys_addr = (void *)iova_addr; + hwq->virt_queues_ctrl.len = size; + + NT_LOG(DBG, ETHDEV, + "Allocated for virtio descr rings combined 1MB : %p, IOVA %016lx\n", + virt, iova_addr); + + size = num_descr * sizeof(struct nthw_memory_descriptor); + hwq->pkt_buffers = rte_zmalloc_socket("rx_pkt_buffers", size, + 64, eth_dev->data->numa_node); + if (!hwq->pkt_buffers) { + NT_LOG(ERR, ETHDEV, + "Failed to allocated buffer array for hw-queue %p, " + "total size %i, elements %i\n", + hwq->pkt_buffers, size, num_descr); + rte_free(virt); + return -1; + } + + size = buf_size * num_descr; + void *virt_addr = rte_malloc_socket("pkt_buffer_pkts", size, + 4096, + eth_dev->data->numa_node); + if (!virt_addr) { + NT_LOG(ERR, ETHDEV, + "Failed allocate packet buffers for hw-queue %p, " + "buf size %i, elements %i\n", + hwq->pkt_buffers, buf_size, num_descr); + rte_free(hwq->pkt_buffers); + rte_free(virt); + return -1; + } + + res = nt_vfio_dma_map(vf_num, virt_addr, &iova_addr, size); + + NT_LOG(DBG, ETHDEV, + "VFIO MMAP res %i, virt %p, iova %016lx, vf_num %i, num " + "pkt bufs %i, tot size %i\n", + res, virt_addr, iova_addr, vf_num, num_descr, size); + + if (res != 0) + return -1; + + for (i = 0; i < num_descr; i++) { + hwq->pkt_buffers[i].virt_addr = + (void *)((char *)virt_addr + + ((uint64_t)(i) * buf_size)); + hwq->pkt_buffers[i].phys_addr = + (void *)(iova_addr + ((uint64_t)(i) * buf_size)); + hwq->pkt_buffers[i].len = buf_size; + } + + return 0; + } /* End of: no optimal IOMMU mapping available */ + + res = nt_vfio_dma_map(vf_num, virt, &iova_addr, ONE_G_SIZE); + if (res != 0) { + NT_LOG(ERR, ETHDEV, "VFIO MMAP FAILED! res %i, vf_num %i\n", + res, vf_num); + return -1; + } + + hwq->vf_num = vf_num; + hwq->virt_queues_ctrl.virt_addr = virt; + hwq->virt_queues_ctrl.phys_addr = (void *)(iova_addr); + hwq->virt_queues_ctrl.len = 0x100000; + iova_addr += 0x100000; + + NT_LOG(DBG, ETHDEV, + "VFIO MMAP: virt_addr=%" PRIX64 " phys_addr=%" PRIX64 + " size=%" PRIX64 " hpa=%" PRIX64 "\n", + hwq->virt_queues_ctrl.virt_addr, hwq->virt_queues_ctrl.phys_addr, + hwq->virt_queues_ctrl.len, + rte_malloc_virt2iova(hwq->virt_queues_ctrl.virt_addr)); + + size = num_descr * sizeof(struct nthw_memory_descriptor); + hwq->pkt_buffers = rte_zmalloc_socket("rx_pkt_buffers", size, 64, + eth_dev->data->numa_node); + if (!hwq->pkt_buffers) { + NT_LOG(ERR, ETHDEV, + "Failed to allocated buffer array for hw-queue %p, total size %i, elements %i\n", + hwq->pkt_buffers, size, num_descr); + rte_free(virt); + return -1; + } + + void *virt_addr = (void *)((uint64_t)virt + 0x100000); + + for (i = 0; i < num_descr; i++) { + hwq->pkt_buffers[i].virt_addr = + (void *)((char *)virt_addr + ((uint64_t)(i) * buf_size)); + hwq->pkt_buffers[i].phys_addr = + (void *)(iova_addr + ((uint64_t)(i) * buf_size)); + hwq->pkt_buffers[i].len = buf_size; + } + return 0; +} + +static void release_hw_virtio_queues(struct hwq_s *hwq) +{ + if (!hwq || hwq->vf_num == 0) + return; + hwq->vf_num = 0; +} + +static int deallocate_hw_virtio_queues(struct hwq_s *hwq) +{ + int vf_num = hwq->vf_num; + + void *virt = hwq->virt_queues_ctrl.virt_addr; + + int res = nt_vfio_dma_unmap(vf_num, hwq->virt_queues_ctrl.virt_addr, + (uint64_t)hwq->virt_queues_ctrl.phys_addr, + ONE_G_SIZE); + if (res != 0) { + NT_LOG(ERR, ETHDEV, "VFIO UNMMAP FAILED! res %i, vf_num %i\n", + res, vf_num); + return -1; + } + + release_hw_virtio_queues(hwq); + rte_free(hwq->pkt_buffers); + rte_free(virt); + return 0; +} + +static void eth_tx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id) +{ + struct pmd_internals *internals = dev->data->dev_private; + struct ntnic_tx_queue *tx_q = &internals->txq_scg[queue_id]; + + deallocate_hw_virtio_queues(&tx_q->hwq); + NT_LOG(DBG, ETHDEV, "NTNIC: %s\n", __func__); +} + +static void eth_rx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id) +{ + struct pmd_internals *internals = dev->data->dev_private; + struct ntnic_rx_queue *rx_q = &internals->rxq_scg[queue_id]; + + deallocate_hw_virtio_queues(&rx_q->hwq); + NT_LOG(DBG, ETHDEV, "NTNIC: %s\n", __func__); +} + +static int num_queues_allocated; + +/* Returns num queue starting at returned queue num or -1 on fail */ +static int allocate_queue(int num) +{ + int next_free = num_queues_allocated; + + NT_LOG(DBG, ETHDEV, + "%s: num_queues_allocated=%u, New queues=%u, Max queues=%u\n", + __func__, num_queues_allocated, num, MAX_TOTAL_QUEUES); + if (num_queues_allocated + num > MAX_TOTAL_QUEUES) + return -1; + num_queues_allocated += num; + return next_free; +} + +static int +eth_rx_scg_queue_setup(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id, + uint16_t nb_rx_desc __rte_unused, + unsigned int socket_id __rte_unused, + const struct rte_eth_rxconf *rx_conf __rte_unused, + struct rte_mempool *mb_pool) +{ + NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__); + struct rte_pktmbuf_pool_private *mbp_priv; + struct pmd_internals *internals = eth_dev->data->dev_private; + struct ntnic_rx_queue *rx_q = &internals->rxq_scg[rx_queue_id]; + struct drv_s *p_drv = internals->p_drv; + struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv; + + if (internals->type == PORT_TYPE_OVERRIDE) { + rx_q->mb_pool = mb_pool; + eth_dev->data->rx_queues[rx_queue_id] = rx_q; + mbp_priv = rte_mempool_get_priv(rx_q->mb_pool); + rx_q->buf_size = (uint16_t)(mbp_priv->mbuf_data_room_size - + RTE_PKTMBUF_HEADROOM); + rx_q->enabled = 1; + return 0; + } + + NT_LOG(DBG, ETHDEV, + "(%i) NTNIC RX OVS-SW queue setup: queue id %i, hw queue index %i\n", + internals->port, rx_queue_id, rx_q->queue.hw_id); + + rx_q->mb_pool = mb_pool; + + eth_dev->data->rx_queues[rx_queue_id] = rx_q; + + mbp_priv = rte_mempool_get_priv(rx_q->mb_pool); + rx_q->buf_size = (uint16_t)(mbp_priv->mbuf_data_room_size - + RTE_PKTMBUF_HEADROOM); + rx_q->enabled = 1; + + if (allocate_hw_virtio_queues(eth_dev, EXCEPTION_PATH_HID, &rx_q->hwq, + SG_NB_HW_RX_DESCRIPTORS, + SG_HW_RX_PKT_BUFFER_SIZE) < 0) + return -1; + + rx_q->nb_hw_rx_descr = SG_NB_HW_RX_DESCRIPTORS; + + rx_q->profile = p_drv->ntdrv.adapter_info.fpga_info.profile; + + rx_q->vq = nthw_setup_managed_rx_virt_queue(p_nt_drv->adapter_info.fpga_info.mp_nthw_dbs, + rx_q->queue.hw_id, /* index */ + rx_q->nb_hw_rx_descr, EXCEPTION_PATH_HID, /* host_id */ + 1, /* header NT DVIO header for exception path */ + &rx_q->hwq.virt_queues_ctrl, rx_q->hwq.pkt_buffers, SPLIT_RING, -1); + + NT_LOG(DBG, ETHDEV, "(%i) NTNIC RX OVS-SW queues successfully setup\n", + internals->port); + + return 0; +} + +static int +eth_tx_scg_queue_setup(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id, + uint16_t nb_tx_desc __rte_unused, + unsigned int socket_id __rte_unused, + const struct rte_eth_txconf *tx_conf __rte_unused) +{ + NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__); + struct pmd_internals *internals = eth_dev->data->dev_private; + struct drv_s *p_drv = internals->p_drv; + struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv; + struct ntnic_tx_queue *tx_q = &internals->txq_scg[tx_queue_id]; + + if (internals->type == PORT_TYPE_OVERRIDE) { + eth_dev->data->tx_queues[tx_queue_id] = tx_q; + return 0; + } + + NT_LOG(DBG, ETHDEV, + "(%i) NTNIC TX OVS-SW queue setup: queue id %i, hw queue index %i\n", + tx_q->port, tx_queue_id, tx_q->queue.hw_id); + + if (tx_queue_id > internals->nb_tx_queues) { + printf("Error invalid tx queue id\n"); + return -1; + } + + eth_dev->data->tx_queues[tx_queue_id] = tx_q; + + /* Calculate target ID for HW - to be used in NTDVIO0 header bypass_port */ + if (tx_q->rss_target_id >= 0) { + /* bypass to a multiqueue port - qsl-hsh index */ + tx_q->target_id = tx_q->rss_target_id + 0x90; + } else { + if (internals->vpq[tx_queue_id].hw_id > -1) { + /* virtual port - queue index */ + tx_q->target_id = internals->vpq[tx_queue_id].hw_id; + } else { + /* Phy port - phy port identifier */ + if (lag_active) { + /* If in LAG mode use bypass 0x90 mode */ + tx_q->target_id = 0x90; + } else { + /* output/bypass to MAC */ + tx_q->target_id = (int)(tx_q->port + 0x80); + } + } + } + + if (allocate_hw_virtio_queues(eth_dev, EXCEPTION_PATH_HID, &tx_q->hwq, + SG_NB_HW_TX_DESCRIPTORS, + SG_HW_TX_PKT_BUFFER_SIZE) < 0) + return -1; + + tx_q->nb_hw_tx_descr = SG_NB_HW_TX_DESCRIPTORS; + + tx_q->profile = p_drv->ntdrv.adapter_info.fpga_info.profile; + + uint32_t port, header; + + if (tx_q->profile == FPGA_INFO_PROFILE_VSWITCH) { + /* transmit port - not used in vswitch enabled mode - using bypass */ + port = 0; + header = 1; /* header type DVIO0 Always for exception path */ + } else { + port = tx_q->port; /* transmit port */ + header = 0; /* header type VirtIO-Net */ + } + /* + * in_port - in vswitch mode has to move tx port from OVS excep. Away + * from VM tx port, because of QoS is matched by port id! + */ + tx_q->vq = nthw_setup_managed_tx_virt_queue(p_nt_drv->adapter_info.fpga_info.mp_nthw_dbs, + tx_q->queue.hw_id, /* index */ + tx_q->nb_hw_tx_descr, /* queue size */ + EXCEPTION_PATH_HID, /* host_id always VF4 */ + port, + tx_q->port + + 128, + header, &tx_q->hwq.virt_queues_ctrl, tx_q->hwq.pkt_buffers, + SPLIT_RING, -1, IN_ORDER); + + tx_q->enabled = 1; + for (uint32_t i = 0; i < internals->vpq_nb_vq; i++) { + nthw_epp_set_queue_to_vport(p_nt_drv->adapter_info.fpga_info.mp_nthw_epp, + internals->vpq[i].hw_id, tx_q->port); + } + + NT_LOG(DBG, ETHDEV, "(%i) NTNIC TX OVS-SW queues successfully setup\n", + internals->port); + + if (internals->type == PORT_TYPE_PHYSICAL) { + struct adapter_info_s *p_adapter_info = + &internals->p_drv->ntdrv.adapter_info; + NT_LOG(DBG, ETHDEV, "Port %i is ready for data. Enable port\n", + internals->if_index); + nt4ga_port_set_adm_state(p_adapter_info, internals->if_index, + true); + if (lag_active && internals->if_index == 0) { + /* + * Special case for link aggregation where the second phy interface (port 1) + * is "hidden" from DPDK and therefore doesn't get enabled through normal + * interface probing + */ + NT_LOG(DBG, ETHDEV, "LAG: Enable port %i\n", + internals->if_index + 1); + nt4ga_port_set_adm_state(p_adapter_info, + internals->if_index + 1, true); + } + } + + return 0; +} + +static int dev_set_mtu_inline(struct rte_eth_dev *dev, uint16_t mtu) +{ + struct pmd_internals *internals = + (struct pmd_internals *)dev->data->dev_private; + struct flow_eth_dev *flw_dev = internals->flw_dev; + int ret = -1; + + if (internals->type == PORT_TYPE_PHYSICAL && mtu >= MIN_MTU_INLINE && + mtu <= MAX_MTU) + ret = flow_set_mtu_inline(flw_dev, internals->port, mtu); + return ret ? -EINVAL : 0; +} + +static int dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) +{ + struct pmd_internals *internals = dev->data->dev_private; + /*struct ntnic_tx_queue *tx_q = internals->txq; */ + struct drv_s *p_drv = internals->p_drv; + struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv; + fpga_info_t *fpga_info = &p_nt_drv->adapter_info.fpga_info; + int retval = EINVAL; + + if (mtu < MIN_MTU || mtu > MAX_MTU) + return -EINVAL; + + if (internals->type == PORT_TYPE_VIRTUAL) { + /* set MTU on exception to MAX_MTU */ + retval = nthw_epp_set_mtu(fpga_info->mp_nthw_epp, + internals->rxq_scg[0] + .queue + .hw_id, /* exception tx queue hw_id to OVS */ + MAX_MTU, /* max number of bytes allowed for a given port. */ + internals->type); /* port type */ + + if (retval) + return retval; + + uint i; + + for (i = 0; i < internals->vpq_nb_vq; i++) { + retval = nthw_epp_set_mtu(fpga_info->mp_nthw_epp, + internals->vpq[i].hw_id, /* tx queue hw_id */ + mtu, /* max number of bytes allowed for a given port. */ + internals->type); /* port type */ + if (retval) + return retval; + + NT_LOG(DBG, ETHDEV, "SET MTU SIZE %d queue hw_id %d\n", + mtu, internals->vpq[i].hw_id); + } + } else if (internals->type == PORT_TYPE_PHYSICAL) { + /* set MTU on exception to MAX_MTU */ + retval = nthw_epp_set_mtu(fpga_info->mp_nthw_epp, + internals->rxq_scg[0] + .queue + .hw_id, /* exception tx queue hw_id to OVS */ + MAX_MTU, /* max number of bytes allowed for a given port. */ + PORT_TYPE_VIRTUAL); /* port type */ + if (retval) + return retval; + + retval = nthw_epp_set_mtu(fpga_info->mp_nthw_epp, + internals->port, /* port number */ + mtu, /* max number of bytes allowed for a given port. */ + internals->type); /* port type */ + + NT_LOG(DBG, ETHDEV, "SET MTU SIZE %d port %d\n", mtu, + internals->port); + } else { + NT_LOG(DBG, ETHDEV, + "COULD NOT SET MTU SIZE %d port %d type %d\n", mtu, + internals->port, internals->type); + retval = -EINVAL; + } + return retval; +} + +static int eth_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) +{ + NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__); + eth_dev->data->rx_queue_state[rx_queue_id] = + RTE_ETH_QUEUE_STATE_STARTED; + return 0; +} + +static int eth_rx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) +{ + NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__); + eth_dev->data->rx_queue_state[rx_queue_id] = + RTE_ETH_QUEUE_STATE_STOPPED; + return 0; +} + +static int eth_tx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) +{ + NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__); + eth_dev->data->tx_queue_state[rx_queue_id] = + RTE_ETH_QUEUE_STATE_STARTED; + return 0; +} + +static int eth_tx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) +{ + NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__); + eth_dev->data->tx_queue_state[rx_queue_id] = + RTE_ETH_QUEUE_STATE_STOPPED; + return 0; +} + +static void eth_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) +{ + struct rte_ether_addr *const eth_addrs = dev->data->mac_addrs; + + assert(index < NUM_MAC_ADDRS_PER_PORT); + + if (index >= NUM_MAC_ADDRS_PER_PORT) { + const struct pmd_internals *const internals = + dev->data->dev_private; + NT_LOG(ERR, ETHDEV, + "%s: [%s:%i]: Port %i: illegal index %u (>= %u)\n", + __FILE__, __func__, __LINE__, internals->if_index, index, + NUM_MAC_ADDRS_PER_PORT); + return; + } + (void)memset(ð_addrs[index], 0, sizeof(eth_addrs[index])); +} + +static int eth_mac_addr_add(struct rte_eth_dev *dev, + struct rte_ether_addr *mac_addr, uint32_t index, + uint32_t vmdq __rte_unused) +{ + struct rte_ether_addr *const eth_addrs = dev->data->mac_addrs; + + assert(index < NUM_MAC_ADDRS_PER_PORT); + + if (index >= NUM_MAC_ADDRS_PER_PORT) { + const struct pmd_internals *const internals = + dev->data->dev_private; + NT_LOG(ERR, ETHDEV, + "%s: [%s:%i]: Port %i: illegal index %u (>= %u)\n", + __FILE__, __func__, __LINE__, internals->if_index, index, + NUM_MAC_ADDRS_PER_PORT); + return -1; + } + + eth_addrs[index] = *mac_addr; + + return 0; +} + +static int eth_mac_addr_set(struct rte_eth_dev *dev, + struct rte_ether_addr *mac_addr) +{ + struct rte_ether_addr *const eth_addrs = dev->data->mac_addrs; + + eth_addrs[0U] = *mac_addr; + + return 0; +} + +static int eth_set_mc_addr_list(struct rte_eth_dev *dev, + struct rte_ether_addr *mc_addr_set, + uint32_t nb_mc_addr) +{ + struct pmd_internals *const internals = dev->data->dev_private; + struct rte_ether_addr *const mc_addrs = internals->mc_addrs; + size_t i; + + if (nb_mc_addr >= NUM_MULTICAST_ADDRS_PER_PORT) { + NT_LOG(ERR, ETHDEV, + "%s: [%s:%i]: Port %i: too many multicast addresses %u (>= %u)\n", + __FILE__, __func__, __LINE__, internals->if_index, + nb_mc_addr, NUM_MULTICAST_ADDRS_PER_PORT); + return -1; + } + + for (i = 0U; i < NUM_MULTICAST_ADDRS_PER_PORT; i++) { + if (i < nb_mc_addr) + mc_addrs[i] = mc_addr_set[i]; + + else + (void)memset(&mc_addrs[i], 0, sizeof(mc_addrs[i])); + } + + return 0; +} + +static int eth_dev_configure(struct rte_eth_dev *eth_dev) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + struct drv_s *p_drv = internals->p_drv; + + NT_LOG(DBG, ETHDEV, "%s: [%s:%u] Called for eth_dev %p\n", __func__, + __func__, __LINE__, eth_dev); + + p_drv->probe_finished = 1; + + /* The device is ALWAYS running promiscuous mode. */ + eth_dev->data->promiscuous ^= ~eth_dev->data->promiscuous; + return 0; +} + +static int eth_dev_start(struct rte_eth_dev *eth_dev) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + const int n_intf_no = internals->if_index; + struct adapter_info_s *p_adapter_info = + &internals->p_drv->ntdrv.adapter_info; + + NT_LOG(DBG, ETHDEV, "%s: [%s:%u] - Port %u, %u\n", __func__, __func__, + __LINE__, internals->n_intf_no, internals->if_index); + + if (internals->type == PORT_TYPE_VIRTUAL || + internals->type == PORT_TYPE_OVERRIDE) { + eth_dev->data->dev_link.link_status = ETH_LINK_UP; + } else { + /* + * wait for link on port + * If application starts sending too soon before FPGA port is ready, garbage is + * produced + */ + int loop = 0; + + while (nt4ga_port_get_link_status(p_adapter_info, n_intf_no) == + ETH_LINK_DOWN) { + /* break out after 5 sec */ + if (++loop >= 50) { + NT_LOG(DBG, ETHDEV, + "%s: TIMEOUT No link on port %i (5sec timeout)\n", + __func__, internals->n_intf_no); + break; + } + usleep(100000); + } + assert(internals->n_intf_no == + internals->if_index); /* Sanity check */ + if (internals->lpbk_mode) { + if (internals->lpbk_mode & 1 << 0) { + nt4ga_port_set_loopback_mode(p_adapter_info, + n_intf_no, + NT_LINK_LOOPBACK_HOST); + } + if (internals->lpbk_mode & 1 << 1) { + nt4ga_port_set_loopback_mode(p_adapter_info, + n_intf_no, + NT_LINK_LOOPBACK_LINE); + } + } + } + return 0; +} + +static int eth_dev_stop(struct rte_eth_dev *eth_dev) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + const int n_intf_no = internals->if_index; + struct adapter_info_s *p_adapter_info = + &internals->p_drv->ntdrv.adapter_info; + + NT_LOG(DBG, ETHDEV, "%s: [%s:%u] - Port %u, %u, type %u\n", __func__, + __func__, __LINE__, internals->n_intf_no, internals->if_index, + internals->type); + + if (internals->type != PORT_TYPE_VIRTUAL) { + struct ntnic_rx_queue *rx_q = internals->rxq_scg; + struct ntnic_tx_queue *tx_q = internals->txq_scg; + + uint q; + + for (q = 0; q < internals->nb_rx_queues; q++) + nthw_release_managed_rx_virt_queue(rx_q[q].vq); + + for (q = 0; q < internals->nb_tx_queues; q++) + nthw_release_managed_tx_virt_queue(tx_q[q].vq); + + nt4ga_port_set_adm_state(p_adapter_info, n_intf_no, 0); + nt4ga_port_set_link_status(p_adapter_info, n_intf_no, 0); + nt4ga_port_set_link_speed(p_adapter_info, n_intf_no, + NT_LINK_SPEED_UNKNOWN); + nt4ga_port_set_loopback_mode(p_adapter_info, n_intf_no, + NT_LINK_LOOPBACK_OFF); + } + + eth_dev->data->dev_link.link_status = ETH_LINK_DOWN; + return 0; +} + +static int eth_dev_set_link_up(struct rte_eth_dev *dev) +{ + struct pmd_internals *const internals = dev->data->dev_private; + struct adapter_info_s *p_adapter_info = + &internals->p_drv->ntdrv.adapter_info; + const int port = internals->if_index; + + if (internals->type == PORT_TYPE_VIRTUAL || + internals->type == PORT_TYPE_OVERRIDE) + return 0; + + assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX); + assert(port == internals->n_intf_no); + + nt4ga_port_set_adm_state(p_adapter_info, port, true); + + return 0; +} + +static int eth_dev_set_link_down(struct rte_eth_dev *dev) +{ + struct pmd_internals *const internals = dev->data->dev_private; + struct adapter_info_s *p_adapter_info = + &internals->p_drv->ntdrv.adapter_info; + const int port = internals->if_index; + + if (internals->type == PORT_TYPE_VIRTUAL || + internals->type == PORT_TYPE_OVERRIDE) + return 0; + + assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX); + assert(port == internals->n_intf_no); + + nt4ga_port_set_link_status(p_adapter_info, port, false); + + return 0; +} + +static int eth_dev_close(struct rte_eth_dev *eth_dev) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + struct drv_s *p_drv = internals->p_drv; + ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv; + fpga_info_t *fpga_info = &p_nt_drv->adapter_info.fpga_info; + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); + (void)pci_dev; /* UNUSED */ + + NT_LOG(DBG, ETHDEV, "%s: enter [%s:%u]\n", __func__, __func__, + __LINE__); + + internals->p_drv = NULL; + + /* LAG cleanup */ + if (internals->lag_config) { + if (internals->lag_config->lag_tid) { + internals->lag_config->lag_thread_active = 0; + pthread_join(internals->lag_config->lag_tid, NULL); + } + lag_active = 0; + rte_free(internals->lag_config); + } + + /* free */ + rte_free(internals); + internals = NULL; + + eth_dev->data->dev_private = NULL; + eth_dev->data->mac_addrs = NULL; + + /* release */ + rte_eth_dev_release_port(eth_dev); + + NT_LOG(DBG, ETHDEV, "%s: %d [%s:%u]\n", __func__, + p_drv->n_eth_dev_init_count, __func__, __LINE__); + p_drv->n_eth_dev_init_count--; + + /* + * rte_pci_dev has no private member for p_drv + * wait until all rte_eth_dev's are closed - then close adapters via p_drv + */ + if (!p_drv->n_eth_dev_init_count && p_drv) { + NT_LOG(DBG, ETHDEV, "%s: %d [%s:%u]\n", __func__, + p_drv->n_eth_dev_init_count, __func__, __LINE__); + p_drv->ntdrv.b_shutdown = true; + void *p_ret_val = NULL; + + pthread_join(p_nt_drv->stat_thread, &p_ret_val); + if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) { + p_ret_val = NULL; + pthread_join(p_nt_drv->flm_thread, &p_ret_val); + } + nt4ga_adapter_deinit(&p_nt_drv->adapter_info); + rte_free(p_drv); + } + NT_LOG(DBG, ETHDEV, "%s: leave [%s:%u]\n", __func__, __func__, + __LINE__); + return 0; +} + +static int eth_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version, + size_t fw_size) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + + if (internals->type == PORT_TYPE_VIRTUAL || + internals->type == PORT_TYPE_OVERRIDE) + return 0; + + fpga_info_t *fpga_info = &internals->p_drv->ntdrv.adapter_info.fpga_info; + const int length = + snprintf(fw_version, fw_size, "%03d-%04d-%02d-%02d", + fpga_info->n_fpga_type_id, fpga_info->n_fpga_prod_id, + fpga_info->n_fpga_ver_id, fpga_info->n_fpga_rev_id); + if ((size_t)length < fw_size) { + /* We have space for the version string */ + return 0; + } + /* We do not have space for the version string -return the needed space */ + return length + 1; +} + +static int eth_xstats_get(struct rte_eth_dev *eth_dev, + struct rte_eth_xstat *stats, unsigned int n) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + struct drv_s *p_drv = internals->p_drv; + ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv; + nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat; + nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat; + int if_index = internals->if_index; + int nb_xstats; + + pthread_mutex_lock(&p_nt_drv->stat_lck); + nb_xstats = nthw_xstats_get(p_nt4ga_stat, stats, n, + p_nthw_stat->mb_is_vswitch, if_index); + pthread_mutex_unlock(&p_nt_drv->stat_lck); + return nb_xstats; +} + +static int eth_xstats_get_by_id(struct rte_eth_dev *eth_dev, + const uint64_t *ids, uint64_t *values, + unsigned int n) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + struct drv_s *p_drv = internals->p_drv; + ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv; + nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat; + nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat; + int if_index = internals->if_index; + int nb_xstats; + + pthread_mutex_lock(&p_nt_drv->stat_lck); + nb_xstats = nthw_xstats_get_by_id(p_nt4ga_stat, ids, values, n, + p_nthw_stat->mb_is_vswitch, if_index); + pthread_mutex_unlock(&p_nt_drv->stat_lck); + return nb_xstats; +} + +static int eth_xstats_reset(struct rte_eth_dev *eth_dev) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + struct drv_s *p_drv = internals->p_drv; + ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv; + nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat; + nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat; + int if_index = internals->if_index; + + pthread_mutex_lock(&p_nt_drv->stat_lck); + nthw_xstats_reset(p_nt4ga_stat, p_nthw_stat->mb_is_vswitch, if_index); + pthread_mutex_unlock(&p_nt_drv->stat_lck); + return dpdk_stats_reset(internals, p_nt_drv, if_index); +} + +static int eth_xstats_get_names(struct rte_eth_dev *eth_dev __rte_unused, + struct rte_eth_xstat_name *xstats_names, + unsigned int size) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + struct drv_s *p_drv = internals->p_drv; + ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv; + nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat; + nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat; + + return nthw_xstats_get_names(p_nt4ga_stat, xstats_names, size, + p_nthw_stat->mb_is_vswitch); +} + +static int eth_xstats_get_names_by_id(struct rte_eth_dev *eth_dev, + const uint64_t *ids, + struct rte_eth_xstat_name *xstats_names, + unsigned int size) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + struct drv_s *p_drv = internals->p_drv; + ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv; + nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat; + nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat; + + return nthw_xstats_get_names_by_id(p_nt4ga_stat, xstats_names, ids, size, + p_nthw_stat->mb_is_vswitch); +} + +static int _dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused, + const struct rte_flow_ops **ops) +{ + *ops = &_dev_flow_ops; + return 0; +} + +static int promiscuous_enable(struct rte_eth_dev __rte_unused * dev) +{ + NT_LOG(DBG, NTHW, "The device always run promiscuous mode."); + return 0; +} + +static int eth_dev_rss_hash_update(struct rte_eth_dev *eth_dev, + struct rte_eth_rss_conf *rss_conf) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + struct flow_eth_dev *fedev = internals->flw_dev; + struct flow_nic_dev *ndev = fedev->ndev; + const int hsh_idx = + 0; /* hsh index 0 means the default receipt in HSH module */ + int res = flow_nic_set_hasher_fields(ndev, hsh_idx, + nt_rss_hash_field_from_dpdk(rss_conf->rss_hf)); + res |= hw_mod_hsh_rcp_flush(&ndev->be, hsh_idx, 1); + return res; +} + +static int rss_hash_conf_get(struct rte_eth_dev *eth_dev, + struct rte_eth_rss_conf *rss_conf) +{ + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + struct flow_eth_dev *fedev = internals->flw_dev; + struct flow_nic_dev *ndev = fedev->ndev; + + rss_conf->rss_key = NULL; + rss_conf->rss_key_len = 0; + rss_conf->rss_hf |= + dpdk_rss_hash_define_from_nt_rss(ndev->rss_hash_config); + return 0; +} + +static struct eth_dev_ops nthw_eth_dev_ops = { + .dev_configure = eth_dev_configure, + .dev_start = eth_dev_start, + .dev_stop = eth_dev_stop, + .dev_set_link_up = eth_dev_set_link_up, + .dev_set_link_down = eth_dev_set_link_down, + .dev_close = eth_dev_close, + .link_update = eth_link_update, + .stats_get = eth_stats_get, + .stats_reset = eth_stats_reset, + .dev_infos_get = eth_dev_infos_get, + .fw_version_get = eth_fw_version_get, + .rx_queue_setup = eth_rx_scg_queue_setup, + .rx_queue_start = eth_rx_queue_start, + .rx_queue_stop = eth_rx_queue_stop, + .rx_queue_release = eth_rx_queue_release, + .tx_queue_setup = eth_tx_scg_queue_setup, + .tx_queue_start = eth_tx_queue_start, + .tx_queue_stop = eth_tx_queue_stop, + .tx_queue_release = eth_tx_queue_release, + .mac_addr_remove = eth_mac_addr_remove, + .mac_addr_add = eth_mac_addr_add, + .mac_addr_set = eth_mac_addr_set, + .set_mc_addr_list = eth_set_mc_addr_list, + .xstats_get = eth_xstats_get, + .xstats_get_names = eth_xstats_get_names, + .xstats_reset = eth_xstats_reset, + .xstats_get_by_id = eth_xstats_get_by_id, + .xstats_get_names_by_id = eth_xstats_get_names_by_id, + .mtu_set = NULL, + .mtr_ops_get = eth_mtr_ops_get, + .flow_ops_get = _dev_flow_ops_get, + .promiscuous_disable = NULL, + .promiscuous_enable = promiscuous_enable, + .rss_hash_update = eth_dev_rss_hash_update, + .rss_hash_conf_get = rss_hash_conf_get, +}; + +/* Converts link speed provided in Mbps to NT specific definitions.*/ +static nt_link_speed_t convert_link_speed(int link_speed_mbps) +{ + switch (link_speed_mbps) { + case 10: + return NT_LINK_SPEED_10M; + case 100: + return NT_LINK_SPEED_100M; + case 1000: + return NT_LINK_SPEED_1G; + case 10000: + return NT_LINK_SPEED_10G; + case 40000: + return NT_LINK_SPEED_40G; + case 100000: + return NT_LINK_SPEED_100G; + case 50000: + return NT_LINK_SPEED_50G; + case 25000: + return NT_LINK_SPEED_25G; + default: + return NT_LINK_SPEED_UNKNOWN; + } +} + +/* + * Adapter flm stat thread + */ +static void *adapter_flm_thread_fn(void *context) +{ + struct drv_s *p_drv = context; + struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv; + struct adapter_info_s *p_adapter_info = &p_nt_drv->adapter_info; + struct nt4ga_filter_s *p_nt4ga_filter = &p_adapter_info->nt4ga_filter; + struct flow_nic_dev *p_flow_nic_dev = p_nt4ga_filter->mp_flow_device; + + NT_LOG(DBG, ETHDEV, "%s: %s: waiting for port configuration\n", + p_adapter_info->mp_adapter_id_str, __func__); + + while (p_flow_nic_dev->eth_base == NULL) + usleep(1000000); + struct flow_eth_dev *dev = p_flow_nic_dev->eth_base; + + NT_LOG(DBG, ETHDEV, "%s: %s: begin\n", p_adapter_info->mp_adapter_id_str, + __func__); + + while (!p_drv->ntdrv.b_shutdown) { + if (flm_mtr_update_stats(dev) == 0) + usleep(10); + } + + NT_LOG(DBG, ETHDEV, "%s: %s: end\n", p_adapter_info->mp_adapter_id_str, + __func__); + + return NULL; +} + +/* + * Adapter stat thread + */ +static void *adapter_stat_thread_fn(void *context) +{ + struct drv_s *p_drv = context; + ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv; + nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat; + nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat; + + const char *const p_adapter_id_str _unused = + p_nt_drv->adapter_info.mp_adapter_id_str; + + NT_LOG(DBG, ETHDEV, "%s: %s: begin\n", p_adapter_id_str, __func__); + + assert(p_nthw_stat); + + while (!p_drv->ntdrv.b_shutdown) { + usleep(100 * 100); + + nthw_stat_trigger(p_nthw_stat); + + uint32_t loop = 0; + + while ((!p_drv->ntdrv.b_shutdown) && + (*p_nthw_stat->mp_timestamp == (uint64_t)-1)) { + usleep(1 * 100); + + if (nt_log_is_debug(NT_LOG_MODULE_ETHDEV) && + (++loop & 0x3fff) == 0) { + uint32_t sf_ram_of = + nthw_rmc_get_status_sf_ram_of(p_nt4ga_stat->mp_nthw_rmc); + uint32_t descr_fifo_of = + nthw_rmc_get_status_descr_fifo_of(p_nt4ga_stat->mp_nthw_rmc); + + uint32_t dbg_merge = + nthw_rmc_get_dbg_merge(p_nt4ga_stat->mp_nthw_rmc); + uint32_t mac_if_err = + nthw_rmc_get_mac_if_err(p_nt4ga_stat->mp_nthw_rmc); + + NT_LOG(ERR, ETHDEV, "Statistics DMA frozen\n"); + NT_LOG(ERR, ETHDEV, + "SF RAM Overflow : %08x\n", + sf_ram_of); + NT_LOG(ERR, ETHDEV, + "Descr Fifo Overflow : %08x\n", + descr_fifo_of); + NT_LOG(ERR, ETHDEV, + "DBG Merge : %08x\n", + dbg_merge); + NT_LOG(ERR, ETHDEV, + "MAC If Errors : %08x\n", + mac_if_err); + } + } + + /* Check then collect */ + { + pthread_mutex_lock(&p_nt_drv->stat_lck); + nt4ga_stat_collect(&p_nt_drv->adapter_info, p_nt4ga_stat); + pthread_mutex_unlock(&p_nt_drv->stat_lck); + } + } + + NT_LOG(DBG, ETHDEV, "%s: %s: end\n", p_adapter_id_str, __func__); + + return NULL; +} + +static struct { + struct rte_pci_device *vpf_dev; + struct rte_eth_devargs eth_da; + int portqueues[MAX_FPGA_VIRTUAL_PORTS_SUPPORTED]; + uint16_t pf_backer_port_id; +} rep; + +static int nthw_pci_dev_init(struct rte_pci_device *pci_dev) +{ + int res; + struct drv_s *p_drv; + ntdrv_4ga_t *p_nt_drv; + fpga_info_t *fpga_info; + + hw_info_t *p_hw_info _unused; + uint32_t n_port_mask = -1; /* All ports enabled by default */ + uint32_t nb_rx_queues = 1; + uint32_t nb_tx_queues = 1; + uint32_t exception_path = 0; + struct flow_queue_id_s queue_ids[FLOW_MAX_QUEUES]; + lag_config_t *lag_config = NULL; + int n_phy_ports; + struct port_link_speed pls_mbps[NUM_ADAPTER_PORTS_MAX] = { 0 }; + int num_port_speeds = 0; + enum flow_eth_dev_profile profile; + + NT_LOG(DBG, ETHDEV, "%s: [%s:%u] enter\n", __func__, __FILE__, __LINE__); + NT_LOG(DBG, ETHDEV, "Dev %s PF #%i Init : %02x:%02x:%i\n", + pci_dev->name, pci_dev->addr.function, pci_dev->addr.bus, + pci_dev->addr.devid, pci_dev->addr.function); + + /* + * Process options/arguments + */ + if (pci_dev->device.devargs && pci_dev->device.devargs->args) { + int kvargs_count; + struct rte_kvargs *kvlist = rte_kvargs_parse(pci_dev->device.devargs->args, + valid_arguments); + if (kvlist == NULL) + return -1; + + /* + * Argument: help + * NOTE: this argument/option check should be the first as it will stop + * execution after producing its output + */ + { + if (rte_kvargs_get(kvlist, ETH_DEV_NTNIC_HELP_ARG)) { + size_t i; + + printf("NTNIC supported arguments:\n\n"); + for (i = 0; i < RTE_DIM(valid_arguments); i++) { + if (valid_arguments[i] == NULL) + break; + printf(" %s\n", valid_arguments[i]); + } + printf("\n"); + exit(0); + } + } + + /* + * Argument: supported-fpgas=list|verbose + * NOTE: this argument/option check should be the first as it will stop + * execution after producing its output + */ + { + const char *val_str; + + val_str = rte_kvargs_get(kvlist, + ETH_DEV_NTNIC_SUPPORTED_FPGAS_ARG); + if (val_str) { + int detail_level = 0; + nt_fpga_mgr_t *p_fpga_mgr = NULL; + + if (strcmp(val_str, "list") == 0) { + detail_level = 0; + } else if (strcmp(val_str, "verbose") == 0) { + detail_level = 1; + } else { + NT_LOG(ERR, ETHDEV, + "%s: argument '%s': '%s': unsupported value\n", + __func__, + ETH_DEV_NTNIC_SUPPORTED_FPGAS_ARG, + val_str); + exit(1); + } + /* Produce fpgamgr output and exit hard */ + p_fpga_mgr = fpga_mgr_new(); + if (p_fpga_mgr) { + fpga_mgr_init(p_fpga_mgr); + fpga_mgr_show(p_fpga_mgr, stdout, + detail_level); + fpga_mgr_delete(p_fpga_mgr); + p_fpga_mgr = NULL; + } else { + NT_LOG(ERR, ETHDEV, + "%s: %s cannot complete\n", + __func__, + ETH_DEV_NTNIC_SUPPORTED_FPGAS_ARG); + exit(1); + } + exit(0); + } + } + + /* link_speed options/argument only applicable for physical ports. */ + num_port_speeds = + rte_kvargs_count(kvlist, ETH_DEV_NTHW_LINK_SPEED_ARG); + if (num_port_speeds) { + assert(num_port_speeds <= NUM_ADAPTER_PORTS_MAX); + void *pls_mbps_ptr = &pls_mbps[0]; + + res = rte_kvargs_process(kvlist, + ETH_DEV_NTHW_LINK_SPEED_ARG, + &string_to_port_link_speed, + &pls_mbps_ptr); + if (res < 0) { + NT_LOG(ERR, ETHDEV, + "%s: problem with port link speed command " + "line arguments: res=%d\n", + __func__, res); + return -1; + } + for (int i = 0; i < num_port_speeds; ++i) { + int pid = pls_mbps[i].port_id; + + int lspeed _unused = pls_mbps[i].link_speed; + + NT_LOG(DBG, ETHDEV, "%s: devargs: %s=%d.%d\n", + __func__, ETH_DEV_NTHW_LINK_SPEED_ARG, + pid, lspeed); + if (pls_mbps[i].port_id >= + NUM_ADAPTER_PORTS_MAX) { + NT_LOG(ERR, ETHDEV, + "%s: problem with port link speed command line " + "arguments: port id should be 0 to %d, got %d\n", + __func__, NUM_ADAPTER_PORTS_MAX, + pid); + return -1; + } + } + } + + /* + * portmask option/argument + * It is intentional that portmask is only used to decide if DPDK eth_dev + * should be created for testing we would still keep the nthw subsystems + * running for all interfaces + */ + kvargs_count = + rte_kvargs_count(kvlist, ETH_DEV_NTHW_PORTMASK_ARG); + if (kvargs_count) { + assert(kvargs_count == 1); + res = rte_kvargs_process(kvlist, + ETH_DEV_NTHW_PORTMASK_ARG, + &string_to_u32, &n_port_mask); + if (res < 0) { + NT_LOG(ERR, ETHDEV, + "%s: problem with command line arguments: res=%d\n", + __func__, res); + return -1; + } + NT_LOG(DBG, ETHDEV, "%s: devargs: %s=%u\n", __func__, + ETH_DEV_NTHW_PORTMASK_ARG, n_port_mask); + } + + /* + * rxq option/argument + * The number of rxq (hostbuffers) allocated in memory. + * Default is 32 RX Hostbuffers + */ + kvargs_count = + rte_kvargs_count(kvlist, ETH_DEV_NTHW_RXQUEUES_ARG); + if (kvargs_count) { + assert(kvargs_count == 1); + res = rte_kvargs_process(kvlist, + ETH_DEV_NTHW_RXQUEUES_ARG, + &string_to_u32, &nb_rx_queues); + if (res < 0) { + NT_LOG(ERR, ETHDEV, + "%s: problem with command line arguments: res=%d\n", + __func__, res); + return -1; + } + NT_LOG(DBG, ETHDEV, "%s: devargs: %s=%u\n", __func__, + ETH_DEV_NTHW_RXQUEUES_ARG, nb_rx_queues); + } + + /* + * txq option/argument + * The number of txq (hostbuffers) allocated in memory. + * Default is 32 TX Hostbuffers + */ + kvargs_count = + rte_kvargs_count(kvlist, ETH_DEV_NTHW_TXQUEUES_ARG); + if (kvargs_count) { + assert(kvargs_count == 1); + res = rte_kvargs_process(kvlist, + ETH_DEV_NTHW_TXQUEUES_ARG, + &string_to_u32, &nb_tx_queues); + if (res < 0) { + NT_LOG(ERR, ETHDEV, + "%s: problem with command line arguments: res=%d\n", + __func__, res); + return -1; + } + NT_LOG(DBG, ETHDEV, "%s: devargs: %s=%u\n", __func__, + ETH_DEV_NTHW_TXQUEUES_ARG, nb_tx_queues); + } + + kvargs_count = rte_kvargs_count(kvlist, ETH_NTNIC_LAG_MODE_ARG); + if (kvargs_count) { + lag_config = (lag_config_t *)rte_zmalloc(NULL, sizeof(lag_config_t), 0); + if (lag_config == NULL) { + NT_LOG(ERR, ETHDEV, + "Failed to alloc lag_config data\n"); + return -1; + } + assert(kvargs_count == 1); + res = rte_kvargs_process(kvlist, ETH_NTNIC_LAG_MODE_ARG, + &string_to_u32, + &lag_config->mode); + if (res < 0) { + NT_LOG(ERR, ETHDEV, + "%s: problem with command line arguments: res=%d\n", + __func__, res); + return -1; + } + NT_LOG(DBG, ETHDEV, "%s: devargs: %s=%u\n", __func__, + ETH_NTNIC_LAG_MODE_ARG, nb_tx_queues); + lag_active = 1; + } + + kvargs_count = rte_kvargs_count(kvlist, + ETH_DEV_NTHW_EXCEPTION_PATH_ARG); + if (kvargs_count) { + assert(kvargs_count == 1); + res = rte_kvargs_process(kvlist, + ETH_DEV_NTHW_EXCEPTION_PATH_ARG, + &string_to_u32, &exception_path); + if (res < 0) { + NT_LOG(ERR, ETHDEV, + "%s: problem with command line arguments: res=%d\n", + __func__, res); + return -1; + } + NT_LOG(DBG, ETHDEV, "%s: devargs: %s=%u\n", __func__, + ETH_DEV_NTHW_EXCEPTION_PATH_ARG, exception_path); + } + + if (lag_active && lag_config) { + switch (lag_config->mode) { + case BONDING_MODE_ACTIVE_BACKUP: + NT_LOG(DBG, ETHDEV, + "Active / Backup LAG mode\n"); + kvargs_count = rte_kvargs_count(kvlist, + ETH_NTNIC_LAG_PRIMARY_ARG); + if (kvargs_count) { + assert(kvargs_count == 1); + res = rte_kvargs_process(kvlist, + ETH_NTNIC_LAG_PRIMARY_ARG, + &string_to_u32, + &lag_config->primary_port); + if (res < 0) { + NT_LOG(ERR, ETHDEV, + "%s: problem with command line " + "arguments: res=%d\n", + __func__, res); + return -1; + } + NT_LOG(DBG, ETHDEV, + "%s: devargs: %s=%u\n", __func__, + ETH_NTNIC_LAG_MODE_ARG, + nb_tx_queues); + } else { + NT_LOG(ERR, ETHDEV, + "LAG must define a primary port\n"); + return -1; + } + + kvargs_count = rte_kvargs_count(kvlist, + ETH_NTNIC_LAG_BACKUP_ARG); + if (kvargs_count) { + assert(kvargs_count == 1); + res = rte_kvargs_process(kvlist, + ETH_NTNIC_LAG_BACKUP_ARG, + &string_to_u32, + &lag_config->backup_port); + if (res != 0) { + NT_LOG(ERR, ETHDEV, + "%s: problem with command line " + "arguments: res=%d\n", + __func__, res); + return -1; + } + NT_LOG(DBG, ETHDEV, + "%s: devargs: %s=%u\n", __func__, + ETH_NTNIC_LAG_MODE_ARG, + nb_tx_queues); + } else { + NT_LOG(ERR, ETHDEV, + "LAG must define a backup port\n"); + return -1; + } + break; + + case BONDING_MODE_8023AD: + NT_LOG(DBG, ETHDEV, + "Active / Active LAG mode\n"); + lag_config->primary_port = 0; + lag_config->backup_port = 0; + break; + + default: + NT_LOG(ERR, ETHDEV, "Unsupported LAG mode\n"); + return -1; + } + } + + rte_kvargs_free(kvlist); + } + + /* parse representor args */ + if (setup_virtual_pf_representor_base(pci_dev) == -1) { + NT_LOG(ERR, ETHDEV, + "%s: setup_virtual_pf_representor_base error %d (%s:%u)\n", + (pci_dev->name[0] ? pci_dev->name : "NA"), -1, __func__, + __LINE__); + return -1; + } + + /* alloc */ + p_drv = rte_zmalloc_socket(pci_dev->name, sizeof(struct drv_s), + RTE_CACHE_LINE_SIZE, + pci_dev->device.numa_node); + if (!p_drv) { + NT_LOG(ERR, ETHDEV, "%s: error %d (%s:%u)\n", + (pci_dev->name[0] ? pci_dev->name : "NA"), -1, __func__, + __LINE__); + return -1; + } + + /* Setup VFIO context */ + int vfio = nt_vfio_setup(pci_dev); + + if (vfio < 0) { + NT_LOG(ERR, ETHDEV, "%s: vfio_setup error %d (%s:%u)\n", + (pci_dev->name[0] ? pci_dev->name : "NA"), -1, __func__, + __LINE__); + rte_free(p_drv); + return -1; + } + + p_drv->probe_finished = 0; + /* context */ + p_nt_drv = &p_drv->ntdrv; + fpga_info = &p_nt_drv->adapter_info.fpga_info; + p_hw_info = &p_nt_drv->adapter_info.hw_info; + + p_drv->p_dev = pci_dev; + + /* Set context for NtDrv */ + p_nt_drv->pciident = + BDF_TO_PCIIDENT(pci_dev->addr.domain, pci_dev->addr.bus, + pci_dev->addr.devid, pci_dev->addr.function); + p_nt_drv->adapter_info.n_rx_host_buffers = nb_rx_queues; + p_nt_drv->adapter_info.n_tx_host_buffers = nb_tx_queues; + + fpga_info->bar0_addr = (void *)pci_dev->mem_resource[0].addr; + fpga_info->bar0_size = pci_dev->mem_resource[0].len; + NT_LOG(DBG, ETHDEV, "bar0=0x%" PRIX64 " len=%d\n", fpga_info->bar0_addr, + fpga_info->bar0_size); + fpga_info->numa_node = pci_dev->device.numa_node; + fpga_info->pciident = p_nt_drv->pciident; + fpga_info->adapter_no = p_drv->adapter_no; + + p_nt_drv->adapter_info.hw_info.pci_class_id = pci_dev->id.class_id; + p_nt_drv->adapter_info.hw_info.pci_vendor_id = pci_dev->id.vendor_id; + p_nt_drv->adapter_info.hw_info.pci_device_id = pci_dev->id.device_id; + p_nt_drv->adapter_info.hw_info.pci_sub_vendor_id = + pci_dev->id.subsystem_vendor_id; + p_nt_drv->adapter_info.hw_info.pci_sub_device_id = + pci_dev->id.subsystem_device_id; + + NT_LOG(DBG, ETHDEV, + "%s: " PCIIDENT_PRINT_STR " %04X:%04X: %04X:%04X:\n", + p_nt_drv->adapter_info.mp_adapter_id_str, + PCIIDENT_TO_DOMAIN(p_nt_drv->pciident), + PCIIDENT_TO_BUSNR(p_nt_drv->pciident), + PCIIDENT_TO_DEVNR(p_nt_drv->pciident), + PCIIDENT_TO_FUNCNR(p_nt_drv->pciident), + p_nt_drv->adapter_info.hw_info.pci_vendor_id, + p_nt_drv->adapter_info.hw_info.pci_device_id, + p_nt_drv->adapter_info.hw_info.pci_sub_vendor_id, + p_nt_drv->adapter_info.hw_info.pci_sub_device_id); + + p_nt_drv->b_shutdown = false; + p_nt_drv->adapter_info.pb_shutdown = &p_nt_drv->b_shutdown; + + for (int i = 0; i < num_port_speeds; ++i) { + struct adapter_info_s *p_adapter_info = &p_nt_drv->adapter_info; + nt_link_speed_t link_speed = + convert_link_speed(pls_mbps[i].link_speed); + nt4ga_port_set_link_speed(p_adapter_info, i, link_speed); + } + + /* store context */ + store_pdrv(p_drv); + + /* initialize nt4ga nthw fpga module instance in drv */ + int err = nt4ga_adapter_init(&p_nt_drv->adapter_info); + + if (err != 0) { + NT_LOG(ERR, ETHDEV, + "%s: Cannot initialize the adapter instance\n", + p_nt_drv->adapter_info.mp_adapter_id_str); + return -1; + } + + if (fpga_info->mp_nthw_epp != NULL) + nthw_eth_dev_ops.mtu_set = dev_set_mtu; + + /* Initialize the queue system */ + if (err == 0) { + err = nthw_virt_queue_init(fpga_info); + if (err != 0) { + NT_LOG(ERR, ETHDEV, + "%s: Cannot initialize scatter-gather queues\n", + p_nt_drv->adapter_info.mp_adapter_id_str); + } else { + NT_LOG(DBG, ETHDEV, + "%s: Initialized scatter-gather queues\n", + p_nt_drv->adapter_info.mp_adapter_id_str); + } + } + + switch (fpga_info->profile) { + case FPGA_INFO_PROFILE_VSWITCH: + profile = FLOW_ETH_DEV_PROFILE_VSWITCH; + break; + case FPGA_INFO_PROFILE_INLINE: + profile = FLOW_ETH_DEV_PROFILE_INLINE; + break; + case FPGA_INFO_PROFILE_UNKNOWN: + /* fallthrough */ + case FPGA_INFO_PROFILE_CAPTURE: + /* fallthrough */ + default: + NT_LOG(ERR, ETHDEV, "%s: fpga profile not supported [%s:%u]\n", + (pci_dev->name[0] ? pci_dev->name : "NA"), __func__, + __LINE__); + return -1; + } + + if (err == 0) { + /* mp_adapter_id_str is initialized after nt4ga_adapter_init(p_nt_drv) */ + const char *const p_adapter_id_str _unused = + p_nt_drv->adapter_info.mp_adapter_id_str; + NT_LOG(DBG, ETHDEV, + "%s: %s: AdapterPCI=" PCIIDENT_PRINT_STR + " Hw=0x%02X_rev%d PhyPorts=%d\n", + (pci_dev->name[0] ? pci_dev->name : "NA"), p_adapter_id_str, + PCIIDENT_TO_DOMAIN(p_nt_drv->adapter_info.fpga_info.pciident), + PCIIDENT_TO_BUSNR(p_nt_drv->adapter_info.fpga_info.pciident), + PCIIDENT_TO_DEVNR(p_nt_drv->adapter_info.fpga_info.pciident), + PCIIDENT_TO_FUNCNR(p_nt_drv->adapter_info.fpga_info.pciident), + p_hw_info->hw_platform_id, fpga_info->nthw_hw_info.hw_id, + fpga_info->n_phy_ports); + } else { + NT_LOG(ERR, ETHDEV, "%s: error=%d [%s:%u]\n", + (pci_dev->name[0] ? pci_dev->name : "NA"), err, __func__, + __LINE__); + return -1; + } + + pthread_mutex_init(&p_nt_drv->stat_lck, NULL); + res = rte_ctrl_thread_create(&p_nt_drv->stat_thread, "nt4ga_stat_thr", + NULL, adapter_stat_thread_fn, + (void *)p_drv); + if (res) { + NT_LOG(ERR, ETHDEV, "%s: error=%d [%s:%u]\n", + (pci_dev->name[0] ? pci_dev->name : "NA"), res, __func__, + __LINE__); + return -1; + } + + if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) { + res = rte_ctrl_thread_create(&p_nt_drv->flm_thread, + "nt_flm_stat_thr", NULL, + adapter_flm_thread_fn, + (void *)p_drv); + if (res) { + NT_LOG(ERR, ETHDEV, "%s: error=%d [%s:%u]\n", + (pci_dev->name[0] ? pci_dev->name : "NA"), res, + __func__, __LINE__); + return -1; + } + } + + if (lag_config) { + /* LAG is activated, so only use port 0 */ + n_phy_ports = 1; + } else { + n_phy_ports = fpga_info->n_phy_ports; + } + for (int n_intf_no = 0; n_intf_no < n_phy_ports; n_intf_no++) { + const char *const p_port_id_str _unused = + p_nt_drv->adapter_info.mp_port_id_str[n_intf_no]; + struct pmd_internals *internals = NULL; + struct rte_eth_dev *eth_dev; + char name[32]; + int i; + + if ((1 << n_intf_no) & ~n_port_mask) { + NT_LOG(DBG, ETHDEV, + "%s: %s: interface #%d: skipping due to portmask 0x%02X\n", + __func__, p_port_id_str, n_intf_no, n_port_mask); + continue; + } + + snprintf(name, sizeof(name), "ntnic%d", n_intf_no); + NT_LOG(DBG, ETHDEV, "%s: %s: interface #%d: %s: '%s'\n", + __func__, p_port_id_str, n_intf_no, + (pci_dev->name[0] ? pci_dev->name : "NA"), name); + + internals = rte_zmalloc_socket(name, + sizeof(struct pmd_internals), + RTE_CACHE_LINE_SIZE, + pci_dev->device.numa_node); + if (!internals) { + NT_LOG(ERR, ETHDEV, "%s: %s: error=%d [%s:%u]\n", + (pci_dev->name[0] ? pci_dev->name : "NA"), name, + -1, __func__, __LINE__); + return -1; + } + + internals->pci_dev = pci_dev; + internals->n_intf_no = n_intf_no; + internals->if_index = n_intf_no; + internals->min_tx_pkt_size = 64; + internals->max_tx_pkt_size = 10000; + internals->type = PORT_TYPE_PHYSICAL; + internals->vhid = -1; + internals->port = n_intf_no; + internals->nb_rx_queues = nb_rx_queues; + internals->nb_tx_queues = nb_tx_queues; + + /* Not used queue index as dest port in bypass - use 0x80 + port nr */ + for (i = 0; i < MAX_QUEUES; i++) + internals->vpq[i].hw_id = -1; + + /* Setup queue_ids */ + if (nb_rx_queues > 1) { + NT_LOG(DBG, ETHDEV, + "(%i) NTNIC configured with Rx multi queues. %i queues\n", + 0 /*port*/, nb_rx_queues); + } + + if (nb_tx_queues > 1) { + NT_LOG(DBG, ETHDEV, + "(%i) NTNIC configured with Tx multi queues. %i queues\n", + 0 /*port*/, nb_tx_queues); + } + + int max_num_queues = (nb_rx_queues > nb_tx_queues) ? + nb_rx_queues : + nb_tx_queues; + int start_queue = allocate_queue(max_num_queues); + + if (start_queue < 0) + return -1; + + for (i = 0; i < (int)max_num_queues; i++) { + queue_ids[i].id = start_queue + i; + queue_ids[i].hw_id = queue_ids[i].id; + + internals->rxq_scg[i].queue = queue_ids[i]; + /* use same index in Rx and Tx rings */ + internals->txq_scg[i].queue = queue_ids[i]; + internals->rxq_scg[i].enabled = 0; + internals->txq_scg[i].type = internals->type; + internals->rxq_scg[i].type = internals->type; + internals->rxq_scg[i].port = internals->port; + } + + /* no tx queues - tx data goes out on phy */ + internals->vpq_nb_vq = 0; + + for (i = 0; i < (int)nb_tx_queues; i++) { + internals->txq_scg[i].port = internals->port; + internals->txq_scg[i].enabled = 0; + } + + /* Set MAC address (but only if the MAC address is permitted) */ + if (n_intf_no < fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_count) { + const uint64_t mac = + fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_value + + n_intf_no; + internals->eth_addrs[0].addr_bytes[0] = (mac >> 40) & + 0xFFu; + internals->eth_addrs[0].addr_bytes[1] = (mac >> 32) & + 0xFFu; + internals->eth_addrs[0].addr_bytes[2] = (mac >> 24) & + 0xFFu; + internals->eth_addrs[0].addr_bytes[3] = (mac >> 16) & + 0xFFu; + internals->eth_addrs[0].addr_bytes[4] = (mac >> 8) & + 0xFFu; + internals->eth_addrs[0].addr_bytes[5] = (mac >> 0) & + 0xFFu; + } + + eth_dev = rte_eth_dev_allocate(name); + if (!eth_dev) { + NT_LOG(ERR, ETHDEV, "%s: %s: error=%d [%s:%u]\n", + (pci_dev->name[0] ? pci_dev->name : "NA"), name, + -1, __func__, __LINE__); + return -1; + } + + internals->flw_dev = flow_get_eth_dev(0, n_intf_no, + eth_dev->data->port_id, + nb_rx_queues, + queue_ids, + &internals->txq_scg[0].rss_target_id, + profile, exception_path); + if (!internals->flw_dev) { + NT_LOG(ERR, VDPA, + "Error creating port. Resource exhaustion in HW\n"); + return -1; + } + + NT_LOG(DBG, ETHDEV, + "%s: [%s:%u] eth_dev %p, port_id %u, if_index %u\n", + __func__, __func__, __LINE__, eth_dev, + eth_dev->data->port_id, n_intf_no); + + /* connect structs */ + internals->p_drv = p_drv; + eth_dev->data->dev_private = internals; + eth_dev->data->mac_addrs = internals->eth_addrs; + + internals->port_id = eth_dev->data->port_id; + + /* + * if representor ports defined on this PF set the assigned port_id as the + * backer_port_id for the VFs + */ + if (rep.vpf_dev == pci_dev) + rep.pf_backer_port_id = eth_dev->data->port_id; + NT_LOG(DBG, ETHDEV, + "%s: [%s:%u] Setting up RX functions for SCG\n", + __func__, __func__, __LINE__); + eth_dev->rx_pkt_burst = eth_dev_rx_scg; + eth_dev->tx_pkt_burst = eth_dev_tx_scg; + eth_dev->tx_pkt_prepare = NULL; + + struct rte_eth_link pmd_link; + + pmd_link.link_speed = ETH_SPEED_NUM_NONE; + pmd_link.link_duplex = ETH_LINK_FULL_DUPLEX; + pmd_link.link_status = ETH_LINK_DOWN; + pmd_link.link_autoneg = ETH_LINK_AUTONEG; + + eth_dev->device = &pci_dev->device; + eth_dev->data->dev_link = pmd_link; + eth_dev->data->numa_node = pci_dev->device.numa_node; + eth_dev->dev_ops = &nthw_eth_dev_ops; + eth_dev->state = RTE_ETH_DEV_ATTACHED; + + rte_eth_copy_pci_info(eth_dev, pci_dev); + eth_dev_pci_specific_init(eth_dev, + pci_dev); /* performs rte_eth_copy_pci_info() */ + + p_drv->n_eth_dev_init_count++; + + if (lag_config) { + internals->lag_config = lag_config; + lag_config->internals = internals; + + /* Always merge port 0 and port 1 on a LAG bond */ + lag_set_port_group(0, (uint32_t)0x01); + lag_config->lag_thread_active = 1; + pthread_create(&lag_config->lag_tid, NULL, + lag_management, lag_config); + } + + if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE && + internals->flw_dev->ndev->be.tpe.ver >= 2) { + assert(nthw_eth_dev_ops.mtu_set == + dev_set_mtu_inline || + nthw_eth_dev_ops.mtu_set == NULL); + nthw_eth_dev_ops.mtu_set = dev_set_mtu_inline; + dev_set_mtu_inline(eth_dev, MTUINITVAL); + NT_LOG(DBG, ETHDEV, + "%s INLINE MTU supported, tpe version %d\n", + __func__, internals->flw_dev->ndev->be.tpe.ver); + } else { + NT_LOG(DBG, ETHDEV, "INLINE MTU not supported"); + } + } + + NT_LOG(DBG, ETHDEV, "%s: [%s:%u] leave\n", __func__, __FILE__, __LINE__); + +#ifdef NT_TOOLS + /* + * If NtConnect interface must be started for external tools + */ + ntconn_adap_register(p_drv); + ntconn_stat_register(p_drv); + + /* Determine CPU used by the DPDK */ + cpu_set_t cpuset; + unsigned int lcore_id; + + CPU_ZERO(&cpuset); + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + if (rte_lcore_has_role(lcore_id, ROLE_OFF)) + continue; + rte_cpuset_t lcore_cpuset = rte_lcore_cpuset(lcore_id); + + RTE_CPU_OR(&cpuset, &cpuset, &lcore_cpuset); + } + /* Set available CPU for ntconnect */ + RTE_CPU_NOT(&cpuset, &cpuset); + + ntconn_flow_register(p_drv); + ntconn_meter_register(p_drv); +#ifdef NTCONNECT_TEST + ntconn_test_register(p_drv); +#endif + ntconnect_init(NTCONNECT_SOCKET, cpuset); +#endif + + return 0; +} + +static int nthw_pci_dev_deinit(struct rte_eth_dev *eth_dev __rte_unused) +{ + int i; + + NT_LOG(DBG, ETHDEV, "%s: [%s:%u] start\n", __func__, __FILE__, __LINE__); + + struct pmd_internals *internals = pmd_intern_base; + + sleep(1); /* let running threads end Rx and Tx activity */ + + while (internals) { + for (i = internals->nb_tx_queues - 1; i >= 0; i--) { + nthw_release_managed_tx_virt_queue(internals->txq_scg[i].vq); + release_hw_virtio_queues(&internals->txq_scg[i].hwq); + } + + for (i = internals->nb_rx_queues - 1; i >= 0; i--) { + nthw_release_managed_rx_virt_queue(internals->rxq_scg[i].vq); + release_hw_virtio_queues(&internals->rxq_scg[i].hwq); + } + internals = internals->next; + } + + for (i = 0; i < MAX_REL_VQS; i++) { + if (rel_virt_queue[i].vq != NULL) { + if (rel_virt_queue[i].rx) { + if (rel_virt_queue[i].managed) + nthw_release_managed_rx_virt_queue(rel_virt_queue[i].vq); + else + nthw_release_rx_virt_queue(rel_virt_queue[i].vq); + } else { + if (rel_virt_queue[i].managed) + nthw_release_managed_tx_virt_queue(rel_virt_queue[i].vq); + else + nthw_release_tx_virt_queue(rel_virt_queue[i].vq); + } + rel_virt_queue[i].vq = NULL; + } + } + + nt_vfio_remove(EXCEPTION_PATH_HID); + + return 0; +} + +static void signal_handler_func_int(int sig) +{ + if (sig != SIGINT) { + signal(sig, previous_handler); + raise(sig); + return; + } + kill_pmd = 1; +} + +static void *shutdown_thread(void *arg __rte_unused) +{ + struct rte_eth_dev dummy; + + while (!kill_pmd) + usleep(100000); + + NT_LOG(DBG, ETHDEV, "%s: Shutting down because of ctrl+C\n", __func__); + nthw_pci_dev_deinit(&dummy); + + signal(SIGINT, previous_handler); + raise(SIGINT); + + return NULL; +} + +static int init_shutdown(void) +{ + NT_LOG(DBG, ETHDEV, "%s: Starting shutdown handler\n", __func__); + kill_pmd = 0; + previous_handler = signal(SIGINT, signal_handler_func_int); + pthread_create(&shutdown_tid, NULL, shutdown_thread, NULL); + + /* + * 1 time calculation of 1 sec stat update rtc cycles to prevent stat poll + * flooding by OVS from multiple virtual port threads - no need to be precise + */ + uint64_t now_rtc = rte_get_tsc_cycles(); + + usleep(10000); + rte_tsc_freq = 100 * (rte_get_tsc_cycles() - now_rtc); + + return 0; +} + +static int nthw_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, + struct rte_pci_device *pci_dev) +{ + int res; + + NT_LOG(DBG, ETHDEV, "%s: [%s:%u] start\n", __func__, __FILE__, __LINE__); + +#if defined(DEBUG) + NT_LOG(DBG, NTHW, "Testing NTHW %u [%s:%u]\n", + nt_log_module_logtype[NT_LOG_MODULE_INDEX(NT_LOG_MODULE_NTHW)], + __func__, __LINE__); +#endif + + NT_LOG(DBG, ETHDEV, "%s: pcidev: name: '%s'\n", __func__, + pci_dev->name); + NT_LOG(DBG, ETHDEV, "%s: devargs: name: '%s'\n", __func__, + pci_dev->device.name); + if (pci_dev->device.devargs) { + NT_LOG(DBG, ETHDEV, "%s: devargs: args: '%s'\n", __func__, + (pci_dev->device.devargs->args ? + pci_dev->device.devargs->args : + "NULL")); + NT_LOG(DBG, ETHDEV, "%s: devargs: data: '%s'\n", __func__, + (pci_dev->device.devargs->data ? + pci_dev->device.devargs->data : + "NULL")); + } + + const int n_rte_has_pci = rte_eal_has_pci(); + + NT_LOG(DBG, ETHDEV, "has_pci=%d\n", n_rte_has_pci); + if (n_rte_has_pci == 0) { + NT_LOG(ERR, ETHDEV, "has_pci=%d: this PMD needs hugepages\n", + n_rte_has_pci); + return -1; + } + + const int n_rte_vfio_no_io_mmu_enabled = rte_vfio_noiommu_is_enabled(); + + NT_LOG(DBG, ETHDEV, "vfio_no_iommu_enabled=%d\n", + n_rte_vfio_no_io_mmu_enabled); + if (n_rte_vfio_no_io_mmu_enabled) { + NT_LOG(ERR, ETHDEV, + "vfio_no_iommu_enabled=%d: this PMD needs VFIO IOMMU\n", + n_rte_vfio_no_io_mmu_enabled); + return -1; + } + + const enum rte_iova_mode n_rte_io_va_mode = rte_eal_iova_mode(); + + NT_LOG(DBG, ETHDEV, "iova mode=%d\n", n_rte_io_va_mode); + if (n_rte_io_va_mode != RTE_IOVA_PA) { + NT_LOG(WRN, ETHDEV, + "iova mode (%d) should be PA for performance reasons\n", + n_rte_io_va_mode); + } + + const int n_rte_has_huge_pages = rte_eal_has_hugepages(); + + NT_LOG(DBG, ETHDEV, "has_hugepages=%d\n", n_rte_has_huge_pages); + if (n_rte_has_huge_pages == 0) { + NT_LOG(ERR, ETHDEV, + "has_hugepages=%d: this PMD needs hugepages\n", + n_rte_has_huge_pages); + return -1; + } + + NT_LOG(DBG, ETHDEV, + "busid=" PCI_PRI_FMT + " pciid=%04x:%04x_%04x:%04x locstr=%s @ numanode=%d: drv=%s drvalias=%s\n", + pci_dev->addr.domain, pci_dev->addr.bus, pci_dev->addr.devid, + pci_dev->addr.function, pci_dev->id.vendor_id, + pci_dev->id.device_id, pci_dev->id.subsystem_vendor_id, + pci_dev->id.subsystem_device_id, + pci_dev->name[0] ? pci_dev->name : "NA", /* locstr */ + pci_dev->device.numa_node, + pci_dev->driver->driver.name ? pci_dev->driver->driver.name : + "NA", + pci_dev->driver->driver.alias ? pci_dev->driver->driver.alias : + "NA"); + + if (pci_dev->id.vendor_id == NT_HW_PCI_VENDOR_ID) { + if (pci_dev->id.device_id == NT_HW_PCI_DEVICE_ID_NT200A01 || + pci_dev->id.device_id == NT_HW_PCI_DEVICE_ID_NT50B01) { + if (pci_dev->id.subsystem_device_id != 0x01) { + NT_LOG(DBG, ETHDEV, + "%s: PCIe bifurcation - secondary endpoint " + "found - leaving probe\n", + __func__); + return -1; + } + } + } + + res = nthw_pci_dev_init(pci_dev); + + init_shutdown(); + + NT_LOG(DBG, ETHDEV, "%s: leave: res=%d\n", __func__, res); + return res; +} + +static int nthw_pci_remove(struct rte_pci_device *pci_dev) +{ + NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__); + + return rte_eth_dev_pci_generic_remove(pci_dev, nthw_pci_dev_deinit); +} + +static int nt_log_init_impl(void) +{ + rte_log_set_global_level(RTE_LOG_DEBUG); + + NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__); + + for (int i = NT_LOG_MODULE_GENERAL; i < NT_LOG_MODULE_END; ++i) { + int index = NT_LOG_MODULE_INDEX(i); + + nt_log_module_logtype[index] = + rte_log_register_type_and_pick_level(nt_log_module_eal_name[index], + RTE_LOG_INFO); + } + + NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__); + + return 0; +} + +__rte_format_printf(3, 0) +static int nt_log_log_impl(enum nt_log_level level, uint32_t module, + const char *format, va_list args) +{ + uint32_t rte_level = 0; + uint32_t rte_module = 0; + + switch (level) { + case NT_LOG_ERR: + rte_level = RTE_LOG_ERR; + break; + case NT_LOG_WRN: + rte_level = RTE_LOG_WARNING; + break; + case NT_LOG_INF: + rte_level = RTE_LOG_INFO; + break; + default: + rte_level = RTE_LOG_DEBUG; + } + + rte_module = + (module >= NT_LOG_MODULE_GENERAL && + module < NT_LOG_MODULE_END) ? + (uint32_t)nt_log_module_logtype[NT_LOG_MODULE_INDEX(module)] : module; + + return (int)rte_vlog(rte_level, rte_module, format, args); +} + +static int nt_log_is_debug_impl(uint32_t module) +{ + if (module < NT_LOG_MODULE_GENERAL || module >= NT_LOG_MODULE_END) + return -1; + int index = NT_LOG_MODULE_INDEX(module); + + return rte_log_get_level(nt_log_module_logtype[index]) == RTE_LOG_DEBUG; +} + +RTE_INIT(ntnic_rte_init); /* must go before function */ + +static void ntnic_rte_init(void) +{ + static struct nt_log_impl impl = { .init = &nt_log_init_impl, + .log = &nt_log_log_impl, + .is_debug = &nt_log_is_debug_impl + }; + + nt_log_init(&impl); +} + +static struct rte_pci_driver rte_nthw_pmd = { + .driver = { + .name = "net_ntnic", + }, + + .id_table = nthw_pci_id_map, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING, + .probe = nthw_pci_probe, + .remove = nthw_pci_remove, +}; + +RTE_PMD_REGISTER_PCI(net_ntnic, rte_nthw_pmd); +RTE_PMD_REGISTER_PCI_TABLE(net_ntnic, nthw_pci_id_map); +RTE_PMD_REGISTER_KMOD_DEP(net_ntnic, "* vfio-pci"); + +/* + * VF and VDPA code + */ +int register_release_virtqueue_info(struct nthw_virt_queue *vq, int rx, + int managed) +{ + int i; + + for (i = 0; i < MAX_REL_VQS; i++) { + if (rel_virt_queue[i].vq == NULL) { + rel_virt_queue[i].vq = vq; + rel_virt_queue[i].rx = rx; + rel_virt_queue[i].managed = managed; + return 0; + } + } + return -1; +} + +int de_register_release_virtqueue_info(struct nthw_virt_queue *vq) +{ + int i; + + for (i = 0; i < MAX_REL_VQS; i++) { + if (rel_virt_queue[i].vq == vq) { + rel_virt_queue[i].vq = NULL; + return 0; + } + } + return -1; +} + +struct pmd_internals *vp_vhid_instance_ready(int vhid) +{ + struct pmd_internals *intern = pmd_intern_base; + + while (intern) { + if (intern->vhid == vhid) + return intern; + intern = intern->next; + } + return NULL; +} + +struct pmd_internals *vp_path_instance_ready(const char *path) +{ + struct pmd_internals *intern = pmd_intern_base; + + while (intern) { + printf("Searching for path: \"%s\" == \"%s\" (%d)\n", + intern->vhost_path, path, + strcmp(intern->vhost_path, path)); + if (strcmp(intern->vhost_path, path) == 0) + return intern; + intern = intern->next; + } + return NULL; +} + +static void read_port_queues_mapping(char *str, int *portq) +{ + int len; + char *tok; + + while (*str != '[' && *str != '\0') + str++; + + if (*str == '\0') + return; + str++; + len = strlen(str); + char *str_e = &str[len]; + + while (*str_e != ']' && str_e != str) + str_e--; + if (*str_e != ']') + return; + *str_e = '\0'; + + tok = strtok(str, ",;"); + while (tok) { + char *ch = strchr(tok, ':'); + + if (ch) { + *ch = '\0'; + int port = atoi(tok); + int nvq = atoi(ch + 1); + + if (port >= 0 && + port < MAX_FPGA_VIRTUAL_PORTS_SUPPORTED && + nvq > 0 && nvq < MAX_QUEUES) + portq[port] = nvq; + } + + tok = strtok(NULL, ",;"); + } +} + +int setup_virtual_pf_representor_base(struct rte_pci_device *dev) +{ + struct rte_eth_devargs eth_da; + + eth_da.nb_representor_ports = 0U; + if (dev->device.devargs && dev->device.devargs->args) { + char *ch = strstr(dev->device.devargs->args, "portqueues"); + + if (ch) { + read_port_queues_mapping(ch, rep.portqueues); + /* + * Remove this extension. DPDK cannot read representor=[x] if added + * parameter to the end + */ + *ch = '\0'; + } + + int err = rte_eth_devargs_parse(dev->device.devargs->args, + ð_da); + if (err) { + rte_errno = -err; + NT_LOG(ERR, VDPA, + "failed to process device arguments: %s", + strerror(rte_errno)); + return -1; + } + + if (eth_da.nb_representor_ports) { + rep.vpf_dev = dev; + rep.eth_da = eth_da; + } + } + /* Will be set later when assigned to this PF */ + rep.pf_backer_port_id = RTE_MAX_ETHPORTS; + return eth_da.nb_representor_ports; +} + +static inline struct rte_eth_dev * +rte_eth_vdev_allocate(struct rte_pci_device *dev, const char *name, + size_t private_data_size, int *n_vq) +{ + static int next_rep_p; + struct rte_eth_dev *eth_dev = NULL; + + eth_dev = rte_eth_dev_allocate(name); + if (!eth_dev) + return NULL; + + NT_LOG(DBG, VDPA, "%s: [%s:%u] eth_dev %p, port_id %u\n", __func__, + __func__, __LINE__, eth_dev, eth_dev->data->port_id); + + if (private_data_size) { + eth_dev->data->dev_private = rte_zmalloc_socket(name, private_data_size, + RTE_CACHE_LINE_SIZE, + dev->device.numa_node); + if (!eth_dev->data->dev_private) { + rte_eth_dev_release_port(eth_dev); + return NULL; + } + } + + eth_dev->intr_handle = NULL; + eth_dev->data->numa_node = dev->device.numa_node; + eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR; + + if (rep.vpf_dev && rep.eth_da.nb_representor_ports > next_rep_p) { + eth_dev->data->representor_id = + rep.eth_da.representor_ports[next_rep_p++]; + eth_dev->device = &rep.vpf_dev->device; + eth_dev->data->backer_port_id = rep.pf_backer_port_id; + } else { + eth_dev->data->representor_id = nt_vfio_vf_num(dev); + eth_dev->device = &dev->device; + } + + if (rep.portqueues[eth_dev->data->representor_id]) + *n_vq = rep.portqueues[eth_dev->data->representor_id]; + + else + *n_vq = 1; + return eth_dev; +} + +static inline const char * +rte_vdev_device_name(const struct rte_pci_device *dev) +{ + if (dev && dev->device.name) + return dev->device.name; + return NULL; +} + +static const char *const valid_args[] = { +#define VP_VLAN_ID "vlan" + VP_VLAN_ID, +#define VP_SEPARATE_SOCKET "sep" + VP_SEPARATE_SOCKET, NULL +}; + +static int rte_pmd_vp_init_internals(struct rte_pci_device *vdev, + struct rte_eth_dev **eth_dev) +{ + struct pmd_internals *internals = NULL; + struct rte_eth_dev_data *data = NULL; + int i; + struct rte_eth_link pmd_link; + int numa_node = vdev->device.numa_node; + const char *name; + int n_vq; + int num_queues; + uint8_t port; + uint32_t vlan = 0; + uint32_t separate_socket = 0; + + enum fpga_info_profile fpga_profile = + get_fpga_profile_from_pci(vdev->addr); + + name = rte_vdev_device_name(vdev); + + /* + * Now do all data allocation - for eth_dev structure + * and internal (private) data + */ + + if (vdev && vdev->device.devargs) { + struct rte_kvargs *kvlist = NULL; + + kvlist = rte_kvargs_parse(vdev->device.devargs->args, + valid_args); + if (!kvlist) { + NT_LOG(ERR, VDPA, "error when parsing param"); + goto error; + } + + if (rte_kvargs_count(kvlist, VP_VLAN_ID) == 1) { + if (rte_kvargs_process(kvlist, VP_VLAN_ID, + &string_to_u32, &vlan) < 0) { + NT_LOG(ERR, VDPA, "error to parse %s", + VP_VLAN_ID); + goto error; + } + } + + if (rte_kvargs_count(kvlist, VP_SEPARATE_SOCKET) == 1) { + if (rte_kvargs_process(kvlist, VP_SEPARATE_SOCKET, + &string_to_u32, + &separate_socket) < 0) { + NT_LOG(ERR, VDPA, "error to parse %s", + VP_SEPARATE_SOCKET); + goto error; + } + } + } + + n_vq = 0; + *eth_dev = + rte_eth_vdev_allocate(vdev, name, sizeof(*internals), &n_vq); + if (*eth_dev == NULL) + goto error; + + data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node); + if (data == NULL) + goto error; + + NT_LOG(DBG, VDPA, "%s: [%s:%u] eth_dev %p, port_id %u, if_index %u\n", + __func__, __func__, __LINE__, *eth_dev, + (*eth_dev)->data->port_id, (*eth_dev)->data->representor_id); + + port = (*eth_dev)->data->representor_id; + + if (port < MAX_NTNIC_PORTS || port >= VIRTUAL_TUNNEL_PORT_OFFSET) { + NT_LOG(ERR, VDPA, + "(%i) Creating ntvp-backend ethdev on numa socket %i has invalid representor port\n", + port, numa_node); + return -1; + } + NT_LOG(DBG, VDPA, + "(%i) Creating ntnic-backend ethdev on numa socket %i\n", port, + numa_node); + + /* Build up private dev data */ + internals = (*eth_dev)->data->dev_private; + internals->pci_dev = vdev; + if (fpga_profile == FPGA_INFO_PROFILE_VSWITCH) { + internals->type = PORT_TYPE_VIRTUAL; + internals->nb_rx_queues = 1; + internals->nb_tx_queues = 1; + } else { + internals->type = PORT_TYPE_OVERRIDE; + internals->nb_rx_queues = n_vq; + internals->nb_tx_queues = n_vq; + } + internals->p_drv = get_pdrv_from_pci(vdev->addr); + + if (n_vq > MAX_QUEUES) { + NT_LOG(ERR, VDPA, + "Error creating virtual port. Too many rx or tx queues. Max is %i\n", + MAX_QUEUES); + goto error; + } + + if (n_vq > FLOW_MAX_QUEUES) { + NT_LOG(ERR, VDPA, + "Error creating virtual port. Too many rx or tx queues for NIC. Max reported %i\n", + FLOW_MAX_QUEUES); + goto error; + } + + /* Initialize HB output dest to none */ + for (i = 0; i < MAX_QUEUES; i++) + internals->vpq[i].hw_id = -1; + + internals->vhid = -1; + internals->port = port; + internals->if_index = port; + internals->port_id = (*eth_dev)->data->port_id; + internals->vlan = vlan; + + /* + * Create first time all queues in HW + */ + struct flow_queue_id_s queue_ids[FLOW_MAX_QUEUES + 1]; + + if (fpga_profile == FPGA_INFO_PROFILE_VSWITCH) + num_queues = n_vq + 1; /* add 1: 0th for exception */ + else + num_queues = n_vq; + + int start_queue = allocate_queue(num_queues); + + if (start_queue < 0) { + NT_LOG(ERR, VDPA, + "Error creating virtual port. Too many rx queues. Could not allocate %i\n", + num_queues); + goto error; + } + + int vhid = -1; + + for (i = 0; i < num_queues; i++) { + queue_ids[i].id = start_queue + i; /* 0th is exception queue */ + queue_ids[i].hw_id = start_queue + i; + } + + if (fpga_profile == FPGA_INFO_PROFILE_VSWITCH) { + internals->txq_scg[0].rss_target_id = -1; + internals->flw_dev = flow_get_eth_dev(0, internals->port, + internals->port_id, num_queues, + queue_ids, + &internals->txq_scg[0].rss_target_id, + FLOW_ETH_DEV_PROFILE_VSWITCH, 0); + } else { + uint16_t in_port = internals->port & 1; + char name[RTE_ETH_NAME_MAX_LEN]; + struct pmd_internals *main_internals; + struct rte_eth_dev *eth_dev; + int i; + int status; + + /* Get name of in_port */ + status = rte_eth_dev_get_name_by_port(in_port, name); + if (status != 0) { + NT_LOG(ERR, VDPA, "Name of port not found"); + goto error; + } + NT_LOG(DBG, VDPA, "Name of port %u = %s\n", in_port, name); + + /* Get ether device for in_port */ + eth_dev = rte_eth_dev_get_by_name(name); + if (eth_dev == NULL) { + NT_LOG(ERR, VDPA, "Failed to get eth device"); + goto error; + } + + /* Get internals for in_port */ + main_internals = + (struct pmd_internals *)eth_dev->data->dev_private; + NT_LOG(DBG, VDPA, "internals port %u\n\n", + main_internals->port); + if (main_internals->port != in_port) { + NT_LOG(ERR, VDPA, "Port did not match"); + goto error; + } + + /* Get flow device for in_port */ + internals->flw_dev = main_internals->flw_dev; + + for (i = 0; i < num_queues && i < MAX_QUEUES; i++) { + NT_LOG(DBG, VDPA, "Queue: %u\n", + queue_ids[i].id); + NT_LOG(DBG, VDPA, "HW ID: %u\n", + queue_ids[i].hw_id); + if (flow_eth_dev_add_queue(main_internals->flw_dev, + &queue_ids[i])) { + NT_LOG(ERR, VDPA, "Could not add queue"); + goto error; + } + } + } + + if (!internals->flw_dev) { + NT_LOG(ERR, VDPA, + "Error creating virtual port. Resource exhaustion in HW\n"); + goto error; + } + + char path[128]; + + if (!separate_socket) { + sprintf(path, "%sstdvio%i", DVIO_VHOST_DIR_NAME, port); + } else { + sprintf(path, "%sstdvio%i/stdvio%i", DVIO_VHOST_DIR_NAME, port, + port); + } + + internals->vpq_nb_vq = n_vq; + if (fpga_profile == FPGA_INFO_PROFILE_VSWITCH) { + if (nthw_vdpa_init(vdev, (*eth_dev)->device->name, path, + queue_ids[1].hw_id, n_vq, n_vq, + internals->port, &vhid)) { + NT_LOG(ERR, VDPA, + "*********** ERROR *********** vDPA RELAY INIT\n"); + goto error; + } + for (i = 0; i < n_vq; i++) { + internals->vpq[i] = + queue_ids[i + 1]; /* queue 0 is for exception */ + } + } else { + if (nthw_vdpa_init(vdev, (*eth_dev)->device->name, path, + queue_ids[0].hw_id, n_vq, n_vq, + internals->port, &vhid)) { + NT_LOG(ERR, VDPA, + "*********** ERROR *********** vDPA RELAY INIT\n"); + goto error; + } + for (i = 0; i < n_vq; i++) + internals->vpq[i] = queue_ids[i]; + } + + /* + * Exception queue for OVS SW path + */ + internals->rxq_scg[0].queue = queue_ids[0]; + internals->txq_scg[0].queue = + queue_ids[0]; /* use same index in Rx and Tx rings */ + internals->rxq_scg[0].enabled = 0; + internals->txq_scg[0].port = port; + + internals->txq_scg[0].type = internals->type; + internals->rxq_scg[0].type = internals->type; + internals->rxq_scg[0].port = internals->port; + + /* Setup pmd_link info */ + pmd_link.link_speed = ETH_SPEED_NUM_NONE; + pmd_link.link_duplex = ETH_LINK_FULL_DUPLEX; + pmd_link.link_status = ETH_LINK_DOWN; + + rte_memcpy(data, (*eth_dev)->data, sizeof(*data)); + data->dev_private = internals; + data->port_id = (*eth_dev)->data->port_id; + + data->nb_rx_queues = 1; /* this is exception */ + data->nb_tx_queues = 1; + + data->dev_link = pmd_link; + data->mac_addrs = ð_addr_vp[port - MAX_NTNIC_PORTS]; + data->numa_node = numa_node; + + (*eth_dev)->data = data; + (*eth_dev)->dev_ops = &nthw_eth_dev_ops; + + if (pmd_intern_base) { + struct pmd_internals *intern = pmd_intern_base; + + while (intern->next) + intern = intern->next; + intern->next = internals; + } else { + pmd_intern_base = internals; + } + internals->next = NULL; + + atomic_store(&internals->vhid, vhid); + + LIST_INIT(&internals->mtr_profiles); + LIST_INIT(&internals->mtrs); + return 0; + +error: + if (data) + rte_free(data); + if (internals) + rte_free(internals); + return -1; +} + +/* + * PORT_TYPE_OVERRIDE cannot receive data through SCG as the queues + * are going to VF/vDPA + */ +static uint16_t eth_dev_rx_scg_dummy(void *queue __rte_unused, + struct rte_mbuf **bufs __rte_unused, + uint16_t nb_pkts __rte_unused) +{ + return 0; +} + +/* + * PORT_TYPE_OVERRIDE cannot transmit data through SCG as the queues + * are coming from VF/vDPA + */ +static uint16_t eth_dev_tx_scg_dummy(void *queue __rte_unused, + struct rte_mbuf **bufs __rte_unused, + uint16_t nb_pkts __rte_unused) +{ + return 0; +} + +int nthw_create_vf_interface_dpdk(struct rte_pci_device *pci_dev) +{ + struct pmd_internals *internals; + struct rte_eth_dev *eth_dev; + + /* Create virtual function DPDK PCI devices.*/ + if (rte_pmd_vp_init_internals(pci_dev, ð_dev) < 0) + return -1; + + internals = (struct pmd_internals *)eth_dev->data->dev_private; + + if (internals->type == PORT_TYPE_OVERRIDE) { + eth_dev->rx_pkt_burst = eth_dev_rx_scg_dummy; + eth_dev->tx_pkt_burst = eth_dev_tx_scg_dummy; + } else { + eth_dev->rx_pkt_burst = eth_dev_rx_scg; + eth_dev->tx_pkt_burst = eth_dev_tx_scg; + } + + rte_eth_dev_probing_finish(eth_dev); + + return 0; +} + +int nthw_remove_vf_interface_dpdk(struct rte_pci_device *pci_dev) +{ + struct rte_eth_dev *eth_dev = NULL; + + NT_LOG(DBG, VDPA, "Closing ntvp pmd on numa socket %u\n", + rte_socket_id()); + + if (!pci_dev) + return -1; + + /* Clean up all vDPA devices */ + nthw_vdpa_close(); + + /* reserve an ethdev entry */ + eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(pci_dev)); + if (eth_dev == NULL) + return -1; + + rte_free(eth_dev->data->dev_private); + rte_free(eth_dev->data); + + rte_eth_dev_release_port(eth_dev); + + return 0; +} + +/* + * LAG + */ + +#define LAG_PORT0_ONLY (100) +#define LAG_BALANCED_50_50 (50) +#define LAG_PORT1_ONLY (0) + +#define LAG_NO_TX (0) +#define LAG_PORT0_INDEX (1) +#define LAG_PORT1_INDEX (2) +#define LAG_HASH_INDEX (3) + +static int lag_nop(lag_config_t *config __rte_unused) +{ + return 0; +} + +static int lag_balance(lag_config_t *config __rte_unused) +{ + NT_LOG(DBG, ETHDEV, "AA LAG: balanced output\n"); + return lag_set_config(0, FLOW_LAG_SET_BALANCE, 0, LAG_BALANCED_50_50); +} + +static int lag_port0_active(lag_config_t *config __rte_unused) +{ + NT_LOG(DBG, ETHDEV, "AA LAG: port 0 output only\n"); + return lag_set_config(0, FLOW_LAG_SET_BALANCE, 0, LAG_PORT0_ONLY); +} + +static int lag_port1_active(lag_config_t *config __rte_unused) +{ + NT_LOG(DBG, ETHDEV, "AA LAG: port 1 output only\n"); + return lag_set_config(0, FLOW_LAG_SET_BALANCE, 0, LAG_PORT1_ONLY); +} + +static int lag_notx(lag_config_t *config __rte_unused) +{ + NT_LOG(DBG, ETHDEV, "AA LAG: no link\n"); + + int retval = 0; + + retval += + lag_set_config(0, FLOW_LAG_SET_ALL, LAG_PORT0_INDEX, LAG_NO_TX); + retval += + lag_set_config(0, FLOW_LAG_SET_ALL, LAG_HASH_INDEX, LAG_NO_TX); + return retval; +} + +static bool lag_get_link_status(lag_config_t *lag_config, uint8_t port) +{ + struct adapter_info_s *p_adapter_info = + &lag_config->internals->p_drv->ntdrv.adapter_info; + const bool link_up = nt4ga_port_get_link_status(p_adapter_info, port); + + NT_LOG(DBG, ETHDEV, "port %d status: %d\n", port, link_up); + return link_up; +} + +static int lag_get_status(lag_config_t *config) +{ + uint8_t port0 = lag_get_link_status(config, 0); + + uint8_t port1 = lag_get_link_status(config, 1); + + uint8_t status = (port1 << 1 | port0); + return status; +} + +static int lag_activate_primary(lag_config_t *config) +{ + int retval; + + uint8_t port_0_distribution; + uint8_t blocked_port; + + if (config->primary_port == 0) { + /* If port 0 is the active primary, then it take 100% of the hash distribution. */ + port_0_distribution = 100; + blocked_port = LAG_PORT1_INDEX; + } else { + /* If port 1 is the active primary, then port 0 take 0% of the hash distribution. */ + port_0_distribution = 0; + blocked_port = LAG_PORT0_INDEX; + } + + retval = + lag_set_config(0, FLOW_LAG_SET_BALANCE, 0, port_0_distribution); + + /* Block Rx on the backup port */ + retval += lag_set_port_block(0, blocked_port); + + return retval; +} + +static int lag_activate_backup(lag_config_t *config) +{ + int retval; + + uint8_t port_0_distribution; + uint8_t blocked_port; + + if (config->backup_port == 0) { + /* If port 0 is the active backup, then it take 100% of the hash distribution. */ + port_0_distribution = 100; + blocked_port = LAG_PORT1_INDEX; + } else { + /* If port 1 is the active backup, then port 0 take 0% of the hash distribution. */ + port_0_distribution = 0; + blocked_port = LAG_PORT0_INDEX; + } + + /* Tx only on the backup port */ + retval = + lag_set_config(0, FLOW_LAG_SET_BALANCE, 0, port_0_distribution); + + /* Block Rx on the primary port */ + retval += lag_set_port_block(0, blocked_port); + + return retval; +} + +static int lag_active_backup(lag_config_t *config) +{ + uint8_t backup_port_active = 0; + + /* Initialize with the primary port active */ + lag_activate_primary(config); + + while (config->lag_thread_active) { + usleep(500 * + 1000); /* 500 ms sleep between testing the link status. */ + + bool primary_port_status = + lag_get_link_status(config, config->primary_port); + + if (!primary_port_status) { + bool backup_port_status = + lag_get_link_status(config, config->backup_port); + /* If the backup port has been activated, no need to do more. */ + if (backup_port_active) + continue; + + /* If the backup port is up, flip to it. */ + if (backup_port_status) { + NT_LOG(DBG, ETHDEV, + "LAG: primary port down => swapping to backup port\n"); + lag_activate_backup(config); + backup_port_active = 1; + } + } else { + /* If using the backup port and primary come back. */ + if (backup_port_active) { + NT_LOG(DBG, ETHDEV, + "LAG: primary port restored => swapping to primary port\n"); + lag_activate_primary(config); + backup_port_active = 0; + } /* Backup is active, while primary is restored. */ + } /* Primary port status */ + } + + return 0; +} + +typedef int (*lag_aa_action)(lag_config_t *config); + +/* port 0 is LSB and port 1 is MSB */ +enum lag_state_e { + P0DOWN_P1DOWN = 0b00, + P0UP_P1DOWN = 0b01, + P0DOWN_P1UP = 0b10, + P0UP_P1UP = 0b11 +}; + +struct lag_action_s { + enum lag_state_e src_state; + enum lag_state_e dst_state; + lag_aa_action action; +}; + +struct lag_action_s actions[] = { + /* No action in same state */ + { P0UP_P1UP, P0UP_P1UP, lag_nop }, + { P0UP_P1DOWN, P0UP_P1DOWN, lag_nop }, + { P0DOWN_P1UP, P0DOWN_P1UP, lag_nop }, + { P0DOWN_P1DOWN, P0DOWN_P1DOWN, lag_nop }, + + /* UU start */ + { P0UP_P1UP, P0UP_P1DOWN, lag_port0_active }, + { P0UP_P1UP, P0DOWN_P1UP, lag_port1_active }, + { P0UP_P1UP, P0DOWN_P1DOWN, lag_notx }, + + /* UD start */ + { P0UP_P1DOWN, P0DOWN_P1DOWN, lag_notx }, + { P0UP_P1DOWN, P0DOWN_P1UP, lag_port1_active }, + { P0UP_P1DOWN, P0UP_P1UP, lag_balance }, + + /* DU start */ + { P0DOWN_P1UP, P0DOWN_P1DOWN, lag_notx }, + { P0DOWN_P1UP, P0UP_P1DOWN, lag_port0_active }, + { P0DOWN_P1UP, P0UP_P1UP, lag_balance }, + + /* DD start */ + { P0DOWN_P1DOWN, P0DOWN_P1UP, lag_port1_active }, + { P0DOWN_P1DOWN, P0UP_P1DOWN, lag_port0_active }, + { P0DOWN_P1DOWN, P0UP_P1UP, lag_balance }, +}; + +static lag_aa_action lookup_action(enum lag_state_e current_state, + enum lag_state_e new_state) +{ + uint32_t i; + + for (i = 0; i < sizeof(actions) / sizeof(struct lag_action_s); i++) { + if (actions[i].src_state == current_state && + actions[i].dst_state == new_state) + return actions[i].action; + } + return NULL; +} + +static int lag_active_active(lag_config_t *config) +{ + enum lag_state_e ports_status; + + /* Set the initial state to 50/50% */ + enum lag_state_e current_state = P0UP_P1UP; + + lag_balance(config); + /* No ports are blocked in active/active */ + lag_set_port_block(0, 0); + + lag_aa_action action; + + while (config->lag_thread_active) { + /* 500 ms sleep between testing the link status. */ + usleep(500 * 1000); + + ports_status = lag_get_status(config); + + action = lookup_action(current_state, ports_status); + action(config); + + current_state = ports_status; + } + + return 0; +} + +static void *lag_management(void *arg) +{ + lag_config_t *config = (lag_config_t *)arg; + + switch (config->mode) { + case BONDING_MODE_ACTIVE_BACKUP: + lag_active_backup(config); + break; + + case BONDING_MODE_8023AD: + lag_active_active(config); + break; + + default: + fprintf(stderr, "Unsupported NTbond mode\n"); + return NULL; + } + + return NULL; +} diff --git a/drivers/net/ntnic/ntnic_ethdev.h b/drivers/net/ntnic/ntnic_ethdev.h new file mode 100644 index 0000000000..a82027cbe7 --- /dev/null +++ b/drivers/net/ntnic/ntnic_ethdev.h @@ -0,0 +1,357 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTNIC_ETHDEV_H__ +#define __NTNIC_ETHDEV_H__ + +#include + +#include +#include /* RTE_VERSION, RTE_VERSION_NUM */ +#include +#include +#include +#include + +#include "ntos_system.h" +#include "ntnic_dbsconfig.h" +#include "stream_binary_flow_api.h" + +#if (RTE_VERSION_NUM(22, 07, 0, 0) <= RTE_VERSION) +#undef ETH_LINK_HALF_DUPLEX +#undef ETH_LINK_FULL_DUPLEX +#undef ETH_LINK_DOWN +#undef ETH_LINK_UP +#undef ETH_LINK_FIXED +#undef ETH_LINK_AUTONEG +#undef ETH_SPEED_NUM_NONE +#undef ETH_SPEED_NUM_10M +#undef ETH_SPEED_NUM_100M +#undef ETH_SPEED_NUM_1G +#undef ETH_SPEED_NUM_2_5G +#undef ETH_SPEED_NUM_5G +#undef ETH_SPEED_NUM_10G +#undef ETH_SPEED_NUM_20G +#undef ETH_SPEED_NUM_25G +#undef ETH_SPEED_NUM_40G +#undef ETH_SPEED_NUM_50G +#undef ETH_SPEED_NUM_56G +#undef ETH_SPEED_NUM_100G +#undef ETH_SPEED_NUM_200G +#undef ETH_SPEED_NUM_UNKNOWN +#undef ETH_LINK_SPEED_AUTONEG +#undef ETH_LINK_SPEED_FIXED +#undef ETH_LINK_SPEED_10M_HD +#undef ETH_LINK_SPEED_10M +#undef ETH_LINK_SPEED_100M_HD +#undef ETH_LINK_SPEED_100M +#undef ETH_LINK_SPEED_1G +#undef ETH_LINK_SPEED_2_5G +#undef ETH_LINK_SPEED_5G +#undef ETH_LINK_SPEED_10G +#undef ETH_LINK_SPEED_20G +#undef ETH_LINK_SPEED_25G +#undef ETH_LINK_SPEED_40G +#undef ETH_LINK_SPEED_50G +#undef ETH_LINK_SPEED_56G +#undef ETH_LINK_SPEED_100G +#undef ETH_LINK_SPEED_200G +#undef ETH_RSS_IP +#undef ETH_RSS_UDP +#undef ETH_RSS_TCP +#undef ETH_RSS_SCTP +#define ETH_LINK_HALF_DUPLEX RTE_ETH_LINK_HALF_DUPLEX +#define ETH_LINK_FULL_DUPLEX RTE_ETH_LINK_FULL_DUPLEX +#define ETH_LINK_DOWN RTE_ETH_LINK_DOWN +#define ETH_LINK_UP RTE_ETH_LINK_UP +#define ETH_LINK_FIXED RTE_ETH_LINK_FIXED +#define ETH_LINK_AUTONEG RTE_ETH_LINK_AUTONEG +#define ETH_SPEED_NUM_NONE RTE_ETH_SPEED_NUM_NONE +#define ETH_SPEED_NUM_10M RTE_ETH_SPEED_NUM_10M +#define ETH_SPEED_NUM_100M RTE_ETH_SPEED_NUM_100M +#define ETH_SPEED_NUM_1G RTE_ETH_SPEED_NUM_1G +#define ETH_SPEED_NUM_2_5G RTE_ETH_SPEED_NUM_2_5G +#define ETH_SPEED_NUM_5G RTE_ETH_SPEED_NUM_5G +#define ETH_SPEED_NUM_10G RTE_ETH_SPEED_NUM_10G +#define ETH_SPEED_NUM_20G RTE_ETH_SPEED_NUM_20G +#define ETH_SPEED_NUM_25G RTE_ETH_SPEED_NUM_25G +#define ETH_SPEED_NUM_40G RTE_ETH_SPEED_NUM_40G +#define ETH_SPEED_NUM_50G RTE_ETH_SPEED_NUM_50G +#define ETH_SPEED_NUM_56G RTE_ETH_SPEED_NUM_56G +#define ETH_SPEED_NUM_100G RTE_ETH_SPEED_NUM_100G +#define ETH_SPEED_NUM_200G RTE_ETH_SPEED_NUM_200G +#define ETH_SPEED_NUM_UNKNOWN RTE_ETH_SPEED_NUM_UNKNOWN +#define ETH_LINK_SPEED_AUTONEG RTE_ETH_LINK_SPEED_AUTONEG +#define ETH_LINK_SPEED_FIXED RTE_ETH_LINK_SPEED_FIXED +#define ETH_LINK_SPEED_10M_HD RTE_ETH_LINK_SPEED_10M_HD +#define ETH_LINK_SPEED_10M RTE_ETH_LINK_SPEED_10M +#define ETH_LINK_SPEED_100M_HD RTE_ETH_LINK_SPEED_100M_HD +#define ETH_LINK_SPEED_100M RTE_ETH_LINK_SPEED_100M +#define ETH_LINK_SPEED_1G RTE_ETH_LINK_SPEED_1G +#define ETH_LINK_SPEED_2_5G RTE_ETH_LINK_SPEED_2_5G +#define ETH_LINK_SPEED_5G RTE_ETH_LINK_SPEED_5G +#define ETH_LINK_SPEED_10G RTE_ETH_LINK_SPEED_10G +#define ETH_LINK_SPEED_20G RTE_ETH_LINK_SPEED_20G +#define ETH_LINK_SPEED_25G RTE_ETH_LINK_SPEED_25G +#define ETH_LINK_SPEED_40G RTE_ETH_LINK_SPEED_40G +#define ETH_LINK_SPEED_50G RTE_ETH_LINK_SPEED_50G +#define ETH_LINK_SPEED_56G RTE_ETH_LINK_SPEED_56G +#define ETH_LINK_SPEED_100G RTE_ETH_LINK_SPEED_100G +#define ETH_LINK_SPEED_200G RTE_ETH_LINK_SPEED_200G +#define ETH_RSS_IP RTE_ETH_RSS_IP +#define ETH_RSS_UDP RTE_ETH_RSS_UDP +#define ETH_RSS_TCP RTE_ETH_RSS_TCP +#define ETH_RSS_SCTP RTE_ETH_RSS_SCTP +#define ETH_RSS_IPV4 RTE_ETH_RSS_IPV4 +#define ETH_RSS_FRAG_IPV4 RTE_ETH_RSS_FRAG_IPV4 +#define ETH_RSS_NONFRAG_IPV4_OTHER RTE_ETH_RSS_NONFRAG_IPV4_OTHER +#define ETH_RSS_IPV6 RTE_ETH_RSS_IPV6 +#define ETH_RSS_FRAG_IPV6 RTE_ETH_RSS_FRAG_IPV6 +#define ETH_RSS_NONFRAG_IPV6_OTHER RTE_ETH_RSS_NONFRAG_IPV6_OTHER +#define ETH_RSS_IPV6_EX RTE_ETH_RSS_IPV6_EX +#define ETH_RSS_C_VLAN RTE_ETH_RSS_C_VLAN +#define ETH_RSS_L3_DST_ONLY RTE_ETH_RSS_L3_DST_ONLY +#define ETH_RSS_L3_SRC_ONLY RTE_ETH_RSS_L3_SRC_ONLY +#endif + +#define NUM_MAC_ADDRS_PER_PORT (16U) +#define NUM_MULTICAST_ADDRS_PER_PORT (16U) + +#define MAX_FPGA_VIRTUAL_PORTS_SUPPORTED 256 + +/* Total max ports per NT NFV NIC */ +#define MAX_NTNIC_PORTS 2 + +/* Max RSS queues */ +#define MAX_QUEUES 125 + +#define SG_NB_HW_RX_DESCRIPTORS 1024 +#define SG_NB_HW_TX_DESCRIPTORS 1024 +#define SG_HW_RX_PKT_BUFFER_SIZE (1024 << 1) +#define SG_HW_TX_PKT_BUFFER_SIZE (1024 << 1) + +#define SG_HDR_SIZE 12 + +/* VQ buffers needed to fit all data in packet + header */ +#define NUM_VQ_SEGS(_data_size_) \ + ({ \ + size_t _size = (_data_size_); \ + size_t _segment_count = ((_size + SG_HDR_SIZE) > SG_HW_TX_PKT_BUFFER_SIZE) ? \ + (((_size + SG_HDR_SIZE) + SG_HW_TX_PKT_BUFFER_SIZE - 1) / \ + SG_HW_TX_PKT_BUFFER_SIZE) : 1; \ + _segment_count; \ + }) + + +#define VIRTQ_DESCR_IDX(_tx_pkt_idx_) \ + (((_tx_pkt_idx_) + first_vq_descr_idx) % SG_NB_HW_TX_DESCRIPTORS) + +#define VIRTQ_DESCR_IDX_NEXT(_vq_descr_idx_) \ + (((_vq_descr_idx_) + 1) % SG_NB_HW_TX_DESCRIPTORS) + +#define MAX_REL_VQS 128 + +/* Functions: */ +struct pmd_internals *vp_vhid_instance_ready(int vhid); +struct pmd_internals *vp_path_instance_ready(const char *path); +int setup_virtual_pf_representor_base(struct rte_pci_device *dev); +int nthw_create_vf_interface_dpdk(struct rte_pci_device *pci_dev); +int nthw_remove_vf_interface_dpdk(struct rte_pci_device *pci_dev); +nthw_dbs_t *get_pdbs_from_pci(struct rte_pci_addr pci_addr); +enum fpga_info_profile get_fpga_profile_from_pci(struct rte_pci_addr pci_addr); +int register_release_virtqueue_info(struct nthw_virt_queue *vq, int rx, + int managed); +int de_register_release_virtqueue_info(struct nthw_virt_queue *vq); +int copy_mbuf_to_virtqueue(struct nthw_cvirtq_desc *cvq_desc, + uint16_t vq_descr_idx, + struct nthw_memory_descriptor *vq_bufs, int max_segs, + struct rte_mbuf *mbuf); + +extern int lag_active; +extern uint64_t rte_tsc_freq; +extern rte_spinlock_t hwlock; + +/* Structs: */ + +#define SG_HDR_SIZE 12 + +struct _pkt_hdr_rx { + uint32_t cap_len : 14; + uint32_t fid : 10; + uint32_t ofs1 : 8; + uint32_t ip_prot : 8; + uint32_t port : 13; + uint32_t descr : 8; + uint32_t descr_12b : 1; + uint32_t color_type : 2; + uint32_t color : 32; +}; + +struct _pkt_hdr_tx { + uint32_t cap_len : 14; + uint32_t lso_cso0 : 9; + uint32_t lso_cso1 : 9; + uint32_t lso_cso2 : 8; + /* all 1's : use implicit in-port. 0-127 queue index. 0x80 + phy-port to phy */ + uint32_t bypass_port : 13; + uint32_t descr : 8; + uint32_t descr_12b : 1; + uint32_t color_type : 2; + uint32_t color : 32; +}; + +/* Compile time verification of scatter gather header size. */ +typedef char check_sg_pkt_rx_hdr_size +[(sizeof(struct _pkt_hdr_rx) == SG_HDR_SIZE) ? 1 : -1]; +typedef char check_sg_pkt_tx_hdr_size +[(sizeof(struct _pkt_hdr_tx) == SG_HDR_SIZE) ? 1 : -1]; + +typedef void *handle_t; + +struct hwq_s { + int vf_num; + struct nthw_memory_descriptor virt_queues_ctrl; + struct nthw_memory_descriptor *pkt_buffers; +}; + +struct ntnic_rx_queue { + struct flow_queue_id_s + queue; /* queue info - user id and hw queue index */ + + struct rte_mempool *mb_pool; /* mbuf memory pool */ + uint16_t buf_size; /* size of data area in mbuf */ + unsigned long rx_pkts; /* Rx packet statistics */ + unsigned long rx_bytes; /* Rx bytes statistics */ + unsigned long err_pkts; /* Rx error packet statistics */ + int enabled; /* Enabling/disabling of this queue */ + + struct hwq_s hwq; + struct nthw_virt_queue *vq; + int nb_hw_rx_descr; + nt_meta_port_type_t type; + uint32_t port; /* Rx port for this queue */ + enum fpga_info_profile profile; /* Vswitch / Inline / Capture */ + +} __rte_cache_aligned; + +struct ntnic_tx_queue { + struct flow_queue_id_s + queue; /* queue info - user id and hw queue index */ + struct hwq_s hwq; + struct nthw_virt_queue *vq; + int nb_hw_tx_descr; + /* Used for bypass in NTDVIO0 header on Tx - pre calculated */ + int target_id; + nt_meta_port_type_t type; + /* only used for exception tx queue from OVS SW switching */ + int rss_target_id; + + uint32_t port; /* Tx port for this queue */ + unsigned long tx_pkts; /* Tx packet statistics */ + unsigned long tx_bytes; /* Tx bytes statistics */ + unsigned long err_pkts; /* Tx error packet stat */ + int enabled; /* Enabling/disabling of this queue */ + enum fpga_info_profile profile; /* Vswitch / Inline / Capture */ +} __rte_cache_aligned; + +#define MAX_ARRAY_ENTRIES MAX_QUEUES +struct array_s { + uint32_t value[MAX_ARRAY_ENTRIES]; + int count; +}; + +/* Configuerations related to LAG management */ +typedef struct { + uint8_t mode; + + int8_t primary_port; + int8_t backup_port; + + uint32_t ntpl_rx_id; + + pthread_t lag_tid; + uint8_t lag_thread_active; + + struct pmd_internals *internals; +} lag_config_t; + +#define BONDING_MODE_ACTIVE_BACKUP (1) +#define BONDING_MODE_8023AD (4) +struct nt_mtr_profile { + LIST_ENTRY(nt_mtr_profile) next; + uint32_t profile_id; + struct rte_mtr_meter_profile profile; +}; + +struct nt_mtr { + LIST_ENTRY(nt_mtr) next; + uint32_t mtr_id; + int shared; + struct nt_mtr_profile *profile; +}; + +enum virt_port_comm { + VIRT_PORT_NEGOTIATED_NONE, + VIRT_PORT_NEGOTIATED_SPLIT, + VIRT_PORT_NEGOTIATED_PACKED, + VIRT_PORT_USE_RELAY +}; + +#define MAX_PATH_LEN 128 + +struct pmd_internals { + const struct rte_pci_device *pci_dev; + + struct flow_eth_dev *flw_dev; + + char name[20]; + char vhost_path[MAX_PATH_LEN]; + + int n_intf_no; + int if_index; + + int lpbk_mode; + + uint8_t nb_ports_on_adapter; + uint8_t ts_multiplier; + uint16_t min_tx_pkt_size; + uint16_t max_tx_pkt_size; + + unsigned int nb_rx_queues; /* Number of Rx queues configured */ + unsigned int nb_tx_queues; /* Number of Tx queues configured */ + uint32_t port; + uint8_t port_id; + + nt_meta_port_type_t type; + struct flow_queue_id_s vpq[MAX_QUEUES]; + unsigned int vpq_nb_vq; + volatile atomic_int vhid; /* if a virtual port type - the vhid */ + enum virt_port_comm vport_comm; /* link and how split,packed,relay */ + uint32_t vlan; + + lag_config_t *lag_config; + + struct ntnic_rx_queue rxq_scg[MAX_QUEUES]; /* Array of Rx queues */ + struct ntnic_tx_queue txq_scg[MAX_QUEUES]; /* Array of Tx queues */ + + struct drv_s *p_drv; + /* Ethernet (MAC) addresses. Element number zero denotes default address. */ + struct rte_ether_addr eth_addrs[NUM_MAC_ADDRS_PER_PORT]; + /* Multicast ethernet (MAC) addresses. */ + struct rte_ether_addr mc_addrs[NUM_MULTICAST_ADDRS_PER_PORT]; + + LIST_HEAD(_profiles, nt_mtr_profile) mtr_profiles; + LIST_HEAD(_mtrs, nt_mtr) mtrs; + + uint64_t last_stat_rtc; + uint64_t rx_missed; + + struct pmd_internals *next; +}; + +void cleanup_flows(struct pmd_internals *internals); +int poll_statistics(struct pmd_internals *internals); +int debug_adapter_show_info(uint32_t pciident, FILE *pfh); + +#endif /* __NTNIC_ETHDEV_H__ */ diff --git a/drivers/net/ntnic/ntnic_filter/create_elements.h b/drivers/net/ntnic/ntnic_filter/create_elements.h new file mode 100644 index 0000000000..e90643ec6b --- /dev/null +++ b/drivers/net/ntnic/ntnic_filter/create_elements.h @@ -0,0 +1,1190 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __CREATE_ELEMENTS_H__ +#define __CREATE_ELEMENTS_H__ + +#include "stream_binary_flow_api.h" + +#define MAX_ELEMENTS 64 +#define MAX_ACTIONS 32 + +#define MAX_COLOR_FLOW_STATS 0x400 + +struct cnv_match_s { + struct flow_elem flow_elem[MAX_ELEMENTS]; +}; + +struct tun_def_s { + struct flow_elem *tun_definition; + struct cnv_match_s match; +}; + +struct cnv_attr_s { + struct cnv_match_s match; + struct flow_attr attr; +}; + +struct cnv_action_s { + struct flow_action flow_actions[MAX_ACTIONS]; + struct tun_def_s tun_def; + struct flow_action_rss flow_rss; + struct rte_flow_action_mark mark; + struct flow_action_raw_encap encap; + struct flow_action_raw_decap decap; + struct flow_action_queue queue; +}; + +/* + * Only needed because it eases the use of statistics through NTAPI + * for faster integration into NTAPI version of driver + * Therefore, this is only a good idea when running on a temporary NTAPI + * The query() functionality must go to flow engine, when moved to Open Source driver + */ + +struct rte_flow { + void *flw_hdl; + int used; + uint32_t flow_stat_id; + + uint64_t stat_pkts; + uint64_t stat_bytes; + uint8_t stat_tcp_flags; +}; + +enum nt_rte_flow_item_type { + NT_RTE_FLOW_ITEM_TYPE_END = INT_MIN, + NT_RTE_FLOW_ITEM_TYPE_TAG, + NT_RTE_FLOW_ITEM_TYPE_TUNNEL, +}; + +enum nt_rte_flow_action_type { + NT_RTE_FLOW_ACTION_TYPE_END = INT_MIN, + NT_RTE_FLOW_ACTION_TYPE_TAG, + NT_RTE_FLOW_ACTION_TYPE_TUNNEL_SET, + NT_RTE_FLOW_ACTION_TYPE_JUMP, +}; + +static int convert_tables_initialized; + +#define MAX_RTE_ENUM_INDEX 127 + +static int elem_list[MAX_RTE_ENUM_INDEX + 1]; +static int action_list[MAX_RTE_ENUM_INDEX + 1]; + +#ifdef RTE_FLOW_DEBUG +static const char *elem_list_str[MAX_RTE_ENUM_INDEX + 1]; +static const char *action_list_str[MAX_RTE_ENUM_INDEX + 1]; +#endif + +#define CNV_TO_ELEM(item) \ + ({ \ + int _temp_item = (item); \ + ((_temp_item >= 0 && _temp_item <= MAX_RTE_ENUM_INDEX) ? \ + elem_list[_temp_item] : -1); \ + }) + + +#define CNV_TO_ACTION(action) \ + ({ \ + int _temp_action = (action); \ + (_temp_action >= 0 && _temp_action <= MAX_RTE_ENUM_INDEX) ? \ + action_list[_temp_action] : -1; \ + }) + + +static uint32_t flow_stat_id_map[MAX_COLOR_FLOW_STATS]; +static rte_spinlock_t flow_lock = RTE_SPINLOCK_INITIALIZER; + +static int convert_error(struct rte_flow_error *error, + struct flow_error *flow_error) +{ + if (error) { + error->cause = NULL; + error->message = flow_error->message; + + if (flow_error->type == FLOW_ERROR_NONE || + flow_error->type == FLOW_ERROR_SUCCESS) + error->type = RTE_FLOW_ERROR_TYPE_NONE; + + else + error->type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + } + return 0; +} + +/* + * Map Flow MARK to flow stat id + */ +static uint32_t create_flow_stat_id_locked(uint32_t mark) +{ + uint32_t flow_stat_id = mark & (MAX_COLOR_FLOW_STATS - 1); + + while (flow_stat_id_map[flow_stat_id]) + flow_stat_id = (flow_stat_id + 1) & (MAX_COLOR_FLOW_STATS - 1); + + flow_stat_id_map[flow_stat_id] = mark + 1; + return flow_stat_id; +} + +static uint32_t create_flow_stat_id(uint32_t mark) +{ + rte_spinlock_lock(&flow_lock); + uint32_t ret = create_flow_stat_id_locked(mark); + + rte_spinlock_unlock(&flow_lock); + return ret; +} + +static void delete_flow_stat_id_locked(uint32_t flow_stat_id) +{ + if (flow_stat_id < MAX_COLOR_FLOW_STATS) + flow_stat_id_map[flow_stat_id] = 0; +} + +static void initialize_global_cnv_tables(void) +{ + if (convert_tables_initialized) + return; + + memset(elem_list, -1, sizeof(elem_list)); + elem_list[RTE_FLOW_ITEM_TYPE_END] = FLOW_ELEM_TYPE_END; + elem_list[RTE_FLOW_ITEM_TYPE_ANY] = FLOW_ELEM_TYPE_ANY; + elem_list[RTE_FLOW_ITEM_TYPE_ETH] = FLOW_ELEM_TYPE_ETH; + elem_list[RTE_FLOW_ITEM_TYPE_VLAN] = FLOW_ELEM_TYPE_VLAN; + elem_list[RTE_FLOW_ITEM_TYPE_IPV4] = FLOW_ELEM_TYPE_IPV4; + elem_list[RTE_FLOW_ITEM_TYPE_IPV6] = FLOW_ELEM_TYPE_IPV6; + elem_list[RTE_FLOW_ITEM_TYPE_UDP] = FLOW_ELEM_TYPE_UDP; + elem_list[RTE_FLOW_ITEM_TYPE_SCTP] = FLOW_ELEM_TYPE_SCTP; + elem_list[RTE_FLOW_ITEM_TYPE_TCP] = FLOW_ELEM_TYPE_TCP; + elem_list[RTE_FLOW_ITEM_TYPE_ICMP] = FLOW_ELEM_TYPE_ICMP; + elem_list[RTE_FLOW_ITEM_TYPE_VXLAN] = FLOW_ELEM_TYPE_VXLAN; + elem_list[RTE_FLOW_ITEM_TYPE_GTP] = FLOW_ELEM_TYPE_GTP; + elem_list[RTE_FLOW_ITEM_TYPE_PORT_ID] = FLOW_ELEM_TYPE_PORT_ID; + elem_list[RTE_FLOW_ITEM_TYPE_TAG] = FLOW_ELEM_TYPE_TAG; + elem_list[RTE_FLOW_ITEM_TYPE_VOID] = FLOW_ELEM_TYPE_VOID; + +#ifdef RTE_FLOW_DEBUG + elem_list_str[RTE_FLOW_ITEM_TYPE_END] = "FLOW_ELEM_TYPE_END"; + elem_list_str[RTE_FLOW_ITEM_TYPE_ANY] = "FLOW_ELEM_TYPE_ANY"; + elem_list_str[RTE_FLOW_ITEM_TYPE_ETH] = "FLOW_ELEM_TYPE_ETH"; + elem_list_str[RTE_FLOW_ITEM_TYPE_VLAN] = "FLOW_ELEM_TYPE_VLAN"; + elem_list_str[RTE_FLOW_ITEM_TYPE_IPV4] = "FLOW_ELEM_TYPE_IPV4"; + elem_list_str[RTE_FLOW_ITEM_TYPE_IPV6] = "FLOW_ELEM_TYPE_IPV6"; + elem_list_str[RTE_FLOW_ITEM_TYPE_UDP] = "FLOW_ELEM_TYPE_UDP"; + elem_list_str[RTE_FLOW_ITEM_TYPE_SCTP] = "FLOW_ELEM_TYPE_SCTP"; + elem_list_str[RTE_FLOW_ITEM_TYPE_TCP] = "FLOW_ELEM_TYPE_TCP"; + elem_list_str[RTE_FLOW_ITEM_TYPE_ICMP] = "FLOW_ELEM_TYPE_ICMP"; + elem_list_str[RTE_FLOW_ITEM_TYPE_VXLAN] = "FLOW_ELEM_TYPE_VXLAN"; + elem_list_str[RTE_FLOW_ITEM_TYPE_GTP] = "FLOW_ELEM_TYPE_GTP"; + elem_list_str[RTE_FLOW_ITEM_TYPE_PORT_ID] = "FLOW_ELEM_TYPE_PORT_ID"; + elem_list_str[RTE_FLOW_ITEM_TYPE_TAG] = "FLOW_ELEM_TYPE_TAG"; + elem_list_str[RTE_FLOW_ITEM_TYPE_VOID] = "FLOW_ELEM_TYPE_VOID"; +#endif + + memset(action_list, -1, sizeof(action_list)); + action_list[RTE_FLOW_ACTION_TYPE_END] = FLOW_ACTION_TYPE_END; + action_list[RTE_FLOW_ACTION_TYPE_MARK] = FLOW_ACTION_TYPE_MARK; + action_list[RTE_FLOW_ACTION_TYPE_SET_TAG] = FLOW_ACTION_TYPE_SET_TAG; + action_list[RTE_FLOW_ACTION_TYPE_DROP] = FLOW_ACTION_TYPE_DROP; + action_list[RTE_FLOW_ACTION_TYPE_COUNT] = FLOW_ACTION_TYPE_COUNT; + action_list[RTE_FLOW_ACTION_TYPE_RSS] = FLOW_ACTION_TYPE_RSS; + action_list[RTE_FLOW_ACTION_TYPE_PORT_ID] = FLOW_ACTION_TYPE_PORT_ID; + action_list[RTE_FLOW_ACTION_TYPE_QUEUE] = FLOW_ACTION_TYPE_QUEUE; + action_list[RTE_FLOW_ACTION_TYPE_JUMP] = FLOW_ACTION_TYPE_JUMP; + action_list[RTE_FLOW_ACTION_TYPE_METER] = FLOW_ACTION_TYPE_METER; + action_list[RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] = + FLOW_ACTION_TYPE_VXLAN_ENCAP; + action_list[RTE_FLOW_ACTION_TYPE_VXLAN_DECAP] = + FLOW_ACTION_TYPE_VXLAN_DECAP; + action_list[RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] = + FLOW_ACTION_TYPE_PUSH_VLAN; + action_list[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID] = + FLOW_ACTION_TYPE_SET_VLAN_VID; + action_list[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = + FLOW_ACTION_TYPE_SET_VLAN_PCP; + action_list[RTE_FLOW_ACTION_TYPE_OF_POP_VLAN] = + FLOW_ACTION_TYPE_POP_VLAN; + action_list[RTE_FLOW_ACTION_TYPE_RAW_ENCAP] = + FLOW_ACTION_TYPE_RAW_ENCAP; + action_list[RTE_FLOW_ACTION_TYPE_RAW_DECAP] = + FLOW_ACTION_TYPE_RAW_DECAP; + action_list[RTE_FLOW_ACTION_TYPE_MODIFY_FIELD] = + FLOW_ACTION_TYPE_MODIFY_FIELD; + +#ifdef RTE_FLOW_DEBUG + action_list_str[RTE_FLOW_ACTION_TYPE_END] = "FLOW_ACTION_TYPE_END"; + action_list_str[RTE_FLOW_ACTION_TYPE_MARK] = "FLOW_ACTION_TYPE_MARK"; + action_list_str[RTE_FLOW_ACTION_TYPE_SET_TAG] = + "FLOW_ACTION_TYPE_SET_TAG"; + action_list_str[RTE_FLOW_ACTION_TYPE_DROP] = "FLOW_ACTION_TYPE_DROP"; + action_list_str[RTE_FLOW_ACTION_TYPE_COUNT] = "FLOW_ACTION_TYPE_COUNT"; + action_list_str[RTE_FLOW_ACTION_TYPE_RSS] = "FLOW_ACTION_TYPE_RSS"; + action_list_str[RTE_FLOW_ACTION_TYPE_PORT_ID] = + "FLOW_ACTION_TYPE_PORT_ID"; + action_list_str[RTE_FLOW_ACTION_TYPE_QUEUE] = "FLOW_ACTION_TYPE_QUEUE"; + action_list_str[RTE_FLOW_ACTION_TYPE_JUMP] = "FLOW_ACTION_TYPE_JUMP"; + action_list_str[RTE_FLOW_ACTION_TYPE_METER] = "FLOW_ACTION_TYPE_METER"; + action_list_str[RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] = + "FLOW_ACTION_TYPE_VXLAN_ENCAP"; + action_list_str[RTE_FLOW_ACTION_TYPE_VXLAN_DECAP] = + "FLOW_ACTION_TYPE_VXLAN_DECAP"; + action_list_str[RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] = + "FLOW_ACTION_TYPE_PUSH_VLAN"; + action_list_str[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID] = + "FLOW_ACTION_TYPE_SET_VLAN_VID"; + action_list_str[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = + "FLOW_ACTION_TYPE_SET_VLAN_PCP"; + action_list_str[RTE_FLOW_ACTION_TYPE_OF_POP_VLAN] = + "FLOW_ACTION_TYPE_POP_VLAN"; + action_list_str[RTE_FLOW_ACTION_TYPE_RAW_ENCAP] = + "FLOW_ACTION_TYPE_RAW_ENCAP"; + action_list_str[RTE_FLOW_ACTION_TYPE_RAW_DECAP] = + "FLOW_ACTION_TYPE_RAW_DECAP"; + action_list_str[RTE_FLOW_ACTION_TYPE_MODIFY_FIELD] = + "FLOW_ACTION_TYPE_MODIFY_FIELD"; +#endif + + convert_tables_initialized = 1; +} + +static int interpret_raw_data(uint8_t *data, uint8_t *preserve, int size, + struct flow_elem *out) +{ + int hdri = 0; + int pkti = 0; + + /* Ethernet */ + if (size - pkti == 0) + goto interpret_end; + if (size - pkti < (int)sizeof(struct rte_ether_hdr)) + return -1; + + out[hdri].type = FLOW_ELEM_TYPE_ETH; + out[hdri].spec = &data[pkti]; + out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL; + + rte_be16_t ether_type = + ((struct rte_ether_hdr *)&data[pkti])->ether_type; + + hdri += 1; + pkti += sizeof(struct rte_ether_hdr); + + if (size - pkti == 0) + goto interpret_end; + + /* VLAN */ + while (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) || + ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ) || + ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ1)) { + if (size - pkti == 0) + goto interpret_end; + if (size - pkti < (int)sizeof(struct rte_vlan_hdr)) + return -1; + + out[hdri].type = FLOW_ELEM_TYPE_VLAN; + out[hdri].spec = &data[pkti]; + out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL; + + ether_type = ((struct rte_vlan_hdr *)&data[pkti])->eth_proto; + + hdri += 1; + pkti += sizeof(struct rte_vlan_hdr); + } + + if (size - pkti == 0) + goto interpret_end; + + /* Layer 3 */ + uint8_t next_header = 0; + + if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) && + (data[pkti] & 0xF0) == 0x40) { + if (size - pkti < (int)sizeof(struct rte_ipv4_hdr)) + return -1; + + out[hdri].type = FLOW_ELEM_TYPE_IPV4; + out[hdri].spec = &data[pkti]; + out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL; + + next_header = data[pkti + 9]; + + hdri += 1; + pkti += sizeof(struct rte_ipv4_hdr); + } else if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6) && + (data[pkti] & 0xF0) == 0x60) { + if (size - pkti < (int)sizeof(struct rte_ipv6_hdr)) + return -1; + + out[hdri].type = FLOW_ELEM_TYPE_IPV6; + out[hdri].spec = &data[pkti]; + out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL; + + next_header = data[pkti + 6]; + + hdri += 1; + pkti += sizeof(struct rte_ipv6_hdr); + + } else { + return -1; + } + + if (size - pkti == 0) + goto interpret_end; + + /* Layer 4 */ + int gtpu_encap = 0; + + if (next_header == 1) { /* ICMP */ + if (size - pkti < (int)sizeof(struct rte_icmp_hdr)) + return -1; + + out[hdri].type = FLOW_ELEM_TYPE_ICMP; + out[hdri].spec = &data[pkti]; + out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL; + + hdri += 1; + pkti += sizeof(struct rte_icmp_hdr); + } else if (next_header == 6) { /* TCP */ + if (size - pkti < (int)sizeof(struct rte_tcp_hdr)) + return -1; + + out[hdri].type = FLOW_ELEM_TYPE_TCP; + out[hdri].spec = &data[pkti]; + out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL; + + hdri += 1; + pkti += sizeof(struct rte_tcp_hdr); + } else if (next_header == 17) { /* UDP */ + if (size - pkti < (int)sizeof(struct rte_udp_hdr)) + return -1; + + out[hdri].type = FLOW_ELEM_TYPE_UDP; + out[hdri].spec = &data[pkti]; + out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL; + + gtpu_encap = ((struct rte_udp_hdr *)&data[pkti])->dst_port == + rte_cpu_to_be_16(RTE_GTPU_UDP_PORT); + + hdri += 1; + pkti += sizeof(struct rte_udp_hdr); + } else if (next_header == 132) { /* SCTP */ + if (size - pkti < (int)sizeof(struct rte_sctp_hdr)) + return -1; + + out[hdri].type = FLOW_ELEM_TYPE_SCTP; + out[hdri].spec = &data[pkti]; + out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL; + + hdri += 1; + pkti += sizeof(struct rte_sctp_hdr); + } else { + return -1; + } + + if (size - pkti == 0) + goto interpret_end; + + /* GTPv1-U */ + if (gtpu_encap) { + if (size - pkti < (int)sizeof(struct rte_gtp_hdr)) + return -1; + + out[hdri].type = FLOW_ELEM_TYPE_GTP; + out[hdri].spec = &data[pkti]; + out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL; + + int extension_present_bit = + ((struct rte_gtp_hdr *)&data[pkti])->e; + + hdri += 1; + pkti += sizeof(struct rte_gtp_hdr); + + if (extension_present_bit) { + if (size - pkti < + (int)sizeof(struct rte_gtp_hdr_ext_word)) + return -1; + + out[hdri].type = FLOW_ELEM_TYPE_GTP; + out[hdri].spec = &data[pkti]; + out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : + NULL; + + uint8_t next_ext = + ((struct rte_gtp_hdr_ext_word *)&data[pkti]) + ->next_ext; + + hdri += 1; + pkti += sizeof(struct rte_gtp_hdr_ext_word); + + while (next_ext) { + size_t ext_len = data[pkti] * 4; + + if (size - pkti < (int)ext_len) + return -1; + + out[hdri].type = FLOW_ELEM_TYPE_GTP; + out[hdri].spec = &data[pkti]; + out[hdri].mask = (preserve != NULL) ? + &preserve[pkti] : + NULL; + + next_ext = data[pkti + ext_len - 1]; + + hdri += 1; + pkti += ext_len; + } + } + } + + if (size - pkti != 0) + return -1; + +interpret_end: + out[hdri].type = FLOW_ELEM_TYPE_END; + out[hdri].spec = NULL; + out[hdri].mask = NULL; + + return hdri + 1; +} + +static int create_attr(struct cnv_attr_s *attribute, + const struct rte_flow_attr *attr) +{ + memset(&attribute->attr, 0x0, sizeof(struct flow_attr)); + if (attr) { + attribute->attr.group = attr->group; + attribute->attr.priority = attr->priority; + } + return 0; +} + +static int create_match_elements(struct cnv_match_s *match, + const struct rte_flow_item items[], + int max_elem) +{ + int eidx = 0; + int iter_idx = 0; + int type = -1; + + if (!items) { + NT_LOG(ERR, FILTER, "ERROR no items to iterate!\n"); + return -1; + } + + if (!convert_tables_initialized) + initialize_global_cnv_tables(); + + do { + type = CNV_TO_ELEM(items[iter_idx].type); + if (type < 0) { + if ((int)items[iter_idx].type == + NT_RTE_FLOW_ITEM_TYPE_TUNNEL) { + type = FLOW_ELEM_TYPE_TUNNEL; + } else { + NT_LOG(ERR, FILTER, + "ERROR unknown item type received!\n"); + return -1; + } + } + + if (type >= 0) { + if (items[iter_idx].last) { + /* Ranges are not supported yet */ + NT_LOG(ERR, FILTER, + "ERROR ITEM-RANGE SETUP - NOT SUPPORTED!\n"); + return -1; + } + + if (eidx == max_elem) { + NT_LOG(ERR, FILTER, + "ERROR TOO MANY ELEMENTS ENCOUNTERED!\n"); + return -1; + } + +#ifdef RTE_FLOW_DEBUG + NT_LOG(INF, FILTER, + "RTE ITEM -> FILTER FLOW ELEM - %i -> %i - %s\n", + items[iter_idx].type, type, + ((int)items[iter_idx].type >= 0) ? + elem_list_str[items[iter_idx].type] : + "FLOW_ELEM_TYPE_TUNNEL"); + + switch (type) { + case FLOW_ELEM_TYPE_ETH: + if (items[iter_idx].spec) { + const struct flow_elem_eth *eth = + items[iter_idx].spec; + NT_LOG(DBG, FILTER, + "FLOW_ELEM_TYPE_ETH SPEC: dst=%02X:%02X:%02X:%02X:%02X:%02X\n", + eth->d_addr.addr_b[0] & 0xFF, + eth->d_addr.addr_b[1] & 0xFF, + eth->d_addr.addr_b[2] & 0xFF, + eth->d_addr.addr_b[3] & 0xFF, + eth->d_addr.addr_b[4] & 0xFF, + eth->d_addr.addr_b[5] & 0xFF); + NT_LOG(DBG, FILTER, + " src=%02X:%02X:%02X:%02X:%02X:%02X\n", + eth->s_addr.addr_b[0] & 0xFF, + eth->s_addr.addr_b[1] & 0xFF, + eth->s_addr.addr_b[2] & 0xFF, + eth->s_addr.addr_b[3] & 0xFF, + eth->s_addr.addr_b[4] & 0xFF, + eth->s_addr.addr_b[5] & 0xFF); + NT_LOG(DBG, FILTER, + " type=%04x\n", + htons(eth->ether_type)); + } + if (items[iter_idx].mask) { + const struct flow_elem_eth *eth = + items[iter_idx].mask; + NT_LOG(DBG, FILTER, + "FLOW_ELEM_TYPE_ETH MASK: dst=%02X:%02X:%02X:%02X:%02X:%02X\n", + eth->d_addr.addr_b[0] & 0xFF, + eth->d_addr.addr_b[1] & 0xFF, + eth->d_addr.addr_b[2] & 0xFF, + eth->d_addr.addr_b[3] & 0xFF, + eth->d_addr.addr_b[4] & 0xFF, + eth->d_addr.addr_b[5] & 0xFF); + NT_LOG(DBG, FILTER, + " src=%02X:%02X:%02X:%02X:%02X:%02X\n", + eth->s_addr.addr_b[0] & 0xFF, + eth->s_addr.addr_b[1] & 0xFF, + eth->s_addr.addr_b[2] & 0xFF, + eth->s_addr.addr_b[3] & 0xFF, + eth->s_addr.addr_b[4] & 0xFF, + eth->s_addr.addr_b[5] & 0xFF); + NT_LOG(DBG, FILTER, + " type=%04x\n", + htons(eth->ether_type)); + } + break; + case FLOW_ELEM_TYPE_VLAN: + if (items[iter_idx].spec) { + const struct flow_elem_vlan *vlan = + (const struct flow_elem_vlan *) + items[iter_idx] + .spec; + NT_LOG(DBG, FILTER, + "FLOW_ELEM_TYPE_VLAN SPEC: tci=%04x\n", + htons(vlan->tci)); + NT_LOG(DBG, FILTER, + " inner type=%04x\n", + htons(vlan->inner_type)); + } + if (items[iter_idx].mask) { + const struct flow_elem_vlan *vlan = + (const struct flow_elem_vlan *) + items[iter_idx] + .mask; + NT_LOG(DBG, FILTER, + "FLOW_ELEM_TYPE_VLAN MASK: tci=%04x\n", + htons(vlan->tci)); + NT_LOG(DBG, FILTER, + " inner type=%04x\n", + htons(vlan->inner_type)); + } + break; + case FLOW_ELEM_TYPE_IPV4: + if (items[iter_idx].spec) { + const struct flow_elem_ipv4 *ip = + items[iter_idx].spec; + NT_LOG(DBG, FILTER, + "FLOW_ELEM_TYPE_IPV4 SPEC: dst=%d.%d.%d.%d\n", + ((const char *)&ip->hdr.dst_ip)[0] & 0xFF, + ((const char *)&ip->hdr.dst_ip)[1] & 0xFF, + ((const char *)&ip->hdr.dst_ip)[2] & 0xFF, + ((const char *)&ip->hdr.dst_ip)[3] & 0xFF); + NT_LOG(DBG, FILTER, + " src=%d.%d.%d.%d\n", + ((const char *)&ip->hdr.src_ip)[0] & 0xFF, + ((const char *)&ip->hdr.src_ip)[1] & 0xFF, + ((const char *)&ip->hdr.src_ip)[2] & 0xFF, + ((const char *)&ip->hdr.src_ip)[3] & 0xFF); + NT_LOG(DBG, FILTER, + " fragment_offset=%u\n", + ip->hdr.frag_offset); + NT_LOG(DBG, FILTER, + " next_proto_id=%u\n", + ip->hdr.next_proto_id); + NT_LOG(DBG, FILTER, + " packet_id=%u\n", + ip->hdr.id); + NT_LOG(DBG, FILTER, + " time_to_live=%u\n", + ip->hdr.ttl); + NT_LOG(DBG, FILTER, + " type_of_service=%u\n", + ip->hdr.tos); + NT_LOG(DBG, FILTER, + " version_ihl=%u\n", + ip->hdr.version_ihl); + NT_LOG(DBG, FILTER, + " total_length=%u\n", + ip->hdr.length); + } + if (items[iter_idx].mask) { + const struct flow_elem_ipv4 *ip = + items[iter_idx].mask; + NT_LOG(DBG, FILTER, + "FLOW_ELEM_TYPE_IPV4 MASK: dst=%d.%d.%d.%d\n", + ((const char *)&ip->hdr.dst_ip)[0] & 0xFF, + ((const char *)&ip->hdr.dst_ip)[1] & 0xFF, + ((const char *)&ip->hdr.dst_ip)[2] & 0xFF, + ((const char *)&ip->hdr.dst_ip)[3] & 0xFF); + NT_LOG(DBG, FILTER, + " src=%d.%d.%d.%d\n", + ((const char *)&ip->hdr.src_ip)[0] & 0xFF, + ((const char *)&ip->hdr.src_ip)[1] & 0xFF, + ((const char *)&ip->hdr.src_ip)[2] & 0xFF, + ((const char *)&ip->hdr.src_ip)[3] & 0xFF); + NT_LOG(DBG, FILTER, + " fragment_offset=%x\n", + ip->hdr.frag_offset); + NT_LOG(DBG, FILTER, + " next_proto_id=%x\n", + ip->hdr.next_proto_id); + NT_LOG(DBG, FILTER, + " packet_id=%x\n", + ip->hdr.id); + NT_LOG(DBG, FILTER, + " time_to_live=%x\n", + ip->hdr.ttl); + NT_LOG(DBG, FILTER, + " type_of_service=%x\n", + ip->hdr.tos); + NT_LOG(DBG, FILTER, + " version_ihl=%x\n", + ip->hdr.version_ihl); + NT_LOG(DBG, FILTER, + " total_length=%x\n", + ip->hdr.length); + } + break; + case FLOW_ELEM_TYPE_UDP: + if (items[iter_idx].spec) { + const struct flow_elem_udp *udp = + (const struct flow_elem_udp *) + items[iter_idx] + .spec; + NT_LOG(DBG, FILTER, + "FLOW_ELEM_TYPE_UDP SPEC: src port=%04x\n", + htons(udp->hdr.src_port)); + NT_LOG(DBG, FILTER, + " dst port=%04x\n", + htons(udp->hdr.dst_port)); + } + if (items[iter_idx].mask) { + const struct flow_elem_udp *udp = + (const struct flow_elem_udp *) + items[iter_idx] + .mask; + NT_LOG(DBG, FILTER, + "FLOW_ELEM_TYPE_UDP MASK: src port=%04x\n", + htons(udp->hdr.src_port)); + NT_LOG(DBG, FILTER, + " dst port=%04x\n", + htons(udp->hdr.dst_port)); + } + break; + case FLOW_ELEM_TYPE_TAG: + if (items[iter_idx].spec) { + const struct flow_elem_tag *tag = + (const struct flow_elem_tag *) + items[iter_idx] + .spec; + NT_LOG(DBG, FILTER, + "FLOW_ELEM_TYPE_TAG SPEC: data=%u\n", + tag->data); + NT_LOG(DBG, FILTER, + " index=%u\n", + tag->index); + } + if (items[iter_idx].mask) { + const struct flow_elem_tag *tag = + (const struct flow_elem_tag *) + items[iter_idx] + .mask; + NT_LOG(DBG, FILTER, + "FLOW_ELEM_TYPE_TAG MASK: data=%u\n", + tag->data); + NT_LOG(DBG, FILTER, + " index=%u\n", + tag->index); + } + break; + case FLOW_ELEM_TYPE_VXLAN: { + const struct flow_elem_vxlan *vxlan = + (const struct flow_elem_vxlan *) + items[iter_idx] + .spec; + const struct flow_elem_vxlan *mask = + (const struct flow_elem_vxlan *) + items[iter_idx] + .mask; + + uint32_t vni = + (uint32_t)(((uint32_t)vxlan->vni[0] + << 16) | + ((uint32_t)vxlan->vni[1] + << 8) | + ((uint32_t)vxlan->vni[2])); + uint32_t vni_mask = + (uint32_t)(((uint32_t)mask->vni[0] + << 16) | + ((uint32_t)mask->vni[1] + << 8) | + ((uint32_t)mask->vni[2])); + + NT_LOG(INF, FILTER, "VNI: %08x / %08x\n", vni, + vni_mask); + } + break; + } +#endif + + match->flow_elem[eidx].type = type; + match->flow_elem[eidx].spec = items[iter_idx].spec; + match->flow_elem[eidx].mask = items[iter_idx].mask; + + eidx++; + iter_idx++; + } + + } while (type >= 0 && type != FLOW_ELEM_TYPE_END); + + return (type >= 0) ? 0 : -1; +} + +static int +create_action_elements_vswitch(struct cnv_action_s *action, + const struct rte_flow_action actions[], + int max_elem, uint32_t *flow_stat_id) +{ + int aidx = 0; + int iter_idx = 0; + int type = -1; + + if (!actions) + return -1; + + if (!convert_tables_initialized) + initialize_global_cnv_tables(); + + *flow_stat_id = MAX_COLOR_FLOW_STATS; + do { + type = CNV_TO_ACTION(actions[iter_idx].type); + if (type < 0) { + if ((int)actions[iter_idx].type == + NT_RTE_FLOW_ACTION_TYPE_TUNNEL_SET) { + type = FLOW_ACTION_TYPE_TUNNEL_SET; + } else { + NT_LOG(ERR, FILTER, + "ERROR unknown action type received!\n"); + return -1; + } + } + +#ifdef RTE_FLOW_DEBUG + NT_LOG(INF, FILTER, + "RTE ACTION -> FILTER FLOW ACTION - %i -> %i - %s\n", + actions[iter_idx].type, type, + ((int)actions[iter_idx].type >= 0) ? + action_list_str[actions[iter_idx].type] : + "FLOW_ACTION_TYPE_TUNNEL_SET"); +#endif + + if (type >= 0) { + action->flow_actions[aidx].type = type; + + /* + * Non-compatible actions handled here + */ + switch (type) { + case -1: +#ifdef RTE_FLOW_DEBUG + NT_LOG(INF, FILTER, + "RTE ACTION UNSUPPORTED %i\n", + actions[iter_idx].type); +#endif + return -1; + + case FLOW_ACTION_TYPE_RSS: { + const struct rte_flow_action_rss *rss = + (const struct rte_flow_action_rss *) + actions[iter_idx] + .conf; + action->flow_rss.func = + FLOW_HASH_FUNCTION_DEFAULT; + + if (rss->func != + RTE_ETH_HASH_FUNCTION_DEFAULT) + return -1; + action->flow_rss.level = rss->level; + action->flow_rss.types = rss->types; + action->flow_rss.key_len = rss->key_len; + action->flow_rss.queue_num = rss->queue_num; + action->flow_rss.key = rss->key; + action->flow_rss.queue = rss->queue; +#ifdef RTE_FLOW_DEBUG + NT_LOG(DBG, FILTER, + "FLOW_ACTION_TYPE_RSS: rss->level = %u\n", + rss->level); + NT_LOG(DBG, FILTER, + " rss->types = 0x%" PRIX64 "\n", + (unsigned long long)rss->types); + NT_LOG(DBG, FILTER, + " rss->key_len = %u\n", + rss->key_len); + NT_LOG(DBG, FILTER, + " rss->queue_num = %u\n", + rss->queue_num); + NT_LOG(DBG, FILTER, + " rss->key = %p\n", + rss->key); + unsigned int i; + + for (i = 0; i < rss->queue_num; i++) { + NT_LOG(DBG, FILTER, + " rss->queue[%u] = %u\n", + i, rss->queue[i]); + } +#endif + action->flow_actions[aidx].conf = + &action->flow_rss; + break; + } + + case FLOW_ACTION_TYPE_VXLAN_ENCAP: { + const struct rte_flow_action_vxlan_encap *tun = + (const struct rte_flow_action_vxlan_encap + *)actions[iter_idx] + .conf; + if (!tun || create_match_elements(&action->tun_def.match, + tun->definition, + MAX_ELEMENTS) != 0) + return -1; + action->tun_def.tun_definition = + action->tun_def.match.flow_elem; + action->flow_actions[aidx].conf = + &action->tun_def; + } + break; + + case FLOW_ACTION_TYPE_MARK: { + const struct rte_flow_action_mark *mark_id = + (const struct rte_flow_action_mark *) + actions[iter_idx] + .conf; + if (mark_id) { +#ifdef RTE_FLOW_DEBUG + NT_LOG(DBG, FILTER, "Mark ID=%u\n", + mark_id->id); +#endif + *flow_stat_id = create_flow_stat_id(mark_id->id); + action->mark.id = *flow_stat_id; + action->flow_actions[aidx].conf = + &action->mark; + + } else { + action->flow_actions[aidx].conf = + actions[iter_idx].conf; + } + } + break; + + default: + /* Compatible */ + + /* + * OVS Full offload does not add mark in RTE Flow + * We need one in FPGA to control flow(color) statistics + */ + if (type == FLOW_ACTION_TYPE_END && + *flow_stat_id == MAX_COLOR_FLOW_STATS) { + /* We need to insert a mark for our FPGA */ + *flow_stat_id = create_flow_stat_id(0); + action->mark.id = *flow_stat_id; + + action->flow_actions[aidx].type = + FLOW_ACTION_TYPE_MARK; + action->flow_actions[aidx].conf = + &action->mark; + aidx++; + + /* Move end type */ + action->flow_actions[aidx].type = + FLOW_ACTION_TYPE_END; + } + +#ifdef RTE_FLOW_DEBUG + switch (type) { + case FLOW_ACTION_TYPE_PORT_ID: + NT_LOG(DBG, FILTER, + "Port ID=%u, Original=%u\n", + ((const struct rte_flow_action_port_id + *)actions[iter_idx] + .conf) + ->id, + ((const struct rte_flow_action_port_id + *)actions[iter_idx] + .conf) + ->original); + break; + case FLOW_ACTION_TYPE_COUNT: + NT_LOG(DBG, FILTER, "Count ID=%u\n", + ((const struct rte_flow_action_count + *)actions[iter_idx] + .conf) + ->id); + break; + case FLOW_ACTION_TYPE_SET_TAG: + NT_LOG(DBG, FILTER, + "FLOW_ACTION_TYPE_SET_TAG: data=%u\n", + ((const struct flow_action_tag *) + actions[iter_idx] + .conf) + ->data); + NT_LOG(DBG, FILTER, + " mask=%u\n", + ((const struct flow_action_tag *) + actions[iter_idx] + .conf) + ->mask); + NT_LOG(DBG, FILTER, + " index=%u\n", + ((const struct flow_action_tag *) + actions[iter_idx] + .conf) + ->index); + break; + } +#endif + + action->flow_actions[aidx].conf = + actions[iter_idx].conf; + break; + } + + aidx++; + if (aidx == max_elem) + return -1; + iter_idx++; + } + + } while (type >= 0 && type != FLOW_ACTION_TYPE_END); + + return (type >= 0) ? 0 : -1; +} + +static int create_action_elements_inline(struct cnv_action_s *action, + const struct rte_flow_action actions[], + int max_elem, uint32_t queue_offset) +{ + int aidx = 0; + int type = -1; + + do { + type = CNV_TO_ACTION(actions[aidx].type); + +#ifdef RTE_FLOW_DEBUG + NT_LOG(INF, FILTER, + "RTE ACTION -> FILTER FLOW ACTION - %i -> %i - %s\n", + actions[aidx].type, type, + ((int)actions[aidx].type >= 0) ? + action_list_str[actions[aidx].type] : + "FLOW_ACTION_TYPE_TUNNEL_SET"); +#endif + + if (type >= 0) { + action->flow_actions[aidx].type = type; + + /* + * Non-compatible actions handled here + */ + switch (type) { + case FLOW_ACTION_TYPE_RSS: { + const struct rte_flow_action_rss *rss = + (const struct rte_flow_action_rss *) + actions[aidx] + .conf; + action->flow_rss.func = + FLOW_HASH_FUNCTION_DEFAULT; + + if (rss->func != + RTE_ETH_HASH_FUNCTION_DEFAULT) + return -1; + action->flow_rss.level = rss->level; + action->flow_rss.types = rss->types; + action->flow_rss.key_len = rss->key_len; + action->flow_rss.queue_num = rss->queue_num; + action->flow_rss.key = rss->key; + action->flow_rss.queue = rss->queue; + action->flow_actions[aidx].conf = + &action->flow_rss; +#ifdef RTE_FLOW_DEBUG + NT_LOG(DBG, FILTER, + "FLOW_ACTION_TYPE_RSS: rss->level = %u\n", + rss->level); + NT_LOG(DBG, FILTER, + " rss->types = 0x%" PRIX64 "\n", + (unsigned long long)rss->types); + NT_LOG(DBG, FILTER, + " rss->key_len = %u\n", + rss->key_len); + NT_LOG(DBG, FILTER, + " rss->queue_num = %u\n", + rss->queue_num); + NT_LOG(DBG, FILTER, + " rss->key = %p\n", + rss->key); + unsigned int i; + + for (i = 0; i < rss->queue_num; i++) { + NT_LOG(DBG, FILTER, + " rss->queue[%u] = %u\n", + i, rss->queue[i]); + } +#endif + } + break; + + case FLOW_ACTION_TYPE_RAW_DECAP: { + const struct rte_flow_action_raw_decap *decap = + (const struct rte_flow_action_raw_decap + *)actions[aidx] + .conf; + int item_count = interpret_raw_data(decap->data, + NULL, decap->size, + action->decap.items); + if (item_count < 0) + return item_count; +#ifdef RTE_FLOW_DEBUG + NT_LOG(DBG, FILTER, + "FLOW_ACTION_TYPE_RAW_DECAP: size = %u\n", + decap->size); + NT_LOG(DBG, FILTER, + "FLOW_ACTION_TYPE_RAW_DECAP: item_count = %u\n", + item_count); + for (int i = 0; i < item_count; i++) { + NT_LOG(DBG, FILTER, + "FLOW_ACTION_TYPE_RAW_DECAP: item = %u\n", + action->decap.items[i].type); + } +#endif + action->decap.data = decap->data; + action->decap.size = decap->size; + action->decap.item_count = item_count; + action->flow_actions[aidx].conf = + &action->decap; + } + break; + + case FLOW_ACTION_TYPE_RAW_ENCAP: { + const struct rte_flow_action_raw_encap *encap = + (const struct rte_flow_action_raw_encap + *)actions[aidx] + .conf; + int item_count = interpret_raw_data(encap->data, + encap->preserve, + encap->size, + action->encap.items); + if (item_count < 0) + return item_count; +#ifdef RTE_FLOW_DEBUG + NT_LOG(DBG, FILTER, + "FLOW_ACTION_TYPE_RAW_ENCAP: size = %u\n", + encap->size); + NT_LOG(DBG, FILTER, + "FLOW_ACTION_TYPE_RAW_ENCAP: item_count = %u\n", + item_count); +#endif + action->encap.data = encap->data; + action->encap.preserve = encap->preserve; + action->encap.size = encap->size; + action->encap.item_count = item_count; + action->flow_actions[aidx].conf = + &action->encap; + } + break; + + case FLOW_ACTION_TYPE_QUEUE: { + const struct rte_flow_action_queue *queue = + (const struct rte_flow_action_queue *) + actions[aidx] + .conf; + action->queue.index = + queue->index + queue_offset; + action->flow_actions[aidx].conf = + &action->queue; +#ifdef RTE_FLOW_DEBUG + NT_LOG(DBG, FILTER, + "FLOW_ACTION_TYPE_QUEUE: queue = %u\n", + action->queue.index); +#endif + } + break; + + default: { + action->flow_actions[aidx].conf = + actions[aidx].conf; + +#ifdef RTE_FLOW_DEBUG + switch (type) { + case FLOW_ACTION_TYPE_PORT_ID: + NT_LOG(DBG, FILTER, + "Port ID=%u, Original=%u\n", + ((const struct rte_flow_action_port_id + *)actions[aidx] + .conf) + ->id, + ((const struct rte_flow_action_port_id + *)actions[aidx] + .conf) + ->original); + break; + case FLOW_ACTION_TYPE_COUNT: + NT_LOG(DBG, FILTER, "Count ID=%u\n", + ((const struct rte_flow_action_count + *)actions[aidx] + .conf) + ->id); + break; + case FLOW_ACTION_TYPE_SET_TAG: + NT_LOG(DBG, FILTER, + "FLOW_ACTION_TYPE_SET_TAG: data=%u\n", + ((const struct flow_action_tag *) + actions[aidx] + .conf) + ->data); + NT_LOG(DBG, FILTER, + " mask=%u\n", + ((const struct flow_action_tag *) + actions[aidx] + .conf) + ->mask); + NT_LOG(DBG, FILTER, + " index=%u\n", + ((const struct flow_action_tag *) + actions[aidx] + .conf) + ->index); + break; + } +#endif + } + break; + } + + aidx++; + if (aidx == max_elem) + return -1; + } + + } while (type >= 0 && type != FLOW_ACTION_TYPE_END); + + return (type >= 0) ? 0 : -1; +} + +#endif /* __CREATE_ELEMENTS_H__ */ diff --git a/drivers/net/ntnic/ntnic_filter/ntnic_filter.c b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c new file mode 100644 index 0000000000..b1cc4d2959 --- /dev/null +++ b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c @@ -0,0 +1,656 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include + +#include "ntdrv_4ga.h" +#include +#include +#include "ntnic_ethdev.h" + +#include "ntlog.h" +#include "nt_util.h" +#include "create_elements.h" +#include "ntnic_filter.h" + +#define MAX_RTE_FLOWS 8192 +#define MAX_PORTIDS 64 + +#if (MAX_COLOR_FLOW_STATS != NT_MAX_COLOR_FLOW_STATS) +#error Difference in COLOR_FLOW_STATS. Please synchronize the defines. +#endif + +struct rte_flow nt_flows[MAX_RTE_FLOWS]; + +static int is_flow_handle_typecast(struct rte_flow *flow) +{ + const void *first_element = &nt_flows[0]; + const void *last_element = &nt_flows[MAX_RTE_FLOWS - 1]; + + return (void *)flow < first_element || (void *)flow > last_element; +} + +static int convert_flow(struct rte_eth_dev *eth_dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item items[], + const struct rte_flow_action actions[], + struct cnv_attr_s *attribute, struct cnv_match_s *match, + struct cnv_action_s *action, + struct rte_flow_error *error, uint32_t *flow_stat_id) +{ + struct pmd_internals *dev = eth_dev->data->dev_private; + struct fpga_info_s *fpga_info = &dev->p_drv->ntdrv.adapter_info.fpga_info; + + static struct flow_error flow_error = { .type = FLOW_ERROR_NONE, + .message = "none" + }; + uint32_t queue_offset = 0; + +#ifdef RTE_FLOW_DEBUG + NT_LOG(DBG, FILTER, "ntnic_flow_create port_id %u - %s\n", + eth_dev->data->port_id, eth_dev->data->name); +#endif + + if (dev->type == PORT_TYPE_OVERRIDE && dev->vpq_nb_vq > 0) { + /* + * The queues coming from the main PMD will always start from 0 + * When the port is a the VF/vDPA port the queues must be changed + * to match the queues allocated for VF/vDPA. + */ + queue_offset = dev->vpq[0].id; + } + + /* Set initial error */ + convert_error(error, &flow_error); + + if (!dev) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Missing eth_dev"); + return -1; + } + + if (create_attr(attribute, attr) != 0) { + rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, + NULL, "Error in attr"); + return -1; + } + if (create_match_elements(match, items, MAX_ELEMENTS) != 0) { + rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, + NULL, "Error in items"); + return -1; + } + if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) { + if (create_action_elements_inline(action, actions, MAX_ACTIONS, + queue_offset) != 0) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "Error in actions"); + return -1; + } + if (attribute->attr.group > 0) + return 0; + } else if (fpga_info->profile == FPGA_INFO_PROFILE_VSWITCH) { + if (create_action_elements_vswitch(action, actions, MAX_ACTIONS, + flow_stat_id) != 0) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "Error in actions"); + return -1; + } + } else { + rte_flow_error_set(error, EPERM, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Unsupported adapter profile"); + return -1; + } + return 0; +} + +static int eth_flow_destroy(struct rte_eth_dev *eth_dev, struct rte_flow *flow, + struct rte_flow_error *error) +{ + struct pmd_internals *dev = eth_dev->data->dev_private; + static struct flow_error flow_error = { .type = FLOW_ERROR_NONE, + .message = "none" + }; + + int res = 0; + + /* Set initial error */ + convert_error(error, &flow_error); + + if (!flow) + return 0; + + if (is_flow_handle_typecast(flow)) { + res = flow_destroy(dev->flw_dev, (void *)flow, &flow_error); + convert_error(error, &flow_error); + } else { + res = flow_destroy(dev->flw_dev, flow->flw_hdl, &flow_error); + convert_error(error, &flow_error); + + rte_spinlock_lock(&flow_lock); + delete_flow_stat_id_locked(flow->flow_stat_id); + flow->used = 0; + rte_spinlock_unlock(&flow_lock); + } + + /* Clear the flow statistics if successfully destroyed */ + if (res == 0) { + flow->stat_pkts = 0UL; + flow->stat_bytes = 0UL; + flow->stat_tcp_flags = 0; + } + + return res; +} + +static int eth_flow_validate(struct rte_eth_dev *eth_dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item items[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + static struct flow_error flow_error = { .type = FLOW_ERROR_NONE, + .message = "none" + }; + struct pmd_internals *dev = eth_dev->data->dev_private; + struct cnv_attr_s attribute; + struct cnv_match_s match; + struct cnv_action_s action; + uint32_t flow_stat_id = 0; + int res; + + if (convert_flow(eth_dev, attr, items, actions, &attribute, &match, + &action, error, &flow_stat_id) < 0) + return -EINVAL; + + res = flow_validate(dev->flw_dev, match.flow_elem, action.flow_actions, + &flow_error); + + if (res < 0) + convert_error(error, &flow_error); + + return res; +} + +static struct rte_flow *eth_flow_create(struct rte_eth_dev *eth_dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item items[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + struct pmd_internals *dev = eth_dev->data->dev_private; + struct fpga_info_s *fpga_info = &dev->p_drv->ntdrv.adapter_info.fpga_info; + + struct cnv_attr_s attribute; + struct cnv_match_s match; + struct cnv_action_s action; + + static struct flow_error flow_error = { .type = FLOW_ERROR_NONE, + .message = "none" + }; + uint32_t flow_stat_id = 0; + +#ifdef RTE_FLOW_DEBUG + NT_LOG(DBG, FILTER, "ntnic_flow_create port_id %u - %s\n", + eth_dev->data->port_id, eth_dev->data->name); +#endif + + if (convert_flow(eth_dev, attr, items, actions, &attribute, &match, + &action, error, &flow_stat_id) < 0) + return NULL; + + if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE && + attribute.attr.group > 0) { + void *flw_hdl = flow_create(dev->flw_dev, &attribute.attr, + match.flow_elem, + action.flow_actions, &flow_error); + convert_error(error, &flow_error); + return (struct rte_flow *)flw_hdl; + } + + struct rte_flow *flow = NULL; + + rte_spinlock_lock(&flow_lock); + int i; + + for (i = 0; i < MAX_RTE_FLOWS; i++) { + if (!nt_flows[i].used) { + nt_flows[i].flow_stat_id = flow_stat_id; + if (nt_flows[i].flow_stat_id < + NT_MAX_COLOR_FLOW_STATS) { + nt_flows[i].used = 1; + flow = &nt_flows[i]; + } + break; + } + } + rte_spinlock_unlock(&flow_lock); + if (flow) { + flow->flw_hdl = flow_create(dev->flw_dev, &attribute.attr, + match.flow_elem, + action.flow_actions, &flow_error); + convert_error(error, &flow_error); + if (!flow->flw_hdl) { + rte_spinlock_lock(&flow_lock); + delete_flow_stat_id_locked(flow->flow_stat_id); + flow->used = 0; + flow = NULL; + rte_spinlock_unlock(&flow_lock); + } else { +#ifdef RTE_FLOW_DEBUG + NT_LOG(INF, FILTER, "Create Flow %p using stat_id %i\n", + flow, flow->flow_stat_id); +#endif + } + } + return flow; +} + +uint64_t last_stat_rtc; + +int poll_statistics(struct pmd_internals *internals) +{ + int flow; + struct drv_s *p_drv = internals->p_drv; + struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv; + nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat; + const int if_index = internals->if_index; + + if (!p_nt4ga_stat || if_index < 0 || if_index > NUM_ADAPTER_PORTS_MAX) + return -1; + + assert(rte_tsc_freq > 0); + + rte_spinlock_lock(&hwlock); + + uint64_t now_rtc = rte_get_tsc_cycles(); + + /* + * Check per port max once a second + * if more than a second since last stat read, do a new one + */ + if ((now_rtc - internals->last_stat_rtc) < rte_tsc_freq) { + rte_spinlock_unlock(&hwlock); + return 0; + } + + internals->last_stat_rtc = now_rtc; + + pthread_mutex_lock(&p_nt_drv->stat_lck); + + /* + * Add the RX statistics increments since last time we polled. + * (No difference if physical or virtual port) + */ + internals->rxq_scg[0].rx_pkts += + p_nt4ga_stat->a_port_rx_packets_total[if_index] - + p_nt4ga_stat->a_port_rx_packets_base[if_index]; + internals->rxq_scg[0].rx_bytes += + p_nt4ga_stat->a_port_rx_octets_total[if_index] - + p_nt4ga_stat->a_port_rx_octets_base[if_index]; + internals->rxq_scg[0].err_pkts += 0; + internals->rx_missed += p_nt4ga_stat->a_port_rx_drops_total[if_index] - + p_nt4ga_stat->a_port_rx_drops_base[if_index]; + + /* _update the increment bases */ + p_nt4ga_stat->a_port_rx_packets_base[if_index] = + p_nt4ga_stat->a_port_rx_packets_total[if_index]; + p_nt4ga_stat->a_port_rx_octets_base[if_index] = + p_nt4ga_stat->a_port_rx_octets_total[if_index]; + p_nt4ga_stat->a_port_rx_drops_base[if_index] = + p_nt4ga_stat->a_port_rx_drops_total[if_index]; + + /* Tx (here we must distinguish between physical and virtual ports) */ + if (internals->type == PORT_TYPE_PHYSICAL) { + /* LAG management of Tx stats. */ + if (lag_active && if_index == 0) { + unsigned int i; + /* + * Collect all LAG ports Tx stat into this one. Simplified to only collect + * from port 0 and 1. + */ + for (i = 0; i < 2; i++) { + /* Add the statistics increments since last time we polled */ + internals->txq_scg[0].tx_pkts += + p_nt4ga_stat->a_port_tx_packets_total[i] - + p_nt4ga_stat->a_port_tx_packets_base[i]; + internals->txq_scg[0].tx_bytes += + p_nt4ga_stat->a_port_tx_octets_total[i] - + p_nt4ga_stat->a_port_tx_octets_base[i]; + internals->txq_scg[0].err_pkts += 0; + + /* _update the increment bases */ + p_nt4ga_stat->a_port_tx_packets_base[i] = + p_nt4ga_stat->a_port_tx_packets_total[i]; + p_nt4ga_stat->a_port_tx_octets_base[i] = + p_nt4ga_stat->a_port_tx_octets_total[i]; + } + } else { + /* Add the statistics increments since last time we polled */ + internals->txq_scg[0].tx_pkts += + p_nt4ga_stat->a_port_tx_packets_total[if_index] - + p_nt4ga_stat->a_port_tx_packets_base[if_index]; + internals->txq_scg[0].tx_bytes += + p_nt4ga_stat->a_port_tx_octets_total[if_index] - + p_nt4ga_stat->a_port_tx_octets_base[if_index]; + internals->txq_scg[0].err_pkts += 0; + + /* _update the increment bases */ + p_nt4ga_stat->a_port_tx_packets_base[if_index] = + p_nt4ga_stat->a_port_tx_packets_total[if_index]; + p_nt4ga_stat->a_port_tx_octets_base[if_index] = + p_nt4ga_stat->a_port_tx_octets_total[if_index]; + } + } + if (internals->type == PORT_TYPE_VIRTUAL) { + /* _update TX counters from HB queue counter */ + unsigned int i; + struct host_buffer_counters *const p_hb_counters = + p_nt4ga_stat->mp_stat_structs_hb; + uint64_t v_port_packets_total = 0, v_port_octets_total = 0; + + /* + * This is a bit odd. But typically nb_tx_queues must be only 1 since it denotes + * the number of exception queues which must be 1 - for now. The code is kept if we + * want it in future, but it will not be likely. + * Therefore adding all vPorts queue tx counters into Tx[0] is ok for now. + * + * Only use the vPort Tx counter to update OVS, since these are the real ones. + * The rep port into OVS that represents this port will always replicate the traffic + * here, also when no offload occurs + */ + for (i = 0; i < internals->vpq_nb_vq; ++i) { + v_port_packets_total += + p_hb_counters[internals->vpq[i].id].fwd_packets; + v_port_octets_total += + p_hb_counters[internals->vpq[i].id].fwd_bytes; + } + /* Add the statistics increments since last time we polled */ + internals->txq_scg[0].tx_pkts += + v_port_packets_total - + p_nt4ga_stat->a_port_tx_packets_base[if_index]; + internals->txq_scg[0].tx_bytes += + v_port_octets_total - + p_nt4ga_stat->a_port_tx_octets_base[if_index]; + internals->txq_scg[0].err_pkts += 0; /* What to user here ?? */ + + /* _update the increment bases */ + p_nt4ga_stat->a_port_tx_packets_base[if_index] = v_port_packets_total; + p_nt4ga_stat->a_port_tx_octets_base[if_index] = v_port_octets_total; + } + + /* Globally only once a second */ + if ((now_rtc - last_stat_rtc) < rte_tsc_freq) { + rte_spinlock_unlock(&hwlock); + pthread_mutex_unlock(&p_nt_drv->stat_lck); + return 0; + } + + last_stat_rtc = now_rtc; + + /* All color counter are global, therefore only 1 pmd must update them */ + const struct color_counters *p_color_counters = + p_nt4ga_stat->mp_stat_structs_color; + struct color_counters *p_color_counters_base = + p_nt4ga_stat->a_stat_structs_color_base; + uint64_t color_packets_accumulated, color_bytes_accumulated; + + for (flow = 0; flow < MAX_RTE_FLOWS; flow++) { + if (nt_flows[flow].used) { + unsigned int color = nt_flows[flow].flow_stat_id; + + if (color < NT_MAX_COLOR_FLOW_STATS) { + color_packets_accumulated = + p_color_counters[color].color_packets; + nt_flows[flow].stat_pkts += + (color_packets_accumulated - + p_color_counters_base[color].color_packets); + + nt_flows[flow].stat_tcp_flags |= + p_color_counters[color].tcp_flags; + + color_bytes_accumulated = + p_color_counters[color].color_bytes; + nt_flows[flow].stat_bytes += + (color_bytes_accumulated - + p_color_counters_base[color].color_bytes); + + /* _update the counter bases */ + p_color_counters_base[color].color_packets = + color_packets_accumulated; + p_color_counters_base[color].color_bytes = + color_bytes_accumulated; + } + } + } + + rte_spinlock_unlock(&hwlock); + pthread_mutex_unlock(&p_nt_drv->stat_lck); + + return 0; +} + +static int eth_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow, + const struct rte_flow_action *action, void *data, + struct rte_flow_error *err) +{ + struct pmd_internals *internals = dev->data->dev_private; + + err->cause = NULL; + err->message = NULL; + + if (is_flow_handle_typecast(flow)) { + rte_flow_error_set(err, EFAULT, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "Error in flow handle"); + return -1; + } + + poll_statistics(internals); + + if (action->type == RTE_FLOW_ACTION_TYPE_COUNT) { + struct rte_flow_query_count *qcnt = + (struct rte_flow_query_count *)data; + if (qcnt) { + if (flow) { + qcnt->hits = flow->stat_pkts; + qcnt->hits_set = 1; + qcnt->bytes = flow->stat_bytes; + qcnt->bytes_set = 1; + + if (qcnt->reset) { + flow->stat_pkts = 0UL; + flow->stat_bytes = 0UL; + flow->stat_tcp_flags = 0; + } + } else { + qcnt->hits_set = 0; + qcnt->bytes_set = 0; + } + } + } else { + rte_flow_error_set(err, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, + NULL, "Unsupported query"); + return -1; + } + rte_flow_error_set(err, 0, RTE_FLOW_ERROR_TYPE_NONE, NULL, "Success"); + return 0; +} + +#ifdef DEBUGGING + +static void _print_tunnel(struct rte_flow_tunnel *tunnel) +{ + struct in_addr addr; + + NT_LOG(DBG, FILTER, " tun type: %i\n", tunnel->type); + NT_LOG(DBG, FILTER, " tun ID: %016lx\n", tunnel->tun_id); + addr.s_addr = tunnel->ipv4.src_addr; + NT_LOG(DBG, FILTER, " tun src IP: %s\n", inet_ntoa(addr)); + addr.s_addr = tunnel->ipv4.dst_addr; + NT_LOG(DBG, FILTER, " tun dst IP: %s\n", inet_ntoa(addr)); + NT_LOG(DBG, FILTER, " tun tp_src: %i\n", htons(tunnel->tp_src)); + NT_LOG(DBG, FILTER, " tun tp_dst: %i\n", htons(tunnel->tp_dst)); + NT_LOG(DBG, FILTER, " tun flags: %i\n", tunnel->tun_flags); + NT_LOG(DBG, FILTER, " tun ipv6: %i\n", tunnel->is_ipv6); + + NT_LOG(DBG, FILTER, " tun tos: %i\n", tunnel->tos); + NT_LOG(DBG, FILTER, " tun ttl: %i\n", tunnel->ttl); +} +#endif + +static struct rte_flow_action _pmd_actions[] = { + { .type = (enum rte_flow_action_type)NT_RTE_FLOW_ACTION_TYPE_TUNNEL_SET, + .conf = NULL + }, + { .type = 0, .conf = NULL } +}; + +static int ntnic_tunnel_decap_set(struct rte_eth_dev *dev _unused, + struct rte_flow_tunnel *tunnel, + struct rte_flow_action **pmd_actions, + uint32_t *num_of_actions, + struct rte_flow_error *err _unused) +{ +#ifdef DEBUGGING + NT_LOG(DBG, FILTER, "%s: [%s:%u] start\n", __func__, __FILE__, __LINE__); +#endif + + if (tunnel->type == RTE_FLOW_ITEM_TYPE_VXLAN) + _pmd_actions[1].type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP; + else + return -ENOTSUP; + + *pmd_actions = _pmd_actions; + *num_of_actions = 2; + + return 0; +} + +static struct rte_flow_item _pmd_items = { + .type = (enum rte_flow_item_type)NT_RTE_FLOW_ITEM_TYPE_TUNNEL, + .spec = NULL, + .last = NULL, + .mask = NULL +}; + +static int ntnic_tunnel_match(struct rte_eth_dev *dev _unused, + struct rte_flow_tunnel *tunnel _unused, + struct rte_flow_item **pmd_items, + uint32_t *num_of_items, + struct rte_flow_error *err _unused) +{ +#ifdef DEBUGGING + NT_LOG(DBG, FILTER, "%s: [%s:%u] start\n", __func__, __FILE__, __LINE__); +#endif + + *pmd_items = &_pmd_items; + *num_of_items = 1; + return 0; +} + +/* + * Restoration API support + */ +static int ntnic_get_restore_info(struct rte_eth_dev *dev _unused, + struct rte_mbuf *m, + struct rte_flow_restore_info *info, + struct rte_flow_error *err _unused) +{ +#ifdef DEBUGGING + NT_LOG(DBG, FILTER, "%s: [%s:%u]\n", __func__, __FILE__, __LINE__); + NT_LOG(DBG, FILTER, "dev name: %s - port_id %i\n", dev->data->name, dev->data->port_id); + NT_LOG(DBG, FILTER, "dpdk tunnel mark %08x\n", m->hash.fdir.hi); +#endif + + if ((m->ol_flags & RTE_MBUF_F_RX_FDIR_ID) && m->hash.fdir.hi) { + uint8_t port_id = (m->hash.fdir.hi >> 24) & 0xff; + uint32_t stat_id = m->hash.fdir.lo & 0xffffff; + + struct tunnel_cfg_s tuncfg; + int ret = flow_get_tunnel_definition(&tuncfg, stat_id, port_id); + + if (ret) + return -EINVAL; + + if (tuncfg.ipversion == 4) { + info->tunnel.ipv4.dst_addr = tuncfg.v4.dst_ip; + info->tunnel.ipv4.src_addr = tuncfg.v4.src_ip; + info->tunnel.is_ipv6 = 0; + } else { + /* IPv6 */ + for (int i = 0; i < 16; i++) { + info->tunnel.ipv6.src_addr[i] = + tuncfg.v6.src_ip[i]; + info->tunnel.ipv6.dst_addr[i] = + tuncfg.v6.dst_ip[i]; + } + info->tunnel.is_ipv6 = 1; + } + + info->tunnel.tp_dst = tuncfg.d_port; + info->tunnel.tp_src = tuncfg.s_port; + + info->tunnel.ttl = 64; + info->tunnel.tos = 0; + + /* FLOW_TNL_F_KEY | FLOW_TNL_F_DONT_FRAGMENT */ + info->tunnel.tun_flags = (1 << 3) | (1 << 1); + + info->tunnel.type = RTE_FLOW_ITEM_TYPE_VXLAN; + info->tunnel.tun_id = m->hash.fdir.hi & 0xffffff; + + info->flags = RTE_FLOW_RESTORE_INFO_TUNNEL; + /* | RTE_FLOW_RESTORE_INFO_ENCAPSULATED; if restored packet is sent back */ + info->group_id = 0; + +#ifdef DEBUGGING + _print_tunnel(&info->tunnel); +#endif + + return 0; + } + return -EINVAL; /* Supported, but no hit found */ +} + +static int +ntnic_tunnel_action_decap_release(struct rte_eth_dev *dev _unused, + struct rte_flow_action *pmd_actions _unused, + uint32_t num_of_actions _unused, + struct rte_flow_error *err _unused) +{ +#ifdef DEBUGGING + NT_LOG(DBG, FILTER, "%s: [%s:%u] start\n", __func__, __FILE__, __LINE__); +#endif + return 0; +} + +static int ntnic_tunnel_item_release(struct rte_eth_dev *dev _unused, + struct rte_flow_item *pmd_items _unused, + uint32_t num_of_items _unused, + struct rte_flow_error *err _unused) +{ +#ifdef DEBUGGING + NT_LOG(DBG, FILTER, "%s: [%s:%u] start\n", __func__, __FILE__, __LINE__); +#endif + return 0; +} + +const struct rte_flow_ops _dev_flow_ops = { + .validate = eth_flow_validate, + .create = eth_flow_create, + .destroy = eth_flow_destroy, + .flush = NULL, + .query = eth_flow_query, + .tunnel_decap_set = ntnic_tunnel_decap_set, + .tunnel_match = ntnic_tunnel_match, + .get_restore_info = ntnic_get_restore_info, + .tunnel_action_decap_release = ntnic_tunnel_action_decap_release, + .tunnel_item_release = ntnic_tunnel_item_release + +}; diff --git a/drivers/net/ntnic/ntnic_filter/ntnic_filter.h b/drivers/net/ntnic/ntnic_filter/ntnic_filter.h new file mode 100644 index 0000000000..cf4207e5de --- /dev/null +++ b/drivers/net/ntnic/ntnic_filter/ntnic_filter.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTNIC_FILTER_H__ +#define __NTNIC_FILTER_H__ + +struct rte_flow * +client_flow_create(struct flow_eth_dev *flw_dev, enum fpga_info_profile profile, + struct cnv_attr_s *attribute, struct cnv_match_s *match, + struct cnv_action_s *action, uint32_t flow_stat_id, + struct rte_flow_error *error); + +#endif /* __NTNIC_FILTER_H__ */ diff --git a/drivers/net/ntnic/ntnic_hshconfig.c b/drivers/net/ntnic/ntnic_hshconfig.c new file mode 100644 index 0000000000..a8eff76528 --- /dev/null +++ b/drivers/net/ntnic/ntnic_hshconfig.c @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include + +#include "ntnic_hshconfig.h" + +#include +#include + +struct pair_uint64_t { + uint64_t first; + uint64_t second; +}; + +#define PAIR_NT(name) \ + { \ + RTE_##name, NT_##name \ + } + +struct pair_uint64_t rte_eth_rss_to_nt[] = { + PAIR_NT(ETH_RSS_IPV4), + PAIR_NT(ETH_RSS_FRAG_IPV4), + PAIR_NT(ETH_RSS_NONFRAG_IPV4_OTHER), + PAIR_NT(ETH_RSS_IPV6), + PAIR_NT(ETH_RSS_FRAG_IPV6), + PAIR_NT(ETH_RSS_NONFRAG_IPV6_OTHER), + PAIR_NT(ETH_RSS_IPV6_EX), + PAIR_NT(ETH_RSS_C_VLAN), + PAIR_NT(ETH_RSS_L3_DST_ONLY), + PAIR_NT(ETH_RSS_L3_SRC_ONLY), + PAIR_NT(ETH_RSS_LEVEL_OUTERMOST), + PAIR_NT(ETH_RSS_LEVEL_INNERMOST), +}; + +static const uint64_t *rte_to_nt_rss_flag(const uint64_t rte_flag) +{ + const struct pair_uint64_t *start = rte_eth_rss_to_nt; + + for (const struct pair_uint64_t *p = start; + p != start + ARRAY_SIZE(rte_eth_rss_to_nt); ++p) { + if (p->first == rte_flag) + return &p->second; + } + return NULL; /* NOT found */ +} + +static const uint64_t *nt_to_rte_rss_flag(const uint64_t nt_flag) +{ + const struct pair_uint64_t *start = rte_eth_rss_to_nt; + + for (const struct pair_uint64_t *p = start; + p != start + ARRAY_SIZE(rte_eth_rss_to_nt); ++p) { + if (p->second == nt_flag) + return &p->first; + } + return NULL; /* NOT found */ +} + +struct nt_eth_rss nt_rss_hash_field_from_dpdk(uint64_t rte_hash_bits) +{ + struct nt_eth_rss res = { 0 }; + + for (uint i = 0; i < sizeof(rte_hash_bits) * CHAR_BIT; ++i) { + uint64_t rte_bit = (UINT64_C(1) << i); + + if (rte_hash_bits & rte_bit) { + const uint64_t *nt_bit_p = rte_to_nt_rss_flag(rte_bit); + + if (!nt_bit_p) { + NT_LOG(ERR, ETHDEV, + "RSS hash function field number %d is not supported. Only supported fields will be used in RSS hash function.", + i); + } else { + res.fields |= *nt_bit_p; + } + } + } + + return res; +} + +uint64_t dpdk_rss_hash_define_from_nt_rss(struct nt_eth_rss nt_hsh) +{ + uint64_t res = 0; + + for (uint i = 0; i < sizeof(nt_hsh.fields) * CHAR_BIT; ++i) { + uint64_t nt_bit = (UINT64_C(1) << i); + + if (nt_hsh.fields & nt_bit) { + const uint64_t *rte_bit_p = nt_to_rte_rss_flag(nt_bit); + + assert(rte_bit_p && + "All nt rss bit flags should be mapped to rte rss bit fields, as nt rss is a subset of rte options"); + res |= *rte_bit_p; + } + } + + return res; +} diff --git a/drivers/net/ntnic/ntnic_hshconfig.h b/drivers/net/ntnic/ntnic_hshconfig.h new file mode 100644 index 0000000000..d4d7337d23 --- /dev/null +++ b/drivers/net/ntnic/ntnic_hshconfig.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include + +/* Mapping from dpdk rss hash defines to nt hash defines */ +struct nt_eth_rss nt_rss_hash_field_from_dpdk(uint64_t rte_hash_bits); +uint64_t dpdk_rss_hash_define_from_nt_rss(struct nt_eth_rss nt_hsh); diff --git a/drivers/net/ntnic/ntnic_meter.c b/drivers/net/ntnic/ntnic_meter.c new file mode 100644 index 0000000000..027ae073dd --- /dev/null +++ b/drivers/net/ntnic/ntnic_meter.c @@ -0,0 +1,811 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include + +#include +#include +#include +#include + +#include "ntdrv_4ga.h" +#include "nthw_fpga.h" +#include "ntnic_ethdev.h" +#include "ntnic_meter.h" +#include "ntlog.h" + +/* + ******************************************************************************* + * Vswitch metering + ******************************************************************************* + */ + +static const uint32_t highest_bit_mask = (~(~0u >> 1)); + +static struct nt_mtr_profile * +nt_mtr_profile_find(struct pmd_internals *dev_priv, uint32_t meter_profile_id) +{ + struct nt_mtr_profile *profile = NULL; + + LIST_FOREACH(profile, &dev_priv->mtr_profiles, next) + if (profile->profile_id == meter_profile_id) + break; + + return profile; +} + +static int eth_meter_profile_add(struct rte_eth_dev *dev, + uint32_t meter_profile_id, + struct rte_mtr_meter_profile *profile, + struct rte_mtr_error *error) +{ + struct pmd_internals *dev_priv = dev->data->dev_private; + + NT_LOG(DBG, NTHW, "%s: [%s:%u] adapter: " PCIIDENT_PRINT_STR "\n", + __func__, __func__, __LINE__, + PCIIDENT_TO_DOMAIN(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_BUSNR(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_DEVNR(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_FUNCNR(dev_priv->p_drv->ntdrv.pciident)); + + const bool is_egress = meter_profile_id & highest_bit_mask; + + if (dev_priv->type == PORT_TYPE_VIRTUAL || is_egress) { + struct nt_mtr_profile *prof; + + prof = nt_mtr_profile_find(dev_priv, meter_profile_id); + if (prof) + return -rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, + "Profile id already exists\n"); + + prof = rte_zmalloc(NULL, sizeof(*prof), 0); + if (!prof) { + return -rte_mtr_error_set(error, + ENOMEM, RTE_MTR_ERROR_TYPE_UNSPECIFIED, + NULL, NULL); + } + + prof->profile_id = meter_profile_id; + memcpy(&prof->profile, profile, + sizeof(struct rte_mtr_meter_profile)); + + LIST_INSERT_HEAD(&dev_priv->mtr_profiles, prof, next); + + return 0; + } + /* Ingress is not possible yet on phy ports */ + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Traffic ingress metering/policing is not supported on physical ports\n"); +} + +static int eth_meter_profile_delete(struct rte_eth_dev *dev, + uint32_t meter_profile_id, + struct rte_mtr_error *error) +{ + struct pmd_internals *dev_priv = dev->data->dev_private; + struct nt_mtr_profile *profile; + + NT_LOG(DBG, NTHW, "%s: [%s:%u] adapter: " PCIIDENT_PRINT_STR "\n", + __func__, __func__, __LINE__, + PCIIDENT_TO_DOMAIN(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_BUSNR(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_DEVNR(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_FUNCNR(dev_priv->p_drv->ntdrv.pciident)); + + profile = nt_mtr_profile_find(dev_priv, meter_profile_id); + if (!profile) + return -rte_mtr_error_set(error, ENODEV, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "Profile id does not exist\n"); + + LIST_REMOVE(profile, next); + rte_free(profile); + return 0; +} + +static struct nt_mtr *nt_mtr_find(struct pmd_internals *dev_priv, + uint32_t mtr_id) +{ + struct nt_mtr *mtr = NULL; + + LIST_FOREACH(mtr, &dev_priv->mtrs, next) + if (mtr->mtr_id == mtr_id) + break; + + return mtr; +} + +struct qos_integer_fractional { + uint32_t integer; + uint32_t fractional; /* 1/1024 */ +}; + +/* + * Converts byte/s to byte/period if form of integer + 1/1024*fractional + * the period depends on the clock friquency and other parameters which + * being combined give multiplier. The resulting formula is: + * f[bytes/period] = x[byte/s] * period_ps / 10^-12 + */ +static struct qos_integer_fractional +byte_per_second_to_qo_s_ri(uint64_t byte_per_second, uint64_t period_ps) +{ + struct qos_integer_fractional res; + const uint64_t dividend = byte_per_second * period_ps; + const uint64_t divisor = 1000000000000ull; /*10^12 pico second*/ + + res.integer = dividend / divisor; + const uint64_t reminder = dividend % divisor; + + res.fractional = 1024ull * reminder / divisor; + return res; +} + +static struct qos_integer_fractional +byte_per_second_to_physical_qo_s_ri(uint64_t byte_per_second) +{ + return byte_per_second_to_qo_s_ri(byte_per_second, 8 * 3333ul); +} + +static struct qos_integer_fractional +byte_per_second_to_virtual_qo_s_ri(uint64_t byte_per_second) +{ + return byte_per_second_to_qo_s_ri(byte_per_second, 512 * 3333ul); +} + +static int eth_meter_enable(struct rte_eth_dev *dev, uint32_t mtr_id, + struct rte_mtr_error *error) +{ + struct pmd_internals *dev_priv = dev->data->dev_private; + int res; + static int ingress_initial; + + NT_LOG(DBG, NTHW, "%s: [%s:%u] adapter: " PCIIDENT_PRINT_STR "\n", + __func__, __func__, __LINE__, + PCIIDENT_TO_DOMAIN(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_BUSNR(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_DEVNR(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_FUNCNR(dev_priv->p_drv->ntdrv.pciident)); + + nthw_dbs_t *p_nthw_dbs = + dev_priv->p_drv->ntdrv.adapter_info.fpga_info.mp_nthw_dbs; + nthw_epp_t *p_nthw_epp = + dev_priv->p_drv->ntdrv.adapter_info.fpga_info.mp_nthw_epp; + + /* + * FPGA is based on FRC 4115 so CIR,EIR and CBS/EBS are used + * rfc4115.cir = rfc2697.cir + * rfc4115.eir = rfc2697.cir + * rfc4115.cbs = rfc2697.cbs + * rfc4115.ebs = rfc2697.ebs + */ + struct nt_mtr *mtr = nt_mtr_find(dev_priv, mtr_id); + + if (!mtr) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, + "Meter id not found\n"); + } + + if (!mtr->profile) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "Meter profile id not found\n"); + } + + const uint32_t profile_id = mtr->profile->profile_id; + const bool is_egress = profile_id & highest_bit_mask; + uint32_t burst = mtr->profile->profile.srtcm_rfc2697.cbs; + + if (is_egress) { + const bool is_virtual = (dev_priv->type == PORT_TYPE_VIRTUAL); + struct qos_integer_fractional cir = { 0 }; + + if (is_virtual) { + cir = + byte_per_second_to_virtual_qo_s_ri(mtr->profile->profile.srtcm_rfc2697.cir); + if (cir.integer == 0 && cir.fractional == 0) + cir.fractional = 1; + res = nthw_epp_set_vport_qos(p_nthw_epp, dev_priv->port, + cir.integer, cir.fractional, + burst); + } else { + cir = + byte_per_second_to_physical_qo_s_ri(mtr->profile->profile + .srtcm_rfc2697.cir); + if (cir.integer == 0 && cir.fractional == 0) + cir.fractional = 1; + res = nthw_epp_set_txp_qos(p_nthw_epp, dev_priv->port, + cir.integer, cir.fractional, + burst); + } + if (res) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, + NULL, + "Applying meter profile for setting egress policy failed\n"); + } + } else { + if (!ingress_initial) { + /* + * based on a 250Mhz FPGA + * _update refresh rate interval calculation: + * multiplier / (divider * 4ns) + * 1 / (2000 * 4ns) = 8,000*10-6 => refresh rate interval = 8000ns + * + * results in resolution of IR is 1Mbps + */ + res = nthw_set_tx_qos_rate_global(p_nthw_dbs, 1, 2000); + + if (res) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Applying meter profile for setting ingress " + "global QoS rate failed\n"); + } + ingress_initial = 1; + } + + if (mtr->profile->profile.srtcm_rfc2697.cbs >= (1 << 27)) { + /* max burst 1,074Mb (27 bits) */ + mtr->profile->profile.srtcm_rfc2697.cbs = (1 << 27) - 1; + } + /* IR - fill x bytes each 8000ns -> 1B/8000ns => 1000Kbps => 125000Bps / x */ + res = nthw_set_tx_qos_config(p_nthw_dbs, dev_priv->port, /* vport */ + 1, /* enable */ + mtr->profile->profile.srtcm_rfc2697.cir / + 125000, + mtr->profile->profile.srtcm_rfc2697 + .cbs); /* BS - burst size in Bytes */ + if (res) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, + NULL, "Applying meter profile failed\n"); + } + } + return 0; +} + +static void disable(struct pmd_internals *dev_priv) +{ + NT_LOG(DBG, NTHW, "%s: [%s:%u] adapter: " PCIIDENT_PRINT_STR "\n", + __func__, __func__, __LINE__, + PCIIDENT_TO_DOMAIN(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_BUSNR(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_DEVNR(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_FUNCNR(dev_priv->p_drv->ntdrv.pciident)); + + nthw_dbs_t *p_nthw_dbs = + dev_priv->p_drv->ntdrv.adapter_info.fpga_info.mp_nthw_dbs; + nthw_set_tx_qos_config(p_nthw_dbs, dev_priv->port, /* vport */ + 0, /* disable */ + 0, /* IR */ + 0); /* BS */ +} + +static int eth_meter_disable(struct rte_eth_dev *dev, uint32_t mtr_id, + struct rte_mtr_error *error) +{ + struct pmd_internals *dev_priv = dev->data->dev_private; + struct nt_mtr *mtr = nt_mtr_find(dev_priv, mtr_id); + + NT_LOG(DBG, NTHW, "%s: [%s:%u] adapter: " PCIIDENT_PRINT_STR "\n", + __func__, __func__, __LINE__, + PCIIDENT_TO_DOMAIN(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_BUSNR(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_DEVNR(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_FUNCNR(dev_priv->p_drv->ntdrv.pciident)); + + nthw_epp_t *p_nthw_epp = + dev_priv->p_drv->ntdrv.adapter_info.fpga_info.mp_nthw_epp; + + if (!mtr) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, + "Meter id not found\n"); + } + + const bool is_egress = mtr_id & highest_bit_mask; + + if (is_egress) { + const bool is_virtual = (dev_priv->type == PORT_TYPE_VIRTUAL); + + if (is_virtual) + nthw_epp_set_vport_qos(p_nthw_epp, dev_priv->port, 0, 0, 0); + else + nthw_epp_set_txp_qos(p_nthw_epp, dev_priv->port, 0, 0, 0); + } else { + disable(dev_priv); + } + return 0; +} + +/* MTR object create */ +static int eth_mtr_create(struct rte_eth_dev *dev, uint32_t mtr_id, + struct rte_mtr_params *params, int shared, + struct rte_mtr_error *error) +{ + struct pmd_internals *dev_priv = dev->data->dev_private; + struct nt_mtr *mtr = NULL; + struct nt_mtr_profile *profile; + + NT_LOG(DBG, NTHW, "%s: [%s:%u] adapter: " PCIIDENT_PRINT_STR "\n", + __func__, __func__, __LINE__, + PCIIDENT_TO_DOMAIN(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_BUSNR(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_DEVNR(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_FUNCNR(dev_priv->p_drv->ntdrv.pciident)); + + const bool is_egress = mtr_id & highest_bit_mask; + + if (dev_priv->type == PORT_TYPE_PHYSICAL && !is_egress) { + NT_LOG(ERR, NTHW, + "ERROR try to create ingress meter object on a phy port. Not supported\n"); + + return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Traffic ingress metering/policing is not supported on physical ports\n"); + } + + mtr = nt_mtr_find(dev_priv, mtr_id); + if (mtr) + return -rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, + "Meter id already exists\n"); + + profile = nt_mtr_profile_find(dev_priv, params->meter_profile_id); + if (!profile) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "Profile id does not exist\n"); + } + + mtr = rte_zmalloc(NULL, sizeof(struct nt_mtr), 0); + if (!mtr) + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + NULL); + + mtr->shared = shared; + mtr->mtr_id = mtr_id; + mtr->profile = profile; + LIST_INSERT_HEAD(&dev_priv->mtrs, mtr, next); + + if (params->meter_enable) + return eth_meter_enable(dev, mtr_id, error); + + return 0; +} + +/* MTR object destroy */ +static int eth_mtr_destroy(struct rte_eth_dev *dev, uint32_t mtr_id, + struct rte_mtr_error *error) +{ + struct pmd_internals *dev_priv = dev->data->dev_private; + struct nt_mtr *mtr; + + NT_LOG(DBG, NTHW, "%s: [%s:%u] adapter: " PCIIDENT_PRINT_STR "\n", + __func__, __func__, __LINE__, + PCIIDENT_TO_DOMAIN(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_BUSNR(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_DEVNR(dev_priv->p_drv->ntdrv.pciident), + PCIIDENT_TO_FUNCNR(dev_priv->p_drv->ntdrv.pciident)); + + nthw_epp_t *p_nthw_epp = + dev_priv->p_drv->ntdrv.adapter_info.fpga_info.mp_nthw_epp; + + mtr = nt_mtr_find(dev_priv, mtr_id); + if (!mtr) + return -rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, + "Meter id does not exist\n"); + + const bool is_egress = mtr_id & highest_bit_mask; + + if (is_egress) { + const bool is_virtual = (dev_priv->type == PORT_TYPE_VIRTUAL); + + if (is_virtual) + nthw_epp_set_vport_qos(p_nthw_epp, dev_priv->port, 0, 0, 0); + else + nthw_epp_set_txp_qos(p_nthw_epp, dev_priv->port, 0, 0, 0); + } else { + disable(dev_priv); + } + LIST_REMOVE(mtr, next); + rte_free(mtr); + return 0; +} + +/* + ******************************************************************************* + * Inline FLM metering + ******************************************************************************* + */ + +static int eth_mtr_capabilities_get_inline(struct rte_eth_dev *dev, + struct rte_mtr_capabilities *cap, + struct rte_mtr_error *error) +{ + struct pmd_internals *dev_priv = dev->data->dev_private; + + if (!flow_mtr_supported(dev_priv->flw_dev)) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Ethernet device does not support metering\n"); + } + + memset(cap, 0x0, sizeof(struct rte_mtr_capabilities)); + + /* MBR records use 28-bit integers */ + cap->n_max = flow_mtr_meters_supported(); + cap->n_shared_max = cap->n_max; + + cap->identical = 0; + cap->shared_identical = 0; + + cap->shared_n_flows_per_mtr_max = UINT32_MAX; + + /* Limited by number of MBR record ids per FLM learn record */ + cap->chaining_n_mtrs_per_flow_max = 4; + + cap->chaining_use_prev_mtr_color_supported = 0; + cap->chaining_use_prev_mtr_color_enforced = 0; + + cap->meter_rate_max = (uint64_t)(0xfff << 0xf) * 1099; + + cap->stats_mask = RTE_MTR_STATS_N_PKTS_GREEN | + RTE_MTR_STATS_N_BYTES_GREEN; + + /* Only color-blind mode is supported */ + cap->color_aware_srtcm_rfc2697_supported = 0; + cap->color_aware_trtcm_rfc2698_supported = 0; + cap->color_aware_trtcm_rfc4115_supported = 0; + + /* Focused on RFC2698 for now */ + cap->meter_srtcm_rfc2697_n_max = 0; + cap->meter_trtcm_rfc2698_n_max = cap->n_max; + cap->meter_trtcm_rfc4115_n_max = 0; + + cap->meter_policy_n_max = flow_mtr_meter_policy_n_max(); + + /* Byte mode is supported */ + cap->srtcm_rfc2697_byte_mode_supported = 0; + cap->trtcm_rfc2698_byte_mode_supported = 1; + cap->trtcm_rfc4115_byte_mode_supported = 0; + + /* Packet mode not supported */ + cap->srtcm_rfc2697_packet_mode_supported = 0; + cap->trtcm_rfc2698_packet_mode_supported = 0; + cap->trtcm_rfc4115_packet_mode_supported = 0; + + return 0; +} + +static int +eth_mtr_meter_profile_add_inline(struct rte_eth_dev *dev, + uint32_t meter_profile_id, + struct rte_mtr_meter_profile *profile, + struct rte_mtr_error *error __rte_unused) +{ + struct pmd_internals *dev_priv = dev->data->dev_private; + + if (meter_profile_id >= flow_mtr_meter_policy_n_max()) + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "Profile id out of range\n"); + + if (profile->packet_mode != 0) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE_PACKET_MODE, NULL, + "Profile packet mode not supported\n"); + } + + if (profile->alg == RTE_MTR_SRTCM_RFC2697) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, + NULL, "RFC 2697 not supported\n"); + } + + if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, + NULL, "RFC 4115 not supported\n"); + } + + if (profile->trtcm_rfc2698.cir != profile->trtcm_rfc2698.pir || + profile->trtcm_rfc2698.cbs != profile->trtcm_rfc2698.pbs) { + return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "Profile committed and peak rates must be equal\n"); + } + + int res = flow_mtr_set_profile(dev_priv->flw_dev, meter_profile_id, + profile->trtcm_rfc2698.cir, + profile->trtcm_rfc2698.cbs, 0, 0); + + if (res) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, + NULL, + "Profile could not be added.\n"); + } + + return 0; +} + +static int +eth_mtr_meter_profile_delete_inline(struct rte_eth_dev *dev __rte_unused, + uint32_t meter_profile_id __rte_unused, + struct rte_mtr_error *error __rte_unused) +{ + struct pmd_internals *dev_priv = dev->data->dev_private; + + if (meter_profile_id >= flow_mtr_meter_policy_n_max()) + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "Profile id out of range\n"); + + flow_mtr_set_profile(dev_priv->flw_dev, meter_profile_id, 0, 0, 0, 0); + + return 0; +} + +static int +eth_mtr_meter_policy_add_inline(struct rte_eth_dev *dev, uint32_t policy_id, + struct rte_mtr_meter_policy_params *policy, + struct rte_mtr_error *error) +{ + struct pmd_internals *dev_priv = dev->data->dev_private; + + if (policy_id >= flow_mtr_meter_policy_n_max()) + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Policy id out of range\n"); + + const struct rte_flow_action *actions = + policy->actions[RTE_COLOR_GREEN]; + int green_action_supported = + (actions[0].type == RTE_FLOW_ACTION_TYPE_END) || + (actions[0].type == RTE_FLOW_ACTION_TYPE_VOID && + actions[1].type == RTE_FLOW_ACTION_TYPE_END) || + (actions[0].type == RTE_FLOW_ACTION_TYPE_PASSTHRU && + actions[1].type == RTE_FLOW_ACTION_TYPE_END); + + actions = policy->actions[RTE_COLOR_YELLOW]; + int yellow_action_supported = + actions[0].type == RTE_FLOW_ACTION_TYPE_DROP && + actions[1].type == RTE_FLOW_ACTION_TYPE_END; + + actions = policy->actions[RTE_COLOR_RED]; + int red_action_supported = actions[0].type == + RTE_FLOW_ACTION_TYPE_DROP && + actions[1].type == RTE_FLOW_ACTION_TYPE_END; + + if (green_action_supported == 0 || yellow_action_supported == 0 || + red_action_supported == 0) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, + "Unsupported meter policy actions\n"); + } + + if (flow_mtr_set_policy(dev_priv->flw_dev, policy_id, 1)) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, + "Policy could not be added\n"); + } + + return 0; +} + +static int +eth_mtr_meter_policy_delete_inline(struct rte_eth_dev *dev __rte_unused, + uint32_t policy_id __rte_unused, + struct rte_mtr_error *error __rte_unused) +{ + if (policy_id >= flow_mtr_meter_policy_n_max()) + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Policy id out of range\n"); + + return 0; +} + +static int eth_mtr_create_inline(struct rte_eth_dev *dev, uint32_t mtr_id, + struct rte_mtr_params *params, int shared, + struct rte_mtr_error *error) +{ + struct pmd_internals *dev_priv = dev->data->dev_private; + + if (params->use_prev_mtr_color != 0 || params->dscp_table != NULL) { + return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "Only color blind mode is supported\n"); + } + + uint64_t allowed_stats_mask = RTE_MTR_STATS_N_PKTS_GREEN | + RTE_MTR_STATS_N_BYTES_GREEN; + if ((params->stats_mask & ~allowed_stats_mask) != 0) { + return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "Requested color stats not supported\n"); + } + + if (params->meter_enable == 0) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "Disabled meters not supported\n"); + } + + if (shared == 0) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "Only shared mtrs are supported\n"); + } + + if (params->meter_profile_id >= flow_mtr_meter_policy_n_max()) + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "Profile id out of range\n"); + + if (params->meter_policy_id >= flow_mtr_meter_policy_n_max()) + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Policy id out of range\n"); + + if (mtr_id >= flow_mtr_meters_supported()) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "MTR id is out of range\n"); + } + + int res = flow_mtr_create_meter(dev_priv->flw_dev, mtr_id, + params->meter_profile_id, + params->meter_policy_id, + params->stats_mask); + + if (res) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Failed to offload to hardware\n"); + } + + return 0; +} + +static int eth_mtr_destroy_inline(struct rte_eth_dev *dev, uint32_t mtr_id, + struct rte_mtr_error *error __rte_unused) +{ + struct pmd_internals *dev_priv = dev->data->dev_private; + + if (mtr_id >= flow_mtr_meters_supported()) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "MTR id is out of range\n"); + } + + if (flow_mtr_destroy_meter(dev_priv->flw_dev, mtr_id)) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Failed to offload to hardware\n"); + } + + return 0; +} + +static int eth_mtr_stats_adjust_inline(struct rte_eth_dev *dev, uint32_t mtr_id, + uint64_t adjust_value, + struct rte_mtr_error *error) +{ + const uint64_t adjust_bit = 1ULL << 63; + struct pmd_internals *dev_priv = dev->data->dev_private; + + if (mtr_id >= flow_mtr_meters_supported()) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "MTR id is out of range\n"); + } + + if ((adjust_value & adjust_bit) == 0) { + return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "To adjust a MTR bucket value, bit 63 of \"stats_mask\" must be 1\n"); + } + + adjust_value &= adjust_bit - 1; + + if (adjust_value > (uint64_t)UINT32_MAX) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "Adjust value is out of range\n"); + } + + if (flm_mtr_adjust_stats(dev_priv->flw_dev, mtr_id, + (uint32_t)adjust_value)) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Failed to adjust offloaded MTR\n"); + } + + return 0; +} + +static int eth_mtr_stats_read_inline(struct rte_eth_dev *dev, uint32_t mtr_id, + struct rte_mtr_stats *stats, + uint64_t *stats_mask, int clear, + struct rte_mtr_error *error) +{ + struct pmd_internals *dev_priv = dev->data->dev_private; + + if (mtr_id >= flow_mtr_meters_supported()) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "MTR id is out of range\n"); + } + + memset(stats, 0x0, sizeof(struct rte_mtr_stats)); + flm_mtr_read_stats(dev_priv->flw_dev, mtr_id, stats_mask, + &stats->n_pkts[RTE_COLOR_GREEN], + &stats->n_bytes[RTE_COLOR_GREEN], clear); + + return 0; +} + +/* + ******************************************************************************* + * Ops setup + ******************************************************************************* + */ + +static const struct rte_mtr_ops mtr_ops_vswitch = { + .meter_profile_add = eth_meter_profile_add, + .meter_profile_delete = eth_meter_profile_delete, + .create = eth_mtr_create, + .destroy = eth_mtr_destroy, + .meter_enable = eth_meter_enable, + .meter_disable = eth_meter_disable, +}; + +static const struct rte_mtr_ops mtr_ops_inline = { + .capabilities_get = eth_mtr_capabilities_get_inline, + .meter_profile_add = eth_mtr_meter_profile_add_inline, + .meter_profile_delete = eth_mtr_meter_profile_delete_inline, + .create = eth_mtr_create_inline, + .destroy = eth_mtr_destroy_inline, + .meter_policy_add = eth_mtr_meter_policy_add_inline, + .meter_policy_delete = eth_mtr_meter_policy_delete_inline, + .stats_update = eth_mtr_stats_adjust_inline, + .stats_read = eth_mtr_stats_read_inline, +}; + +int eth_mtr_ops_get(struct rte_eth_dev *dev, void *ops) +{ + struct pmd_internals *internals = + (struct pmd_internals *)dev->data->dev_private; + ntdrv_4ga_t *p_nt_drv = &internals->p_drv->ntdrv; + enum fpga_info_profile profile = p_nt_drv->adapter_info.fpga_info.profile; + + switch (profile) { + case FPGA_INFO_PROFILE_VSWITCH: + *(const struct rte_mtr_ops **)ops = &mtr_ops_vswitch; + break; + case FPGA_INFO_PROFILE_INLINE: + *(const struct rte_mtr_ops **)ops = &mtr_ops_inline; + break; + case FPGA_INFO_PROFILE_UNKNOWN: + /* fallthrough */ + case FPGA_INFO_PROFILE_CAPTURE: + /* fallthrough */ + default: + NT_LOG(ERR, NTHW, + "" PCIIDENT_PRINT_STR + ": fpga profile not supported [%s:%u]\n", + PCIIDENT_TO_DOMAIN(p_nt_drv->pciident), + PCIIDENT_TO_BUSNR(p_nt_drv->pciident), + PCIIDENT_TO_DEVNR(p_nt_drv->pciident), + PCIIDENT_TO_FUNCNR(p_nt_drv->pciident), + __func__, __LINE__); + return -1; + } + + return 0; +} diff --git a/drivers/net/ntnic/ntnic_meter.h b/drivers/net/ntnic/ntnic_meter.h new file mode 100644 index 0000000000..9484c9ee20 --- /dev/null +++ b/drivers/net/ntnic/ntnic_meter.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTNIC_METER_H__ +#define __NTNIC_METER_H__ + +int eth_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *ops); + +#endif /* __NTNIC_METER_H__ */ diff --git a/drivers/net/ntnic/ntnic_vdpa.c b/drivers/net/ntnic/ntnic_vdpa.c new file mode 100644 index 0000000000..6372514527 --- /dev/null +++ b/drivers/net/ntnic/ntnic_vdpa.c @@ -0,0 +1,365 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ntnic_vf_vdpa.h" +#include "ntnic_vdpa.h" +#include "ntnic_ethdev.h" +#include "nt_util.h" +#include "ntlog.h" +#include "ntnic_vfio.h" + +#define MAX_PATH_LEN 128 +#define MAX_VDPA_PORTS 128UL + +struct vdpa_port { + char ifname[MAX_PATH_LEN]; + struct rte_vdpa_device *vdev; + int vid; + uint32_t index; + uint32_t host_id; + uint32_t rep_port; + int rxqs; + int txqs; + uint64_t flags; + struct rte_pci_addr addr; +}; + +static struct vdpa_port vport[MAX_VDPA_PORTS]; +static uint32_t nb_vpda_devcnt; + +static int nthw_vdpa_start(struct vdpa_port *vport); + +int nthw_vdpa_get_queue_id_info(struct rte_vdpa_device *vdpa_dev, int rx, + int queue_id, uint32_t *hw_index, + uint32_t *host_id, uint32_t *rep_port) +{ + uint32_t i; + + for (i = 0; i < nb_vpda_devcnt; i++) { + if (vport[i].vdev == vdpa_dev) { + if (rx) { + if (queue_id >= vport[i].rxqs) { + NT_LOG(ERR, VDPA, + "Failed: %s: Queue ID not configured. vDPA dev %p, rx queue_id %i, rxqs %i\n", + __func__, vdpa_dev, queue_id, + vport[i].rxqs); + return -1; + } + *hw_index = vport[i].index + queue_id; + } else { + if (queue_id >= vport[i].txqs) { + NT_LOG(ERR, VDPA, + "Failed: %s: Queue ID not configured. vDPA dev %p, tx queue_id %i, rxqs %i\n", + __func__, vdpa_dev, queue_id, + vport[i].rxqs); + return -1; + } + *hw_index = vport[i].index + queue_id; + } + + *host_id = vport[i].host_id; + *rep_port = vport[i].rep_port; + return 0; + } + } + + NT_LOG(ERR, VDPA, + "Failed: %s: Ask on vDPA dev %p, queue_id %i, nb_vpda_devcnt %i\n", + __func__, vdpa_dev, queue_id, nb_vpda_devcnt); + return -1; +} + +int nthw_vdpa_init(const struct rte_pci_device *vdev, + const char *backing_devname _unused, const char *socket_path, + uint32_t index, int rxqs, int txqs, uint32_t rep_port, + int *vhid) +{ + int ret; + uint32_t host_id = nt_vfio_vf_num(vdev); + + struct rte_vdpa_device *vdpa_dev = + rte_vdpa_find_device_by_name(vdev->name); + if (!vdpa_dev) { + NT_LOG(ERR, VDPA, "vDPA device with name %s - not found\n", + vdev->name); + return -1; + } + + vport[nb_vpda_devcnt].vdev = vdpa_dev; + vport[nb_vpda_devcnt].host_id = host_id; /* VF # */ + vport[nb_vpda_devcnt].index = index; /* HW ring index */ + vport[nb_vpda_devcnt].rep_port = rep_port; /* in port override on Tx */ + vport[nb_vpda_devcnt].rxqs = rxqs; + vport[nb_vpda_devcnt].txqs = txqs; + vport[nb_vpda_devcnt].addr = vdev->addr; + + vport[nb_vpda_devcnt].flags = RTE_VHOST_USER_CLIENT; + strlcpy(vport[nb_vpda_devcnt].ifname, socket_path, MAX_PATH_LEN); + + NT_LOG(INF, VDPA, + "vDPA%u: device %s (host_id %u), backing device %s, index %u, queues %i, rep port %u, ifname %s\n", + nb_vpda_devcnt, vdev->name, host_id, backing_devname, index, + rxqs, rep_port, vport[nb_vpda_devcnt].ifname); + + ret = nthw_vdpa_start(&vport[nb_vpda_devcnt]); + + *vhid = nb_vpda_devcnt; + nb_vpda_devcnt++; + return ret; +} + +void nthw_vdpa_close(void) +{ + uint32_t i; + + for (i = 0; i < MAX_VDPA_PORTS; i++) { + if (vport[i].ifname[0] != '\0') { + int ret; + char *socket_path = vport[i].ifname; + + ret = rte_vhost_driver_detach_vdpa_device(socket_path); + if (ret != 0) { + NT_LOG(ERR, VDPA, + "detach vdpa device failed: %s\n", + socket_path); + } + + ret = rte_vhost_driver_unregister(socket_path); + if (ret != 0) { + NT_LOG(ERR, VDPA, + "Fail to unregister vhost driver for %s.\n", + socket_path); + } + + vport[i].ifname[0] = '\0'; + return; + } + } +} + +#ifdef DUMP_VIRTIO_FEATURES +#define VIRTIO_F_NOTIFICATION_DATA 38 +#define NUM_FEATURES 40 +struct { + uint64_t id; + const char *name; +} virt_features[NUM_FEATURES] = { + { VIRTIO_NET_F_CSUM, "VIRTIO_NET_F_CSUM" }, + { VIRTIO_NET_F_GUEST_CSUM, "VIRTIO_NET_F_GUEST_CSUM" }, + { VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, + " VIRTIO_NET_F_CTRL_GUEST_OFFLOADS" + }, + { VIRTIO_NET_F_MTU, " VIRTIO_NET_F_MTU" }, + { VIRTIO_NET_F_MAC, " VIRTIO_NET_F_MAC" }, + { VIRTIO_NET_F_GSO, " VIRTIO_NET_F_GSO" }, + { VIRTIO_NET_F_GUEST_TSO4, " VIRTIO_NET_F_GUEST_TSO4" }, + { VIRTIO_NET_F_GUEST_TSO6, " VIRTIO_NET_F_GUEST_TSO6" }, + { VIRTIO_NET_F_GUEST_ECN, " VIRTIO_NET_F_GUEST_ECN" }, + { VIRTIO_NET_F_GUEST_UFO, " VIRTIO_NET_F_GUEST_UFO" }, + { VIRTIO_NET_F_HOST_TSO4, " VIRTIO_NET_F_HOST_TSO4" }, + { VIRTIO_NET_F_HOST_TSO6, " VIRTIO_NET_F_HOST_TSO6" }, + { VIRTIO_NET_F_HOST_ECN, " VIRTIO_NET_F_HOST_ECN" }, + { VIRTIO_NET_F_HOST_UFO, " VIRTIO_NET_F_HOST_UFO" }, + { VIRTIO_NET_F_MRG_RXBUF, " VIRTIO_NET_F_MRG_RXBUF" }, + { VIRTIO_NET_F_STATUS, " VIRTIO_NET_F_STATUS" }, + { VIRTIO_NET_F_CTRL_VQ, " VIRTIO_NET_F_CTRL_VQ" }, + { VIRTIO_NET_F_CTRL_RX, " VIRTIO_NET_F_CTRL_RX" }, + { VIRTIO_NET_F_CTRL_VLAN, " VIRTIO_NET_F_CTRL_VLAN" }, + { VIRTIO_NET_F_CTRL_RX_EXTRA, " VIRTIO_NET_F_CTRL_RX_EXTRA" }, + { VIRTIO_NET_F_GUEST_ANNOUNCE, " VIRTIO_NET_F_GUEST_ANNOUNCE" }, + { VIRTIO_NET_F_MQ, " VIRTIO_NET_F_MQ" }, + { VIRTIO_NET_F_CTRL_MAC_ADDR, " VIRTIO_NET_F_CTRL_MAC_ADDR" }, + { VIRTIO_NET_F_HASH_REPORT, " VIRTIO_NET_F_HASH_REPORT" }, + { VIRTIO_NET_F_RSS, " VIRTIO_NET_F_RSS" }, + { VIRTIO_NET_F_RSC_EXT, " VIRTIO_NET_F_RSC_EXT" }, + { VIRTIO_NET_F_STANDBY, " VIRTIO_NET_F_STANDBY" }, + { VIRTIO_NET_F_SPEED_DUPLEX, " VIRTIO_NET_F_SPEED_DUPLEX" }, + { VIRTIO_F_NOTIFY_ON_EMPTY, " VIRTIO_F_NOTIFY_ON_EMPTY" }, + { VIRTIO_F_ANY_LAYOUT, " VIRTIO_F_ANY_LAYOUT" }, + { VIRTIO_RING_F_INDIRECT_DESC, " VIRTIO_RING_F_INDIRECT_DESC" }, + { VIRTIO_F_VERSION_1, " VIRTIO_F_VERSION_1" }, + { VIRTIO_F_IOMMU_PLATFORM, " VIRTIO_F_IOMMU_PLATFORM" }, + { VIRTIO_F_RING_PACKED, " VIRTIO_F_RING_PACKED" }, + { VIRTIO_TRANSPORT_F_START, " VIRTIO_TRANSPORT_F_START" }, + { VIRTIO_TRANSPORT_F_END, " VIRTIO_TRANSPORT_F_END" }, + { VIRTIO_F_IN_ORDER, " VIRTIO_F_IN_ORDER" }, + { VIRTIO_F_ORDER_PLATFORM, " VIRTIO_F_ORDER_PLATFORM" }, + { VIRTIO_F_NOTIFICATION_DATA, " VIRTIO_F_NOTIFICATION_DATA" }, +}; + +static void dump_virtio_features(uint64_t features) +{ + int i; + + for (i = 0; i < NUM_FEATURES; i++) { + if ((1ULL << virt_features[i].id) == + (features & (1ULL << virt_features[i].id))) + printf("Virtio feature: %s\n", virt_features[i].name); + } +} +#endif + +static int nthw_vdpa_new_device(int vid) +{ + char ifname[MAX_PATH_LEN]; + uint64_t negotiated_features = 0; + unsigned int vhid = -1; + + rte_vhost_get_ifname(vid, ifname, sizeof(ifname)); + + for (vhid = 0; vhid < MAX_VDPA_PORTS; vhid++) { + if (strncmp(ifname, vport[vhid].ifname, MAX_PATH_LEN) == 0) { + vport[vhid].vid = vid; + break; + } + } + + if (vhid >= MAX_VDPA_PORTS) + return -1; + + int max_loops = 2000; + struct pmd_internals *intern; + + while ((intern = vp_vhid_instance_ready(vhid)) == NULL) { + usleep(1000); + if (--max_loops == 0) { + NT_LOG(INF, VDPA, + "FAILED CREATING (vhost could not get ready) New port %s, vDPA dev: %s\n", + ifname, vport[vhid].vdev->device->name); + return -1; + } + } + + /* set link up on virtual port */ + intern->vport_comm = VIRT_PORT_NEGOTIATED_NONE; + + /* Store ifname (vhost_path) */ + strlcpy(intern->vhost_path, ifname, MAX_PATH_LEN); + + NT_LOG(INF, VDPA, "New port %s, vDPA dev: %s\n", ifname, + vport[vhid].vdev->device->name); + rte_vhost_get_negotiated_features(vid, &negotiated_features); + NT_LOG(INF, VDPA, "Virtio Negotiated features %016lx\n", + negotiated_features); + +#ifdef DUMP_VIRTIO_FEATURES + dump_virtio_features(negotiated_features); +#endif + + if ((((negotiated_features & (1ULL << VIRTIO_F_IN_ORDER))) || + ((negotiated_features & (1ULL << VIRTIO_F_RING_PACKED))))) { + /* IN_ORDER negotiated - we can run HW-virtio directly (vDPA) */ + NT_LOG(INF, VDPA, "Running virtio in vDPA mode : %s %s\n", + (negotiated_features & (1ULL << VIRTIO_F_RING_PACKED)) ? + "\"Packed-Ring\"" : + "\"Split-Ring\"", + (negotiated_features & (1ULL << VIRTIO_F_IN_ORDER)) ? + "\"In-Order\"" : + "\"No In-Order Requested\""); + + intern->vport_comm = + (negotiated_features & (1ULL << VIRTIO_F_RING_PACKED)) ? + VIRT_PORT_NEGOTIATED_PACKED : + VIRT_PORT_NEGOTIATED_SPLIT; + } else { + NT_LOG(ERR, VDPA, "Incompatible virtio negotiated features.\n"); + return -1; + } + return 0; +} + +static void nthw_vdpa_destroy_device(int vid) +{ + char ifname[MAX_PATH_LEN]; + uint32_t i; + unsigned int vhid; + + rte_vhost_get_ifname(vid, ifname, sizeof(ifname)); + for (i = 0; i < MAX_VDPA_PORTS; i++) { + if (strcmp(ifname, vport[i].ifname) == 0) { + NT_LOG(INF, VDPA, "\ndestroy port %s, vDPA dev: %s\n", + ifname, vport[i].vdev->device->name); + break; + } + } + + struct pmd_internals *intern; + + /* set link down on virtual port */ + for (vhid = 0; vhid < MAX_VDPA_PORTS; vhid++) { + if (strncmp(ifname, vport[vhid].ifname, MAX_PATH_LEN) == 0) { + intern = vp_vhid_instance_ready(vhid); + if (intern) + intern->vport_comm = VIRT_PORT_NEGOTIATED_NONE; + break; + } + } +} + +static const struct rte_vhost_device_ops vdpa_devops = { + .new_device = nthw_vdpa_new_device, + .destroy_device = nthw_vdpa_destroy_device, +}; + +static int nthw_vdpa_start(struct vdpa_port *vport) +{ + int ret; + char *socket_path = vport->ifname; + + ret = rte_vhost_driver_register(socket_path, vport->flags); + if (ret != 0) { + NT_LOG(ERR, VDPA, "register driver failed: %s\n", socket_path); + return -1; + } + + ret = rte_vhost_driver_callback_register(socket_path, &vdpa_devops); + if (ret != 0) { + NT_LOG(ERR, VDPA, "register driver ops failed: %s\n", + socket_path); + return -1; + } + + ret = rte_vhost_driver_disable_features(socket_path, (1ULL << VIRTIO_NET_F_HOST_TSO4) | + (1ULL << VIRTIO_NET_F_HOST_TSO6) | + (1ULL << VIRTIO_NET_F_CSUM) | + (1ULL << VIRTIO_RING_F_EVENT_IDX) | + (1ULL << VIRTIO_RING_F_INDIRECT_DESC) | + (1ULL << VIRTIO_NET_F_HOST_UFO) | + (1ULL << VIRTIO_NET_F_HOST_ECN) | + (1ULL << VIRTIO_NET_F_GUEST_CSUM) | + (1ULL << VIRTIO_NET_F_GUEST_TSO4) | + (1ULL << VIRTIO_NET_F_GUEST_TSO6) | + (1ULL << VIRTIO_NET_F_GUEST_UFO) | + (1ULL << VIRTIO_NET_F_GUEST_ECN) | + (1ULL << VIRTIO_NET_F_CTRL_VQ) | + (1ULL << VIRTIO_NET_F_CTRL_RX) | + (1ULL << VIRTIO_NET_F_GSO) | + (1ULL << VIRTIO_NET_F_MTU)); + + if (ret != 0) { + NT_LOG(INF, VDPA, + "rte_vhost_driver_disable_features failed for vhost user client port: %s\n", + socket_path); + return -1; + } + + if (rte_vhost_driver_start(socket_path) < 0) { + NT_LOG(ERR, VDPA, "start vhost driver failed: %s\n", + socket_path); + return -1; + } + return 0; +} diff --git a/drivers/net/ntnic/ntnic_vdpa.h b/drivers/net/ntnic/ntnic_vdpa.h new file mode 100644 index 0000000000..7acc2c8e4b --- /dev/null +++ b/drivers/net/ntnic/ntnic_vdpa.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTNIC_VDPA_H_ +#define _NTNIC_VDPA_H_ + +#include + +int nthw_vdpa_get_queue_id_info(struct rte_vdpa_device *vdpa_dev, int rx, + int queue_id, uint32_t *hw_index, + uint32_t *host_id, uint32_t *rep_port); + +int nthw_vdpa_init(const struct rte_pci_device *vdev, + const char *backing_devname, const char *socket_path, + uint32_t index, int rxqs, int txqs, uint32_t rep_port, + int *vhid); + +void nthw_vdpa_close(void); + +#endif /* _NTNIC_VDPA_H_ */ diff --git a/drivers/net/ntnic/ntnic_vf.c b/drivers/net/ntnic/ntnic_vf.c new file mode 100644 index 0000000000..0724b040c3 --- /dev/null +++ b/drivers/net/ntnic/ntnic_vf.c @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ntnic_ethdev.h" +#include "ntnic_vf.h" +#include "ntnic_vf_vdpa.h" +#include "nt_util.h" +#include "ntlog.h" + +#define NT_HW_NAPATECH_PCI_VENDOR_ID (0x18F4) +#define NT_HW_NAPATECH_PCI_DEVICE_ID_NT200A02_VF (0x051A) +#define NT_HW_NAPATECH_PCI_DEVICE_ID_NT50B01_VF (0x051B) + +static const char *get_adapter_name(struct rte_pci_device *pci_dev) +{ + switch (pci_dev->id.vendor_id) { + case NT_HW_NAPATECH_PCI_VENDOR_ID: + switch (pci_dev->id.device_id) { + case NT_HW_NAPATECH_PCI_DEVICE_ID_NT200A02_VF: + return "NT200A02"; + case NT_HW_NAPATECH_PCI_DEVICE_ID_NT50B01_VF: + return "NT50B01"; + } + break; + } + + return "Unknown"; +} + +int nt_vf_pci_probe(struct rte_pci_driver *pci_drv, + struct rte_pci_device *pci_dev) +{ + const char *adapter_name _unused = get_adapter_name(pci_dev); + + NT_LOG(INF, VDPA, "Probe %s VF : %02x:%02x:%i\n", adapter_name, + pci_dev->addr.bus, pci_dev->addr.devid, pci_dev->addr.function); + + /* Create vDPA device for the virtual function interface.*/ + + if (ntvf_vdpa_pci_probe(pci_drv, pci_dev) != 0) + return -1; + + return nthw_create_vf_interface_dpdk(pci_dev); +} + +int nt_vf_pci_remove(struct rte_pci_device *pci_dev) +{ + if (ntvf_vdpa_pci_remove(pci_dev) != 0) + return -1; + + return nthw_remove_vf_interface_dpdk(pci_dev); +} + +static const struct rte_pci_id pci_id_nt_vf_map[] = { + { RTE_PCI_DEVICE(NT_HW_NAPATECH_PCI_VENDOR_ID, + NT_HW_NAPATECH_PCI_DEVICE_ID_NT200A02_VF) + }, + { RTE_PCI_DEVICE(NT_HW_NAPATECH_PCI_VENDOR_ID, + NT_HW_NAPATECH_PCI_DEVICE_ID_NT50B01_VF) + }, + { .vendor_id = 0, /* sentinel */ }, +}; + +static struct rte_pci_driver rte_nt_vf = { + .id_table = pci_id_nt_vf_map, + .drv_flags = 0, + .probe = nt_vf_pci_probe, + .remove = nt_vf_pci_remove, +}; + +RTE_PMD_REGISTER_PCI(net_nt_vf, rte_nt_vf); +RTE_PMD_REGISTER_PCI_TABLE(net_nt_vf, pci_id_nt_vf_map); +RTE_PMD_REGISTER_KMOD_DEP(net_nt_vf, "* vfio-pci"); diff --git a/drivers/net/ntnic/ntnic_vf.h b/drivers/net/ntnic/ntnic_vf.h new file mode 100644 index 0000000000..84be3bd71f --- /dev/null +++ b/drivers/net/ntnic/ntnic_vf.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTNIC_VF_H_ +#define _NTNIC_VF_H_ + +#include "rte_bus_pci.h" + +int nt_vf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, + struct rte_pci_device *pci_dev); +int nt_vf_pci_remove(struct rte_pci_device *pci_dev __rte_unused); + +int get_container_fd(int vf_num); +int close_vf_mem_mapping(int vf_num); + +#endif /* _NTNIC_VF_H_ */ diff --git a/drivers/net/ntnic/ntnic_vf_vdpa.c b/drivers/net/ntnic/ntnic_vf_vdpa.c new file mode 100644 index 0000000000..c520a43c44 --- /dev/null +++ b/drivers/net/ntnic/ntnic_vf_vdpa.c @@ -0,0 +1,1246 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ntdrv_4ga.h" +#include "ntnic_ethdev.h" +#include "ntnic_vdpa.h" +#include "ntnic_vf_vdpa.h" +#include "ntnic_vf.h" +#include "ntnic_vfio.h" +#include "ntnic_dbsconfig.h" +#include "ntlog.h" + +#define NTVF_VDPA_MAX_QUEUES (MAX_QUEUES) +#define NTVF_VDPA_MAX_INTR_VECTORS 8 + +#if RTE_VERSION_NUM(23, 3, 0, 99) > RTE_VERSION +#define NTVF_VDPA_SUPPORTED_PROTOCOL_FEATURES \ + ((1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK) | \ + (1ULL << VHOST_USER_PROTOCOL_F_SLAVE_REQ) | \ + (1ULL << VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD) | \ + (1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) | \ + (1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD) | \ + (1ULL << VHOST_USER_PROTOCOL_F_MQ)) +#else +#define NTVF_VDPA_SUPPORTED_PROTOCOL_FEATURES \ + ((1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK) | \ + (1ULL << VHOST_USER_PROTOCOL_F_BACKEND_REQ) | \ + (1ULL << VHOST_USER_PROTOCOL_F_BACKEND_SEND_FD) | \ + (1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) | \ + (1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD) | \ + (1ULL << VHOST_USER_PROTOCOL_F_MQ)) +#endif + +#define NTVF_VIRTIO_NET_SUPPORTED_FEATURES \ + ((1ULL << VIRTIO_F_ANY_LAYOUT) | (1ULL << VIRTIO_F_VERSION_1) | \ + (1ULL << VHOST_F_LOG_ALL) | (1ULL << VIRTIO_NET_F_MRG_RXBUF) | \ + (1ULL << VIRTIO_F_IOMMU_PLATFORM) | (1ULL << VIRTIO_F_IN_ORDER) | \ + (1ULL << VIRTIO_F_RING_PACKED) | \ + (1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) | \ + (1ULL << VHOST_USER_F_PROTOCOL_FEATURES)) + +static int ntvf_vdpa_set_vring_state(int vid, int vring, int state); + +struct vring_info { + uint64_t desc; + uint64_t avail; + uint64_t used; + uint16_t size; + + uint16_t last_avail_idx; + uint16_t last_used_idx; + + int vq_type; + struct nthw_virt_queue *p_vq; + + int enable; +}; + +struct ntvf_vdpa_hw { + uint64_t negotiated_features; + + uint8_t nr_vring; + + struct vring_info vring[NTVF_VDPA_MAX_QUEUES * 2]; +}; + +struct ntvf_vdpa_internal { + struct rte_pci_device *pdev; + struct rte_vdpa_device *vdev; + + int vfio_container_fd; + int vfio_group_fd; + int vfio_dev_fd; + + int vid; + + uint32_t outport; + + uint16_t max_queues; + + uint64_t features; + + struct ntvf_vdpa_hw hw; + + volatile atomic_int_fast32_t started; + volatile atomic_int_fast32_t dev_attached; + volatile atomic_int_fast32_t running; + + rte_spinlock_t lock; + + volatile atomic_int_fast32_t dma_mapped; + volatile atomic_int_fast32_t intr_enabled; +}; + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + +#define NTVF_USED_RING_LEN(size) \ + ((size) * sizeof(struct vring_used_elem) + sizeof(uint16_t) * 3) + +#define NTVF_MEDIATED_VRING 0x210000000000 + +struct internal_list { + TAILQ_ENTRY(internal_list) next; + struct ntvf_vdpa_internal *internal; +}; + +TAILQ_HEAD(internal_list_head, internal_list); + +static struct internal_list_head internal_list = + TAILQ_HEAD_INITIALIZER(internal_list); + +static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER; + +int ntvf_vdpa_logtype; + +static struct internal_list * +find_internal_resource_by_vdev(struct rte_vdpa_device *vdev) +{ + int found = 0; + struct internal_list *list; + + NT_LOG(DBG, VDPA, "%s: vDPA dev=%p\n", __func__, vdev); + + pthread_mutex_lock(&internal_list_lock); + + TAILQ_FOREACH(list, &internal_list, next) + { + if (vdev == list->internal->vdev) { + found = 1; + break; + } + } + + pthread_mutex_unlock(&internal_list_lock); + + if (!found) + return NULL; + + return list; +} + +static struct internal_list * +ntvf_vdpa_find_internal_resource_by_dev(const struct rte_pci_device *pdev) +{ + int found = 0; + struct internal_list *list; + + NT_LOG(DBG, VDPA, "%s: [%s:%u]\n", __func__, __FILE__, __LINE__); + + pthread_mutex_lock(&internal_list_lock); + + TAILQ_FOREACH(list, &internal_list, next) + { + if (pdev == list->internal->pdev) { + found = 1; + break; + } + } + + pthread_mutex_unlock(&internal_list_lock); + + if (!found) + return NULL; + + return list; +} + +static int ntvf_vdpa_vfio_setup(struct ntvf_vdpa_internal *internal) +{ + int vfio; + + LOG_FUNC_ENTER(); + + internal->vfio_dev_fd = -1; + internal->vfio_group_fd = -1; + internal->vfio_container_fd = -1; + + vfio = nt_vfio_setup(internal->pdev); + if (vfio == -1) { + NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__, __LINE__); + return -1; + } + internal->vfio_container_fd = nt_vfio_get_container_fd(vfio); + internal->vfio_group_fd = nt_vfio_get_group_fd(vfio); + internal->vfio_dev_fd = nt_vfio_get_dev_fd(vfio); + return 0; +} + +static int ntvf_vdpa_dma_map(struct ntvf_vdpa_internal *internal, int do_map) +{ + uint32_t i; + int ret = 0; + struct rte_vhost_memory *mem = NULL; + int vf_num = nt_vfio_vf_num(internal->pdev); + + LOG_FUNC_ENTER(); + + NT_LOG(DBG, VDPA, "%s: vid=%d vDPA dev=%p\n", __func__, internal->vid, + internal->vdev); + + if ((do_map && atomic_load(&internal->dma_mapped)) || + (!do_map && !atomic_load(&internal->dma_mapped))) { + ret = -1; + goto exit; + } + ret = rte_vhost_get_mem_table(internal->vid, &mem); + if (ret < 0) { + NT_LOG(ERR, VDPA, "failed to get VM memory layout.\n"); + goto exit; + } + + for (i = 0; i < mem->nregions; i++) { + struct rte_vhost_mem_region *reg = &mem->regions[i]; + + NT_LOG(INF, VDPA, + "%s, region %u: HVA 0x%" PRIX64 ", GPA 0xllx, size 0x%" PRIX64 ".\n", + (do_map ? "DMA map" : "DMA unmap"), i, + reg->host_user_addr, reg->guest_phys_addr, reg->size); + + if (do_map) { + ret = nt_vfio_dma_map_vdpa(vf_num, reg->host_user_addr, + reg->guest_phys_addr, + reg->size); + if (ret < 0) { + NT_LOG(ERR, VDPA, "%s: DMA map failed.\n", + __func__); + goto exit; + } + atomic_store(&internal->dma_mapped, 1); + } else { + ret = nt_vfio_dma_unmap_vdpa(vf_num, + reg->host_user_addr, + reg->guest_phys_addr, + reg->size); + if (ret < 0) { + NT_LOG(ERR, VDPA, "%s: DMA unmap failed.\n", __func__); + goto exit; + } + atomic_store(&internal->dma_mapped, 0); + } + } + +exit: + if (mem) + free(mem); + + LOG_FUNC_LEAVE(); + return ret; +} + +static uint64_t _hva_to_gpa(int vid, uint64_t hva) +{ + struct rte_vhost_memory *mem = NULL; + struct rte_vhost_mem_region *reg; + uint64_t gpa = 0; + uint32_t i; + + if (rte_vhost_get_mem_table(vid, &mem) < 0) + goto exit; + + for (i = 0; i < mem->nregions; i++) { + reg = &mem->regions[i]; + if (hva >= reg->host_user_addr && + hva < reg->host_user_addr + reg->size) { + gpa = hva - reg->host_user_addr + reg->guest_phys_addr; + break; + } + } + +exit: + if (mem) + free(mem); + + return gpa; +} + +static int ntvf_vdpa_create_vring(struct ntvf_vdpa_internal *internal, + int vring) +{ + struct ntvf_vdpa_hw *hw = &internal->hw; + struct rte_vhost_vring vq; + int vid = internal->vid; + uint64_t gpa; + + rte_vhost_get_vhost_vring(vid, vring, &vq); + + NT_LOG(INF, VDPA, "%s: idx=%d: vq.desc %p\n", __func__, vring, vq.desc); + + gpa = _hva_to_gpa(vid, (uint64_t)(uintptr_t)vq.desc); + if (gpa == 0) { + NT_LOG(ERR, VDPA, + "%s: idx=%d: failed to get GPA for descriptor ring: vq.desc %p\n", + __func__, vring, vq.desc); + return -1; + } + hw->vring[vring].desc = gpa; + + gpa = _hva_to_gpa(vid, (uint64_t)(uintptr_t)vq.avail); + if (gpa == 0) { + NT_LOG(ERR, VDPA, + "%s: idx=%d: failed to get GPA for available ring\n", + __func__, vring); + return -1; + } + hw->vring[vring].avail = gpa; + + gpa = _hva_to_gpa(vid, (uint64_t)(uintptr_t)vq.used); + if (gpa == 0) { + NT_LOG(ERR, VDPA, "%s: idx=%d: fail to get GPA for used ring\n", + __func__, vring); + return -1; + } + + hw->vring[vring].used = gpa; + hw->vring[vring].size = vq.size; + + rte_vhost_get_vring_base(vid, vring, &hw->vring[vring].last_avail_idx, + &hw->vring[vring].last_used_idx); + + /* Prevent multiple creations */ + { + const int index = vring; + uint32_t hw_index = 0; + uint32_t host_id = 0; + const uint32_t header = 0; /* 0=VirtIO hdr, 1=NT virtio hdr */ + uint32_t vport = 0; + uint32_t port = internal->outport; + struct vring_info *p_vr_inf = &hw->vring[vring]; + nthw_dbs_t *p_nthw_dbs = get_pdbs_from_pci(internal->pdev->addr); + + int res = nthw_vdpa_get_queue_id_info(internal->vdev, + !(vring & 1), vring >> 1, + &hw_index, &host_id, + &vport); + if (res) { + NT_LOG(ERR, VDPA, "HW info received failed\n"); + p_vr_inf->p_vq = NULL; /* Failed to create the vring */ + return res; + } + + if (!(vring & 1)) { + NT_LOG(DBG, VDPA, + "Rx: idx %u, host_id %u, vport %u, queue %i\n", + hw_index, host_id, vport, vring >> 1); + } else { + NT_LOG(DBG, VDPA, + "Tx: idx %u, host_id %u, vport %u, queue %i\n", + hw_index, host_id, vport, vring >> 1); + } + NT_LOG(DBG, VDPA, + "%s: idx=%d: avail=%p used=%p desc=%p: %X: %d %d %d\n", + __func__, index, (void *)p_vr_inf->avail, + (void *)p_vr_inf->used, (void *)p_vr_inf->desc, + p_vr_inf->size, host_id, port, header); + + if ((hw->negotiated_features & (1ULL << VIRTIO_F_IN_ORDER)) || + (hw->negotiated_features & + (1ULL << VIRTIO_F_RING_PACKED))) { + int res; + + NT_LOG(DBG, VDPA, + "%s: idx=%d: feature VIRTIO_F_IN_ORDER is set: 0x%016lX\n", + __func__, index, hw->negotiated_features); + + if (!(vring & 1)) { + struct nthw_virt_queue *rx_vq; + + uint16_t start_idx = + hw->vring[vring].last_avail_idx; + uint16_t next_ptr = + (start_idx & 0x7fff) % vq.size; + + /* disable doorbell not needed by FPGA */ + ((struct pvirtq_event_suppress *)vq.used) + ->flags = RING_EVENT_FLAGS_DISABLE; + rte_wmb(); + if (hw->negotiated_features & + (1ULL << VIRTIO_F_RING_PACKED)) { + NT_LOG(DBG, VDPA, + "Rx: hw_index %u, host_id %u, start_idx %u, header %u, vring %u, vport %u\n", + hw_index, host_id, start_idx, + header, vring, vport); + /* irq_vector 1,3,5... for Rx we support max 8 pr VF */ + rx_vq = nthw_setup_rx_virt_queue(p_nthw_dbs, + hw_index, start_idx, + next_ptr, + (void *)p_vr_inf + ->avail, /* -> driver_event */ + (void *)p_vr_inf + ->used, /* -> device_event */ + (void *)p_vr_inf->desc, + p_vr_inf->size, host_id, header, + PACKED_RING, + vring + 1); + + } else { + rx_vq = nthw_setup_rx_virt_queue(p_nthw_dbs, + hw_index, start_idx, + next_ptr, + (void *)p_vr_inf->avail, + (void *)p_vr_inf->used, + (void *)p_vr_inf->desc, + p_vr_inf->size, host_id, header, + SPLIT_RING, + -1); /* no interrupt enabled */ + } + + p_vr_inf->p_vq = rx_vq; + p_vr_inf->vq_type = 0; + res = (rx_vq ? 0 : -1); + if (res == 0) + register_release_virtqueue_info(rx_vq, + 1, 0); + + NT_LOG(DBG, VDPA, "[%i] Rx Queue size %i\n", + hw_index, p_vr_inf->size); + } else if (vring & 1) { + /* + * transmit virt queue + */ + struct nthw_virt_queue *tx_vq; + uint16_t start_idx = + hw->vring[vring].last_avail_idx; + uint16_t next_ptr; + + if (hw->negotiated_features & + (1ULL << VIRTIO_F_RING_PACKED)) { + next_ptr = + (start_idx & 0x7fff) % vq.size; + + /* disable doorbell needs from FPGA */ + ((struct pvirtq_event_suppress *)vq.used) + ->flags = + RING_EVENT_FLAGS_DISABLE; + rte_wmb(); + tx_vq = nthw_setup_tx_virt_queue(p_nthw_dbs, + hw_index, start_idx, + next_ptr, + (void *)p_vr_inf->avail, /* driver_event */ + (void *)p_vr_inf->used, /* device_event */ + (void *)p_vr_inf->desc, + p_vr_inf->size, host_id, port, + vport, header, PACKED_RING, + vring + 1, /* interrupt 2,4,6... */ + !!(hw->negotiated_features & + (1ULL << VIRTIO_F_IN_ORDER))); + + } else { + /* + * In Live Migration restart scenario: + * This only works if no jumbo packets has been send from VM + * on the LM source sideю This pointer points to the next + * free descr and may be pushed ahead by next flag and if + * so, this pointer calculation is incorrect + * + * NOTE: THEREFORE, THIS DOES NOT WORK WITH JUMBO PACKETS + * SUPPORT IN VM + */ + next_ptr = + (start_idx & 0x7fff) % vq.size; + tx_vq = nthw_setup_tx_virt_queue(p_nthw_dbs, + hw_index, start_idx, + next_ptr, + (void *)p_vr_inf->avail, + (void *)p_vr_inf->used, + (void *)p_vr_inf->desc, + p_vr_inf->size, host_id, port, + vport, header, SPLIT_RING, + -1, /* no interrupt enabled */ + IN_ORDER); + } + + p_vr_inf->p_vq = tx_vq; + p_vr_inf->vq_type = 1; + res = (tx_vq ? 0 : -1); + if (res == 0) + register_release_virtqueue_info(tx_vq, + 0, 0); + + NT_LOG(DBG, VDPA, "[%i] Tx Queue size %i\n", + hw_index, p_vr_inf->size); + } else { + NT_LOG(ERR, VDPA, + "%s: idx=%d: unexpected index: %d\n", + __func__, index, vring); + res = -1; + } + if (res != 0) { + NT_LOG(ERR, VDPA, + "%s: idx=%d: vring error: res=%d\n", + __func__, index, res); + } + + } else { + NT_LOG(WRN, VDPA, + "%s: idx=%d: for SPLIT RING: feature VIRTIO_F_IN_ORDER is *NOT* set: 0x%016lX\n", + __func__, index, hw->negotiated_features); + return 0; + } + } + + return 0; +} + +static int ntvf_vdpa_start(struct ntvf_vdpa_internal *internal) +{ + enum fpga_info_profile fpga_profile = + get_fpga_profile_from_pci(internal->pdev->addr); + struct ntvf_vdpa_hw *hw = &internal->hw; + int vid; + + LOG_FUNC_ENTER(); + + vid = internal->vid; + hw->nr_vring = rte_vhost_get_vring_num(vid); + rte_vhost_get_negotiated_features(vid, &hw->negotiated_features); + + if (fpga_profile == FPGA_INFO_PROFILE_INLINE) { + NT_LOG(INF, VDPA, "%s: Number of VRINGs=%u\n", __func__, + hw->nr_vring); + + for (int i = 0; i < hw->nr_vring && i < 2; i++) { + if (!hw->vring[i].enable) { + ntvf_vdpa_dma_map(internal, 1); + ntvf_vdpa_create_vring(internal, i); + if (hw->vring[i].desc && hw->vring[i].p_vq) { + if (hw->vring[i].vq_type == 0) + nthw_enable_rx_virt_queue(hw->vring[i].p_vq); + else + nthw_enable_tx_virt_queue(hw->vring[i].p_vq); + hw->vring[i].enable = 1; + } + } + } + } else { + /* + * Initially vring 0 must be enabled/created here - it is not later + * enabled in vring state + */ + if (!hw->vring[0].enable) { + ntvf_vdpa_dma_map(internal, 1); + ntvf_vdpa_create_vring(internal, 0); + hw->vring[0].enable = 1; + } + } + + LOG_FUNC_LEAVE(); + return 0; +} + +static int ntvf_vdpa_stop(struct ntvf_vdpa_internal *internal) +{ + struct ntvf_vdpa_hw *hw = &internal->hw; + uint64_t features; + uint32_t i; + int vid; + int res; + + LOG_FUNC_ENTER(); + + vid = internal->vid; + + for (i = 0; i < hw->nr_vring; i++) { + rte_vhost_set_vring_base(vid, i, hw->vring[i].last_avail_idx, + hw->vring[i].last_used_idx); + } + + rte_vhost_get_negotiated_features(vid, &features); + + for (i = 0; i < hw->nr_vring; i++) { + struct vring_info *p_vr_inf = &hw->vring[i]; + + if ((hw->negotiated_features & (1ULL << VIRTIO_F_IN_ORDER)) || + (hw->negotiated_features & + (1ULL << VIRTIO_F_RING_PACKED))) { + NT_LOG(DBG, VDPA, + "%s: feature VIRTIO_F_IN_ORDER is set: 0x%016lX\n", + __func__, hw->negotiated_features); + if (p_vr_inf->vq_type == 0) { + de_register_release_virtqueue_info(p_vr_inf->p_vq); + res = nthw_release_rx_virt_queue(p_vr_inf->p_vq); + } else if (p_vr_inf->vq_type == 1) { + de_register_release_virtqueue_info(p_vr_inf->p_vq); + res = nthw_release_tx_virt_queue(p_vr_inf->p_vq); + } else { + NT_LOG(ERR, VDPA, + "%s: vring #%d: unknown type %d\n", + __func__, i, p_vr_inf->vq_type); + res = -1; + } + if (res != 0) { + NT_LOG(ERR, VDPA, "%s: vring #%d: res=%d\n", + __func__, i, res); + } + } else { + NT_LOG(WRN, VDPA, + "%s: feature VIRTIO_F_IN_ORDER is *NOT* set: 0x%016lX\n", + __func__, hw->negotiated_features); + } + p_vr_inf->desc = 0UL; + } + + if (RTE_VHOST_NEED_LOG(features)) { + NT_LOG(WRN, VDPA, + "%s: vid %d: vhost logging feature needed - currently not supported\n", + __func__, vid); + } + + LOG_FUNC_LEAVE(); + return 0; +} + +#define MSIX_IRQ_SET_BUF_LEN \ + (sizeof(struct vfio_irq_set) + \ + sizeof(int) * NTVF_VDPA_MAX_QUEUES * 2 + 1) + +static int ntvf_vdpa_enable_vfio_intr(struct ntvf_vdpa_internal *internal) +{ + int ret; + uint32_t i, nr_vring; + char irq_set_buf[MSIX_IRQ_SET_BUF_LEN]; + struct vfio_irq_set *irq_set; + int *fd_ptr; + struct rte_vhost_vring vring; + + if (atomic_load(&internal->intr_enabled)) + return 0; + + LOG_FUNC_ENTER(); + vring.callfd = -1; + + nr_vring = rte_vhost_get_vring_num(internal->vid); + + NT_LOG(INF, VDPA, + "Enable VFIO interrupt MSI-X num rings %i on VID %i (%02x:%02x.%x)\n", + nr_vring, internal->vid, internal->pdev->addr.bus, + internal->pdev->addr.devid, internal->pdev->addr.function); + + if (nr_vring + 1 > NTVF_VDPA_MAX_INTR_VECTORS) { + NT_LOG(WRN, VDPA, + "Can't enable MSI interrupts. Too many vectors requested: " + "%i (max: %i) only poll mode drivers will work", + nr_vring + 1, NTVF_VDPA_MAX_INTR_VECTORS); + /* + * Return success, because polling drivers in VM still works without + * interrupts (i.e. DPDK PMDs) + */ + return 0; + } + + irq_set = (struct vfio_irq_set *)irq_set_buf; + irq_set->argsz = sizeof(irq_set_buf); + irq_set->count = nr_vring + 1; + irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | + VFIO_IRQ_SET_ACTION_TRIGGER; + irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX; + irq_set->start = 0; + fd_ptr = (int *)&irq_set->data; + + fd_ptr[RTE_INTR_VEC_ZERO_OFFSET] = internal->pdev->intr_handle->fd; + + for (i = 0; i < nr_vring; i += 2) { + rte_vhost_get_vhost_vring(internal->vid, i, &vring); + fd_ptr[RTE_INTR_VEC_RXTX_OFFSET + i] = vring.callfd; + + rte_vhost_get_vhost_vring(internal->vid, i + 1, &vring); + fd_ptr[RTE_INTR_VEC_RXTX_OFFSET + i + 1] = vring.callfd; + } + + ret = ioctl(internal->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set); + if (ret) { + NT_LOG(ERR, VDPA, "Error enabling MSI-X interrupts: %s", + strerror(errno)); + return -1; + } + + atomic_store(&internal->intr_enabled, 1); + + LOG_FUNC_LEAVE(); + return 0; +} + +static int ntvf_vdpa_disable_vfio_intr(struct ntvf_vdpa_internal *internal) +{ + int ret; + char irq_set_buf[MSIX_IRQ_SET_BUF_LEN]; + struct vfio_irq_set *irq_set; + int len; + + if (!atomic_load(&internal->intr_enabled)) + return 0; + LOG_FUNC_ENTER(); + + NT_LOG(INF, VDPA, "Disable VFIO interrupt on VID %i (%02x:%02x.%x)\n", + internal->vid, internal->pdev->addr.bus, + internal->pdev->addr.devid, internal->pdev->addr.function); + + len = sizeof(struct vfio_irq_set); + irq_set = (struct vfio_irq_set *)irq_set_buf; + irq_set->argsz = len; + irq_set->count = 0; + irq_set->flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER; + irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX; + irq_set->start = 0; + + ret = ioctl(internal->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set); + if (ret) { + NT_LOG(ERR, VDPA, "Error disabling MSI-X interrupts: %s", + strerror(errno)); + return -1; + } + + atomic_store(&internal->intr_enabled, 0); + + LOG_FUNC_LEAVE(); + return 0; +} + +static int ntvf_vdpa_update_datapath(struct ntvf_vdpa_internal *internal) +{ + int ret; + + LOG_FUNC_ENTER(); + + rte_spinlock_lock(&internal->lock); + + if (!atomic_load(&internal->running) && + (atomic_load(&internal->started) && + atomic_load(&internal->dev_attached))) { + NT_LOG(DBG, VDPA, "%s: [%s:%u] start\n", __func__, __FILE__, + __LINE__); + + ret = ntvf_vdpa_start(internal); + if (ret) { + NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__, + __LINE__); + goto err; + } + + atomic_store(&internal->running, 1); + } else if (atomic_load(&internal->running) && + (!atomic_load(&internal->started) || + !atomic_load(&internal->dev_attached))) { + NT_LOG(DBG, VDPA, "%s: stop\n", __func__); + + ret = ntvf_vdpa_stop(internal); + if (ret) { + NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__, + __LINE__); + goto err; + } + + ret = ntvf_vdpa_disable_vfio_intr(internal); + if (ret) { + goto err; + NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__, + __LINE__); + } + + ret = ntvf_vdpa_dma_map(internal, 0); + if (ret) { + NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__, + __LINE__); + goto err; + } + + atomic_store(&internal->running, 0); + } else { + NT_LOG(INF, VDPA, "%s: unhandled state [%s:%u]\n", __func__, + __FILE__, __LINE__); + } + + rte_spinlock_unlock(&internal->lock); + LOG_FUNC_LEAVE(); + return 0; + +err: + rte_spinlock_unlock(&internal->lock); + NT_LOG(ERR, VDPA, "%s: leave [%s:%u]\n", __func__, __FILE__, __LINE__); + return ret; +} + +static int ntvf_vdpa_dev_config(int vid) +{ + struct rte_vdpa_device *vdev; + struct internal_list *list; + struct ntvf_vdpa_internal *internal; + + LOG_FUNC_ENTER(); + + vdev = rte_vhost_get_vdpa_device(vid); + list = find_internal_resource_by_vdev(vdev); + if (list == NULL) { + NT_LOG(ERR, VDPA, "Invalid vDPA device: %p", vdev); + return -1; + } + + internal = list->internal; + internal->vid = vid; + + atomic_store(&internal->dev_attached, 1); + + ntvf_vdpa_update_datapath(internal); + + LOG_FUNC_LEAVE(); + return 0; +} + +static int ntvf_vdpa_dev_close(int vid) +{ + struct rte_vdpa_device *vdev; + struct internal_list *list; + struct ntvf_vdpa_internal *internal; + + LOG_FUNC_ENTER(); + + vdev = rte_vhost_get_vdpa_device(vid); + list = find_internal_resource_by_vdev(vdev); + if (list == NULL) { + NT_LOG(ERR, VDPA, "Invalid vDPA device: %p", vdev); + return -1; + } + + internal = list->internal; + + atomic_store(&internal->dev_attached, 0); + ntvf_vdpa_update_datapath(internal); + + /* Invalidate the virt queue pointers */ + uint32_t i; + struct ntvf_vdpa_hw *hw = &internal->hw; + + for (i = 0; i < hw->nr_vring; i++) + hw->vring[i].p_vq = NULL; + + LOG_FUNC_LEAVE(); + return 0; +} + +static int ntvf_vdpa_set_features(int vid) +{ + uint64_t features; + struct rte_vdpa_device *vdev; + struct internal_list *list; + + LOG_FUNC_ENTER(); + + vdev = rte_vhost_get_vdpa_device(vid); + list = find_internal_resource_by_vdev(vdev); + if (list == NULL) { + NT_LOG(ERR, VDPA, "Invalid vDPA device: %p", vdev); + return -1; + } + + rte_vhost_get_negotiated_features(vid, &features); + NT_LOG(DBG, VDPA, "%s: vid %d: vDPA dev %p: features=0x%016lX\n", + __func__, vid, vdev, features); + + if (!RTE_VHOST_NEED_LOG(features)) + return 0; + + NT_LOG(INF, VDPA, + "%s: Starting Live Migration for vid=%d vDPA dev=%p\n", __func__, + vid, vdev); + + /* Relay core feature not present. We cannot do live migration then. */ + NT_LOG(ERR, VDPA, + "%s: Live Migration not possible. Relay core feature required.\n", + __func__); + return -1; +} + +static int ntvf_vdpa_get_vfio_group_fd(int vid) +{ + struct rte_vdpa_device *vdev; + struct internal_list *list; + + LOG_FUNC_ENTER(); + + vdev = rte_vhost_get_vdpa_device(vid); + list = find_internal_resource_by_vdev(vdev); + if (list == NULL) { + NT_LOG(ERR, VDPA, "Invalid vDPA device: %p", vdev); + return -1; + } + + LOG_FUNC_LEAVE(); + return list->internal->vfio_group_fd; +} + +static int ntvf_vdpa_get_vfio_device_fd(int vid) +{ + struct rte_vdpa_device *vdev; + struct internal_list *list; + + LOG_FUNC_ENTER(); + + vdev = rte_vhost_get_vdpa_device(vid); + list = find_internal_resource_by_vdev(vdev); + if (list == NULL) { + NT_LOG(ERR, VDPA, "Invalid vDPA device: %p", vdev); + return -1; + } + + LOG_FUNC_LEAVE(); + return list->internal->vfio_dev_fd; +} + +static int ntvf_vdpa_get_queue_num(struct rte_vdpa_device *vdev, + uint32_t *queue_num) +{ + struct internal_list *list; + + LOG_FUNC_ENTER(); + + list = find_internal_resource_by_vdev(vdev); + if (list == NULL) { + NT_LOG(ERR, VDPA, "%s: Invalid device : %p\n", __func__, vdev); + return -1; + } + *queue_num = list->internal->max_queues; + NT_LOG(DBG, VDPA, "%s: vDPA dev=%p queue_num=%d\n", __func__, vdev, + *queue_num); + + LOG_FUNC_LEAVE(); + return 0; +} + +static int ntvf_vdpa_get_vdpa_features(struct rte_vdpa_device *vdev, + uint64_t *features) +{ + struct internal_list *list; + + LOG_FUNC_ENTER(); + + list = find_internal_resource_by_vdev(vdev); + if (list == NULL) { + NT_LOG(ERR, VDPA, "%s: Invalid device : %p\n", __func__, vdev); + return -1; + } + + if (!features) { + NT_LOG(ERR, VDPA, "%s: vDPA dev=%p: no ptr to feature\n", + __func__, vdev); + return -1; + } + + *features = list->internal->features; + NT_LOG(DBG, VDPA, "%s: vDPA dev=%p: features=0x%016lX\n", __func__, + vdev, *features); + + LOG_FUNC_LEAVE(); + return 0; +} + +static int +ntvf_vdpa_get_protocol_features(struct rte_vdpa_device *vdev __rte_unused, + uint64_t *features) +{ + LOG_FUNC_ENTER(); + + if (!features) { + NT_LOG(ERR, VDPA, "%s: vDPA dev=%p: no ptr to feature\n", + __func__, vdev); + return -1; + } + + *features = NTVF_VDPA_SUPPORTED_PROTOCOL_FEATURES; + NT_LOG(DBG, VDPA, "%s: vDPA dev=%p: features=0x%016lX\n", __func__, + vdev, *features); + + LOG_FUNC_LEAVE(); + return 0; +} + +static int ntvf_vdpa_configure_queue(struct ntvf_vdpa_hw *hw, + struct ntvf_vdpa_internal *internal) +{ + int ret = 0; + + ret = ntvf_vdpa_enable_vfio_intr(internal); + if (ret) { + printf("ERROR - ENABLE INTERRUPT via VFIO\n"); + return ret; + } + /* Enable Rx and Tx for all vrings */ + for (int i = 0; i < hw->nr_vring; i++) { + if (i & 1) + nthw_enable_tx_virt_queue(hw->vring[i].p_vq); + else + nthw_enable_rx_virt_queue(hw->vring[i].p_vq); + } + return ret; +} +static int ntvf_vdpa_set_vring_state(int vid, int vring, int state) +{ + struct rte_vdpa_device *vdev; + struct internal_list *list; + + struct ntvf_vdpa_internal *internal; + struct ntvf_vdpa_hw *hw; + int ret = 0; + + LOG_FUNC_ENTER(); + + vdev = rte_vhost_get_vdpa_device(vid); + list = find_internal_resource_by_vdev(vdev); + if (list == NULL) { + NT_LOG(ERR, VDPA, "Invalid vDPA device: %p", vdev); + return -1; + } + + internal = list->internal; + if (vring < 0 || vring >= internal->max_queues * 2) { + NT_LOG(ERR, VDPA, "Vring index %d not correct", vring); + return -1; + } + + hw = &internal->hw; + enum fpga_info_profile fpga_profile = + get_fpga_profile_from_pci(internal->pdev->addr); + + if (!state && hw->vring[vring].enable) { + /* Disable vring */ + if (hw->vring[vring].desc && hw->vring[vring].p_vq) { + if (hw->vring[vring].vq_type == 0) + nthw_disable_rx_virt_queue(hw->vring[vring].p_vq); + else + nthw_disable_tx_virt_queue(hw->vring[vring].p_vq); + } + } + + if (state && !hw->vring[vring].enable) { + /* Enable/Create vring */ + if (hw->vring[vring].desc && hw->vring[vring].p_vq) { + if (hw->vring[vring].vq_type == 0) + nthw_enable_rx_virt_queue(hw->vring[vring].p_vq); + else + nthw_enable_tx_virt_queue(hw->vring[vring].p_vq); + } else { + ntvf_vdpa_dma_map(internal, 1); + ntvf_vdpa_create_vring(internal, vring); + + if (fpga_profile != FPGA_INFO_PROFILE_INLINE) { + /* + * After last vq enable VFIO interrupt IOMMU re-mapping and enable + * FPGA Rx/Tx + */ + if (vring == hw->nr_vring - 1) { + ret = ntvf_vdpa_configure_queue(hw, internal); + if (ret) + return ret; + } + } + } + } + + if (fpga_profile == FPGA_INFO_PROFILE_INLINE) { + hw->vring[vring].enable = !!state; + /* after last vq enable VFIO interrupt IOMMU re-mapping */ + if (hw->vring[vring].enable && vring == hw->nr_vring - 1) { + ret = ntvf_vdpa_configure_queue(hw, internal); + if (ret) + return ret; + } + } else { + hw->vring[vring].enable = !!state; + } + LOG_FUNC_LEAVE(); + return 0; +} + +static struct rte_vdpa_dev_ops ntvf_vdpa_vdpa_ops = { + .get_queue_num = ntvf_vdpa_get_queue_num, + .get_features = ntvf_vdpa_get_vdpa_features, + .get_protocol_features = ntvf_vdpa_get_protocol_features, + .dev_conf = ntvf_vdpa_dev_config, + .dev_close = ntvf_vdpa_dev_close, + .set_vring_state = ntvf_vdpa_set_vring_state, + .set_features = ntvf_vdpa_set_features, + .migration_done = NULL, + .get_vfio_group_fd = ntvf_vdpa_get_vfio_group_fd, + .get_vfio_device_fd = ntvf_vdpa_get_vfio_device_fd, + .get_notify_area = NULL, +}; + +int ntvf_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, + struct rte_pci_device *pci_dev) +{ + struct ntvf_vdpa_internal *internal = NULL; + struct internal_list *list = NULL; + enum fpga_info_profile fpga_profile; + + LOG_FUNC_ENTER(); + + NT_LOG(INF, VDPA, "%s: [%s:%u] %04x:%02x:%02x.%x\n", __func__, __FILE__, + __LINE__, pci_dev->addr.domain, pci_dev->addr.bus, + pci_dev->addr.devid, pci_dev->addr.function); + list = rte_zmalloc("ntvf_vdpa", sizeof(*list), 0); + if (list == NULL) { + NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__, + __LINE__); + goto error; + } + + internal = rte_zmalloc("ntvf_vdpa", sizeof(*internal), 0); + if (internal == NULL) { + NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__, + __LINE__); + goto error; + } + + internal->pdev = pci_dev; + rte_spinlock_init(&internal->lock); + + if (ntvf_vdpa_vfio_setup(internal) < 0) { + NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__, + __LINE__); + return -1; + } + + internal->max_queues = NTVF_VDPA_MAX_QUEUES; + + internal->features = NTVF_VIRTIO_NET_SUPPORTED_FEATURES; + + NT_LOG(DBG, VDPA, "%s: masked features=0x%016lX [%s:%u]\n", __func__, + internal->features, __FILE__, __LINE__); + + fpga_profile = get_fpga_profile_from_pci(internal->pdev->addr); + if (fpga_profile == FPGA_INFO_PROFILE_VSWITCH) { + internal->outport = 0; + } else { + /* VF4 output port 0, VF5 output port 1, VF6 output port 0, ....... */ + internal->outport = internal->pdev->addr.function & 1; + } + + list->internal = internal; + + internal->vdev = + rte_vdpa_register_device(&pci_dev->device, &ntvf_vdpa_vdpa_ops); + NT_LOG(DBG, VDPA, "%s: vDPA dev=%p\n", __func__, internal->vdev); + + if (!internal->vdev) { + NT_LOG(ERR, VDPA, "%s: [%s:%u] Register vDPA device failed\n", + __func__, __FILE__, __LINE__); + goto error; + } + + pthread_mutex_lock(&internal_list_lock); + TAILQ_INSERT_TAIL(&internal_list, list, next); + pthread_mutex_unlock(&internal_list_lock); + + atomic_store(&internal->started, 1); + + ntvf_vdpa_update_datapath(internal); + + LOG_FUNC_LEAVE(); + return 0; + +error: + rte_free(list); + rte_free(internal); + return -1; +} + +int ntvf_vdpa_pci_remove(struct rte_pci_device *pci_dev) +{ + struct ntvf_vdpa_internal *internal; + struct internal_list *list; + int vf_num = nt_vfio_vf_num(pci_dev); + + LOG_FUNC_ENTER(); + list = ntvf_vdpa_find_internal_resource_by_dev(pci_dev); + if (list == NULL) { + NT_LOG(ERR, VDPA, "%s: Invalid device: %s", __func__, + pci_dev->name); + return -1; + } + + internal = list->internal; + atomic_store(&internal->started, 0); + + ntvf_vdpa_update_datapath(internal); + + rte_pci_unmap_device(internal->pdev); + nt_vfio_remove(vf_num); + rte_vdpa_unregister_device(internal->vdev); + + pthread_mutex_lock(&internal_list_lock); + TAILQ_REMOVE(&internal_list, list, next); + pthread_mutex_unlock(&internal_list_lock); + + rte_free(list); + rte_free(internal); + + LOG_FUNC_LEAVE(); + return 0; +} + +static const struct rte_pci_id pci_id_ntvf_vdpa_map[] = { + { + .vendor_id = 0, + }, +}; + +static struct rte_pci_driver rte_ntvf_vdpa = { + .id_table = pci_id_ntvf_vdpa_map, + .drv_flags = 0, + .probe = ntvf_vdpa_pci_probe, + .remove = ntvf_vdpa_pci_remove, +}; + +RTE_PMD_REGISTER_PCI(net_ntvf_vdpa, rte_ntvf_vdpa); +RTE_PMD_REGISTER_PCI_TABLE(net_ntvf_vdpa, pci_id_ntvf_vdpa_map); +RTE_PMD_REGISTER_KMOD_DEP(net_ntvf_vdpa, "* vfio-pci"); + diff --git a/drivers/net/ntnic/ntnic_vf_vdpa.h b/drivers/net/ntnic/ntnic_vf_vdpa.h new file mode 100644 index 0000000000..561e3bf7cf --- /dev/null +++ b/drivers/net/ntnic/ntnic_vf_vdpa.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTNIC_VF_VDPA_H__ +#define __NTNIC_VF_VDPA_H__ + +extern int ntvf_vdpa_logtype; + +#define LOG_FUNC_TRACE +#ifdef LOG_FUNC_TRACE +#define LOG_FUNC_ENTER() NT_LOG(DBG, VDPA, "%s: enter\n", __func__) +#define LOG_FUNC_LEAVE() NT_LOG(DBG, VDPA, "%s: leave\n", __func__) +#else +#define LOG_FUNC_ENTER() +#define LOG_FUNC_LEAVE() +#endif + +int ntvf_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, + struct rte_pci_device *pci_dev); +int ntvf_vdpa_pci_remove(struct rte_pci_device *pci_dev); + +void ntvf_vdpa_reset_hw(int vid); + +#endif /* __NTNIC_VF_VDPA_H__ */ diff --git a/drivers/net/ntnic/ntnic_vfio.c b/drivers/net/ntnic/ntnic_vfio.c new file mode 100644 index 0000000000..1390383c55 --- /dev/null +++ b/drivers/net/ntnic/ntnic_vfio.c @@ -0,0 +1,321 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "ntnic_vfio.h" + +#define ONE_G_SIZE 0x40000000 +#define ONE_G_MASK (ONE_G_SIZE - 1) +#define START_VF_IOVA 0x220000000000 + +int nt_vfio_vf_num(const struct rte_pci_device *pdev) +{ + return ((pdev->addr.devid & 0x1f) << 3) + ((pdev->addr.function) & 0x7); +} + +/* Internal API */ +struct vfio_dev { + int container_fd; + int group_fd; + int dev_fd; + uint64_t iova_addr; +}; + +static struct vfio_dev vfio_list[256]; + +static struct vfio_dev *vfio_get(int vf_num) +{ + if (vf_num < 0 || vf_num > 255) + return NULL; + return &vfio_list[vf_num]; +} + +/* External API */ +int nt_vfio_setup(struct rte_pci_device *dev) +{ + char devname[RTE_DEV_NAME_MAX_LEN] = { 0 }; + int iommu_group_num; + int vf_num; + struct vfio_dev *vfio; + + NT_LOG(INF, ETHDEV, "NT VFIO device setup %s\n", dev->name); + + vf_num = nt_vfio_vf_num(dev); + + vfio = vfio_get(vf_num); + if (vfio == NULL) { + NT_LOG(ERR, ETHDEV, + "VFIO device setup failed. Illegal device id\n"); + return -1; + } + + vfio->dev_fd = -1; + vfio->group_fd = -1; + vfio->container_fd = -1; + vfio->iova_addr = START_VF_IOVA; + + rte_pci_device_name(&dev->addr, devname, RTE_DEV_NAME_MAX_LEN); + rte_vfio_get_group_num(rte_pci_get_sysfs_path(), devname, + &iommu_group_num); + + if (vf_num == 0) { + /* use default container for pf0 */ + vfio->container_fd = RTE_VFIO_DEFAULT_CONTAINER_FD; + } else { + vfio->container_fd = rte_vfio_container_create(); + if (vfio->container_fd < 0) { + NT_LOG(ERR, ETHDEV, + "VFIO device setup failed. VFIO container creation failed.\n"); + return -1; + } + } + + vfio->group_fd = rte_vfio_container_group_bind(vfio->container_fd, + iommu_group_num); + if (vfio->group_fd < 0) { + NT_LOG(ERR, ETHDEV, + "VFIO device setup failed. VFIO container group bind failed.\n"); + goto err; + } + + if (vf_num > 0) { + if (rte_pci_map_device(dev)) { + NT_LOG(ERR, ETHDEV, + "Map VFIO device failed. is the vfio-pci driver loaded?\n"); + goto err; + } + } + + vfio->dev_fd = rte_intr_dev_fd_get(dev->intr_handle); + + NT_LOG(DBG, ETHDEV, + "%s: VFIO id=%d, dev_fd=%d, container_fd=%d, group_fd=%d, iommu_group_num=%d\n", + dev->name, vf_num, vfio->dev_fd, vfio->container_fd, + vfio->group_fd, iommu_group_num); + + return vf_num; + +err: + if (vfio->container_fd != RTE_VFIO_DEFAULT_CONTAINER_FD) + rte_vfio_container_destroy(vfio->container_fd); + return -1; +} + +int nt_vfio_remove(int vf_num) +{ + struct vfio_dev *vfio; + + NT_LOG(DBG, ETHDEV, "NT VFIO device remove VF=%d\n", vf_num); + + vfio = vfio_get(vf_num); + if (!vfio) { + NT_LOG(ERR, ETHDEV, + "VFIO device remove failed. Illegal device id\n"); + return -1; + } + + rte_vfio_container_destroy(vfio->container_fd); + return 0; +} + +int nt_vfio_dma_map(int vf_num, void *virt_addr, uint64_t *iova_addr, + uint64_t size) +{ + uint64_t gp_virt_base; + uint64_t gp_offset; + + if (size == ONE_G_SIZE) { + gp_virt_base = (uint64_t)virt_addr & ~ONE_G_MASK; + gp_offset = (uint64_t)virt_addr & ONE_G_MASK; + } else { + gp_virt_base = (uint64_t)virt_addr; + gp_offset = 0; + } + + struct vfio_dev *vfio; + + vfio = vfio_get(vf_num); + if (vfio == NULL) { + NT_LOG(ERR, ETHDEV, "VFIO MAP: VF number %d invalid\n", vf_num); + return -1; + } + + NT_LOG(DBG, ETHDEV, + "VFIO MMAP VF=%d VirtAddr=%" PRIX64 " HPA=%" PRIX64 + " VirtBase=%" PRIX64 " IOVA Addr=%" PRIX64 " size=%d\n", + vf_num, virt_addr, rte_malloc_virt2iova(virt_addr), gp_virt_base, + vfio->iova_addr, size); + + int res = rte_vfio_container_dma_map(vfio->container_fd, gp_virt_base, + vfio->iova_addr, size); + + NT_LOG(DBG, ETHDEV, "VFIO MMAP res %i, container_fd %i, vf_num %i\n", + res, vfio->container_fd, vf_num); + if (res) { + NT_LOG(ERR, ETHDEV, + "rte_vfio_container_dma_map failed: res %d\n", res); + return -1; + } + + *iova_addr = vfio->iova_addr + gp_offset; + + vfio->iova_addr += ONE_G_SIZE; + + return 0; +} + +int nt_vfio_dma_unmap(int vf_num, void *virt_addr, uint64_t iova_addr, + uint64_t size) +{ + uint64_t gp_virt_base; + struct vfio_dev *vfio; + + if (size == ONE_G_SIZE) { + uint64_t gp_offset; + + gp_virt_base = (uint64_t)virt_addr & ~ONE_G_MASK; + gp_offset = (uint64_t)virt_addr & ONE_G_MASK; + iova_addr -= gp_offset; + } else { + gp_virt_base = (uint64_t)virt_addr; + } + + vfio = vfio_get(vf_num); + + if (vfio == NULL) { + NT_LOG(ERR, ETHDEV, "VFIO UNMAP: VF number %d invalid\n", + vf_num); + return -1; + } + + if (vfio->container_fd == -1) + return 0; + + int res = rte_vfio_container_dma_unmap(vfio->container_fd, gp_virt_base, + iova_addr, size); + if (res != 0) { + NT_LOG(ERR, ETHDEV, + "VFIO UNMMAP FAILED! res %i, container_fd %i, vf_num %i, virt_base=%" PRIX64 + ", IOVA=%" PRIX64 ", size=%i\n", + res, vfio->container_fd, vf_num, gp_virt_base, iova_addr, + (int)size); + return -1; + } + + return 0; +} + +/* vDPA mapping with Guest Phy addresses as IOVA */ +int nt_vfio_dma_map_vdpa(int vf_num, uint64_t virt_addr, uint64_t iova_addr, + uint64_t size) +{ + struct vfio_dev *vfio = vfio_get(vf_num); + + if (vfio == NULL) { + NT_LOG(ERR, ETHDEV, "VFIO MAP: VF number %d invalid\n", vf_num); + return -1; + } + + NT_LOG(DBG, ETHDEV, + "VFIO vDPA MMAP VF=%d VirtAddr=%" PRIX64 " IOVA Addr=%" PRIX64 + " size=%d\n", + vf_num, virt_addr, iova_addr, size); + + int res = rte_vfio_container_dma_map(vfio->container_fd, virt_addr, + iova_addr, size); + + NT_LOG(DBG, ETHDEV, + "VFIO vDPA MMAP res %i, container_fd %i, vf_num %i\n", res, + vfio->container_fd, vf_num); + if (res) { + NT_LOG(ERR, ETHDEV, + "rte_vfio_container_dma_map failed: res %d\n", res); + return -1; + } + + return 0; +} + +int nt_vfio_dma_unmap_vdpa(int vf_num, uint64_t virt_addr, uint64_t iova_addr, + uint64_t size) +{ + struct vfio_dev *vfio = vfio_get(vf_num); + + if (vfio == NULL) { + NT_LOG(ERR, ETHDEV, "VFIO vDPA UNMAP: VF number %d invalid\n", + vf_num); + return -1; + } + int res = rte_vfio_container_dma_unmap(vfio->container_fd, virt_addr, + iova_addr, size); + if (res != 0) { + NT_LOG(ERR, ETHDEV, + "VFIO vDPA UNMMAP FAILED! res %i, container_fd %i, vf_num %i\n", + res, vfio->container_fd, vf_num); + return -1; + } + + return 0; +} + +int nt_vfio_get_container_fd(int vf_num) +{ + struct vfio_dev *vfio; + + vfio = vfio_get(vf_num); + if (!vfio) { + NT_LOG(ERR, ETHDEV, + "VFIO device remove failed. Illegal device id\n"); + return -1; + } + return vfio->container_fd; +} + +int nt_vfio_get_group_fd(int vf_num) +{ + struct vfio_dev *vfio; + + vfio = vfio_get(vf_num); + if (!vfio) { + NT_LOG(ERR, ETHDEV, + "VFIO device remove failed. Illegal device id\n"); + return -1; + } + return vfio->group_fd; +} + +int nt_vfio_get_dev_fd(int vf_num) +{ + struct vfio_dev *vfio; + + vfio = vfio_get(vf_num); + if (!vfio) { + NT_LOG(ERR, ETHDEV, + "VFIO device remove failed. Illegal device id\n"); + return -1; + } + return vfio->dev_fd; +} + +/* Internal init */ + +RTE_INIT(nt_vfio_init); + +static void nt_vfio_init(void) +{ + struct nt_util_vfio_impl s = { .vfio_dma_map = nt_vfio_dma_map, + .vfio_dma_unmap = nt_vfio_dma_unmap + }; + nt_util_vfio_init(&s); +} diff --git a/drivers/net/ntnic/ntnic_vfio.h b/drivers/net/ntnic/ntnic_vfio.h new file mode 100644 index 0000000000..5d8a63d364 --- /dev/null +++ b/drivers/net/ntnic/ntnic_vfio.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTNIC_VFIO_H_ +#define _NTNIC_VFIO_H_ + +#include +#include +#include + +int nt_vfio_setup(struct rte_pci_device *dev); +int nt_vfio_remove(int vf_num); + +int nt_vfio_get_container_fd(int vf_num); +int nt_vfio_get_group_fd(int vf_num); +int nt_vfio_get_dev_fd(int vf_num); + +int nt_vfio_dma_map(int vf_num, void *virt_addr, uint64_t *iova_addr, + uint64_t size); +int nt_vfio_dma_unmap(int vf_num, void *virt_addr, uint64_t iova_addr, + uint64_t size); + +int nt_vfio_dma_map_vdpa(int vf_num, uint64_t virt_addr, uint64_t iova_addr, + uint64_t size); +int nt_vfio_dma_unmap_vdpa(int vf_num, uint64_t virt_addr, uint64_t iova_addr, + uint64_t size); + +/* Find device (PF/VF) number from device address */ +int nt_vfio_vf_num(const struct rte_pci_device *dev); +#endif /* _NTNIC_VFIO_H_ */ diff --git a/drivers/net/ntnic/ntnic_xstats.c b/drivers/net/ntnic/ntnic_xstats.c new file mode 100644 index 0000000000..e034e33c89 --- /dev/null +++ b/drivers/net/ntnic/ntnic_xstats.c @@ -0,0 +1,703 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include + +#include "ntdrv_4ga.h" +#include "ntlog.h" +#include "nthw_drv.h" +#include "nthw_fpga.h" +#include "ntnic_xstats.h" + +#define UNUSED __rte_unused + +struct rte_nthw_xstats_names_s { + char name[RTE_ETH_XSTATS_NAME_SIZE]; + uint8_t source; + unsigned int offset; +}; + +/* + * Extended stat for VSwitch + */ +static struct rte_nthw_xstats_names_s nthw_virt_xstats_names[] = { + { "rx_octets", 1, offsetof(struct port_counters_vswitch_v1, octets) }, + { "rx_packets", 1, offsetof(struct port_counters_vswitch_v1, pkts) }, + { "rx_dropped_packets", 1, + offsetof(struct port_counters_vswitch_v1, drop_events) + }, + { "rx_qos_dropped_bytes", 1, + offsetof(struct port_counters_vswitch_v1, qos_drop_octets) + }, + { "rx_qos_dropped_packets", 1, + offsetof(struct port_counters_vswitch_v1, qos_drop_pkts) + }, + { "tx_octets", 2, offsetof(struct port_counters_vswitch_v1, octets) }, + { "tx_packets", 2, offsetof(struct port_counters_vswitch_v1, pkts) }, + { "tx_dropped_packets", 2, + offsetof(struct port_counters_vswitch_v1, drop_events) + }, + { "tx_qos_dropped_bytes", 2, + offsetof(struct port_counters_vswitch_v1, qos_drop_octets) + }, + { "tx_qos_dropped_packets", 2, + offsetof(struct port_counters_vswitch_v1, qos_drop_pkts) + }, +}; + +#define NTHW_VIRT_XSTATS_NAMES RTE_DIM(nthw_virt_xstats_names) + +/* + * Extended stat for Capture/Inline - implements RMON + * FLM 0.17 + */ +static struct rte_nthw_xstats_names_s nthw_cap_xstats_names_v1[] = { + { "rx_drop_events", 1, offsetof(struct port_counters_v2, drop_events) }, + { "rx_octets", 1, offsetof(struct port_counters_v2, octets) }, + { "rx_packets", 1, offsetof(struct port_counters_v2, pkts) }, + { "rx_broadcast_packets", 1, + offsetof(struct port_counters_v2, broadcast_pkts) + }, + { "rx_multicast_packets", 1, + offsetof(struct port_counters_v2, multicast_pkts) + }, + { "rx_unicast_packets", 1, + offsetof(struct port_counters_v2, unicast_pkts) + }, + { "rx_align_errors", 1, + offsetof(struct port_counters_v2, pkts_alignment) + }, + { "rx_code_violation_errors", 1, + offsetof(struct port_counters_v2, pkts_code_violation) + }, + { "rx_crc_errors", 1, offsetof(struct port_counters_v2, pkts_crc) }, + { "rx_undersize_packets", 1, + offsetof(struct port_counters_v2, undersize_pkts) + }, + { "rx_oversize_packets", 1, + offsetof(struct port_counters_v2, oversize_pkts) + }, + { "rx_fragments", 1, offsetof(struct port_counters_v2, fragments) }, + { "rx_jabbers_not_truncated", 1, + offsetof(struct port_counters_v2, jabbers_not_truncated) + }, + { "rx_jabbers_truncated", 1, + offsetof(struct port_counters_v2, jabbers_truncated) + }, + { "rx_size_64_packets", 1, + offsetof(struct port_counters_v2, pkts_64_octets) + }, + { "rx_size_65_to_127_packets", 1, + offsetof(struct port_counters_v2, pkts_65_to_127_octets) + }, + { "rx_size_128_to_255_packets", 1, + offsetof(struct port_counters_v2, pkts_128_to_255_octets) + }, + { "rx_size_256_to_511_packets", 1, + offsetof(struct port_counters_v2, pkts_256_to_511_octets) + }, + { "rx_size_512_to_1023_packets", 1, + offsetof(struct port_counters_v2, pkts_512_to_1023_octets) + }, + { "rx_size_1024_to_1518_packets", 1, + offsetof(struct port_counters_v2, pkts_1024_to_1518_octets) + }, + { "rx_size_1519_to_2047_packets", 1, + offsetof(struct port_counters_v2, pkts_1519_to_2047_octets) + }, + { "rx_size_2048_to_4095_packets", 1, + offsetof(struct port_counters_v2, pkts_2048_to_4095_octets) + }, + { "rx_size_4096_to_8191_packets", 1, + offsetof(struct port_counters_v2, pkts_4096_to_8191_octets) + }, + { "rx_size_8192_to_max_packets", 1, + offsetof(struct port_counters_v2, pkts_8192_to_max_octets) + }, + { "rx_ip_checksum_error", 1, + offsetof(struct port_counters_v2, pkts_ip_chksum_error) + }, + { "rx_udp_checksum_error", 1, + offsetof(struct port_counters_v2, pkts_udp_chksum_error) + }, + { "rx_tcp_checksum_error", 1, + offsetof(struct port_counters_v2, pkts_tcp_chksum_error) + }, + + { "tx_drop_events", 2, offsetof(struct port_counters_v2, drop_events) }, + { "tx_octets", 2, offsetof(struct port_counters_v2, octets) }, + { "tx_packets", 2, offsetof(struct port_counters_v2, pkts) }, + { "tx_broadcast_packets", 2, + offsetof(struct port_counters_v2, broadcast_pkts) + }, + { "tx_multicast_packets", 2, + offsetof(struct port_counters_v2, multicast_pkts) + }, + { "tx_unicast_packets", 2, + offsetof(struct port_counters_v2, unicast_pkts) + }, + { "tx_align_errors", 2, + offsetof(struct port_counters_v2, pkts_alignment) + }, + { "tx_code_violation_errors", 2, + offsetof(struct port_counters_v2, pkts_code_violation) + }, + { "tx_crc_errors", 2, offsetof(struct port_counters_v2, pkts_crc) }, + { "tx_undersize_packets", 2, + offsetof(struct port_counters_v2, undersize_pkts) + }, + { "tx_oversize_packets", 2, + offsetof(struct port_counters_v2, oversize_pkts) + }, + { "tx_fragments", 2, offsetof(struct port_counters_v2, fragments) }, + { "tx_jabbers_not_truncated", 2, + offsetof(struct port_counters_v2, jabbers_not_truncated) + }, + { "tx_jabbers_truncated", 2, + offsetof(struct port_counters_v2, jabbers_truncated) + }, + { "tx_size_64_packets", 2, + offsetof(struct port_counters_v2, pkts_64_octets) + }, + { "tx_size_65_to_127_packets", 2, + offsetof(struct port_counters_v2, pkts_65_to_127_octets) + }, + { "tx_size_128_to_255_packets", 2, + offsetof(struct port_counters_v2, pkts_128_to_255_octets) + }, + { "tx_size_256_to_511_packets", 2, + offsetof(struct port_counters_v2, pkts_256_to_511_octets) + }, + { "tx_size_512_to_1023_packets", 2, + offsetof(struct port_counters_v2, pkts_512_to_1023_octets) + }, + { "tx_size_1024_to_1518_packets", 2, + offsetof(struct port_counters_v2, pkts_1024_to_1518_octets) + }, + { "tx_size_1519_to_2047_packets", 2, + offsetof(struct port_counters_v2, pkts_1519_to_2047_octets) + }, + { "tx_size_2048_to_4095_packets", 2, + offsetof(struct port_counters_v2, pkts_2048_to_4095_octets) + }, + { "tx_size_4096_to_8191_packets", 2, + offsetof(struct port_counters_v2, pkts_4096_to_8191_octets) + }, + { "tx_size_8192_to_max_packets", 2, + offsetof(struct port_counters_v2, pkts_8192_to_max_octets) + }, + + /* FLM 0.17 */ + { "flm_count_current", 3, offsetof(struct flm_counters_v1, current) }, + { "flm_count_learn_done", 3, + offsetof(struct flm_counters_v1, learn_done) + }, + { "flm_count_learn_ignore", 3, + offsetof(struct flm_counters_v1, learn_ignore) + }, + { "flm_count_learn_fail", 3, + offsetof(struct flm_counters_v1, learn_fail) + }, + { "flm_count_unlearn_done", 3, + offsetof(struct flm_counters_v1, unlearn_done) + }, + { "flm_count_unlearn_ignore", 3, + offsetof(struct flm_counters_v1, unlearn_ignore) + }, + { "flm_count_auto_unlearn_done", 3, + offsetof(struct flm_counters_v1, auto_unlearn_done) + }, + { "flm_count_auto_unlearn_ignore", 3, + offsetof(struct flm_counters_v1, auto_unlearn_ignore) + }, + { "flm_count_auto_unlearn_fail", 3, + offsetof(struct flm_counters_v1, auto_unlearn_fail) + }, + { "flm_count_timeout_unlearn_done", 3, + offsetof(struct flm_counters_v1, timeout_unlearn_done) + }, + { "flm_count_rel_done", 3, offsetof(struct flm_counters_v1, rel_done) }, + { "flm_count_rel_ignore", 3, + offsetof(struct flm_counters_v1, rel_ignore) + }, + { "flm_count_prb_done", 3, offsetof(struct flm_counters_v1, prb_done) }, + { "flm_count_prb_ignore", 3, + offsetof(struct flm_counters_v1, prb_ignore) + }, +}; + +/* + * Extended stat for Capture/Inline - implements RMON + * FLM 0.18 + */ +static struct rte_nthw_xstats_names_s nthw_cap_xstats_names_v2[] = { + { "rx_drop_events", 1, offsetof(struct port_counters_v2, drop_events) }, + { "rx_octets", 1, offsetof(struct port_counters_v2, octets) }, + { "rx_packets", 1, offsetof(struct port_counters_v2, pkts) }, + { "rx_broadcast_packets", 1, + offsetof(struct port_counters_v2, broadcast_pkts) + }, + { "rx_multicast_packets", 1, + offsetof(struct port_counters_v2, multicast_pkts) + }, + { "rx_unicast_packets", 1, + offsetof(struct port_counters_v2, unicast_pkts) + }, + { "rx_align_errors", 1, + offsetof(struct port_counters_v2, pkts_alignment) + }, + { "rx_code_violation_errors", 1, + offsetof(struct port_counters_v2, pkts_code_violation) + }, + { "rx_crc_errors", 1, offsetof(struct port_counters_v2, pkts_crc) }, + { "rx_undersize_packets", 1, + offsetof(struct port_counters_v2, undersize_pkts) + }, + { "rx_oversize_packets", 1, + offsetof(struct port_counters_v2, oversize_pkts) + }, + { "rx_fragments", 1, offsetof(struct port_counters_v2, fragments) }, + { "rx_jabbers_not_truncated", 1, + offsetof(struct port_counters_v2, jabbers_not_truncated) + }, + { "rx_jabbers_truncated", 1, + offsetof(struct port_counters_v2, jabbers_truncated) + }, + { "rx_size_64_packets", 1, + offsetof(struct port_counters_v2, pkts_64_octets) + }, + { "rx_size_65_to_127_packets", 1, + offsetof(struct port_counters_v2, pkts_65_to_127_octets) + }, + { "rx_size_128_to_255_packets", 1, + offsetof(struct port_counters_v2, pkts_128_to_255_octets) + }, + { "rx_size_256_to_511_packets", 1, + offsetof(struct port_counters_v2, pkts_256_to_511_octets) + }, + { "rx_size_512_to_1023_packets", 1, + offsetof(struct port_counters_v2, pkts_512_to_1023_octets) + }, + { "rx_size_1024_to_1518_packets", 1, + offsetof(struct port_counters_v2, pkts_1024_to_1518_octets) + }, + { "rx_size_1519_to_2047_packets", 1, + offsetof(struct port_counters_v2, pkts_1519_to_2047_octets) + }, + { "rx_size_2048_to_4095_packets", 1, + offsetof(struct port_counters_v2, pkts_2048_to_4095_octets) + }, + { "rx_size_4096_to_8191_packets", 1, + offsetof(struct port_counters_v2, pkts_4096_to_8191_octets) + }, + { "rx_size_8192_to_max_packets", 1, + offsetof(struct port_counters_v2, pkts_8192_to_max_octets) + }, + { "rx_ip_checksum_error", 1, + offsetof(struct port_counters_v2, pkts_ip_chksum_error) + }, + { "rx_udp_checksum_error", 1, + offsetof(struct port_counters_v2, pkts_udp_chksum_error) + }, + { "rx_tcp_checksum_error", 1, + offsetof(struct port_counters_v2, pkts_tcp_chksum_error) + }, + + { "tx_drop_events", 2, offsetof(struct port_counters_v2, drop_events) }, + { "tx_octets", 2, offsetof(struct port_counters_v2, octets) }, + { "tx_packets", 2, offsetof(struct port_counters_v2, pkts) }, + { "tx_broadcast_packets", 2, + offsetof(struct port_counters_v2, broadcast_pkts) + }, + { "tx_multicast_packets", 2, + offsetof(struct port_counters_v2, multicast_pkts) + }, + { "tx_unicast_packets", 2, + offsetof(struct port_counters_v2, unicast_pkts) + }, + { "tx_align_errors", 2, + offsetof(struct port_counters_v2, pkts_alignment) + }, + { "tx_code_violation_errors", 2, + offsetof(struct port_counters_v2, pkts_code_violation) + }, + { "tx_crc_errors", 2, offsetof(struct port_counters_v2, pkts_crc) }, + { "tx_undersize_packets", 2, + offsetof(struct port_counters_v2, undersize_pkts) + }, + { "tx_oversize_packets", 2, + offsetof(struct port_counters_v2, oversize_pkts) + }, + { "tx_fragments", 2, offsetof(struct port_counters_v2, fragments) }, + { "tx_jabbers_not_truncated", 2, + offsetof(struct port_counters_v2, jabbers_not_truncated) + }, + { "tx_jabbers_truncated", 2, + offsetof(struct port_counters_v2, jabbers_truncated) + }, + { "tx_size_64_packets", 2, + offsetof(struct port_counters_v2, pkts_64_octets) + }, + { "tx_size_65_to_127_packets", 2, + offsetof(struct port_counters_v2, pkts_65_to_127_octets) + }, + { "tx_size_128_to_255_packets", 2, + offsetof(struct port_counters_v2, pkts_128_to_255_octets) + }, + { "tx_size_256_to_511_packets", 2, + offsetof(struct port_counters_v2, pkts_256_to_511_octets) + }, + { "tx_size_512_to_1023_packets", 2, + offsetof(struct port_counters_v2, pkts_512_to_1023_octets) + }, + { "tx_size_1024_to_1518_packets", 2, + offsetof(struct port_counters_v2, pkts_1024_to_1518_octets) + }, + { "tx_size_1519_to_2047_packets", 2, + offsetof(struct port_counters_v2, pkts_1519_to_2047_octets) + }, + { "tx_size_2048_to_4095_packets", 2, + offsetof(struct port_counters_v2, pkts_2048_to_4095_octets) + }, + { "tx_size_4096_to_8191_packets", 2, + offsetof(struct port_counters_v2, pkts_4096_to_8191_octets) + }, + { "tx_size_8192_to_max_packets", 2, + offsetof(struct port_counters_v2, pkts_8192_to_max_octets) + }, + + /* FLM 0.17 */ + { "flm_count_current", 3, offsetof(struct flm_counters_v1, current) }, + { "flm_count_learn_done", 3, + offsetof(struct flm_counters_v1, learn_done) + }, + { "flm_count_learn_ignore", 3, + offsetof(struct flm_counters_v1, learn_ignore) + }, + { "flm_count_learn_fail", 3, + offsetof(struct flm_counters_v1, learn_fail) + }, + { "flm_count_unlearn_done", 3, + offsetof(struct flm_counters_v1, unlearn_done) + }, + { "flm_count_unlearn_ignore", 3, + offsetof(struct flm_counters_v1, unlearn_ignore) + }, + { "flm_count_auto_unlearn_done", 3, + offsetof(struct flm_counters_v1, auto_unlearn_done) + }, + { "flm_count_auto_unlearn_ignore", 3, + offsetof(struct flm_counters_v1, auto_unlearn_ignore) + }, + { "flm_count_auto_unlearn_fail", 3, + offsetof(struct flm_counters_v1, auto_unlearn_fail) + }, + { "flm_count_timeout_unlearn_done", 3, + offsetof(struct flm_counters_v1, timeout_unlearn_done) + }, + { "flm_count_rel_done", 3, offsetof(struct flm_counters_v1, rel_done) }, + { "flm_count_rel_ignore", 3, + offsetof(struct flm_counters_v1, rel_ignore) + }, + { "flm_count_prb_done", 3, offsetof(struct flm_counters_v1, prb_done) }, + { "flm_count_prb_ignore", 3, + offsetof(struct flm_counters_v1, prb_ignore) + }, + + /* FLM 0.20 */ + { "flm_count_sta_done", 3, offsetof(struct flm_counters_v1, sta_done) }, + { "flm_count_inf_done", 3, offsetof(struct flm_counters_v1, inf_done) }, + { "flm_count_inf_skip", 3, offsetof(struct flm_counters_v1, inf_skip) }, + { "flm_count_pck_hit", 3, offsetof(struct flm_counters_v1, pck_hit) }, + { "flm_count_pck_miss", 3, offsetof(struct flm_counters_v1, pck_miss) }, + { "flm_count_pck_unh", 3, offsetof(struct flm_counters_v1, pck_unh) }, + { "flm_count_pck_dis", 3, offsetof(struct flm_counters_v1, pck_dis) }, + { "flm_count_csh_hit", 3, offsetof(struct flm_counters_v1, csh_hit) }, + { "flm_count_csh_miss", 3, offsetof(struct flm_counters_v1, csh_miss) }, + { "flm_count_csh_unh", 3, offsetof(struct flm_counters_v1, csh_unh) }, + { "flm_count_cuc_start", 3, + offsetof(struct flm_counters_v1, cuc_start) + }, + { "flm_count_cuc_move", 3, offsetof(struct flm_counters_v1, cuc_move) }, +}; + +#define NTHW_CAP_XSTATS_NAMES_V1 RTE_DIM(nthw_cap_xstats_names_v1) +#define NTHW_CAP_XSTATS_NAMES_V2 RTE_DIM(nthw_cap_xstats_names_v2) + +/* + * Container for the reset values + */ +#define NTHW_XSTATS_SIZE ((NTHW_VIRT_XSTATS_NAMES < NTHW_CAP_XSTATS_NAMES_V2) ? \ + NTHW_CAP_XSTATS_NAMES_V2 : NTHW_VIRT_XSTATS_NAMES) + +uint64_t nthw_xstats_reset_val[NUM_ADAPTER_PORTS_MAX][NTHW_XSTATS_SIZE] = { 0 }; + + +/* + * These functions must only be called with stat mutex locked + */ +int nthw_xstats_get(nt4ga_stat_t *p_nt4ga_stat, struct rte_eth_xstat *stats, + unsigned int n, bool is_vswitch, uint8_t port) +{ + unsigned int i; + uint8_t *flm_ptr; + uint8_t *rx_ptr; + uint8_t *tx_ptr; + uint32_t nb_names; + struct rte_nthw_xstats_names_s *names; + + if (is_vswitch) { + flm_ptr = NULL; + rx_ptr = (uint8_t *)&p_nt4ga_stat->virt.mp_stat_structs_port_rx[port]; + tx_ptr = (uint8_t *)&p_nt4ga_stat->virt.mp_stat_structs_port_tx[port]; + names = nthw_virt_xstats_names; + nb_names = NTHW_VIRT_XSTATS_NAMES; + } else { + flm_ptr = (uint8_t *)p_nt4ga_stat->mp_stat_structs_flm; + rx_ptr = (uint8_t *)&p_nt4ga_stat->cap.mp_stat_structs_port_rx[port]; + tx_ptr = (uint8_t *)&p_nt4ga_stat->cap.mp_stat_structs_port_tx[port]; + if (p_nt4ga_stat->flm_stat_ver < 18) { + names = nthw_cap_xstats_names_v1; + nb_names = NTHW_CAP_XSTATS_NAMES_V1; + } else { + names = nthw_cap_xstats_names_v2; + nb_names = NTHW_CAP_XSTATS_NAMES_V2; + } + } + + for (i = 0; i < n && i < nb_names; i++) { + stats[i].id = i; + switch (names[i].source) { + case 1: + /* RX stat */ + stats[i].value = + *((uint64_t *)&rx_ptr[names[i].offset]) - + nthw_xstats_reset_val[port][i]; + break; + case 2: + /* TX stat */ + stats[i].value = + *((uint64_t *)&tx_ptr[names[i].offset]) - + nthw_xstats_reset_val[port][i]; + break; + case 3: + /* FLM stat */ + if (flm_ptr) { + stats[i].value = + *((uint64_t *)&flm_ptr[names[i].offset]) - + nthw_xstats_reset_val[0][i]; + } else { + stats[i].value = 0; + } + break; + default: + stats[i].value = 0; + break; + } + } + + return i; +} + +int nthw_xstats_get_by_id(nt4ga_stat_t *p_nt4ga_stat, const uint64_t *ids, + uint64_t *values, unsigned int n, bool is_vswitch, + uint8_t port) +{ + unsigned int i; + uint8_t *flm_ptr; + uint8_t *rx_ptr; + uint8_t *tx_ptr; + uint32_t nb_names; + struct rte_nthw_xstats_names_s *names; + int count = 0; + + if (is_vswitch) { + flm_ptr = NULL; + rx_ptr = (uint8_t *)&p_nt4ga_stat->virt.mp_stat_structs_port_rx[port]; + tx_ptr = (uint8_t *)&p_nt4ga_stat->virt.mp_stat_structs_port_tx[port]; + names = nthw_virt_xstats_names; + nb_names = NTHW_VIRT_XSTATS_NAMES; + } else { + flm_ptr = (uint8_t *)p_nt4ga_stat->mp_stat_structs_flm; + rx_ptr = (uint8_t *)&p_nt4ga_stat->cap.mp_stat_structs_port_rx[port]; + tx_ptr = (uint8_t *)&p_nt4ga_stat->cap.mp_stat_structs_port_tx[port]; + if (p_nt4ga_stat->flm_stat_ver < 18) { + names = nthw_cap_xstats_names_v1; + nb_names = NTHW_CAP_XSTATS_NAMES_V1; + } else { + names = nthw_cap_xstats_names_v2; + nb_names = NTHW_CAP_XSTATS_NAMES_V2; + } + } + + for (i = 0; i < n; i++) { + if (ids[i] < nb_names) { + switch (names[ids[i]].source) { + case 1: + /* RX stat */ + values[i] = + *((uint64_t *)&rx_ptr[names[ids[i]] + .offset]) - + nthw_xstats_reset_val[port][ids[i]]; + break; + case 2: + /* TX stat */ + values[i] = + *((uint64_t *)&tx_ptr[names[ids[i]] + .offset]) - + nthw_xstats_reset_val[port][ids[i]]; + break; + case 3: + /* FLM stat */ + if (flm_ptr) { + values[i] = + *((uint64_t *)&flm_ptr + [names[ids[i]].offset]) - + nthw_xstats_reset_val[0][ids[i]]; + } else { + values[i] = 0; + } + break; + default: + values[i] = 0; + break; + } + count++; + } + } + + return count; +} + +void nthw_xstats_reset(nt4ga_stat_t *p_nt4ga_stat, bool is_vswitch, uint8_t port) +{ + unsigned int i; + uint8_t *flm_ptr; + uint8_t *rx_ptr; + uint8_t *tx_ptr; + uint32_t nb_names; + struct rte_nthw_xstats_names_s *names; + + if (is_vswitch) { + flm_ptr = NULL; + rx_ptr = (uint8_t *)&p_nt4ga_stat->virt.mp_stat_structs_port_rx[port]; + tx_ptr = (uint8_t *)&p_nt4ga_stat->virt.mp_stat_structs_port_tx[port]; + names = nthw_virt_xstats_names; + nb_names = NTHW_VIRT_XSTATS_NAMES; + } else { + flm_ptr = (uint8_t *)p_nt4ga_stat->mp_stat_structs_flm; + rx_ptr = (uint8_t *)&p_nt4ga_stat->cap.mp_stat_structs_port_rx[port]; + tx_ptr = (uint8_t *)&p_nt4ga_stat->cap.mp_stat_structs_port_tx[port]; + if (p_nt4ga_stat->flm_stat_ver < 18) { + names = nthw_cap_xstats_names_v1; + nb_names = NTHW_CAP_XSTATS_NAMES_V1; + } else { + names = nthw_cap_xstats_names_v2; + nb_names = NTHW_CAP_XSTATS_NAMES_V2; + } + } + + for (i = 0; i < nb_names; i++) { + switch (names[i].source) { + case 1: + /* RX stat */ + nthw_xstats_reset_val[port][i] = + *((uint64_t *)&rx_ptr[names[i].offset]); + break; + case 2: + /* TX stat */ + nthw_xstats_reset_val[port][i] = + *((uint64_t *)&tx_ptr[names[i].offset]); + break; + case 3: + /* + * FLM stat + * Reset makes no sense for flm_count_current + */ + if (flm_ptr && strcmp(names[i].name, "flm_count_current") != 0) { + nthw_xstats_reset_val[0][i] = + *((uint64_t *)&flm_ptr[names[i].offset]); + } + break; + default: + break; + } + } +} + +/* + * These functions does not require stat mutex locked + */ +int nthw_xstats_get_names(nt4ga_stat_t *p_nt4ga_stat, + struct rte_eth_xstat_name *xstats_names, + unsigned int size, bool is_vswitch) +{ + int count = 0; + unsigned int i; + uint32_t nb_names; + struct rte_nthw_xstats_names_s *names; + + if (is_vswitch) { + names = nthw_virt_xstats_names; + nb_names = NTHW_VIRT_XSTATS_NAMES; + } else { + if (p_nt4ga_stat->flm_stat_ver < 18) { + names = nthw_cap_xstats_names_v1; + nb_names = NTHW_CAP_XSTATS_NAMES_V1; + } else { + names = nthw_cap_xstats_names_v2; + nb_names = NTHW_CAP_XSTATS_NAMES_V2; + } + } + + if (!xstats_names) + return nb_names; + + for (i = 0; i < size && i < nb_names; i++) { + strlcpy(xstats_names[i].name, names[i].name, + sizeof(xstats_names[i].name)); + count++; + } + + return count; +} + +int nthw_xstats_get_names_by_id(nt4ga_stat_t *p_nt4ga_stat, + struct rte_eth_xstat_name *xstats_names, + const uint64_t *ids, unsigned int size, + bool is_vswitch) +{ + int count = 0; + unsigned int i; + + uint32_t nb_names; + struct rte_nthw_xstats_names_s *names; + + if (is_vswitch) { + names = nthw_virt_xstats_names; + nb_names = NTHW_VIRT_XSTATS_NAMES; + } else { + if (p_nt4ga_stat->flm_stat_ver < 18) { + names = nthw_cap_xstats_names_v1; + nb_names = NTHW_CAP_XSTATS_NAMES_V1; + } else { + names = nthw_cap_xstats_names_v2; + nb_names = NTHW_CAP_XSTATS_NAMES_V2; + } + } + + if (!xstats_names) + return nb_names; + + for (i = 0; i < size; i++) { + if (ids[i] < nb_names) { + strlcpy(xstats_names[i].name, names[ids[i]].name, + RTE_ETH_XSTATS_NAME_SIZE); + } + count++; + } + + return count; +} diff --git a/drivers/net/ntnic/ntnic_xstats.h b/drivers/net/ntnic/ntnic_xstats.h new file mode 100644 index 0000000000..0a82a1a677 --- /dev/null +++ b/drivers/net/ntnic/ntnic_xstats.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NTNIC_XSTATS_H_ +#define NTNIC_XSTATS_H_ + +int nthw_xstats_get_names(nt4ga_stat_t *p_nt4ga_stat, + struct rte_eth_xstat_name *xstats_names, + unsigned int size, bool is_vswitch); +int nthw_xstats_get(nt4ga_stat_t *p_nt4ga_stat, struct rte_eth_xstat *stats, + unsigned int n, bool is_vswitch, uint8_t port); +void nthw_xstats_reset(nt4ga_stat_t *p_nt4ga_stat, bool is_vswitch, uint8_t port); +int nthw_xstats_get_names_by_id(nt4ga_stat_t *p_nt4ga_stat, + struct rte_eth_xstat_name *xstats_names, + const uint64_t *ids, unsigned int size, + bool is_vswitch); +int nthw_xstats_get_by_id(nt4ga_stat_t *p_nt4ga_stat, const uint64_t *ids, + uint64_t *values, unsigned int n, bool is_vswitch, + uint8_t port); + +#endif /* NTNIC_XSTATS_H_ */ From patchwork Mon Aug 21 13:54:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mykola Kostenok X-Patchwork-Id: 130584 X-Patchwork-Delegate: thomas@monjalon.net 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 B4F68430C1; Mon, 21 Aug 2023 15:55:53 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 70D9C43278; Mon, 21 Aug 2023 15:54:49 +0200 (CEST) Received: from egress-ip33a.ess.de.barracuda.com (egress-ip33a.ess.de.barracuda.com [18.185.115.192]) by mails.dpdk.org (Postfix) with ESMTP id 188584326B for ; Mon, 21 Aug 2023 15:54:45 +0200 (CEST) Received: from EUR05-DB8-obe.outbound.protection.outlook.com (mail-db8eur05lp2107.outbound.protection.outlook.com [104.47.17.107]) by mx-outbound43-64.eu-central-1c.ess.aws.cudaops.com (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 21 Aug 2023 13:54:37 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=W/CMwdpsQKFDMo2NbVrbCT7jarp/kF1lf79Ye5tpNAg87V89oNhV4eIA9IPuUoASbrE5tmXM82gGaiZGcpUoxpkjny8qTfnqaCGF8oJrgbxTc2WQ/IFWOO9j2emnZoQnG/+Enq5AaI1dM1YPgj7TAUHQOQ9okO2qAB0B+5IuO5Qkae3UJBaKaHJ3gxbWOTtFK7HUMNJ+exSUlR/yZaExopAQfX06WRsdp6aq0jcVXLJPaxK+m2Ck/7kVGHZGMcQDPu714Fl4wHztcSe/7mp5i1KCIZzaToxtO+a1XIA85AKUOvempAst2SaUft7BcNL0PW0a0flW2QpaGCcMedJzgA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=sk0CbhEGjUM3UWyu7es8gTT0QMWDzYHTbLTZBNN6d4Y=; b=U/HIKYgD0xVjIitzyYFvkaVDojMu5AcUU13eO9Kb0V8B2xxcIXNSyKypE5ZOkcEI4TfW85trBTR7GnGCFtH3YFxQ6L2eBa0cY02dW9a3KoC5jC3gb0/czieJUsoinM3RJ6HQxbpa4U5V4S2nFVhBFe1/ycv6sMlbMapImOIb7n927wRviMjIwWsUqtr4fA5NuWjDvsRgAZ+fy28rdxm9Jw8q5XVsl2JUufe6RYfE1AuWVzPh1dYLP6RgbdM31GBVIQ8KBe7JbV+Wi+CQCrVsX0iqDtXJPl08NhiW6kdJ1x0yzpKyZw6ahR3SZ9p5LdZrPD+BVw9cE1Vcb9KRICkCfQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=fail (sender ip is 178.72.21.4) smtp.rcpttodomain=dpdk.org smtp.mailfrom=napatech.com; dmarc=fail (p=none sp=none pct=100) action=none header.from=napatech.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=napatech.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=sk0CbhEGjUM3UWyu7es8gTT0QMWDzYHTbLTZBNN6d4Y=; b=dR80S/yYrMKMO7hgKHoagcNu+j8ef/R0wvk7IjkTW4ayUsR8e6sCJjcMyqmFUCXpbJIHet7v6BRwxwwPiqfYsXXbqvbAqHcmfTghkqwGrUYD7Az5gdf73yrfhu7jeb3Eo2qNAhFJioeZSPKiQlzFFrc9DXz5gcSsd4vjmiR2Vpg= Received: from DB8PR04CA0013.eurprd04.prod.outlook.com (2603:10a6:10:110::23) by AM0P190MB0674.EURP190.PROD.OUTLOOK.COM (2603:10a6:208:194::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.24; Mon, 21 Aug 2023 13:54:31 +0000 Received: from DU2PEPF0001E9C5.eurprd03.prod.outlook.com (2603:10a6:10:110:cafe::90) by DB8PR04CA0013.outlook.office365.com (2603:10a6:10:110::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.20 via Frontend Transport; Mon, 21 Aug 2023 13:54:31 +0000 X-MS-Exchange-Authentication-Results: spf=fail (sender IP is 178.72.21.4) smtp.mailfrom=napatech.com; dkim=none (message not signed) header.d=none;dmarc=fail action=none header.from=napatech.com; Received-SPF: Fail (protection.outlook.com: domain of napatech.com does not designate 178.72.21.4 as permitted sender) receiver=protection.outlook.com; client-ip=178.72.21.4; helo=localhost.localdomain.com; Received: from localhost.localdomain.com (178.72.21.4) by DU2PEPF0001E9C5.mail.protection.outlook.com (10.167.8.74) with Microsoft SMTP Server id 15.20.6699.14 via Frontend Transport; Mon, 21 Aug 2023 13:54:31 +0000 From: Mykola Kostenok To: dev@dpdk.org, mko-plv@napatech.com Cc: ckm@napatech.com Subject: [PATCH v6 8/8] net/ntnic: adds socket connection to PMD Date: Mon, 21 Aug 2023 15:54:26 +0200 Message-Id: <20230821135426.1478754-8-mko-plv@napatech.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20230821135426.1478754-1-mko-plv@napatech.com> References: <20230816132552.2483752-1-mko-plv@napatech.com> <20230821135426.1478754-1-mko-plv@napatech.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU2PEPF0001E9C5:EE_|AM0P190MB0674:EE_ X-MS-Office365-Filtering-Correlation-Id: b1f2704a-cd42-445f-d3b9-08dba24e24e9 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 1e/2BBsazCcPt7v79oO+U+usu/wT9gUvmfBC0QSNpCGorZMCnf0u4yQOweiBYWygqMf05GwcLrTQB4yEhk4WHXGKa3WYdjZfUdzxJU5fDxjLkN9966qKN1oBc1ZxZm1U89Wbs10mXoqnamkwdbZrPcBqQVKdZiz92VxCUqFcfhGKjGg+7zo5tytkVKidso4h51UQbzgx6JCJr9Yqic+/cpHWzQ0xFOA9HFH87wpBloxlGysVOaS1/lSShYEpgrVwsEk8b2ZdwMIjoM4sa88EdiDQ8JPDs6yiLcWzDVoUMm7/vtFbi7BBjxUcR66Q1MHZo0OkSQhqwc61EYZK/ZPlznuiKlxmxbFQD3+bsJTCxPvWfMf2VjC5HcVW762MeR4E/hcfdVXRyhDh/Tm63wsfaVhLotOylb4Kgayw83QlF5TwsXhUVGfNyRgE7N/+O565ZEIZWOiSIgxVSyTEzrOLGUcKcZ0ffmmYTGJKt7CSIpeRz0wdwHuOF22BX/mS3ALYEjAMnwEC3Hjprpf2B4/XyIXmmN6Io/u4F5Xk5pzxXtLulod4vAGYU+OgKJNm362ovMwZi5DAw3PRMFyN6wEknL+gQtwpc/Y0iox+6Em/lTk2qoTApsoUuyGoaPJwZmOXPyv6wAVyBEPK3PtHiyjro+4QLV0dUd8FXJAJXifPrLw28vcTgExX5YwZE+orqjQ4RSI5ZOkOy8QVsU7Tk/ZlAkcFp+xiw6W6Km/1+Ir7MSyDPOloGkaUMIR512CCnZEvh/mttoS6hkJZYMZt1Dp06g== X-Forefront-Antispam-Report: CIP:178.72.21.4; CTRY:DK; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:localhost.localdomain.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230031)(6069001)(346002)(39840400004)(376002)(136003)(396003)(82310400011)(451199024)(186009)(1800799009)(36840700001)(46966006)(118246002)(2906002)(30864003)(40480700001)(6506007)(6486002)(83380400001)(5660300002)(336012)(26005)(34020700004)(86362001)(36860700001)(47076005)(8676002)(2616005)(8936002)(956004)(107886003)(4326008)(70206006)(316002)(6512007)(70586007)(36736006)(9316004)(478600001)(356005)(81166007)(6666004)(36756003)(41300700001)(1076003)(36900700001)(559001)(579004); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: eybKw/0oFFkiLieOX7oP1GYcw6L+45RWudxFt0AbFHvoWgEJLRLGN4VqpN/yyM+u0VD5DrQ4zDnaAWL/Rqt8yRZv4sAfQIW5XcxRoRUJUCqMSt1VLZQxU0iykFUq21SbVSuYNhXtE5TQc4CyCVml0nORqyzllH2/2fgvkafFTfHuS5el2pdkyWJb00EAo/Du1Kiz+gRkj2ssNbHhyUBmqIcKGPulSoo/Nk64H3nsHLcKeqfJA1OAyOlczFKIEq9qWp2UqfRoC1iZkBYt9xKPixf2T83WnrgPjKO9cIl7k7SVQ/jNLyyZH35T9EOpv4wgOvk5kSqoQVcWDA4DUS4A+CeJRgpBfpo+NoOExqPrYZAYaZpAFaMXwVEwwbqz2SccXs+PB8laiHaA327QDrRmYEi2lCnWgMGwYaTx0cNvLnhtqkHAUBmxLM0uSmv5D7we6ENPUPGoJCAJ4GJWWlAAd8FAt2KK+XXx4jXHeWw4T9+1/cUfSQHoA0vxe5SuLOW/lDWZlQOQZejjIW+oOPBpUYl7uECt7MhlIfsdSf0IFT2r5HTGVEdydkvEDEgH/4fbrfagAaZ8/oL/Rt9CCpBNW7h1QH5nhIljbqHdZWMtxzYWP1tCS38BCRZshseMEGfFHd+Vee6ATi4e5gsUxgDSXTaR8evWl2ZW9VTmcp7j/ohfyw9InOz6hFJiKFEO2M55ys95doKUw8C3r+WthNAyGcPv5qLydmAlb717y1hu3JwV+l+XBjlWvelI9f7R8Dql+jvno1Kb/aSZVE7+kbD/X3sWvbh++rKE7myo3LFYI3w= X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Aug 2023 13:54:31.1791 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: b1f2704a-cd42-445f-d3b9-08dba24e24e9 X-MS-Exchange-CrossTenant-Id: c4540d0b-728a-4233-9da5-9ea30c7ec3ed X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=c4540d0b-728a-4233-9da5-9ea30c7ec3ed; Ip=[178.72.21.4]; Helo=[localhost.localdomain.com] X-MS-Exchange-CrossTenant-AuthSource: DU2PEPF0001E9C5.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM0P190MB0674 X-BESS-ID: 1692626077-311072-12495-15881-1 X-BESS-VER: 2019.1_20230817.1828 X-BESS-Apparent-Source-IP: 104.47.17.107 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKVoZmxoaGZkB2BlA4NcnUKDk5NT HFKMnc0jTF0jLNwDI1xdwsNcnYwDI5yUSpNhYAgWLrJEMAAAA= X-BESS-Outbound-Spam-Score: 0.50 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.250292 [from cloudscan13-215.eu-central-1a.ess.aws.cudaops.com] Rule breakdown below pts rule name description ---- ---------------------- -------------------------------- 0.50 BSF_RULE7568M META: Custom Rule 7568M 0.00 BSF_BESS_OUTBOUND META: BESS Outbound X-BESS-Outbound-Spam-Status: SCORE=0.50 using account:ESS113687 scores of KILL_LEVEL=7.0 tests=BSF_RULE7568M, BSF_BESS_OUTBOUND X-BESS-BRTS-Status: 1 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 From: Christian Koue Muf The socket connection is used by Napatech's tools for monitoring and rte_flow programming from other processes. Signed-off-by: Christian Koue Muf Reviewed-by: Mykola Kostenok --- v2: * Fixed WARNING:TYPO_SPELLING v4: * Fixed Alpine build --- drivers/net/ntnic/meson.build | 24 + .../ntconnect/include/ntconn_mod_helper.h | 97 ++ .../net/ntnic/ntconnect/include/ntconnect.h | 96 ++ .../ntnic/ntconnect/include/ntconnect_api.h | 87 ++ .../ntconnect/include/ntconnect_api_adapter.h | 221 +++ .../ntconnect/include/ntconnect_api_flow.h | 168 +++ .../ntconnect/include/ntconnect_api_meter.h | 89 ++ .../include/ntconnect_api_statistic.h | 173 +++ .../ntconnect/include/ntconnect_api_test.h | 18 + drivers/net/ntnic/ntconnect/ntconn_server.c | 97 ++ drivers/net/ntnic/ntconnect/ntconnect.c | 641 ++++++++ .../ntnic/ntconnect_modules/ntconn_adapter.c | 775 ++++++++++ .../net/ntnic/ntconnect_modules/ntconn_flow.c | 1310 +++++++++++++++++ .../ntnic/ntconnect_modules/ntconn_meter.c | 517 +++++++ .../ntnic/ntconnect_modules/ntconn_modules.h | 19 + .../net/ntnic/ntconnect_modules/ntconn_stat.c | 876 +++++++++++ .../net/ntnic/ntconnect_modules/ntconn_test.c | 146 ++ 17 files changed, 5354 insertions(+) create mode 100644 drivers/net/ntnic/ntconnect/include/ntconn_mod_helper.h create mode 100644 drivers/net/ntnic/ntconnect/include/ntconnect.h create mode 100644 drivers/net/ntnic/ntconnect/include/ntconnect_api.h create mode 100644 drivers/net/ntnic/ntconnect/include/ntconnect_api_adapter.h create mode 100644 drivers/net/ntnic/ntconnect/include/ntconnect_api_flow.h create mode 100644 drivers/net/ntnic/ntconnect/include/ntconnect_api_meter.h create mode 100644 drivers/net/ntnic/ntconnect/include/ntconnect_api_statistic.h create mode 100644 drivers/net/ntnic/ntconnect/include/ntconnect_api_test.h create mode 100644 drivers/net/ntnic/ntconnect/ntconn_server.c create mode 100644 drivers/net/ntnic/ntconnect/ntconnect.c create mode 100644 drivers/net/ntnic/ntconnect_modules/ntconn_adapter.c create mode 100644 drivers/net/ntnic/ntconnect_modules/ntconn_flow.c create mode 100644 drivers/net/ntnic/ntconnect_modules/ntconn_meter.c create mode 100644 drivers/net/ntnic/ntconnect_modules/ntconn_modules.h create mode 100644 drivers/net/ntnic/ntconnect_modules/ntconn_stat.c create mode 100644 drivers/net/ntnic/ntconnect_modules/ntconn_test.c diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build index d3c3129a0c..bc34ae80b2 100644 --- a/drivers/net/ntnic/meson.build +++ b/drivers/net/ntnic/meson.build @@ -13,6 +13,22 @@ if not dpdk_conf.has('RTE_ARCH_X86_64') subdir_done() endif +# config object +ntnic_conf = configuration_data() + +# transfer options into config object +ntnic_conf.set('NT_TOOLS', true) + +# check option 'debug' (boolean flag derived from meson buildtype) +if get_option('debug') + cflags += '-DDEBUG' +endif + +# check nt_tools build option +if ntnic_conf.get('NT_TOOLS') + cflags += '-DNT_TOOLS' +endif + # includes includes = [ include_directories('.'), @@ -26,6 +42,7 @@ includes = [ include_directories('nthw/supported'), include_directories('nthw/flow_api'), include_directories('nthw/flow_filter'), + include_directories('ntconnect/include'), include_directories('sensors'), include_directories('sensors/avr_sensors'), include_directories('sensors/board_sensors'), @@ -47,6 +64,13 @@ sources = files( 'nim/nt_link_speed.c', 'nim/qsfp_sensors.c', 'nim/sfp_sensors.c', + 'ntconnect/ntconn_server.c', + 'ntconnect/ntconnect.c', + 'ntconnect_modules/ntconn_adapter.c', + 'ntconnect_modules/ntconn_flow.c', + 'ntconnect_modules/ntconn_meter.c', + 'ntconnect_modules/ntconn_stat.c', + 'ntconnect_modules/ntconn_test.c', 'nthw/core/nthw_clock_profiles.c', 'nthw/core/nthw_fpga.c', 'nthw/core/nthw_fpga_nt200a0x.c', diff --git a/drivers/net/ntnic/ntconnect/include/ntconn_mod_helper.h b/drivers/net/ntnic/ntconnect/include/ntconn_mod_helper.h new file mode 100644 index 0000000000..f55c4141cc --- /dev/null +++ b/drivers/net/ntnic/ntconnect/include/ntconn_mod_helper.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTCONN_MOD_HELPER_H_ +#define _NTCONN_MOD_HELPER_H_ + +#include "ntconnect.h" + +/* + * Module parameter function call tree structures + */ +struct func_s { + const char *param; + struct func_s *sub_funcs; + int (*func)(void *hdl, int client_fd, struct ntconn_header_s *hdr, + char **data, int *len); +}; + +static inline int ntconn_error(char **data, int *len, const char *module, + enum ntconn_err_e err_code) +{ + *len = 0; + if (data) { + const ntconn_err_t *ntcerr = get_ntconn_error(err_code); + *data = malloc(4 + strlen(module) + 1 + + strlen(ntcerr->err_text) + 1); + if (*data) { + sprintf(*data, "----%s:%s", module, ntcerr->err_text); + *len = strlen(*data) + 1; /* add 0 - terminator */ + *(uint32_t *)*data = (uint32_t)ntcerr->err_code; + } + } + return REQUEST_ERR; +} + +static inline int ntconn_reply_status(char **data, int *len, + enum ntconn_reply_code_e code) +{ + *len = 0; + if (data) { + *data = malloc(sizeof(uint32_t)); + if (*data) { + *len = sizeof(uint32_t); + *(uint32_t *)*data = (uint32_t)code; + } + } + return REQUEST_OK; +} + +static inline int execute_function(const char *module, void *hdl, int client_id, + struct ntconn_header_s *hdr, char *function, + struct func_s *func_list, char **data, + int *len, int recur_depth) +{ + char *tok = strtok(function, ","); + + if (!tok) { + if (recur_depth == 0) + return ntconn_error(data, len, module, + NTCONN_ERR_CODE_MISSING_INVALID_PARAM); + else + return ntconn_error(data, len, module, + NTCONN_ERR_CODE_FUNCTION_PARAM_INCOMPLETE); + } + + hdr->len -= strlen(tok) + 1; + char *sub_funcs = function + strlen(tok) + 1; + int idx = 0; + + while (func_list[idx].param) { + if (strcmp(func_list[idx].param, tok) == 0) { + /* hit */ + if (func_list[idx].sub_funcs) { + return execute_function(module, hdl, client_id, + hdr, sub_funcs, + func_list[idx].sub_funcs, + data, len, + ++recur_depth); + } else if (func_list[idx].func) { + /* commands/parameters for function in text, zero-terminated */ + *data = sub_funcs; + return func_list[idx].func(hdl, client_id, hdr, + data, len); + } else { + return ntconn_error(data, len, module, + NTCONN_ERR_CODE_INTERNAL_FUNC_ERROR); + } + } + idx++; + } + /* no hits */ + return ntconn_error(data, len, module, + NTCONN_ERR_CODE_FUNC_PARAM_NOT_RECOGNIZED); +} + +#endif /* _NTCONN_MOD_HELPER_H_ */ diff --git a/drivers/net/ntnic/ntconnect/include/ntconnect.h b/drivers/net/ntnic/ntconnect/include/ntconnect.h new file mode 100644 index 0000000000..9dcf2ec0a1 --- /dev/null +++ b/drivers/net/ntnic/ntconnect/include/ntconnect.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTCONNECT_H_ +#define _NTCONNECT_H_ + +#include +#include +#include + +#include "ntconnect_api.h" + +#define REQUEST_OK 0 +#define REQUEST_ERR -1 + +typedef struct ntconn_api_s { + /* + * Name specifying this module. This name is used in the request string + */ + const char *module; + /* + * The version of this module integration + */ + uint32_t version_major; + uint32_t version_minor; + /* + * The request function: + * hdl : pointer to the context of this instance. + * client_id : identifying the client. To be able to manage client specific data/state. + * function : pointer to the remainder of the request command (Layer 3). May be modified. + * an example: ;adapter;get,interface,port0,link_speed function will + * then be 'get,interface,port0,link_speed'. + * hdr : header for length of command string and length of binary blop. + * The command string will start at "*data" and will have the length hdr->len. + * The binary blob will start at "&(*data)[hdr->len]" and will have the length + * hdr->blob_len. + * data : pointer to the resulting data. Typically this will be allocated. + * len : length of the data in the reply. + * + * return : REQUEST_OK on success, REQUEST_ERR on failure. On failure, the data and len + * can contain an describing error text + */ + int (*request)(void *hdl, int client_id, struct ntconn_header_s *hdr, + char *function, char **data, int *len); + /* + * After each request call, and when 'len' returns > 0, this function is called + * after sending reply to client. + * hdl : pointer to the context of this instance. + * data : the data pointer returned in the request function + */ + void (*free_data)(void *hdl, char *data); + /* + * Clean up of client specific data allocations. Called when client disconnects from server + * hdl : pointer to the context of this instance. + * client_id : identifying the client. + */ + void (*client_cleanup)(void *hdl, int client_id); +} ntconnapi_t; + +/* + * ntconn error + */ +typedef struct ntconn_err_s { + uint32_t err_code; + const char *err_text; +} ntconn_err_t; + +const ntconn_err_t *get_ntconn_error(enum ntconn_err_e err_code); + +typedef struct ntconn_mod_s { + void *hdl; + struct pci_id_s addr; + const ntconnapi_t *op; + + pthread_mutex_t mutex; + struct ntconn_mod_s *next; +} ntconn_mod_t; + +struct ntconn_server_s { + int serv_fd; + int running; + /* + * list of different pci_ids registered aka SmartNICs + */ + struct pci_id_s pci_id_list[MAX_PCI_IDS]; /* 0 - terminates */ + cpu_set_t cpuset; +}; + +int ntconn_server_register(void *server); + +int register_ntconn_mod(const struct rte_pci_addr *addr, void *hdl, + const ntconnapi_t *op); +int ntconnect_init(const char *sockname, cpu_set_t cpuset); + +#endif /* _NTCONNECT_H_ */ diff --git a/drivers/net/ntnic/ntconnect/include/ntconnect_api.h b/drivers/net/ntnic/ntconnect/include/ntconnect_api.h new file mode 100644 index 0000000000..14668bf2ee --- /dev/null +++ b/drivers/net/ntnic/ntconnect/include/ntconnect_api.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTCONNECT_API_H_ +#define _NTCONNECT_API_H_ + +#include "stdint.h" +/* + * NtConnect API + */ + +#define NTCONNECT_SOCKET "/var/run/ntconnect/ntconnect.sock" + +enum ntconn_err_e { + NTCONN_ERR_CODE_NONE = 0U, + NTCONN_ERR_CODE_INTERNAL_ERROR, + NTCONN_ERR_CODE_INVALID_REQUEST, + NTCONN_ERR_CODE_INTERNAL_REPLY_ERROR, + NTCONN_ERR_CODE_NO_DATA, + NTCONN_ERR_CODE_NOT_YET_IMPLEMENTED, + NTCONN_ERR_CODE_MISSING_INVALID_PARAM, + NTCONN_ERR_CODE_FUNCTION_PARAM_INCOMPLETE, + NTCONN_ERR_CODE_INTERNAL_FUNC_ERROR, + NTCONN_ERR_CODE_FUNC_PARAM_NOT_RECOGNIZED, +}; + +enum ntconn_reply_code_e { + NTCONN_ADAPTER_ERR_PORT_STATE_FAIL = 0U, + NTCONN_ADAPTER_ERR_WRONG_LINK_STATE, + NTCONN_ADAPTER_ERR_TX_POWER_FAIL, +}; + +enum { + NTCONN_TAG_NONE, + NTCONN_TAG_REQUEST, + NTCONN_TAG_REPLY, + NTCONN_TAG_ERROR +}; + +#define MESSAGE_BUFFER 256 +#define MAX_ERR_MESSAGE_LENGTH 256 + +struct reply_err_s { + enum ntconn_err_e err_code; + char msg[MAX_ERR_MESSAGE_LENGTH]; +}; + +#define NTCMOD_HDR_LEN sizeof(struct ntconn_header_s) +struct ntconn_header_s { + uint16_t tag; + uint16_t len; + uint32_t blob_len; +}; + +struct pci_id_s { + union { + uint64_t pci_id; + struct { + uint32_t domain; + uint8_t bus; + uint8_t devid; + uint8_t function; + uint8_t pad; + }; + }; +}; + +#define VERSION_HI(version) ((unsigned int)((version) >> 32)) +#define VERSION_LO(version) ((unsigned int)((version) & 0xffffffff)) + +/* + * Binary interface description for ntconnect module replies + */ + +/* + * server get,nic_pci_ids + */ +#define MAX_PCI_IDS 16 +#define NICS_PCI_ID_LEN 12 + +struct ntc_nic_pci_ids_s { + char nic_pci_id[MAX_PCI_IDS][NICS_PCI_ID_LEN + 1]; + int num_nics; +}; + +#endif /* _NTCONNECT_API_H_ */ diff --git a/drivers/net/ntnic/ntconnect/include/ntconnect_api_adapter.h b/drivers/net/ntnic/ntconnect/include/ntconnect_api_adapter.h new file mode 100644 index 0000000000..affe905027 --- /dev/null +++ b/drivers/net/ntnic/ntconnect/include/ntconnect_api_adapter.h @@ -0,0 +1,221 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTCONNECT_API_ADAPTER_H_ +#define _NTCONNECT_API_ADAPTER_H_ + +/* + * adapter get,interfaces + */ +enum port_speed { + PORT_LINK_SPEED_UNKNOWN, + PORT_LINK_SPEED_NONE_REPORTED, + PORT_LINK_SPEED_10M, + PORT_LINK_SPEED_100M, + PORT_LINK_SPEED_1G, + PORT_LINK_SPEED_10G, + PORT_LINK_SPEED_25G, + PORT_LINK_SPEED_40G, + PORT_LINK_SPEED_50G, + PORT_LINK_SPEED_100G, +}; + +enum port_states { + PORT_STATE_DISABLED, + PORT_STATE_NIM_PRESENT, + PORT_STATE_NIM_ABSENT, + PORT_STATE_VIRTUAL_UNATTACHED, + PORT_STATE_VIRTUAL_SPLIT, + PORT_STATE_VIRTUAL_PACKED, + PORT_STATE_VIRTUAL_RELAY, +}; + +enum port_link { PORT_LINK_UNKNOWN, PORT_LINK_UP, PORT_LINK_DOWN }; + +enum port_type { + PORT_TYPE_PHY_NORMAL, /* Normal phy port (no LAG) */ + /* Link aggregated phy port in active/active LAG configuration */ + PORT_TYPE_PHY_LAG_ACTIVE_ACTIVE, + PORT_TYPE_PHY_LAG_PRIMARY, /* Primary phy port in active/backup LAG configuration */ + PORT_TYPE_PHY_LAG_BACKUP, /* Backup phy port in active/backup LAG configuration */ + PORT_TYPE_VIRT, + PORT_TYPE_LAST +}; + +enum nim_identifier_e { + NIM_UNKNOWN = 0x00, /* Nim type is unknown */ + NIM_GBIC = 0x01, /* Nim type = GBIC */ + NIM_FIXED = 0x02, /* Nim type = FIXED */ + NIM_SFP_SFP_PLUS = 0x03, /* Nim type = SFP/SFP+ */ + NIM_300_PIN_XBI = 0x04, /* Nim type = 300 pin XBI */ + NIM_XEN_PAK = 0x05, /* Nim type = XEN-PAK */ + NIM_XFP = 0x06, /* Nim type = XFP */ + NIM_XFF = 0x07, /* Nim type = XFF */ + NIM_XFP_E = 0x08, /* Nim type = XFP-E */ + NIM_XPAK = 0x09, /* Nim type = XPAK */ + NIM_X2 = 0x0A, /* Nim type = X2 */ + NIM_DWDM = 0x0B, /* Nim type = DWDM */ + NIM_QSFP = 0x0C, /* Nim type = QSFP */ + NIM_QSFP_PLUS = 0x0D, /* Nim type = QSFP+ */ + NIM_QSFP28 = 0x11, /* Nim type = QSFP28 */ + NIM_CFP4 = 0x12, /* Nim type = CFP4 */ +}; + +/* + * Port types + */ +enum port_type_e { + PORT_TYPE_NOT_AVAILABLE = + 0, /* The NIM/port type is not available (unknown) */ + PORT_TYPE_NOT_RECOGNISED, /* The NIM/port type not recognized */ + PORT_TYPE_RJ45, /* RJ45 type */ + PORT_TYPE_SFP_NOT_PRESENT, /* SFP type but slot is empty */ + PORT_TYPE_SFP_SX, /* SFP SX */ + PORT_TYPE_SFP_SX_DD, /* SFP SX digital diagnostic */ + PORT_TYPE_SFP_LX, /* SFP LX */ + PORT_TYPE_SFP_LX_DD, /* SFP LX digital diagnostic */ + PORT_TYPE_SFP_ZX, /* SFP ZX */ + PORT_TYPE_SFP_ZX_DD, /* SFP ZX digital diagnostic */ + PORT_TYPE_SFP_CU, /* SFP copper */ + PORT_TYPE_SFP_CU_DD, /* SFP copper digital diagnostic */ + PORT_TYPE_SFP_NOT_RECOGNISED, /* SFP unknown */ + PORT_TYPE_XFP, /* XFP */ + PORT_TYPE_XPAK, /* XPAK */ + PORT_TYPE_SFP_CU_TRI_SPEED, /* SFP copper tri-speed */ + PORT_TYPE_SFP_CU_TRI_SPEED_DD, /* SFP copper tri-speed digital diagnostic */ + PORT_TYPE_SFP_PLUS, /* SFP+ type */ + PORT_TYPE_SFP_PLUS_NOT_PRESENT, /* SFP+ type but slot is empty */ + PORT_TYPE_XFP_NOT_PRESENT, /* XFP type but slot is empty */ + PORT_TYPE_QSFP_PLUS_NOT_PRESENT, /* QSFP type but slot is empty */ + PORT_TYPE_QSFP_PLUS, /* QSFP type */ + PORT_TYPE_SFP_PLUS_PASSIVE_DAC, /* SFP+ Passive DAC */ + PORT_TYPE_SFP_PLUS_ACTIVE_DAC, /* SFP+ Active DAC */ + PORT_TYPE_CFP4, /* CFP4 type */ + PORT_TYPE_CFP4_LR4 = PORT_TYPE_CFP4, /* CFP4 100G, LR4 type */ + PORT_TYPE_CFP4_NOT_PRESENT, /* CFP4 type but slot is empty */ + PORT_TYPE_INITIALIZE, /* The port type is not fully established yet */ + PORT_TYPE_NIM_NOT_PRESENT, /* Generic "Not present" */ + PORT_TYPE_HCB, /* Test mode: Host Compliance Board */ + PORT_TYPE_NOT_SUPPORTED, /* The NIM type is not supported in this context */ + PORT_TYPE_SFP_PLUS_DUAL_RATE, /* SFP+ supports 1G/10G */ + PORT_TYPE_CFP4_SR4, /* CFP4 100G, SR4 type */ + PORT_TYPE_QSFP28_NOT_PRESENT, /* QSFP28 type but slot is empty */ + PORT_TYPE_QSFP28, /* QSFP28 type */ + PORT_TYPE_QSFP28_SR4, /* QSFP28-SR4 type */ + PORT_TYPE_QSFP28_LR4, /* QSFP28-LR4 type */ + /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */ + PORT_TYPE_QSFP_PLUS_4X10, + /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */ + PORT_TYPE_QSFP_PASSIVE_DAC_4X10, + PORT_TYPE_QSFP_PASSIVE_DAC = + PORT_TYPE_QSFP_PASSIVE_DAC_4X10, /* QSFP passive DAC type */ + /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */ + PORT_TYPE_QSFP_ACTIVE_DAC_4X10, + PORT_TYPE_QSFP_ACTIVE_DAC = + PORT_TYPE_QSFP_ACTIVE_DAC_4X10, /* QSFP active DAC type */ + PORT_TYPE_SFP_28, /* SFP28 type */ + PORT_TYPE_SFP_28_SR, /* SFP28-SR type */ + PORT_TYPE_SFP_28_LR, /* SFP28-LR type */ + PORT_TYPE_SFP_28_CR_CA_L, /* SFP28-CR-CA-L type */ + PORT_TYPE_SFP_28_CR_CA_S, /* SFP28-CR-CA-S type */ + PORT_TYPE_SFP_28_CR_CA_N, /* SFP28-CR-CA-N type */ + PORT_TYPE_QSFP28_CR_CA_L, /* QSFP28-CR-CA-L type */ + PORT_TYPE_QSFP28_CR_CA_S, /* QSFP28-CR-CA-S type */ + PORT_TYPE_QSFP28_CR_CA_N, /* QSFP28-CR-CA-N type */ + PORT_TYPE_SFP_28_SR_DR, /* SFP28-SR-DR type */ + PORT_TYPE_SFP_28_LR_DR, /* SFP28-LR-DR type */ + PORT_TYPE_SFP_FX, /* SFP FX */ + PORT_TYPE_SFP_PLUS_CU, /* SFP+ CU type */ + PORT_TYPE_QSFP28_FR, /* QSFP28-FR type. Uses PAM4 modulation on one lane only */ + PORT_TYPE_QSFP28_DR, /* QSFP28-DR type. Uses PAM4 modulation on one lane only */ + PORT_TYPE_QSFP28_LR, /* QSFP28-LR type. Uses PAM4 modulation on one lane only */ +}; + +struct mac_addr_s { + uint8_t addr_b[6]; +}; + +struct nim_link_length_s { + /* NIM link length (in meters) supported SM (9um). A value of 0xFFFF indicates that the + * length is >= 65535 m + */ + uint16_t sm; + uint16_t ebw; /* NIM link length (in meters) supported EBW (50um) */ + uint16_t mm50; /* NIM link length (in meters) supported MM (50um) */ + uint16_t mm62; /* NIM link length (in meters) supported MM (62.5um) */ + uint16_t copper; /* NIM link length (in meters) supported copper */ +}; + +struct nim_data_s { + uint8_t nim_id; + uint8_t port_type; + char vendor_name[17]; + char prod_no[17]; + char serial_no[17]; + char date[9]; + char rev[5]; + uint8_t pwr_level_req; + uint8_t pwr_level_cur; + struct nim_link_length_s link_length; +}; + +struct sensor { + uint8_t sign; + uint8_t type; + uint32_t current_value; + uint32_t min_value; + uint32_t max_value; + char name[50]; +}; + +struct ntc_sensors_s { + uint16_t adapter_sensors_cnt; + uint16_t ports_cnt; + uint16_t nim_sensors_cnt[8]; + char adapter_name[24]; +}; + +#define MAX_RSS_QUEUES 128 + +enum queue_dir_e { QUEUE_INPUT, QUEUE_OUTPUT }; + +struct queue_s { + enum queue_dir_e dir; + int idx; +}; + +struct ntc_interface_s { + uint8_t port_id; + enum port_type type; + enum port_link link; + enum port_states port_state; + enum port_speed port_speed; + struct pci_id_s pci_id; + struct mac_addr_s mac; + struct nim_data_s nim_data; + uint16_t mtu; + /* attached queues */ + struct { + struct queue_s queue[MAX_RSS_QUEUES]; + int num_queues; + }; +}; + +/* + * adapter get,interfaces + */ +struct ntc_interfaces_s { + int final_list; + uint8_t nb_ports; + struct ntc_interface_s intf[]; +}; + +/* + * adapter get,info + */ +struct ntc_adap_get_info_s { + char *fw_version[32]; +}; + +#endif /* _NTCONNECT_API_ADAPTER_H_ */ diff --git a/drivers/net/ntnic/ntconnect/include/ntconnect_api_flow.h b/drivers/net/ntnic/ntconnect/include/ntconnect_api_flow.h new file mode 100644 index 0000000000..4091d61d7d --- /dev/null +++ b/drivers/net/ntnic/ntconnect/include/ntconnect_api_flow.h @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTCONNECT_API_FILTER_H_ +#define _NTCONNECT_API_FILTER_H_ + +#include "stream_binary_flow_api.h" + +/* + * Create structures allocating the space to carry through ntconnect interface + */ +#define MAX_FLOW_STREAM_ELEM 16 +#define MAX_FLOW_STREAM_QUERY_DATA 1024 +#define MAX_FLOW_STREAM_ERROR_MSG 128 +#define MAX_FLOW_STREAM_VXLAN_TUN_ELEM 8 +#define MAX_FLOW_STREAM_COUNT_ACTIONS 4 + +#define MAX_PATH_LEN 128 + +enum ntconn_flow_err_e { + NTCONN_FLOW_ERR_NONE = 0, + NTCONN_FLOW_ERR_INTERNAL_ERROR = 0x100, + NTCONN_FLOW_ERR_PORT_IS_NOT_INITIALIZED, + NTCONN_FLOW_ERR_INVALID_PORT, + NTCONN_FLOW_ERR_UNEXPECTED_VIRTIO_PATH, + NTCONN_FLOW_ERR_UNSUPPORTED_ADAPTER, + NTCONN_FLOW_ERR_TO_MANY_FLOWS, + NTCONN_FLOW_ERR_NOT_YET_IMPLEMENTED, + NTCONN_FLOW_ERR_NO_VF_QUEUES, +}; + +struct flow_elem_types_s { + int valid; + union { + int start_addr; + struct flow_elem_eth eth; + struct flow_elem_vlan vlan[2]; + struct flow_elem_ipv4 ipv4; + struct flow_elem_ipv6 ipv6; + struct flow_elem_sctp sctp; + struct flow_elem_tcp tcp; + struct flow_elem_udp udp; + struct flow_elem_icmp icmp; + struct flow_elem_vxlan vxlan; + struct flow_elem_port_id port_id; + struct flow_elem_tag tag; + } u; +}; + +struct flow_elem_cpy { + enum flow_elem_type type; /* element type */ + struct flow_elem_types_s spec_cpy; + struct flow_elem_types_s mask_cpy; +}; + +struct flow_action_vxlan_encap_cpy { + /* Encapsulating vxlan tunnel definition */ + struct flow_elem_cpy vxlan_tunnel[MAX_FLOW_STREAM_VXLAN_TUN_ELEM]; +}; + +struct flow_action_rss_cpy { + struct flow_action_rss rss; + uint16_t cpy_queue[FLOW_MAX_QUEUES]; +}; + +#define MAX_ACTION_ENCAP_DATA 512 +struct flow_action_decap_cpy { + uint8_t data[MAX_ACTION_ENCAP_DATA]; + size_t size; + struct flow_elem_cpy item_cpy + [RAW_ENCAP_DECAP_ELEMS_MAX]; /* Need room for end command */ + int item_count; +}; + +struct flow_action_encap_cpy { + uint8_t data[MAX_ACTION_ENCAP_DATA]; + size_t size; + struct flow_elem_cpy item_cpy + [RAW_ENCAP_DECAP_ELEMS_MAX]; /* Need room for end command */ + int item_count; +}; + +struct flow_action_types_s { + int valid; + union { + int start_addr; + struct flow_action_rss_cpy rss; + struct flow_action_push_vlan vlan; + struct flow_action_set_vlan_vid vlan_vid; + struct flow_action_vxlan_encap_cpy vxlan; + struct flow_action_count count; + struct flow_action_mark mark; + struct flow_action_port_id port_id; + struct flow_action_tag tag; + struct flow_action_queue queue; + struct flow_action_decap_cpy decap; + struct flow_action_encap_cpy encap; + struct flow_action_jump jump; + struct flow_action_meter meter; + } u; +}; + +struct flow_action_cpy { + enum flow_action_type type; + struct flow_action_types_s conf_cpy; +}; + +struct query_flow_ntconnect { + uint8_t port; + struct flow_action_cpy action; + uint64_t flow; +}; + +struct create_flow_ntconnect { + uint8_t port; + uint8_t vport; + struct flow_attr attr; + struct flow_elem_cpy elem[MAX_FLOW_STREAM_ELEM]; + struct flow_action_cpy action[MAX_FLOW_STREAM_ELEM]; +}; + +struct destroy_flow_ntconnect { + uint8_t port; + uint64_t flow; +}; + +#define ERR_MSG_LEN 128LLU + +struct flow_setport_return { + struct flow_queue_id_s queues[FLOW_MAX_QUEUES]; + uint8_t num_queues; +}; + +struct flow_error_return_s { + enum flow_error_e type; + char err_msg[ERR_MSG_LEN]; + int status; +}; + +struct create_flow_return_s { + uint64_t flow; +}; + +struct validate_flow_return_s { + int status; +}; + +struct query_flow_return_s { + enum flow_error_e type; + char err_msg[ERR_MSG_LEN]; + int status; + uint32_t data_length; + uint8_t data[]; +}; + +struct flow_return_s { + enum flow_error_e type; + char err_msg[ERR_MSG_LEN]; + int status; +}; + +struct flow_error_ntconn { + enum flow_error_e type; + char message[ERR_MSG_LEN]; +}; + +#endif /* _NTCONNECT_API_FILTER_H_ */ diff --git a/drivers/net/ntnic/ntconnect/include/ntconnect_api_meter.h b/drivers/net/ntnic/ntconnect/include/ntconnect_api_meter.h new file mode 100644 index 0000000000..901b0ccba1 --- /dev/null +++ b/drivers/net/ntnic/ntconnect/include/ntconnect_api_meter.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTCONNECT_METER_FILTER_H_ +#define _NTCONNECT_METER_FILTER_H_ + +#define FLOW_COOKIE 0x12344321 + +/* + * Create structures allocating the space to carry through ntconnect interface + */ + +#define MAX_PATH_LEN 128 + +enum ntconn_meter_err_e { + NTCONN_METER_ERR_NONE = 0, + NTCONN_METER_ERR_INTERNAL_ERROR = 0x100, + NTCONN_METER_ERR_INVALID_PORT, + NTCONN_METER_ERR_UNEXPECTED_VIRTIO_PATH, + NTCONN_METER_ERR_PROFILE_ID, + NTCONN_METER_ERR_POLICY_ID, + NTCONN_METER_ERR_METER_ID, +}; + +enum ntconn_meter_command_e { + UNKNOWN_CMD, + ADD_PROFILE, + DEL_PROFILE, + ADD_POLICY, + DEL_POLICY, + CREATE_MTR, + DEL_MTR +}; + +#define ERR_MSG_LEN 128LLU + +struct meter_error_return_s { + enum rte_mtr_error_type type; + int status; + char err_msg[ERR_MSG_LEN]; +}; + +struct meter_setup_s { + uint8_t vport; + uint32_t id; + int shared; + union { + struct rte_mtr_meter_profile profile; + struct { + struct rte_mtr_meter_policy_params policy; + struct rte_flow_action actions_green[2]; + struct rte_flow_action actions_yellow[2]; + struct rte_flow_action actions_red[2]; + } p; + struct rte_mtr_params mtr_params; + }; +}; + +struct meter_get_stat_s { + uint8_t vport; + uint32_t mtr_id; + int clear; +}; + +struct meter_return_stat_s { + struct rte_mtr_stats stats; + uint64_t stats_mask; +}; + +struct meter_setup_ptr_s { + uint32_t id; + int shared; + union { + struct rte_mtr_meter_profile *profile; + struct rte_mtr_meter_policy_params *policy; + struct rte_mtr_params *mtr_params; + }; +}; + +struct meter_return_s { + int status; +}; + +struct meter_capabilities_return_s { + struct rte_mtr_capabilities cap; +}; + +#endif /* _NTCONNECT_METER_FILTER_H_ */ diff --git a/drivers/net/ntnic/ntconnect/include/ntconnect_api_statistic.h b/drivers/net/ntnic/ntconnect/include/ntconnect_api_statistic.h new file mode 100644 index 0000000000..1022bc2056 --- /dev/null +++ b/drivers/net/ntnic/ntconnect/include/ntconnect_api_statistic.h @@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTCONNECT_API_STATISTIC_H_ +#define _NTCONNECT_API_STATISTIC_H_ + +/* + * Supported defined statistic records for Stat layout version 6 - defined in nthw_stat module + */ +#define NUM_STAT_RECORD_TYPE_COLOR \ + (sizeof(struct color_type_fields_s) / sizeof(uint64_t)) +struct color_type_fields_s { + uint64_t pkts; + uint64_t octets; + uint64_t tcp_flgs; +}; + +#define NUM_STAT_RECORD_TYPE_FLOWMATCHER \ + (sizeof(struct flowmatcher_type_fields_s) / sizeof(uint64_t)) +struct flowmatcher_type_fields_s { + /* FLM 0.17 */ + uint64_t current; + uint64_t learn_done; + uint64_t learn_ignore; + uint64_t learn_fail; + uint64_t unlearn_done; + uint64_t unlearn_ignore; + uint64_t auto_unlearn_done; + uint64_t auto_unlearn_ignore; + uint64_t auto_unlearn_fail; + uint64_t timeout_unlearn_done; + uint64_t rel_done; + uint64_t rel_ignore; + uint64_t prb_done; + uint64_t prb_ignore; + /* FLM 0.20 */ + uint64_t sta_done; + uint64_t inf_done; + uint64_t inf_skip; + uint64_t pck_hit; + uint64_t pck_miss; + uint64_t pck_unh; + uint64_t pck_dis; + uint64_t csh_hit; + uint64_t csh_miss; + uint64_t csh_unh; + uint64_t cuc_start; + uint64_t cuc_move; +}; + +#define NUM_STAT_RECORD_TYPE_QUEUE \ + (sizeof(struct queue_type_fields_s) / sizeof(uint64_t)) +struct queue_type_fields_s { + uint64_t flush_pkts; + uint64_t drop_pkts; + uint64_t fwd_pkts; + uint64_t dbs_drop_pkts; + uint64_t flush_octets; + uint64_t drop_octets; + uint64_t fwd_octets; + uint64_t dbs_drop_octets; +}; + +/* + * Port stat counters for virtualization NICS with virtual ports support + */ +#define NUM_STAT_RECORD_TYPE_RX_PORT_VIRT \ + (sizeof(struct rtx_type_fields_virt_s) / sizeof(uint64_t)) +/* same for Rx and Tx counters on Virt */ +#define NUM_STAT_RECORD_TYPE_TX_PORT_VIRT NUM_STAT_RECORD_TYPE_RX_PORT_VIRT +struct rtx_type_fields_virt_s { + uint64_t octets; + uint64_t pkts; + uint64_t drop_events; + uint64_t qos_drop_octets; + uint64_t qos_drop_pkts; +}; + +/* + * Port RMON counters for Cap devices + */ +struct stat_rmon_s { + /* Sums that are calculated by software */ + uint64_t drop_events; + uint64_t pkts; + /* Read from FPGA */ + uint64_t octets; + uint64_t broadcast_pkts; + uint64_t multicast_pkts; + uint64_t unicast_pkts; + uint64_t pkts_alignment; + uint64_t pkts_code_violation; + uint64_t pkts_crc; + uint64_t undersize_pkts; + uint64_t oversize_pkts; + uint64_t fragments; + uint64_t jabbers_not_truncated; + uint64_t jabbers_truncated; + uint64_t pkts_64_octets; + uint64_t pkts_65_to_127_octets; + uint64_t pkts_128_to_255_octets; + uint64_t pkts_256_to_511_octets; + uint64_t pkts_512_to_1023_octets; + uint64_t pkts_1024_to_1518_octets; + uint64_t pkts_1519_to_2047_octets; + uint64_t pkts_2048_to_4095_octets; + uint64_t pkts_4096_to_8191_octets; + uint64_t pkts_8192_to_max_octets; +}; + +#define NUM_STAT_RECORD_TYPE_RX_PORT_CAP \ + (sizeof(struct rx_type_fields_cap_s) / sizeof(uint64_t)) +struct rx_type_fields_cap_s { + struct stat_rmon_s rmon; + uint64_t mac_drop_events; + uint64_t pkts_lr; + /* Rx only port counters */ + uint64_t duplicate; + uint64_t pkts_ip_chksum_error; + uint64_t pkts_udp_chksum_error; + uint64_t pkts_tcp_chksum_error; + uint64_t pkts_giant_undersize; + uint64_t pkts_baby_giant; + uint64_t pkts_not_isl_vlan_mpls; + uint64_t pkts_isl; + uint64_t pkts_vlan; + uint64_t pkts_isl_vlan; + uint64_t pkts_mpls; + uint64_t pkts_isl_mpls; + uint64_t pkts_vlan_mpls; + uint64_t pkts_isl_vlan_mpls; + uint64_t pkts_no_filter; + uint64_t pkts_dedup_drop; + uint64_t pkts_filter_drop; + uint64_t pkts_overflow; + uint64_t pkts_dbs_drop; + uint64_t octets_no_filter; + uint64_t octets_dedup_drop; + uint64_t octets_filter_drop; + uint64_t octets_overflow; + uint64_t octets_dbs_drop; + uint64_t ipft_first_hit; + uint64_t ipft_first_not_hit; + uint64_t ipft_mid_hit; + uint64_t ipft_mid_not_hit; + uint64_t ipft_last_hit; + uint64_t ipft_last_not_hit; +}; + +#define NUM_STAT_RECORD_TYPE_TX_PORT_CAP \ + (sizeof(struct tx_type_fields_cap_s) / sizeof(uint64_t)) +struct tx_type_fields_cap_s { + struct stat_rmon_s rmon; +}; + +/* + * stat get,colors + * stat get,queues + * stat get,rx_counters + * stat get,tx_counters + */ +#define STAT_INFO_ELEMENTS \ + (sizeof(struct ntc_stat_get_data_s) / sizeof(uint64_t)) + +struct ntc_stat_get_data_s { + uint64_t nb_counters; + uint64_t timestamp; + uint64_t is_virt; + uint64_t data[]; +}; + +#endif /* _NTCONNECT_API_STATISTIC_H_ */ diff --git a/drivers/net/ntnic/ntconnect/include/ntconnect_api_test.h b/drivers/net/ntnic/ntconnect/include/ntconnect_api_test.h new file mode 100644 index 0000000000..44cacbd931 --- /dev/null +++ b/drivers/net/ntnic/ntconnect/include/ntconnect_api_test.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTCONNECT_TEST_FILTER_H_ +#define _NTCONNECT_TEST_FILTER_H_ + +/* + * Create structures allocating the space to carry through ntconnect interface + */ + +struct test_s { + int number; + int status; + uint64_t test[]; +}; + +#endif /* _NTCONNECT_TEST_FILTER_H_ */ diff --git a/drivers/net/ntnic/ntconnect/ntconn_server.c b/drivers/net/ntnic/ntconnect/ntconn_server.c new file mode 100644 index 0000000000..34a3c19955 --- /dev/null +++ b/drivers/net/ntnic/ntconnect/ntconn_server.c @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include + +#include "ntconnect.h" +#include "ntconn_mod_helper.h" +#include "nt_util.h" +#include "ntlog.h" + +/* + * Server module always registered on 0000:00:00.0 + */ +#define this_module_name "server" + +#define NTCONNECT_SERVER_VERSION_MAJOR 0U +#define NTCONNECT_SERVER_VERSION_MINOR 1U + +static int func_get_nic_pci(void *hdl, int client_fd, + struct ntconn_header_s *hdr, char **data, int *len); +static struct func_s funcs_get_level1[] = { + { "nic_pci_ids", NULL, func_get_nic_pci }, + { NULL, NULL, NULL }, +}; + +/* + * Entry level + */ +static struct func_s server_entry_funcs[] = { + { "get", funcs_get_level1, NULL }, + { NULL, NULL, NULL }, +}; + +static int func_get_nic_pci(void *hdl, int client_fd _unused, + struct ntconn_header_s *hdr _unused, char **data, + int *len) +{ + struct ntconn_server_s *serv = (struct ntconn_server_s *)hdl; + struct ntc_nic_pci_ids_s *npci = + calloc(1, sizeof(struct ntc_nic_pci_ids_s)); + if (!npci) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "memory allocation failed"); + return REQUEST_ERR; + } + int i = 0; + + while (i < MAX_PCI_IDS && serv->pci_id_list[i].pci_id) { + sprintf(npci->nic_pci_id[i], "%04x:%02x:%02x.%x", + serv->pci_id_list[i].domain & 0xffff, + serv->pci_id_list[i].bus, serv->pci_id_list[i].devid, + serv->pci_id_list[i].function); + i++; + } + npci->num_nics = i; + *data = (char *)npci; + *len = sizeof(struct ntc_nic_pci_ids_s); + + return REQUEST_OK; +} + +static int ntconn_server_request(void *hdl, int client_id, + struct ntconn_header_s *hdr, char *function, + char **data, int *len) +{ + return execute_function(this_module_name, hdl, client_id, hdr, function, + server_entry_funcs, data, len, 0); +} + +static void ntconn_server_free_data(void *hdl _unused, char *data) +{ + if (data) { +#ifdef DEBUG + NT_LOG(DBG, NTCONNECT, "server free data\n"); +#endif + free(data); + } +} + +static const ntconnapi_t ntconn_server_op = { this_module_name, + NTCONNECT_SERVER_VERSION_MAJOR, + NTCONNECT_SERVER_VERSION_MINOR, + ntconn_server_request, + ntconn_server_free_data, + NULL + }; + +int ntconn_server_register(void *server) +{ + const struct rte_pci_addr addr = { + .domain = 0, .bus = 0, .devid = 0, .function = 0 + }; + + return register_ntconn_mod(&addr, server, &ntconn_server_op); +} diff --git a/drivers/net/ntnic/ntconnect/ntconnect.c b/drivers/net/ntnic/ntconnect/ntconnect.c new file mode 100644 index 0000000000..22ef7828c7 --- /dev/null +++ b/drivers/net/ntnic/ntconnect/ntconnect.c @@ -0,0 +1,641 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nt_util.h" +#include "ntconnect.h" +#include "ntconnect_api.h" +#include "ntlog.h" + +/* clang-format off */ +ntconn_err_t ntconn_err[] = { + {NTCONN_ERR_CODE_NONE, "Success"}, + {NTCONN_ERR_CODE_INTERNAL_ERROR, "Internal error"}, + {NTCONN_ERR_CODE_INTERNAL_REPLY_ERROR, "Internal error in reply from module"}, + {NTCONN_ERR_CODE_NO_DATA, "No data found"}, + {NTCONN_ERR_CODE_INVALID_REQUEST, "Invalid request"}, + {NTCONN_ERR_CODE_NOT_YET_IMPLEMENTED, "Function not yet implemented"}, + {NTCONN_ERR_CODE_INTERNAL_FUNC_ERROR, "Internal error in function call list"}, + {NTCONN_ERR_CODE_MISSING_INVALID_PARAM, "Missing or invalid parameter"}, + {NTCONN_ERR_CODE_FUNCTION_PARAM_INCOMPLETE, "Function parameter is incomplete"}, + {NTCONN_ERR_CODE_FUNC_PARAM_NOT_RECOGNIZED, + "Function or parameter not recognized/supported"}, + {-1, NULL} +}; + +/* clang-format on */ + +static ntconn_mod_t *ntcmod_base; +static pthread_t tid; +static pthread_t ctid; +static struct ntconn_server_s ntconn_serv; + +const ntconn_err_t *get_ntconn_error(enum ntconn_err_e err_code) +{ + int idx = 0; + + while (ntconn_err[idx].err_code != (uint32_t)-1 && + ntconn_err[idx].err_code != err_code) + idx++; + if (ntconn_err[idx].err_code == (uint32_t)-1) + idx = 1; + + return &ntconn_err[idx]; +} + +int register_ntconn_mod(const struct rte_pci_addr *addr, void *hdl, + const ntconnapi_t *op) +{ + /* Verify and check module name is unique */ +#ifdef DEBUG + NT_LOG(DBG, NTCONNECT, + "Registering pci: %04x:%02x:%02x.%x, module %s\n", addr->domain, + addr->bus, addr->devid, addr->function, op->module); +#endif + + ntconn_mod_t *ntcmod = (ntconn_mod_t *)malloc(sizeof(ntconn_mod_t)); + + if (!ntcmod) { + NT_LOG(ERR, NTCONNECT, "memory allocation failed"); + return -1; + } + ntcmod->addr.domain = addr->domain; + ntcmod->addr.bus = addr->bus; + ntcmod->addr.devid = addr->devid; + ntcmod->addr.function = addr->function; + ntcmod->addr.pad = 0; + + ntcmod->hdl = hdl; + ntcmod->op = op; + pthread_mutex_init(&ntcmod->mutex, NULL); + + ntcmod->next = ntcmod_base; + ntcmod_base = ntcmod; + + if (ntcmod->addr.pci_id) { /* Avoid server fake pci_id */ + int i; + + for (i = 0; i < MAX_PCI_IDS; i++) { + if (ntconn_serv.pci_id_list[i].pci_id == 0) { + NT_LOG(DBG, NTCONNECT, + "insert at index %i PCI ID %" PRIX64 "\n", i, + ntcmod->addr.pci_id); + ntconn_serv.pci_id_list[i].pci_id = + ntcmod->addr.pci_id; + break; + } else if (ntconn_serv.pci_id_list[i].pci_id == + ntcmod->addr.pci_id) + break; + } + } + + return 0; +} + +static int unix_build_address(const char *path, struct sockaddr_un *addr) +{ + if (addr == NULL || path == NULL) + return -1; + memset(addr, 0, sizeof(struct sockaddr_un)); + addr->sun_family = AF_UNIX; + if (strlen(path) < sizeof(addr->sun_path)) { + rte_strscpy(addr->sun_path, path, sizeof(addr->sun_path) - 1); + return 0; + } + return -1; +} + +#define STATUS_OK 0 +#define STATUS_INTERNAL_ERROR -1 +#define STATUS_TRYAGAIN -2 +#define STATUS_INVALID_PARAMETER -3 +#define STATUS_CONNECTION_CLOSED -4 +#define STATUS_CONNECTION_INVALID -5 +#define STATUS_TIMEOUT -6 + +static int read_data(int fd, size_t len, uint8_t *data, size_t *recv_len, + int timeout) +{ + struct pollfd pfd; + ssize_t ret; + + pfd.fd = fd; + pfd.events = POLLIN; + pfd.revents = 0; + + ret = poll(&pfd, 1, timeout); + if (ret < 0) { + if (errno == EINTR) + return STATUS_TRYAGAIN; /* Caught signal before timeout */ + if (errno == EINVAL) + return STATUS_INVALID_PARAMETER; /* Timeout is negative */ + if (errno == EFAULT) + return STATUS_INVALID_PARAMETER; /* Fds argument is illegal */ + /* else */ + assert(0); + return STATUS_INTERNAL_ERROR; + } + + if (ret == 0) + return STATUS_TIMEOUT; + + if (pfd.revents == 0) { + assert(ret == 1); + assert(0); /* Revents cannot be zero when NtSocket_Poll returns 1 */ + return STATUS_TRYAGAIN; + } + + if ((pfd.revents & POLLIN) && + ((pfd.revents & (POLLERR | POLLNVAL)) == 0)) { + ret = recv(pfd.fd, data, len, 0); + if (ret < 0) { + int lerrno = errno; + + if (lerrno == EWOULDBLOCK || lerrno == EAGAIN) { + /* + * We have data but if the very first read turns out to return + * EWOULDBLOCK or EAGAIN it means that the remote end has dropped + * the connection + */ + NT_LOG(DBG, NTCONNECT, + "The socket with fd %d has been closed by remote end. %d [%s]\n", + pfd.fd, lerrno, strerror(lerrno)); + return STATUS_CONNECTION_CLOSED; + } + if (lerrno != EINTR) { + NT_LOG(ERR, NTCONNECT, + "recv() from fd %d received errno %d [%s]\n", + pfd.fd, lerrno, strerror(lerrno)); + return STATUS_CONNECTION_INVALID; + } + /* EINTR */ + return STATUS_TRYAGAIN; + } + if (ret == 0) { + if (pfd.revents & POLLHUP) { + /* This means that we have read all data and the remote end has + * HUP + */ +#ifdef DEBUG + NT_LOG(DBG, NTCONNECT, + "The remote end has terminated the session\n"); +#endif + return STATUS_CONNECTION_CLOSED; + } + return STATUS_TRYAGAIN; + } + + /* Ret can only be positive at this point */ + *recv_len = (size_t)ret; + return STATUS_OK; + } + + if ((pfd.revents & POLLHUP) == POLLHUP) { + /* this means that the remote end has HUP */ + NT_LOG(DBG, NTCONNECT, + "The remote end has terminated the session\n"); + return STATUS_CONNECTION_CLOSED; + } + + NT_LOG(ERR, NTCONNECT, + "poll() returned 0x%x. Invalidating the connection\n", + pfd.revents); + return STATUS_CONNECTION_INVALID; +} + +static int read_all(int clfd, uint8_t *data, size_t length) +{ + size_t recv_len = 0; + size_t left = length; + size_t pos = 0; + + while (left > 0) { + int ret = read_data(clfd, left, &data[pos], &recv_len, -1); + + if (ret == STATUS_OK) { + pos += recv_len; + left -= recv_len; + } else { + if (ret == STATUS_CONNECTION_CLOSED || ret == STATUS_TIMEOUT) { + /* Silently return status */ + return ret; + } + if (ret != STATUS_TRYAGAIN) { + NT_LOG(ERR, NTCONNECT, + "Failed getting packet. Error code: 0x%X\n", + ret); + return ret; + } + } + /* Try again */ + } + return STATUS_OK; +} + +static int write_all(int fd, const uint8_t *data, size_t size) +{ + size_t len = 0; + + while (len < size) { + ssize_t res = write(fd, (const void *)&data[len], size - len); + + if (res < 0) { + NT_LOG(ERR, NTCONNECT, "write to socket failed!"); + return STATUS_INTERNAL_ERROR; + } + len += res; + } + return 0; +} + +static int read_request(int clfd, char **rdata) +{ + uint8_t *data = malloc(MESSAGE_BUFFER * sizeof(uint8_t)); + + if (!data) { + NT_LOG(ERR, NTCONNECT, "memory allocation failed"); + return STATUS_INTERNAL_ERROR; + } + + size_t recv_len = 0; + int ret = read_data(clfd, MESSAGE_BUFFER, data, &recv_len, -1); + + if (ret) { + free(data); + return ret; + } + + struct ntconn_header_s hdr; + + memcpy(&hdr, data, NTCMOD_HDR_LEN); + size_t length = (hdr.len + hdr.blob_len) * sizeof(uint8_t); + + if (length > MESSAGE_BUFFER) { + uint8_t *new_data = realloc(data, length); + + if (!new_data) { + NT_LOG(ERR, NTCONNECT, "memory reallocation failed"); + free(data); + return STATUS_INTERNAL_ERROR; + } + data = new_data; + ret = read_all(clfd, &data[recv_len], length - recv_len); + if (ret) { + free(data); + return ret; + } + } + + *rdata = (char *)data; + return STATUS_OK; +} + +static ntconn_mod_t *ntconnect_interpret_request(int clfd, + struct ntconn_header_s *hdr, + char **get_req _unused, + char **module_cmd, int *status) +{ + char pci_id[32]; + char module[64]; + ntconn_mod_t *result_ntcmod = NULL; + char *request = NULL; + + int ret = read_request(clfd, &request); + *status = ret; + *get_req = request; + + if (ret == STATUS_OK && request) { + *hdr = *(struct ntconn_header_s *)request; + + if (!hdr) { + NT_LOG(ERR, NTCONNECT, "hdr returned NULL\n"); + *status = STATUS_INTERNAL_ERROR; + return NULL; + } + + switch (hdr->tag) { + case NTCONN_TAG_REQUEST: { + unsigned long idx = NTCMOD_HDR_LEN; + char *saveptr; + char *req = &request[idx]; + + uint32_t domain = 0xffffffff; + uint8_t bus = 0xff; + uint8_t devid = 0xff; + uint8_t function = 0xff; + + char *tok = strtok_r(req, ";", &saveptr); + + idx += strlen(tok) + 1; + if (!tok) + goto err_out; + rte_strscpy(pci_id, tok, 31); + + tok = strtok_r(NULL, ";", &saveptr); + idx += strlen(tok) + 1; + if (!tok) + goto err_out; + rte_strscpy(module, tok, 63); + + tok = strtok_r(NULL, "", &saveptr); + hdr->len -= idx; + if (tok) + *module_cmd = &request[idx]; + + tok = strtok_r(pci_id, ":.", &saveptr); + if (!tok) + goto err_out; + domain = (uint32_t)strtol(tok, NULL, 16); + tok = strtok_r(NULL, ":.", &saveptr); + if (!tok) + goto err_out; + bus = (uint8_t)strtol(tok, NULL, 16); + + tok = strtok_r(NULL, ":.", &saveptr); + if (!tok) + goto err_out; + devid = (uint8_t)strtol(tok, NULL, 16); + tok = strtok_r(NULL, "", &saveptr); + if (!tok) + goto err_out; + function = (uint8_t)strtol(tok, NULL, 16); + + /* Search for module registered as */ + ntconn_mod_t *ntcmod = ntcmod_base; + + while (ntcmod) { + if (domain == ntcmod->addr.domain && + bus == ntcmod->addr.bus && + devid == ntcmod->addr.devid && + function == ntcmod->addr.function && + strcmp(ntcmod->op->module, module) == 0) { + result_ntcmod = ntcmod; + break; + } + ntcmod = ntcmod->next; + } + } + break; + + default: + break; + } + } + +err_out: + + return result_ntcmod; +} + +static int send_reply(int clfd, uint16_t reply_tag, const void *data, + uint32_t size) +{ + struct ntconn_header_s hdr; + + hdr.tag = reply_tag; + hdr.len = NTCMOD_HDR_LEN + size; + hdr.blob_len = 0; + uint8_t *message = malloc(hdr.len * sizeof(uint8_t)); + + if (!message) { + NT_LOG(ERR, NTCONNECT, "memory allocation failed"); + return STATUS_INTERNAL_ERROR; + } + memcpy(message, (void *)&hdr, NTCMOD_HDR_LEN); + memcpy(&message[NTCMOD_HDR_LEN], data, size); + int res = write_all(clfd, message, hdr.len); + + free(message); + if (res) + return res; + + return 0; +} + +static int send_reply_free_data(int clfd, ntconn_mod_t *cmod, + uint16_t reply_tag, void *data, uint32_t size) +{ + int res = send_reply(clfd, reply_tag, data, size); + + if (size) { + pthread_mutex_lock(&cmod->mutex); + cmod->op->free_data(cmod->hdl, data); + pthread_mutex_unlock(&cmod->mutex); + } + + return res; +} + +static int ntconnect_send_error(int clfd, enum ntconn_err_e err_code) +{ + char err_buf[MAX_ERR_MESSAGE_LENGTH]; + const ntconn_err_t *ntcerr = get_ntconn_error(err_code); + + sprintf(err_buf, "----connect:%s", ntcerr->err_text); + unsigned int len = strlen(err_buf); + *(uint32_t *)err_buf = (uint32_t)ntcerr->err_code; + + return send_reply(clfd, NTCONN_TAG_ERROR, err_buf, len); +} + +static void *ntconnect_worker(void *arg) +{ + int status; + int clfd = (int)(uint64_t)arg; + char *module_cmd = NULL; + char *request = NULL; + struct ntconn_header_s hdr; + + do { + ntconn_mod_t *cmod = ntconnect_interpret_request(clfd, &hdr, + &request, + &module_cmd, + &status); + + if (cmod && module_cmd && status == 0) { + int len; + char *data; + + /* + * Handle general module commands + */ + if (strcmp(module_cmd, "version") == 0) { + uint64_t version = + ((uint64_t)cmod->op->version_major + << 32) + + (cmod->op->version_minor); + + if (send_reply(clfd, NTCONN_TAG_REPLY, + (void *)&version, + sizeof(uint64_t))) + break; + + } else { + /* + * Call module for execution of command + */ + data = NULL; + pthread_mutex_lock(&cmod->mutex); + int repl = cmod->op->request(cmod->hdl, clfd, + &hdr, module_cmd, + &data, &len); + pthread_mutex_unlock(&cmod->mutex); + + if (repl == REQUEST_OK && len >= 0) { + if (send_reply_free_data(clfd, cmod, + NTCONN_TAG_REPLY, + (void *)data, + (uint32_t)len)) + break; + + } else if (repl == REQUEST_ERR && len >= 0) { + if (send_reply_free_data(clfd, cmod, + NTCONN_TAG_ERROR, + (void *)data, + (uint32_t)len)) + break; + } else { + NT_LOG(ERR, NTCONNECT, + "Invalid result from module request function: module %s, result %i\n", + cmod->op->module, repl); + if (ntconnect_send_error(clfd, + NTCONN_ERR_CODE_INTERNAL_REPLY_ERROR)) + break; + } + } + + } else if (status == STATUS_TIMEOUT) { + /* Other end is dead */ + NT_LOG(WRN, NTCONNECT, + "Client must be dead - timeout\n"); + break; + } else if (status == STATUS_CONNECTION_CLOSED) { + break; /* silently break out */ + } + /* Error - send error back */ + if (ntconnect_send_error(clfd, NTCONN_ERR_CODE_INVALID_REQUEST)) + break; + if (request) + free(request); + } while (1); /* while still connected */ + + close(clfd); + + /* call module cleanup callback function for client_id */ + ntconn_mod_t *ntcmod = ntcmod_base; + + while (ntcmod) { + if (ntcmod->op->client_cleanup) { + pthread_mutex_lock(&ntcmod->mutex); + ntcmod->op->client_cleanup(ntcmod->hdl, clfd); + pthread_mutex_unlock(&ntcmod->mutex); + } + + ntcmod = ntcmod->next; + } + pthread_exit(NULL); + return NULL; +} + +static void *ntconnect_server(void *arg) +{ + struct ntconn_server_s *ntcserv = (struct ntconn_server_s *)arg; + + ntcserv->running = 1; + +#ifdef DEBUG + NT_LOG(DBG, NTCONNECT, "Running NT Connection Server fd %i\n", + ntcserv->serv_fd); +#endif + + if (listen(ntcserv->serv_fd, 5) < 0) { + NT_LOG(ERR, NTCONNECT, + "Server failed on listen(), stopping thread. err: %s\n", + strerror(errno)); + pthread_exit(NULL); + return NULL; + } + + while (ntcserv->running) { + int clfd = accept(ntcserv->serv_fd, NULL, NULL); + + if (clfd < 0) { + NT_LOG(ERR, NTCONNECT, + "ERROR from accept(), stopping thread. err: %s\n", + strerror(errno)); + break; + } + pthread_create(&ctid, NULL, ntconnect_worker, + (void *)(uint64_t)clfd); + pthread_setaffinity_np(ctid, sizeof(cpu_set_t), + &ntcserv->cpuset); + /* Detach immediately. We will never join this thread */ + pthread_detach(ctid); + } + + pthread_exit(NULL); + return NULL; +} + +int ntconnect_init(const char *sockname, cpu_set_t cpuset) +{ + if (ntcmod_base) { + /* Make sure the socket directory exists */ + char *sockname_copy = strdup(sockname); + char *sockname_dir = dirname(sockname_copy); + + if (mkdir(sockname_dir, 0755) < 0 && errno != EEXIST) { + NT_LOG(ERR, NTCONNECT, + "Can't create socket directory: %s", + sockname_dir); + free(sockname_copy); + return -1; + } + free(sockname_copy); + + /* Add server to module list - cannot work without */ + ntconn_server_register(&ntconn_serv); + + /* Start named socket server */ + struct sockaddr_un addr; + + unix_build_address(sockname, &addr); + + ntconn_serv.serv_fd = socket(AF_UNIX, SOCK_STREAM, 0); + ntconn_serv.cpuset = cpuset; + if (ntconn_serv.serv_fd == -1) + return -1; + + /* Make sure the node in filesystem is deleted otherwise bind will fail */ + unlink(sockname); + + if (bind(ntconn_serv.serv_fd, (struct sockaddr *)&addr, + sizeof(struct sockaddr_un)) == -1) { + close(ntconn_serv.serv_fd); + return -1; + } + + /* Run ntconnect service */ + pthread_create(&tid, NULL, ntconnect_server, &ntconn_serv); + pthread_setaffinity_np(tid, sizeof(cpu_set_t), + &ntconn_serv.cpuset); + } + + return 0; +} diff --git a/drivers/net/ntnic/ntconnect_modules/ntconn_adapter.c b/drivers/net/ntnic/ntconnect_modules/ntconn_adapter.c new file mode 100644 index 0000000000..294b95846b --- /dev/null +++ b/drivers/net/ntnic/ntconnect_modules/ntconn_adapter.c @@ -0,0 +1,775 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntnic_ethdev.h" +#include "ntconnect.h" +#include "ntconnect_api_adapter.h" +#include "ntos_system.h" +#include "ntconn_modules.h" +#include "ntconn_mod_helper.h" +#include "nt_util.h" +#include "ntlog.h" + +#define NTCONN_ADAP_VERSION_MAJOR 0U +#define NTCONN_ADAP_VERSION_MINOR 1U + +#define this_module_name "adapter" + +#define MAX_ADAPTERS 2 + +static struct adap_hdl_s { + struct drv_s *drv; +} adap_hdl[MAX_ADAPTERS]; + +static int func_adapter_get_interfaces(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static int func_adapter_get_info(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static int func_adapter_get_sensors(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr _unused, + char **data, int *len); +static struct func_s funcs_get_level1[] = { + { "interfaces", NULL, func_adapter_get_interfaces }, + { "info", NULL, func_adapter_get_info }, + { "sensors", NULL, func_adapter_get_sensors }, + { NULL, NULL, NULL }, +}; + +static int func_adapter_set_interface(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static int func_adapter_set_adapter(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static struct func_s funcs_set_level1[] = { + { "interface", NULL, func_adapter_set_interface }, + { "adapter", NULL, func_adapter_set_adapter }, + { NULL, NULL, NULL }, +}; + +/* + * Entry level + */ +static struct func_s adapter_entry_funcs[] = { + { "get", funcs_get_level1, NULL }, + { "set", funcs_set_level1, NULL }, + { NULL, NULL, NULL }, +}; + +static int read_link_speed(enum nt_link_speed_e link_speed) +{ + switch (link_speed) { + case NT_LINK_SPEED_10M: + return PORT_LINK_SPEED_10M; + case NT_LINK_SPEED_100M: + return PORT_LINK_SPEED_100M; + case NT_LINK_SPEED_1G: + return PORT_LINK_SPEED_1G; + case NT_LINK_SPEED_10G: + return PORT_LINK_SPEED_10G; + case NT_LINK_SPEED_25G: + return PORT_LINK_SPEED_25G; + case NT_LINK_SPEED_40G: + return PORT_LINK_SPEED_40G; + case NT_LINK_SPEED_50G: + return PORT_LINK_SPEED_50G; + case NT_LINK_SPEED_100G: + return PORT_LINK_SPEED_100G; + default: + break; + } + return PORT_LINK_SPEED_UNKNOWN; +} + +static nt_link_speed_t convert_link_speed(char *speed_str) +{ + if (strcmp(speed_str, "10M") == 0) + return NT_LINK_SPEED_10M; + else if (strcmp(speed_str, "100M") == 0) + return NT_LINK_SPEED_100M; + else if (strcmp(speed_str, "1G") == 0) + return NT_LINK_SPEED_1G; + else if (strcmp(speed_str, "10G") == 0) + return NT_LINK_SPEED_10G; + else if (strcmp(speed_str, "25G") == 0) + return NT_LINK_SPEED_25G; + else if (strcmp(speed_str, "40G") == 0) + return NT_LINK_SPEED_40G; + else if (strcmp(speed_str, "50G") == 0) + return NT_LINK_SPEED_50G; + else if (strcmp(speed_str, "100G") == 0) + return NT_LINK_SPEED_100G; + else + return NT_LINK_SPEED_UNKNOWN; +} + +static int func_adapter_get_interfaces(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr _unused, + char **data, int *len) +{ + struct ntc_interfaces_s *ifs; + struct adap_hdl_s *adap = (struct adap_hdl_s *)hdl; + fpga_info_t *fpga_info = &adap->drv->ntdrv.adapter_info.fpga_info; + int lag_active; + int final_list = adap->drv->probe_finished; + /* keep final_list set before nb_ports are called */ + rte_compiler_barrier(); + int nb_ports = rte_eth_dev_count_avail(); + + /* Get the "internals" structure of phy port 0 to find out if we're running LAG */ + char phy0_name[128]; + + rte_eth_dev_get_name_by_port(0, phy0_name); + struct rte_eth_dev *phy0_eth_dev = rte_eth_dev_get_by_name(phy0_name); + + if (phy0_eth_dev == NULL || phy0_eth_dev->data == NULL || + phy0_eth_dev->data->dev_private == NULL) { + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_INTERNAL_ERROR); + } + struct pmd_internals *phy0_internals = + (struct pmd_internals *)phy0_eth_dev->data->dev_private; + lag_active = (phy0_internals->lag_config == NULL) ? 0 : 1; + if (lag_active) { + /* + * Phy ports are link aggregated. I.e. number of ports is actually + * one bigger than what rte_eth_dev_count_avail() returned + */ + nb_ports++; + + /* + * Sanity check: + * For now we know about LAG with 2 ports only. + * If in the future we get HW with more ports, make assert to alert + * the developers that something needs to be looked at... + */ + assert(fpga_info->n_phy_ports == 2); + } + + *len = sizeof(struct ntc_interfaces_s) + + sizeof(struct ntc_interface_s) * nb_ports; + ifs = malloc(*len); + if (!ifs) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "memory allocation failed"); + return REQUEST_ERR; + } + *data = (char *)ifs; + + ifs->nb_ports = nb_ports; + ifs->final_list = final_list; + + int i; + + /* First set the "port type" of the physical ports */ + if (lag_active) { + if (phy0_internals->lag_config->mode == BONDING_MODE_8023AD) { + /* Active/active LAG */ + for (i = 0; i < fpga_info->n_phy_ports; i++) { + ifs->intf[i].type = + PORT_TYPE_PHY_LAG_ACTIVE_ACTIVE; + } + } else if (phy0_internals->lag_config->mode == + BONDING_MODE_ACTIVE_BACKUP) { + /* Active/backup LAG */ + ifs->intf[phy0_internals->lag_config->primary_port] + .type = PORT_TYPE_PHY_LAG_PRIMARY; + ifs->intf[phy0_internals->lag_config->backup_port].type = + PORT_TYPE_PHY_LAG_BACKUP; + } else { + /* Unknown LAG mode */ + assert(0); + } + } else { + /* Normal phy ports (not link aggregated) */ + for (i = 0; i < fpga_info->n_phy_ports; i++) + ifs->intf[i].type = PORT_TYPE_PHY_NORMAL; + } + + /* Then set the remaining port values for the physical ports. */ + for (i = 0; i < fpga_info->n_phy_ports; i++) { + char name[128]; + + if (i > 0 && lag_active) { + /* + * Secondary link aggregated port. Just display the "internals" values + * from port 0 + */ + rte_eth_dev_get_name_by_port(0, name); + } else { + rte_eth_dev_get_name_by_port(i, name); + } + struct rte_eth_dev *eth_dev = rte_eth_dev_get_by_name(name); + + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + struct adapter_info_s *p_adapter_info = + &adap->drv->ntdrv.adapter_info; + + ifs->intf[i].port_id = i; + ifs->intf[i].pci_id.domain = internals->pci_dev->addr.domain; + ifs->intf[i].pci_id.bus = internals->pci_dev->addr.bus; + ifs->intf[i].pci_id.devid = internals->pci_dev->addr.devid; + ifs->intf[i].pci_id.function = + internals->pci_dev->addr.function; + ifs->intf[i].pci_id.pad = 0; + + const bool port_link_status = + nt4ga_port_get_link_status(p_adapter_info, i); + ifs->intf[i].link = port_link_status ? PORT_LINK_UP : + PORT_LINK_DOWN; + + const nt_link_speed_t port_link_speed = + nt4ga_port_get_link_speed(p_adapter_info, i); + ifs->intf[i].port_speed = read_link_speed(port_link_speed); + + const bool port_adm_state = + nt4ga_port_get_adm_state(p_adapter_info, i); + if (!port_adm_state) { + ifs->intf[i].port_state = PORT_STATE_DISABLED; + } else { + const bool port_nim_present = + nt4ga_port_get_nim_present(p_adapter_info, i); + if (port_nim_present) { + ifs->intf[i].port_state = + PORT_STATE_NIM_PRESENT; + } else { + ifs->intf[i].port_state = PORT_STATE_NIM_ABSENT; + } + } + + /* MTU */ + if (i > 0 && lag_active) { + /* Secondary link aggregated port. Display same MTU value as port 0 */ + rte_eth_dev_get_mtu(0, &ifs->intf[i].mtu); + } else { + rte_eth_dev_get_mtu(i, &ifs->intf[i].mtu); + } + + /* MAC */ + const uint64_t mac = + fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_value + i; + ifs->intf[i].mac.addr_b[0] = (mac >> 40) & 0xFFu; + ifs->intf[i].mac.addr_b[1] = (mac >> 32) & 0xFFu; + ifs->intf[i].mac.addr_b[2] = (mac >> 24) & 0xFFu; + ifs->intf[i].mac.addr_b[3] = (mac >> 16) & 0xFFu; + ifs->intf[i].mac.addr_b[4] = (mac >> 8) & 0xFFu; + ifs->intf[i].mac.addr_b[5] = (mac >> 0) & 0xFFu; + + if (i > 0 && lag_active) { + /* Secondary link aggregated port. Queues not applicable */ + ifs->intf[i].num_queues = 0; + } else { + /* attached hw queues to this interface */ + unsigned int input_num = internals->nb_rx_queues; + /* + * These are the "input" queues, meaning these go to host and is attached + * to receiving from a port + */ + for (unsigned int ii = 0; ii < input_num; ii++) { + ifs->intf[i].queue[ii].idx = + internals->rxq_scg[ii].queue.hw_id; + ifs->intf[i].queue[ii].dir = QUEUE_INPUT; + } + + /* + * These are the "output" queues, meaning these go to a virtual port queue + * which typically is used by vDPA + */ + for (unsigned int ii = 0; ii < internals->vpq_nb_vq; + ii++) { + ifs->intf[i].queue[ii + input_num].idx = + internals->vpq[ii].hw_id; + ifs->intf[i].queue[ii + input_num].dir = + QUEUE_OUTPUT; + } + + ifs->intf[i].num_queues = + input_num + internals->vpq_nb_vq; + } + + /* NIM information */ + nim_i2c_ctx_t nim_ctx = + nt4ga_port_get_nim_capabilities(p_adapter_info, i); + + strlcpy((char *)&ifs->intf[i].nim_data.vendor_name, + nim_ctx.vendor_name, + sizeof(ifs->intf[i].nim_data.vendor_name)); + strlcpy((char *)&ifs->intf[i].nim_data.prod_no, nim_ctx.prod_no, + sizeof(ifs->intf[i].nim_data.prod_no)); + strlcpy((char *)&ifs->intf[i].nim_data.serial_no, + nim_ctx.serial_no, + sizeof(ifs->intf[i].nim_data.serial_no)); + strlcpy((char *)&ifs->intf[i].nim_data.date, nim_ctx.date, + sizeof(ifs->intf[i].nim_data.date)); + strlcpy((char *)&ifs->intf[i].nim_data.rev, nim_ctx.rev, + sizeof(ifs->intf[i].nim_data.rev)); + + if (nim_ctx.len_info[0] >= 0xFFFF) + ifs->intf[i].nim_data.link_length.sm = 0xFFFF; + else + ifs->intf[i].nim_data.link_length.sm = + nim_ctx.len_info[0]; + + ifs->intf[i].nim_data.link_length.ebw = nim_ctx.len_info[1]; + ifs->intf[i].nim_data.link_length.mm50 = nim_ctx.len_info[2]; + ifs->intf[i].nim_data.link_length.mm62 = nim_ctx.len_info[3]; + ifs->intf[i].nim_data.link_length.copper = nim_ctx.len_info[4]; + + ifs->intf[i].nim_data.pwr_level_req = nim_ctx.pwr_level_req; + ifs->intf[i].nim_data.pwr_level_cur = nim_ctx.pwr_level_cur; + ifs->intf[i].nim_data.nim_id = nim_ctx.nim_id; + ifs->intf[i].nim_data.port_type = nim_ctx.port_type; + } + + /* And finally handle the virtual ports. */ + int rte_eth_dev_virt_port_offset = lag_active ? 1 : + fpga_info->n_phy_ports; + for (; i < nb_ports; i++, rte_eth_dev_virt_port_offset++) { + /* Continue counting from the "i" value reached in the previous for loop */ + char name[128]; + + rte_eth_dev_get_name_by_port(rte_eth_dev_virt_port_offset, + name); + struct rte_eth_dev *eth_dev = rte_eth_dev_get_by_name(name); + + struct pmd_internals *internals = + (struct pmd_internals *)eth_dev->data->dev_private; + + ifs->intf[i].port_id = i; + ifs->intf[i].type = PORT_TYPE_VIRT; + ifs->intf[i].pci_id.domain = internals->pci_dev->addr.domain; + ifs->intf[i].pci_id.bus = internals->pci_dev->addr.bus; + ifs->intf[i].pci_id.devid = internals->pci_dev->addr.devid; + ifs->intf[i].pci_id.function = + internals->pci_dev->addr.function; + ifs->intf[i].pci_id.pad = 0; + + ifs->intf[i].port_speed = PORT_LINK_SPEED_NONE_REPORTED; + switch (internals->vport_comm) { + case VIRT_PORT_NEGOTIATED_NONE: + ifs->intf[i].port_state = PORT_STATE_VIRTUAL_UNATTACHED; + ifs->intf[i].link = PORT_LINK_DOWN; + break; + case VIRT_PORT_NEGOTIATED_SPLIT: + ifs->intf[i].port_state = PORT_STATE_VIRTUAL_SPLIT; + ifs->intf[i].link = PORT_LINK_UP; + break; + case VIRT_PORT_NEGOTIATED_PACKED: + ifs->intf[i].port_state = PORT_STATE_VIRTUAL_PACKED; + ifs->intf[i].link = PORT_LINK_UP; + break; + case VIRT_PORT_USE_RELAY: + ifs->intf[i].port_state = PORT_STATE_VIRTUAL_RELAY; + ifs->intf[i].link = PORT_LINK_UP; + break; + } + + /* MTU */ + rte_eth_dev_get_mtu(rte_eth_dev_virt_port_offset, + &ifs->intf[i].mtu); + + /* MAC */ + for (int ii = 0; ii < 6; ii++) { + ifs->intf[i].mac.addr_b[ii] = + internals->eth_addrs[0].addr_bytes[ii]; + } + + /* attached hw queues to this interface */ + unsigned int input_num = internals->nb_rx_queues; + + /* + * These are the "input" queues, meaning these go to host and is attached to + * receiving from a port + */ + for (unsigned int ii = 0; ii < input_num; ii++) { + ifs->intf[i].queue[ii].idx = + internals->rxq_scg[ii].queue.hw_id; + ifs->intf[i].queue[ii].dir = QUEUE_INPUT; + } + + /* + * These are the "output" queues, meaning these go to a virtual port queue + * which typically is used by vDPA + */ + unsigned int numq = + ((internals->vpq_nb_vq + input_num) > MAX_RSS_QUEUES) ? + MAX_RSS_QUEUES - input_num : + internals->vpq_nb_vq; + for (unsigned int ii = 0; ii < numq; ii++) { + ifs->intf[i].queue[ii + input_num].idx = + internals->vpq[ii].hw_id; + ifs->intf[i].queue[ii + input_num].dir = QUEUE_OUTPUT; + } + ifs->intf[i].num_queues = input_num + numq; + } + return REQUEST_OK; +} + +static int func_adapter_get_info(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr _unused, + char **data, int *len) +{ + struct adap_hdl_s *adap = (struct adap_hdl_s *)hdl; + fpga_info_t *fpga_info = &adap->drv->ntdrv.adapter_info.fpga_info; + + *len = sizeof(struct ntc_adap_get_info_s); + *data = malloc(*len); + if (!*data) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "memory allocation failed"); + return REQUEST_ERR; + } + + snprintf(*data, 31, "%03d-%04d-%02d-%02d", fpga_info->n_fpga_type_id, + fpga_info->n_fpga_prod_id, fpga_info->n_fpga_ver_id, + fpga_info->n_fpga_rev_id); + + return REQUEST_OK; +} + +static int func_adapter_get_sensors(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr _unused, + char **data, int *len) +{ + struct adapter_info_s *adapter = + &(((struct adap_hdl_s *)hdl)->drv->ntdrv.adapter_info); + struct sensor *sensor_ptr = NULL; + uint16_t sensors_num = 0; + uint8_t *sensors = NULL; + struct ntc_sensors_s sensors_info = { + .adapter_sensors_cnt = adapter->adapter_sensors_cnt, + .ports_cnt = adapter->fpga_info.n_phy_ports + }; + memcpy(sensors_info.adapter_name, adapter->p_dev_name, 24); + + /* Set a sum of sensor`s counters */ + sensors_num = adapter->adapter_sensors_cnt; + for (int i = 0; i < adapter->fpga_info.n_phy_ports; i++) { + sensors_num += adapter->nim_sensors_cnt[i]; + sensors_info.nim_sensors_cnt[i] = adapter->nim_sensors_cnt[i]; + } + + *len = sizeof(struct ntc_sensors_s) + + sensors_num * sizeof(struct sensor); + + /* Allocate memory for sensors array */ + sensors = malloc(*len); + if (!sensors) { + NT_LOG(ERR, NTCONNECT, "memory allocation failed"); + *len = 0; + return REQUEST_ERR; + } + memcpy(sensors, &sensors_info, sizeof(struct ntc_sensors_s)); + sensor_ptr = (struct sensor *)(sensors + sizeof(struct ntc_sensors_s)); + + /* Fetch adapter sensors */ + for (struct nt_sensor_group *ptr = adapter->adapter_sensors; + ptr != NULL; ptr = ptr->next) { + sensor_ptr->current_value = ptr->sensor->info.value; + sensor_ptr->min_value = ptr->sensor->info.value_lowest; + sensor_ptr->max_value = ptr->sensor->info.value_highest; + sensor_ptr->sign = ptr->sensor->si; + sensor_ptr->type = ptr->sensor->info.type; + memcpy(sensor_ptr->name, ptr->sensor->info.name, 50); + sensor_ptr++; + } + + /* Fetch NIM sensors */ + for (int i = 0; i < adapter->fpga_info.n_phy_ports; i++) { + for (struct nim_sensor_group *ptr = adapter->nim_sensors[i]; + ptr != NULL; ptr = ptr->next) { + sensor_ptr->current_value = ptr->sensor->info.value; + sensor_ptr->min_value = ptr->sensor->info.value_lowest; + sensor_ptr->max_value = ptr->sensor->info.value_highest; + sensor_ptr->sign = ptr->sensor->si; + sensor_ptr->type = ptr->sensor->info.type; + + memcpy(sensor_ptr->name, ptr->sensor->info.name, + (strlen(ptr->sensor->info.name) >= 50) ? + 50 : + strlen(ptr->sensor->info.name)); + sensor_ptr++; + } + } + + /* Send response */ + *data = (char *)sensors; + + return REQUEST_OK; +} + +static int set_port_enable(struct adap_hdl_s *adap, int port_nr) +{ + adapter_info_t *p_adapter_info = &adap->drv->ntdrv.adapter_info; + + nt4ga_port_set_adm_state(p_adapter_info, port_nr, true); + + return REQUEST_OK; +} + +static int set_port_disable(struct adap_hdl_s *adap, int port_nr) +{ + adapter_info_t *p_adapter_info = &adap->drv->ntdrv.adapter_info; + + nt4ga_port_set_adm_state(p_adapter_info, port_nr, false); + + return REQUEST_OK; +} + +static int set_link_up(struct adap_hdl_s *adap, int portid) +{ + struct adapter_info_s *p_adapter_info = &adap->drv->ntdrv.adapter_info; + + const bool link_status = + nt4ga_port_get_link_status(p_adapter_info, portid); + + if (!link_status) { + nt4ga_port_set_link_status(p_adapter_info, portid, true); + NT_LOG(DBG, NTCONNECT, "Port %i: Link set to be up\n", portid); + } else { + NT_LOG(DBG, NTCONNECT, + "Port %i: Link is already set to be up\n", portid); + } + + return REQUEST_OK; +} + +static int set_link_down(struct adap_hdl_s *adap, int portid) +{ + struct adapter_info_s *p_adapter_info = &adap->drv->ntdrv.adapter_info; + + const bool link_status = + nt4ga_port_get_link_status(p_adapter_info, portid); + + if (!link_status) { + NT_LOG(DBG, NTCONNECT, + "Port %i: Link is already set to be down\n", portid); + } else { + nt4ga_port_set_link_status(p_adapter_info, portid, false); + NT_LOG(DBG, NTCONNECT, "Port %i: Link set to be down\n", + portid); + } + + return REQUEST_OK; +} + +static int set_link_speed(struct adap_hdl_s *adap, int portid, char *speed_str, + char **data, int *len) +{ + struct adapter_info_s *p_adapter_info = &adap->drv->ntdrv.adapter_info; + + const bool port_adm_state = + nt4ga_port_get_adm_state(p_adapter_info, portid); + if (!port_adm_state) { + const nt_link_speed_t speed = convert_link_speed(speed_str); + + if (speed != NT_LINK_SPEED_UNKNOWN) { + nt4ga_port_set_link_speed(p_adapter_info, portid, speed); + NT_LOG(DBG, NTCONNECT, "Port %i: set link speed - %s\n", + portid, speed_str); + } else { + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_MISSING_INVALID_PARAM); + } + } else { + NT_LOG(DBG, NTCONNECT, + "Port %i: fail to set link speed, port is enabled\n", + portid); + return ntconn_reply_status(data, len, + NTCONN_ADAPTER_ERR_WRONG_LINK_STATE); + } + + return REQUEST_OK; +} + +static int set_loopback_mode(struct adap_hdl_s *adap, int portid, int mode) +{ + struct adapter_info_s *p_adapter_info = &adap->drv->ntdrv.adapter_info; + + NT_LOG(DBG, NTCONNECT, "Port %i: set loopback mode %i\n", portid, mode); + nt4ga_port_set_loopback_mode(p_adapter_info, portid, mode); + return REQUEST_OK; +} + +static int set_tx_power(struct adap_hdl_s *adap, int portid, bool disable, + char **data, int *len) +{ + struct adapter_info_s *p_adapter_info = &adap->drv->ntdrv.adapter_info; + + NT_LOG(DBG, NTCONNECT, "Port %i: set tx_power %i\n", portid, disable); + if (nt4ga_port_tx_power(p_adapter_info, portid, disable)) { + NT_LOG(DBG, NTCONNECT, + "Port %i: ERROR while changing tx_power\n", portid); + return ntconn_reply_status(data, len, + NTCONN_ADAPTER_ERR_TX_POWER_FAIL); + } + return REQUEST_OK; +} + +static int func_adapter_set_interface(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr _unused, + char **data, int *len) +{ + struct adap_hdl_s *adap = (struct adap_hdl_s *)hdl; + char *saveptr; + int port_nr; + int length; + char *tok; + + *len = 0; + + /* + * This will receive the request strings starting with "adapter;set,interface,...." + * so in the situation of a request like: "adapter,set,interface,port0,link_speed=10G" + * the remainder of the command "port0,link_speed=10G" will be pointed to by *data, + * zero-terminated on entry + */ + + if (!(data && *data)) + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_INVALID_REQUEST); + + /* OK to modify *data */ + tok = strtok_r(*data, ",", &saveptr); + if (!tok) + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_MISSING_INVALID_PARAM); + + length = strlen(tok); + + if (!(length > 4 && memcmp(tok, "port", 4) == 0)) + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_MISSING_INVALID_PARAM); + + port_nr = atoi(tok + 4); + + /* Only set on phy ports */ + if (port_nr < adap->drv->ntdrv.adapter_info.fpga_info.n_phy_ports) + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_MISSING_INVALID_PARAM); + + tok = strtok_r(NULL, "=,", &saveptr); + if (!tok) + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_MISSING_INVALID_PARAM); + if (strcmp(tok, "link_speed") == 0) { + tok = strtok_r(NULL, ",", &saveptr); + if (!tok) + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_MISSING_INVALID_PARAM); + return set_link_speed(adap, port_nr, tok, data, len); + } else if (strcmp(tok, "enable") == 0) { + return set_port_enable(adap, port_nr); + } else if (strcmp(tok, "disable") == 0) { + return set_port_disable(adap, port_nr); + } else if (strcmp(tok, "link_state") == 0) { + tok = strtok_r(NULL, ",", &saveptr); + if (!tok) + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_MISSING_INVALID_PARAM); + if (strcmp(tok, "up") == 0) + return set_link_up(adap, port_nr); + else if (strcmp(tok, "down") == 0) + return set_link_down(adap, port_nr); + } else if (strcmp(tok, "host_loopback") == 0) { + tok = strtok_r(NULL, ",", &saveptr); + if (!tok) + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_MISSING_INVALID_PARAM); + if (strcmp(tok, "on") == 0) + return set_loopback_mode(adap, port_nr, + NT_LINK_LOOPBACK_HOST); + else if (strcmp(tok, "off") == 0) + return set_loopback_mode(adap, port_nr, + NT_LINK_LOOPBACK_OFF); + } else if (strcmp(tok, "line_loopback") == 0) { + tok = strtok_r(NULL, ",", &saveptr); + if (!tok) + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_MISSING_INVALID_PARAM); + if (strcmp(tok, "on") == 0) + return set_loopback_mode(adap, port_nr, + NT_LINK_LOOPBACK_LINE); + else if (strcmp(tok, "off") == 0) + return set_loopback_mode(adap, port_nr, + NT_LINK_LOOPBACK_OFF); + } else if (strcmp(tok, "tx_power") == 0) { + tok = strtok_r(NULL, ",", &saveptr); + if (!tok) + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_MISSING_INVALID_PARAM); + if (strcmp(tok, "on") == 0) + return set_tx_power(adap, port_nr, false, data, len); + else if (strcmp(tok, "off") == 0) + return set_tx_power(adap, port_nr, true, data, len); + } + + /* Should return 0 on success */ + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_MISSING_INVALID_PARAM); +} + +static int func_adapter_set_adapter(void *hdl _unused, int client_id _unused, + struct ntconn_header_s *hdr _unused, + char **data, int *len) +{ + if (data && *data) { + NT_LOG(DBG, NTCONNECT, + "Set adapter: Command: %s\n", *data); + } + + *len = 0; + + /* Should return 0 on success */ + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_NOT_YET_IMPLEMENTED); +} + +static int adap_request(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr, char *function, + char **data, int *len) +{ + return execute_function(this_module_name, hdl, client_id, hdr, function, + adapter_entry_funcs, data, len, 0); +} + +static void adap_free_data(void *hdl _unused, char *data) +{ + free(data); +} + +static void adap_client_cleanup(void *hdl _unused, int client_id _unused) +{ + /* Nothing to do */ +} + +static const ntconnapi_t ntconn_adap_op = { this_module_name, + NTCONN_ADAP_VERSION_MAJOR, + NTCONN_ADAP_VERSION_MINOR, + adap_request, + adap_free_data, + adap_client_cleanup + }; + +int ntconn_adap_register(struct drv_s *drv) +{ + int i; + + for (i = 0; i < MAX_ADAPTERS; i++) { + if (adap_hdl[i].drv == NULL) + break; + } + if (i == MAX_ADAPTERS) { + NT_LOG(ERR, NTCONNECT, + "Cannot register more adapters into NtConnect framework"); + return -1; + } + + adap_hdl[i].drv = drv; + return register_ntconn_mod(&drv->p_dev->addr, (void *)&adap_hdl[i], + &ntconn_adap_op); +} diff --git a/drivers/net/ntnic/ntconnect_modules/ntconn_flow.c b/drivers/net/ntnic/ntconnect_modules/ntconn_flow.c new file mode 100644 index 0000000000..31d5dc3edc --- /dev/null +++ b/drivers/net/ntnic/ntconnect_modules/ntconn_flow.c @@ -0,0 +1,1310 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include "ntnic_ethdev.h" +#include "ntconnect.h" +#include "ntos_system.h" +#include "ntconn_modules.h" +#include "ntconn_mod_helper.h" +#include "nt_util.h" +#include "ntlog.h" +#include "ntnic_vf_vdpa.h" + +#include "ntconnect_api_flow.h" +#include "ntconnect_api_meter.h" +#include "stream_binary_flow_api.h" + +#include +#include "flow_api.h" + +#define DEBUG_FLOW 1 + +#define NTCONN_FLOW_VERSION_MAJOR 0U +#define NTCONN_FLOW_VERSION_MINOR 1U + +#define this_module_name "filter" + +#define MAX_CLIENTS 32 + +#define UNUSED __rte_unused + +static struct flow_hdl_s { + struct drv_s *drv; +} flow_hdl[MAX_CLIENTS]; + +#define MAX_PORTS 64 +static struct port_to_eth_s { + struct flow_eth_dev *flw_dev; + uint32_t forced_vlan_vid; + uint32_t caller_id; +} port_eth[MAX_PORTS]; + +static ntconn_err_t ntconn_err[] = { + { NTCONN_FLOW_ERR_NONE, "Success" }, + { NTCONN_FLOW_ERR_INTERNAL_ERROR, "Internal error" }, + { NTCONN_FLOW_ERR_PORT_IS_NOT_INITIALIZED, "Port is not initialized" }, + { NTCONN_FLOW_ERR_UNEXPECTED_VIRTIO_PATH, "Unexpected virtio path" }, + { NTCONN_FLOW_ERR_TO_MANY_FLOWS, "To many flows" }, + { NTCONN_FLOW_ERR_INVALID_PORT, "Invalid port" }, + { NTCONN_FLOW_ERR_NOT_YET_IMPLEMENTED, "Function not yet implemented" }, + { NTCONN_FLOW_ERR_UNSUPPORTED_ADAPTER, "Adapter is not supported" }, + { NTCONN_FLOW_ERR_NO_VF_QUEUES, "No queues for the VF is found" }, + { -1, NULL } +}; + +static const char *get_error_msg(enum ntconn_flow_err_e err_code) +{ + int idx = 0; + + while (ntconn_err[idx].err_code != (uint32_t)-1 && + ntconn_err[idx].err_code != err_code) + idx++; + if (ntconn_err[idx].err_code == (uint32_t)-1) + idx = 1; + + return ntconn_err[idx].err_text; +} + +static inline int ntconn_flow_err_reply_status(char **data, int *len, + enum ntconn_flow_err_e code, + int err) +{ + *data = malloc(sizeof(struct flow_return_s)); + if (*data) { + struct flow_return_s *return_value = + (struct flow_return_s *)*data; + *len = sizeof(struct flow_return_s); + return_value->status = err; + return_value->type = FLOW_ERROR_GENERAL; + const char *err_msg = get_error_msg(code); + + memcpy(return_value->err_msg, err_msg, + RTE_MIN(strlen(err_msg), ERR_MSG_LEN)); + return REQUEST_OK; + } + *len = 0; + NT_LOG(ERR, NTCONNECT, "Not able to allocate memory"); + return REQUEST_ERR; +} + +static inline int ntconn_flow_err_status(char **data, int *len, int err) +{ + *data = malloc(sizeof(struct flow_return_s)); + if (*data) { + struct flow_return_s *return_value = + (struct flow_return_s *)*data; + *len = sizeof(struct flow_return_s); + return_value->status = err; + return_value->type = FLOW_ERROR_GENERAL; + const char *err_msg = + get_error_msg(NTCONN_FLOW_ERR_INTERNAL_ERROR); + strlcpy(return_value->err_msg, err_msg, ERR_MSG_LEN); + return REQUEST_OK; + } + *len = 0; + NT_LOG(ERR, NTCONNECT, "Not able to allocate memory"); + return REQUEST_ERR; +} + +/* + * Filter functions + */ +static int func_flow_create(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, int *len); +static int func_flow_validate(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static int func_flow_destroy(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static int func_flow_flush(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, int *len); +static int func_flow_query(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, int *len); +static int func_flow_setport(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static struct func_s adapter_entry_funcs[] = { + { "setport", NULL, func_flow_setport }, + { "create", NULL, func_flow_create }, + { "validate", NULL, func_flow_validate }, + { "destroy", NULL, func_flow_destroy }, + { "flush", NULL, func_flow_flush }, + { "query", NULL, func_flow_query }, + { NULL, NULL, NULL }, +}; + +static int copy_return_status(char **data, int *len, int status, + struct flow_error *error) +{ + *data = malloc(sizeof(struct flow_return_s)); + if (*data) { + struct flow_return_s *return_value = + (struct flow_return_s *)*data; + *len = sizeof(struct flow_return_s); + + return_value->status = status; + return_value->type = error->type; + strlcpy(return_value->err_msg, error->message, ERR_MSG_LEN); + return REQUEST_OK; + } + *len = 0; + NT_LOG(ERR, NTCONNECT, "Not able to allocate memory %s", + __func__); + return REQUEST_ERR; +} + +static void set_error(struct flow_error *error) +{ + error->type = FLOW_ERROR_SUCCESS; + error->message = "Operation successfully completed"; +} + +static int func_flow_setport(void *hdl _unused, int client_id _unused, + struct ntconn_header_s *hdr _unused, char **data, + int *len) +{ + uint32_t i; + struct flow_error error; + uint32_t nb_port; + uint8_t in_port = MAX_PORTS; + char vpath[MAX_PATH_LEN]; + char *saveptr; + + set_error(&error); + + nb_port = rte_eth_dev_count_avail(); + +#ifdef DEBUG_FLOW + NT_LOG(DBG, NTCONNECT, "%s: \"%s\"\n", __func__, *data); + NT_LOG(DBG, NTCONNECT, "Number of ports: %u\n", nb_port); +#endif + + char *tok = strtok_r(*data, ",", &saveptr); + + if (tok) { + int length = strlen(tok); + + if (length > 7 && memcmp(tok, "in_port=", 5) == 0) + in_port = atoi(tok + 7); + } +#ifdef DEBUG_FLOW + NT_LOG(DBG, NTCONNECT, "in_port: %u\n", in_port); +#endif + + tok = strtok_r(NULL, ",", &saveptr); + if (tok) { + int length = strlen(tok); + + if (length > 6 && memcmp(tok, "vpath=", 6) == 0) + strlcpy(vpath, tok + 6, MAX_PATH_LEN); + } +#ifdef DEBUG_FLOW + NT_LOG(DBG, NTCONNECT, "vpath: %s\n", vpath); +#endif + + /* Check that the wanted ports are valid ports */ + if (in_port >= nb_port) { + NT_LOG(ERR, NTCONNECT, "port out of range"); + return ntconn_flow_err_status(data, len, ENODEV); + } + + struct pmd_internals *vp_internals = vp_path_instance_ready(vpath); + + if (!vp_internals) { + NT_LOG(ERR, NTCONNECT, "Failed to get VF device"); + return ntconn_flow_err_status(data, len, ENODEV); + } + + /* Get flow device */ + port_eth[in_port].flw_dev = vp_internals->flw_dev; + + if (port_eth[in_port].flw_dev == NULL) { + NT_LOG(ERR, NTCONNECT, "Failed to get eth device"); + return ntconn_flow_err_status(data, len, ENODEV); + } + + /* Only INLINE is supported */ + if (vp_internals->flw_dev->ndev->flow_profile != + FLOW_ETH_DEV_PROFILE_INLINE) { + /* Only inline profile is supported */ + NT_LOG(ERR, NTCONNECT, "Adapter is not supported"); + return ntconn_flow_err_status(data, len, ENODEV); + } + + if (vp_internals->vpq_nb_vq == 0) { + NT_LOG(ERR, NTCONNECT, "No queues for the VF is found"); + return ntconn_flow_err_status(data, len, ENODEV); + } + + /* Server and client must agree of the virtual port number */ + if (vp_internals->port != (in_port + 4U)) { + NT_LOG(ERR, NTCONNECT, + "Internal error: Virtual port out of sync"); + return ntconn_flow_err_status(data, len, ENODEV); + } + +#ifdef DEBUG_FLOW + NT_LOG(DBG, NTCONNECT, "vport: %u\n", vp_internals->port); + NT_LOG(DBG, NTCONNECT, "vlan (forced): %u\n", vp_internals->vlan); +#endif + + port_eth[in_port].caller_id = vp_internals->port; + port_eth[in_port].forced_vlan_vid = vp_internals->vlan; + + *data = malloc(sizeof(struct flow_setport_return)); + if (*data) { + struct flow_setport_return *return_value = + (struct flow_setport_return *)*data; + *len = sizeof(struct flow_setport_return); + return_value->num_queues = vp_internals->vpq_nb_vq; + +#ifdef DEBUG_FLOW + NT_LOG(DBG, NTCONNECT, "Number of queues: %u\n", + vp_internals->vpq_nb_vq); +#endif + for (i = 0; i < vp_internals->vpq_nb_vq && i < MAX_QUEUES; + i++) { +#ifdef DEBUG_FLOW + NT_LOG(DBG, NTCONNECT, "Queue: %u\n", + vp_internals->vpq[i].id); + NT_LOG(DBG, NTCONNECT, "HW ID: %u\n", + vp_internals->vpq[i].hw_id); +#endif + return_value->queues[i].id = vp_internals->vpq[i].id; + return_value->queues[i].hw_id = + vp_internals->vpq[i].hw_id; +#ifdef DEBUG_FLOW + NT_LOG(DBG, NTCONNECT, + "Setup output port: %u, %04x:%02x:%02x.%x\n", + in_port, vp_internals->pci_dev->addr.domain, + vp_internals->pci_dev->addr.bus, + vp_internals->pci_dev->addr.devid, + vp_internals->pci_dev->addr.function); +#endif + } + return REQUEST_OK; + } + *len = 0; + return REQUEST_ERR; +} + +static int func_flow_flush(void *hdl _unused, int client_id _unused, + struct ntconn_header_s *hdr _unused, char **data, + int *len) +{ + struct flow_error error; + int port = MAX_PORTS; + int status = -1; + char *saveptr; + + set_error(&error); + +#ifdef DEBUG_FLOW + NT_LOG(DBG, NTCONNECT, "%s: [%s:%u] enter\n", __func__, __FILE__, __LINE__); +#endif + + char *tok = strtok_r(*data, ",", &saveptr); + + if (tok) { + int length = strlen(tok); + + if (length > 5 && memcmp(tok, "port=", 5) == 0) + port = atoi(tok + 5); + } +#ifdef DEBUG_FLOW + NT_LOG(DBG, NTCONNECT, "Port id=%u\n", port); +#endif + + if (port >= MAX_PORTS) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "port id out of range"); + return ntconn_flow_err_reply_status(data, len, + NTCONN_FLOW_ERR_INVALID_PORT, + ENODEV); + } + + /* Call filter with data */ + status = flow_flush(port_eth[port].flw_dev, &error); + return copy_return_status(data, len, status, &error); +} + +static int func_flow_destroy(void *hdl _unused, int client_id _unused, + struct ntconn_header_s *hdr, char **data, int *len) +{ + struct flow_error error; + int port = MAX_PORTS; + uint64_t flow = 0; + int status = -1; + + struct destroy_flow_ntconnect *flow_cpy = + (struct destroy_flow_ntconnect *)&(*data)[hdr->len]; + + if (hdr->blob_len != sizeof(struct destroy_flow_ntconnect)) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "Error in filter data"); + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_INVALID_REQUEST); + } + +#ifdef DEBUG_FLOW1 + NT_LOG(DBG, NTCONNECT, "%s: [%s:%u] enter\n", __func__, __FILE__, __LINE__); +#endif + + port = flow_cpy->port; + +#ifdef DEBUG_FLOW1 + NT_LOG(DBG, NTCONNECT, "Port id=%u\n", port); +#endif + + if (port >= MAX_PORTS) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "port id out of range"); + return ntconn_flow_err_reply_status(data, len, + NTCONN_FLOW_ERR_INVALID_PORT, + ENODEV); + } + + flow = flow_cpy->flow; + +#ifdef DEBUG_FLOW1 + NT_LOG(DBG, NTCONNECT, "flow=0x%016llX\n", + (unsigned long long)flow); +#endif + + /* Call filter with data */ + status = flow_destroy(port_eth[port].flw_dev, + (struct flow_handle *)flow, &error); + + *data = malloc(sizeof(struct flow_return_s)); + if (*data) { + struct flow_return_s *return_value = + (struct flow_return_s *)*data; + *len = sizeof(struct flow_return_s); + + return_value->status = status; + return_value->type = error.type; + strlcpy(return_value->err_msg, error.message, ERR_MSG_LEN); + return REQUEST_OK; + } + *len = 0; + NT_LOG(ERR, NTCONNECT, "Not able to allocate memory %s", + __func__); + return REQUEST_ERR; +} + +enum { + FLOW_API_FUNC_CREATE, + FLOW_API_FUNC_VALIDATE, +}; + +static uint64_t make_flow_create(int func, int port, + struct create_flow_ntconnect *flow_cpy, + int *status, struct flow_error *error) +{ + struct flow_elem elem[MAX_FLOW_STREAM_ELEM]; + struct flow_action action[MAX_FLOW_STREAM_ELEM]; + struct flow_action_vxlan_encap vxlan_tun; + struct flow_action_raw_encap encap; + struct flow_action_raw_decap decap; + struct flow_elem elem_tun[MAX_FLOW_STREAM_VXLAN_TUN_ELEM]; + int idx = -1; + + struct flow_attr *attr = &flow_cpy->attr; + struct flow_elem_cpy *elem_cpy = flow_cpy->elem; + struct flow_action_cpy *action_cpy = flow_cpy->action; + + error->type = FLOW_ERROR_GENERAL; + error->message = "To many flows"; + *status = NTCONN_FLOW_ERR_TO_MANY_FLOWS; + + attr->caller_id = port_eth[port].caller_id; + attr->forced_vlan_vid = port_eth[port].forced_vlan_vid; + + do { + idx++; + if (idx > MAX_FLOW_STREAM_ELEM) + goto error; + elem[idx].type = elem_cpy[idx].type; + if (!elem_cpy[idx].spec_cpy.valid) { + elem[idx].spec = NULL; + } else { + elem[idx].spec = + (void *)&elem_cpy[idx].spec_cpy.u.start_addr; + } + if (!elem_cpy[idx].mask_cpy.valid) { + elem[idx].mask = NULL; + } else { + elem[idx].mask = + (void *)&elem_cpy[idx].mask_cpy.u.start_addr; + } + } while (elem_cpy[idx].type != FLOW_ELEM_TYPE_END); + + idx = -1; + do { + idx++; + if (idx > MAX_FLOW_STREAM_ELEM) + goto error; + action[idx].type = action_cpy[idx].type; + if (!action_cpy[idx].conf_cpy.valid) { + action[idx].conf = NULL; + } else { + switch (action_cpy[idx].type) { + case FLOW_ACTION_TYPE_VXLAN_ENCAP: { + /* + * Special VXLAN ENCAP treatment create inner tunnel + * elements in action + */ + struct flow_elem_cpy *tun_elem_cpy = + (struct flow_elem_cpy *)action_cpy[idx] + .conf_cpy.u.vxlan.vxlan_tunnel; + vxlan_tun.vxlan_tunnel = elem_tun; + int tun_idx = -1; + + do { + tun_idx++; + if (tun_idx > + MAX_FLOW_STREAM_VXLAN_TUN_ELEM) { + error->message = + "To many VXLAN tunnels"; + goto error; + } + elem_tun[tun_idx].type = + tun_elem_cpy[tun_idx].type; + if (!tun_elem_cpy[tun_idx] + .spec_cpy.valid) { + elem_tun[tun_idx].spec = NULL; + } else { + elem_tun[tun_idx].spec = + (void *)&tun_elem_cpy[tun_idx] + .spec_cpy.u + .start_addr; + } + if (!tun_elem_cpy[tun_idx] + .mask_cpy.valid) { + elem_tun[tun_idx].mask = NULL; + } else { + elem_tun[tun_idx].mask = + (void *)&tun_elem_cpy[tun_idx] + .mask_cpy.u + .start_addr; + } + } while (tun_elem_cpy[tun_idx].type != + FLOW_ELEM_TYPE_END); + /* VXLAN ENCAP tunnel finished */ + action[idx].conf = &vxlan_tun; + } + break; + case FLOW_ACTION_TYPE_RSS: { + /* Need to set queue pointer */ + action_cpy[idx].conf_cpy.u.rss.rss.queue = + (const uint16_t *)&action_cpy[idx] + .conf_cpy.u.rss.cpy_queue; + action[idx].conf = (void *)&action_cpy[idx] + .conf_cpy.u.rss.rss; + } + break; + case FLOW_ACTION_TYPE_METER: { + /* Need to convert meter ID to uniq ID for the VF */ + action_cpy[idx].conf_cpy.u.meter.mtr_id = + ((flow_mtr_meters_supported() / + (RTE_MAX_ETHPORTS - 2)) * + (flow_cpy->vport - 4)) + + action_cpy[idx].conf_cpy.u.meter.mtr_id; + action[idx].conf = (void *)&action_cpy[idx] + .conf_cpy.u.meter; + } + break; + case FLOW_ACTION_TYPE_RAW_ENCAP: { + encap.preserve = NULL; + encap.data = + action_cpy[idx].conf_cpy.u.encap.data; + encap.item_count = + action_cpy[idx] + .conf_cpy.u.encap.item_count; + encap.size = + action_cpy[idx].conf_cpy.u.encap.size; + + for (int eidx = 0; + eidx < + action_cpy[idx].conf_cpy.u.encap.item_count; + eidx++) { + if (eidx > RAW_ENCAP_DECAP_ELEMS_MAX) { + error->message = + "To many encap items"; + goto error; + } + encap.items[eidx].type = + action_cpy[idx] + .conf_cpy.u.encap + .item_cpy[eidx] + .type; + if (action_cpy[idx] + .conf_cpy.u.encap + .item_cpy[eidx] + .spec_cpy.valid) { + encap.items[eidx].spec = + (void *)&action_cpy[idx] + .conf_cpy.u + .encap + .item_cpy[eidx] + .spec_cpy.u + .start_addr; + } else { + encap.items[eidx].spec = NULL; + } + if (action_cpy[idx] + .conf_cpy.u.encap + .item_cpy[eidx] + .mask_cpy.valid) { + encap.items[eidx].mask = + (void *)&action_cpy[idx] + .conf_cpy.u + .encap + .item_cpy[eidx] + .mask_cpy.u + .start_addr; + } else { + encap.items[eidx].mask = NULL; + } + } + action[idx].conf = &encap; + } + break; + case FLOW_ACTION_TYPE_RAW_DECAP: { + decap.data = + action_cpy[idx].conf_cpy.u.decap.data; + decap.item_count = + action_cpy[idx] + .conf_cpy.u.decap.item_count; + decap.size = + action_cpy[idx].conf_cpy.u.decap.size; + + for (int eidx = 0; + eidx < + action_cpy[idx].conf_cpy.u.decap.item_count; + eidx++) { + if (eidx > RAW_ENCAP_DECAP_ELEMS_MAX) { + error->message = + "To many decap items"; + goto error; + } + decap.items[eidx].type = + action_cpy[idx] + .conf_cpy.u.decap + .item_cpy[eidx] + .type; + if (action_cpy[idx] + .conf_cpy.u.decap + .item_cpy[eidx] + .spec_cpy.valid) { + decap.items[eidx].spec = + (void *)&action_cpy[idx] + .conf_cpy.u + .decap + .item_cpy[eidx] + .spec_cpy.u + .start_addr; + } else { + decap.items[eidx].spec = NULL; + } + if (action_cpy[idx] + .conf_cpy.u.decap + .item_cpy[eidx] + .mask_cpy.valid) { + decap.items[eidx].mask = + (void *)&action_cpy[idx] + .conf_cpy.u + .decap + .item_cpy[eidx] + .mask_cpy.u + .start_addr; + } else { + decap.items[eidx].mask = NULL; + } + } + action[idx].conf = &decap; + } + break; + default: { + /* Move conf pointer into conf_cpy data field */ + action[idx].conf = + (void *)&action_cpy[idx] + .conf_cpy.u.start_addr; + } + break; + } + } + } while (action_cpy[idx].type != FLOW_ACTION_TYPE_END); + + *status = NTCONN_FLOW_ERR_NONE; + if (func == FLOW_API_FUNC_VALIDATE) { + *status = flow_validate(port_eth[port].flw_dev, elem, action, + error); + return 0ULL; + } else { + return (uint64_t)flow_create(port_eth[port].flw_dev, attr, elem, + action, error); + } + +error: + return 0; +} + +static int func_flow_create(void *hdl _unused, int client_id _unused, + struct ntconn_header_s *hdr, char **data, int *len) +{ + int status; + struct flow_error error; + uint64_t flow = 0UL; + int port = MAX_PORTS; + + struct create_flow_ntconnect *flow_cpy = + (struct create_flow_ntconnect *)&(*data)[hdr->len]; + + if (hdr->blob_len != sizeof(struct create_flow_ntconnect)) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "Error in filter data"); + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_INVALID_REQUEST); + } + + port = flow_cpy->port; + + if (port >= MAX_PORTS) { + NT_LOG(ERR, NTCONNECT, "port id out of range"); + return ntconn_flow_err_reply_status(data, len, + NTCONN_FLOW_ERR_INVALID_PORT, + ENODEV); + } + +#ifdef DEBUG_PARSING + int i; + + for (i = 0; i < MAX_FLOW_STREAM_ELEM; i++) { + if (flow_cpy[i].elem[i].type == FLOW_ELEM_TYPE_END) { + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_END\n"); + break; + } + switch (flow_cpy->elem[i].type) { + case FLOW_ELEM_TYPE_IPV4: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_IPV4 %i\n", i); + NT_LOG(DBG, NTCONNECT, " src_ip: %u.%u.%u.%u\n", + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.src_ip)[1] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.src_ip)[2] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.src_ip)[3] & 0xFF); + NT_LOG(DBG, NTCONNECT, " dst_ip: %u.%u.%u.%u\n", + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.dst_ip)[1] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.dst_ip)[2] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.dst_ip)[3] & 0xFF); + NT_LOG(DBG, NTCONNECT, " src_mask: %u.%u.%u.%u\n", + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.src_ip)[1] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.src_ip)[2] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.src_ip)[3] & 0xFF); + NT_LOG(DBG, NTCONNECT, " dst_mask: %u.%u.%u.%u\n", + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.dst_ip)[1] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.dst_ip)[2] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.dst_ip)[3] & 0xFF); + break; + case FLOW_ELEM_TYPE_ETH: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_ETH %i\n", i); + NT_LOG(DBG, NTCONNECT, + " src mac: %02X:%02X:%02X:%02X:%02X:%02X\n", + flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[0] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[1] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[2] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[3] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[4] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[5] & 0xFF); + NT_LOG(DBG, NTCONNECT, + " dst mac: %02X:%02X:%02X:%02X:%02X:%02X\n", + flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[0] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[1] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[2] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[3] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[4] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[5] & 0xFF); + NT_LOG(DBG, NTCONNECT, + " src mask %02X:%02X:%02X:%02X:%02X:%02X\n", + flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[0] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[1] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[2] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[3] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[4] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[5] & 0xFF); + NT_LOG(DBG, NTCONNECT, + " dst mask %02X:%02X:%02X:%02X:%02X:%02X\n", + flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[0] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[1] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[2] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[3] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[4] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[5] & 0xFF); + break; + case FLOW_ELEM_TYPE_VLAN: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_VLAN %i\n", i); + break; + case FLOW_ELEM_TYPE_IPV6: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_IPV6 %i\n", i); + break; + case FLOW_ELEM_TYPE_SCTP: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_SCTP %i\n", i); + break; + case FLOW_ELEM_TYPE_TCP: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_TCP %i\n", i); + break; + case FLOW_ELEM_TYPE_UDP: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_UDP %i\n", i); + break; + case FLOW_ELEM_TYPE_ICMP: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_ICMP %i\n", i); + break; + case FLOW_ELEM_TYPE_VXLAN: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_VXLAN %i\n", i); + break; + case FLOW_ELEM_TYPE_PORT_ID: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_PORT_ID %i\n", + i); + break; + default: + NT_LOG(DBG, NTCONNECT, "Unknown item %u\n", + flow_cpy->elem[i].type); + break; + } + } + + for (i = 0; i < MAX_FLOW_STREAM_ELEM; i++) { + uint32_t j; + + if (flow_cpy->action[i].type == FLOW_ACTION_TYPE_END) { + NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_END\n"); + break; + } + switch (flow_cpy->action[i].type) { + case FLOW_ACTION_TYPE_RSS: + NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_RSS %i\n", i); + NT_LOG(DBG, NTCONNECT, " queue nb: %u\n", + flow_cpy->action[i].conf_cpy.u.rss.rss.queue_num); + NT_LOG(DBG, NTCONNECT, " queue: "); + for (j = 0; + j < flow_cpy->action[i] + .conf_cpy.u.rss.rss.queue_num && + j < FLOW_MAX_QUEUES; + j++) { + NT_LOG(DBG, NTCONNECT, "%u ", + flow_cpy->action[i] + .conf_cpy.u.rss.cpy_queue[j]); + } + NT_LOG(DBG, NTCONNECT, "\n"); + break; + + case FLOW_ACTION_TYPE_POP_VLAN: + NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_POP_VLAN %i\n", + i); + break; + case FLOW_ACTION_TYPE_PUSH_VLAN: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_PUSH_VLAN %i\n", i); + break; + case FLOW_ACTION_TYPE_SET_VLAN_VID: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_SET_VLAN_VID %i\n", i); + break; + case FLOW_ACTION_TYPE_SET_VLAN_PCP: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_SET_VLAN_PCP %i\n", i); + break; + case FLOW_ACTION_TYPE_VXLAN_DECAP: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_VXLAN_DECAP %i\n", i); + break; + case FLOW_ACTION_TYPE_VXLAN_ENCAP: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_VXLAN_ENCAP %i\n", i); + break; + case FLOW_ACTION_TYPE_DROP: + NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_DROP %i\n", i); + break; + case FLOW_ACTION_TYPE_COUNT: + NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_COUNT %i\n", + i); + break; + case FLOW_ACTION_TYPE_MARK: + NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_MARK %i\n", i); + break; + case FLOW_ACTION_TYPE_PORT_ID: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_PORT_ID %i: ID=%u\n", i, + flow_cpy->action[i].conf_cpy.u.port_id.id); + break; + case FLOW_ACTION_TYPE_QUEUE: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_QUEUE %i: queue=%u\n", i, + flow_cpy->action[i].conf_cpy.u.queue.index); + break; + case FLOW_ACTION_TYPE_SET_TAG: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_SET_TAG %i: idx=%u, data=%u, mask=%X\n", + i, flow_cpy->action[i].conf_cpy.u.tag.index, + flow_cpy->action[i].conf_cpy.u.tag.data, + flow_cpy->action[i].conf_cpy.u.tag.mask); + break; + default: + NT_LOG(DBG, NTCONNECT, "Unknown action %u\n", + flow_cpy->action[i].type); + break; + } + } +#endif + + /* Call filter with data */ + flow = make_flow_create(FLOW_API_FUNC_CREATE, port, flow_cpy, &status, + &error); + if (flow) { + *data = malloc(sizeof(struct create_flow_return_s)); + if (!*data) + goto create_flow_error_malloc; + struct create_flow_return_s *return_value = + (struct create_flow_return_s *)*data; + *len = sizeof(struct create_flow_return_s); + return_value->flow = flow; + return REQUEST_OK; + } + + *data = malloc(sizeof(struct flow_error_return_s)); + if (!*data) + goto create_flow_error_malloc; + struct flow_error_return_s *return_value = + (struct flow_error_return_s *)*data; + *len = sizeof(struct flow_error_return_s); + return_value->type = error.type; + strlcpy(return_value->err_msg, error.message, ERR_MSG_LEN); + return REQUEST_OK; + +create_flow_error_malloc: + + *len = 0; + NT_LOG(ERR, NTCONNECT, "Not able to allocate memory %s", __func__); + return REQUEST_ERR; +} + +static int func_flow_validate(void *hdl _unused, int client_id _unused, + struct ntconn_header_s *hdr, char **data, + int *len) +{ + int status; + struct flow_error error; + int port = MAX_PORTS; + + struct create_flow_ntconnect *flow_cpy = + (struct create_flow_ntconnect *)&(*data)[hdr->len]; + + if (hdr->blob_len != sizeof(struct create_flow_ntconnect)) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "Error in filter data"); + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_INVALID_REQUEST); + } + + set_error(&error); + +#ifdef DEBUG_FLOW + NT_LOG(DBG, NTCONNECT, "func_flow_create\n"); +#endif + + port = flow_cpy->port; + +#ifdef DEBUG_FLOW + NT_LOG(DBG, NTCONNECT, "Port id=%u\n", port); +#endif + + if (port >= MAX_PORTS) { + NT_LOG(ERR, NTCONNECT, "port id out of range"); + return ntconn_flow_err_reply_status(data, len, + NTCONN_FLOW_ERR_INVALID_PORT, ENODEV); + } + +#ifdef DEBUG_PARSING + int i; + + for (i = 0; i < MAX_FLOW_STREAM_ELEM; i++) { + if (flow_cpy[i].elem[i].type == FLOW_ELEM_TYPE_END) { + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_END\n"); + break; + } + switch (flow_cpy->elem[i].type) { + case FLOW_ELEM_TYPE_IPV4: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_IPV4 %i\n", i); + NT_LOG(DBG, NTCONNECT, " src_ip: %u.%u.%u.%u\n", + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF); + NT_LOG(DBG, NTCONNECT, " dst_ip: %u.%u.%u.%u\n", + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .spec_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF); + NT_LOG(DBG, NTCONNECT, " src_mask: %u.%u.%u.%u\n", + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF); + NT_LOG(DBG, NTCONNECT, " dst_mask: %u.%u.%u.%u\n", + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF, + ((const char *)&flow_cpy->elem[i] + .mask_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF); + break; + case FLOW_ELEM_TYPE_ETH: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_ETH %i\n", i); + NT_LOG(DBG, NTCONNECT, + " src mac: %02X:%02X:%02X:%02X:%02X:%02X\n", + flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[0] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[1] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[2] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[3] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[4] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[5] & 0xFF); + NT_LOG(DBG, NTCONNECT, + " dst mac: %02X:%02X:%02X:%02X:%02X:%02X\n", + flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[0] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[1] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[2] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[3] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[4] & 0xFF, + flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[5] & 0xFF); + NT_LOG(DBG, NTCONNECT, + " src mask %02X:%02X:%02X:%02X:%02X:%02X\n", + flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[0] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[1] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[2] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[3] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[4] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[5] & 0xFF); + NT_LOG(DBG, NTCONNECT, + " dst mask %02X:%02X:%02X:%02X:%02X:%02X\n", + flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[0] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[1] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[2] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[3] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[4] & 0xFF, + flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[5] & 0xFF); + break; + case FLOW_ELEM_TYPE_VLAN: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_VLAN %i\n", i); + break; + case FLOW_ELEM_TYPE_IPV6: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_IPV6 %i\n", i); + break; + case FLOW_ELEM_TYPE_SCTP: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_SCTP %i\n", i); + break; + case FLOW_ELEM_TYPE_TCP: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_TCP %i\n", i); + break; + case FLOW_ELEM_TYPE_UDP: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_UDP %i\n", i); + break; + case FLOW_ELEM_TYPE_ICMP: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_ICMP %i\n", i); + break; + case FLOW_ELEM_TYPE_VXLAN: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_VXLAN %i\n", i); + break; + case FLOW_ELEM_TYPE_PORT_ID: + NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_PORT_ID %i\n", + i); + break; + default: + NT_LOG(DBG, NTCONNECT, "Unknown item %u\n", + flow_cpy->elem[i].type); + break; + } + } + + for (i = 0; i < MAX_FLOW_STREAM_ELEM; i++) { + uint32_t j; + + if (flow_cpy->action[i].type == FLOW_ACTION_TYPE_END) { + NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_END\n"); + break; + } + switch (flow_cpy->action[i].type) { + case FLOW_ACTION_TYPE_RSS: + NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_RSS %i\n", i); + NT_LOG(DBG, NTCONNECT, " queue nb: %u\n", + flow_cpy->action[i].conf_cpy.u.rss.rss.queue_num); + NT_LOG(DBG, NTCONNECT, " queue: "); + for (j = 0; + j < flow_cpy->action[i] + .conf_cpy.u.rss.rss.queue_num && + j < FLOW_MAX_QUEUES; + j++) { + NT_LOG(DBG, NTCONNECT, "%u ", + flow_cpy->action[i] + .conf_cpy.u.rss.cpy_queue[j]); + } + NT_LOG(DBG, NTCONNECT, "\n"); + break; + + case FLOW_ACTION_TYPE_POP_VLAN: + NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_POP_VLAN %i\n", + i); + break; + case FLOW_ACTION_TYPE_PUSH_VLAN: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_PUSH_VLAN %i\n", i); + break; + case FLOW_ACTION_TYPE_SET_VLAN_VID: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_SET_VLAN_VID %i\n", i); + break; + case FLOW_ACTION_TYPE_SET_VLAN_PCP: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_SET_VLAN_PCP %i\n", i); + break; + case FLOW_ACTION_TYPE_VXLAN_DECAP: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_VXLAN_DECAP %i\n", i); + break; + case FLOW_ACTION_TYPE_VXLAN_ENCAP: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_VXLAN_ENCAP %i\n", i); + break; + case FLOW_ACTION_TYPE_DROP: + NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_DROP %i\n", i); + break; + case FLOW_ACTION_TYPE_COUNT: + NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_COUNT %i\n", + i); + break; + case FLOW_ACTION_TYPE_MARK: + NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_MARK %i\n", i); + break; + case FLOW_ACTION_TYPE_PORT_ID: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_PORT_ID %i: ID=%u\n", i, + flow_cpy->action[i].conf_cpy.u.port_id.id); + break; + case FLOW_ACTION_TYPE_QUEUE: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_QUEUE %i: queue=%u\n", i, + flow_cpy->action[i].conf_cpy.u.queue.index); + break; + case FLOW_ACTION_TYPE_SET_TAG: + NT_LOG(DBG, NTCONNECT, + "FLOW_ACTION_TYPE_SET_TAG %i: idx=%u, data=%u, mask=%X\n", + i, flow_cpy->action[i].conf_cpy.u.tag.index, + flow_cpy->action[i].conf_cpy.u.tag.data, + flow_cpy->action[i].conf_cpy.u.tag.mask); + break; + default: + NT_LOG(DBG, NTCONNECT, "Unknown action %u\n", + flow_cpy->action[i].type); + break; + } + } +#endif + + /* Call filter with data */ + make_flow_create(FLOW_API_FUNC_VALIDATE, port, flow_cpy, &status, + &error); + return copy_return_status(data, len, status, &error); + + /* Call filter with data */ + make_flow_create(FLOW_API_FUNC_VALIDATE, port, flow_cpy, &status, + &error); + if (!status) { + *data = malloc(sizeof(struct validate_flow_return_s)); + if (!*data) + goto validate_flow_error_malloc; + struct validate_flow_return_s *return_value = + (struct validate_flow_return_s *)*data; + *len = sizeof(struct validate_flow_return_s); + return_value->status = 0; + return REQUEST_OK; + } + + *data = malloc(sizeof(struct flow_error_return_s)); + if (!*data) + goto validate_flow_error_malloc; + struct flow_error_return_s *return_value = + (struct flow_error_return_s *)*data; + *len = sizeof(struct flow_error_return_s); + return_value->type = error.type; + strlcpy(return_value->err_msg, error.message, ERR_MSG_LEN); + return_value->status = status; + return REQUEST_OK; + +validate_flow_error_malloc: + + *len = 0; + NT_LOG(ERR, NTCONNECT, "Not able to allocate memory %s", __func__); + return REQUEST_ERR; +} + +static int func_flow_query(void *hdl _unused, int client_id _unused, + struct ntconn_header_s *hdr, char **data, int *len) +{ + int status; + struct flow_error error; + int port = MAX_PORTS; + struct flow_handle *flow; + + struct query_flow_ntconnect *flow_cpy = + (struct query_flow_ntconnect *)&(*data)[hdr->len]; + + if (hdr->blob_len != sizeof(struct query_flow_ntconnect)) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "Error in filter data"); + return ntconn_error(data, len, this_module_name, + NTCONN_ERR_CODE_INVALID_REQUEST); + } + + set_error(&error); + +#ifdef DEBUG_FLOW + NT_LOG(DBG, NTCONNECT, "%s: [%s:%u] enter\n", __func__, __FILE__, __LINE__); +#endif + + port = flow_cpy->port; + +#ifdef DEBUG_FLOW + NT_LOG(DBG, NTCONNECT, "Port id=%u\n", port); +#endif + + if (port >= MAX_PORTS) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "port id out of range"); + return ntconn_flow_err_reply_status(data, len, + NTCONN_FLOW_ERR_INVALID_PORT, ENODEV); + } + +#ifdef DEBUG_FLOW + NT_LOG(DBG, NTCONNECT, "flow=0x%016llX\n", + (unsigned long long)flow_cpy->flow); +#endif + + flow = (struct flow_handle *)flow_cpy->flow; + + const struct flow_action action = { + flow_cpy->action.type, + (const void *)&flow_cpy->action.conf_cpy.u.count + }; + + /* Call filter with data */ + void *data_out = NULL; + uint32_t length = 0; + + status = flow_query(port_eth[port].flw_dev, flow, &action, &data_out, + &length, &error); + + *data = malloc(sizeof(struct query_flow_return_s) + length); + if (*data) { + struct query_flow_return_s *return_value = + (struct query_flow_return_s *)*data; + *len = sizeof(struct query_flow_return_s) + length; + + return_value->status = status; + return_value->type = error.type; + strlcpy(return_value->err_msg, error.message, ERR_MSG_LEN); + + if (data_out) { + memcpy(return_value->data, data_out, length); + return_value->data_length = length; + free(data_out); + } else { + return_value->data_length = 0; + } + return REQUEST_OK; + } + *len = 0; + NT_LOG(ERR, NTCONNECT, "Not able to allocate memory %s", + __func__); + return REQUEST_ERR; +} + +static int flow_request(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr, char *function, + char **data, int *len) +{ + return execute_function(this_module_name, hdl, client_id, hdr, function, + adapter_entry_funcs, data, len, 0); +} + +static void flow_free_data(void *hdl _unused, char *data) +{ + if (data) + free(data); +} + +static void flow_client_cleanup(void *hdl _unused, int client_id _unused) +{ + /* Nothing to do */ +} + +static const ntconnapi_t ntconn_flow_op = { this_module_name, + NTCONN_FLOW_VERSION_MAJOR, + NTCONN_FLOW_VERSION_MINOR, + flow_request, + flow_free_data, + flow_client_cleanup + }; + +int ntconn_flow_register(struct drv_s *drv) +{ + int i; + + for (i = 0; i < MAX_CLIENTS; i++) { + if (flow_hdl[i].drv == NULL) + break; + } + if (i == MAX_CLIENTS) { + NT_LOG(ERR, NTCONNECT, + "Cannot register more adapters into NtConnect framework"); + return -1; + } + + flow_hdl[i].drv = drv; + return register_ntconn_mod(&drv->p_dev->addr, (void *)&flow_hdl[i], + &ntconn_flow_op); +} diff --git a/drivers/net/ntnic/ntconnect_modules/ntconn_meter.c b/drivers/net/ntnic/ntconnect_modules/ntconn_meter.c new file mode 100644 index 0000000000..7c21690f8b --- /dev/null +++ b/drivers/net/ntnic/ntconnect_modules/ntconn_meter.c @@ -0,0 +1,517 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include "ntnic_ethdev.h" +#include "ntconnect.h" +#include "ntos_system.h" +#include "ntconn_modules.h" +#include "ntconn_mod_helper.h" +#include "nt_util.h" +#include "ntlog.h" +#include "ntnic_vf_vdpa.h" + +#include "ntconnect_api_meter.h" +#include "flow_api_profile_inline.h" + +#include +#include +#include + +#define NTCONN_METER_VERSION_MAJOR 0U +#define NTCONN_METER_VERSION_MINOR 1U + +#define this_module_name "meter" + +#define MAX_CLIENTS 32 + +#define UNUSED __rte_unused + +static struct meter_hdl_s { + struct drv_s *drv; +} meter_hdl[MAX_CLIENTS]; + +static ntconn_err_t ntconn_err[] = { + { NTCONN_METER_ERR_NONE, "Success" }, + { NTCONN_METER_ERR_INTERNAL_ERROR, "Internal error" }, + { NTCONN_METER_ERR_INVALID_PORT, "Invalid virtual port" }, + { NTCONN_METER_ERR_PROFILE_ID, "Profile ID out of range" }, + { NTCONN_METER_ERR_POLICY_ID, "Policy ID out of range" }, + { NTCONN_METER_ERR_METER_ID, "Meter ID out of range" }, + { -1, NULL } +}; + +/********************************************************************/ +/* Get error message corresponding to the error code */ +/********************************************************************/ +static const char *get_error_msg(uint32_t err_code) +{ + int idx = 0; + + if (err_code < NTCONN_METER_ERR_INTERNAL_ERROR) { + const ntconn_err_t *err_msg = get_ntconn_error(err_code); + + return err_msg->err_text; + } + while (ntconn_err[idx].err_code != (uint32_t)-1 && + ntconn_err[idx].err_code != err_code) + idx++; + if (ntconn_err[idx].err_code == (uint32_t)-1) + idx = 1; + return ntconn_err[idx].err_text; +} + +/* + * Filter functions + */ +static int func_meter_get_capabilities(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static int func_meter_setup(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, int *len); +static int func_meter_read(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, int *len); +static struct func_s adapter_entry_funcs[] = { + { "capabilities", NULL, func_meter_get_capabilities }, + { "setup", NULL, func_meter_setup }, + { "read", NULL, func_meter_read }, + { NULL, NULL, NULL }, +}; + +/**********************************************************************/ +/* copy error message corresponding to the error code to error struct */ +/**********************************************************************/ +static void copy_mtr_error(struct rte_mtr_error *error, uint32_t err) +{ + error->type = RTE_MTR_ERROR_TYPE_UNSPECIFIED; + error->message = get_error_msg(err); + error->cause = NULL; +} + +static int func_meter_get_capabilities(void *hdl _unused, int client_id _unused, + struct ntconn_header_s *hdr _unused, + char **data, int *len) +{ + char *saveptr; + uint8_t vport = 0; + uint8_t port = 0; + int status; + struct rte_mtr_capabilities cap; + struct rte_mtr_error error; + +#ifdef DEBUG_METER + NT_LOG(DBG, NTCONNECT, "%s: \"%s\"\n", __func__, *data); +#endif + + char *tok = strtok_r(*data, ",", &saveptr); + + if (tok) { + int length = strlen(tok); + + if (length > 6 && memcmp(tok, "vport=", 6) == 0) + vport = atoi(tok + 6); + } +#ifdef DEBUG_METER + NT_LOG(DBG, NTCONNECT, "vport=%u\n", vport); +#endif + + if (vport == 0 || vport > 64) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "Virtual port is invalid"); + copy_mtr_error(&error, NTCONN_METER_ERR_INVALID_PORT); + status = -ENODEV; + goto error_get_capa; + } + + port = vport & 1; + status = rte_mtr_capabilities_get(port, &cap, &error); + if (status == 0) { + /* Handle success by copying the return values to the return struct */ + *data = malloc(sizeof(struct meter_capabilities_return_s)); + if (!*data) + goto error_get_capa_malloc; + struct meter_capabilities_return_s *return_value = + (struct meter_capabilities_return_s *)*data; + *len = sizeof(struct meter_capabilities_return_s); + memcpy(&return_value->cap, &cap, + sizeof(struct rte_mtr_capabilities)); + return REQUEST_OK; + } + +error_get_capa: + + /* Handle errors by copy errors to the error struct */ + NT_LOG(ERR, NTCONNECT, "Failed to get capabilities for port %u (%u)", + port, vport); + *data = malloc(sizeof(struct meter_error_return_s)); + if (!*data) + goto error_get_capa_malloc; + struct meter_error_return_s *return_value = + (struct meter_error_return_s *)*data; + *len = sizeof(struct meter_error_return_s); + return_value->status = status; + return_value->type = error.type; + strlcpy(return_value->err_msg, error.message, ERR_MSG_LEN); + return REQUEST_OK; + +error_get_capa_malloc: + + *len = 0; + return REQUEST_ERR; +} + +static int func_meter_setup(void *hdl _unused, int client_id _unused, + struct ntconn_header_s *hdr, char **data, int *len) +{ + char *saveptr; + uint8_t port; + uint32_t max_id; + int status; + struct rte_mtr_error error; + int command = UNKNOWN_CMD; + +#ifdef DEBUG_METER + NT_LOG(DBG, NTCONNECT, "%s: \"%s\"\n", __func__, *data); +#endif + + if (hdr->blob_len != sizeof(struct meter_setup_s)) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "Error: Profile data size is illegal"); + copy_mtr_error(&error, NTCONN_ERR_CODE_INVALID_REQUEST); + status = -EINTR; + goto error_meter_setup; + } + + /* Get the data blob containing the data for the meter function */ + struct meter_setup_s *cpy_data = + (struct meter_setup_s *)&(*data)[hdr->len]; + + if (cpy_data->vport < 4 || cpy_data->vport > 128) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "Virtual port is invalid"); + copy_mtr_error(&error, NTCONN_METER_ERR_INVALID_PORT); + status = -ENODEV; + goto error_meter_setup; + } + + char *tok = strtok_r(*data, ",", &saveptr); + + if (tok) { + int length = strlen(tok); + + if (length == 6) { + if (memcmp(tok, "addpro", 6) == 0) + command = ADD_PROFILE; + + else if (memcmp(tok, "delpro", 6) == 0) + command = DEL_PROFILE; + + else if (memcmp(tok, "addpol", 6) == 0) + command = ADD_POLICY; + + else if (memcmp(tok, "delpol", 6) == 0) + command = DEL_POLICY; + + else if (memcmp(tok, "crtmtr", 6) == 0) + command = CREATE_MTR; + + else if (memcmp(tok, "delmtr", 6) == 0) + command = DEL_MTR; + } + } + + if (command == UNKNOWN_CMD) { + NT_LOG(ERR, NTCONNECT, "Error: Invalid command"); + copy_mtr_error(&error, NTCONN_ERR_CODE_INVALID_REQUEST); + status = -EINVAL; + goto error_meter_setup; + } + + /* Port will be either 0 or 1 depending on the VF. */ + port = cpy_data->vport & 1; + + switch (command) { + case ADD_PROFILE: + max_id = flow_mtr_meter_policy_n_max() / (RTE_MAX_ETHPORTS - 2); + if (cpy_data->id > max_id) { + NT_LOG(ERR, NTCONNECT, + "Error: Profile ID %u out of range. Max value is %u", + cpy_data->id, max_id); + copy_mtr_error(&error, NTCONN_METER_ERR_PROFILE_ID); + status = -EINVAL; + goto error_meter_setup; + } + cpy_data->id = ((cpy_data->vport - 4) * max_id) + cpy_data->id; + status = rte_mtr_meter_profile_add(port, cpy_data->id, + &cpy_data->profile, &error); + if (status != 0) { + NT_LOG(ERR, NTCONNECT, + "Failed to add profile for port %u (%u)", port, + cpy_data->vport); + } + break; + case DEL_PROFILE: + max_id = flow_mtr_meter_policy_n_max() / (RTE_MAX_ETHPORTS - 2); + if (cpy_data->id > max_id) { + NT_LOG(ERR, NTCONNECT, + "Error: Profile ID %u out of range. Max value is %u", + cpy_data->id, max_id); + copy_mtr_error(&error, NTCONN_METER_ERR_PROFILE_ID); + status = -EINVAL; + goto error_meter_setup; + } + cpy_data->id = ((cpy_data->vport - 4) * max_id) + cpy_data->id; + status = rte_mtr_meter_profile_delete(port, cpy_data->id, + &error); + if (status != 0) { + NT_LOG(ERR, NTCONNECT, + "Failed to delete profile for port %u (%u)", + port, cpy_data->vport); + } + break; + case ADD_POLICY: + max_id = flow_mtr_meter_policy_n_max() / (RTE_MAX_ETHPORTS - 2); + if (cpy_data->id > max_id) { + NT_LOG(ERR, NTCONNECT, + "Error: Policy ID %u out of range. Max value is %u", + cpy_data->id, max_id); + copy_mtr_error(&error, NTCONN_METER_ERR_POLICY_ID); + status = -EINVAL; + goto error_meter_setup; + } + cpy_data->id = ((cpy_data->vport - 4) * max_id) + cpy_data->id; + cpy_data->p.policy.actions[RTE_COLOR_GREEN] = + cpy_data->p.actions_green; + cpy_data->p.policy.actions[RTE_COLOR_YELLOW] = + cpy_data->p.actions_yellow; + cpy_data->p.policy.actions[RTE_COLOR_RED] = + cpy_data->p.actions_red; + status = rte_mtr_meter_policy_add(port, cpy_data->id, + &cpy_data->p.policy, &error); + if (status != 0) { + NT_LOG(ERR, NTCONNECT, + "Failed to add policy for port %u (%u)", port, + cpy_data->vport); + } + break; + case DEL_POLICY: + max_id = flow_mtr_meter_policy_n_max() / (RTE_MAX_ETHPORTS - 2); + if (cpy_data->id > max_id) { + NT_LOG(ERR, NTCONNECT, + "Error: Policy ID %u out of range. Max value is %u", + cpy_data->id, max_id); + copy_mtr_error(&error, NTCONN_METER_ERR_POLICY_ID); + status = -EINVAL; + goto error_meter_setup; + } + cpy_data->id = ((cpy_data->vport - 4) * max_id) + cpy_data->id; + status = + rte_mtr_meter_policy_delete(port, cpy_data->id, &error); + if (status != 0) { + NT_LOG(ERR, NTCONNECT, + "Failed to delete policy for port %u (%u)", port, + cpy_data->vport); + } + break; + case CREATE_MTR: + max_id = flow_mtr_meters_supported() / (RTE_MAX_ETHPORTS - 2); + if (cpy_data->id > max_id) { + NT_LOG(ERR, NTCONNECT, + "Error: Meter ID %u out of range. Max value is %u", + cpy_data->id, max_id); + copy_mtr_error(&error, NTCONN_METER_ERR_METER_ID); + status = -EINVAL; + goto error_meter_setup; + } + cpy_data->id = ((cpy_data->vport - 4) * max_id) + cpy_data->id; + cpy_data->mtr_params.meter_profile_id = + ((cpy_data->vport - 4) * + (flow_mtr_meter_policy_n_max() / + (RTE_MAX_ETHPORTS - 2))) + + cpy_data->mtr_params.meter_profile_id; + cpy_data->mtr_params.meter_policy_id = + ((cpy_data->vport - 4) * + (flow_mtr_meter_policy_n_max() / + (RTE_MAX_ETHPORTS - 2))) + + cpy_data->mtr_params.meter_policy_id; + status = rte_mtr_create(port, cpy_data->id, + &cpy_data->mtr_params, cpy_data->shared, + &error); + if (status != 0) { + NT_LOG(ERR, NTCONNECT, + "Failed to create meter for port %u (%u)", port, + cpy_data->vport); + } + break; + case DEL_MTR: + max_id = flow_mtr_meters_supported() / (RTE_MAX_ETHPORTS - 2); + if (cpy_data->id > max_id) { + NT_LOG(ERR, NTCONNECT, + "Error: Meter ID %u out of range. Max value is %u", + cpy_data->id, max_id); + copy_mtr_error(&error, NTCONN_METER_ERR_METER_ID); + status = -EINVAL; + goto error_meter_setup; + } + cpy_data->id = ((cpy_data->vport - 4) * max_id) + cpy_data->id; + status = rte_mtr_destroy(port, cpy_data->id, &error); + if (status != 0) { + NT_LOG(ERR, NTCONNECT, + "Failed to destroy meter for port %u (%u)", port, + cpy_data->vport); + } + break; + } + + if (status == 0) { + /* Handle success by copying the return values to the return struct */ + *data = malloc(sizeof(struct meter_return_s)); + if (!*data) + goto error_meter_setup_malloc; + struct meter_return_s *return_value = + (struct meter_return_s *)*data; + *len = sizeof(struct meter_return_s); + return_value->status = 0; + return REQUEST_OK; + } + +error_meter_setup: + + /* Handle errors by copy errors to the error struct */ + *data = malloc(sizeof(struct meter_error_return_s)); + if (!*data) + goto error_meter_setup_malloc; + struct meter_error_return_s *return_value = + (struct meter_error_return_s *)*data; + *len = sizeof(struct meter_error_return_s); + return_value->status = status; + return_value->type = error.type; + strlcpy(return_value->err_msg, error.message, ERR_MSG_LEN); + return REQUEST_OK; + +error_meter_setup_malloc: + + *len = 0; + return REQUEST_ERR; +} + +static int func_meter_read(void *hdl _unused, int client_id _unused, + struct ntconn_header_s *hdr, char **data, int *len) +{ + uint8_t port = 0; + int status; + struct rte_mtr_error error; + struct rte_mtr_stats stats; + uint64_t stats_mask; + +#ifdef DEBUG_METER + NT_LOG(DBG, NTCONNECT, "%s: [%s:%u] enter\n", __func__, __FILE__, __LINE__); +#endif + + if (hdr->blob_len != sizeof(struct meter_get_stat_s)) { + *len = 0; + NT_LOG(ERR, NTCONNECT, + "Error: Read meter stats data size is illegal"); + copy_mtr_error(&error, NTCONN_ERR_CODE_INVALID_REQUEST); + status = -EINTR; + goto error_meter_read; + } + + /* Get the data blob containing the data for the meter function */ + struct meter_get_stat_s *cpy_data = + (struct meter_get_stat_s *)&(*data)[hdr->len]; + + if (cpy_data->vport < 4 || cpy_data->vport > 128) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "Virtual port is invalid"); + copy_mtr_error(&error, NTCONN_METER_ERR_INVALID_PORT); + status = -ENODEV; + goto error_meter_read; + } + + port = cpy_data->vport & 1; + cpy_data->mtr_id = + ((cpy_data->vport - 4) * + (flow_mtr_meters_supported() / (RTE_MAX_ETHPORTS - 2))) + + cpy_data->mtr_id; + status = rte_mtr_stats_read(port, cpy_data->mtr_id, &stats, &stats_mask, + cpy_data->clear, &error); + if (status == 0) { + /* Handle success by copying the return values to the return struct */ + *data = malloc(sizeof(struct meter_return_stat_s)); + if (!*data) + goto error_meter_read_malloc; + struct meter_return_stat_s *return_value = + (struct meter_return_stat_s *)*data; + *len = sizeof(struct meter_return_stat_s); + return_value->stats_mask = stats_mask; + memcpy(&return_value->stats, &stats, + sizeof(struct rte_mtr_stats)); + return REQUEST_OK; + } + +error_meter_read: + /* Handle errors by copy errors to the error struct */ + NT_LOG(ERR, NTCONNECT, "Failed to read meter stats"); + *data = malloc(sizeof(struct meter_error_return_s)); + if (!*data) + goto error_meter_read_malloc; + struct meter_error_return_s *return_value = + (struct meter_error_return_s *)*data; + *len = sizeof(struct meter_error_return_s); + strlcpy(return_value->err_msg, error.message, ERR_MSG_LEN); + return_value->status = status; + return_value->type = error.type; + return REQUEST_OK; + +error_meter_read_malloc: + *len = 0; + return REQUEST_ERR; +} + +static int meter_request(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr, char *function, + char **data, int *len) +{ + return execute_function(this_module_name, hdl, client_id, hdr, function, + adapter_entry_funcs, data, len, 0); +} + +static void meter_free_data(void *hdl _unused, char *data) +{ + if (data) + free(data); +} + +static void meter_client_cleanup(void *hdl _unused, int client_id _unused) +{ + /* Nothing to do */ +} + +static const ntconnapi_t ntconn_meter_op = { this_module_name, + NTCONN_METER_VERSION_MAJOR, + NTCONN_METER_VERSION_MINOR, + meter_request, + meter_free_data, + meter_client_cleanup + }; + +int ntconn_meter_register(struct drv_s *drv) +{ + int i; + + for (i = 0; i < MAX_CLIENTS; i++) { + if (meter_hdl[i].drv == NULL) + break; + } + if (i == MAX_CLIENTS) { + NT_LOG(ERR, NTCONNECT, + "Cannot register more adapters into NtConnect framework"); + return -1; + } + + meter_hdl[i].drv = drv; + return register_ntconn_mod(&drv->p_dev->addr, (void *)&meter_hdl[i], + &ntconn_meter_op); +} diff --git a/drivers/net/ntnic/ntconnect_modules/ntconn_modules.h b/drivers/net/ntnic/ntconnect_modules/ntconn_modules.h new file mode 100644 index 0000000000..ea379015fe --- /dev/null +++ b/drivers/net/ntnic/ntconnect_modules/ntconn_modules.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTCONN_MODULES_H_ +#define _NTCONN_MODULES_H_ + +#include "ntos_system.h" + +/* + * All defined NT connection modules + */ +int ntconn_adap_register(struct drv_s *drv); +int ntconn_stat_register(struct drv_s *drv); +int ntconn_flow_register(struct drv_s *drv); +int ntconn_meter_register(struct drv_s *drv); +int ntconn_test_register(struct drv_s *drv); + +#endif /* _NTCONN_MODULES_H_ */ diff --git a/drivers/net/ntnic/ntconnect_modules/ntconn_stat.c b/drivers/net/ntnic/ntconnect_modules/ntconn_stat.c new file mode 100644 index 0000000000..5c8b8db39e --- /dev/null +++ b/drivers/net/ntnic/ntconnect_modules/ntconn_stat.c @@ -0,0 +1,876 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include +#include +#include + +#include "ntconnect.h" +#include "ntconnect_api_statistic.h" +#include "ntos_system.h" +#include "ntconn_modules.h" +#include "ntconn_mod_helper.h" +#include "nt_util.h" +#include "ntlog.h" +#include "ntnic_xstats.h" + +#define STAT_VERSION_MAJOR 0U +#define STAT_VERSION_MINOR 2U + +#define this_module_name "stat" + +/* + * Supported Stat Layout Versions + */ +#define NUM_LAYOUT_VERSIONS_SUPPORTED (RTE_DIM(layout_versions_supported)) +static int layout_versions_supported[] = { + 6, + /* + * Add here other layout versions to support + * When more versions are added, add new version dependent binary reply structures + * in ntconnect_api.h file for client to select on reading layout_version + */ +}; + +enum snap_addr_select_e { + SNAP_COLORS, + SNAP_QUEUES, + SNAP_RX_PORT, + SNAP_TX_PORT, + SNAP_ADDR_COUNT +}; + +struct snap_addr_s { + const uint64_t *ptr; + unsigned int size; +}; + +struct snaps_s { + int client_id; + /* Pointers into buffer */ + struct snap_addr_s snap_addr[SNAP_ADDR_COUNT]; + uint64_t *buffer; + struct snaps_s *next; +}; + +static struct stat_hdl { + struct drv_s *drv; + nt4ga_stat_t *p_nt4ga_stat; + struct snaps_s *snaps_base; +} stat_hdl; + +enum stat_type_e { + STAT_TYPE_COLOR, + STAT_TYPE_QUEUE, + STAT_TYPE_RX, + STAT_TYPE_TX, + STAT_TYPE_FLOWMATCHER +}; + +static int func_get_snap_colors(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static int func_get_snap_queues(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static int func_get_snap_rx_port(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static int func_get_snap_tx_port(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static struct func_s func_snap_level2[] = { + { "colors", NULL, func_get_snap_colors }, + { "queues", NULL, func_get_snap_queues }, + { "rx_counters", NULL, func_get_snap_rx_port }, + { "tx_counters", NULL, func_get_snap_tx_port }, + { NULL, NULL, NULL }, +}; + +static int func_get_layout_version(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static int func_get_flm(void *hdl, int client_id, struct ntconn_header_s *hdr, + char **data, int *len); +static int func_get_color(void *hdl, int client_id, struct ntconn_header_s *hdr, + char **data, int *len); +static int func_get_queue(void *hdl, int client_id, struct ntconn_header_s *hdr, + char **data, int *len); +static int func_get_rx_counters(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static int func_get_tx_counters(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); +static int func_get_flm_layout_version(void *hdl, int client_id, + struct ntconn_header_s *hdr, char **data, + int *len); + +static struct func_s funcs_get_level1[] = { + { "snapshot", func_snap_level2, NULL }, + { "layout_version", NULL, func_get_layout_version }, + { "flm", NULL, func_get_flm }, + { "colors", NULL, func_get_color }, + { "queues", NULL, func_get_queue }, + { "rx_counters", NULL, func_get_rx_counters }, + { "tx_counters", NULL, func_get_tx_counters }, + { "flm_layout_version", NULL, func_get_flm_layout_version }, + { NULL, NULL, NULL }, +}; + +/* + * Entry level + */ +static int func_snapshot(void *hdl, int client_id, struct ntconn_header_s *hdr, + char **data, int *len); +static struct func_s stat_entry_funcs[] = { + { "get", funcs_get_level1, NULL }, + { "snapshot", NULL, func_snapshot }, + { NULL, NULL, NULL }, +}; + +static int read_flm(nt4ga_stat_t *hwstat, uint64_t *val, int nbc) +{ + struct ntc_stat_get_data_s *cdata = (struct ntc_stat_get_data_s *)val; + + cdata->nb_counters = (uint64_t)nbc; + cdata->timestamp = hwstat->last_timestamp; + cdata->is_virt = hwstat->mp_nthw_stat->mb_is_vswitch; + + struct rte_eth_xstat stats[100]; + struct rte_eth_xstat_name names[100]; + int cnt_names = nthw_xstats_get_names(hwstat, names, 100, + hwstat->mp_nthw_stat->mb_is_vswitch); + int cnt_values = nthw_xstats_get(hwstat, stats, 100, + hwstat->mp_nthw_stat->mb_is_vswitch, 0); + assert(cnt_names == cnt_values); + + /* virt/cap same */ + struct flowmatcher_type_fields_s *flm = + (struct flowmatcher_type_fields_s *)cdata->data; + if (hwstat->mp_stat_structs_flm) { + int c; + + for (c = 0; c < nbc; c++) { + flm->current = hwstat->mp_stat_structs_flm->current; + flm->learn_done = hwstat->mp_stat_structs_flm->learn_done; + flm->learn_ignore = + hwstat->mp_stat_structs_flm->learn_ignore; + flm->learn_fail = hwstat->mp_stat_structs_flm->learn_fail; + flm->unlearn_done = + hwstat->mp_stat_structs_flm->unlearn_done; + flm->unlearn_ignore = + hwstat->mp_stat_structs_flm->unlearn_ignore; + flm->auto_unlearn_done = + hwstat->mp_stat_structs_flm->auto_unlearn_done; + flm->auto_unlearn_ignore = + hwstat->mp_stat_structs_flm->auto_unlearn_ignore; + flm->auto_unlearn_fail = + hwstat->mp_stat_structs_flm->auto_unlearn_fail; + flm->timeout_unlearn_done = + hwstat->mp_stat_structs_flm->timeout_unlearn_done; + flm->rel_done = hwstat->mp_stat_structs_flm->rel_done; + flm->rel_ignore = hwstat->mp_stat_structs_flm->rel_ignore; + flm->prb_done = hwstat->mp_stat_structs_flm->prb_done; + flm->prb_ignore = hwstat->mp_stat_structs_flm->prb_ignore; + + flm->sta_done = hwstat->mp_stat_structs_flm->sta_done; + flm->inf_done = hwstat->mp_stat_structs_flm->inf_done; + flm->inf_skip = hwstat->mp_stat_structs_flm->inf_skip; + flm->pck_hit = hwstat->mp_stat_structs_flm->pck_hit; + flm->pck_miss = hwstat->mp_stat_structs_flm->pck_miss; + flm->pck_unh = hwstat->mp_stat_structs_flm->pck_unh; + flm->pck_dis = hwstat->mp_stat_structs_flm->pck_dis; + flm->csh_hit = hwstat->mp_stat_structs_flm->csh_hit; + flm->csh_miss = hwstat->mp_stat_structs_flm->csh_miss; + flm->csh_unh = hwstat->mp_stat_structs_flm->csh_unh; + flm->cuc_start = hwstat->mp_stat_structs_flm->cuc_start; + flm->cuc_move = hwstat->mp_stat_structs_flm->cuc_move; + } + } else { + memset(flm, 0, sizeof(*hwstat->mp_stat_structs_flm)); + } + return nbc * NUM_STAT_RECORD_TYPE_FLOWMATCHER + STAT_INFO_ELEMENTS; +} + +static int read_colors(nt4ga_stat_t *hwstat, uint64_t *val, int nbc) +{ + struct ntc_stat_get_data_s *cdata = (struct ntc_stat_get_data_s *)val; + + cdata->nb_counters = (uint64_t)nbc; + cdata->timestamp = hwstat->last_timestamp; + cdata->is_virt = hwstat->mp_nthw_stat->mb_is_vswitch; + + /* virt/cap same */ + struct color_type_fields_s *clr = + (struct color_type_fields_s *)cdata->data; + int c; + + for (c = 0; c < nbc; c++) { + clr->pkts = hwstat->mp_stat_structs_color[c].color_packets; + clr->octets = hwstat->mp_stat_structs_color[c].color_bytes; + clr->tcp_flgs = + (uint64_t)hwstat->mp_stat_structs_color[c].tcp_flags; + clr++; + } + return nbc * NUM_STAT_RECORD_TYPE_COLOR + STAT_INFO_ELEMENTS; +} + +static int read_queues(nt4ga_stat_t *hwstat, uint64_t *val, int nbq) +{ + struct ntc_stat_get_data_s *qdata = (struct ntc_stat_get_data_s *)val; + + qdata->nb_counters = (uint64_t)nbq; + qdata->timestamp = hwstat->last_timestamp; + qdata->is_virt = hwstat->mp_nthw_stat->mb_is_vswitch; + + /* virt/cap same */ + struct queue_type_fields_s *queue = + (struct queue_type_fields_s *)qdata->data; + int q; + + for (q = 0; q < nbq; q++) { + queue->flush_pkts = hwstat->mp_stat_structs_hb[q].flush_packets; + queue->drop_pkts = hwstat->mp_stat_structs_hb[q].drop_packets; + queue->fwd_pkts = hwstat->mp_stat_structs_hb[q].fwd_packets; + queue->dbs_drop_pkts = hwstat->mp_stat_structs_hb[q].dbs_drop_packets; + queue->flush_octets = hwstat->mp_stat_structs_hb[q].flush_bytes; + queue->drop_octets = hwstat->mp_stat_structs_hb[q].drop_bytes; + queue->fwd_octets = hwstat->mp_stat_structs_hb[q].fwd_bytes; + queue->dbs_drop_octets = hwstat->mp_stat_structs_hb[q].dbs_drop_bytes; + queue++; + } + return nbq * NUM_STAT_RECORD_TYPE_QUEUE + STAT_INFO_ELEMENTS; +} + +static void copy_rmon_stat(struct port_counters_v2 *cptr, + struct stat_rmon_s *rmon) +{ + rmon->drop_events = cptr->drop_events; + rmon->pkts = cptr->pkts; + rmon->octets = cptr->octets; + rmon->broadcast_pkts = cptr->broadcast_pkts; + rmon->multicast_pkts = cptr->multicast_pkts; + rmon->unicast_pkts = cptr->unicast_pkts; + rmon->pkts_alignment = cptr->pkts_alignment; + rmon->pkts_code_violation = cptr->pkts_code_violation; + rmon->pkts_crc = cptr->pkts_crc; + rmon->undersize_pkts = cptr->undersize_pkts; + rmon->oversize_pkts = cptr->oversize_pkts; + rmon->fragments = cptr->fragments; + rmon->jabbers_not_truncated = cptr->jabbers_not_truncated; + rmon->jabbers_truncated = cptr->jabbers_truncated; + rmon->pkts_64_octets = cptr->pkts_64_octets; + rmon->pkts_65_to_127_octets = cptr->pkts_65_to_127_octets; + rmon->pkts_128_to_255_octets = cptr->pkts_128_to_255_octets; + rmon->pkts_256_to_511_octets = cptr->pkts_256_to_511_octets; + rmon->pkts_512_to_1023_octets = cptr->pkts_512_to_1023_octets; + rmon->pkts_1024_to_1518_octets = cptr->pkts_1024_to_1518_octets; + rmon->pkts_1519_to_2047_octets = cptr->pkts_1519_to_2047_octets; + rmon->pkts_2048_to_4095_octets = cptr->pkts_2048_to_4095_octets; + rmon->pkts_4096_to_8191_octets = cptr->pkts_4096_to_8191_octets; + rmon->pkts_8192_to_max_octets = cptr->pkts_8192_to_max_octets; +} + +static int read_rx_counters(nt4ga_stat_t *hwstat, uint64_t *val, int nbp) +{ + struct ntc_stat_get_data_s *rxdata = (struct ntc_stat_get_data_s *)val; + + rxdata->nb_counters = (uint64_t)nbp; + rxdata->timestamp = hwstat->last_timestamp; + rxdata->is_virt = hwstat->mp_nthw_stat->mb_is_vswitch; + + if (rxdata->is_virt) { + struct rtx_type_fields_virt_s *rxc = + (struct rtx_type_fields_virt_s *)rxdata->data; + int p; + + for (p = 0; p < nbp; p++) { + rxc->octets = + hwstat->virt.mp_stat_structs_port_rx[p].octets; + rxc->pkts = hwstat->virt.mp_stat_structs_port_rx[p].pkts; + rxc->drop_events = + hwstat->virt.mp_stat_structs_port_rx[p].drop_events; + rxc->qos_drop_octets = + hwstat->virt.mp_stat_structs_port_rx[p] + .qos_drop_octets; + rxc->qos_drop_pkts = hwstat->virt.mp_stat_structs_port_rx[p] + .qos_drop_pkts; + rxc++; + } + return nbp * NUM_STAT_RECORD_TYPE_RX_PORT_VIRT + + STAT_INFO_ELEMENTS; + } else { + struct rx_type_fields_cap_s *rxc = + (struct rx_type_fields_cap_s *)rxdata->data; + int p; + + for (p = 0; p < nbp; p++) { + copy_rmon_stat(&hwstat->cap.mp_stat_structs_port_rx[p], + &rxc->rmon); + + /* Rx only port counters */ + rxc->mac_drop_events = + hwstat->cap.mp_stat_structs_port_rx[p] + .mac_drop_events; + rxc->pkts_lr = + hwstat->cap.mp_stat_structs_port_rx[p].pkts_lr; + rxc->duplicate = + hwstat->cap.mp_stat_structs_port_rx[p].duplicate; + rxc->pkts_ip_chksum_error = + hwstat->cap.mp_stat_structs_port_rx[p] + .pkts_ip_chksum_error; + rxc->pkts_udp_chksum_error = + hwstat->cap.mp_stat_structs_port_rx[p] + .pkts_udp_chksum_error; + rxc->pkts_tcp_chksum_error = + hwstat->cap.mp_stat_structs_port_rx[p] + .pkts_tcp_chksum_error; + rxc->pkts_giant_undersize = + hwstat->cap.mp_stat_structs_port_rx[p] + .pkts_giant_undersize; + rxc->pkts_baby_giant = + hwstat->cap.mp_stat_structs_port_rx[p] + .pkts_baby_giant; + rxc->pkts_not_isl_vlan_mpls = + hwstat->cap.mp_stat_structs_port_rx[p] + .pkts_not_isl_vlan_mpls; + rxc->pkts_isl = + hwstat->cap.mp_stat_structs_port_rx[p].pkts_isl; + rxc->pkts_vlan = + hwstat->cap.mp_stat_structs_port_rx[p].pkts_vlan; + rxc->pkts_isl_vlan = + hwstat->cap.mp_stat_structs_port_rx[p].pkts_isl_vlan; + rxc->pkts_mpls = + hwstat->cap.mp_stat_structs_port_rx[p].pkts_mpls; + rxc->pkts_isl_mpls = + hwstat->cap.mp_stat_structs_port_rx[p].pkts_isl_mpls; + rxc->pkts_vlan_mpls = hwstat->cap.mp_stat_structs_port_rx[p] + .pkts_vlan_mpls; + rxc->pkts_isl_vlan_mpls = + hwstat->cap.mp_stat_structs_port_rx[p] + .pkts_isl_vlan_mpls; + rxc->pkts_no_filter = hwstat->cap.mp_stat_structs_port_rx[p] + .pkts_no_filter; + rxc->pkts_dedup_drop = + hwstat->cap.mp_stat_structs_port_rx[p] + .pkts_dedup_drop; + rxc->pkts_filter_drop = + hwstat->cap.mp_stat_structs_port_rx[p] + .pkts_filter_drop; + rxc->pkts_overflow = + hwstat->cap.mp_stat_structs_port_rx[p].pkts_overflow; + rxc->pkts_dbs_drop = + hwstat->cap.mp_stat_structs_port_rx[p].pkts_dbs_drop; + rxc->octets_no_filter = + hwstat->cap.mp_stat_structs_port_rx[p] + .octets_no_filter; + rxc->octets_dedup_drop = + hwstat->cap.mp_stat_structs_port_rx[p] + .octets_dedup_drop; + rxc->octets_filter_drop = + hwstat->cap.mp_stat_structs_port_rx[p] + .octets_filter_drop; + rxc->octets_overflow = + hwstat->cap.mp_stat_structs_port_rx[p] + .octets_overflow; + rxc->octets_dbs_drop = + hwstat->cap.mp_stat_structs_port_rx[p] + .octets_dbs_drop; + rxc->ipft_first_hit = hwstat->cap.mp_stat_structs_port_rx[p] + .ipft_first_hit; + rxc->ipft_first_not_hit = + hwstat->cap.mp_stat_structs_port_rx[p] + .ipft_first_not_hit; + rxc->ipft_mid_hit = + hwstat->cap.mp_stat_structs_port_rx[p].ipft_mid_hit; + rxc->ipft_mid_not_hit = + hwstat->cap.mp_stat_structs_port_rx[p] + .ipft_mid_not_hit; + rxc->ipft_last_hit = + hwstat->cap.mp_stat_structs_port_rx[p].ipft_last_hit; + rxc->ipft_last_not_hit = + hwstat->cap.mp_stat_structs_port_rx[p] + .ipft_last_not_hit; + rxc++; + } + return nbp * NUM_STAT_RECORD_TYPE_RX_PORT_CAP + + STAT_INFO_ELEMENTS; + } +} + +static int read_tx_counters(nt4ga_stat_t *hwstat, uint64_t *val, int nbp) +{ + struct ntc_stat_get_data_s *txdata = (struct ntc_stat_get_data_s *)val; + + txdata->nb_counters = (uint64_t)nbp; + txdata->timestamp = hwstat->last_timestamp; + txdata->is_virt = hwstat->mp_nthw_stat->mb_is_vswitch; + + if (txdata->is_virt) { + struct rtx_type_fields_virt_s *txc = + (struct rtx_type_fields_virt_s *)txdata->data; + int p; + + for (p = 0; p < nbp; p++) { + txc->octets = + hwstat->virt.mp_stat_structs_port_tx[p].octets; + txc->pkts = hwstat->virt.mp_stat_structs_port_tx[p].pkts; + txc->drop_events = + hwstat->virt.mp_stat_structs_port_tx[p].drop_events; + txc->qos_drop_octets = + hwstat->virt.mp_stat_structs_port_tx[p] + .qos_drop_octets; + txc->qos_drop_pkts = hwstat->virt.mp_stat_structs_port_tx[p] + .qos_drop_pkts; + txc++; + } + return nbp * NUM_STAT_RECORD_TYPE_TX_PORT_VIRT + + STAT_INFO_ELEMENTS; + } else { + struct tx_type_fields_cap_s *txc = + (struct tx_type_fields_cap_s *)txdata->data; + int p; + + for (p = 0; p < nbp; p++) { + copy_rmon_stat(&hwstat->cap.mp_stat_structs_port_tx[p], + &txc->rmon); + txc->rmon.pkts = hwstat->a_port_tx_packets_total[p]; + txc++; + } + return nbp * NUM_STAT_RECORD_TYPE_TX_PORT_CAP + + STAT_INFO_ELEMENTS; + } +} + +static int func_get_layout_version(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr _unused, + char **data, int *len) +{ + struct stat_hdl *stat = (struct stat_hdl *)hdl; + + if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) { + *data = NULL; + *len = 0; + return REQUEST_ERR; + } + *data = malloc(sizeof(int)); + if (!*data) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "memory allocation failed"); + return REQUEST_ERR; + } + + *(int *)*data = stat->p_nt4ga_stat->mp_nthw_stat->mn_stat_layout_version; + *len = sizeof(int); + return REQUEST_OK; +} + +static int func_get_flm_layout_version(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr _unused, + char **data, int *len) +{ + struct stat_hdl *stat = (struct stat_hdl *)hdl; + + if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) { + *data = NULL; + *len = 0; + return REQUEST_ERR; + } + *data = malloc(sizeof(int)); + if (!*data) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "memory allocation failed"); + return REQUEST_ERR; + } + + *(int *)*data = (stat->p_nt4ga_stat->flm_stat_ver < 18) ? 1 : 2; + *len = sizeof(int); + return REQUEST_OK; +} + +/* + * Return total number of 64bit counters occupied by this stat type + * additionally, returns total number of records for this type (ie number of queues, ports, etc) + */ +static int get_size(struct stat_hdl *stat, enum stat_type_e type, + int *num_records) +{ + int nrec, size; + + switch (type) { + case STAT_TYPE_COLOR: + nrec = stat->p_nt4ga_stat->mp_nthw_stat->m_nb_color_counters / 2; + size = nrec * NUM_STAT_RECORD_TYPE_COLOR; + break; + case STAT_TYPE_QUEUE: + nrec = stat->p_nt4ga_stat->mp_nthw_stat->m_nb_rx_host_buffers; + size = nrec * NUM_STAT_RECORD_TYPE_QUEUE; + break; + case STAT_TYPE_RX: + nrec = stat->p_nt4ga_stat->mn_rx_ports; + size = nrec * ((stat->p_nt4ga_stat->mp_nthw_stat->mb_is_vswitch) ? + NUM_STAT_RECORD_TYPE_RX_PORT_VIRT : + NUM_STAT_RECORD_TYPE_RX_PORT_CAP); + break; + case STAT_TYPE_TX: + nrec = stat->p_nt4ga_stat->mn_tx_ports; + size = nrec * ((stat->p_nt4ga_stat->mp_nthw_stat->mb_is_vswitch) ? + NUM_STAT_RECORD_TYPE_TX_PORT_VIRT : + NUM_STAT_RECORD_TYPE_TX_PORT_CAP); + break; + case STAT_TYPE_FLOWMATCHER: + nrec = 1; + size = nrec * NUM_STAT_RECORD_TYPE_FLOWMATCHER; + break; + } + + *num_records = nrec; + return size + STAT_INFO_ELEMENTS; +} + +static int do_get_stats(struct stat_hdl *stat, char **data, int *len, + enum stat_type_e stype, + int (*read_counters)(nt4ga_stat_t *, uint64_t *, int)) +{ + int nbg; + int size = get_size(stat, stype, &nbg); + + size *= sizeof(uint64_t); + uint64_t *val = (uint64_t *)malloc(size); + + if (!val) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "memory allocation failed"); + return REQUEST_ERR; + } + + pthread_mutex_lock(&stat->drv->ntdrv.stat_lck); + read_counters(stat->p_nt4ga_stat, val, nbg); + pthread_mutex_unlock(&stat->drv->ntdrv.stat_lck); + + *data = (char *)val; + *len = size; + return REQUEST_OK; +} + +/* + * Stat Request functions + */ +static int func_get_flm(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr _unused, char **data, + int *len) +{ + struct stat_hdl *stat = (struct stat_hdl *)hdl; + + if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) { + *data = NULL; + *len = 0; + return REQUEST_ERR; + } + return do_get_stats(stat, data, len, STAT_TYPE_FLOWMATCHER, read_flm); +} + +static int func_get_color(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr _unused, char **data, + int *len) +{ + struct stat_hdl *stat = (struct stat_hdl *)hdl; + + if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) { + *data = NULL; + *len = 0; + return REQUEST_ERR; + } + return do_get_stats(stat, data, len, STAT_TYPE_COLOR, read_colors); +} + +static int func_get_queue(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr _unused, char **data, + int *len) +{ + struct stat_hdl *stat = (struct stat_hdl *)hdl; + + if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) { + *data = NULL; + *len = 0; + return REQUEST_ERR; + } + return do_get_stats(stat, data, len, STAT_TYPE_QUEUE, read_queues); +} + +static int func_get_rx_counters(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr _unused, + char **data, int *len) +{ + struct stat_hdl *stat = (struct stat_hdl *)hdl; + + if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) { + *data = NULL; + *len = 0; + return REQUEST_ERR; + } + return do_get_stats(stat, data, len, STAT_TYPE_RX, read_rx_counters); +} + +static int func_get_tx_counters(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr _unused, + char **data, int *len) +{ + struct stat_hdl *stat = (struct stat_hdl *)hdl; + + if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) { + *data = NULL; + *len = 0; + return REQUEST_ERR; + } + return do_get_stats(stat, data, len, STAT_TYPE_TX, read_tx_counters); +} + +/* + * Snapshot handling. This is to ensure atomic reading of all statistics in one collection + */ + +static struct snaps_s *find_client_snap_data(struct stat_hdl *stat, + int client_id, + struct snaps_s **parent) +{ + struct snaps_s *snaps = stat->snaps_base; + + if (parent) + *parent = NULL; + while (snaps && snaps->client_id != client_id) { + if (parent) + *parent = snaps; + snaps = snaps->next; + } + + return snaps; +} + +static struct snaps_s *get_client_snap_data(struct stat_hdl *stat, + int client_id) +{ + struct snaps_s *snaps = find_client_snap_data(stat, client_id, NULL); + + if (!snaps) { + snaps = malloc(sizeof(struct snaps_s)); /* return NULL on malloc failure */ + if (snaps) { + snaps->client_id = client_id; + snaps->next = stat->snaps_base; + stat->snaps_base = snaps; + snaps->buffer = NULL; + } + } + return snaps; +} + +static int func_snapshot(void *hdl, int client_id, + struct ntconn_header_s *hdr _unused, char **data, + int *len) +{ + struct stat_hdl *stat = (struct stat_hdl *)hdl; + int nbc, nbq, nbpr, nbpt; + struct snaps_s *snaps; + + if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) { + *data = NULL; + *len = 0; + return REQUEST_ERR; + } + snaps = get_client_snap_data(stat, client_id); + if (!snaps) + goto err_out; + + if (snaps->buffer) + free(snaps->buffer); + + snaps->snap_addr[SNAP_COLORS].size = + (unsigned int)get_size(stat, STAT_TYPE_COLOR, &nbc); + snaps->snap_addr[SNAP_QUEUES].size = + (unsigned int)get_size(stat, STAT_TYPE_QUEUE, &nbq); + snaps->snap_addr[SNAP_RX_PORT].size = + (unsigned int)get_size(stat, STAT_TYPE_RX, &nbpr); + snaps->snap_addr[SNAP_TX_PORT].size = + (unsigned int)get_size(stat, STAT_TYPE_TX, &nbpt); + + unsigned int tot_size = snaps->snap_addr[SNAP_COLORS].size + + snaps->snap_addr[SNAP_QUEUES].size + + snaps->snap_addr[SNAP_RX_PORT].size + + snaps->snap_addr[SNAP_TX_PORT].size; + + snaps->buffer = malloc(tot_size * sizeof(uint64_t)); + if (!snaps->buffer) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "memory allocation failed"); + return REQUEST_ERR; + } + uint64_t *val = snaps->buffer; + + snaps->snap_addr[SNAP_COLORS].ptr = val; + pthread_mutex_lock(&stat->drv->ntdrv.stat_lck); + unsigned int size = read_colors(stat->p_nt4ga_stat, val, nbc); + + if (size != snaps->snap_addr[SNAP_COLORS].size) { + NT_LOG(ERR, NTCONNECT, "stat.snapshot: color size mismatch"); + goto err_out; + } + + val += size; + snaps->snap_addr[SNAP_QUEUES].ptr = val; + size = read_queues(stat->p_nt4ga_stat, val, nbq); + if (size != snaps->snap_addr[SNAP_QUEUES].size) { + NT_LOG(ERR, NTCONNECT, + "stat.snapshot: queue statistic size mismatch"); + goto err_out; + } + + val += size; + snaps->snap_addr[SNAP_RX_PORT].ptr = val; + size = read_rx_counters(stat->p_nt4ga_stat, val, nbpr); + if (size != snaps->snap_addr[SNAP_RX_PORT].size) { + NT_LOG(ERR, NTCONNECT, + "stat.snapshot: Rx port statistic size mismatch %i, %i", + size, snaps->snap_addr[SNAP_RX_PORT].size); + goto err_out; + } + + val += size; + snaps->snap_addr[SNAP_TX_PORT].ptr = val; + size = read_tx_counters(stat->p_nt4ga_stat, val, nbpt); + if (size != snaps->snap_addr[SNAP_TX_PORT].size) { + NT_LOG(ERR, NTCONNECT, + "stat.snapshot: Tx port statistic size mismatch"); + goto err_out; + } + + pthread_mutex_unlock(&stat->drv->ntdrv.stat_lck); + + *data = NULL; + *len = 0; + return REQUEST_OK; + +err_out: + pthread_mutex_unlock(&stat->drv->ntdrv.stat_lck); + return ntconn_error(data, len, "stat", + NTCONN_ERR_CODE_INTERNAL_REPLY_ERROR); +} + +static int get_snap_data(void *hdl, int client_id, char **data, int *len, + enum snap_addr_select_e snap_addr_idx) +{ + struct stat_hdl *stat = (struct stat_hdl *)hdl; + struct snaps_s *snaps = find_client_snap_data(stat, client_id, NULL); + + if (!snaps || !snaps->buffer) + return ntconn_error(data, len, "stat", NTCONN_ERR_CODE_NO_DATA); + + int ln = snaps->snap_addr[snap_addr_idx].size * sizeof(uint64_t); + + *data = malloc(ln); + if (!data) { + *len = 0; + NT_LOG(ERR, NTCONNECT, "memory allocation failed"); + return REQUEST_ERR; + } + memcpy(*data, snaps->snap_addr[snap_addr_idx].ptr, ln); + *len = ln; + + return REQUEST_OK; +} + +static int func_get_snap_colors(void *hdl, int client_id, + struct ntconn_header_s *hdr _unused, + char **data, int *len) +{ + return get_snap_data(hdl, client_id, data, len, SNAP_COLORS); +} + +static int func_get_snap_queues(void *hdl, int client_id, + struct ntconn_header_s *hdr _unused, + char **data, int *len) +{ + return get_snap_data(hdl, client_id, data, len, SNAP_QUEUES); +} + +static int func_get_snap_rx_port(void *hdl, int client_id, + struct ntconn_header_s *hdr _unused, + char **data, int *len) +{ + return get_snap_data(hdl, client_id, data, len, SNAP_RX_PORT); +} + +static int func_get_snap_tx_port(void *hdl, int client_id, + struct ntconn_header_s *hdr _unused, + char **data, int *len) +{ + return get_snap_data(hdl, client_id, data, len, SNAP_TX_PORT); +} + +/* + * Stat main request function + */ +static int stat_request(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr, char *function, + char **data, int *len) +{ + return execute_function(this_module_name, hdl, client_id, hdr, function, + stat_entry_funcs, data, len, 0); +} + +static void stat_free_data(void *hdl _unused, char *data) +{ + free(data); +} + +static void stat_client_cleanup(void *hdl, int client_id) +{ + struct stat_hdl *stat = (struct stat_hdl *)hdl; + struct snaps_s *snaps_parent; + struct snaps_s *snaps = + find_client_snap_data(stat, client_id, &snaps_parent); + + if (!snaps) + return; + + if (snaps_parent) + snaps_parent->next = snaps->next; + else + stat->snaps_base = snaps->next; + + if (snaps->buffer) + free(snaps->buffer); + free(snaps); +} + +static const ntconnapi_t ntconn_stat_op = { + this_module_name, STAT_VERSION_MAJOR, STAT_VERSION_MINOR, + stat_request, stat_free_data, stat_client_cleanup +}; + +int ntconn_stat_register(struct drv_s *drv) +{ + stat_hdl.drv = drv; + stat_hdl.p_nt4ga_stat = &drv->ntdrv.adapter_info.nt4ga_stat; + + /* Check supported Layout_versions by this module */ + size_t i; + + for (i = 0; i < NUM_LAYOUT_VERSIONS_SUPPORTED; i++) { + if (stat_hdl.p_nt4ga_stat->mp_nthw_stat->mn_stat_layout_version == + layout_versions_supported[i]) + break; + } + + if (i == NUM_LAYOUT_VERSIONS_SUPPORTED) { + NT_LOG(ERR, NTCONNECT, + "stat: layout version %i is not supported. Module will not be activated", + stat_hdl.p_nt4ga_stat->mp_nthw_stat->mn_stat_layout_version); + return -1; + } + + return register_ntconn_mod(&drv->p_dev->addr, (void *)&stat_hdl, + &ntconn_stat_op); +} diff --git a/drivers/net/ntnic/ntconnect_modules/ntconn_test.c b/drivers/net/ntnic/ntconnect_modules/ntconn_test.c new file mode 100644 index 0000000000..907ea4ff5f --- /dev/null +++ b/drivers/net/ntnic/ntconnect_modules/ntconn_test.c @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include +#include "ntnic_ethdev.h" +#include "ntconnect.h" +#include "ntos_system.h" +#include "ntconn_modules.h" +#include "ntconn_mod_helper.h" +#include "nt_util.h" +#include "ntlog.h" +#include "ntnic_vf_vdpa.h" + +#include "ntconnect_api_test.h" + +#define NTCONN_TEST_VERSION_MAJOR 0U +#define NTCONN_TEST_VERSION_MINOR 1U + +#define this_module_name "ntconnect_test" + +#define MAX_CLIENTS 32 + +#define UNUSED __rte_unused + +static struct test_hdl_s { + struct drv_s *drv; +} test_hdl[MAX_CLIENTS]; + +/* + * Test functions + */ +static int func_test(void *hdl, int client_id, struct ntconn_header_s *hdr, + char **data, int *len); +static struct func_s adapter_entry_funcs[] = { + { "test", NULL, func_test }, + { NULL, NULL, NULL }, +}; + +static int func_test(void *hdl _unused, int client_id _unused, + struct ntconn_header_s *hdr, char **data, int *len) +{ + int status = 0; + int number = 0; + uint32_t size; + struct test_s *test_cpy = (struct test_s *)&(*data)[hdr->len]; + + if (hdr->blob_len < sizeof(struct test_s)) { + NT_LOG(ERR, NTCONNECT, "Error in test data: to small"); + status = -1; + goto TEST_ERROR; + } + + number = test_cpy->number; + size = sizeof(struct test_s) + sizeof(uint64_t) * number; + + if (hdr->blob_len != size) { + NT_LOG(ERR, NTCONNECT, "Error in test data: wrong size"); + status = -1; + goto TEST_ERROR; + } + + { + *data = malloc(sizeof(struct test_s) + + number * sizeof(uint64_t)); + if (!*data) + goto TEST_ERROR_MALLOC; + struct test_s *return_value = (struct test_s *)*data; + *len = sizeof(struct test_s) + number * sizeof(uint64_t); + for (int i = 0; i < number; i++) + return_value->test[i] = test_cpy->test[i]; + return_value->status = 0; + return_value->number = number; + return REQUEST_OK; + } + +TEST_ERROR: + + { + *data = malloc(sizeof(struct test_s)); + if (!*data) + goto TEST_ERROR_MALLOC; + struct test_s *return_value = (struct test_s *)*data; + *len = sizeof(struct test_s); + return_value->status = status; + return_value->number = 0; + return REQUEST_OK; + } + +TEST_ERROR_MALLOC: + + *len = 0; + NT_LOG(ERR, NTCONNECT, "Not able to allocate memory %s", __func__); + return REQUEST_ERR; +} + +enum { + FLOW_API_FUNC_CREATE, + FLOW_API_FUNC_VALIDATE, +}; + +static int test_request(void *hdl, int client_id _unused, + struct ntconn_header_s *hdr, char *function, + char **data, int *len) +{ + return execute_function(this_module_name, hdl, client_id, hdr, function, + adapter_entry_funcs, data, len, 0); +} + +static void test_free_data(void *hdl _unused, char *data) +{ + if (data) + free(data); +} + +static void test_client_cleanup(void *hdl _unused, int client_id _unused) +{ + /* Nothing to do */ +} + +static const ntconnapi_t ntconn_test_op = { this_module_name, + NTCONN_TEST_VERSION_MAJOR, + NTCONN_TEST_VERSION_MINOR, + test_request, + test_free_data, + test_client_cleanup + }; + +int ntconn_test_register(struct drv_s *drv) +{ + int i; + + for (i = 0; i < MAX_CLIENTS; i++) { + if (test_hdl[i].drv == NULL) + break; + } + if (i == MAX_CLIENTS) { + NT_LOG(ERR, NTCONNECT, + "Cannot register more adapters into NtConnect framework"); + return -1; + } + + test_hdl[i].drv = drv; + return register_ntconn_mod(&drv->p_dev->addr, (void *)&test_hdl[i], + &ntconn_test_op); +}