Tue, Feb 26, 2019 at 09:20:14PM CET, jakub.kicin...@netronome.com wrote: >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.kicin...@netronome.com>
Acked-by: Jiri Pirko <j...@mellanox.com> Thanks! >--- > devlink/devlink.c | 54 ++++++++++++++++++++++++++++++++++++++++++ > man/man8/devlink-dev.8 | 32 +++++++++++++++++++++++++ > 2 files changed, 86 insertions(+) > >diff --git a/devlink/devlink.c b/devlink/devlink.c >index 960cdda99b5b..5c6cac1f76dd 100644 >--- a/devlink/devlink.c >+++ b/devlink/devlink.c >@@ -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_ADDRESS BIT(23) > #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 { > uint32_t present; /* flags of present items */ >@@ -230,6 +232,8 @@ struct dl_opts { > uint32_t region_snapshot_id; > uint64_t region_address; > uint64_t region_length; >+ const char *flash_file_name; >+ const char *flash_component; > }; > > struct dl { >@@ -1185,6 +1189,20 @@ static int dl_argv_parse(struct dl *dl, uint32_t >o_required, > if (err) > return err; > 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 { > pr_err("Unknown option \"%s\"\n", dl_argv(dl)); > return -EINVAL; >@@ -1389,6 +1407,12 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl >*dl) > if (opts->present & DL_OPT_REGION_LENGTH) > mnl_attr_put_u64(nlh, DEVLINK_ATTR_REGION_CHUNK_LEN, > 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, >@@ -1451,6 +1475,7 @@ static void cmd_dev_help(void) > pr_err(" devlink dev param show [DEV name PARAMETER]\n"); > pr_err(" devlink dev reload 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, >@@ -2583,6 +2608,32 @@ static int cmd_dev_info(struct dl *dl) > 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) > { > if (dl_argv_match(dl, "help")) { >@@ -2604,6 +2655,9 @@ static int cmd_dev(struct dl *dl) > } else if (dl_argv_match(dl, "info")) { > dl_arg_inc(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)); > return -ENOENT; >diff --git a/man/man8/devlink-dev.8 b/man/man8/devlink-dev.8 >index 47838371fecd..1804463b2321 100644 >--- a/man/man8/devlink-dev.8 >+++ b/man/man8/devlink-dev.8 >@@ -69,6 +69,16 @@ devlink-dev \- devlink device configuration > .IR DEV > .RI "]" > >+.ti -8 >+.BR "devlink dev flash" >+.IR DEV >+.BR file >+.IR PATH >+.RI "[" >+.BR target >+.IR ID >+.RI "]" >+ > .SH "DESCRIPTION" > .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. > 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" > .PP > devlink dev show >-- >2.19.2 >