From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id B2B7A45509; Thu, 27 Jun 2024 09:41:53 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 0FB1640BA0; Thu, 27 Jun 2024 09:39:57 +0200 (CEST) Received: from egress-ip42b.ess.de.barracuda.com (egress-ip42b.ess.de.barracuda.com [18.185.115.246]) by mails.dpdk.org (Postfix) with ESMTP id C7CA340E2E for ; Thu, 27 Jun 2024 09:39:47 +0200 (CEST) Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05lp2112.outbound.protection.outlook.com [104.47.18.112]) by mx-outbound22-108.eu-central-1b.ess.aws.cudaops.com (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 27 Jun 2024 07:39:46 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ZnI7JvwPN2S+KTJAoxKMfFDBSrMFTiX11tNsKShWfg0SGAbu8HPbJ+Z9mBDeif+RgqIZHeJn4mEiG95Z3FAZjYzr/sSV+3k998q0up38tvP+TskT+KJnaKcdtDg8nteurXrAV3XPIGESV9AmzYFoA5pivgt85htghm2W96U2JyAHA1uVsnLnNq6Cf0xoqBES/ZvvoWMYpeqMYqw61tR3pBA5Ok2GTJYuOtO71CkBADnMPB032oqsSqJD/axk7xLXH+g1oNVd2QwrVG9mpP1edLAB9+qr0J6j7MpX6qQ9XifePCHfezoz8xfXUTeIEMvRNqLWGUv41VfyeDq+y1ffVQ== 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=p5GBfmRxMlHFxyBInHculfiy+BtWn/4FoI6NHNMbsZQ=; b=dVjgxlKThHlS9Czar6dv5iT6kWWYJNBWxzGW1xfrWq5ySXece1K/iuzmCX71Bn0tQAMxCEo6OR78T03+2GdldSmvyOvaD2LquCHTxpGf3dHuRNW3/uODjaZ1jbMNMWWfv+2lzvzA19C1kPJbvdY4IT+FYV00KAdkQ/RIvz/LKCngW9GuBbnwYyAnD6hZKM5myi2KsNEJZWYK4dE5D/ZkXQnwYX941uOLd2gCfR0GUoc13DzLcdVkV793nkMYTGA1bdbWuh1QehVUYIBoYBdA0w1bIVvYzQOXlED4hepfKaGRp3UWqMFeoTYJraF/WzUhzGUOwgapsyEmK7Zxbu70zg== 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=reject sp=reject pct=100) action=oreject header.from=napatech.com; dkim=none (message not signed); arc=none (0) 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=p5GBfmRxMlHFxyBInHculfiy+BtWn/4FoI6NHNMbsZQ=; b=IQI2IaL9KQrhwt5bj4V2o/2YCt3cfgyy2BrowrsUVdLykNCoEAFkFui6ex6PQIZbqM471h3WIisXOpbBSSNOwpgtXogRa0o0TWtuMkE/h5Vg8gOHvu7reGw18Tup94M5o3kzWUavsnlrYTY+nr1aqbDE7w/K10Fg3O1c8AkmR9k= Received: from DUZPR01CA0331.eurprd01.prod.exchangelabs.com (2603:10a6:10:4b8::24) by AM7P190MB0680.EURP190.PROD.OUTLOOK.COM (2603:10a6:20b:120::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.32; Thu, 27 Jun 2024 07:39:44 +0000 Received: from DB1PEPF000509E2.eurprd03.prod.outlook.com (2603:10a6:10:4b8:cafe::38) by DUZPR01CA0331.outlook.office365.com (2603:10a6:10:4b8::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7719.25 via Frontend Transport; Thu, 27 Jun 2024 07:39:44 +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=oreject 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; Received: from localhost.localdomain (178.72.21.4) by DB1PEPF000509E2.mail.protection.outlook.com (10.167.242.52) with Microsoft SMTP Server id 15.20.7677.15 via Frontend Transport; Thu, 27 Jun 2024 07:39:44 +0000 From: Serhii Iliushyk To: dev@dpdk.org Cc: mko-plv@napatech.com, sil-plv@napatech.com, ckm@napatech.com, andrew.rybchenko@oktetlabs.ru, ferruh.yigit@amd.com Subject: [PATCH v5 19/23] net/ntnic: add QSFP support Date: Thu, 27 Jun 2024 09:39:00 +0200 Message-ID: <20240627073918.2039719-19-sil-plv@napatech.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240627073918.2039719-1-sil-plv@napatech.com> References: <20240530144929.4127931-1-sil-plv@napatech.com> <20240627073918.2039719-1-sil-plv@napatech.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DB1PEPF000509E2:EE_|AM7P190MB0680:EE_ Content-Type: text/plain X-MS-Office365-Filtering-Correlation-Id: 80ec8fa9-0ce7-499d-2f1a-08dc967c501d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|1800799024|82310400026|376014|36860700013; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?v7zinwNTbA1mR8vBQBBLMWDWJNv0Ew1ICfUaUOGNF0LpHYFPJW2XjHkkc/cV?= =?us-ascii?Q?eQ6UC5ZOqqDdgpn2ftQP5fDQe1/MSDZ+u6qrQQVzMK+AJzso8MNOQSs+PnNS?= =?us-ascii?Q?k5ECksPN7PnaYG2mSsIXw+JDtLd4JrkwsSAP61dH9Ssy3TsZLgk3vetvBsR4?= =?us-ascii?Q?AoaHebDNMDbgikyiNS0HjA9ltmc5OEW43MhrdnRMJfliu5HHNpA+gqFRs8Bs?= =?us-ascii?Q?P/HcTwf9/5xSZBx4WdiAK0JKqGzALvr8lhzzSg8l1Obs0EH6hmSQGVM9Uqq5?= =?us-ascii?Q?6E0pATDs6Qi88IpXtqlZR7kkzPFvnVpLJu+fzSDFDgQ/R0Uv3WrsFPpJjCFe?= =?us-ascii?Q?FmqP+Uc+BD2tHSnd+20ZHTMasgGrMEK8PcNS5BHxawInZoaIhejNXg0TB+7f?= =?us-ascii?Q?IDUCZexR1PRM0MQcjMZYf/O05dhATw4x+QUk8Gmlgw4SpALahAepiZD9v6oP?= =?us-ascii?Q?pLLJXt6ZvOgi8J8YyTleFlUvrx2pcmR09qLH5ct/Q+aNQDd/z4JjGcgzHKvM?= =?us-ascii?Q?c83oaF0/yQpygVxaPVSl6DOa7vpDfS079k5uTrZn+Ww9/oJrPmCsktnOs2xm?= =?us-ascii?Q?bWYs2OWAmoYE1BrSDBNX93elDtJiqb8EoJfeAnx5DLm/30v8ME/9eJqro97r?= =?us-ascii?Q?kpiwtftaNhxN+41RJb3rNmeP/RZWDyaehfOqbwgm7PL71GH7rnzE1JmIJ71q?= =?us-ascii?Q?s6vTvBBrpNdmwlQfYcHB1oxei9eYBlZYC3ukuXRUnqtlQFCgQc6ah11lYRM9?= =?us-ascii?Q?++/+A8WeIdZ9CvW7382CaMyH+NclaOmhvLd0mmMAqu4GZ2oPybkH2ZbloMTn?= =?us-ascii?Q?egEF2quEOnnA6msw6GMCGSpqmVxSFRMNg4dInZvJ28K7DiOU/4Por92eBznD?= =?us-ascii?Q?fM8VXOQDZaE/WWvotv2SZyqkCFNbEt3WzT74Ffo2gAhd1MEfmXkNfMvh8edO?= =?us-ascii?Q?Wrsw4KYkm1042scQHPPM2IjeAya0LLlbEsqi5Xb4no5YVjJsIjw+hOB3u+NM?= =?us-ascii?Q?QEIfgrfjSNFTQd90J/n/VQ0dGpCFfgzs6uksYiMPIpQTavAUpItLTkdxGZ1+?= =?us-ascii?Q?BhrQOMb9HJaV1pYoGN/DuVn072pGrSp7RR/HV9ya2WUnVylhss2k7CoBl5Fx?= =?us-ascii?Q?lLxFcIp2CnXppFVRil7DUo0lExlk1nsFrJFlPdiDVWkMc72lQA2ii8hluUyd?= =?us-ascii?Q?RkJYbNDpdAtg4wR2pjjESQgnZ81Uxe/PSNlNwztpzbK9IwPvC07cwikdVkz3?= =?us-ascii?Q?HnJcIjm9+A9DwzA5lFWD16HgWzlbBkdy097tzODBRUkIX77lqmiqbngoFpjs?= =?us-ascii?Q?nOeWsIehDhTTKkmTwqx+kx1GG5aIsBC6sTY4Wg/Wd4eZEVP1vkqWry5IF53w?= =?us-ascii?Q?GHpvI6ABO0uc6J3CEBl3pogm7B7dReWJvbsbwX+OamrmfW9M5IC9hwqIMBf4?= =?us-ascii?Q?S9MKEjsudhA9Z/Tqzk6hMYLzwc2E8De0?= X-Forefront-Antispam-Report: CIP:178.72.21.4; CTRY:DK; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:localhost.localdomain; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(1800799024)(82310400026)(376014)(36860700013); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: zHkTOyr77wGQGxcgSxZ2DH1V6NJTSjLRnxTSWT7U8nZ4KgHY55TXMg5FjAccUfeTEiLT09WRkuNpJz8HlzgSY1ywaIrVL7JR7hK+S4u68ywVEivkxm5J06CUNAVuyn7FjgMvqW42CfBwXhrxuquCSs07JlwQvhcOxuKYY9WS/7Vstom4ar4uVYMGs5pAGQl7lwmm3MpbOW+JxOfIaAOeqP9gwdcGYc68vYBrGBXtiC7MPVh8MK9acz26juMCITi018VPZ0ynTNJKqhcOYx94urlalUMYHTz2tav3Lf71a6X45vfEGrLf04U2m5z9wrN40iAsvnkF9c5bT05hf/+YhzTmYz9ihifOcUqOodcCLB72/tG5WhX/TVLCSdsRdyuV6N92cbfvMHMa4lhOy16R8njrDjuWOBl678PWSc4m+HmXrzILZMBbI3HrlQwkS3XMINW/OVZ6a2QfQYB4iM5beEhNwB8J/GvagPIfXvAJ+9OIaKNxOBtRM7u2x+7EmPplNP2r73ZGbc8YL/+JY+0ossH3kAkILE2ZM4R010SAurzrkcO4bGWxutx7xjrJ+GmitA3BAmnUIYaDIL14vANrVRaJpbC+Eeq0x7mbn7adPwzDFqf8O+D0tBNNMgNk9PCArfGEa8Iv5zsdd+Iqin2gqw== X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jun 2024 07:39:44.1156 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 80ec8fa9-0ce7-499d-2f1a-08dc967c501d 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] X-MS-Exchange-CrossTenant-AuthSource: DB1PEPF000509E2.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM7P190MB0680 X-BESS-ID: 1719473986-305740-12659-2633-1 X-BESS-VER: 2019.1_20240620.2317 X-BESS-Apparent-Source-IP: 104.47.18.112 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKVoZmhgaGQGYGUDQlxdDYzMTCMN E8LcUgLTkp0STJ3DzZOCUx1dLQzCLRQqk2FgBdoNAkQgAAAA== X-BESS-Outbound-Spam-Score: 0.50 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.257231 [from cloudscan22-230.eu-central-1b.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 Includes support for QSFP and QSFP+. Signed-off-by: Serhii Iliushyk --- drivers/net/ntnic/include/ntnic_nim.h | 10 + .../link_mgmt/link_100g/nt4ga_link_100g.c | 12 +- drivers/net/ntnic/nim/i2c_nim.c | 310 +++++++++++++++++- drivers/net/ntnic/nim/i2c_nim.h | 14 +- drivers/net/ntnic/nim/nim_defines.h | 3 + drivers/net/ntnic/nim/qsfp_registers.h | 43 +++ 6 files changed, 389 insertions(+), 3 deletions(-) create mode 100644 drivers/net/ntnic/nim/qsfp_registers.h diff --git a/drivers/net/ntnic/include/ntnic_nim.h b/drivers/net/ntnic/include/ntnic_nim.h index 263875a857..300842b570 100644 --- a/drivers/net/ntnic/include/ntnic_nim.h +++ b/drivers/net/ntnic/include/ntnic_nim.h @@ -15,6 +15,8 @@ typedef enum i2c_type { 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_QSFP_PLUS_NOT_PRESENT, /* QSFP type but slot is empty */ + NT_PORT_TYPE_QSFP_PLUS, /* QSFP type */ }; typedef enum nt_port_type_e nt_port_type_t, *nt_port_type_p; @@ -51,6 +53,14 @@ typedef struct nim_i2c_ctx { bool tx_disable; bool dmi_supp; + union { + struct { + bool rx_only; + union { + } specific_u; + } qsfp; + + } specific_u; } nim_i2c_ctx_t, *nim_i2c_ctx_p; struct nim_sensor_group { diff --git a/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c b/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c index 4c159431e1..1f4ed62498 100644 --- a/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c +++ b/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c @@ -18,6 +18,7 @@ static int _create_nim(adapter_info_t *drv, int port) int res = 0; const uint8_t valid_nim_id = 17U; nim_i2c_ctx_t *nim_ctx; + sfp_nim_state_t nim; nt4ga_link_t *link_info = &drv->nt4ga_link; assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX); @@ -31,11 +32,20 @@ static int _create_nim(adapter_info_t *drv, int port) */ nt_os_wait_usec(1000000); /* pause 1.0s */ - res = construct_and_preinit_nim(nim_ctx); + res = construct_and_preinit_nim(nim_ctx, NULL); 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? */ diff --git a/drivers/net/ntnic/nim/i2c_nim.c b/drivers/net/ntnic/nim/i2c_nim.c index 2918eda072..4831078a2c 100644 --- a/drivers/net/ntnic/nim/i2c_nim.c +++ b/drivers/net/ntnic/nim/i2c_nim.c @@ -10,6 +10,7 @@ #include "ntlog.h" #include "nt_util.h" #include "ntnic_mod_reg.h" +#include "qsfp_registers.h" #include "nim_defines.h" #define NIM_READ false @@ -17,6 +18,25 @@ #define NIM_PAGE_SEL_REGISTER 127 #define NIM_I2C_0XA0 0xA0 /* Basic I2C address */ + +static bool page_addressing(nt_nim_identifier_t id) +{ + switch (id) { + case NT_NIM_QSFP: + case NT_NIM_QSFP_PLUS: + return true; + + default: + NT_LOG(DBG, NTNIC, "Unknown NIM identifier %d\n", id); + return false; + } +} + +static 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 a_reg_addr, uint8_t seq_cnt, uint8_t *p_data) @@ -158,6 +178,13 @@ static int nim_read_write_data_lin(nim_i2c_ctx_p ctx, bool m_page_addressing, ui return 0; } +static int read_data_lin(nim_i2c_ctx_p ctx, uint16_t lin_addr, uint16_t length, void *data) +{ + /* Wrapper for using Mutex for QSFP TODO */ + return nim_read_write_data_lin(ctx, page_addressing(ctx->nim_id), lin_addr, length, data, + NIM_READ); +} + 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. */ @@ -205,20 +232,301 @@ static int i2c_nim_common_construct(nim_i2c_ctx_p ctx) 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 max_len that includes a terminating "0" */ + + if (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; +} + +static void qsfp_read_vendor_info(nim_i2c_ctx_t *ctx) +{ + nim_read_vendor_info(ctx, QSFP_VENDOR_NAME_LIN_ADDR, sizeof(ctx->vendor_name), + ctx->vendor_name); + nim_read_vendor_info(ctx, QSFP_VENDOR_PN_LIN_ADDR, sizeof(ctx->prod_no), ctx->prod_no); + nim_read_vendor_info(ctx, QSFP_VENDOR_SN_LIN_ADDR, sizeof(ctx->serial_no), ctx->serial_no); + nim_read_vendor_info(ctx, QSFP_VENDOR_DATE_LIN_ADDR, sizeof(ctx->date), ctx->date); + nim_read_vendor_info(ctx, QSFP_VENDOR_REV_LIN_ADDR, (uint8_t)(sizeof(ctx->rev) - 2), + ctx->rev); /*OBS Only two bytes*/ +} +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; + + default: + NT_LOG(INF, NIM, "nim_id = %u is not an QSFP/QSFP+ module\n", ctx->nim_id); + res = -1; + } + + return res; +} + +int nim_state_build(nim_i2c_ctx_t *ctx, sfp_nim_state_t *state) +{ + 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 0x0C: + return "QSFP"; + + case 0x0D: + return "QSFP+"; + default: return "ILLEGAL!"; } } -int construct_and_preinit_nim(nim_i2c_ctx_p ctx) +/* + * 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_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_read_write_data_lin(ctx, pg_addr, QSFP_CONTROL_STATUS_LIN_ADDR, sizeof(value), + &value, NIM_WRITE) != 0) { + return -1; + } + + 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] = { "No", "Yes" }; + (void)yes_no; + NT_LOG(DBG, NTNIC, "Instance %d: NIM id: %s (%d)\n", ctx->instance, + nim_id_to_text(ctx->nim_id), ctx->nim_id); + + /* Read DMI options */ + if (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, NTNIC, "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_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_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; +} + +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 */ + 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 */ + 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 void qsfpplus_construct(nim_i2c_ctx_p ctx, int8_t lane_idx) +{ + assert(lane_idx < 4); + 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); + + /* + * 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; +} + +int construct_and_preinit_nim(nim_i2c_ctx_p ctx, void *extra) { int res = i2c_nim_common_construct(ctx); + switch (translate_nimid(ctx)) { + case NT_NIM_QSFP_PLUS: + qsfpplus_preinit(ctx, extra ? *(int8_t *)extra : (int8_t)-1); + 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 index e89ae47835..edb6dcf1b6 100644 --- a/drivers/net/ntnic/nim/i2c_nim.h +++ b/drivers/net/ntnic/nim/i2c_nim.h @@ -8,17 +8,29 @@ #include "ntnic_nim.h" +typedef struct sfp_nim_state { + uint8_t br; /* bit rate, units of 100 MBits/sec */ +} sfp_nim_state_t, *sfp_nim_state_p; + +/* + * 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_qsfp_plus_nim_set_tx_laser_disable(nim_i2c_ctx_t *ctx, bool disable, int lane_idx); + /* * 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); +int construct_and_preinit_nim(nim_i2c_ctx_p ctx, void *extra); #endif /* I2C_NIM_H_ */ diff --git a/drivers/net/ntnic/nim/nim_defines.h b/drivers/net/ntnic/nim/nim_defines.h index 9ba861bb4f..e5a033a3d4 100644 --- a/drivers/net/ntnic/nim/nim_defines.h +++ b/drivers/net/ntnic/nim/nim_defines.h @@ -7,6 +7,7 @@ #define NIM_DEFINES_H_ #define NIM_IDENTIFIER_ADDR 0 /* 1 byte */ +#define QSFP_EXTENDED_IDENTIFIER 129 /* I2C addresses */ #define NIM_I2C_0XA0 0xA0 /* Basic I2C address */ @@ -23,6 +24,8 @@ typedef enum { enum nt_nim_identifier_e { NT_NIM_UNKNOWN = 0x00, /* Nim type is unknown */ + NT_NIM_QSFP = 0x0C, /* Nim type = QSFP */ + NT_NIM_QSFP_PLUS = 0x0D,/* Nim type = QSFP+ */ }; typedef enum nt_nim_identifier_e nt_nim_identifier_t; diff --git a/drivers/net/ntnic/nim/qsfp_registers.h b/drivers/net/ntnic/nim/qsfp_registers.h new file mode 100644 index 0000000000..13172ce30b --- /dev/null +++ b/drivers/net/ntnic/nim/qsfp_registers.h @@ -0,0 +1,43 @@ +/* + * 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_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) + + +#endif /* _QSFP_REGISTERS_H */ -- 2.45.0