Commit 3af4b40b authored by Jacob Keller's avatar Jacob Keller Committed by Jakub Kicinski
Browse files

ice: implement direct read for NVM and Shadow RAM regions



Implement the .read handler for the NVM and Shadow RAM regions. This
enables user space to read a small chunk of the flash without needing the
overhead of creating a full snapshot.

Update the documentation for ice to detail which regions have direct read
support.

Signed-off-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Acked-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 2d019784
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -198,8 +198,12 @@ device data.
      - The contents of the device firmware's capabilities buffer. Useful to
        determine the current state and configuration of the device.

Users can request an immediate capture of a snapshot via the
``DEVLINK_CMD_REGION_NEW``
Both the ``nvm-flash`` and ``shadow-ram`` regions can be accessed without a
snapshot. The ``device-caps`` region requires a snapshot as the contents are
sent by firmware and can't be split into separate reads.

Users can request an immediate capture of a snapshot for all three regions
via the ``DEVLINK_CMD_REGION_NEW`` command.

.. code:: shell

+69 −0
Original line number Diff line number Diff line
@@ -1687,6 +1687,73 @@ static int ice_devlink_nvm_snapshot(struct devlink *devlink,
	return 0;
}

/**
 * ice_devlink_nvm_read - Read a portion of NVM flash contents
 * @devlink: the devlink instance
 * @ops: the devlink region to snapshot
 * @extack: extended ACK response structure
 * @offset: the offset to start at
 * @size: the amount to read
 * @data: the data buffer to read into
 *
 * This function is called in response to DEVLINK_CMD_REGION_READ to directly
 * read a section of the NVM contents.
 *
 * It reads from either the nvm-flash or shadow-ram region contents.
 *
 * @returns zero on success, and updates the data pointer. Returns a non-zero
 * error code on failure.
 */
static int ice_devlink_nvm_read(struct devlink *devlink,
				const struct devlink_region_ops *ops,
				struct netlink_ext_ack *extack,
				u64 offset, u32 size, u8 *data)
{
	struct ice_pf *pf = devlink_priv(devlink);
	struct device *dev = ice_pf_to_dev(pf);
	struct ice_hw *hw = &pf->hw;
	bool read_shadow_ram;
	u64 nvm_size;
	int status;

	if (ops == &ice_nvm_region_ops) {
		read_shadow_ram = false;
		nvm_size = hw->flash.flash_size;
	} else if (ops == &ice_sram_region_ops) {
		read_shadow_ram = true;
		nvm_size = hw->flash.sr_words * 2u;
	} else {
		NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function");
		return -EOPNOTSUPP;
	}

	if (offset + size >= nvm_size) {
		NL_SET_ERR_MSG_MOD(extack, "Cannot read beyond the region size");
		return -ERANGE;
	}

	status = ice_acquire_nvm(hw, ICE_RES_READ);
	if (status) {
		dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
			status, hw->adminq.sq_last_status);
		NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
		return -EIO;
	}

	status = ice_read_flat_nvm(hw, (u32)offset, &size, data,
				   read_shadow_ram);
	if (status) {
		dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n",
			size, status, hw->adminq.sq_last_status);
		NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents");
		ice_release_nvm(hw);
		return -EIO;
	}
	ice_release_nvm(hw);

	return 0;
}

/**
 * ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities
 * @devlink: the devlink instance
@@ -1735,12 +1802,14 @@ static const struct devlink_region_ops ice_nvm_region_ops = {
	.name = "nvm-flash",
	.destructor = vfree,
	.snapshot = ice_devlink_nvm_snapshot,
	.read = ice_devlink_nvm_read,
};

static const struct devlink_region_ops ice_sram_region_ops = {
	.name = "shadow-ram",
	.destructor = vfree,
	.snapshot = ice_devlink_nvm_snapshot,
	.read = ice_devlink_nvm_read,
};

static const struct devlink_region_ops ice_devcaps_region_ops = {