Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

devlink: check flash_update parameter support in net core

When implementing .flash_update, drivers which do not support
per-component update are manually checking the component parameter to
verify that it is NULL. Without this check, the driver might accept an
update request with a component specified even though it will not honor
such a request.

Instead of having each driver check this, move the logic into
net/core/devlink.c, and use a new `supported_flash_update_params` field
in the devlink_ops. Drivers which will support per-component update must
now specify this by setting DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT in
the supported_flash_update_params in their devlink_ops.

This helps ensure that drivers do not forget to check for a NULL
component if they do not support per-component update. This also enables
a slightly better error message by enabling the core stack to set the
netlink bad attribute message to indicate precisely the unsupported
attribute in the message.

Going forward, any new additional parameter to flash update will require
a bit in the supported_flash_update_params bitfield.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Reviewed-by: Jakub Kicinski <kuba@kernel.org>
Cc: Jiri Pirko <jiri@mellanox.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Michael Chan <michael.chan@broadcom.com>
Cc: Bin Luo <luobin9@huawei.com>
Cc: Saeed Mahameed <saeedm@mellanox.com>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: Ido Schimmel <idosch@mellanox.com>
Cc: Danielle Ratson <danieller@mellanox.com>
Cc: Shannon Nelson <snelson@pensando.io>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Jacob Keller and committed by
David S. Miller
22ec3d23 6fba737a

