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 8231545628; Tue, 16 Jul 2024 14:04:36 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 88A664337A; Tue, 16 Jul 2024 14:02:48 +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 2392043328 for ; Tue, 16 Jul 2024 14:02:39 +0200 (CEST) Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05lp2169.outbound.protection.outlook.com [104.47.17.169]) by mx-outbound21-91.eu-central-1b.ess.aws.cudaops.com (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Tue, 16 Jul 2024 12:02:37 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ZKEJBzYq6jDsSVqUfHRVl49ECug1BxhmSMwH7YoxNhzTXP7zFZLur6oE0FoWFzgaXMYlZelKMzsf+RKUFZCBFyVOrsCiIXi6s7QeY5Zc/IWwvdpwzEME6JpVR3gPGf4yDb1LGhWJ9emZbg9EvQXkqsFEhiuiE3lbhEm+rPr63GqDVOtuqUEdTrzKOUgZK0nbYenDTBoG0PeqBMaF1xqHkoRwC3Sovxry0xsFttyj0gPJwaLmz5/L2Fh1g/R9N6Q9WSTtQAnEoRtAhzrbchQdRetGsTn3aUAeTFsyD/aflhWays1ibeLJHX2MUTKYx/OCjc12xslIFMKQEiEQi8clxg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=6VxLuKiShgCxnLQokfNPAE61MXrYyEUAn03vxmmHUHc=; b=qJtuspoS3kYYjEgs7Mz+PreanxJOYhC5oseykoFb04apqBrOLf+5dQVlrdZ3UyV9VN9tPLW4WCwo+JXxP2ROcRlEyUdZsrXx/b4o1CoC+4D9PgTl9paSU/YBInakkR7KOLsbvwx474WhZuOE4Xz5cjAmOa+M89bFzAF9TRBeew9JbcInw0jJnOEy9X9fphmH38Crq2aKzqsqRYcXE3BZZt7M54zl3WoBk6Z5VZLfTjxWlKrzDnolP+zvJiSN7ihdwHhWWqqcbLsEMzWVD4l1g9MxwO/Qy8AN7WP9rWKeSv+2gl2JzX/PVenqaZrHzFm2nbHB538bFkn7eit4xegFgw== 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=6VxLuKiShgCxnLQokfNPAE61MXrYyEUAn03vxmmHUHc=; b=RIrUIuT+6G5+iVZYj8Q7JhRPGkHvs/X30RRxQBy/IjYAFeipEzUHGh7EoOdyGFhvLd6Z0ZNpciJR90+IaJDKx20KbG+9bAlWno/xmqh2prUPZrLaisj6zIfZHp/f3lhAY5Kc1I+3WpZ6thvnlXGVyXm4U4B1CBb43/24VhKHSB0= Received: from DU7P195CA0027.EURP195.PROD.OUTLOOK.COM (2603:10a6:10:54d::20) 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.7784.14; Tue, 16 Jul 2024 12:02:35 +0000 Received: from DU6PEPF0000A7DD.eurprd02.prod.outlook.com (2603:10a6:10:54d:cafe::82) by DU7P195CA0027.outlook.office365.com (2603:10a6:10:54d::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7762.29 via Frontend Transport; Tue, 16 Jul 2024 12:02:35 +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 DU6PEPF0000A7DD.mail.protection.outlook.com (10.167.8.37) with Microsoft SMTP Server id 15.20.7784.11 via Frontend Transport; Tue, 16 Jul 2024 12:02:35 +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 v9 18/21] net/ntnic: add QSFP support Date: Tue, 16 Jul 2024 14:02:07 +0200 Message-ID: <20240716120216.3032484-18-sil-plv@napatech.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240716120216.3032484-1-sil-plv@napatech.com> References: <20240530144929.4127931-1-sil-plv@napatech.com> <20240716120216.3032484-1-sil-plv@napatech.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU6PEPF0000A7DD:EE_|AM9P190MB1329:EE_ Content-Type: text/plain X-MS-Office365-Filtering-Correlation-Id: 669e8964-41e8-4cd6-537c-08dca58f2e80 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|376014|82310400026|1800799024|36860700013; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?6JW19Jqpo8vprCTylmK3N9JUZMi0rdaTphRB9WDGqlZMyJVlZVejaKeTLmR2?= =?us-ascii?Q?m9e+ws4yF2maDuGAQd1HZI/2AsFytYtbT0XCe+Spv3AQQrMzZBgh3//wpSZp?= =?us-ascii?Q?2qsZiWETVv1c9/pDuByO2bBF8aO7LVUhcqeYC41ul+1dMeUID1hi9E0FJLL+?= =?us-ascii?Q?qy+nE7PVxlXN3G1cWQz8R+XARh4+uK2lZ16Uw4JLT0Vy8btOvM7CDNWwY1vE?= =?us-ascii?Q?lrJ6SkA+Ea9QtkoMOWyXvO5vToscUR2i4hmFUkQyhtzWwNx9+B7AejSifwxL?= =?us-ascii?Q?gmfPeGR0xWGw2t9mau0AlvyJdJtphVZ6ZmF74YnjYblu2fWGJtPvI5eMtVa5?= =?us-ascii?Q?kSddIFuDddkjDJ2QCpPcnhgNFCovvEw25vrjkE2ht8dvmVdSyBy+RHBvRGPc?= =?us-ascii?Q?uMgGOawyQOeDAGRz69QTdV0enq9FWVIPoMbHgfdzFA30dd9cpg1oJKzcUSST?= =?us-ascii?Q?M46lB6WP16AQQbzdK6agfi+26lnysvoWJrkuQ2afRQU0vuvl8iKFLIZJzjxS?= =?us-ascii?Q?+s7PBVIjasg4Wl5WF95kRqBx6mI0tAqHxEOalbH58DsxONHH19ATOg7pdCC9?= =?us-ascii?Q?7yoiylV+PYAFfFFELGvgFC8EO6X3jN9poY9YlJsT1IAgzHeNYCeKIxaHRsUM?= =?us-ascii?Q?qOE+XwXpLDFHXra0Ubloe0wBzMstJHpUjp1FxD9ZSvRPN0k7Hxo6BJpUgrlG?= =?us-ascii?Q?I3AS4Y/Y1MFAyv72IV8wlnXokKwvv/Evc8dyBJHdeSEGPWPLVLl4f98d8IyE?= =?us-ascii?Q?bVg/pN5zwdRbeXC/1qLNM/Z+NgF7d2ZdSS5LAWAgJSR0+oHqXSSJ2yRk2nWN?= =?us-ascii?Q?EN2DCway+lxuw5fLTvJc6ewCTsCoN1Dljvi8nNG2NZq1oTpeSMBqp4vTCwQc?= =?us-ascii?Q?pZFHrCOEFBc2+pSmWDjxjbd3fpSHegchivlBxpeMAkeKXyCzWzFVJZCYZFFF?= =?us-ascii?Q?h9192CS8HNxxhNNhpOXB3DEgabn0pB5+TryRYcAIyhwcXWrhAd0E35tsde63?= =?us-ascii?Q?aYFRt0fqGEFw2FwXNt+m/y8scv8Jwpz10GwFaHnHy18kNelYfxBK2FY+ZsFV?= =?us-ascii?Q?qJlS2AYWcsTHM754sJz3Oui8NX+j+8XAemwF48a/OYyyGXH72mdCPLXCmpjS?= =?us-ascii?Q?P2kKrW6Niq3XmCjaoqxDZ1jk/PkBlXDoUQSJWLMeUo1/Ottt1vjgz5f0qK/3?= =?us-ascii?Q?n9sZIadmeWZGlHR2+SbRtYs0YtBcJjy6/AQlfe9oY+AT+blFhEcS/BJ4D7t7?= =?us-ascii?Q?+G63ZpkamNrfrVYeD+HKBE8QzsB3ZWejQK4WNKl8UomQtWXmTBaJwRRR7pT4?= =?us-ascii?Q?7lmXnpKEDkp8BHjhuGyXTvhLxsuDCZr+PuuVnoRdYdK+6Z9zXIGUYklk/Iw2?= =?us-ascii?Q?BwzBeCf03X1yueEP839aqvg3YcELNeiE4Ddo94JtfSjliw38VUQ3Mv9liabR?= =?us-ascii?Q?TNDC8V7Fmi6PYPhlfozuYD9l0Qti06u8?= 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)(376014)(82310400026)(1800799024)(36860700013); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: gfDLSDggdrX1s22D1apd5yG6R/n2dtiJO1bE7ZRrCBc5zKYpQh66WNb9zct/R1HF9f5bmkKFfMLlVg+Ghf13Z5DKRL556Z5mMvsO64OSJtkI4iSOJ4+nE6zW3goT5Tc3AHSjuvLQlfgHApSu1p2boRZaL9CHDvd27gcD+0clHpU+UeZ7uE46DhAajhXHmFgpRcLHv4gJA5Dt8Ua9NQpfLBQHW3RuU3roKu/YpI9iqwBli/mD0wl0n8Darl4bZQj9VK+orYtYJ1WiVDvHawEmShUEGh60WniKcz+VImChhjX3t5E6i7TIS8pbJU7ZUjTFNgQBl6/BLju+TaK8qh0U9bmLrZXpM3WRYhlrG5lsb6311W9zZVyGikGE0FdDdF2IC0HdM2kuEFJaziiSEBYy490ZKt4UJ9nWDw2wodT1TgfJU5rBvANtQvJKu/MygJo7+SD2QeY+W3ty0WScdw9B8uIyI3TihEnOJpnNO/qZoiBdA58dqbngpzTPBwFWm4RnZ6jObtQqX3s3NS/Vj5q/6qsAQgm6N4foLXGRwxh2OPs1ArOUkHPH4gpNIpVH2RrGin7TzYftTgs30I3FOdM8SC4zm//dha4MKwPeLfZbzGATf7p15/OVC/ZBthRUEaVM+OoEZKwGJ5k81EziBzoM/rwy+1d4V7cmsvTN5dvKOAI= X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Jul 2024 12:02:35.6023 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 669e8964-41e8-4cd6-537c-08dca58f2e80 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: DU6PEPF0000A7DD.eurprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM9P190MB1329 X-BESS-ID: 1721131357-305467-12647-23789-1 X-BESS-VER: 2019.1_20240702.1505 X-BESS-Apparent-Source-IP: 104.47.17.169 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKVoZmhgaGQGYGUNTQ0iI1ydI8xc jYyDDNPNE8xdLMIjHVLMnc0CLRxCApUak2FgA0UDA0QgAAAA== X-BESS-Outbound-Spam-Score: 0.50 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.257662 [from cloudscan16-150.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 fd4a915811..216930af76 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 4a8d28af9c..69d0a5d24a 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 3281058822..0071d452bb 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