diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_devlink.c')
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_devlink.c | 388 |
1 files changed, 282 insertions, 106 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c index 111d6bfe4222..cf685eeea198 100644 --- a/drivers/net/ethernet/intel/ice/ice_devlink.c +++ b/drivers/net/ethernet/intel/ice/ice_devlink.c @@ -6,129 +6,226 @@ #include "ice_devlink.h" #include "ice_fw_update.h" -static int ice_info_get_dsn(struct ice_pf *pf, char *buf, size_t len) +/* context for devlink info version reporting */ +struct ice_info_ctx { + char buf[128]; + struct ice_orom_info pending_orom; + struct ice_nvm_info pending_nvm; + struct ice_netlist_info pending_netlist; + struct ice_hw_dev_caps dev_caps; +}; + +/* The following functions are used to format specific strings for various + * devlink info versions. The ctx parameter is used to provide the storage + * buffer, as well as any ancillary information calculated when the info + * request was made. + * + * If a version does not exist, for example when attempting to get the + * inactive version of flash when there is no pending update, the function + * should leave the buffer in the ctx structure empty and return 0. + */ + +static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx) { u8 dsn[8]; /* Copy the DSN into an array in Big Endian format */ put_unaligned_be64(pci_get_dsn(pf->pdev), dsn); - snprintf(buf, len, "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", - dsn[0], dsn[1], dsn[2], dsn[3], - dsn[4], dsn[5], dsn[6], dsn[7]); - - return 0; + snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn); } -static int ice_info_pba(struct ice_pf *pf, char *buf, size_t len) +static int ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx) { struct ice_hw *hw = &pf->hw; enum ice_status status; - status = ice_read_pba_string(hw, (u8 *)buf, len); + status = ice_read_pba_string(hw, (u8 *)ctx->buf, sizeof(ctx->buf)); if (status) return -EIO; return 0; } -static int ice_info_fw_mgmt(struct ice_pf *pf, char *buf, size_t len) +static int ice_info_fw_mgmt(struct ice_pf *pf, struct ice_info_ctx *ctx) { struct ice_hw *hw = &pf->hw; - snprintf(buf, len, "%u.%u.%u", hw->fw_maj_ver, hw->fw_min_ver, + snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", hw->fw_maj_ver, hw->fw_min_ver, hw->fw_patch); return 0; } -static int ice_info_fw_api(struct ice_pf *pf, char *buf, size_t len) +static int ice_info_fw_api(struct ice_pf *pf, struct ice_info_ctx *ctx) { struct ice_hw *hw = &pf->hw; - snprintf(buf, len, "%u.%u", hw->api_maj_ver, hw->api_min_ver); + snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u", hw->api_maj_ver, hw->api_min_ver); return 0; } -static int ice_info_fw_build(struct ice_pf *pf, char *buf, size_t len) +static int ice_info_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx) { struct ice_hw *hw = &pf->hw; - snprintf(buf, len, "0x%08x", hw->fw_build); + snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build); return 0; } -static int ice_info_orom_ver(struct ice_pf *pf, char *buf, size_t len) +static int ice_info_orom_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) { - struct ice_orom_info *orom = &pf->hw.nvm.orom; + struct ice_orom_info *orom = &pf->hw.flash.orom; - snprintf(buf, len, "%u.%u.%u", orom->major, orom->build, orom->patch); + snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", orom->major, orom->build, orom->patch); return 0; } -static int ice_info_nvm_ver(struct ice_pf *pf, char *buf, size_t len) +static int +ice_info_pending_orom_ver(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx) { - struct ice_nvm_info *nvm = &pf->hw.nvm; + struct ice_orom_info *orom = &ctx->pending_orom; - snprintf(buf, len, "%x.%02x", nvm->major_ver, nvm->minor_ver); + if (ctx->dev_caps.common_cap.nvm_update_pending_orom) + snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", + orom->major, orom->build, orom->patch); return 0; } -static int ice_info_eetrack(struct ice_pf *pf, char *buf, size_t len) +static int ice_info_nvm_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) { - struct ice_nvm_info *nvm = &pf->hw.nvm; + struct ice_nvm_info *nvm = &pf->hw.flash.nvm; - snprintf(buf, len, "0x%08x", nvm->eetrack); + snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor); return 0; } -static int ice_info_ddp_pkg_name(struct ice_pf *pf, char *buf, size_t len) +static int +ice_info_pending_nvm_ver(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx) +{ + struct ice_nvm_info *nvm = &ctx->pending_nvm; + + if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) + snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor); + + return 0; +} + +static int ice_info_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx) +{ + struct ice_nvm_info *nvm = &pf->hw.flash.nvm; + + snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack); + + return 0; +} + +static int +ice_info_pending_eetrack(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx) +{ + struct ice_nvm_info *nvm = &ctx->pending_nvm; + + if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) + snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack); + + return 0; +} + +static int ice_info_ddp_pkg_name(struct ice_pf *pf, struct ice_info_ctx *ctx) { struct ice_hw *hw = &pf->hw; - snprintf(buf, len, "%s", hw->active_pkg_name); + snprintf(ctx->buf, sizeof(ctx->buf), "%s", hw->active_pkg_name); return 0; } -static int ice_info_ddp_pkg_version(struct ice_pf *pf, char *buf, size_t len) +static int ice_info_ddp_pkg_version(struct ice_pf *pf, struct ice_info_ctx *ctx) { struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver; - snprintf(buf, len, "%u.%u.%u.%u", pkg->major, pkg->minor, pkg->update, + snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u.%u", pkg->major, pkg->minor, pkg->update, pkg->draft); return 0; } -static int ice_info_netlist_ver(struct ice_pf *pf, char *buf, size_t len) +static int ice_info_ddp_pkg_bundle_id(struct ice_pf *pf, struct ice_info_ctx *ctx) +{ + snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", pf->hw.active_track_id); + + return 0; +} + +static int ice_info_netlist_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) { - struct ice_netlist_ver_info *netlist = &pf->hw.netlist_ver; + struct ice_netlist_info *netlist = &pf->hw.flash.netlist; /* The netlist version fields are BCD formatted */ - snprintf(buf, len, "%x.%x.%x-%x.%x.%x", netlist->major, netlist->minor, + snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", netlist->major, netlist->minor, netlist->type >> 16, netlist->type & 0xFFFF, netlist->rev, netlist->cust_ver); return 0; } -static int ice_info_netlist_build(struct ice_pf *pf, char *buf, size_t len) +static int ice_info_netlist_build(struct ice_pf *pf, struct ice_info_ctx *ctx) +{ + struct ice_netlist_info *netlist = &pf->hw.flash.netlist; + + snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); + + return 0; +} + +static int +ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx) +{ + struct ice_netlist_info *netlist = &ctx->pending_netlist; + + /* The netlist version fields are BCD formatted */ + if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) + snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", + netlist->major, netlist->minor, + netlist->type >> 16, netlist->type & 0xFFFF, netlist->rev, + netlist->cust_ver); + + return 0; +} + +static int +ice_info_pending_netlist_build(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx) { - struct ice_netlist_ver_info *netlist = &pf->hw.netlist_ver; + struct ice_netlist_info *netlist = &ctx->pending_netlist; - snprintf(buf, len, "0x%08x", netlist->hash); + if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) + snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); return 0; } -#define fixed(key, getter) { ICE_VERSION_FIXED, key, getter } -#define running(key, getter) { ICE_VERSION_RUNNING, key, getter } +#define fixed(key, getter) { ICE_VERSION_FIXED, key, getter, NULL } +#define running(key, getter) { ICE_VERSION_RUNNING, key, getter, NULL } +#define stored(key, getter, fallback) { ICE_VERSION_STORED, key, getter, fallback } + +/* The combined() macro inserts both the running entry as well as a stored + * entry. The running entry will always report the version from the active + * handler. The stored entry will first try the pending handler, and fallback + * to the active handler if the pending function does not report a version. + * The pending handler should check the status of a pending update for the + * relevant flash component. It should only fill in the buffer in the case + * where a valid pending version is available. This ensures that the related + * stored and running versions remain in sync, and that stored versions are + * correctly reported as expected. + */ +#define combined(key, active, pending) \ + running(key, active), \ + stored(key, pending, active) enum ice_version_type { ICE_VERSION_FIXED, @@ -139,19 +236,21 @@ enum ice_version_type { static const struct ice_devlink_version { enum ice_version_type type; const char *key; - int (*getter)(struct ice_pf *pf, char *buf, size_t len); + int (*getter)(struct ice_pf *pf, struct ice_info_ctx *ctx); + int (*fallback)(struct ice_pf *pf, struct ice_info_ctx *ctx); } ice_devlink_versions[] = { fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba), running(DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, ice_info_fw_mgmt), running("fw.mgmt.api", ice_info_fw_api), running("fw.mgmt.build", ice_info_fw_build), - running(DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, ice_info_orom_ver), - running("fw.psid.api", ice_info_nvm_ver), - running(DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, ice_info_eetrack), + combined(DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, ice_info_orom_ver, ice_info_pending_orom_ver), + combined("fw.psid.api", ice_info_nvm_ver, ice_info_pending_nvm_ver), + combined(DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, ice_info_eetrack, ice_info_pending_eetrack), running("fw.app.name", ice_info_ddp_pkg_name), running(DEVLINK_INFO_VERSION_GENERIC_FW_APP, ice_info_ddp_pkg_version), - running("fw.netlist", ice_info_netlist_ver), - running("fw.netlist.build", ice_info_netlist_build), + running("fw.app.bundle_id", ice_info_ddp_pkg_bundle_id), + combined("fw.netlist", ice_info_netlist_ver, ice_info_pending_netlist_ver), + combined("fw.netlist.build", ice_info_netlist_build, ice_info_pending_netlist_build), }; /** @@ -170,71 +269,134 @@ static int ice_devlink_info_get(struct devlink *devlink, struct netlink_ext_ack *extack) { struct ice_pf *pf = devlink_priv(devlink); - char buf[100]; + struct device *dev = ice_pf_to_dev(pf); + struct ice_hw *hw = &pf->hw; + struct ice_info_ctx *ctx; + enum ice_status status; size_t i; int err; + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + /* discover capabilities first */ + status = ice_discover_dev_caps(hw, &ctx->dev_caps); + if (status) { + err = -EIO; + goto out_free_ctx; + } + + if (ctx->dev_caps.common_cap.nvm_update_pending_orom) { + status = ice_get_inactive_orom_ver(hw, &ctx->pending_orom); + if (status) { + dev_dbg(dev, "Unable to read inactive Option ROM version data, status %s aq_err %s\n", + ice_stat_str(status), ice_aq_str(hw->adminq.sq_last_status)); + + /* disable display of pending Option ROM */ + ctx->dev_caps.common_cap.nvm_update_pending_orom = false; + } + } + + if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) { + status = ice_get_inactive_nvm_ver(hw, &ctx->pending_nvm); + if (status) { + dev_dbg(dev, "Unable to read inactive NVM version data, status %s aq_err %s\n", + ice_stat_str(status), ice_aq_str(hw->adminq.sq_last_status)); + + /* disable display of pending Option ROM */ + ctx->dev_caps.common_cap.nvm_update_pending_nvm = false; + } + } + + if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) { + status = ice_get_inactive_netlist_ver(hw, &ctx->pending_netlist); + if (status) { + dev_dbg(dev, "Unable to read inactive Netlist version data, status %s aq_err %s\n", + ice_stat_str(status), ice_aq_str(hw->adminq.sq_last_status)); + + /* disable display of pending Option ROM */ + ctx->dev_caps.common_cap.nvm_update_pending_netlist = false; + } + } + err = devlink_info_driver_name_put(req, KBUILD_MODNAME); if (err) { NL_SET_ERR_MSG_MOD(extack, "Unable to set driver name"); - return err; + goto out_free_ctx; } - err = ice_info_get_dsn(pf, buf, sizeof(buf)); - if (err) { - NL_SET_ERR_MSG_MOD(extack, "Unable to obtain serial number"); - return err; - } + ice_info_get_dsn(pf, ctx); - err = devlink_info_serial_number_put(req, buf); + err = devlink_info_serial_number_put(req, ctx->buf); if (err) { NL_SET_ERR_MSG_MOD(extack, "Unable to set serial number"); - return err; + goto out_free_ctx; } for (i = 0; i < ARRAY_SIZE(ice_devlink_versions); i++) { enum ice_version_type type = ice_devlink_versions[i].type; const char *key = ice_devlink_versions[i].key; - err = ice_devlink_versions[i].getter(pf, buf, sizeof(buf)); + memset(ctx->buf, 0, sizeof(ctx->buf)); + + err = ice_devlink_versions[i].getter(pf, ctx); if (err) { NL_SET_ERR_MSG_MOD(extack, "Unable to obtain version info"); - return err; + goto out_free_ctx; + } + + /* If the default getter doesn't report a version, use the + * fallback function. This is primarily useful in the case of + * "stored" versions that want to report the same value as the + * running version in the normal case of no pending update. + */ + if (ctx->buf[0] == '\0' && ice_devlink_versions[i].fallback) { + err = ice_devlink_versions[i].fallback(pf, ctx); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Unable to obtain version info"); + goto out_free_ctx; + } } + /* Do not report missing versions */ + if (ctx->buf[0] == '\0') + continue; + switch (type) { case ICE_VERSION_FIXED: - err = devlink_info_version_fixed_put(req, key, buf); + err = devlink_info_version_fixed_put(req, key, ctx->buf); if (err) { NL_SET_ERR_MSG_MOD(extack, "Unable to set fixed version"); - return err; + goto out_free_ctx; } break; case ICE_VERSION_RUNNING: - err = devlink_info_version_running_put(req, key, buf); + err = devlink_info_version_running_put(req, key, ctx->buf); if (err) { NL_SET_ERR_MSG_MOD(extack, "Unable to set running version"); - return err; + goto out_free_ctx; } break; case ICE_VERSION_STORED: - err = devlink_info_version_stored_put(req, key, buf); + err = devlink_info_version_stored_put(req, key, ctx->buf); if (err) { NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version"); - return err; + goto out_free_ctx; } break; } } - return 0; +out_free_ctx: + kfree(ctx); + return err; } /** * ice_devlink_flash_update - Update firmware stored in flash on the device * @devlink: pointer to devlink associated with device to update - * @path: the path of the firmware file to use via request_firmware - * @component: name of the component to update, or NULL + * @params: flash update parameters * @extack: netlink extended ACK structure * * Perform a device flash update. The bulk of the update logic is contained @@ -243,46 +405,46 @@ static int ice_devlink_info_get(struct devlink *devlink, * Returns: zero on success, or an error code on failure. */ static int -ice_devlink_flash_update(struct devlink *devlink, const char *path, - const char *component, struct netlink_ext_ack *extack) +ice_devlink_flash_update(struct devlink *devlink, + struct devlink_flash_update_params *params, + struct netlink_ext_ack *extack) { struct ice_pf *pf = devlink_priv(devlink); - struct device *dev = &pf->pdev->dev; struct ice_hw *hw = &pf->hw; - const struct firmware *fw; + u8 preservation; int err; - /* individual component update is not yet supported */ - if (component) + if (!params->overwrite_mask) { + /* preserve all settings and identifiers */ + preservation = ICE_AQC_NVM_PRESERVE_ALL; + } else if (params->overwrite_mask == DEVLINK_FLASH_OVERWRITE_SETTINGS) { + /* overwrite settings, but preserve the vital device identifiers */ + preservation = ICE_AQC_NVM_PRESERVE_SELECTED; + } else if (params->overwrite_mask == (DEVLINK_FLASH_OVERWRITE_SETTINGS | + DEVLINK_FLASH_OVERWRITE_IDENTIFIERS)) { + /* overwrite both settings and identifiers, preserve nothing */ + preservation = ICE_AQC_NVM_NO_PRESERVATION; + } else { + NL_SET_ERR_MSG_MOD(extack, "Requested overwrite mask is not supported"); return -EOPNOTSUPP; + } if (!hw->dev_caps.common_cap.nvm_unified_update) { NL_SET_ERR_MSG_MOD(extack, "Current firmware does not support unified update"); return -EOPNOTSUPP; } - err = ice_check_for_pending_update(pf, component, extack); + err = ice_check_for_pending_update(pf, NULL, extack); if (err) return err; - err = request_firmware(&fw, path, dev); - if (err) { - NL_SET_ERR_MSG_MOD(extack, "Unable to read file from disk"); - return err; - } - - devlink_flash_update_begin_notify(devlink); - devlink_flash_update_status_notify(devlink, "Preparing to flash", - component, 0, 0); - err = ice_flash_pldm_image(pf, fw, extack); - devlink_flash_update_end_notify(devlink); - - release_firmware(fw); + devlink_flash_update_status_notify(devlink, "Preparing to flash", NULL, 0, 0); - return err; + return ice_flash_pldm_image(pf, params->fw, preservation, extack); } static const struct devlink_ops ice_devlink_ops = { + .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK, .info_get = ice_devlink_info_get, .flash_update = ice_devlink_flash_update, }; @@ -352,55 +514,66 @@ void ice_devlink_unregister(struct ice_pf *pf) } /** - * ice_devlink_create_port - Create a devlink port for this PF - * @pf: the PF to create a port for + * ice_devlink_create_port - Create a devlink port for this VSI + * @vsi: the VSI to create a port for * - * Create and register a devlink_port for this PF. Note that although each - * physical function is connected to a separate devlink instance, the port - * will still be numbered according to the physical function ID. + * Create and register a devlink_port for this VSI. * * Return: zero on success or an error code on failure. */ -int ice_devlink_create_port(struct ice_pf *pf) +int ice_devlink_create_port(struct ice_vsi *vsi) { - struct devlink *devlink = priv_to_devlink(pf); - struct ice_vsi *vsi = ice_get_main_vsi(pf); - struct device *dev = ice_pf_to_dev(pf); struct devlink_port_attrs attrs = {}; + struct ice_port_info *pi; + struct devlink *devlink; + struct device *dev; + struct ice_pf *pf; int err; - if (!vsi) { - dev_err(dev, "%s: unable to find main VSI\n", __func__); - return -EIO; - } + /* Currently we only create devlink_port instances for PF VSIs */ + if (vsi->type != ICE_VSI_PF) + return -EINVAL; + + pf = vsi->back; + devlink = priv_to_devlink(pf); + dev = ice_pf_to_dev(pf); + pi = pf->hw.port_info; attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; - attrs.phys.port_number = pf->hw.pf_id; - devlink_port_attrs_set(&pf->devlink_port, &attrs); - err = devlink_port_register(devlink, &pf->devlink_port, pf->hw.pf_id); + attrs.phys.port_number = pi->lport; + devlink_port_attrs_set(&vsi->devlink_port, &attrs); + err = devlink_port_register(devlink, &vsi->devlink_port, vsi->idx); if (err) { dev_err(dev, "devlink_port_register failed: %d\n", err); return err; } + vsi->devlink_port_registered = true; + return 0; } /** - * ice_devlink_destroy_port - Destroy the devlink_port for this PF - * @pf: the PF to cleanup + * ice_devlink_destroy_port - Destroy the devlink_port for this VSI + * @vsi: the VSI to cleanup * - * Unregisters the devlink_port structure associated with this PF. + * Unregisters the devlink_port structure associated with this VSI. */ -void ice_devlink_destroy_port(struct ice_pf *pf) +void ice_devlink_destroy_port(struct ice_vsi *vsi) { - devlink_port_type_clear(&pf->devlink_port); - devlink_port_unregister(&pf->devlink_port); + if (!vsi->devlink_port_registered) + return; + + devlink_port_type_clear(&vsi->devlink_port); + devlink_port_unregister(&vsi->devlink_port); + + vsi->devlink_port_registered = false; } /** * ice_devlink_nvm_snapshot - Capture a snapshot of the Shadow RAM contents * @devlink: the devlink instance + * @ops: the devlink region being snapshotted * @extack: extended ACK response structure * @data: on exit points to snapshot data buffer * @@ -413,6 +586,7 @@ void ice_devlink_destroy_port(struct ice_pf *pf) * error code on failure. */ static int ice_devlink_nvm_snapshot(struct devlink *devlink, + const struct devlink_region_ops *ops, struct netlink_ext_ack *extack, u8 **data) { struct ice_pf *pf = devlink_priv(devlink); @@ -422,7 +596,7 @@ static int ice_devlink_nvm_snapshot(struct devlink *devlink, void *nvm_data; u32 nvm_size; - nvm_size = hw->nvm.flash_size; + nvm_size = hw->flash.flash_size; nvm_data = vzalloc(nvm_size); if (!nvm_data) return -ENOMEM; @@ -456,6 +630,7 @@ static int ice_devlink_nvm_snapshot(struct devlink *devlink, /** * ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities * @devlink: the devlink instance + * @ops: the devlink region being snapshotted * @extack: extended ACK response structure * @data: on exit points to snapshot data buffer * @@ -468,6 +643,7 @@ static int ice_devlink_nvm_snapshot(struct devlink *devlink, */ static int ice_devlink_devcaps_snapshot(struct devlink *devlink, + const struct devlink_region_ops *ops, struct netlink_ext_ack *extack, u8 **data) { struct ice_pf *pf = devlink_priv(devlink); @@ -520,7 +696,7 @@ void ice_devlink_init_regions(struct ice_pf *pf) struct device *dev = ice_pf_to_dev(pf); u64 nvm_size; - nvm_size = pf->hw.nvm.flash_size; + nvm_size = pf->hw.flash.flash_size; pf->nvm_region = devlink_region_create(devlink, &ice_nvm_region_ops, 1, nvm_size); if (IS_ERR(pf->nvm_region)) { |