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 1DC6045509; Thu, 27 Jun 2024 09:42:22 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 9C05540EE1; Thu, 27 Jun 2024 09:40:01 +0200 (CEST) Received: from egress-ip11a.ess.de.barracuda.com (egress-ip11a.ess.de.barracuda.com [18.184.203.234]) by mails.dpdk.org (Postfix) with ESMTP id 6990640E6E for ; Thu, 27 Jun 2024 09:39:52 +0200 (CEST) Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05lp2110.outbound.protection.outlook.com [104.47.18.110]) by mx-outbound11-228.eu-central-1a.ess.aws.cudaops.com (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 27 Jun 2024 07:39:51 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=RY6ISkglMroRTxlA1MpGBhM3V0NCRyMs2x5NLF0M1dl6WSQlkrTGnrX40sSinwqS1kLOCHHt2nwVwY4kf0Nl37xiRkGorBa/P/4eFUDTHvG+j/lyZCMgEvehjYjho1HE+pXW4teOTj3+Xpb2BbckK+OicQ351k5LqIt1a/LMk6AGtbPUXS0Fq4GQhQyVbCd+HpQdMoIL5nCI/Z0P1Umi/lMoolGELOU413Ick8idNv7hz4ge9LKieZIiFERHvsMxT0nc2DyW/lg2OsKM5eJg9NKbS8vmaAB4zOgRDlrZC8Sv9tOiBbDEVvL2O+WJTePWq1YQUvgMz1EZLU/3analGw== 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=TR73MN63c5F1NDf8XT9VT2SoN6AqAqlRz8CYAYELKlc=; b=G3aNR0sUNcSBiB2jBjnLcGacIIBhO5t7rRE/hxlkD7cH+BC7iZLy10STYt5SNrCPnasS5qqI9PYBYOw5HNWDZEnB16Yr1Tm9VLp3G1uuE8dJScnMKm3mxyolKHdX+w3pqu9C9L178bbvDNK8NAXDV6WskCbvb5YdOxhT+yycK+YmbnzJwsuvw5uEIEmHX1f3vEdXsl+wAMMjJHWXVHXsDXeeIl5AP+v8tHpXtiZV9oGVLBULDG2Ks35QfXIjbw0+4pvcVqUbJimQ0VuZy2eOfoLxcr+LegH7JYoih5o1JtvEdUt7UPqKnrHnLlE2Z5yJPml+xgqLWUbJZ8wMURrYVA== 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=TR73MN63c5F1NDf8XT9VT2SoN6AqAqlRz8CYAYELKlc=; b=dVVkPMXphEtWN0tkGmuLpGROo7IPna3C2EG5baTd6N/YVgkGt93czFQtRfRKQuvekl0HqGktQDExsKG4HmVfOMXJAsayXWGg+inbpZai+htk6zVV++7MhNzmhqUk1BCdVWFqnEiD/B0+xFxJTi8LvZbYBGWt42o58oZtzfqP/fU= Received: from DUZPR01CA0333.eurprd01.prod.exchangelabs.com (2603:10a6:10:4b8::27) by VI1P190MB0605.EURP190.PROD.OUTLOOK.COM (2603:10a6:800:12d::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.35; Thu, 27 Jun 2024 07:39:45 +0000 Received: from DB1PEPF000509E2.eurprd03.prod.outlook.com (2603:10a6:10:4b8:cafe::40) by DUZPR01CA0333.outlook.office365.com (2603:10a6:10:4b8::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7719.26 via Frontend Transport; Thu, 27 Jun 2024 07:39:45 +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 20/23] net/ntnic: add QSFP28 support Date: Thu, 27 Jun 2024 09:39:01 +0200 Message-ID: <20240627073918.2039719-20-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_|VI1P190MB0605:EE_ Content-Type: text/plain X-MS-Office365-Filtering-Correlation-Id: 886bc859-5d52-446a-29de-08dc967c5099 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?QTLGZHZMMGPF0Z6bcC9DP/KGyFrsGkcBhurFLctJQBlcAKPak5M6WMCT02Bd?= =?us-ascii?Q?R83q0hXRDrhEkZWj/RHTSQXSnzVkQzMV3dyHEDnuGB6vwmLznyGbkBvFm3lg?= =?us-ascii?Q?B8qlSE/PMZAx+BZYzZmopvctlxJGcQR55X8GDA1hyDrEnWxFJJ9RehTHs2V7?= =?us-ascii?Q?35Jnc4f9NFsXvlLDNfsSgZBjZwl32RLbTxcdcyhyCeY3i2LbSOtLr1IGiykQ?= =?us-ascii?Q?FLcTVPA2xEE9/YOpvnRLQIfFOE/Da1IOmt6g2WA0qGK4omOXvABwOTnETuK/?= =?us-ascii?Q?PjdpvvegqnsBqTyQAeJvWJsrEhHbIcPTuJ1u8utU3/twXFzhYADywU6xLnzY?= =?us-ascii?Q?w4lPJI/zRZXXjSFdeSmt8INSpbFv44y30gIiQ8JGdDwPn8kUdmgOWowgaXM5?= =?us-ascii?Q?a2zHmXO7G9KNYjdnrujUU+D9lVCV+6ToHPJZTuCQtpS3q4Csjyo7p2ykiUjJ?= =?us-ascii?Q?WYgf+D9/9L9InNb+D7f7v1ZZ9tkXjGuw2yrhZkitV5bDLw3rxE0iifd7VuA9?= =?us-ascii?Q?VbDC0LSalCgtPpe/QUPV039QBPfEGf93baQV04/oRlQsNEdOq6pzt01WcY6E?= =?us-ascii?Q?lt32DUIQlYCbLYvi8Om8Tet4s0ZxrToanREoT2ELGkDPh+rKsVYM0QNtlTQ/?= =?us-ascii?Q?K8zkk9U0vMJP/wch02crA68kJPmNXkPRiPIHAr2IurrZ3rU2nZHfu0zlkyQk?= =?us-ascii?Q?v8ppEjxRvhc4KURUSSZBn7KjA/PMRP3ZImUcEoQ84IRRp7aNWvHeujuN0Gzx?= =?us-ascii?Q?PA8aa/gcNuNzVgUupkNjAHJ9taBLjm9g1Gp2ARJ9U8QPv46BNGrhz7454mfI?= =?us-ascii?Q?ur6D0uPY5dqTCFYgWkziiWjWm+noAlwCoD/n4G/z9Hs/pI+N1L7g20sanXwg?= =?us-ascii?Q?I+PruZhWb2M/qD3wiaW4DpGo4JJIJTyH0SkLkIA8v6e/1r3HCJt284Mn6Cmd?= =?us-ascii?Q?C/pxqz620XsDEstGncO3vZui9zZkRiZzA6NdkuxcMhcWBt8c6cekFkgYhTYH?= =?us-ascii?Q?fGL+FRXLjiJLs/mhUAOOU310V8cwA0dzyDnRTUoIodf9/xmGkZ0gAsaAaBZo?= =?us-ascii?Q?6663cbeSm+CwjP3lXnIY4i2cE+oSbSKeiNIB8EVEeigMkcEhFR4qhWBzaieE?= =?us-ascii?Q?hz7VpJ9hp+7ShPuNJj0PCbvB8p5mMVR54Ydij1DjFFZdujSZmSGTSm8aihAu?= =?us-ascii?Q?R3It6T5bQXpbev2rm+A37DkdqOwmUVzTPu1WSuZgwvw8ameS5fcRILmSRkPm?= =?us-ascii?Q?3SJRwNfLcqW+1UhaYT2k/3KD5NELACwU8cdb5PtppcwCOJoVj1blNLaHqxSb?= =?us-ascii?Q?yivv5CMeLDBS91zB83XzJebDTH5c7tjiohf76mIW8d4sJ0yZqepEIb6F0jro?= =?us-ascii?Q?vOCBx6tMLihceaXHlaJAM8kZpG+StMT/9C5ZdBSRCNlM8YpjuxGz0nJrQR1t?= =?us-ascii?Q?6vaT9683jIXYuFg6lJ/qWveLEnstLpFd?= 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: vW8GTQRn/RmuVGdCP/NxzdAzddAVGiJjGm0YJeXCMEQHeyHC8yRNbzm5CObg23tF+sq9cKMfEjCBaWKupkxfyOcWlrgvK2f5gVKXAc2bcNzW7eLvJix9YwGhotqdInsHtFLS+NlcPpIw3Buqa57XARGlbh+0H7KJiUD2yaRYUIlLOLTPtvcYmUPtNcJjbey7JFEOjwEsHIoVNNiburKBLbZYjNJPpGgNqaUNHaHLzo9pne8KgTfE71ZMSdoT7JR4JAlSRjseTP8Iy5+PrhCv6Ka2SvGYBhTV1tw4D2C/We4Bn7Z5x2a3w4Izw0R/0N2rgEOVfkZydqEHCCL5U08JlFrQ4NN0mUT7raQTBL/YJzta7PqITmuq/fvZCxpx4iER7hh2Ni7AOhCMdixhFWNNCBMwbDWoHGHbVPSoXCaiYcPkwEJPOEZ3YQ56P7oQDtBB8EHKOhINQ27UTYy3+s2YEVjSWG//ADX+O7QupWzlkJu/xIeA3U8037rpNni2uvW1/aMQQB2Lfigy7EToFvewls5yCJJ94XDhaEqOL+DtDvNoWHGbY0SZUz6wiov4UyjNUNMs4kVdJhvh34bB8x1ZJ0sOluzre8C7KMr+VfDLCo5T/1qY5oQVHqT/Ixk74K7oPZ0nL8CKH9uKIWGbO9pv/g== X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jun 2024 07:39:44.9281 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 886bc859-5d52-446a-29de-08dc967c5099 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: VI1P190MB0605 X-BESS-ID: 1719473988-303044-12647-2734-2 X-BESS-VER: 2019.1_20240620.2317 X-BESS-Apparent-Source-IP: 104.47.18.110 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKVobGhubGQGYGUNTA2MzSMMnC2C TJyMTQ3DLR0iw1yTDVxDzRJMnEzDTJRKk2FgDSNZ6FQgAAAA== X-BESS-Outbound-Spam-Score: 0.50 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.257231 [from cloudscan11-98.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 Includes support for QSFP28 Signed-off-by: Serhii Iliushyk --- drivers/net/ntnic/include/ntnic_nim.h | 21 ++ drivers/net/ntnic/link_mgmt/nt4ga_link.c | 25 +++ drivers/net/ntnic/nim/i2c_nim.c | 267 ++++++++++++++++++++++- drivers/net/ntnic/nim/nim_defines.h | 1 + 4 files changed, 313 insertions(+), 1 deletion(-) diff --git a/drivers/net/ntnic/include/ntnic_nim.h b/drivers/net/ntnic/include/ntnic_nim.h index 300842b570..f3bd159130 100644 --- a/drivers/net/ntnic/include/ntnic_nim.h +++ b/drivers/net/ntnic/include/ntnic_nim.h @@ -17,6 +17,19 @@ enum nt_port_type_e { 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 */ + 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 */ + 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 */ + /* 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; @@ -56,7 +69,15 @@ typedef struct nim_i2c_ctx { union { 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; diff --git a/drivers/net/ntnic/link_mgmt/nt4ga_link.c b/drivers/net/ntnic/link_mgmt/nt4ga_link.c index bc362776fc..4dc1c3d467 100644 --- a/drivers/net/ntnic/link_mgmt/nt4ga_link.c +++ b/drivers/net/ntnic/link_mgmt/nt4ga_link.c @@ -140,6 +140,26 @@ static uint32_t nt4ga_port_get_loopback_mode(struct adapter_info_s *p, int port) return p_link->port_action[port].port_lpbk_mode; } +/* + * port: tx power + */ +static 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; + } + } + + return 0; +} static const struct port_ops ops = { .get_nim_present = nt4ga_port_get_nim_present, @@ -181,6 +201,11 @@ static const struct port_ops ops = { .get_loopback_mode = nt4ga_port_get_loopback_mode, .get_link_speed_capabilities = nt4ga_port_get_link_speed_capabilities, + + /* + * port: tx power + */ + .tx_power = nt4ga_port_tx_power, }; void port_init(void) diff --git a/drivers/net/ntnic/nim/i2c_nim.c b/drivers/net/ntnic/nim/i2c_nim.c index 4831078a2c..10848029ee 100644 --- a/drivers/net/ntnic/nim/i2c_nim.c +++ b/drivers/net/ntnic/nim/i2c_nim.c @@ -24,6 +24,7 @@ static bool page_addressing(nt_nim_identifier_t id) switch (id) { case NT_NIM_QSFP: case NT_NIM_QSFP_PLUS: + case NT_NIM_QSFP28: return true; default: @@ -185,6 +186,14 @@ static int read_data_lin(nim_i2c_ctx_p ctx, uint16_t lin_addr, uint16_t length, NIM_READ); } +/* 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. */ @@ -294,8 +303,12 @@ static int qsfp_nim_state_build(nim_i2c_ctx_t *ctx, sfp_nim_state_t *state) state->br = 103U; /* QSFP+: 4 x 10G = 40G */ break; + case 17U: + state->br = 255U; /* QSFP28: 4 x 25G = 100G */ + break; + default: - NT_LOG(INF, NIM, "nim_id = %u is not an QSFP/QSFP+ module\n", ctx->nim_id); + NT_LOG(INF, NIM, "nim_id = %u is not an QSFP/QSFP+/QSFP28 module\n", ctx->nim_id); res = -1; } @@ -319,6 +332,9 @@ const char *nim_id_to_text(uint8_t nim_id) case 0x0D: return "QSFP+"; + case 0x11: + return "QSFP28"; + default: return "ILLEGAL!"; } @@ -446,6 +462,132 @@ static int qsfpplus_read_basic_data(nim_i2c_ctx_t *ctx) return 0; } +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 + /* PAM-4 modules can only run on all lanes together */ + ctx->speed_mask = 0; + + } 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; @@ -474,6 +616,7 @@ static void qsfpplus_set_speed_mask(nim_i2c_ctx_p ctx) 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; } @@ -514,6 +657,124 @@ static int qsfpplus_preinit(nim_i2c_ctx_p ctx, int8_t lane_idx) 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; +} + int construct_and_preinit_nim(nim_i2c_ctx_p ctx, void *extra) { int res = i2c_nim_common_construct(ctx); @@ -523,6 +784,10 @@ int construct_and_preinit_nim(nim_i2c_ctx_p ctx, void *extra) qsfpplus_preinit(ctx, extra ? *(int8_t *)extra : (int8_t)-1); break; + case NT_NIM_QSFP28: + qsfp28_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)); diff --git a/drivers/net/ntnic/nim/nim_defines.h b/drivers/net/ntnic/nim/nim_defines.h index e5a033a3d4..8e17b263c5 100644 --- a/drivers/net/ntnic/nim/nim_defines.h +++ b/drivers/net/ntnic/nim/nim_defines.h @@ -26,6 +26,7 @@ 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+ */ + NT_NIM_QSFP28 = 0x11, /* Nim type = QSFP28 */ }; typedef enum nt_nim_identifier_e nt_nim_identifier_t; -- 2.45.0