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

devlink: introduce flash update overwrite mask

Sections of device flash may contain settings or device identifying
information. When performing a flash update, it is generally expected
that these settings and identifiers are not overwritten.

However, it may sometimes be useful to allow overwriting these fields
when performing a flash update. Some examples include, 1) customizing
the initial device config on first programming, such as overwriting
default device identifying information, or 2) reverting a device
configuration to known good state provided in the new firmware image, or
3) in case it is suspected that current firmware logic for managing the
preservation of fields during an update is broken.

Although some devices are able to completely separate these types of
settings and fields into separate components, this is not true for all
hardware.

To support controlling this behavior, a new
DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK is defined. This is an
nla_bitfield32 which will define what subset of fields in a component
should be overwritten during an update.

If no bits are specified, or of the overwrite mask is not provided, then
an update should not overwrite anything, and should maintain the
settings and identifiers as they are in the previous image.

If the overwrite mask has the DEVLINK_FLASH_OVERWRITE_SETTINGS bit set,
then the device should be configured to overwrite any of the settings in
the requested component with settings found in the provided image.

Similarly, if the DEVLINK_FLASH_OVERWRITE_IDENTIFIERS bit is set, the
device should be configured to overwrite any device identifiers in the
requested component with the identifiers from the image.

Multiple overwrite modes may be combined to indicate that a combination
of the set of fields that should be overwritten.

Drivers which support the new overwrite mask must set the
DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK in the
supported_flash_update_params field of their devlink_ops.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Reviewed-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Jacob Keller and committed by
David S. Miller
5d5b4128 bc75c054

+70 -2
+3 -1
include/net/devlink.h
··· 562 562 struct devlink_flash_update_params { 563 563 const char *file_name; 564 564 const char *component; 565 + u32 overwrite_mask; 565 566 }; 566 567 567 - #define DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT BIT(0) 568 + #define DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT BIT(0) 569 + #define DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK BIT(1) 568 570 569 571 struct devlink_region; 570 572 struct devlink_info_req;
+23
include/uapi/linux/devlink.h
··· 230 230 DEVLINK_ATTR_STATS_MAX = __DEVLINK_ATTR_STATS_MAX - 1 231 231 }; 232 232 233 + /* Specify what sections of a flash component can be overwritten when 234 + * performing an update. Overwriting of firmware binary sections is always 235 + * implicitly assumed to be allowed. 236 + * 237 + * Each section must be documented in 238 + * Documentation/networking/devlink/devlink-flash.rst 239 + * 240 + */ 241 + enum { 242 + DEVLINK_FLASH_OVERWRITE_SETTINGS_BIT, 243 + DEVLINK_FLASH_OVERWRITE_IDENTIFIERS_BIT, 244 + 245 + __DEVLINK_FLASH_OVERWRITE_MAX_BIT, 246 + DEVLINK_FLASH_OVERWRITE_MAX_BIT = __DEVLINK_FLASH_OVERWRITE_MAX_BIT - 1 247 + }; 248 + 249 + #define DEVLINK_FLASH_OVERWRITE_SETTINGS _BITUL(DEVLINK_FLASH_OVERWRITE_SETTINGS_BIT) 250 + #define DEVLINK_FLASH_OVERWRITE_IDENTIFIERS _BITUL(DEVLINK_FLASH_OVERWRITE_IDENTIFIERS_BIT) 251 + 252 + #define DEVLINK_SUPPORTED_FLASH_OVERWRITE_SECTIONS \ 253 + (_BITUL(__DEVLINK_FLASH_OVERWRITE_MAX_BIT) - 1) 254 + 233 255 /** 234 256 * enum devlink_trap_action - Packet trap action. 235 257 * @DEVLINK_TRAP_ACTION_DROP: Packet is dropped by the device and a copy is not ··· 486 464 DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, /* u32 */ 487 465 488 466 DEVLINK_ATTR_FLASH_UPDATE_STATUS_TIMEOUT, /* u64 */ 467 + DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK, /* bitfield32 */ 489 468 490 469 /* add new attributes above here, update the policy in devlink.c */ 491 470
+16 -1
net/core/devlink.c
··· 3147 3147 static int devlink_nl_cmd_flash_update(struct sk_buff *skb, 3148 3148 struct genl_info *info) 3149 3149 { 3150 + struct nlattr *nla_component, *nla_overwrite_mask; 3150 3151 struct devlink_flash_update_params params = {}; 3151 3152 struct devlink *devlink = info->user_ptr[0]; 3152 - struct nlattr *nla_component; 3153 3153 u32 supported_params; 3154 3154 3155 3155 if (!devlink->ops->flash_update) ··· 3170 3170 return -EOPNOTSUPP; 3171 3171 } 3172 3172 params.component = nla_data(nla_component); 3173 + } 3174 + 3175 + nla_overwrite_mask = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK]; 3176 + if (nla_overwrite_mask) { 3177 + struct nla_bitfield32 sections; 3178 + 3179 + if (!(supported_params & DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK)) { 3180 + NL_SET_ERR_MSG_ATTR(info->extack, nla_overwrite_mask, 3181 + "overwrite settings are not supported by this device"); 3182 + return -EOPNOTSUPP; 3183 + } 3184 + sections = nla_get_bitfield32(nla_overwrite_mask); 3185 + params.overwrite_mask = sections.value & sections.selector; 3173 3186 } 3174 3187 3175 3188 return devlink->ops->flash_update(devlink, &params, info->extack); ··· 7106 7093 [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 }, 7107 7094 [DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME] = { .type = NLA_NUL_STRING }, 7108 7095 [DEVLINK_ATTR_FLASH_UPDATE_COMPONENT] = { .type = NLA_NUL_STRING }, 7096 + [DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK] = 7097 + NLA_POLICY_BITFIELD32(DEVLINK_SUPPORTED_FLASH_OVERWRITE_SECTIONS), 7109 7098 [DEVLINK_ATTR_TRAP_NAME] = { .type = NLA_NUL_STRING }, 7110 7099 [DEVLINK_ATTR_TRAP_ACTION] = { .type = NLA_U8 }, 7111 7100 [DEVLINK_ATTR_TRAP_GROUP_NAME] = { .type = NLA_NUL_STRING },