+34 -32
+3 -9
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
··· 23 23 struct bnxt *bp = bnxt_get_bp_from_dl(dl); 24 24 int rc; 25 25 26 - if (region) 27 - return -EOPNOTSUPP; 28 - 29 26 if (!BNXT_PF(bp)) { 30 27 NL_SET_ERR_MSG_MOD(extack, 31 28 "flash update not supported from a VF"); ··· 30 33 } 31 34 32 35 devlink_flash_update_begin_notify(dl); 33 - devlink_flash_update_status_notify(dl, "Preparing to flash", region, 0, 34 - 0); 36 + devlink_flash_update_status_notify(dl, "Preparing to flash", NULL, 0, 0); 35 37 rc = bnxt_flash_package_from_file(bp->dev, filename, 0); 36 38 if (!rc) 37 - devlink_flash_update_status_notify(dl, "Flashing done", region, 38 - 0, 0); 39 + devlink_flash_update_status_notify(dl, "Flashing done", NULL, 0, 0); 39 40 else 40 - devlink_flash_update_status_notify(dl, "Flashing failed", 41 - region, 0, 0); 41 + devlink_flash_update_status_notify(dl, "Flashing failed", NULL, 0, 0); 42 42 devlink_flash_update_end_notify(dl); 43 43 return rc; 44 44 }
-3
drivers/net/ethernet/huawei/hinic/hinic_devlink.c
··· 289 289 const struct firmware *fw; 290 290 int err; 291 291 292 - if (component) 293 - return -EOPNOTSUPP; 294 - 295 292 err = request_firmware_direct(&fw, file_name, 296 293 &priv->hwdev->hwif->pdev->dev); 297 294 if (err)
+2 -7
drivers/net/ethernet/intel/ice/ice_devlink.c
··· 252 252 const struct firmware *fw; 253 253 int err; 254 254 255 - /* individual component update is not yet supported */ 256 - if (component) 257 - return -EOPNOTSUPP; 258 - 259 255 if (!hw->dev_caps.common_cap.nvm_unified_update) { 260 256 NL_SET_ERR_MSG_MOD(extack, "Current firmware does not support unified update"); 261 257 return -EOPNOTSUPP; 262 258 } 263 259 264 - err = ice_check_for_pending_update(pf, component, extack); 260 + err = ice_check_for_pending_update(pf, NULL, extack); 265 261 if (err) 266 262 return err; 267 263 ··· 268 272 } 269 273 270 274 devlink_flash_update_begin_notify(devlink); 271 - devlink_flash_update_status_notify(devlink, "Preparing to flash", 272 - component, 0, 0); 275 + devlink_flash_update_status_notify(devlink, "Preparing to flash", NULL, 0, 0); 273 276 err = ice_flash_pldm_image(pf, fw, extack); 274 277 devlink_flash_update_end_notify(devlink); 275 278
-3
drivers/net/ethernet/mellanox/mlx5/core/devlink.c
··· 16 16 const struct firmware *fw; 17 17 int err; 18 18 19 - if (component) 20 - return -EOPNOTSUPP; 21 - 22 19 err = request_firmware_direct(&fw, file_name, &dev->pdev->dev); 23 20 if (err) 24 21 return err;
-3
drivers/net/ethernet/mellanox/mlxsw/core.c
··· 1108 1108 const struct firmware *firmware; 1109 1109 int err; 1110 1110 1111 - if (component) 1112 - return -EOPNOTSUPP; 1113 - 1114 1111 err = request_firmware_direct(&firmware, file_name, mlxsw_core->bus_info->dev); 1115 1112 if (err) 1116 1113 return err;
-2
drivers/net/ethernet/netronome/nfp/nfp_devlink.c
··· 332 332 nfp_devlink_flash_update(struct devlink *devlink, const char *path, 333 333 const char *component, struct netlink_ext_ack *extack) 334 334 { 335 - if (component) 336 - return -EOPNOTSUPP; 337 335 return nfp_flash_update_common(devlink_priv(devlink), path, extack); 338 336 } 339 337
-3
drivers/net/ethernet/pensando/ionic/ionic_devlink.c
··· 16 16 { 17 17 struct ionic *ionic = devlink_priv(dl); 18 18 19 - if (component) 20 - return -EOPNOTSUPP; 21 - 22 19 return ionic_firmware_update(ionic->lif, fwname, extack); 23 20 } 24 21
+1
drivers/net/netdevsim/dev.c
··· 879 879 } 880 880 881 881 static const struct devlink_ops nsim_dev_devlink_ops = { 882 + .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT, 882 883 .reload_down = nsim_dev_reload_down, 883 884 .reload_up = nsim_dev_reload_up, 884 885 .info_get = nsim_dev_info_get,
+15
include/net/devlink.h
··· 550 550 /* Firmware bundle identifier */ 551 551 #define DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID "fw.bundle_id" 552 552 553 + #define DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT BIT(0) 554 + 553 555 struct devlink_region; 554 556 struct devlink_info_req; 555 557 ··· 1039 1037 } 1040 1038 1041 1039 struct devlink_ops { 1040 + /** 1041 + * @supported_flash_update_params: 1042 + * mask of parameters supported by the driver's .flash_update 1043 + * implemementation. 1044 + */ 1045 + u32 supported_flash_update_params; 1042 1046 int (*reload_down)(struct devlink *devlink, bool netns_change, 1043 1047 struct netlink_ext_ack *extack); 1044 1048 int (*reload_up)(struct devlink *devlink, ··· 1105 1097 struct netlink_ext_ack *extack); 1106 1098 int (*info_get)(struct devlink *devlink, struct devlink_info_req *req, 1107 1099 struct netlink_ext_ack *extack); 1100 + /** 1101 + * @flash_update: Device flash update function 1102 + * 1103 + * Used to perform a flash update for the device. The set of 1104 + * parameters supported by the driver should be set in 1105 + * supported_flash_update_params. 1106 + */ 1108 1107 int (*flash_update)(struct devlink *devlink, const char *file_name, 1109 1108 const char *component, 1110 1109 struct netlink_ext_ack *extack);
+13 -2
net/core/devlink.c
··· 3148 3148 struct genl_info *info) 3149 3149 { 3150 3150 struct devlink *devlink = info->user_ptr[0]; 3151 - const char *file_name, *component; 3151 + const char *file_name, *component = NULL; 3152 3152 struct nlattr *nla_component; 3153 + u32 supported_params; 3153 3154 3154 3155 if (!devlink->ops->flash_update) 3155 3156 return -EOPNOTSUPP; 3156 3157 3157 3158 if (!info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME]) 3158 3159 return -EINVAL; 3160 + 3161 + supported_params = devlink->ops->supported_flash_update_params; 3162 + 3159 3163 file_name = nla_data(info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME]); 3160 3164 3161 3165 nla_component = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT]; 3162 - component = nla_component ? nla_data(nla_component) : NULL; 3166 + if (nla_component) { 3167 + if (!(supported_params & DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT)) { 3168 + NL_SET_ERR_MSG_ATTR(info->extack, nla_component, 3169 + "component update is not supported by this device"); 3170 + return -EOPNOTSUPP; 3171 + } 3172 + component = nla_data(nla_component); 3173 + } 3163 3174 3164 3175 return devlink->ops->flash_update(devlink, file_name, component, 3165 3176 info->extack);