Commit a13aab66 authored by Moshe Shemesh's avatar Moshe Shemesh Committed by Jakub Kicinski
Browse files

devlink: Move devlink dev flash code to dev



Move devlink dev flash callbacks, helpers and other related code from
leftover.c to dev.c. No functional change in this patch.

Signed-off-by: default avatarMoshe Shemesh <moshe@nvidia.com>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent d60191c4
Loading
Loading
Loading
Loading
+271 −0
Original line number Diff line number Diff line
@@ -833,6 +833,246 @@ const struct devlink_cmd devl_cmd_info_get = {
	.dump_one		= devlink_nl_cmd_info_get_dump_one,
};

static int devlink_nl_flash_update_fill(struct sk_buff *msg,
					struct devlink *devlink,
					enum devlink_command cmd,
					struct devlink_flash_notify *params)
{
	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 (params->status_msg &&
	    nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG,
			   params->status_msg))
		goto nla_put_failure;
	if (params->component &&
	    nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,
			   params->component))
		goto nla_put_failure;
	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE,
			      params->done, DEVLINK_ATTR_PAD))
		goto nla_put_failure;
	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL,
			      params->total, DEVLINK_ATTR_PAD))
		goto nla_put_failure;
	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TIMEOUT,
			      params->timeout, 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,
					  struct devlink_flash_notify *params)
{
	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);

	if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
		return;

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

	err = devlink_nl_flash_update_fill(msg, devlink, cmd, params);
	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);
}

static void devlink_flash_update_begin_notify(struct devlink *devlink)
{
	struct devlink_flash_notify params = {};

	__devlink_flash_update_notify(devlink,
				      DEVLINK_CMD_FLASH_UPDATE,
				      &params);
}

static void devlink_flash_update_end_notify(struct devlink *devlink)
{
	struct devlink_flash_notify params = {};

	__devlink_flash_update_notify(devlink,
				      DEVLINK_CMD_FLASH_UPDATE_END,
				      &params);
}

void devlink_flash_update_status_notify(struct devlink *devlink,
					const char *status_msg,
					const char *component,
					unsigned long done,
					unsigned long total)
{
	struct devlink_flash_notify params = {
		.status_msg = status_msg,
		.component = component,
		.done = done,
		.total = total,
	};

	__devlink_flash_update_notify(devlink,
				      DEVLINK_CMD_FLASH_UPDATE_STATUS,
				      &params);
}
EXPORT_SYMBOL_GPL(devlink_flash_update_status_notify);

void devlink_flash_update_timeout_notify(struct devlink *devlink,
					 const char *status_msg,
					 const char *component,
					 unsigned long timeout)
{
	struct devlink_flash_notify params = {
		.status_msg = status_msg,
		.component = component,
		.timeout = timeout,
	};

	__devlink_flash_update_notify(devlink,
				      DEVLINK_CMD_FLASH_UPDATE_STATUS,
				      &params);
}
EXPORT_SYMBOL_GPL(devlink_flash_update_timeout_notify);

struct devlink_flash_component_lookup_ctx {
	const char *lookup_name;
	bool lookup_name_found;
};

static void
devlink_flash_component_lookup_cb(const char *version_name,
				  enum devlink_info_version_type version_type,
				  void *version_cb_priv)
{
	struct devlink_flash_component_lookup_ctx *lookup_ctx = version_cb_priv;

	if (version_type != DEVLINK_INFO_VERSION_TYPE_COMPONENT ||
	    lookup_ctx->lookup_name_found)
		return;

	lookup_ctx->lookup_name_found =
		!strcmp(lookup_ctx->lookup_name, version_name);
}

static int devlink_flash_component_get(struct devlink *devlink,
				       struct nlattr *nla_component,
				       const char **p_component,
				       struct netlink_ext_ack *extack)
{
	struct devlink_flash_component_lookup_ctx lookup_ctx = {};
	struct devlink_info_req req = {};
	const char *component;
	int ret;

	if (!nla_component)
		return 0;

	component = nla_data(nla_component);

	if (!devlink->ops->info_get) {
		NL_SET_ERR_MSG_ATTR(extack, nla_component,
				    "component update is not supported by this device");
		return -EOPNOTSUPP;
	}

	lookup_ctx.lookup_name = component;
	req.version_cb = devlink_flash_component_lookup_cb;
	req.version_cb_priv = &lookup_ctx;

	ret = devlink->ops->info_get(devlink, &req, NULL);
	if (ret)
		return ret;

	if (!lookup_ctx.lookup_name_found) {
		NL_SET_ERR_MSG_ATTR(extack, nla_component,
				    "selected component is not supported by this device");
		return -EINVAL;
	}
	*p_component = component;
	return 0;
}

