Commit cb9e4a73 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'devlink-flash-update-overwrite-mask'



Jacob Keller says:

====================
devlink flash update overwrite mask

This series introduces support for a new attribute to the flash update
command: DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK.

This attribute is a bitfield which allows userspace to specify what set of
subfields to overwrite when performing a flash update for a device.

The intention is to support the ability to control the behavior of
overwriting the configuration and identifying fields in the Intel ice device
flash update process. This is necessary  as the firmware layout for the ice
device includes some settings and configuration within the same flash
section as the main firmware binary.

This series, and the accompanying iproute2 series, introduce support for the
attribute. Once applied, the overwrite support can be be invoked via
devlink:

  # overwrite settings
  devlink dev flash pci/0000:af:00.0 file firmware.bin overwrite settings

  # overwrite identifiers and settings
  devlink dev flash pci/0000:af:00.0 file firmware.bin overwrite settings overwrite identifiers

To aid in the safe addition of new parameters, first some refactoring is
done to the .flash_update function: its parameters are converted from a
series of function arguments into a structure. This makes it easier to add
the new parameter without changing the signature of the .flash_update
handler in the future. Additionally, a "supported_flash_update_params" field
is added to devlink_ops. This field is similar to the ethtool
"supported_coalesc_params" field. The devlink core will now check that the
DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT bit is set before forwarding the
component attribute. Similarly, the new overwrite attribute will also
require a supported bit.

Doing these refactors will aid in adding any other attributes in the future,
and creates a good pattern for other interfaces to use in the future. By
requiring drivers to opt-in, we reduce the risk of accidentally breaking
drivers when ever we add an additional parameter. We also reduce boiler
plate code in drivers which do not support the parameters.

Changes since v9:
* rebased to current net-next, no other changes

Changes since v7
* resend, hopefully avoiding the SMTP server issues I experienced on Friday

Changes since v6
* Rebased to current net-next to resolve conflicts
* Added changes to the ionic driver that recently merged flash update support
* Fixed the changes for mlxsw to apply to core instead of spectrum.c after
  the recent refactor.
* Picked up the review tags from Jakub

Changes since v5
* Fix *all* of the BIT usage to use _BITUL() (thanks Jakub!)

Changes since v4
* Renamed nla_overwrite to nla_overwrite_mask at Jiri's suggestion
* Added "by this device" to the netlink error messages for unsupported
  attributes
* Removed use of BIT() in the uapi header
* Fixed the commit message for the netdevsim patch
* Picked up Jakub's reviewed
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6fba737a 50db1bca
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -16,6 +16,34 @@ Note that the file name is a path relative to the firmware loading path
(usually ``/lib/firmware/``). Drivers may send status updates to inform
user space about the progress of the update operation.

Overwrite Mask
==============

The ``devlink-flash`` command allows optionally specifying a mask indicating
how the device should handle subsections of flash components when updating.
This mask indicates the set of sections which are allowed to be overwritten.

.. list-table:: List of overwrite mask bits
   :widths: 5 95

   * - Name
     - Description
   * - ``DEVLINK_FLASH_OVERWRITE_SETTINGS``
     - Indicates that the device should overwrite settings in the components
       being updated with the settings found in the provided image.
   * - ``DEVLINK_FLASH_OVERWRITE_IDENTIFIERS``
     - Indicates that the device should overwrite identifiers in the
       components being updated with the identifiers found in the provided
       image. This includes MAC addresses, serial IDs, and similar device
       identifiers.

Multiple overwrite bits may be combined and requested together. If no bits
are provided, it is expected that the device only update firmware binaries
in the components being updated. Settings and identifiers are expected to be
preserved across the update. A device may not support every combination and
the driver for such a device must reject any combination which cannot be
faithfully implemented.

Firmware Loading
================

+31 −0
Original line number Diff line number Diff line
@@ -81,6 +81,37 @@ The ``ice`` driver reports the following versions
      - 0xee16ced7
      - The first 4 bytes of the hash of the netlist module contents.

Flash Update
============

The ``ice`` driver implements support for flash update using the
``devlink-flash`` interface. It supports updating the device flash using a
combined flash image that contains the ``fw.mgmt``, ``fw.undi``, and
``fw.netlist`` components.

.. list-table:: List of supported overwrite modes
   :widths: 5 95

   * - Bits
     - Behavior
   * - ``DEVLINK_FLASH_OVERWRITE_SETTINGS``
     - Do not preserve settings stored in the flash components being
       updated. This includes overwriting the port configuration that
       determines the number of physical functions the device will
       initialize with.
   * - ``DEVLINK_FLASH_OVERWRITE_SETTINGS`` and ``DEVLINK_FLASH_OVERWRITE_IDENTIFIERS``
     - Do not preserve either settings or identifiers. Overwrite everything
       in the flash with the contents from the provided image, without
       performing any preservation. This includes overwriting device
       identifying fields such as the MAC address, VPD area, and device
       serial number. It is expected that this combination be used with an
       image customized for the specific device.

The ice hardware does not support overwriting only identifiers while
preserving settings, and thus ``DEVLINK_FLASH_OVERWRITE_IDENTIFIERS`` on its
own will be rejected. If no overwrite mask is provided, the firmware will be
instructed to preserve all settings and identifying fields when updating.

Regions
=======

+7 −12
Original line number Diff line number Diff line
@@ -17,15 +17,13 @@
#include "bnxt_ethtool.h"

static int
bnxt_dl_flash_update(struct devlink *dl, const char *filename,
		     const char *region, struct netlink_ext_ack *extack)
