netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH ethtool-next 0/4] Add ability to flash modules' firmware
@ 2024-07-16 13:11 Danielle Ratson
  2024-07-16 13:11 ` [PATCH ethtool-next 1/4] cmis: Print active and inactive firmware versions Danielle Ratson
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Danielle Ratson @ 2024-07-16 13:11 UTC (permalink / raw)
  To: netdev; +Cc: mkubecek, mlxsw, Danielle Ratson

CMIS compliant modules such as QSFP-DD might be running a firmware that
can be updated in a vendor-neutral way by exchanging messages between
the host and the module as described in section 7.2.2 of revision
4.0 of the CMIS standard.

Add ability to flash transceiver modules' firmware over netlink.

Example output:

 # ethtool --flash-module-firmware eth0 file test.img

Transceiver module firmware flashing started for device swp23
Transceiver module firmware flashing in progress for device swp23
Progress: 99%
Transceiver module firmware flashing completed for device swp23

In addition, add some firmware and CDB messaging information to
ethtool's output for observability.

Patchset overview:
Patches #1-#2: adds firmware info to ethtool's output.
Patch #3: updates headers.
Patch #4: adds ability to flash modules' firmware.

Danielle Ratson (2):
  Update UAPI header copies
  ethtool: Add ability to flash transceiver modules' firmware

Ido Schimmel (2):
  cmis: Print active and inactive firmware versions
  cmis: Print CDB messaging support advertisement

 cmis.c                        | 125 +++++++++++++++++++++++
 cmis.h                        |  19 ++++
 ethtool.8.in                  |  29 ++++++
 ethtool.c                     |   7 ++
 netlink/desc-ethtool.c        |  13 +++
 netlink/extapi.h              |   2 +
 netlink/module.c              | 183 ++++++++++++++++++++++++++++++++++
 netlink/netlink.h             |  16 +++
 netlink/prettymsg.c           |   5 +
 netlink/prettymsg.h           |   2 +
 shell-completion/bash/ethtool |  27 +++++
 uapi/linux/ethtool.h          |  18 ++++
 uapi/linux/ethtool_netlink.h  |  19 ++++
 13 files changed, 465 insertions(+)

-- 
2.45.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH ethtool-next 1/4] cmis: Print active and inactive firmware versions
  2024-07-16 13:11 [PATCH ethtool-next 0/4] Add ability to flash modules' firmware Danielle Ratson
@ 2024-07-16 13:11 ` Danielle Ratson
  2024-07-16 13:11 ` [PATCH ethtool-next 2/4] cmis: Print CDB messaging support advertisement Danielle Ratson
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Danielle Ratson @ 2024-07-16 13:11 UTC (permalink / raw)
  To: netdev; +Cc: mkubecek, mlxsw, Ido Schimmel, Danielle Ratson

From: Ido Schimmel <idosch@nvidia.com>

Parse and print the active and inactive firmware versions from the CMIS
EEPROM dump. Example output:

 # ethtool -m swp23
 Identifier                                : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))
 [...]
 Active firmware version                   : 2.6
 Inactive firmware version                 : 2.7

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Danielle Ratson <danieller@nvidia.com>
---
 cmis.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 cmis.h |  8 ++++++++
 2 files changed, 53 insertions(+)

diff --git a/cmis.c b/cmis.c
index 531932e..bbbbb47 100644
--- a/cmis.c
+++ b/cmis.c
@@ -884,6 +884,50 @@ static void cmis_show_dom(const struct cmis_memory_map *map)
 		sff_show_thresholds(sd);
 }
 
+/* Print active and inactive firmware versions. Relevant documents:
+ * [1] CMIS Rev. 5, page 115, section 8.2.9, Table 8-14
+ * [2] CMIS Rev. 5, page 127, section 8.4.1, Table 8-37
+ */
+static void cmis_show_fw_version_common(const char *name, __u8 major,
+					__u8 minor)
+{
+	if (major == 0 && minor == 0) {
+		return;
+	} else if (major == 0xFF && minor == 0xFF) {
+		printf("\t%-41s : Invalid\n", name);
+		return;
+	}
+
+	printf("\t%-41s : %d.%d\n", name, major, minor);
+}
+
+static void cmis_show_fw_active_version(const struct cmis_memory_map *map)
+{
+	__u8 major = map->lower_memory[CMIS_MODULE_ACTIVE_FW_MAJOR_OFFSET];
+	__u8 minor = map->lower_memory[CMIS_MODULE_ACTIVE_FW_MINOR_OFFSET];
+
+	cmis_show_fw_version_common("Active firmware version", major, minor);
+}
+
+static void cmis_show_fw_inactive_version(const struct cmis_memory_map *map)
+{
+	__u8 major;
+	__u8 minor;
+
+	if (!map->page_01h)
+		return;
+
+	major = map->page_01h[CMIS_MODULE_INACTIVE_FW_MAJOR_OFFSET];
+	minor = map->page_01h[CMIS_MODULE_INACTIVE_FW_MINOR_OFFSET];
+	cmis_show_fw_version_common("Inactive firmware version", major, minor);
+}
+
+static void cmis_show_fw_version(const struct cmis_memory_map *map)
+{
+	cmis_show_fw_active_version(map);
+	cmis_show_fw_inactive_version(map);
+}
+
 static void cmis_show_all_common(const struct cmis_memory_map *map)
 {
 	cmis_show_identifier(map);
@@ -900,6 +944,7 @@ static void cmis_show_all_common(const struct cmis_memory_map *map)
 	cmis_show_mod_fault_cause(map);
 	cmis_show_mod_lvl_controls(map);
 	cmis_show_dom(map);
+	cmis_show_fw_version(map);
 }
 
 static void cmis_memory_map_init_buf(struct cmis_memory_map *map,
diff --git a/cmis.h b/cmis.h
index 8d66f92..3015c54 100644
--- a/cmis.h
+++ b/cmis.h
@@ -41,6 +41,10 @@
 #define CMIS_LOW_PWR_ALLOW_REQUEST_HW_MASK	0x40
 #define CMIS_LOW_PWR_REQUEST_SW_MASK		0x10
 
+/* Module Active Firmware Version (Page 0) */
+#define CMIS_MODULE_ACTIVE_FW_MAJOR_OFFSET	0x27
+#define CMIS_MODULE_ACTIVE_FW_MINOR_OFFSET	0x28
+
 /* Module Fault Information (Page 0) */
 #define CMIS_MODULE_FAULT_OFFSET		0x29
 #define CMIS_MODULE_FAULT_NO_FAULT		0x00
@@ -134,6 +138,10 @@
  * GlobalOffset = 2 * 0x80 + LocalOffset
  */
 
+/* Module Inactive Firmware Version (Page 1) */
+#define CMIS_MODULE_INACTIVE_FW_MAJOR_OFFSET	0x80
+#define CMIS_MODULE_INACTIVE_FW_MINOR_OFFSET	0x81
+
 /* Supported Link Length (Page 1) */
 #define CMIS_SMF_LEN_OFFSET			0x84
 #define CMIS_OM5_LEN_OFFSET			0x85
-- 
2.45.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH ethtool-next 2/4] cmis: Print CDB messaging support advertisement
  2024-07-16 13:11 [PATCH ethtool-next 0/4] Add ability to flash modules' firmware Danielle Ratson
  2024-07-16 13:11 ` [PATCH ethtool-next 1/4] cmis: Print active and inactive firmware versions Danielle Ratson
