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 85BE64560F; Fri, 12 Jul 2024 11:50:32 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7193142F61; Fri, 12 Jul 2024 11:49:06 +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 5FDC542EFD for ; Fri, 12 Jul 2024 11:48:53 +0200 (CEST) Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05lp2168.outbound.protection.outlook.com [104.47.17.168]) by mx-outbound23-2.eu-central-1b.ess.aws.cudaops.com (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Fri, 12 Jul 2024 09:48:52 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=SVHp8yLqZ9XM82qSPOfJ6FiaiISZGLRa0beuWoStseAL8l+uCVGLrzg83ntCAqc+0TJ34gadTxsDw/fqnKkQMvj9VYwxEWJhMHpWE9EnOQFmEiTFjIDmxVw+eoMNmW6fTDW+0xxMH9CY+gojK1CrA4aoPUYPQ7UKPxE5Z4DX9X8fJE8Af2xHVEL7wECw5a2RD1hivgPaR1K2N84XtQ8egze6+CEEDb5Ft665IZNd545IpGZ10Rqd/IH/ffAjoWQQqOSCo2RPw6dC0evVqepfV//H/2deU0dz1/T6uamrT5xpmS04ICb79R8ekwACz/vLu3WM4AfALiOyo82sA1ibPw== 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=ZIfJxc6l2lmO05KvcqwbSDyoENATdbduKYHIsRPqwy4=; b=tMQEfn1Kc3C3rQco3iXhb4ED6IcsNC2wKzsaolbGO+nz1qOgytSzv22vOFt/kDhTRmPFwS5DX0TO18+ODwamsNTGKYzJi/C5LvJuPSmEPzv6IdkFJKEQzlvRYVJCoMbOZDG/6CBGZ4OrJxJvfA8hcXEb1MqTtMzAylN0SGJHNoCI8Gzo4LCObh92LPIangFQ4oWpjtNiqZsUwFBVuvmpnByl0usv3oKd24NvqNWtkvelLwiCmNpDXDQa9qQr2j6IqXGfqPf3aJOKE+P5n0jOcjjHut21uE0CBDTEiy+mcRkrGtlCq06Lm5brcOD3diRh6I+UN0yU4eyuaIU3wEivMw== 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=ZIfJxc6l2lmO05KvcqwbSDyoENATdbduKYHIsRPqwy4=; b=nlQANi8p6e2yxJk068cpp4kxbJzcTPvhHPTu3TZjHy2R4nbD7ZYEQFjCZJ1L1l7eb791y+c5gO1QfBkSh8LJGRQ7B7AIsxa0AuYNiewXABZlPYxTJHKWASr9iJ8gxHHepf5SQUtVhGiGpYxHwvH52u7KYS8mXHEA2gOttUDpYSk= Received: from AS9PR06CA0511.eurprd06.prod.outlook.com (2603:10a6:20b:49d::6) by VI0P190MB2234.EURP190.PROD.OUTLOOK.COM (2603:10a6:800:25f::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7762.20; Fri, 12 Jul 2024 09:48:49 +0000 Received: from AM1PEPF000252DD.eurprd07.prod.outlook.com (2603:10a6:20b:49d:cafe::b1) by AS9PR06CA0511.outlook.office365.com (2603:10a6:20b:49d::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7762.23 via Frontend Transport; Fri, 12 Jul 2024 09:48:49 +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 AM1PEPF000252DD.mail.protection.outlook.com (10.167.16.55) with Microsoft SMTP Server id 15.20.7762.17 via Frontend Transport; Fri, 12 Jul 2024 09:48:49 +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 v7 19/21] net/ntnic: add QSFP28 support Date: Fri, 12 Jul 2024 11:48:24 +0200 Message-ID: <20240712094831.861260-19-sil-plv@napatech.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240712094831.861260-1-sil-plv@napatech.com> References: <20240530144929.4127931-1-sil-plv@napatech.com> <20240712094831.861260-1-sil-plv@napatech.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AM1PEPF000252DD:EE_|VI0P190MB2234:EE_ Content-Type: text/plain X-MS-Office365-Filtering-Correlation-Id: 57f1ddad-4697-4209-14df-08dca257d4e0 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|36860700013|1800799024|82310400026|376014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?yHWg2OE2XsBkT9jCS1sNS8AMnKh36k7QBh/ThbxBCZUlSGMgKhhCUQcprM4K?= =?us-ascii?Q?/3VAnGtiOiOto7Q4dmdqVLRoC/XMVAx/G7h06D2ky9li9b13gzdjlL9wkxcS?= =?us-ascii?Q?5OuqezyR+0rVO7qME6oEa0XXahLl6xv74xMlOVogjV2/JHG4mgEisOsiSjx+?= =?us-ascii?Q?w2BHQovmCXQu0XEBTl85Nai8dxdiZondPxi+A33d16346aCcDp6FoN5ZtETu?= =?us-ascii?Q?CtR3G8VUFJofzmrdoIy3fQT9yYqTOL/1W9p+FY1Gbm5g+n9p3NC0KtIxaiIW?= =?us-ascii?Q?x9khE+v6tlUpg/QAK2vrNoCeOFj52SzS7bviDvT3wI+dKAgz7Lcq6lfHIIqF?= =?us-ascii?Q?I462m69f9noisTb4Iw1ujfW57C1Ezp52t10z/+Z5f1koefSz/MJXLk9l9nOT?= =?us-ascii?Q?UXpfm02V/04vqaFWEOgwUp7qvtFTCw608eSnfmaQV7QuSfWk6zVLoF9UlZjy?= =?us-ascii?Q?YV5LO6U3EMTuPxeoU5dLUFTwnhiq4VsGBXzR3KmbKJexzWuSdUFixgkVErUT?= =?us-ascii?Q?1NYWKF8pSCykJCP10ZUyifRwhxR6Ep8zUecOcW4PaAl/HFTMndmwetKm3YhW?= =?us-ascii?Q?P+RUo0hocM5M6DPcNQirkMaQAhoTj/lrfl0FwurAlJU8oOgfDRDBAVyvC+Gt?= =?us-ascii?Q?gRkEV9351UJS73rvT+mhKUrSec5mQKUKLjQpwq+C0XGHruIWUXvfzAMRpSGR?= =?us-ascii?Q?2UW1ADvYNhLTWJmasyc7SMEHucamWRKGTV833BXYWLOoCh//5DMc2lfC/iPJ?= =?us-ascii?Q?88yCFmdrsYsVAotfxVK/Ocx5APInGIpDmDOSLmZtki11VhlMrfv07Pi+pF/8?= =?us-ascii?Q?ZRoyt5ny1E7IeonyW0XJzKXAtdZBXuutIaT67k5a8s1epsYH/x/yb3Qzj1eG?= =?us-ascii?Q?yzrQ9CHA2GEwV/C821l/abVpG7+Q+bON4ookRy4q0l1oBFa7cI43wNBrD5r7?= =?us-ascii?Q?yae5kSKsK+GRE9COVnGbZ8VTdKRt91GUG5qRt3CRRdk0kpFt4zSgilN1Vnsj?= =?us-ascii?Q?QGJVQ9D8MsJ3fRwbxRXC6UaGtWtX/euq04+B8ldblkDlfiA05KYDVTflFBJl?= =?us-ascii?Q?EE1R3m7zPvRpBbP0ltrDOKLaTW748Pb6Ezwo8fwEBCH0Y+DG5DU/+zsds31P?= =?us-ascii?Q?6K3tcR9pvA1dvoqx2RaSzybDGp2kB5U2GUxlnOzNJlFiozN+1pfc/3Td1AR+?= =?us-ascii?Q?i/oFxPRq7n728uoK5QZ/sZKq5Mt67yHYyRnrV8BgCiNCiwKZ1P3e7wSjI1wO?= =?us-ascii?Q?/sFefqFYejCQaERI/DbBcoYsi6qhzgVPnjQn1mMRvh2+85iRHqQxwuXjVZqm?= =?us-ascii?Q?zJTtBYz2D8i2NTbCgqdZu0ouQXpMf+c+8oto6Y1zbhiksG4JiTlD/epyz5F7?= =?us-ascii?Q?XO5CYCa68wvvA26N9bjl/q4HjTjuT94dBQlaEuFfvdcJzReDIZtsooZKpB9D?= =?us-ascii?Q?gNlB/DfIWHaQWZ7eo4qtqEOg3sGa5RGm?= 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)(36860700013)(1800799024)(82310400026)(376014); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: GZADBXCiH+tYLz1hJApFy+sD0l+MVEqrhW2ZBwAukEoAkM92ddHDhH7JP/Yesc2fdYOe1Dmu5o6WySrwG0yT4uBhBR6z3UIj/b/ekEalc127Y+Hfzh5qx2K/3fzjxLeXRtfrIxaPQ/Ibeni80tKZoCnhvp/9zVITZRHO0Rq8VIZpZeaKzDRzdXVwYR3jCf//tTZ3j8GBs+urJy+LIZyOeTulsyTuZXtivP65uWs72AQ1LVRX0J7yw62yTipX614qZwN9qhiZP632B6f3+k6RMk7LUkgBkC3PQvi6Xi2CwntrMGJBcqHBvdcL8zObdrirGpnYBX2L8uEEBII/yupPqsBRv6DSHxAEuDUCsImygKSYGegMUQMKgxxsubIBnmlZyX+nANpoBKgfG02xKKyc6DO7nq5n1BQpEFV3durxUH+mYCYor8pPg7DBPfs35tgBgK+AKj78lOwZ2tu0GeRrAq7IIC+KwJJn2AQdV/RVC4SG4mHpWhbVMR4i41Wchpvmn4ecFIXJ5rVCSoV6QnIpgRytPg8YdwmidGsf9UCcc8eGuKZvTh4EVqU6WxS/KW//nngm/6sa3qgbqLHzgZ1dGIpxo3zIPlnMda15YLbcPbVSEHdRWYuV0fNFiu1fjKY2U2z+bII8nF/ERU/mY4OPFQ== X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Jul 2024 09:48:49.5671 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 57f1ddad-4697-4209-14df-08dca257d4e0 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: AM1PEPF000252DD.eurprd07.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0P190MB2234 X-BESS-ID: 1720777732-305890-12643-7801-1 X-BESS-VER: 2019.1_20240702.1505 X-BESS-Apparent-Source-IP: 104.47.17.168 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKVobGhubGQGYGUNTQIjUxzSzRyM jAAihokpZmkZhskmZpYGCaYmhilmiiVBsLAKBp9ZlCAAAA X-BESS-Outbound-Spam-Score: 0.50 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.257571 [from cloudscan21-75.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 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 0071d452bb..e6e256b062 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