Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 191ed202 authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller
Browse files

devlink: allow driver to update progress of flash update



Introduce a function to be called from drivers during flash. It sends
notification to userspace about flash update progress.

Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Reviewed-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 44f18db5
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -741,6 +741,14 @@ void
devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
				     enum devlink_health_reporter_state state);

void devlink_flash_update_begin_notify(struct devlink *devlink);
void devlink_flash_update_end_notify(struct devlink *devlink);
void devlink_flash_update_status_notify(struct devlink *devlink,
					const char *status_msg,
					const char *component,
					unsigned long done,
					unsigned long total);

#if IS_ENABLED(CONFIG_NET_DEVLINK)

void devlink_compat_running_version(struct net_device *dev,
+5 −0
Original line number Diff line number Diff line
@@ -104,6 +104,8 @@ enum devlink_command {
	DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR,

	DEVLINK_CMD_FLASH_UPDATE,
	DEVLINK_CMD_FLASH_UPDATE_END,		/* notification only */
	DEVLINK_CMD_FLASH_UPDATE_STATUS,	/* notification only */

	/* add new commands above here */
	__DEVLINK_CMD_MAX,
@@ -331,6 +333,9 @@ enum devlink_attr {

	DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME,	/* string */
	DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,	/* string */
	DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG,	/* string */
	DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE,	/* u64 */
	DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL,	/* u64 */

	/* add new attributes above here, update the policy in devlink.c */

+102 −0
Original line number Diff line number Diff line
@@ -2673,6 +2673,108 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
	return devlink->ops->reload(devlink, info->extack);
}

static int devlink_nl_flash_update_fill(struct sk_buff *msg,
					struct devlink *devlink,
					enum devlink_command cmd,
					const char *status_msg,
					const char *component,
					unsigned long done, unsigned long total)
{
	void *hdr;

	hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
	if (!hdr)
		return -EMSGSIZE;

	if (devlink_nl_put_handle(msg, devlink))
		goto nla_put_failure;

	if (cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS)
		goto out;

	if (status_msg &&
	    nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG,
			   status_msg))
		goto nla_put_failure;
	if (component &&
	    nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,
			   component))
		goto nla_put_failure;
	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE,
			      done, DEVLINK_ATTR_PAD))
		goto nla_put_failure;
	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL,
			      total, DEVLINK_ATTR_PAD))
		goto nla_put_failure;

out:
	genlmsg_end(msg, hdr);
	return 0;

nla_put_failure:
	genlmsg_cancel(msg, hdr);
	return -EMSGSIZE;
}

static void __devlink_flash_update_notify(struct devlink *devlink,
					  enum devlink_command cmd,
					  const char *status_msg,
					  const char *component,
					  unsigned long done,
					  unsigned long total)
{
	struct sk_buff *msg;
	int err;

	WARN_ON(cmd != DEVLINK_CMD_FLASH_UPDATE &&
		cmd != DEVLINK_CMD_FLASH_UPDATE_END &&
		cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS);

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!msg)
		return;

	err = devlink_nl_flash_update_fill(msg, devlink, cmd, status_msg,
					   component, done, total);
	if (err)
		goto out_free_msg;

	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
				msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
	return;

out_free_msg:
	nlmsg_free(msg);
}

void devlink_flash_update_begin_notify(struct devlink *devlink)
{
	__devlink_flash_update_notify(devlink,
				      DEVLINK_CMD_FLASH_UPDATE,
				      NULL, NULL, 0, 0);
}
EXPORT_SYMBOL_GPL(devlink_flash_update_begin_notify);

void devlink_flash_update_end_notify(struct devlink *devlink)
{
	__devlink_flash_update_notify(devlink,
				      DEVLINK_CMD_FLASH_UPDATE_END,
				      NULL, NULL, 0, 0);
}
EXPORT_SYMBOL_GPL(devlink_flash_update_end_notify);

void devlink_flash_update_status_notify(struct devlink *devlink,
					const char *status_msg,
					const char *component,
					unsigned long done,
					unsigned long total)
{
	__devlink_flash_update_notify(devlink,
				      DEVLINK_CMD_FLASH_UPDATE_STATUS,
				      status_msg, component, done, total);
}
EXPORT_SYMBOL_GPL(devlink_flash_update_status_notify);

static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
				       struct genl_info *info)
{