@ 2024-07-16 13:11 ` Danielle Ratson
  2024-07-16 13:11 ` [PATCH ethtool-next 3/4] Update UAPI header copies Danielle Ratson
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Danielle Ratson @ 2024-07-16 13:11 UTC (permalink / raw)
  To: netdev; +Cc: mkubecek, mlxsw, Ido Schimmel, Danielle Ratson

From: Ido Schimmel <idosch@nvidia.com>

Parse and print CDB messaging support advertisement information to aid
in debugging CDB related problems. Example output:

 # ethtool -m swp23
 Identifier                                : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))
 [...]
 CDB instances                             : 1
 CDB background mode                       : Supported
 CDB EPL pages                             : 0
 CDB Maximum EPL RW length                 : 128
 CDB Maximum LPL RW length                 : 128
 CDB trigger method                        : Single write

Fields that are not used by the CDB code in the kernel are not printed,
but can be added in the future, when needed.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Danielle Ratson <danieller@nvidia.com>
---
 cmis.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 cmis.h | 11 ++++++++
 2 files changed, 91 insertions(+)

diff --git a/cmis.c b/cmis.c
index bbbbb47..6fe5dfb 100644
--- a/cmis.c
+++ b/cmis.c
@@ -928,6 +928,85 @@ static void cmis_show_fw_version(const struct cmis_memory_map *map)
 	cmis_show_fw_inactive_version(map);
 }
 
