From nobody Fri Apr 17 12:06:33 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5DE341CEAC2; Thu, 19 Feb 2026 13:01:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771506069; cv=none; b=ENfSebD0W3fIXTr2qyH+ht/RWBR1qrpBQR6NUWDa+kSHODpyZf4I9UggORfVTgC7nN8uPHwFroRlTNcaXz5VMGInnBRzKTMS3g9rYn6iv8WkJ+pMETbnWfNknu3NQrFK09kp1jOCp3vxxT6r5ho/CEtz7ZjNfCdtuMP2mq3mz70= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771506069; c=relaxed/simple; bh=cTOhHb76G6R1iG3wVlA+/gxlO3g7G8eEMKEpEVWljZc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=umaRUOvLsDZxyoOBSGo1dwfQG7dOHu0y+PC4kXK0dabaiV5bANiCN7cSufsSCoX8qJHaI/5QZiF5teHiYTJe3dMB8WOG0XF8ghW0mRTamYnoQ6XRcwnE0MtMCwXFYul52kzmEjAmPEfrOfNFHiyHrOhFkvFabaYVm09I/8JVGi4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Oo3iYqCL; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Oo3iYqCL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D2A3CC2BC86; Thu, 19 Feb 2026 13:01:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771506068; bh=cTOhHb76G6R1iG3wVlA+/gxlO3g7G8eEMKEpEVWljZc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Oo3iYqCLOSYLNCgOZIap2KOVS0X0Pljst9Fegz3F8H/ilM47meGh/FKVeWQYIba0l gXvUoKDx+lbeyK3yNOQBfNfy+y/7T1ZykqQsZlArab6oIfaCEij5yq0xTMXXjdj72E gvYkdGUFVV33uvf+sd2k0CASq2LrK0+rjH/gx2802BQjEwbwZZG5ysKq7mgbx8PlOz S3KHBTEVkiOb1opBFM8q+oI5RDjGgj6e6iWJKv/OZM3mLWYc/SbQYt2aEiD3RY4iNU 00BgGWenTvdl6qR6TDcIA69W7Td4Dqyyf5kTMoPwAxsGh+lFBCxctS8fty0I2DeKCL MsM6ut6D/CkdA== From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= To: netdev@vger.kernel.org, Donald Hunter , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Saeed Mahameed , Tariq Toukan , Leon Romanovsky , Andrew Lunn Cc: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= , Maxime Chevallier , Andrew Lunn , Michael Chan , Hariprasad Kelam , Ido Schimmel , Danielle Ratson , linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org Subject: [RFC net-next 1/4] ethtool: module: Define CMIS loopback YAML spec and UAPI Date: Thu, 19 Feb 2026 14:00:42 +0100 Message-ID: <20260219130050.2390226-2-bjorn@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260219130050.2390226-1-bjorn@kernel.org> References: <20260219130050.2390226-1-bjorn@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add the netlink YAML specification for module loopback attributes used to query and control diagnostic loopback modes on CMIS-compliant transceiver modules. Define the module-loopback-types flags enum with four loopback types from CMIS 5.2 Section 8.4.11 ("Diagnostic Loopback Capabilities"): - media-side-output (Rx to Tx) - media-side-input (Tx to Rx) - host-side-output (Rx to Tx) - host-side-input (Tx to Rx) Add two new attributes to the module attribute-set: - loopback-capabilities: bitmask of supported loopback types - loopback-enabled: bitmask of currently enabled loopback types Include both attributes in the module-get reply (and by YAML anchor reuse, in the module-set request). Regenerate the UAPI header. Signed-off-by: Bj=C3=B6rn T=C3=B6pel --- Documentation/netlink/specs/ethtool.yaml | 27 +++++++++++++++++++ .../uapi/linux/ethtool_netlink_generated.h | 22 +++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netli= nk/specs/ethtool.yaml index 0a2d2343f79a..88dfd5f05b3c 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -11,6 +11,23 @@ c-family-name: ethtool-genl-name c-version-name: ethtool-genl-version =20 definitions: + - + name: module-loopback-types + type: flags + doc: Defines the loopback types (host/electrical or media/optical side= ) and the signal's path direction (input/near-end or output/far-end). + entries: + - + name: media-side-output + doc: Media Side Output Loopback (Rx to Tx) + - + name: media-side-input + doc: Media Side Input Loopback (Tx to Rx) + - + name: host-side-output + doc: Host Side Output Loopback (Rx to Tx) + - + name: host-side-input + doc: Host Side Input Loopback (Tx to Rx) - name: udp-tunnel-type enum-name: @@ -1438,6 +1455,14 @@ attribute-sets: - name: power-mode type: u8 + - + name: loopback-capabilities + type: uint + enum: module-loopback-types + - + name: loopback-enabled + type: uint + enum: module-loopback-types - name: c33-pse-pw-limit attr-cnt-name: __ethtool-a-c33-pse-pw-limit-cnt @@ -2501,6 +2526,8 @@ operations: - header - power-mode-policy - power-mode + - loopback-capabilities + - loopback-enabled dump: *module-get-op - name: module-set diff --git a/include/uapi/linux/ethtool_netlink_generated.h b/include/uapi/= linux/ethtool_netlink_generated.h index 556a0c834df5..d94b75b27718 100644 --- a/include/uapi/linux/ethtool_netlink_generated.h +++ b/include/uapi/linux/ethtool_netlink_generated.h @@ -10,6 +10,26 @@ #define ETHTOOL_GENL_NAME "ethtool" #define ETHTOOL_GENL_VERSION 1 =20 +/** + * enum ethtool_module_loopback_types - Defines the loopback types + * (host/electrical or media/optical side) and the signal's path directi= on + * (input/near-end or output/far-end). + * @ETHTOOL_MODULE_LOOPBACK_TYPES_MEDIA_SIDE_OUTPUT: Media Side Output Loo= pback + * (Rx to Tx) + * @ETHTOOL_MODULE_LOOPBACK_TYPES_MEDIA_SIDE_INPUT: Media Side Input Loopb= ack + * (Tx to Rx) + * @ETHTOOL_MODULE_LOOPBACK_TYPES_HOST_SIDE_OUTPUT: Host Side Output Loopb= ack + * (Rx to Tx) + * @ETHTOOL_MODULE_LOOPBACK_TYPES_HOST_SIDE_INPUT: Host Side Input Loopbac= k (Tx + * to Rx) + */ +enum ethtool_module_loopback_types { + ETHTOOL_MODULE_LOOPBACK_TYPES_MEDIA_SIDE_OUTPUT =3D 1, + ETHTOOL_MODULE_LOOPBACK_TYPES_MEDIA_SIDE_INPUT =3D 2, + ETHTOOL_MODULE_LOOPBACK_TYPES_HOST_SIDE_OUTPUT =3D 4, + ETHTOOL_MODULE_LOOPBACK_TYPES_HOST_SIDE_INPUT =3D 8, +}; + enum { ETHTOOL_UDP_TUNNEL_TYPE_VXLAN, ETHTOOL_UDP_TUNNEL_TYPE_GENEVE, @@ -654,6 +674,8 @@ enum { ETHTOOL_A_MODULE_HEADER, ETHTOOL_A_MODULE_POWER_MODE_POLICY, ETHTOOL_A_MODULE_POWER_MODE, + ETHTOOL_A_MODULE_LOOPBACK_CAPABILITIES, + ETHTOOL_A_MODULE_LOOPBACK_ENABLED, =20 __ETHTOOL_A_MODULE_CNT, ETHTOOL_A_MODULE_MAX =3D (__ETHTOOL_A_MODULE_CNT - 1) --=20 2.53.0 From nobody Fri Apr 17 12:06:33 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C618930AAD7; Thu, 19 Feb 2026 13:01:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771506073; cv=none; b=b9uzz18vwuOD4mhafiN+H9pawAkUPwjsIBedJFW5X/recCrQQpLX/ppDoQVFvVrGMh/PB6XRKpqYcFUb+SOb+7PClBjuMdM4GvdCylLSVkSlH4NGo+3G7xt7wKpmCK6t7uAvavgGPJaSKDk2ZdKVGao11fW+P2ENLfDjSbdgIpY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771506073; c=relaxed/simple; bh=N0+BoRFmiVNbRlaBtSp+cpYcmOQcv+RQ0WP1lS7akO4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ndc422iNEjSpMECQ0b/wRok5qRPpkXXm42fjCz23pxaHBw/xVxDulSvwgIw/H63GPB0CHcijOZtNlGhaJVYYeuYL0HF+p0q+nGolEKKvWso1mXwfNiUbWjnupSOJEfKTAaf+D+WlOaCbBOreJyzYMJvVX4PrAURqedueq1vTRYM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=P5G6wcK1; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="P5G6wcK1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 62A8BC4CEF7; Thu, 19 Feb 2026 13:01:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771506073; bh=N0+BoRFmiVNbRlaBtSp+cpYcmOQcv+RQ0WP1lS7akO4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=P5G6wcK1StOjHx2+7khnQdKuqYl6ek6RW560I3/4QH1PWHUu868JGzMbtiPJEeCuc 4cHUpd76KSEZeeVNVaqHsRn/OTNzDvMrCGVYXH5qgkw/HelcUXDod/pefHH+aWt5ng 7K8awl1X1Ey2bHZgcYQU7p8AAsxK3p29cuFOJVW/fVd3XNX3J7lNOyp2WnB5FcMDc7 yTVp1yyhowaLKsK8xFf2wMuDO7nwDNZXZdz9BUiPjj1MoLPLlyN/Ngh+pVzaPc3KLe uKc+KCy2MCy7pou9pt9MYSYvbB0ag2jWdPF44S5XySYyfVtVJAvho8DJ2qNycmQnOd 7qiMbHNYAa5kg== From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= To: netdev@vger.kernel.org, Donald Hunter , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Saeed Mahameed , Tariq Toukan , Leon Romanovsky , Andrew Lunn Cc: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= , Maxime Chevallier , Andrew Lunn , Michael Chan , Hariprasad Kelam , Ido Schimmel , Danielle Ratson , linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org Subject: [RFC net-next 2/4] ethtool: module: Add CMIS loopback GET/SET support Date: Thu, 19 Feb 2026 14:00:43 +0100 Message-ID: <20260219130050.2390226-3-bjorn@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260219130050.2390226-1-bjorn@kernel.org> References: <20260219130050.2390226-1-bjorn@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Implement loopback mode control for CMIS-compliant transceiver modules (QSFP-DD, OSFP, DSFP, etc.) by reading and writing EEPROM registers directly via the existing get/set_module_eeprom_by_page driver ops. Loopback capabilities are read from Page 01h Byte 142 (Table 8-40, "Supported Diagnostic and Monitoring Capabilities", CMIS 5.2), where the lower 4 bits advertise supported loopback types. Loopback control is read/written via Page 13h Bytes 180-183 (Table 8-128 "Media Lane-Specific Loopback Controls", CMIS 5.2): - Byte 180: Media Side Output Loopback - Byte 181: Media Side Input Loopback - Byte 182: Host Side Output Loopback - Byte 183: Host Side Input Loopback The SET path validates that the module is CMIS, that Page 13h is advertised, and that requested modes are within the capabilities mask before writing 0xFF (all-lanes enable) or 0x00 (disable) per control byte. No new ethtool_ops callbacks are introduced; all register access reuses the existing EEPROM page infrastructure. Signed-off-by: Bj=C3=B6rn T=C3=B6pel --- include/linux/ethtool.h | 12 ++ net/ethtool/module.c | 280 ++++++++++++++++++++++++++++++++++++++-- net/ethtool/netlink.h | 2 +- 3 files changed, 279 insertions(+), 15 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 798abec67a1b..b4cf0314b38c 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -683,6 +683,18 @@ struct ethtool_module_power_mode_params { enum ethtool_module_power_mode mode; }; =20 +/** + * struct ethtool_module_loopback_params - module loopback parameters + * @caps: The loopback types, %ETHTOOL_MODULE_LOOPBACK_TYPES_*, + * supported by the module. + * @enabled: The loopback types, %ETHTOOL_MODULE_LOOPBACK_TYPES_*, + * currently enabled by the module. + */ +struct ethtool_module_loopback_params { + u32 caps; + u32 enabled; +}; + /** * struct ethtool_mm_state - 802.3 MAC merge layer state * @verify_time: diff --git a/net/ethtool/module.c b/net/ethtool/module.c index 4d4e0a82579a..21d2f59985af 100644 --- a/net/ethtool/module.c +++ b/net/ethtool/module.c @@ -10,6 +10,7 @@ #include "common.h" #include "bitset.h" #include "module_fw.h" +#include "cmis.h" =20 struct module_req_info { struct ethnl_req_info base; @@ -18,6 +19,8 @@ struct module_req_info { struct module_reply_data { struct ethnl_reply_data base; struct ethtool_module_power_mode_params power; + struct ethtool_module_loopback_params loopback; + bool loopback_supp; }; =20 #define MODULE_REPDATA(__reply_base) \ @@ -47,6 +50,144 @@ static int module_get_power_mode(struct net_device *dev, return ops->get_module_power_mode(dev, &data->power, extack); } =20 +#define CMIS_PHYS_ADMINISTRATIVE_INFO_PAGE 0 +#define CMIS_PHYS_ADMINISTRATIVE_INFO_OFFSET 0 + +#define CMIS_PAGE13_ADVERTISEMENT_PAGE 0x01 +#define CMIS_PAGE13_ADVERTISEMENT_OFFSET 0x8E +#define CMIS_PAGE13_SUPPORTED BIT(5) + +#define CMIS_MODULE_LOOPBACK_CAPS_PAGE 0x13 +#define CMIS_MODULE_LOOPBACK_CAPS_OFFSET 0x80 + +#define CMIS_MODULE_LOOPBACK_CTRL_PAGE 0x13 +#define CMIS_MODULE_LOOPBACK_CTRL_OFFSET 0xB4 /* 4 consecutive bytes */ +#define CMIS_MODULE_LOOPBACK_CTRL_LEN 4 + +/* Mapping from Page 13h control bytes to ethtool_module_loopback_types fl= ags. + * Byte offset 0xB4+i maps to loopback_ctrl_flags[i]. + */ +static const u32 loopback_ctrl_flags[] =3D { + ETHTOOL_MODULE_LOOPBACK_TYPES_MEDIA_SIDE_OUTPUT, + ETHTOOL_MODULE_LOOPBACK_TYPES_MEDIA_SIDE_INPUT, + ETHTOOL_MODULE_LOOPBACK_TYPES_HOST_SIDE_OUTPUT, + ETHTOOL_MODULE_LOOPBACK_TYPES_HOST_SIDE_INPUT, +}; + +static bool module_is_cmis(u8 phys_id) +{ + switch (phys_id) { + case SFF8024_ID_QSFP_DD: + case SFF8024_ID_OSFP: + case SFF8024_ID_DSFP: + case SFF8024_ID_QSFP_PLUS_CMIS: + case SFF8024_ID_SFP_DD_CMIS: + case SFF8024_ID_SFP_PLUS_CMIS: + return true; + default: + } + return false; +} + +static bool module_has_cmis_page13(u8 supp) +{ + return !!(supp & CMIS_PAGE13_SUPPORTED); +} + +/* Return <0 error, >0 loopback supported, =3D0 no support */ +static int module_get_loopback_caps(struct net_device *dev, struct netlink= _ext_ack *extack, + u8 *caps) +{ + const struct ethtool_ops *ops =3D dev->ethtool_ops; + struct ethtool_module_eeprom page_data =3D {}; + u8 phys_id, page13; + int err; + + *caps =3D 0; + + /* Read module physical ID to verify CMIS type */ + ethtool_cmis_page_init(&page_data, CMIS_PHYS_ADMINISTRATIVE_INFO_PAGE, + CMIS_PHYS_ADMINISTRATIVE_INFO_OFFSET, sizeof(phys_id)); + page_data.data =3D &phys_id; + + err =3D ops->get_module_eeprom_by_page(dev, &page_data, extack); + if (err < 0) + return err; + + if (!module_is_cmis(phys_id)) + return 0; + + /* Read DiagnosticPagesSupported/Page13 availability */ + ethtool_cmis_page_init(&page_data, CMIS_PAGE13_ADVERTISEMENT_PAGE, + CMIS_PAGE13_ADVERTISEMENT_OFFSET, sizeof(page13)); + page_data.data =3D &page13; + + err =3D ops->get_module_eeprom_by_page(dev, &page_data, extack); + if (err < 0) + return err; + + if (!module_has_cmis_page13(page13)) + return 0; + + /* Read loopback capabilities */ + ethtool_cmis_page_init(&page_data, CMIS_MODULE_LOOPBACK_CAPS_PAGE, + CMIS_MODULE_LOOPBACK_CAPS_OFFSET, sizeof(*caps)); + page_data.data =3D caps; + + err =3D ops->get_module_eeprom_by_page(dev, &page_data, extack); + if (err < 0) + return err; + + /* Lower 4 bits map directly to ethtool_module_loopback_types flags */ + *caps &=3D 0x0F; + return 1; +} + +static int module_get_loopback(struct net_device *dev, struct module_reply= _data *data, + struct netlink_ext_ack *extack) +{ + const struct ethtool_ops *ops =3D dev->ethtool_ops; + struct ethtool_module_eeprom page_data =3D {}; + u8 ctrl[CMIS_MODULE_LOOPBACK_CTRL_LEN]; + int err, i; + u8 caps; + + if (!ops->get_module_eeprom_by_page) + return 0; + + if (dev->ethtool->module_fw_flash_in_progress) { + NL_SET_ERR_MSG(extack, "Module firmware flashing is in progress"); + return -EBUSY; + } + + err =3D module_get_loopback_caps(dev, extack, &caps); + if (err < 0) + return err; + + data->loopback_supp =3D (err =3D=3D 1); + data->loopback.caps =3D caps; + + if (!data->loopback.caps) + return 0; + + /* Read loopback control from Page 13h, Bytes 180-183 */ + ethtool_cmis_page_init(&page_data, CMIS_MODULE_LOOPBACK_CTRL_PAGE, + CMIS_MODULE_LOOPBACK_CTRL_OFFSET, sizeof(ctrl)); + page_data.data =3D ctrl; + + err =3D ops->get_module_eeprom_by_page(dev, &page_data, extack); + if (err < 0) + return err; + + /* Each non-zero byte means that loopback type is enabled */ + for (i =3D 0; i < CMIS_MODULE_LOOPBACK_CTRL_LEN; i++) { + if (ctrl[i]) + data->loopback.enabled |=3D loopback_ctrl_flags[i]; + } + + return 0; +} + static int module_prepare_data(const struct ethnl_req_info *req_base, struct ethnl_reply_data *reply_base, const struct genl_info *info) @@ -63,6 +204,10 @@ static int module_prepare_data(const struct ethnl_req_i= nfo *req_base, if (ret < 0) goto out_complete; =20 + ret =3D module_get_loopback(dev, data, info->extack); + if (ret < 0) + goto out_complete; + out_complete: ethnl_ops_complete(dev); return ret; @@ -80,6 +225,11 @@ static int module_reply_size(const struct ethnl_req_inf= o *req_base, if (data->power.mode) len +=3D nla_total_size(sizeof(u8)); /* _MODULE_POWER_MODE */ =20 + if (data->loopback_supp) { + /* _MODULE_LOOPBACK_{CAPABILITIES,ENABLED} */ + len +=3D nla_total_size(sizeof(u32)) * 2; + } + return len; } =20 @@ -98,16 +248,32 @@ static int module_fill_reply(struct sk_buff *skb, nla_put_u8(skb, ETHTOOL_A_MODULE_POWER_MODE, data->power.mode)) return -EMSGSIZE; =20 + if (data->loopback_supp && + nla_put_uint(skb, ETHTOOL_A_MODULE_LOOPBACK_CAPABILITIES, + data->loopback.caps)) + return -EMSGSIZE; + + if (data->loopback_supp && + nla_put_uint(skb, ETHTOOL_A_MODULE_LOOPBACK_ENABLED, + data->loopback.enabled)) + return -EMSGSIZE; + return 0; } =20 /* MODULE_SET */ =20 -const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_POWER_MOD= E_POLICY + 1] =3D { +const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_LOOPBACK_= ENABLED + 1] =3D { [ETHTOOL_A_MODULE_HEADER] =3D NLA_POLICY_NESTED(ethnl_header_policy), [ETHTOOL_A_MODULE_POWER_MODE_POLICY] =3D NLA_POLICY_RANGE(NLA_U8, ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH, ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO), + [ETHTOOL_A_MODULE_LOOPBACK_ENABLED] =3D + NLA_POLICY_MASK(NLA_UINT, + ETHTOOL_MODULE_LOOPBACK_TYPES_MEDIA_SIDE_OUTPUT | + ETHTOOL_MODULE_LOOPBACK_TYPES_MEDIA_SIDE_INPUT | + ETHTOOL_MODULE_LOOPBACK_TYPES_HOST_SIDE_OUTPUT | + ETHTOOL_MODULE_LOOPBACK_TYPES_HOST_SIDE_INPUT), }; =20 static int @@ -117,7 +283,8 @@ ethnl_set_module_validate(struct ethnl_req_info *req_in= fo, const struct ethtool_ops *ops =3D req_info->dev->ethtool_ops; struct nlattr **tb =3D info->attrs; =20 - if (!tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY]) + if (!tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY] && + !tb[ETHTOOL_A_MODULE_LOOPBACK_ENABLED]) return 0; =20 if (req_info->dev->ethtool->module_fw_flash_in_progress) { @@ -126,38 +293,123 @@ ethnl_set_module_validate(struct ethnl_req_info *req= _info, return -EBUSY; } =20 - if (!ops->get_module_power_mode || !ops->set_module_power_mode) { + if (tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY] && + (!ops->get_module_power_mode || !ops->set_module_power_mode)) { NL_SET_ERR_MSG_ATTR(info->extack, tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY], "Setting power mode policy is not supported by this device"); return -EOPNOTSUPP; } =20 + if (tb[ETHTOOL_A_MODULE_LOOPBACK_ENABLED] && + (!ops->get_module_eeprom_by_page || !ops->set_module_eeprom_by_page))= { + NL_SET_ERR_MSG_ATTR(info->extack, + tb[ETHTOOL_A_MODULE_LOOPBACK_ENABLED], + "Setting loopback is not supported by this device"); + return -EOPNOTSUPP; + } + + if (tb[ETHTOOL_A_MODULE_LOOPBACK_ENABLED] && + (req_info->dev->flags & IFF_UP)) { + NL_SET_ERR_MSG(info->extack, + "Netdevice is up, so setting loopback is not permitted"); + return -EBUSY; + } + return 1; } =20 -static int -ethnl_set_module(struct ethnl_req_info *req_info, struct genl_info *info) +static int module_set_loopback(struct net_device *dev, struct genl_info *i= nfo) +{ + const struct ethtool_ops *ops =3D dev->ethtool_ops; + struct ethtool_module_eeprom page_data =3D {}; + u8 ctrl[CMIS_MODULE_LOOPBACK_CTRL_LEN], caps; + bool changed =3D false; + int err, i; + u32 req; + + req =3D nla_get_uint(info->attrs[ETHTOOL_A_MODULE_LOOPBACK_ENABLED]); + + err =3D module_get_loopback_caps(dev, info->extack, &caps); + if (err < 0) + return err; + + if (err =3D=3D 0 || req & ~(u32)caps) { + NL_SET_ERR_MSG(info->extack, "Requested loopback mode(s) not supported b= y module"); + return -EOPNOTSUPP; + } + + /* Read current enabled state from Page 13h */ + ethtool_cmis_page_init(&page_data, CMIS_MODULE_LOOPBACK_CTRL_PAGE, + CMIS_MODULE_LOOPBACK_CTRL_OFFSET, sizeof(ctrl)); + page_data.data =3D ctrl; + + err =3D ops->get_module_eeprom_by_page(dev, &page_data, info->extack); + if (err < 0) + return err; + + /* Update control bytes: 0xFF for all-lanes enable, 0x00 for disable */ + for (i =3D 0; i < CMIS_MODULE_LOOPBACK_CTRL_LEN; i++) { + u8 new_val =3D (req & loopback_ctrl_flags[i]) ? 0xFF : 0x00; + + if (ctrl[i] !=3D new_val) { + ctrl[i] =3D new_val; + changed =3D true; + } + } + + if (!changed) + return 0; + + /* Write updated control bytes */ + ethtool_cmis_page_init(&page_data, CMIS_MODULE_LOOPBACK_CTRL_PAGE, + CMIS_MODULE_LOOPBACK_CTRL_OFFSET, sizeof(ctrl)); + page_data.data =3D ctrl; + + err =3D ops->set_module_eeprom_by_page(dev, &page_data, info->extack); + if (err < 0) + return err; + + return 1; +} + +static int ethnl_set_module(struct ethnl_req_info *req_info, struct genl_i= nfo *info) { struct ethtool_module_power_mode_params power =3D {}; struct ethtool_module_power_mode_params power_new; const struct ethtool_ops *ops; struct net_device *dev =3D req_info->dev; struct nlattr **tb =3D info->attrs; - int ret; + int ret =3D 0; =20 ops =3D dev->ethtool_ops; =20 - power_new.policy =3D nla_get_u8(tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY]); - ret =3D ops->get_module_power_mode(dev, &power, info->extack); - if (ret < 0) - return ret; + if (tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY]) { + power_new.policy =3D nla_get_u8(tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY]); + ret =3D ops->get_module_power_mode(dev, &power, info->extack); + if (ret < 0) + return ret; =20 - if (power_new.policy =3D=3D power.policy) - return 0; + if (power_new.policy !=3D power.policy) { + ret =3D ops->set_module_power_mode(dev, &power_new, + info->extack); + if (ret < 0) + return ret; + ret =3D 1; + } + } =20 - ret =3D ops->set_module_power_mode(dev, &power_new, info->extack); - return ret < 0 ? ret : 1; + if (tb[ETHTOOL_A_MODULE_LOOPBACK_ENABLED]) { + int lret; + + lret =3D module_set_loopback(dev, info); + if (lret < 0) + return lret; + if (lret > 0) + ret =3D lret; + } + + return ret; } =20 const struct ethnl_request_ops ethnl_module_request_ops =3D { diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index 89010eaa67df..2284a333aa74 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -482,7 +482,7 @@ extern const struct nla_policy ethnl_module_eeprom_get_= policy[ETHTOOL_A_MODULE_E extern const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_SRC = + 1]; extern const struct nla_policy ethnl_phc_vclocks_get_policy[ETHTOOL_A_PHC_= VCLOCKS_HEADER + 1]; extern const struct nla_policy ethnl_module_get_policy[ETHTOOL_A_MODULE_HE= ADER + 1]; -extern const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_PO= WER_MODE_POLICY + 1]; +extern const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_LO= OPBACK_ENABLED + 1]; extern const struct nla_policy ethnl_pse_get_policy[ETHTOOL_A_PSE_HEADER += 1]; extern const struct nla_policy ethnl_pse_set_policy[ETHTOOL_A_PSE_MAX + 1]; extern const struct nla_policy ethnl_rss_get_policy[ETHTOOL_A_RSS_START_CO= NTEXT + 1]; --=20 2.53.0 From nobody Fri Apr 17 12:06:33 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9178133A713; Thu, 19 Feb 2026 13:01:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771506078; cv=none; b=Hp+5ucsCPwXj26nzjxkwzANM93UL3+y1/dI15KNrtdkbWOsoJWnWoMrz6pn80WHk1QQnYg354QQrHYHP52MlRQaEU+vqkqTQ6s+bht1lTziVXiFeMs1uT+sY8pFUpR+tzvrkg9rr+1T+Lhvzqzihz6hDrW9cveyZJFS9e1x1Ums= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771506078; c=relaxed/simple; bh=5Jcs61XxaPz2ZX7VjzJx1L9dXyxRoQTzSOywqI9uovM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Q6NitppA2KFrR/jPtlcpzM5A4aNBO49Aw+0sxjHqC531ZLbP25p0V295qvYfzRFyWFaVT/OilkwlBsueQ75KMVCZR0niu9UKOG78mDe/x6EP0Ulx9s+ZS4W5IQK8V+tPMxg1MjLVbObrDkR7apKdYCMpwp+ui6cI184DosDUIR0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nECaiRXQ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="nECaiRXQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1F757C2BC86; Thu, 19 Feb 2026 13:01:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771506078; bh=5Jcs61XxaPz2ZX7VjzJx1L9dXyxRoQTzSOywqI9uovM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nECaiRXQ/cP0VkcuTPVgRfJoKECJTFMVsP8d6+kw18SM6WMNx9Vzq7e6e1o9PzD1n AULRg2i3rL4eUoQY2lIHtDACHpLwADRtUy+563WjEW1xiQtj+QupgXyVtzE8vsTTxD ckXomHvQxo03zJjyLHhuPcFWcLUdrKfLkiDLNrnWUYkZtAfdbMARDo3KUF82pbWeFn No8zLxzQqy0Sl0/yYnAI7oTzLCJ/0YbVoPSP1Q6Y94yMxEU6ZmtAIFW7OETnWb4AzY z1xL/LT2gV3qC8Rn4nG7ZVJhHWeRrHVczp+V4oV5OYdtBx7+01eriXNvREbNqCYxtZ qGhfQCJgE4azQ== From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= To: netdev@vger.kernel.org, Donald Hunter , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Saeed Mahameed , Tariq Toukan , Leon Romanovsky , Andrew Lunn Cc: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= , Maxime Chevallier , Andrew Lunn , Michael Chan , Hariprasad Kelam , Ido Schimmel , Danielle Ratson , linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org Subject: [RFC net-next 3/4] ethtool: module: refactor fw flash init to reuse CMIS helpers Date: Thu, 19 Feb 2026 14:00:44 +0100 Message-ID: <20260219130050.2390226-4-bjorn@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260219130050.2390226-1-bjorn@kernel.org> References: <20260219130050.2390226-1-bjorn@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Simplify module_flash_fw_work_init() by reusing the module_is_cmis() helper and ethtool_cmis_page_init() introduced in the loopback support commit, replacing the open-coded CMIS type switch and manual EEPROM page setup. Remove the now-duplicate MODULE_EEPROM_PHYS_ID_I2C_ADDR define from the firmware flash section since ethtool_cmis_page_init() sets the I2C address internally. Signed-off-by: Bj=C3=B6rn T=C3=B6pel --- net/ethtool/module.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/net/ethtool/module.c b/net/ethtool/module.c index 21d2f59985af..76e35dae1db2 100644 --- a/net/ethtool/module.c +++ b/net/ethtool/module.c @@ -486,7 +486,6 @@ static void module_flash_fw_work(struct work_struct *wo= rk) } =20 #define MODULE_EEPROM_PHYS_ID_PAGE 0 -#define MODULE_EEPROM_PHYS_ID_I2C_ADDR 0x50 =20 static int module_flash_fw_work_init(struct ethtool_module_fw_flash *modul= e_fw, struct net_device *dev, @@ -501,31 +500,20 @@ static int module_flash_fw_work_init(struct ethtool_m= odule_fw_flash *module_fw, * is located at I2C address 0x50, byte 0. See section 4.1 in SFF-8024, * revision 4.9. */ - page_data.page =3D MODULE_EEPROM_PHYS_ID_PAGE; - page_data.offset =3D SFP_PHYS_ID; - page_data.length =3D sizeof(phys_id); - page_data.i2c_address =3D MODULE_EEPROM_PHYS_ID_I2C_ADDR; + ethtool_cmis_page_init(&page_data, MODULE_EEPROM_PHYS_ID_PAGE, + SFP_PHYS_ID, sizeof(phys_id)); page_data.data =3D &phys_id; =20 err =3D ops->get_module_eeprom_by_page(dev, &page_data, extack); if (err < 0) return err; =20 - switch (phys_id) { - case SFF8024_ID_QSFP_DD: - case SFF8024_ID_OSFP: - case SFF8024_ID_DSFP: - case SFF8024_ID_QSFP_PLUS_CMIS: - case SFF8024_ID_SFP_DD_CMIS: - case SFF8024_ID_SFP_PLUS_CMIS: - INIT_WORK(&module_fw->work, module_flash_fw_work); - break; - default: - NL_SET_ERR_MSG(extack, - "Module type does not support firmware flashing"); + if (!module_is_cmis(phys_id)) { + NL_SET_ERR_MSG(extack, "Module type does not support firmware flashing"); return -EOPNOTSUPP; } =20 + INIT_WORK(&module_fw->work, module_flash_fw_work); return 0; } =20 --=20 2.53.0 From nobody Fri Apr 17 12:06:33 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1140733A037; Thu, 19 Feb 2026 13:01:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771506083; cv=none; b=QKaLJMUNedxeV5AHdCGg3Sgu6TSX09nAEZ9NCXFZWDljf/nZQmtgy3wx8ugQAAQj+EeJA4UxIYxTmYqrwoYhkuP3Iy+8oQOFgcMT96EfrHm4zQUVfSz3+WSnsxl6GXj2YH5Hu5ynuKTDX/RBDbTFWcEKLyR7jQXEtZWKkjaBkkI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771506083; c=relaxed/simple; bh=V2Sg/sfv4PWxxKI75fDIqd1RPCy34I6/UXyVpO38+G8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Y98x9AwreysnjlZaVggnRs3aA2Kz9RsJ8yciTMengA0MMhLbgMO46t7vZqlGMTn/+QP6CnrWhLyvEtY3eYqibo52dfyODu+9dZowdaCnmhlqGDQbRqsPdtBuz4693jD7lE7GWg9GE7k0uT5zj+vmjqWsnl0+o2uM4uHmT+cnJKA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Cr4Z6+DB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Cr4Z6+DB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A3FC6C116C6; Thu, 19 Feb 2026 13:01:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771506082; bh=V2Sg/sfv4PWxxKI75fDIqd1RPCy34I6/UXyVpO38+G8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Cr4Z6+DBa/B/bdDMhtrKzSh9U8kAFd1Fmi29Oi9IyqLvOYoyXjCQJm8+LYkfQwlCo AvN4nWz6WHVPM5qc9mIY2Ae1ctG5tGXDV1OYskwU3csFgnOt6ZaUzfz3NAOjeBv1qd 9Q+VGw+RCXPCPBsLOHN1AA4E6vV6tX13a+8NRM3qOwzucPfjdNosGGa4gEEo6lHUR5 bAK23oORQQdaNCAFKwDphlEFLTUw2QC5nl3jo66g2J93Zr8aiG8oqUdjP78+X5jNuS MbnLuSHI3NswtssBiusmRodpGHsf68eLU3Jjrh9nRUvrMlNysIQisxK3ftrmP0JvqE Bcn3ZWj9GwyGw== From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= To: netdev@vger.kernel.org, Donald Hunter , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Saeed Mahameed , Tariq Toukan , Leon Romanovsky , Andrew Lunn Cc: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= , Maxime Chevallier , Andrew Lunn , Michael Chan , Hariprasad Kelam , Ido Schimmel , Danielle Ratson , linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org Subject: [RFC net-next 4/4] net/mlx5e: Implement set_module_eeprom_by_page ethtool callback Date: Thu, 19 Feb 2026 14:00:45 +0100 Message-ID: <20260219130050.2390226-5-bjorn@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260219130050.2390226-1-bjorn@kernel.org> References: <20260219130050.2390226-1-bjorn@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add EEPROM write support by implementing the set_module_eeprom_by_page ethtool_ops callback, mirroring the existing get_module_eeprom_by_page read path. This enables the kernel's module loopback SET path which requires both get and set callbacks. The write path reuses the MCIA register (MLX5_REG_MCIA) via mlx5_core_access_reg() with write=3D1 instead of write=3D0. This seems to work, but I'd like some proper feedback from the mlx5 folks! ;-) Signed-off-by: Bj=C3=B6rn T=C3=B6pel --- .../ethernet/mellanox/mlx5/core/en_ethtool.c | 52 +++++++++++++------ .../ethernet/mellanox/mlx5/core/mlx5_core.h | 6 +-- .../net/ethernet/mellanox/mlx5/core/port.c | 34 ++++++++---- 3 files changed, 64 insertions(+), 28 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers= /net/ethernet/mellanox/mlx5/core/en_ethtool.c index 4a8dc85d5924..1dce67485651 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -2103,22 +2103,24 @@ static int mlx5e_get_module_eeprom(struct net_devic= e *netdev, return 0; } =20 -static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev, - const struct ethtool_module_eeprom *page_data, - struct netlink_ext_ack *extack) +static int __mlx5e_access_module_eeprom_by_page(struct net_device *netdev, + const struct ethtool_module_eeprom *page_data, + struct netlink_ext_ack *extack, + bool write) { struct mlx5e_priv *priv =3D netdev_priv(netdev); struct mlx5_module_eeprom_query_params query; struct mlx5_core_dev *mdev =3D priv->mdev; u8 *data =3D page_data->data; - int size_read; + int size_xfered; u8 status =3D 0; int i =3D 0; =20 if (!page_data->length) return -EINVAL; =20 - memset(data, 0, page_data->length); + if (!write) + memset(data, 0, page_data->length); =20 query.offset =3D page_data->offset; query.i2c_address =3D page_data->i2c_address; @@ -2126,28 +2128,47 @@ static int mlx5e_get_module_eeprom_by_page(struct n= et_device *netdev, query.page =3D page_data->page; while (i < page_data->length) { query.size =3D page_data->length - i; - size_read =3D mlx5_query_module_eeprom_by_page(mdev, &query, - data + i, &status); + size_xfered =3D mlx5_access_module_eeprom_by_page(mdev, &query, + data + i, &status, + write); =20 - /* Done reading, return how many bytes was read */ - if (!size_read) + if (!size_xfered) return i; =20 - if (size_read < 0) { + if (size_xfered < 0) { NL_SET_ERR_MSG_FMT_MOD( extack, - "Query module eeprom by page failed, read %u bytes, err %d, status %u", - i, size_read, status); - return size_read; + "%s module eeprom by page failed, %s %u bytes, err %d, status %u", + write ? "Set" : "Query", + write ? "wrote" : "read", + i, size_xfered, status); + return size_xfered; } =20 - i +=3D size_read; - query.offset +=3D size_read; + i +=3D size_xfered; + query.offset +=3D size_xfered; } =20 return i; } =20 +static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev, + const struct ethtool_module_eeprom *page_data, + struct netlink_ext_ack *extack) +{ + return __mlx5e_access_module_eeprom_by_page(netdev, page_data, extack, fa= lse); +} + +static int mlx5e_set_module_eeprom_by_page(struct net_device *netdev, + const struct ethtool_module_eeprom *page_data, + struct netlink_ext_ack *extack) +{ + int err; + + err =3D __mlx5e_access_module_eeprom_by_page(netdev, page_data, extack, t= rue); + return err < 0 ? err : 0; +} + int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv, struct ethtool_flash *flash) { @@ -2776,6 +2797,7 @@ const struct ethtool_ops mlx5e_ethtool_ops =3D { .get_module_info =3D mlx5e_get_module_info, .get_module_eeprom =3D mlx5e_get_module_eeprom, .get_module_eeprom_by_page =3D mlx5e_get_module_eeprom_by_page, + .set_module_eeprom_by_page =3D mlx5e_set_module_eeprom_by_page, .flash_device =3D mlx5e_flash_device, .get_priv_flags =3D mlx5e_get_priv_flags, .set_priv_flags =3D mlx5e_set_priv_flags, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/= net/ethernet/mellanox/mlx5/core/mlx5_core.h index b635b423d972..b69730727764 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -361,9 +361,9 @@ void mlx5_query_port_fcs(struct mlx5_core_dev *mdev, bo= ol *supported, int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, u16 offset, u16 size, u8 *data, u8 *status); int -mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev, - struct mlx5_module_eeprom_query_params *params, - u8 *data, u8 *status); +mlx5_access_module_eeprom_by_page(struct mlx5_core_dev *dev, + struct mlx5_module_eeprom_query_params *params, + u8 *data, u8 *status, bool write); =20 int mlx5_query_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *out); int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/e= thernet/mellanox/mlx5/core/port.c index ee8b9765c5ba..d68f9f9d7a80 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -369,9 +369,9 @@ static int mlx5_mcia_max_bytes(struct mlx5_core_dev *de= v) return (MLX5_CAP_MCAM_FEATURE(dev, mcia_32dwords) ? 32 : 12) * sizeof(u32= ); } =20 -static int mlx5_query_mcia(struct mlx5_core_dev *dev, - struct mlx5_module_eeprom_query_params *params, - u8 *data, u8 *status) +static int __mlx5_access_mcia(struct mlx5_core_dev *dev, + struct mlx5_module_eeprom_query_params *params, + u8 *data, u8 *status, bool write) { u32 in[MLX5_ST_SZ_DW(mcia_reg)] =3D {}; u32 out[MLX5_ST_SZ_DW(mcia_reg)]; @@ -388,8 +388,13 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev, MLX5_SET(mcia_reg, in, page_number, params->page); MLX5_SET(mcia_reg, in, i2c_device_address, params->i2c_address); =20 + if (write) { + ptr =3D MLX5_ADDR_OF(mcia_reg, in, dword_0); + memcpy(ptr, data, size); + } + err =3D mlx5_core_access_reg(dev, in, sizeof(in), out, - sizeof(out), MLX5_REG_MCIA, 0, 0); + sizeof(out), MLX5_REG_MCIA, 0, write); if (err) return err; =20 @@ -399,12 +404,21 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev, return -EIO; } =20 - ptr =3D MLX5_ADDR_OF(mcia_reg, out, dword_0); - memcpy(data, ptr, size); + if (!write) { + ptr =3D MLX5_ADDR_OF(mcia_reg, out, dword_0); + memcpy(data, ptr, size); + } =20 return size; } =20 +static int mlx5_query_mcia(struct mlx5_core_dev *dev, + struct mlx5_module_eeprom_query_params *params, + u8 *data, u8 *status) +{ + return __mlx5_access_mcia(dev, params, data, status, false); +} + int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, u16 offset, u16 size, u8 *data, u8 *status) { @@ -446,9 +460,9 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, return mlx5_query_mcia(dev, &query, data, status); } =20 -int mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev, - struct mlx5_module_eeprom_query_params *params, - u8 *data, u8 *status) +int mlx5_access_module_eeprom_by_page(struct mlx5_core_dev *dev, + struct mlx5_module_eeprom_query_params *params, + u8 *data, u8 *status, bool write) { int err; =20 @@ -462,7 +476,7 @@ int mlx5_query_module_eeprom_by_page(struct mlx5_core_d= ev *dev, return -EINVAL; } =20 - return mlx5_query_mcia(dev, params, data, status); + return __mlx5_access_mcia(dev, params, data, status, write); } =20 static int mlx5_query_port_pvlc(struct mlx5_core_dev *dev, u32 *pvlc, --=20 2.53.0