devlink: add support for updating device flash
Add new command for updating flash of devices via devlink API. Example: $ cp flash-boot.bin /lib/firmware/ $ devlink dev flash pci/0000:05:00.0 file flash-boot.bin Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
parent
41fda879a1
commit
d326d79c22
|
|
@ -199,6 +199,8 @@ static void ifname_map_free(struct ifname_map *ifname_map)
|
||||||
#define DL_OPT_REGION_SNAPSHOT_ID BIT(22)
|
#define DL_OPT_REGION_SNAPSHOT_ID BIT(22)
|
||||||
#define DL_OPT_REGION_ADDRESS BIT(23)
|
#define DL_OPT_REGION_ADDRESS BIT(23)
|
||||||
#define DL_OPT_REGION_LENGTH BIT(24)
|
#define DL_OPT_REGION_LENGTH BIT(24)
|
||||||
|
#define DL_OPT_FLASH_FILE_NAME BIT(25)
|
||||||
|
#define DL_OPT_FLASH_COMPONENT BIT(26)
|
||||||
|
|
||||||
struct dl_opts {
|
struct dl_opts {
|
||||||
uint32_t present; /* flags of present items */
|
uint32_t present; /* flags of present items */
|
||||||
|
|
@ -230,6 +232,8 @@ struct dl_opts {
|
||||||
uint32_t region_snapshot_id;
|
uint32_t region_snapshot_id;
|
||||||
uint64_t region_address;
|
uint64_t region_address;
|
||||||
uint64_t region_length;
|
uint64_t region_length;
|
||||||
|
const char *flash_file_name;
|
||||||
|
const char *flash_component;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dl {
|
struct dl {
|
||||||
|
|
@ -1185,6 +1189,20 @@ static int dl_argv_parse(struct dl *dl, uint32_t o_required,
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
o_found |= DL_OPT_REGION_LENGTH;
|
o_found |= DL_OPT_REGION_LENGTH;
|
||||||
|
} else if (dl_argv_match(dl, "file") &&
|
||||||
|
(o_all & DL_OPT_FLASH_FILE_NAME)) {
|
||||||
|
dl_arg_inc(dl);
|
||||||
|
err = dl_argv_str(dl, &opts->flash_file_name);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
o_found |= DL_OPT_FLASH_FILE_NAME;
|
||||||
|
} else if (dl_argv_match(dl, "component") &&
|
||||||
|
(o_all & DL_OPT_FLASH_COMPONENT)) {
|
||||||
|
dl_arg_inc(dl);
|
||||||
|
err = dl_argv_str(dl, &opts->flash_component);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
o_found |= DL_OPT_FLASH_COMPONENT;
|
||||||
} else {
|
} else {
|
||||||
pr_err("Unknown option \"%s\"\n", dl_argv(dl));
|
pr_err("Unknown option \"%s\"\n", dl_argv(dl));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
@ -1389,6 +1407,12 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl)
|
||||||
if (opts->present & DL_OPT_REGION_LENGTH)
|
if (opts->present & DL_OPT_REGION_LENGTH)
|
||||||
mnl_attr_put_u64(nlh, DEVLINK_ATTR_REGION_CHUNK_LEN,
|
mnl_attr_put_u64(nlh, DEVLINK_ATTR_REGION_CHUNK_LEN,
|
||||||
opts->region_length);
|
opts->region_length);
|
||||||
|
if (opts->present & DL_OPT_FLASH_FILE_NAME)
|
||||||
|
mnl_attr_put_strz(nlh, DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME,
|
||||||
|
opts->flash_file_name);
|
||||||
|
if (opts->present & DL_OPT_FLASH_COMPONENT)
|
||||||
|
mnl_attr_put_strz(nlh, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,
|
||||||
|
opts->flash_component);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl,
|
static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl,
|
||||||
|
|
@ -1451,6 +1475,7 @@ static void cmd_dev_help(void)
|
||||||
pr_err(" devlink dev param show [DEV name PARAMETER]\n");
|
pr_err(" devlink dev param show [DEV name PARAMETER]\n");
|
||||||
pr_err(" devlink dev reload DEV\n");
|
pr_err(" devlink dev reload DEV\n");
|
||||||
pr_err(" devlink dev info [ DEV ]\n");
|
pr_err(" devlink dev info [ DEV ]\n");
|
||||||
|
pr_err(" devlink dev flash DEV file PATH [ component NAME ]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmp_arr_last_handle(struct dl *dl, const char *bus_name,
|
static bool cmp_arr_last_handle(struct dl *dl, const char *bus_name,
|
||||||
|
|
@ -2583,6 +2608,32 @@ static int cmd_dev_info(struct dl *dl)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cmd_dev_flash_help(void)
|
||||||
|
{
|
||||||
|
pr_err("Usage: devlink dev flash DEV file PATH [ component NAME ]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_dev_flash(struct dl *dl)
|
||||||
|
{
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (dl_argv_match(dl, "help") || dl_no_arg(dl)) {
|
||||||
|
cmd_dev_flash_help();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_FLASH_UPDATE,
|
||||||
|
NLM_F_REQUEST | NLM_F_ACK);
|
||||||
|
|
||||||
|
err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_FLASH_FILE_NAME,
|
||||||
|
DL_OPT_FLASH_COMPONENT);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int cmd_dev(struct dl *dl)
|
static int cmd_dev(struct dl *dl)
|
||||||
{
|
{
|
||||||
if (dl_argv_match(dl, "help")) {
|
if (dl_argv_match(dl, "help")) {
|
||||||
|
|
@ -2604,6 +2655,9 @@ static int cmd_dev(struct dl *dl)
|
||||||
} else if (dl_argv_match(dl, "info")) {
|
} else if (dl_argv_match(dl, "info")) {
|
||||||
dl_arg_inc(dl);
|
dl_arg_inc(dl);
|
||||||
return cmd_dev_info(dl);
|
return cmd_dev_info(dl);
|
||||||
|
} else if (dl_argv_match(dl, "flash")) {
|
||||||
|
dl_arg_inc(dl);
|
||||||
|
return cmd_dev_flash(dl);
|
||||||
}
|
}
|
||||||
pr_err("Command \"%s\" not found\n", dl_argv(dl));
|
pr_err("Command \"%s\" not found\n", dl_argv(dl));
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,16 @@ devlink-dev \- devlink device configuration
|
||||||
.IR DEV
|
.IR DEV
|
||||||
.RI "]"
|
.RI "]"
|
||||||
|
|
||||||
|
.ti -8
|
||||||
|
.BR "devlink dev flash"
|
||||||
|
.IR DEV
|
||||||
|
.BR file
|
||||||
|
.IR PATH
|
||||||
|
.RI "["
|
||||||
|
.BR target
|
||||||
|
.IR ID
|
||||||
|
.RI "]"
|
||||||
|
|
||||||
.SH "DESCRIPTION"
|
.SH "DESCRIPTION"
|
||||||
.SS devlink dev show - display devlink device attributes
|
.SS devlink dev show - display devlink device attributes
|
||||||
|
|
||||||
|
|
@ -177,6 +187,28 @@ versions may differ after flash has been updated, but before reboot.
|
||||||
- specifies the devlink device to show.
|
- specifies the devlink device to show.
|
||||||
If this argument is omitted all devices are listed.
|
If this argument is omitted all devices are listed.
|
||||||
|
|
||||||
|
.SS devlink dev flash - write device's non-volatile memory.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
.I "DEV"
|
||||||
|
- specifies the devlink device to write to.
|
||||||
|
|
||||||
|
.BR file
|
||||||
|
.I PATH
|
||||||
|
- Path to the file which will be written into device's flash. The path needs
|
||||||
|
to be relative to one of the directories searched by the kernel firmware loaded,
|
||||||
|
such as /lib/firmware.
|
||||||
|
|
||||||
|
.BR component
|
||||||
|
.I NAME
|
||||||
|
- If device stores multiple firmware images in non-volatile memory, this
|
||||||
|
parameter may be used to indicate which firmware image should be written.
|
||||||
|
The value of
|
||||||
|
.I NAME
|
||||||
|
should match the component names from
|
||||||
|
.B "devlink dev info"
|
||||||
|
and may be driver-dependent.
|
||||||
|
|
||||||
.SH "EXAMPLES"
|
.SH "EXAMPLES"
|
||||||
.PP
|
.PP
|
||||||
devlink dev show
|
devlink dev show
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue