diff mbox series

[net-next,2/2] ice: support dry run of a flash update to validate firmware file

Message ID 20220720183433.2070122-3-jacob.e.keller@intel.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series devlink: implement dry run support for flash update | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 2 this patch: 2
netdev/cc_maintainers warning 8 maintainers not CCed: intel-wired-lan@lists.osuosl.org anthony.l.nguyen@intel.com jesse.brandeburg@intel.com corbet@lwn.net pabeni@redhat.com linux-doc@vger.kernel.org davem@davemloft.net edumazet@google.com
netdev/build_clang success Errors and warnings before: 6 this patch: 6
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 2 this patch: 2
netdev/checkpatch warning WARNING: line length of 86 exceeds 80 columns WARNING: line length of 94 exceeds 80 columns WARNING: line length of 99 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Jacob Keller July 20, 2022, 6:34 p.m. UTC
Now that devlink core flash update can handle dry run requests, update
the ice driver to allow validating a PLDM file in dry_run mode.

First, add a new dry_run field to the pldmfw context structure. This
indicates that the PLDM firmware file library should only validate the
file and verify that it has a matching record. Update the pldmfw
documentation to indicate this "dry run" mode.

In the ice driver, let the stack know that we support the dry run
attribute for flash update by setting the appropriate bit in the
.supported_flash_update_params field.

If the dry run is requested, notify the PLDM firmware library by setting
the context bit appropriately. Don't cancel a pending update during
a dry run.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
 Documentation/driver-api/pldmfw/index.rst      | 10 ++++++++++
 drivers/net/ethernet/intel/ice/ice_devlink.c   |  3 ++-
 drivers/net/ethernet/intel/ice/ice_fw_update.c | 14 ++++++++++----
 include/linux/pldmfw.h                         |  5 +++++
 lib/pldmfw/pldmfw.c                            | 12 ++++++++++++
 5 files changed, 39 insertions(+), 5 deletions(-)

Comments

