Skip to content

Commit

Permalink
devlink: Move devlink dev flash code to dev
Browse files Browse the repository at this point in the history
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: Moshe Shemesh <moshe@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Moshe Shemesh authored and Jakub Kicinski committed Feb 4, 2023
1 parent d60191c commit a13aab6
Show file tree
Hide file tree
Showing 3 changed files with 272 additions and 271 deletions.
271 changes: 271 additions & 0 deletions net/devlink/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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 change: 1 addition & 0 deletions net/devlink/devl_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Loading

0 comments on commit a13aab6

Please sign in to comment.