bnxt_dl_flash_update(struct devlink *dl,
		     struct devlink_flash_update_params *params,
		     struct netlink_ext_ack *extack)
{
	struct bnxt *bp = bnxt_get_bp_from_dl(dl);
	int rc;

	if (region)
		return -EOPNOTSUPP;

	if (!BNXT_PF(bp)) {
		NL_SET_ERR_MSG_MOD(extack,
				   "flash update not supported from a VF");
@@ -33,15 +31,12 @@ bnxt_dl_flash_update(struct devlink *dl, const char *filename,
	}

	devlink_flash_update_begin_notify(dl);
	devlink_flash_update_status_notify(dl, "Preparing to flash", region, 0,
					   0);
	rc = bnxt_flash_package_from_file(bp->dev, filename, 0);
	devlink_flash_update_status_notify(dl, "Preparing to flash", NULL, 0, 0);
	rc = bnxt_flash_package_from_file(bp->dev, params->file_name, 0);
	if (!rc)
		devlink_flash_update_status_notify(dl, "Flashing done", region,
						   0, 0);
		devlink_flash_update_status_notify(dl, "Flashing done", NULL, 0, 0);
	else
		devlink_flash_update_status_notify(dl, "Flashing failed",
						   region, 0, 0);
		devlink_flash_update_status_notify(dl, "Flashing failed", NULL, 0, 0);
	devlink_flash_update_end_notify(dl);
	return rc;
}
+2 −6
Original line number Diff line number Diff line
@@ -281,18 +281,14 @@ static int hinic_firmware_update(struct hinic_devlink_priv *priv,
}

static int hinic_devlink_flash_update(struct devlink *devlink,
				      const char *file_name,
				      const char *component,
				      struct devlink_flash_update_params *params,
				      struct netlink_ext_ack *extack)
{
	struct hinic_devlink_priv *priv = devlink_priv(devlink);
	const struct firmware *fw;
	int err;

	if (component)
		return -EOPNOTSUPP;

	err = request_firmware_direct(&fw, file_name,
	err = request_firmware_direct(&fw, params->file_name,
				      &priv->hwdev->hwif->pdev->dev);
	if (err)
		return err;
+23 −11
Original line number Diff line number Diff line
@@ -233,8 +233,7 @@ static int ice_devlink_info_get(struct devlink *devlink,
/**
 * ice_devlink_flash_update - Update firmware stored in flash on the device
 * @devlink: pointer to devlink associated with device to update
 * @path: the path of the firmware file to use via request_firmware
 * @component: name of the component to update, or NULL
 * @params: flash update parameters
 * @extack: netlink extended ACK structure
 *
 * Perform a device flash update. The bulk of the update logic is contained
@@ -243,38 +242,50 @@ static int ice_devlink_info_get(struct devlink *devlink,
 * Returns: zero on success, or an error code on failure.
 */
static int
ice_devlink_flash_update(struct devlink *devlink, const char *path,
			 const char *component, struct netlink_ext_ack *extack)
ice_devlink_flash_update(struct devlink *devlink,
			 struct devlink_flash_update_params *params,
			 struct netlink_ext_ack *extack)
{
	struct ice_pf *pf = devlink_priv(devlink);
	struct device *dev = &pf->pdev->dev;
	struct ice_hw *hw = &pf->hw;
	const struct firmware *fw;
	u8 preservation;
	int err;

	/* individual component update is not yet supported */
	if (component)
	if (!params->overwrite_mask) {
		/* preserve all settings and identifiers */
		preservation = ICE_AQC_NVM_PRESERVE_ALL;
	} else if (params->overwrite_mask == DEVLINK_FLASH_OVERWRITE_SETTINGS) {
		/* overwrite settings, but preserve the vital device identifiers */
		preservation = ICE_AQC_NVM_PRESERVE_SELECTED;
	} else if (params->overwrite_mask == (DEVLINK_FLASH_OVERWRITE_SETTINGS |
					      DEVLINK_FLASH_OVERWRITE_IDENTIFIERS)) {
		/* overwrite both settings and identifiers, preserve nothing */
		preservation = ICE_AQC_NVM_NO_PRESERVATION;
	} else {
		NL_SET_ERR_MSG_MOD(extack, "Requested overwrite mask is not supported");
		return -EOPNOTSUPP;
	}

	if (!hw->dev_caps.common_cap.nvm_unified_update) {
		NL_SET_ERR_MSG_MOD(extack, "Current firmware does not support unified update");
		return -EOPNOTSUPP;
	}

	err = ice_check_for_pending_update(pf, component, extack);
	err = ice_check_for_pending_update(pf, NULL, extack);
	if (err)
		return err;

	err = request_firmware(&fw, path, dev);
	err = request_firmware(&fw, params->file_name, dev);
	if (err) {
		NL_SET_ERR_MSG_MOD(extack, "Unable to read file from disk");
		return err;
	}

	devlink_flash_update_begin_notify(devlink);
	devlink_flash_update_status_notify(devlink, "Preparing to flash",
					   component, 0, 0);
	err = ice_flash_pldm_image(pf, fw, extack);
	devlink_flash_update_status_notify(devlink, "Preparing to flash", NULL, 0, 0);
	err = ice_flash_pldm_image(pf, fw, preservation, extack);
	devlink_flash_update_end_notify(devlink);

	release_firmware(fw);
@@ -283,6 +294,7 @@ ice_devlink_flash_update(struct devlink *devlink, const char *path,
}

static const struct devlink_ops ice_devlink_ops = {
	.supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
	.info_get = ice_devlink_info_get,
	.flash_update = ice_devlink_flash_update,
};
Loading