Jiri Pirko July 21, 2022, 5:56 a.m. UTC | #1
Wed, Jul 20, 2022 at 08:34:33PM CEST, jacob.e.keller@intel.com wrote:
>Now that devlink core flash update can handle dry run requests, update
>the ice driver to allow validating a PLDM file in dry_run mode.
>
>First, add a new dry_run field to the pldmfw context structure. This
>indicates that the PLDM firmware file library should only validate the
>file and verify that it has a matching record. Update the pldmfw
>documentation to indicate this "dry run" mode.
>
>In the ice driver, let the stack know that we support the dry run
>attribute for flash update by setting the appropriate bit in the
>.supported_flash_update_params field.
>
>If the dry run is requested, notify the PLDM firmware library by setting
>the context bit appropriately. Don't cancel a pending update during
>a dry run.
>
>Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
>---
> Documentation/driver-api/pldmfw/index.rst      | 10 ++++++++++
> drivers/net/ethernet/intel/ice/ice_devlink.c   |  3 ++-
> drivers/net/ethernet/intel/ice/ice_fw_update.c | 14 ++++++++++----
> include/linux/pldmfw.h                         |  5 +++++
> lib/pldmfw/pldmfw.c                            | 12 ++++++++++++
> 5 files changed, 39 insertions(+), 5 deletions(-)
>
>diff --git a/Documentation/driver-api/pldmfw/index.rst b/Documentation/driver-api/pldmfw/index.rst
>index ad2c33ece30f..454b3ed6576a 100644
>--- a/Documentation/driver-api/pldmfw/index.rst
>+++ b/Documentation/driver-api/pldmfw/index.rst
>@@ -51,6 +51,16 @@ unaligned access of multi-byte fields, and to properly convert from Little
> Endian to CPU host format. Additionally the records, descriptors, and
> components are stored in linked lists.
> 
>+Validating a PLDM firmware file
>+===============================
>+
>+To simply validate a PLDM firmware file, and verify whether it applies to
>+the device, set the ``dry_run`` flag in the ``pldmfw`` context structure.
>+If this flag is set, the library will parse the file, validating its UUID
>+and checking if any record matches the device. Note that in a dry run, the
>+library will *not* issue any ops besides ``match_record``. It will not
>+attempt to send the component table or package data to the device firmware.
>+
> Performing a flash update
> =========================
> 
>diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c
>index 3337314a7b35..18214ea33e2d 100644
>--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
>+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
>@@ -467,7 +467,8 @@ ice_devlink_reload_empr_finish(struct devlink *devlink,
> }
> 
> static const struct devlink_ops ice_devlink_ops = {
>-	.supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
>+	.supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK |
>+					 DEVLINK_SUPPORT_FLASH_UPDATE_DRY_RUN,
> 	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
> 	/* The ice driver currently does not support driver reinit */
> 	.reload_down = ice_devlink_reload_empr_start,
>diff --git a/drivers/net/ethernet/intel/ice/ice_fw_update.c b/drivers/net/ethernet/intel/ice/ice_fw_update.c
>index 3dc5662d62a6..63317ae88186 100644
>--- a/drivers/net/ethernet/intel/ice/ice_fw_update.c
>+++ b/drivers/net/ethernet/intel/ice/ice_fw_update.c
>@@ -1015,15 +1015,21 @@ int ice_devlink_flash_update(struct devlink *devlink,
> 	else
> 		priv.context.ops = &ice_fwu_ops_e810;
> 	priv.context.dev = dev;
>+	priv.context.dry_run = params->dry_run;
> 	priv.extack = extack;
> 	priv.pf = pf;
> 	priv.activate_flags = preservation;
> 
>-	devlink_flash_update_status_notify(devlink, "Preparing to flash", NULL, 0, 0);
>+	if (params->dry_run)
>+		devlink_flash_update_status_notify(devlink, "Validating flash binary", NULL, 0, 0);

You do validation of the binary instead of the actual flash. Why is it
called "dry-run" then? Perhaps "validate" would be more suitable?



>+	else
>+		devlink_flash_update_status_notify(devlink, "Preparing to flash", NULL, 0, 0);
> 
>-	err = ice_cancel_pending_update(pf, NULL, extack);
>-	if (err)
>-		return err;
>+	if (!params->dry_run) {
>+		err = ice_cancel_pending_update(pf, NULL, extack);
>+		if (err)
>+			return err;
>+	}
> 
> 	err = ice_acquire_nvm(hw, ICE_RES_WRITE);
> 	if (err) {
>diff --git a/include/linux/pldmfw.h b/include/linux/pldmfw.h
>index 0fc831338226..d9add301582b 100644
>--- a/include/linux/pldmfw.h
>+++ b/include/linux/pldmfw.h
>@@ -124,10 +124,15 @@ struct pldmfw_ops;
>  * should embed this in a private structure and use container_of to obtain
>  * a pointer to their own data, used to implement the device specific
>  * operations.
>+ *
>+ * @ops: function pointers used as callbacks from the PLDMFW library
>+ * @dev: pointer to the device being updated
>+ * @dry_run: if true, only validate the file, do not perform an update.
>  */
> struct pldmfw {
> 	const struct pldmfw_ops *ops;
> 	struct device *dev;
>+	bool dry_run;
> };
> 
> bool pldmfw_op_pci_match_record(struct pldmfw *context, struct pldmfw_record *record);
>diff --git a/lib/pldmfw/pldmfw.c b/lib/pldmfw/pldmfw.c
>index 6e77eb6d8e72..29a132a39876 100644
>--- a/lib/pldmfw/pldmfw.c
>+++ b/lib/pldmfw/pldmfw.c
>@@ -827,6 +827,10 @@ static int pldm_finalize_update(struct pldmfw_priv *data)
>  * to the device firmware. Extract and write the flash data for each of the
>  * components indicated in the firmware file.
>  *
>+ * If the context->dry_run is set, this is a request for a dry run, i.e. to
>+ * only validate the PLDM firmware file. In this case, stop and exit after we
>+ * find a valid matching record.
>+ *
>  * Returns: zero on success, or a negative error code on failure.
>  */
> int pldmfw_flash_image(struct pldmfw *context, const struct firmware *fw)
>@@ -844,14 +848,22 @@ int pldmfw_flash_image(struct pldmfw *context, const struct firmware *fw)
> 	data->fw = fw;
> 	data->context = context;
> 
>+	/* Parse the image and make sure it is a valid PLDM firmware binary */
> 	err = pldm_parse_image(data);
> 	if (err)
> 		goto out_release_data;
> 
>+	/* Search for a record matching the device */
> 	err = pldm_find_matching_record(data);
> 	if (err)
> 		goto out_release_data;
> 
>+	/* If this is a dry run, do not perform an update */
>+	if (context->dry_run)
>+		goto out_release_data;
>+
>+	/* Perform the device update */
>+
> 	err = pldm_send_package_data(data);
> 	if (err)
> 		goto out_release_data;
>-- 
>2.35.1.456.ga9c7032d4631
>
Leon Romanovsky July 21, 2022, 7:53 a.m. UTC | #2
On Wed, Jul 20, 2022 at 11:34:33AM -0700, Jacob Keller wrote:
> Now that devlink core flash update can handle dry run requests, update
> the ice driver to allow validating a PLDM file in dry_run mode.
> 
> First, add a new dry_run field to the pldmfw context structure. This
> indicates that the PLDM firmware file library should only validate the
> file and verify that it has a matching record. Update the pldmfw
> documentation to indicate this "dry run" mode.
> 
> In the ice driver, let the stack know that we support the dry run
> attribute for flash update by setting the appropriate bit in the
> .supported_flash_update_params field.
> 
> If the dry run is requested, notify the PLDM firmware library by setting
> the context bit appropriately. Don't cancel a pending update during
> a dry run.
> 
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> ---
>  Documentation/driver-api/pldmfw/index.rst      | 10 ++++++++++
>  drivers/net/ethernet/intel/ice/ice_devlink.c   |  3 ++-
>  drivers/net/ethernet/intel/ice/ice_fw_update.c | 14 ++++++++++----
>  include/linux/pldmfw.h                         |  5 +++++
>  lib/pldmfw/pldmfw.c                            | 12 ++++++++++++
>  5 files changed, 39 insertions(+), 5 deletions(-)

<...>

>  struct pldmfw {
>  	const struct pldmfw_ops *ops;
>  	struct device *dev;
> +	bool dry_run;
>  };

Just a nitpick, it is better to write "u8 dry_run : 1;" and not bool.

Thanks
Jacob Keller July 21, 2022, 6:57 p.m. UTC | #3
> -----Original Message-----
> From: Jiri Pirko <jiri@resnulli.us>
> Sent: Wednesday, July 20, 2022 10:56 PM
> To: Keller, Jacob E <jacob.e.keller@intel.com>
> Cc: netdev@vger.kernel.org; Jakub Kicinski <kuba@kernel.org>
> Subject: Re: [net-next PATCH 2/2] ice: support dry run of a flash update to
> validate firmware file
> 
> Wed, Jul 20, 2022 at 08:34:33PM CEST, jacob.e.keller@intel.com wrote:
> >Now that devlink core flash update can handle dry run requests, update
> >the ice driver to allow validating a PLDM file in dry_run mode.
> >
> >First, add a new dry_run field to the pldmfw context structure. This
> >indicates that the PLDM firmware file library should only validate the
> >file and verify that it has a matching record. Update the pldmfw
> >documentation to indicate this "dry run" mode.
> >
> >In the ice driver, let the stack know that we support the dry run
> >attribute for flash update by setting the appropriate bit in the
> >.supported_flash_update_params field.
> >
> >If the dry run is requested, notify the PLDM firmware library by setting
> >the context bit appropriately. Don't cancel a pending update during
> >a dry run.
> >
> >Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> >---
> > Documentation/driver-api/pldmfw/index.rst      | 10 ++++++++++
> > drivers/net/ethernet/intel/ice/ice_devlink.c   |  3 ++-
> > drivers/net/ethernet/intel/ice/ice_fw_update.c | 14 ++++++++++----
> > include/linux/pldmfw.h                         |  5 +++++
> > lib/pldmfw/pldmfw.c                            | 12 ++++++++++++
> > 5 files changed, 39 insertions(+), 5 deletions(-)
> >
> >diff --git a/Documentation/driver-api/pldmfw/index.rst
> b/Documentation/driver-api/pldmfw/index.rst
> >index ad2c33ece30f..454b3ed6576a 100644
> >--- a/Documentation/driver-api/pldmfw/index.rst
> >+++ b/Documentation/driver-api/pldmfw/index.rst
> >@@ -51,6 +51,16 @@ unaligned access of multi-byte fields, and to properly
> convert from Little
> > Endian to CPU host format. Additionally the records, descriptors, and
> > components are stored in linked lists.
> >
> >+Validating a PLDM firmware file
> >+===============================
> >+
> >+To simply validate a PLDM firmware file, and verify whether it applies to
> >+the device, set the ``dry_run`` flag in the ``pldmfw`` context structure.
> >+If this flag is set, the library will parse the file, validating its UUID
> >+and checking if any record matches the device. Note that in a dry run, the
> >+library will *not* issue any ops besides ``match_record``. It will not
> >+attempt to send the component table or package data to the device firmware.
> >+
> > Performing a flash update
> > =========================
> >
> >diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c
> b/drivers/net/ethernet/intel/ice/ice_devlink.c
> >index 3337314a7b35..18214ea33e2d 100644
> >--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
> >+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
> >@@ -467,7 +467,8 @@ ice_devlink_reload_empr_finish(struct devlink *devlink,
> > }
> >
> > static const struct devlink_ops ice_devlink_ops = {
> >-	.supported_flash_update_params =
> DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
> >+	.supported_flash_update_params =
> DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK |
> >+
> DEVLINK_SUPPORT_FLASH_UPDATE_DRY_RUN,
> > 	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
> > 	/* The ice driver currently does not support driver reinit */
> > 	.reload_down = ice_devlink_reload_empr_start,
> >diff --git a/drivers/net/ethernet/intel/ice/ice_fw_update.c
> b/drivers/net/ethernet/intel/ice/ice_fw_update.c
> >index 3dc5662d62a6..63317ae88186 100644
> >--- a/drivers/net/ethernet/intel/ice/ice_fw_update.c
> >+++ b/drivers/net/ethernet/intel/ice/ice_fw_update.c
> >@@ -1015,15 +1015,21 @@ int ice_devlink_flash_update(struct devlink
> *devlink,
> > 	else
> > 		priv.context.ops = &ice_fwu_ops_e810;
> > 	priv.context.dev = dev;
> >+	priv.context.dry_run = params->dry_run;
> > 	priv.extack = extack;
> > 	priv.pf = pf;
> > 	priv.activate_flags = preservation;
> >
> >-	devlink_flash_update_status_notify(devlink, "Preparing to flash", NULL,
> 0, 0);
> >+	if (params->dry_run)
> >+		devlink_flash_update_status_notify(devlink, "Validating flash
> binary", NULL, 0, 0);
> 
> You do validation of the binary instead of the actual flash. Why is it
> called "dry-run" then? Perhaps "validate" would be more suitable?
> 

I had it as dry-run to match the naming of the devlink, but validate might make more sense for what we are able to do with PLDM here.

I don't believe we have  a method to actually load it and have firmware perform any further validation without actually updating.
diff mbox series

Patch

diff --git a/Documentation/driver-api/pldmfw/index.rst b/Documentation/driver-api/pldmfw/index.rst
index ad2c33ece30f..454b3ed6576a 100644
--- a/Documentation/driver-api/pldmfw/index.rst
+++ b/Documentation/driver-api/pldmfw/index.rst
@@ -51,6 +51,16 @@  unaligned access of multi-byte fields, and to properly convert from Little
 Endian to CPU host format. Additionally the records, descriptors, and
 components are stored in linked lists.
 
+Validating a PLDM firmware file
+===============================
+
+To simply validate a PLDM firmware file, and verify whether it applies to
+the device, set the ``dry_run`` flag in the ``pldmfw`` context structure.
+If this flag is set, the library will parse the file, validating its UUID
+and checking if any record matches the device. Note that in a dry run, the
+library will *not* issue any ops besides ``match_record``. It will not
+attempt to send the component table or package data to the device firmware.
+
 Performing a flash update
 =========================
 
diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c
index 3337314a7b35..18214ea33e2d 100644
--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
@@ -467,7 +467,8 @@  ice_devlink_reload_empr_finish(struct devlink *devlink,
 }
 
 static const struct devlink_ops ice_devlink_ops = {
-	.supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
+	.supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK |
+					 DEVLINK_SUPPORT_FLASH_UPDATE_DRY_RUN,
 	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
 	/* The ice driver currently does not support driver reinit */
 	.reload_down = ice_devlink_reload_empr_start,
diff --git a/drivers/net/ethernet/intel/ice/ice_fw_update.c b/drivers/net/ethernet/intel/ice/ice_fw_update.c
index 3dc5662d62a6..63317ae88186 100644
--- a/drivers/net/ethernet/intel/ice/ice_fw_update.c
+++ b/drivers/net/ethernet/intel/ice/ice_fw_update.c
@@ -1015,15 +1015,21 @@  int ice_devlink_flash_update(struct devlink *devlink,
 	else
 		priv.context.ops = &ice_fwu_ops_e810;
 	priv.context.dev = dev;
+	priv.context.dry_run = params->dry_run;
 	priv.extack = extack;
 	priv.pf = pf;
 	priv.activate_flags = preservation;
 
-	devlink_flash_update_status_notify(devlink, "Preparing to flash", NULL, 0, 0);
+	if (params->dry_run)
+		devlink_flash_update_status_notify(devlink, "Validating flash binary", NULL, 0, 0);
+	else
+		devlink_flash_update_status_notify(devlink, "Preparing to flash", NULL, 0, 0);
 
-	err = ice_cancel_pending_update(pf, NULL, extack);
-	if (err)
-		return err;
+	if (!params->dry_run) {
+		err = ice_cancel_pending_update(pf, NULL, extack);
+		if (err)
+			return err;
+	}
 
 	err = ice_acquire_nvm(hw, ICE_RES_WRITE);
 	if (err) {
diff --git a/include/linux/pldmfw.h b/include/linux/pldmfw.h
index 0fc831338226..d9add301582b 100644
--- a/include/linux/pldmfw.h
+++ b/include/linux/pldmfw.h
@@ -124,10 +124,15 @@  struct pldmfw_ops;
  * should embed this in a private structure and use container_of to obtain
  * a pointer to their own data, used to implement the device specific
  * operations.
+ *
+ * @ops: function pointers used as callbacks from the PLDMFW library
+ * @dev: pointer to the device being updated
+ * @dry_run: if true, only validate the file, do not perform an update.
  */
 struct pldmfw {
 	const struct pldmfw_ops *ops;
 	struct device *dev;
+	bool dry_run;
 };
 
 bool pldmfw_op_pci_match_record(struct pldmfw *context, struct pldmfw_record *record);
diff --git a/lib/pldmfw/pldmfw.c b/lib/pldmfw/pldmfw.c
index 6e77eb6d8e72..29a132a39876 100644
--- a/lib/pldmfw/pldmfw.c
+++ b/lib/pldmfw/pldmfw.c
@@ -827,6 +827,10 @@  static int pldm_finalize_update(struct pldmfw_priv *data)
  * to the device firmware. Extract and write the flash data for each of the
  * components indicated in the firmware file.
  *
+ * If the context->dry_run is set, this is a request for a dry run, i.e. to
+ * only validate the PLDM firmware file. In this case, stop and exit after we
+ * find a valid matching record.
+ *
  * Returns: zero on success, or a negative error code on failure.
  */
 int pldmfw_flash_image(struct pldmfw *context, const struct firmware *fw)
@@ -844,14 +848,22 @@  int pldmfw_flash_image(struct pldmfw *context, const struct firmware *fw)
 	data->fw = fw;
 	data->context = context;
 
+	/* Parse the image and make sure it is a valid PLDM firmware binary */
 	err = pldm_parse_image(data);
 	if (err)
 		goto out_release_data;
 
+	/* Search for a record matching the device */
 	err = pldm_find_matching_record(data);
 	if (err)
 		goto out_release_data;
 
+	/* If this is a dry run, do not perform an update */
+	if (context->dry_run)
+		goto out_release_data;
+
+	/* Perform the device update */
+
 	err = pldm_send_package_data(data);
 	if (err)
 		goto out_release_data;