+static u8 cmis_cdb_instances_get(const struct cmis_memory_map *map)
+{
+	return (map->page_01h[CMIS_CDB_ADVER_OFFSET] &
+		CMIS_CDB_ADVER_INSTANCES_MASK) >> 6;
+}
+
+static bool cmis_cdb_is_supported(const struct cmis_memory_map *map)
+{
+	__u8 cdb_instances = cmis_cdb_instances_get(map);
+
+	/* Up to two CDB instances are supported. */
+	return cdb_instances == 1 || cdb_instances == 2;
+}
+
+static void cmis_show_cdb_instances(const struct cmis_memory_map *map)
+{
+	__u8 cdb_instances = cmis_cdb_instances_get(map);
+
+	printf("\t%-41s : %u\n", "CDB instances", cdb_instances);
+}
+
+static void cmis_show_cdb_mode(const struct cmis_memory_map *map)
+{
+	__u8 mode = map->page_01h[CMIS_CDB_ADVER_OFFSET] &
+		    CMIS_CDB_ADVER_MODE_MASK;
+
+	printf("\t%-41s : %s\n", "CDB background mode",
+	       mode ? "Supported" : "Not supported");
+}
+
+static void cmis_show_cdb_epl_pages(const struct cmis_memory_map *map)
+{
+	__u8 epl_pages = map->page_01h[CMIS_CDB_ADVER_OFFSET] &
+			 CMIS_CDB_ADVER_EPL_MASK;
+
+	printf("\t%-41s : %u\n", "CDB EPL pages", epl_pages);
+}
+
+static void cmis_show_cdb_rw_len(const struct cmis_memory_map *map)
+{
+	__u16 rw_len = map->page_01h[CMIS_CDB_ADVER_RW_LEN_OFFSET];
+
+	/* Maximum read / write length for CDB EPL pages and the LPL page in
+	 * units of 8 bytes, in addition to the minimum 8 bytes.
+	 */
+	rw_len = (rw_len + 1) * 8;
+	printf("\t%-41s : %u\n", "CDB Maximum EPL RW length", rw_len);
+	printf("\t%-41s : %u\n", "CDB Maximum LPL RW length",
+	       rw_len > CMIS_PAGE_SIZE ? CMIS_PAGE_SIZE : rw_len);
+}
+
+static void cmis_show_cdb_trigger(const struct cmis_memory_map *map)
+{
+	__u8 trigger = map->page_01h[CMIS_CDB_ADVER_TRIGGER_OFFSET] &
+		       CMIS_CDB_ADVER_TRIGGER_MASK;
+
+	/* Whether a CDB command can be triggered in a single write to the LPL
+	 * page, or by multiple writes ending with the writing of the CDB
+	 * Command Code (CMDID).
+	 */
+	printf("\t%-41s : %s\n", "CDB trigger method",
+	       trigger ? "Single write" : "Multiple writes");
+}
+
+/* Print CDB messaging support advertisement. Relevant documents:
+ * [1] CMIS Rev. 5, page 133, section 8.4.11
+ */
+static void cmis_show_cdb_adver(const struct cmis_memory_map *map)
+{
+	if (!map->page_01h || !cmis_cdb_is_supported(map))
+		return;
+
+	cmis_show_cdb_instances(map);
+	cmis_show_cdb_mode(map);
+	cmis_show_cdb_epl_pages(map);
+	cmis_show_cdb_rw_len(map);
+	cmis_show_cdb_trigger(map);
+}
+
 static void cmis_show_all_common(const struct cmis_memory_map *map)
 {
 	cmis_show_identifier(map);
@@ -945,6 +1024,7 @@ static void cmis_show_all_common(const struct cmis_memory_map *map)
 	cmis_show_mod_lvl_controls(map);
 	cmis_show_dom(map);
 	cmis_show_fw_version(map);
+	cmis_show_cdb_adver(map);
 }
 
 static void cmis_memory_map_init_buf(struct cmis_memory_map *map,
diff --git a/cmis.h b/cmis.h
index 3015c54..cee2a38 100644
--- a/cmis.h
+++ b/cmis.h
@@ -191,6 +191,17 @@
 #define CMIS_SIG_INTEG_TX_OFFSET		0xA1
 #define CMIS_SIG_INTEG_RX_OFFSET		0xA2
 
+/* CDB Messaging Support Advertisement */
+#define CMIS_CDB_ADVER_OFFSET			0xA3
+#define CMIS_CDB_ADVER_INSTANCES_MASK		0xC0
+#define CMIS_CDB_ADVER_MODE_MASK		0x20
+#define CMIS_CDB_ADVER_EPL_MASK			0x0F
+
+#define CMIS_CDB_ADVER_RW_LEN_OFFSET		0xA4
+
+#define CMIS_CDB_ADVER_TRIGGER_OFFSET		0xA5
+#define CMIS_CDB_ADVER_TRIGGER_MASK		0x80
+
 /*-----------------------------------------------------------------------
  * Upper Memory Page 0x02: Optional Page that informs about module-defined
  * thresholds for module-level and lane-specific threshold crossing monitors.
-- 
2.45.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH ethtool-next 3/4] Update UAPI header copies
  2024-07-16 13:11 [PATCH ethtool-next 0/4] Add ability to flash modules' firmware Danielle Ratson
  2024-07-16 13:11 ` [PATCH ethtool-next 1/4] cmis: Print active and inactive firmware versions Danielle Ratson
  2024-07-16 13:11 ` [PATCH ethtool-next 2/4] cmis: Print CDB messaging support advertisement Danielle Ratson
@ 2024-07-16 13:11 ` Danielle Ratson
  2024-07-16 13:11 ` [PATCH ethtool-next 4/4] ethtool: Add ability to flash transceiver modules' firmware Danielle Ratson
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Danielle Ratson @ 2024-07-16 13:11 UTC (permalink / raw)
  To: netdev; +Cc: mkubecek, mlxsw, Danielle Ratson

Update to kernel commit 46fb3ba95b93.

Signed-off-by: Danielle Ratson <danieller@nvidia.com>
---
 uapi/linux/ethtool.h         | 18 ++++++++++++++++++
 uapi/linux/ethtool_netlink.h | 19 +++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/uapi/linux/ethtool.h b/uapi/linux/ethtool.h
index bcec30c..d6e3652 100644
--- a/uapi/linux/ethtool.h
+++ b/uapi/linux/ethtool.h
@@ -875,6 +875,24 @@ enum ethtool_mm_verify_status {
 	ETHTOOL_MM_VERIFY_STATUS_DISABLED,
 };
 
+/**
+ * enum ethtool_module_fw_flash_status - plug-in module firmware flashing status
+ * @ETHTOOL_MODULE_FW_FLASH_STATUS_STARTED: The firmware flashing process has
+ *	started.
+ * @ETHTOOL_MODULE_FW_FLASH_STATUS_IN_PROGRESS: The firmware flashing process
+ *	is in progress.
+ * @ETHTOOL_MODULE_FW_FLASH_STATUS_COMPLETED: The firmware flashing process was
+ *	completed successfully.
+ * @ETHTOOL_MODULE_FW_FLASH_STATUS_ERROR: The firmware flashing process was
+ *	stopped due to an error.
+ */
+enum ethtool_module_fw_flash_status {
+	ETHTOOL_MODULE_FW_FLASH_STATUS_STARTED = 1,
+	ETHTOOL_MODULE_FW_FLASH_STATUS_IN_PROGRESS,
+	ETHTOOL_MODULE_FW_FLASH_STATUS_COMPLETED,
+	ETHTOOL_MODULE_FW_FLASH_STATUS_ERROR,
+};
+
 /**
  * struct ethtool_gstrings - string set for data tagging
  * @cmd: Command number = %ETHTOOL_GSTRINGS
diff --git a/uapi/linux/ethtool_netlink.h b/uapi/linux/ethtool_netlink.h
index c0be6e5..61af33b 100644
--- a/uapi/linux/ethtool_netlink.h
+++ b/uapi/linux/ethtool_netlink.h
@@ -57,6 +57,7 @@ enum {
 	ETHTOOL_MSG_PLCA_GET_STATUS,
 	ETHTOOL_MSG_MM_GET,
 	ETHTOOL_MSG_MM_SET,
+	ETHTOOL_MSG_MODULE_FW_FLASH_ACT,
 
 	/* add new constants above here */
 	__ETHTOOL_MSG_USER_CNT,
@@ -109,6 +110,7 @@ enum {
 	ETHTOOL_MSG_PLCA_NTF,
 	ETHTOOL_MSG_MM_GET_REPLY,
 	ETHTOOL_MSG_MM_NTF,
+	ETHTOOL_MSG_MODULE_FW_FLASH_NTF,
 
 	/* add new constants above here */
 	__ETHTOOL_MSG_KERNEL_CNT,
@@ -996,6 +998,23 @@ enum {
 	ETHTOOL_A_MM_MAX = (__ETHTOOL_A_MM_CNT - 1)
 };
 
+/* MODULE_FW_FLASH */
+
+enum {
+	ETHTOOL_A_MODULE_FW_FLASH_UNSPEC,
+	ETHTOOL_A_MODULE_FW_FLASH_HEADER,		/* nest - _A_HEADER_* */
+	ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME,		/* string */
+	ETHTOOL_A_MODULE_FW_FLASH_PASS,			/* u32 */
+	ETHTOOL_A_MODULE_FW_FLASH_STATUS,		/* u32 */
+	ETHTOOL_A_MODULE_FW_FLASH_STATUS_MSG,		/* string */
+	ETHTOOL_A_MODULE_FW_FLASH_DONE,			/* uint */
+	ETHTOOL_A_MODULE_FW_FLASH_TOTAL,		/* uint */
+
+	/* add new constants above here */
+	__ETHTOOL_A_MODULE_FW_FLASH_CNT,
+	ETHTOOL_A_MODULE_FW_FLASH_MAX = (__ETHTOOL_A_MODULE_FW_FLASH_CNT - 1)
+};
+
 /* generic netlink info */
 #define ETHTOOL_GENL_NAME "ethtool"
 #define ETHTOOL_GENL_VERSION 1
-- 
2.45.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH ethtool-next 4/4] ethtool: Add ability to flash transceiver modules' firmware
  2024-07-16 13:11 [PATCH ethtool-next 0/4] Add ability to flash modules' firmware Danielle Ratson
                   ` (2 preceding siblings ...)
  2024-07-16 13:11 ` [PATCH ethtool-next 3/4] Update UAPI header copies Danielle Ratson
@ 2024-07-16 13:11 ` Danielle Ratson
  2024-07-30 10:52 ` [PATCH ethtool-next 0/4] Add ability to flash " Danielle Ratson
  2024-08-09 23:06 ` Michal Kubecek
  5 siblings, 0 replies; 8+ messages in thread
From: Danielle Ratson @ 2024-07-16 13:11 UTC (permalink / raw)
  To: netdev; +Cc: mkubecek, mlxsw, Danielle Ratson, Ido Schimmel

Add ability to flash transceiver modules' firmware over netlink.

Example output:

 # ethtool --flash-module-firmware eth0 file test.img

Transceiver module firmware flashing started for device swp23
Transceiver module firmware flashing in progress for device swp23
Progress: 99%
Transceiver module firmware flashing completed for device swp23

Co-developed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Danielle Ratson <danieller@nvidia.com>
---
 ethtool.8.in                  |  29 ++++++
 ethtool.c                     |   7 ++
 netlink/desc-ethtool.c        |  13 +++
 netlink/extapi.h              |   2 +
 netlink/module.c              | 183 ++++++++++++++++++++++++++++++++++
 netlink/netlink.h             |  16 +++
 netlink/prettymsg.c           |   5 +
 netlink/prettymsg.h           |   2 +
 shell-completion/bash/ethtool |  27 +++++
 9 files changed, 284 insertions(+)

diff --git a/ethtool.8.in b/ethtool.8.in
index 8090f0f..bfcaca8 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -536,6 +536,13 @@ ethtool \- query or control network driver and hardware settings
 .I devname
 .RB [ podl\-pse\-admin\-control
 .BR enable | disable ]
+.HP
+.B ethtool \-\-flash\-module\-firmware
+.I devname
+.BI file
+.IR FILE
+.RB [ pass
+.IR PASS ]
 .
 .\" Adjust lines (i.e. full justification) and hyphenate.
 .ad
@@ -1772,6 +1779,28 @@ Set Power Sourcing Equipment (PSE) parameters.
 This parameter manages PoDL PSE Admin operations in accordance with the IEEE
 802.3-2018 30.15.1.2.1 (acPoDLPSEAdminControl) specification.
 
+.RE
+.TP
+.B \-\-flash\-module\-firmware
+Flash the transceiver module's firmware. The firmware update process is
+composed from three logical steps. Downloading a firmware image to the
+transceiver module, running the image and committing the image so that it is
+run upon reset. When flash command is given, the firmware update process is
+performed in its entirety in that order.
+.RS 4
+.TP
+.BI file \ FILE
+Specifies the filename of the transceiver module firmware image. The firmware
+must first be installed in one of the directories where the kernel firmware
+loader or firmware agent will look, such as /lib/firmware. The firmware image
+is downloaded to the transceiver module, validated, run and committed.
+.RE
+.RS 4
+.TP
+.BI pass \ PASS
+Optional transceiver module password that might be required as part of the
+transceiver module firmware update process.
+
 .SH BUGS
 Not supported (in part or whole) on all network drivers.
 .SH AUTHOR
diff --git a/ethtool.c b/ethtool.c
index d85a57a..0a6a9f9 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -6218,6 +6218,13 @@ static const struct option args[] = {
 		.xhelp	= "		[ podl-pse-admin-control enable|disable ]\n"
 			  "		[ c33-pse-admin-control enable|disable ]\n"
 	},
+	{
+		.opts	= "--flash-module-firmware",
+		.nlfunc	= nl_flash_module_fw,
+		.help	= "Flash transceiver module firmware",
+		.xhelp	= "		file FILE\n"
+			  "		[ pass PASS ]\n"
+	},
 	{
 		.opts	= "-h|--help",
 		.no_dev	= true,
diff --git a/netlink/desc-ethtool.c b/netlink/desc-ethtool.c
index 661de26..bd5cbc1 100644
--- a/netlink/desc-ethtool.c
+++ b/netlink/desc-ethtool.c
@@ -496,6 +496,17 @@ static const struct pretty_nla_desc __mm_desc[] = {
 	NLATTR_DESC_NESTED(ETHTOOL_A_MM_STATS, mm_stat),
 };
 
+static const struct pretty_nla_desc __module_fw_flash_desc[] = {
+	NLATTR_DESC_INVALID(ETHTOOL_A_MODULE_FW_FLASH_UNSPEC),
+	NLATTR_DESC_NESTED(ETHTOOL_A_MODULE_FW_FLASH_HEADER, header),
+	NLATTR_DESC_STRING(ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME),
+	NLATTR_DESC_U32(ETHTOOL_A_MODULE_FW_FLASH_PASS),
+	NLATTR_DESC_U32(ETHTOOL_A_MODULE_FW_FLASH_STATUS),
+	NLATTR_DESC_STRING(ETHTOOL_A_MODULE_FW_FLASH_STATUS_MSG),
+	NLATTR_DESC_UINT(ETHTOOL_A_MODULE_FW_FLASH_DONE),
+	NLATTR_DESC_UINT(ETHTOOL_A_MODULE_FW_FLASH_TOTAL),
+};
+
 const struct pretty_nlmsg_desc ethnl_umsg_desc[] = {
 	NLMSG_DESC_INVALID(ETHTOOL_MSG_USER_NONE),
 	NLMSG_DESC(ETHTOOL_MSG_STRSET_GET, strset),
@@ -541,6 +552,7 @@ const struct pretty_nlmsg_desc ethnl_umsg_desc[] = {
 	NLMSG_DESC(ETHTOOL_MSG_PLCA_GET_STATUS, plca),
 	NLMSG_DESC(ETHTOOL_MSG_MM_GET, mm),
 	NLMSG_DESC(ETHTOOL_MSG_MM_SET, mm),
+	NLMSG_DESC(ETHTOOL_MSG_MODULE_FW_FLASH_ACT, module_fw_flash),
 };
 
 const unsigned int ethnl_umsg_n_desc = ARRAY_SIZE(ethnl_umsg_desc);
@@ -590,6 +602,7 @@ const struct pretty_nlmsg_desc ethnl_kmsg_desc[] = {
 	NLMSG_DESC(ETHTOOL_MSG_PLCA_NTF, plca),
 	NLMSG_DESC(ETHTOOL_MSG_MM_GET_REPLY, mm),
 	NLMSG_DESC(ETHTOOL_MSG_MM_NTF, mm),
+	NLMSG_DESC(ETHTOOL_MSG_MODULE_FW_FLASH_NTF, module_fw_flash),
 };
 
 const unsigned int ethnl_kmsg_n_desc = ARRAY_SIZE(ethnl_kmsg_desc);
diff --git a/netlink/extapi.h b/netlink/extapi.h
index e2d6b71..c882295 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -55,6 +55,7 @@ int nl_get_mm(struct cmd_context *ctx);
 int nl_set_mm(struct cmd_context *ctx);
 int nl_gpse(struct cmd_context *ctx);
 int nl_spse(struct cmd_context *ctx);
+int nl_flash_module_fw(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
 
@@ -130,6 +131,7 @@ nl_get_eeprom_page(struct cmd_context *ctx __maybe_unused,
 #define nl_set_mm		NULL
 #define nl_gpse			NULL
 #define nl_spse			NULL
+#define nl_flash_module_fw	NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/module.c b/netlink/module.c
index 54aa6d0..42def91 100644
--- a/netlink/module.c
+++ b/netlink/module.c
@@ -10,6 +10,7 @@
 #include <inttypes.h>
 #include <string.h>
 #include <stdio.h>
+#include <stdarg.h>
 
 #include "../internal.h"
 #include "../common.h"
@@ -177,3 +178,185 @@ int nl_smodule(struct cmd_context *ctx)
 	else
 		return nlctx->exit_code ?: 83;
 }
+
+/* MODULE_FW_FLASH_ACT */
+
+static const struct param_parser flash_module_fw_params[] = {
+	{
+		.arg		= "file",
+		.type		= ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME,
+		.handler	= nl_parse_string,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "pass",
+		.type		= ETHTOOL_A_MODULE_FW_FLASH_PASS,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{}
+};
+
+struct module_flash_context {
+	uint8_t breakout:1,
+		first:1;
+};
+
+static int module_fw_flash_ntf_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct nlattr *tb[ETHTOOL_A_MODULE_FW_FLASH_MAX + 1] = {};
+	struct module_flash_context *mfctx;
+	struct nl_context *nlctx = data;
+	DECLARE_ATTR_TB_INFO(tb);
+	u8 status = 0;
+	int ret;
+
+	mfctx = nlctx->cmd_private;
+
+	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+	if (ret < 0)
+		return MNL_CB_OK;
+	nlctx->devname = get_dev_name(tb[ETHTOOL_A_MODULE_FW_FLASH_HEADER]);
+	if (!dev_ok(nlctx))
+		return MNL_CB_OK;
+
+	if (tb[ETHTOOL_A_MODULE_FW_FLASH_STATUS])
+		status = mnl_attr_get_u32(tb[ETHTOOL_A_MODULE_FW_FLASH_STATUS]);
+
+	switch (status) {
+	case ETHTOOL_MODULE_FW_FLASH_STATUS_STARTED:
+		print_string(PRINT_FP, NULL,
+			     "Transceiver module firmware flashing started for device %s\n",
+			     nlctx->devname);
+		break;
+	case ETHTOOL_MODULE_FW_FLASH_STATUS_IN_PROGRESS:
+		if (mfctx->first) {
+			print_string(PRINT_FP, NULL,
+				     "Transceiver module firmware flashing in progress for device %s\n",
+				     nlctx->devname);
+			mfctx->first = 0;
+		}
+		break;
+	case ETHTOOL_MODULE_FW_FLASH_STATUS_COMPLETED:
+		print_nl();
+		print_string(PRINT_FP, NULL,
+			     "Transceiver module firmware flashing completed for device %s\n",
+			     nlctx->devname);
+		mfctx->breakout = 1;
+		break;
+	case ETHTOOL_MODULE_FW_FLASH_STATUS_ERROR:
+		print_nl();
+		print_string(PRINT_FP, NULL,
+			     "Transceiver module firmware flashing encountered an error for device %s\n",
+			     nlctx->devname);
+		mfctx->breakout = 1;
+		break;
+	default:
+		break;
+	}
+
+	if (tb[ETHTOOL_A_MODULE_FW_FLASH_STATUS_MSG]) {
+		const char *status_msg;
+
+		status_msg = mnl_attr_get_str(tb[ETHTOOL_A_MODULE_FW_FLASH_STATUS_MSG]);
+		print_string(PRINT_FP, NULL, "Status message: %s\n", status_msg);
+	}
+
+	if (tb[ETHTOOL_A_MODULE_FW_FLASH_DONE] &&
+	    tb[ETHTOOL_A_MODULE_FW_FLASH_TOTAL]) {
+		uint64_t done, total;
+
+		done = attr_get_uint(tb[ETHTOOL_A_MODULE_FW_FLASH_DONE]);
+		total = attr_get_uint(tb[ETHTOOL_A_MODULE_FW_FLASH_TOTAL]);
+
+		if (total)
+			print_u64(PRINT_FP, NULL, "Progress: %"PRIu64"%\r",
+				  done * 100 / total);
+	}
+
+	return MNL_CB_OK;
+}
+
+static int nl_flash_module_fw_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct genlmsghdr *ghdr = (const struct genlmsghdr *)(nlhdr + 1);
+
+	if (ghdr->cmd != ETHTOOL_MSG_MODULE_FW_FLASH_NTF)
+		return MNL_CB_OK;
+
+	module_fw_flash_ntf_cb(nlhdr, data);
+
+	return MNL_CB_STOP;
+}
+
+static int nl_flash_module_fw_process_ntf(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct module_flash_context *mfctx;
+	struct nl_socket *nlsk;
+	int ret;
+
+	nlsk = nlctx->ethnl_socket;
+
+	mfctx = malloc(sizeof(struct module_flash_context));
+	if (!mfctx)
+		return -ENOMEM;
+
+	mfctx->breakout = 0;
+	mfctx->first = 1;
+	nlctx->cmd_private = mfctx;
+
+	while (!mfctx->breakout) {
+		ret = nlsock_process_reply(nlsk, nl_flash_module_fw_cb, nlctx);
+		if (ret)
+			goto out;
+		nlsk->seq++;
+	}
+
+out:
+	free(mfctx);
+	return ret;
+}
+
+int nl_flash_module_fw(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_msg_buff *msgbuff;
+	struct nl_socket *nlsk;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_MODULE_FW_FLASH_ACT, false))
+		return -EOPNOTSUPP;
+	if (!ctx->argc) {
+		fprintf(stderr, "ethtool (--flash-module-firmware): parameters missing\n");
+		return 1;
+	}
+
+	nlctx->cmd = "--flash-module-firmware";
+	nlctx->argp = ctx->argp;
+	nlctx->argc = ctx->argc;
+	nlctx->devname = ctx->devname;
+	nlsk = nlctx->ethnl_socket;
+	msgbuff = &nlsk->msgbuff;
+
+	ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_MODULE_FW_FLASH_ACT,
+		       NLM_F_REQUEST | NLM_F_ACK);
+	if (ret < 0)
+		return 2;
+	if (ethnla_fill_header(msgbuff, ETHTOOL_A_MODULE_FW_FLASH_HEADER,
+			       ctx->devname, 0))
+		return -EMSGSIZE;
+
+	ret = nl_parser(nlctx, flash_module_fw_params, NULL, PARSER_GROUP_NONE,
+			NULL);
+	if (ret < 0)
+		return 1;
+
+	ret = nlsock_sendmsg(nlsk, NULL);
+	if (ret < 0)
+		fprintf(stderr, "Cannot flash transceiver module firmware\n");
+	else
+		ret = nl_flash_module_fw_process_ntf(ctx);
+
+	return ret;
+}
diff --git a/netlink/netlink.h b/netlink/netlink.h
index 1274a3b..92a336e 100644
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -175,4 +175,20 @@ static inline int netlink_init_rtnl_socket(struct nl_context *nlctx)
 	return nlsock_init(nlctx, &nlctx->rtnl_socket, NETLINK_ROUTE);
 }
 
+static inline uint64_t attr_get_uint(const struct nlattr *attr)
+{
+	switch (mnl_attr_get_payload_len(attr)) {
+	case sizeof(uint8_t):
+		return mnl_attr_get_u8(attr);
+	case sizeof(uint16_t):
+		return mnl_attr_get_u16(attr);
+	case sizeof(uint32_t):
+		return mnl_attr_get_u32(attr);
+	case sizeof(uint64_t):
+		return mnl_attr_get_u64(attr);
+	}
+
+	return -1ULL;
+}
+
 #endif /* ETHTOOL_NETLINK_INT_H__ */
diff --git a/netlink/prettymsg.c b/netlink/prettymsg.c
index fbf684f..0eb4447 100644
--- a/netlink/prettymsg.c
+++ b/netlink/prettymsg.c
@@ -15,6 +15,8 @@
 #include <linux/if_link.h>
 #include <libmnl/libmnl.h>
 
+#include "../internal.h"
+#include "netlink.h"
 #include "prettymsg.h"
 
 #define __INDENT 4
@@ -114,6 +116,9 @@ static int pretty_print_attr(const struct nlattr *attr,
 	case NLA_U64:
 		printf("%" PRIu64, mnl_attr_get_u64(attr));
 		break;
+	case NLA_UINT:
+		printf("%" PRIu64, attr_get_uint(attr));
+		break;
 	case NLA_X8:
 		printf("0x%02x", mnl_attr_get_u8(attr));
 		break;
diff --git a/netlink/prettymsg.h b/netlink/prettymsg.h
index 8ca1db3..ef8e73f 100644
--- a/netlink/prettymsg.h
+++ b/netlink/prettymsg.h
@@ -18,6 +18,7 @@ enum pretty_nla_format {
 	NLA_U16,
 	NLA_U32,
 	NLA_U64,
+	NLA_UINT,
 	NLA_X8,
 	NLA_X16,
 	NLA_X32,
@@ -67,6 +68,7 @@ struct pretty_nlmsg_desc {
 #define NLATTR_DESC_U16(_name)		NLATTR_DESC(_name, NLA_U16)
 #define NLATTR_DESC_U32(_name)		NLATTR_DESC(_name, NLA_U32)
 #define NLATTR_DESC_U64(_name)		NLATTR_DESC(_name, NLA_U64)
+#define NLATTR_DESC_UINT(_name)		NLATTR_DESC(_name, NLA_UINT)
 #define NLATTR_DESC_X8(_name)		NLATTR_DESC(_name, NLA_X8)
 #define NLATTR_DESC_X16(_name)		NLATTR_DESC(_name, NLA_X16)
 #define NLATTR_DESC_X32(_name)		NLATTR_DESC(_name, NLA_X32)
diff --git a/shell-completion/bash/ethtool b/shell-completion/bash/ethtool
index f7d6aed..3c775a1 100644
--- a/shell-completion/bash/ethtool
+++ b/shell-completion/bash/ethtool
@@ -1164,6 +1164,32 @@ _ethtool_set_module()
 	COMPREPLY=( $( compgen -W "${!settings[*]}" -- "$cur" ) )
 }
 
+# Completion for ethtool --flash-module-firmware
+_ethtool_flash_module_firmware()
+{
+	local -A settings=(
+		[file]=1
+		[pass]=1
+	)
+
+	case "$prev" in
+		file)
+			_ethtool_firmware
+			return ;;
+		pass)
+			# Number
+			return ;;
+	esac
+
+	# Remove settings which have been seen
+	local word
+	for word in "${words[@]:3:${#words[@]}-4}"; do
+		unset "settings[$word]"
+	done
+
+	COMPREPLY=( $( compgen -W "${!settings[*]}" -- "$cur" ) )
+}
+
 # Complete any ethtool command
 _ethtool()
 {
@@ -1217,6 +1243,7 @@ _ethtool()
 		[--test]=test
 		[--set-module]=set_module
 		[--show-module]=devname
+		[--flash-module-firmware]=flash_module_firmware
 	)
 	local -A other_funcs=(
 		[--config-ntuple]=config_nfc
-- 
2.45.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* RE: [PATCH ethtool-next 0/4] Add ability to flash modules' firmware
  2024-07-16 13:11 [PATCH ethtool-next 0/4] Add ability to flash modules' firmware Danielle Ratson
                   ` (3 preceding siblings ...)
  2024-07-16 13:11 ` [PATCH ethtool-next 4/4] ethtool: Add ability to flash transceiver modules' firmware Danielle Ratson
@ 2024-07-30 10:52 ` Danielle Ratson
  2024-08-09 23:06 ` Michal Kubecek
  5 siblings, 0 replies; 8+ messages in thread
From: Danielle Ratson @ 2024-07-30 10:52 UTC (permalink / raw)
  To: netdev@vger.kernel.org, mkubecek@suse.cz; +Cc: mlxsw

Hi,

I haven’t gotten any comment on this patchset yet, could you please take a look at it?

Thanks,
Danielle

> -----Original Message-----
> From: Danielle Ratson <danieller@nvidia.com>
> Sent: Tuesday, 16 July 2024 16:11
> To: netdev@vger.kernel.org
> Cc: mkubecek@suse.cz; mlxsw <mlxsw@nvidia.com>; Danielle Ratson
> <danieller@nvidia.com>
> Subject: [PATCH ethtool-next 0/4] Add ability to flash modules' firmware
> 
> CMIS compliant modules such as QSFP-DD might be running a firmware that
> can be updated in a vendor-neutral way by exchanging messages between the
> host and the module as described in section 7.2.2 of revision
> 4.0 of the CMIS standard.
> 
> Add ability to flash transceiver modules' firmware over netlink.
> 
> Example output:
> 
>  # ethtool --flash-module-firmware eth0 file test.img
> 
> Transceiver module firmware flashing started for device swp23 Transceiver
> module firmware flashing in progress for device swp23
> Progress: 99%
> Transceiver module firmware flashing completed for device swp23
> 
> In addition, add some firmware and CDB messaging information to ethtool's
> output for observability.
> 
> Patchset overview:
> Patches #1-#2: adds firmware info to ethtool's output.
> Patch #3: updates headers.
> Patch #4: adds ability to flash modules' firmware.
> 
> Danielle Ratson (2):
>   Update UAPI header copies
>   ethtool: Add ability to flash transceiver modules' firmware
> 
> Ido Schimmel (2):
>   cmis: Print active and inactive firmware versions
>   cmis: Print CDB messaging support advertisement
> 
>  cmis.c                        | 125 +++++++++++++++++++++++
>  cmis.h                        |  19 ++++
>  ethtool.8.in                  |  29 ++++++
>  ethtool.c                     |   7 ++
>  netlink/desc-ethtool.c        |  13 +++
>  netlink/extapi.h              |   2 +
>  netlink/module.c              | 183 ++++++++++++++++++++++++++++++++++
>  netlink/netlink.h             |  16 +++
>  netlink/prettymsg.c           |   5 +
>  netlink/prettymsg.h           |   2 +
>  shell-completion/bash/ethtool |  27 +++++
>  uapi/linux/ethtool.h          |  18 ++++
>  uapi/linux/ethtool_netlink.h  |  19 ++++
>  13 files changed, 465 insertions(+)
> 
> --
> 2.45.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH ethtool-next 0/4] Add ability to flash modules' firmware
  2024-07-16 13:11 [PATCH ethtool-next 0/4] Add ability to flash modules' firmware Danielle Ratson
                   ` (4 preceding siblings ...)
  2024-07-30 10:52 ` [PATCH ethtool-next 0/4] Add ability to flash " Danielle Ratson
@ 2024-08-09 23:06 ` Michal Kubecek
  2024-08-11  8:22   ` Danielle Ratson
  5 siblings, 1 reply; 8+ messages in thread
From: Michal Kubecek @ 2024-08-09 23:06 UTC (permalink / raw)
  To: Danielle Ratson; +Cc: netdev, mlxsw

[-- Attachment #1: Type: text/plain, Size: 1361 bytes --]

On Tue, Jul 16, 2024 at 04:11:08PM +0300, Danielle Ratson wrote:
> CMIS compliant modules such as QSFP-DD might be running a firmware that
> can be updated in a vendor-neutral way by exchanging messages between
> the host and the module as described in section 7.2.2 of revision
> 4.0 of the CMIS standard.
> 
> Add ability to flash transceiver modules' firmware over netlink.
> 
> Example output:
> 
>  # ethtool --flash-module-firmware eth0 file test.img
> 
> Transceiver module firmware flashing started for device swp23
> Transceiver module firmware flashing in progress for device swp23
> Progress: 99%
> Transceiver module firmware flashing completed for device swp23
> 
> In addition, add some firmware and CDB messaging information to
> ethtool's output for observability.
> 
> Patchset overview:
> Patches #1-#2: adds firmware info to ethtool's output.
> Patch #3: updates headers.
> Patch #4: adds ability to flash modules' firmware.

Hello,

this series seems to be based on slightly different version of the kernel
counterpart than what was merged into mainline. One difference I noticed is
that this series uses ETHTOOL_A_MODULE_FW_FLASH_PASS while kernel headers
use ETHTOOL_A_MODULE_FW_FLASH_PASSWORD; but I'm not sure if it's the only
difference.

Could you please check it and update what is needed?

Michal

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [PATCH ethtool-next 0/4] Add ability to flash modules' firmware
  2024-08-09 23:06 ` Michal Kubecek
@ 2024-08-11  8:22   ` Danielle Ratson
  0 siblings, 0 replies; 8+ messages in thread
From: Danielle Ratson @ 2024-08-11  8:22 UTC (permalink / raw)
  To: Michal Kubecek; +Cc: netdev@vger.kernel.org, mlxsw

> From: Michal Kubecek <mkubecek@suse.cz>
> Sent: Saturday, 10 August 2024 2:07
> To: Danielle Ratson <danieller@nvidia.com>
> Cc: netdev@vger.kernel.org; mlxsw <mlxsw@nvidia.com>
> Subject: Re: [PATCH ethtool-next 0/4] Add ability to flash modules' firmware
> 
> On Tue, Jul 16, 2024 at 04:11:08PM +0300, Danielle Ratson wrote:
> > CMIS compliant modules such as QSFP-DD might be running a firmware
> > that can be updated in a vendor-neutral way by exchanging messages
> > between the host and the module as described in section 7.2.2 of
> > revision
> > 4.0 of the CMIS standard.
> >
> > Add ability to flash transceiver modules' firmware over netlink.
> >
> > Example output:
> >
> >  # ethtool --flash-module-firmware eth0 file test.img
> >
> > Transceiver module firmware flashing started for device swp23
> > Transceiver module firmware flashing in progress for device swp23
> > Progress: 99%
> > Transceiver module firmware flashing completed for device swp23
> >
> > In addition, add some firmware and CDB messaging information to
> > ethtool's output for observability.
> >
> > Patchset overview:
> > Patches #1-#2: adds firmware info to ethtool's output.
> > Patch #3: updates headers.
> > Patch #4: adds ability to flash modules' firmware.
> 
> Hello,
> 
> this series seems to be based on slightly different version of the kernel
> counterpart than what was merged into mainline. One difference I noticed is
> that this series uses ETHTOOL_A_MODULE_FW_FLASH_PASS while kernel
> headers use ETHTOOL_A_MODULE_FW_FLASH_PASSWORD; but I'm not sure
> if it's the only difference.
> 
> Could you please check it and update what is needed?
> 
> Michal

Hi Michal,

Thank you for your feedback.

Ill fix it in a new version, there is no other difference between the versions that I could find.

Thanks,
Danielle

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2024-08-11  8:22 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-16 13:11 [PATCH ethtool-next 0/4] Add ability to flash modules' firmware Danielle Ratson
2024-07-16 13:11 ` [PATCH ethtool-next 1/4] cmis: Print active and inactive firmware versions Danielle Ratson
2024-07-16 13:11 ` [PATCH ethtool-next 2/4] cmis: Print CDB messaging support advertisement Danielle Ratson
2024-07-16 13:11 ` [PATCH ethtool-next 3/4] Update UAPI header copies Danielle Ratson
2024-07-16 13:11 ` [PATCH ethtool-next 4/4] ethtool: Add ability to flash transceiver modules' firmware Danielle Ratson
2024-07-30 10:52 ` [PATCH ethtool-next 0/4] Add ability to flash " Danielle Ratson
2024-08-09 23:06 ` Michal Kubecek
2024-08-11  8:22   ` Danielle Ratson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).