From: Brett Creeley Add detailed component information display. This allows users to see individual firmware components, their versions, and update status via devlink info. Components are marked as fixed, running, or stored based on their flags. Example output: $ devlink dev info pci/0000:b5:00.0 ... versions: running: fw.goldfw 1.2.3 fw.mainfwa 1.2.4 fw.mainfwb 1.2.3 Signed-off-by: Brett Creeley --- drivers/net/ethernet/amd/pds_core/devlink.c | 75 ++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c index 7f44e1a8d4fd..c519fde45d71 100644 --- a/drivers/net/ethernet/amd/pds_core/devlink.c +++ b/drivers/net/ethernet/amd/pds_core/devlink.c @@ -93,14 +93,61 @@ int pdsc_dl_flash_update(struct devlink *dl, return pdsc_firmware_update(pdsc, params, extack); } +static int pdsc_dl_component_info_get(struct devlink *dl, + struct devlink_info_req *req, + struct netlink_ext_ack *extack) +{ + struct pds_core_component_list_info *list_info; + struct pdsc *pdsc = devlink_priv(dl); + u8 num_components; + char buf[32]; + int err; + int i; + + err = pdsc_get_component_info(pdsc); + if (err) { + dev_err(pdsc->dev, "Failed to get component_info %pe", ERR_PTR(err)); + return err; + } + + list_info = &pdsc->fw_components; + num_components = min_t(u8, list_info->num_components, + le16_to_cpu(pdsc->dev_ident.max_fw_slots)); + for (i = 0; i < num_components; i++) { + enum devlink_info_version_type dl_ver_type = DEVLINK_INFO_VERSION_TYPE_NONE; + struct pds_core_fw_component_info *info = &list_info->info[i]; + u16 flags = le16_to_cpu(info->flags); + + snprintf(buf, sizeof(buf), "fw.%s", info->name); + if (flags & PDS_CORE_FW_COMPONENT_INFO_F_UPDATE_BY_NAME) + dl_ver_type = DEVLINK_INFO_VERSION_TYPE_COMPONENT; + + if (flags & PDS_CORE_FW_COMPONENT_INFO_F_FIXED) + err = devlink_info_version_fixed_put(req, buf, + info->version); + else if (flags & PDS_CORE_FW_COMPONENT_INFO_F_RUNNING) + err = devlink_info_version_running_put_ext(req, buf, + info->version, dl_ver_type); + else + err = devlink_info_version_stored_put_ext(req, buf, + info->version, dl_ver_type); + + if (err) + return err; + } + + return 0; +} + static char *fw_slotnames[] = { "fw.goldfw", "fw.mainfwa", "fw.mainfwb", }; -int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req, - struct netlink_ext_ack *extack) +static int pdsc_dl_fw_list_info_get(struct devlink *dl, + struct devlink_info_req *req, + struct netlink_ext_ack *extack) { union pds_core_dev_cmd cmd = { .fw_control.opcode = PDS_CORE_CMD_FW_CONTROL, @@ -132,11 +179,27 @@ int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req, return err; } - err = devlink_info_version_running_put(req, - DEVLINK_INFO_VERSION_GENERIC_FW, - pdsc->dev_info.fw_version); - if (err) + return devlink_info_version_running_put(req, + DEVLINK_INFO_VERSION_GENERIC_FW, + pdsc->dev_info.fw_version); +} + +int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req, + struct netlink_ext_ack *extack) +{ + struct pdsc *pdsc = devlink_priv(dl); + char buf[32]; + int err; + + if (pdsc->dev_ident.version >= PDS_CORE_IDENTITY_VERSION_2) + err = pdsc_dl_component_info_get(dl, req, extack); + else + err = pdsc_dl_fw_list_info_get(dl, req, extack); + if (err) { + dev_err(pdsc->dev, "Failed to get devlink info for identity version %u: %pe\n", + pdsc->dev_ident.version, ERR_PTR(err)); return err; + } snprintf(buf, sizeof(buf), "0x%x", pdsc->dev_info.asic_type); err = devlink_info_version_fixed_put(req, -- 2.43.0