* [PATCH ethtool-next v2 0/3] Add ability to flash modules' firmware
@ 2024-08-11 11:59 Danielle Ratson
2024-08-11 11:59 ` [PATCH ethtool-next v2 1/3] cmis: Print active and inactive firmware versions Danielle Ratson
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Danielle Ratson @ 2024-08-11 11:59 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: adds ability to flash modules' firmware.
v2:
* Remove patch #3 of updating header, since it was already done.
* s/ETHTOOL_A_MODULE_FW_FLASH_PASS/ETHTOOL_A_MODULE_FW_FLASH_PASSWORD
Danielle Ratson (1):
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 +++++
11 files changed, 428 insertions(+)
--
2.45.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH ethtool-next v2 1/3] cmis: Print active and inactive firmware versions
2024-08-11 11:59 [PATCH ethtool-next v2 0/3] Add ability to flash modules' firmware Danielle Ratson
@ 2024-08-11 11:59 ` Danielle Ratson
2024-08-11 11:59 ` [PATCH ethtool-next v2 2/3] cmis: Print CDB messaging support advertisement Danielle Ratson
2024-08-11 11:59 ` [PATCH ethtool-next v2 3/3] ethtool: Add ability to flash transceiver modules' firmware Danielle Ratson
2 siblings, 0 replies; 4+ messages in thread
From: Danielle Ratson @ 2024-08-11 11:59 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] 4+ messages in thread
* [PATCH ethtool-next v2 2/3] cmis: Print CDB messaging support advertisement
2024-08-11 11:59 [PATCH ethtool-next v2 0/3] Add ability to flash modules' firmware Danielle Ratson
2024-08-11 11:59 ` [PATCH ethtool-next v2 1/3] cmis: Print active and inactive firmware versions Danielle Ratson
@ 2024-08-11 11:59 ` Danielle Ratson
2024-08-11 11:59 ` [PATCH ethtool-next v2 3/3] ethtool: Add ability to flash transceiver modules' firmware Danielle Ratson
2 siblings, 0 replies; 4+ messages in thread
From: Danielle Ratson @ 2024-08-11 11:59 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] 4+ messages in thread
* [PATCH ethtool-next v2 3/3] ethtool: Add ability to flash transceiver modules' firmware
2024-08-11 11:59 [PATCH ethtool-next v2 0/3] Add ability to flash modules' firmware Danielle Ratson
2024-08-11 11:59 ` [PATCH ethtool-next v2 1/3] cmis: Print active and inactive firmware versions Danielle Ratson
2024-08-11 11:59 ` [PATCH ethtool-next v2 2/3] cmis: Print CDB messaging support advertisement Danielle Ratson
@ 2024-08-11 11:59 ` Danielle Ratson
2 siblings, 0 replies; 4+ messages in thread
From: Danielle Ratson @ 2024-08-11 11:59 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>
---
Notes:
v2:
* s/ETHTOOL_A_MODULE_FW_FLASH_PASS/ETHTOOL_A_MODULE_FW_FLASH_PASSWORD
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 c798cc2..89811b9 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 1e0a349..225f3aa 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -6236,6 +6236,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..5c0e1c6 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_PASSWORD),
+ 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..a92f272 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_PASSWORD,
+ .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 4a4b68b..ad2a787 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] 4+ messages in thread
end of thread, other threads:[~2024-08-11 12:00 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-11 11:59 [PATCH ethtool-next v2 0/3] Add ability to flash modules' firmware Danielle Ratson
2024-08-11 11:59 ` [PATCH ethtool-next v2 1/3] cmis: Print active and inactive firmware versions Danielle Ratson
2024-08-11 11:59 ` [PATCH ethtool-next v2 2/3] cmis: Print CDB messaging support advertisement Danielle Ratson
2024-08-11 11:59 ` [PATCH ethtool-next v2 3/3] ethtool: Add ability to flash transceiver modules' firmware 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).