int devlink_nl_cmd_flash_update(struct sk_buff *skb, struct genl_info *info)
{
	struct nlattr *nla_overwrite_mask, *nla_file_name;
	struct devlink_flash_update_params params = {};
	struct devlink *devlink = info->user_ptr[0];
	const char *file_name;
	u32 supported_params;
	int ret;

	if (!devlink->ops->flash_update)
		return -EOPNOTSUPP;

	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME))
		return -EINVAL;

	ret = devlink_flash_component_get(devlink,
					  info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT],
					  &params.component, info->extack);
	if (ret)
		return ret;

	supported_params = devlink->ops->supported_flash_update_params;

	nla_overwrite_mask = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK];
	if (nla_overwrite_mask) {
		struct nla_bitfield32 sections;

		if (!(supported_params & DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK)) {
			NL_SET_ERR_MSG_ATTR(info->extack, nla_overwrite_mask,
					    "overwrite settings are not supported by this device");
			return -EOPNOTSUPP;
		}
		sections = nla_get_bitfield32(nla_overwrite_mask);
		params.overwrite_mask = sections.value & sections.selector;
	}

	nla_file_name = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME];
	file_name = nla_data(nla_file_name);
	ret = request_firmware(&params.fw, file_name, devlink->dev);
	if (ret) {
		NL_SET_ERR_MSG_ATTR(info->extack, nla_file_name,
				    "failed to locate the requested firmware file");
		return ret;
	}

	devlink_flash_update_begin_notify(devlink);
	ret = devlink->ops->flash_update(devlink, &params, info->extack);
	devlink_flash_update_end_notify(devlink);

	release_firmware(params.fw);

	return ret;
}

static void __devlink_compat_running_version(struct devlink *devlink,
					     char *buf, size_t len)
{
@@ -880,3 +1120,34 @@ void devlink_compat_running_version(struct devlink *devlink,
		__devlink_compat_running_version(devlink, buf, len);
	devl_unlock(devlink);
}

int devlink_compat_flash_update(struct devlink *devlink, const char *file_name)
{
	struct devlink_flash_update_params params = {};
	int ret;

	devl_lock(devlink);
	if (!devl_is_registered(devlink)) {
		ret = -ENODEV;
		goto out_unlock;
	}

	if (!devlink->ops->flash_update) {
		ret = -EOPNOTSUPP;
		goto out_unlock;
	}

	ret = request_firmware(&params.fw, file_name, devlink->dev);
	if (ret)
		goto out_unlock;

	devlink_flash_update_begin_notify(devlink);
	ret = devlink->ops->flash_update(devlink, &params, NULL);
	devlink_flash_update_end_notify(devlink);

	release_firmware(params.fw);
out_unlock:
	devl_unlock(devlink);

	return ret;
}
+1 −0
Original line number Diff line number Diff line
@@ -224,3 +224,4 @@ int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info);
int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb, struct genl_info *info);
int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb, struct genl_info *info);
int devlink_nl_cmd_info_get_doit(struct sk_buff *skb, struct genl_info *info);
int devlink_nl_cmd_flash_update(struct sk_buff *skb, struct genl_info *info);
+0 −271
Original line number Diff line number Diff line
@@ -3848,246 +3848,6 @@ int devlink_resources_validate(struct devlink *devlink,
	return err;
}

static int devlink_nl_flash_update_fill(struct sk_buff *msg,
					struct devlink *devlink,
					enum devlink_command cmd,
					struct devlink_flash_notify *params)
{
	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 (params->status_msg &&
	    nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG,
			   params->status_msg))
		goto nla_put_failure;
	if (params->component &&
	    nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,
			   params->component))
		goto nla_put_failure;
	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE,
			      params->done, DEVLINK_ATTR_PAD))
		goto nla_put_failure;
	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL,
			      params->total, DEVLINK_ATTR_PAD))
		goto nla_put_failure;
	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TIMEOUT,
			      params->timeout, 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,
					  struct devlink_flash_notify *params)
{
	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);

	if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
		return;

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

	err = devlink_nl_flash_update_fill(msg, devlink, cmd, params);
	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);
}

static void devlink_flash_update_begin_notify(struct devlink *devlink)
{
	struct devlink_flash_notify params = {};

	__devlink_flash_update_notify(devlink,
				      DEVLINK_CMD_FLASH_UPDATE,
				      &params);
}

static void devlink_flash_update_end_notify(struct devlink *devlink)
{
	struct devlink_flash_notify params = {};

	__devlink_flash_update_notify(devlink,
				      DEVLINK_CMD_FLASH_UPDATE_END,
				      &params);
}

void devlink_flash_update_status_notify(struct devlink *devlink,
					const char *status_msg,
					const char *component,
					unsigned long done,
					unsigned long total)
{
	struct devlink_flash_notify params = {
		.status_msg = status_msg,
		.component = component,
		.done = done,
		.total = total,
	};

	__devlink_flash_update_notify(devlink,
				      DEVLINK_CMD_FLASH_UPDATE_STATUS,
				      &params);
}
EXPORT_SYMBOL_GPL(devlink_flash_update_status_notify);

void devlink_flash_update_timeout_notify(struct devlink *devlink,
					 const char *status_msg,
					 const char *component,
					 unsigned long timeout)
{
	struct devlink_flash_notify params = {
		.status_msg = status_msg,
		.component = component,
		.timeout = timeout,
	};

	__devlink_flash_update_notify(devlink,
				      DEVLINK_CMD_FLASH_UPDATE_STATUS,
				      &params);
}
EXPORT_SYMBOL_GPL(devlink_flash_update_timeout_notify);

struct devlink_flash_component_lookup_ctx {
	const char *lookup_name;
	bool lookup_name_found;
};

static void
devlink_flash_component_lookup_cb(const char *version_name,
				  enum devlink_info_version_type version_type,
				  void *version_cb_priv)
{
	struct devlink_flash_component_lookup_ctx *lookup_ctx = version_cb_priv;

	if (version_type != DEVLINK_INFO_VERSION_TYPE_COMPONENT ||
	    lookup_ctx->lookup_name_found)
		return;

	lookup_ctx->lookup_name_found =
		!strcmp(lookup_ctx->lookup_name, version_name);
}

static int devlink_flash_component_get(struct devlink *devlink,
				       struct nlattr *nla_component,
				       const char **p_component,
				       struct netlink_ext_ack *extack)
{
	struct devlink_flash_component_lookup_ctx lookup_ctx = {};
	struct devlink_info_req req = {};
	const char *component;
	int ret;

	if (!nla_component)
		return 0;

	component = nla_data(nla_component);

	if (!devlink->ops->info_get) {
		NL_SET_ERR_MSG_ATTR(extack, nla_component,
				    "component update is not supported by this device");
		return -EOPNOTSUPP;
	}

	lookup_ctx.lookup_name = component;
	req.version_cb = devlink_flash_component_lookup_cb;
	req.version_cb_priv = &lookup_ctx;

	ret = devlink->ops->info_get(devlink, &req, NULL);
	if (ret)
		return ret;

	if (!lookup_ctx.lookup_name_found) {
		NL_SET_ERR_MSG_ATTR(extack, nla_component,
				    "selected component is not supported by this device");
		return -EINVAL;
	}
	*p_component = component;
	return 0;
}

static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
				       struct genl_info *info)
{
	struct nlattr *nla_overwrite_mask, *nla_file_name;
	struct devlink_flash_update_params params = {};
	struct devlink *devlink = info->user_ptr[0];
	const char *file_name;
	u32 supported_params;
	int ret;

	if (!devlink->ops->flash_update)
		return -EOPNOTSUPP;

	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME))
		return -EINVAL;

	ret = devlink_flash_component_get(devlink,
					  info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT],
					  &params.component, info->extack);
	if (ret)
		return ret;

	supported_params = devlink->ops->supported_flash_update_params;

	nla_overwrite_mask = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK];
	if (nla_overwrite_mask) {
		struct nla_bitfield32 sections;

		if (!(supported_params & DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK)) {
			NL_SET_ERR_MSG_ATTR(info->extack, nla_overwrite_mask,
					    "overwrite settings are not supported by this device");
			return -EOPNOTSUPP;
		}
		sections = nla_get_bitfield32(nla_overwrite_mask);
		params.overwrite_mask = sections.value & sections.selector;
	}

	nla_file_name = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME];
	file_name = nla_data(nla_file_name);
	ret = request_firmware(&params.fw, file_name, devlink->dev);
	if (ret) {
		NL_SET_ERR_MSG_ATTR(info->extack, nla_file_name, "failed to locate the requested firmware file");
		return ret;
	}

	devlink_flash_update_begin_notify(devlink);
	ret = devlink->ops->flash_update(devlink, &params, info->extack);
	devlink_flash_update_end_notify(devlink);

	release_firmware(params.fw);

	return ret;
}

static int
devlink_nl_selftests_fill(struct sk_buff *msg, struct devlink *devlink,
			  u32 portid, u32 seq, int flags,
@@ -11222,37 +10982,6 @@ devl_trap_policers_unregister(struct devlink *devlink,
}
EXPORT_SYMBOL_GPL(devl_trap_policers_unregister);

int devlink_compat_flash_update(struct devlink *devlink, const char *file_name)
{
	struct devlink_flash_update_params params = {};
	int ret;

	devl_lock(devlink);
	if (!devl_is_registered(devlink)) {
		ret = -ENODEV;
		goto out_unlock;
	}

	if (!devlink->ops->flash_update) {
		ret = -EOPNOTSUPP;
		goto out_unlock;
	}

	ret = request_firmware(&params.fw, file_name, devlink->dev);
	if (ret)
		goto out_unlock;

	devlink_flash_update_begin_notify(devlink);
	ret = devlink->ops->flash_update(devlink, &params, NULL);
	devlink_flash_update_end_notify(devlink);

	release_firmware(params.fw);
out_unlock:
	devl_unlock(devlink);

	return ret;
}

int devlink_compat_phys_port_name_get(struct net_device *dev,
				      char *name, size_t len)
{