Commit 247dd97d authored by Wojciech Drewek's avatar Wojciech Drewek Committed by Tony Nguyen
Browse files

ice: Refactor status flow for DDP load



Before this change, final state of the DDP pkg load process was
dependent on many variables such as: ice_status, pkg version,
ice_aq_err. The last one had be stored in hw->pkg_dwnld_status.
It was impossible to conclude this state just from ice_status, that's
why logging process of DDP pkg load in the caller was a little bit
complicated.

With this patch new status enum is introduced - ice_ddp_state.
It covers all the possible final states of the loading process.
What's tricky for ice_ddp_state is that not only
ICE_DDP_PKG_SUCCESS(=0) means that load was successful. Actually
three states mean that:
 - ICE_DDP_PKG_SUCCESS
 - ICE_DDP_PKG_SAME_VERSION_ALREADY_LOADED
 - ICE_DDP_PKG_COMPATIBLE_ALREADY_LOADED
ice_is_init_pkg_successful can tell that information.

One ddp_state should not be used outside of ice_init_pkg which is
ICE_DDP_PKG_ALREADY_LOADED. It is more generic, it is used in
ice_dwnld_cfg_bufs to see if pkg is already loaded. At this point
we can't use one of the specific one (SAME_VERSION, COMPATIBLE,
NOT_SUPPORTED) because we don't have information on the package
currently loaded in HW (we are before calling ice_get_pkg_info).

We can get rid of hw->pkg_dwnld_status because we are immediately
mapping aq errors to ice_ddp_state in ice_dwnld_cfg_bufs.

Other errors like ICE_ERR_NO_MEMORY, ICE_ERR_PARAM are mapped the
generic ICE_DDP_PKG_ERR.

Suggested-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Signed-off-by: default avatarWojciech Drewek <wojciech.drewek@intel.com>
Tested-by: default avatarTony Brelinski <tony.brelinski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent fabf480b
Loading
Loading
Loading
Loading
+144 −80
Original line number Diff line number Diff line
@@ -993,6 +993,22 @@ ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
	return status;
}

static enum ice_ddp_state ice_map_aq_err_to_ddp_state(enum ice_aq_err aq_err)
{
	switch (aq_err) {
	case ICE_AQ_RC_ENOSEC:
	case ICE_AQ_RC_EBADSIG:
		return ICE_DDP_PKG_FILE_SIGNATURE_INVALID;
	case ICE_AQ_RC_ESVN:
		return ICE_DDP_PKG_FILE_REVISION_TOO_LOW;
	case ICE_AQ_RC_EBADMAN:
	case ICE_AQ_RC_EBADBUF:
		return ICE_DDP_PKG_LOAD_ERROR;
	default:
		return ICE_DDP_PKG_ERR;
	}
}

/**
 * ice_dwnld_cfg_bufs
 * @hw: pointer to the hardware structure
@@ -1003,15 +1019,17 @@ ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
 * to the firmware. Metadata buffers are skipped, and the first metadata buffer
 * found indicates that the rest of the buffers are all metadata buffers.
 */
static enum ice_status
static enum ice_ddp_state
ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
{
	enum ice_ddp_state state = ICE_DDP_PKG_SUCCESS;
	enum ice_status status;
	struct ice_buf_hdr *bh;
	enum ice_aq_err err;
	u32 offset, info, i;

	if (!bufs || !count)
		return ICE_ERR_PARAM;
		return ICE_DDP_PKG_ERR;

	/* If the first buffer's first section has its metadata bit set
	 * then there are no buffers to be downloaded, and the operation is
@@ -1019,20 +1037,13 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
	 */
	bh = (struct ice_buf_hdr *)bufs;
	if (le32_to_cpu(bh->section_entry[0].type) & ICE_METADATA_BUF)
		return 0;

	/* reset pkg_dwnld_status in case this function is called in the
	 * reset/rebuild flow
	 */
	hw->pkg_dwnld_status = ICE_AQ_RC_OK;
		return ICE_DDP_PKG_SUCCESS;

	status = ice_acquire_global_cfg_lock(hw, ICE_RES_WRITE);
	if (status) {
		if (status == ICE_ERR_AQ_NO_WORK)
			hw->pkg_dwnld_status = ICE_AQ_RC_EEXIST;
		else
			hw->pkg_dwnld_status = hw->adminq.sq_last_status;
		return status;
			return ICE_DDP_PKG_ALREADY_LOADED;
		return ice_map_aq_err_to_ddp_state(hw->adminq.sq_last_status);
	}

	for (i = 0; i < count; i++) {
@@ -1058,11 +1069,11 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
					     &offset, &info, NULL);

		/* Save AQ status from download package */
		hw->pkg_dwnld_status = hw->adminq.sq_last_status;
		if (status) {
			ice_debug(hw, ICE_DBG_PKG, "Pkg download failed: err %d off %d inf %d\n",
				  status, offset, info);

			err = hw->adminq.sq_last_status;
			state = ice_map_aq_err_to_ddp_state(err);
			break;
		}

@@ -1072,7 +1083,7 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)

	ice_release_global_cfg_lock(hw);

	return status;
	return state;
}

/**
@@ -1103,7 +1114,7 @@ ice_aq_get_pkg_info_list(struct ice_hw *hw,
 *
 * Handles the download of a complete package.
 */
static enum ice_status
static enum ice_ddp_state
ice_download_pkg(struct ice_hw *hw, struct ice_seg *ice_seg)
{
	struct ice_buf_table *ice_buf_tbl;
@@ -1134,13 +1145,13 @@ ice_download_pkg(struct ice_hw *hw, struct ice_seg *ice_seg)
 *
 * Saves off the package details into the HW structure.
 */
static enum ice_status
static enum ice_ddp_state
ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
{
	struct ice_generic_seg_hdr *seg_hdr;

	if (!pkg_hdr)
		return ICE_ERR_PARAM;
		return ICE_DDP_PKG_ERR;

	seg_hdr = ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE, pkg_hdr);
	if (seg_hdr) {
@@ -1154,7 +1165,7 @@ ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
					    ICE_SID_METADATA);
		if (!meta) {
			ice_debug(hw, ICE_DBG_INIT, "Did not find ice metadata section in package\n");
			return ICE_ERR_CFG;
			return ICE_DDP_PKG_INVALID_FILE;
		}

		hw->pkg_ver = meta->ver;
@@ -1176,10 +1187,10 @@ ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
			  seg_hdr->seg_id);
	} else {
		ice_debug(hw, ICE_DBG_INIT, "Did not find ice segment in driver package\n");
		return ICE_ERR_CFG;
		return ICE_DDP_PKG_INVALID_FILE;
	}

	return 0;
	return ICE_DDP_PKG_SUCCESS;
}

/**
@@ -1188,21 +1199,22 @@ ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
 *
 * Store details of the package currently loaded in HW into the HW structure.
 */
static enum ice_status ice_get_pkg_info(struct ice_hw *hw)
static enum ice_ddp_state ice_get_pkg_info(struct ice_hw *hw)
{
	enum ice_ddp_state state = ICE_DDP_PKG_SUCCESS;
	struct ice_aqc_get_pkg_info_resp *pkg_info;
	enum ice_status status;
	u16 size;
	u32 i;

	size = struct_size(pkg_info, pkg_info, ICE_PKG_CNT);
	pkg_info = kzalloc(size, GFP_KERNEL);
	if (!pkg_info)
		return ICE_ERR_NO_MEMORY;
		return ICE_DDP_PKG_ERR;

	status = ice_aq_get_pkg_info_list(hw, pkg_info, size, NULL);
	if (status)
	if (ice_aq_get_pkg_info_list(hw, pkg_info, size, NULL)) {
		state = ICE_DDP_PKG_ERR;
		goto init_pkg_free_alloc;
	}

	for (i = 0; i < le32_to_cpu(pkg_info->count); i++) {
#define ICE_PKG_FLAG_COUNT	4
@@ -1237,7 +1249,7 @@ static enum ice_status ice_get_pkg_info(struct ice_hw *hw)
init_pkg_free_alloc:
	kfree(pkg_info);

	return status;
	return state;
}

/**
@@ -1248,28 +1260,28 @@ static enum ice_status ice_get_pkg_info(struct ice_hw *hw)
 * Verifies various attributes of the package file, including length, format
 * version, and the requirement of at least one segment.
 */
static enum ice_status ice_verify_pkg(struct ice_pkg_hdr *pkg, u32 len)
static enum ice_ddp_state ice_verify_pkg(struct ice_pkg_hdr *pkg, u32 len)
{
	u32 seg_count;
	u32 i;

	if (len < struct_size(pkg, seg_offset, 1))
		return ICE_ERR_BUF_TOO_SHORT;
		return ICE_DDP_PKG_INVALID_FILE;

	if (pkg->pkg_format_ver.major != ICE_PKG_FMT_VER_MAJ ||
	    pkg->pkg_format_ver.minor != ICE_PKG_FMT_VER_MNR ||
	    pkg->pkg_format_ver.update != ICE_PKG_FMT_VER_UPD ||
	    pkg->pkg_format_ver.draft != ICE_PKG_FMT_VER_DFT)
		return ICE_ERR_CFG;
		return ICE_DDP_PKG_INVALID_FILE;

	/* pkg must have at least one segment */
	seg_count = le32_to_cpu(pkg->seg_count);
	if (seg_count < 1)
		return ICE_ERR_CFG;
		return ICE_DDP_PKG_INVALID_FILE;

	/* make sure segment array fits in package length */
	if (len < struct_size(pkg, seg_offset, seg_count))
		return ICE_ERR_BUF_TOO_SHORT;
		return ICE_DDP_PKG_INVALID_FILE;

	/* all segments must fit within length */
	for (i = 0; i < seg_count; i++) {
@@ -1278,16 +1290,16 @@ static enum ice_status ice_verify_pkg(struct ice_pkg_hdr *pkg, u32 len)

		/* segment header must fit */
		if (len < off + sizeof(*seg))
			return ICE_ERR_BUF_TOO_SHORT;
			return ICE_DDP_PKG_INVALID_FILE;

		seg = (struct ice_generic_seg_hdr *)((u8 *)pkg + off);

		/* segment body must fit */
		if (len < off + le32_to_cpu(seg->seg_size))
			return ICE_ERR_BUF_TOO_SHORT;
			return ICE_DDP_PKG_INVALID_FILE;
	}

	return 0;
	return ICE_DDP_PKG_SUCCESS;
}

/**
@@ -1331,13 +1343,18 @@ static void ice_init_pkg_regs(struct ice_hw *hw)
 * version must match our ICE_PKG_SUPP_VER_MAJ and ICE_PKG_SUPP_VER_MNR
 * definitions.
 */
static enum ice_status ice_chk_pkg_version(struct ice_pkg_ver *pkg_ver)
static enum ice_ddp_state ice_chk_pkg_version(struct ice_pkg_ver *pkg_ver)
{
	if (pkg_ver->major != ICE_PKG_SUPP_VER_MAJ ||
	    pkg_ver->minor != ICE_PKG_SUPP_VER_MNR)
		return ICE_ERR_NOT_SUPPORTED;
	if (pkg_ver->major > ICE_PKG_SUPP_VER_MAJ ||
	    (pkg_ver->major == ICE_PKG_SUPP_VER_MAJ &&
	     pkg_ver->minor > ICE_PKG_SUPP_VER_MNR))
		return ICE_DDP_PKG_FILE_VERSION_TOO_HIGH;
	else if (pkg_ver->major < ICE_PKG_SUPP_VER_MAJ ||
		 (pkg_ver->major == ICE_PKG_SUPP_VER_MAJ &&
		  pkg_ver->minor < ICE_PKG_SUPP_VER_MNR))
		return ICE_DDP_PKG_FILE_VERSION_TOO_LOW;

	return 0;
	return ICE_DDP_PKG_SUCCESS;
}

/**
@@ -1348,20 +1365,20 @@ static enum ice_status ice_chk_pkg_version(struct ice_pkg_ver *pkg_ver)
 *
 * This function checks the package version compatibility with driver and NVM
 */
static enum ice_status
static enum ice_ddp_state
ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg,
		   struct ice_seg **seg)
{
	struct ice_aqc_get_pkg_info_resp *pkg;
	enum ice_status status;
	enum ice_ddp_state state;
	u16 size;
	u32 i;

	/* Check package version compatibility */
	status = ice_chk_pkg_version(&hw->pkg_ver);
	if (status) {
	state = ice_chk_pkg_version(&hw->pkg_ver);
	if (state) {
		ice_debug(hw, ICE_DBG_INIT, "Package version check failed.\n");
		return status;
		return state;
	}

	/* find ICE segment in given package */
@@ -1369,18 +1386,19 @@ ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg,
						     ospkg);
	if (!*seg) {
		ice_debug(hw, ICE_DBG_INIT, "no ice segment in package.\n");
		return ICE_ERR_CFG;
		return ICE_DDP_PKG_INVALID_FILE;
	}

	/* Check if FW is compatible with the OS package */
	size = struct_size(pkg, pkg_info, ICE_PKG_CNT);
	pkg = kzalloc(size, GFP_KERNEL);
	if (!pkg)
		return ICE_ERR_NO_MEMORY;
		return ICE_DDP_PKG_ERR;

	status = ice_aq_get_pkg_info_list(hw, pkg, size, NULL);
	if (status)
	if (ice_aq_get_pkg_info_list(hw, pkg, size, NULL)) {
		state = ICE_DDP_PKG_LOAD_ERROR;
		goto fw_ddp_compat_free_alloc;
	}

	for (i = 0; i < le32_to_cpu(pkg->count); i++) {
		/* loop till we find the NVM package */
@@ -1390,7 +1408,7 @@ ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg,
			pkg->pkg_info[i].ver.major ||
		    (*seg)->hdr.seg_format_ver.minor >
			pkg->pkg_info[i].ver.minor) {
			status = ICE_ERR_FW_DDP_MISMATCH;
			state = ICE_DDP_PKG_FW_MISMATCH;
			ice_debug(hw, ICE_DBG_INIT, "OS package is not compatible with NVM.\n");
		}
		/* done processing NVM package so break */
@@ -1398,7 +1416,7 @@ ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg,
	}
fw_ddp_compat_free_alloc:
	kfree(pkg);
	return status;
	return state;
}

/**
@@ -1481,6 +1499,34 @@ static enum ice_status ice_get_prof_index_max(struct ice_hw *hw)
	return 0;
}

/**
 * ice_get_ddp_pkg_state - get DDP pkg state after download
 * @hw: pointer to the HW struct
 * @already_loaded: indicates if pkg was already loaded onto the device
 */
static enum ice_ddp_state
ice_get_ddp_pkg_state(struct ice_hw *hw, bool already_loaded)
{
	if (hw->pkg_ver.major == hw->active_pkg_ver.major &&
	    hw->pkg_ver.minor == hw->active_pkg_ver.minor &&
	    hw->pkg_ver.update == hw->active_pkg_ver.update &&
	    hw->pkg_ver.draft == hw->active_pkg_ver.draft &&
	    !memcmp(hw->pkg_name, hw->active_pkg_name, sizeof(hw->pkg_name))) {
		if (already_loaded)
			return ICE_DDP_PKG_SAME_VERSION_ALREADY_LOADED;
		else
			return ICE_DDP_PKG_SUCCESS;
	} else if (hw->active_pkg_ver.major != ICE_PKG_SUPP_VER_MAJ ||
		   hw->active_pkg_ver.minor != ICE_PKG_SUPP_VER_MNR) {
		return ICE_DDP_PKG_ALREADY_LOADED_NOT_SUPPORTED;
	} else if (hw->active_pkg_ver.major == ICE_PKG_SUPP_VER_MAJ &&
		   hw->active_pkg_ver.minor == ICE_PKG_SUPP_VER_MNR) {
		return ICE_DDP_PKG_COMPATIBLE_ALREADY_LOADED;
	} else {
		return ICE_DDP_PKG_ERR;
	}
}

/**
 * ice_init_pkg - initialize/download package
 * @hw: pointer to the hardware structure
@@ -1506,53 +1552,54 @@ static enum ice_status ice_get_prof_index_max(struct ice_hw *hw)
 * ice_copy_and_init_pkg() instead of directly calling ice_init_pkg() in this
 * case.
 */
enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len)
enum ice_ddp_state ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len)
{
	bool already_loaded = false;
	enum ice_ddp_state state;
	struct ice_pkg_hdr *pkg;
	enum ice_status status;
	struct ice_seg *seg;

	if (!buf || !len)
		return ICE_ERR_PARAM;
		return ICE_DDP_PKG_ERR;

	pkg = (struct ice_pkg_hdr *)buf;
	status = ice_verify_pkg(pkg, len);
	if (status) {
	state = ice_verify_pkg(pkg, len);
	if (state) {
		ice_debug(hw, ICE_DBG_INIT, "failed to verify pkg (err: %d)\n",
			  status);
		return status;
			  state);
		return state;
	}

	/* initialize package info */
	status = ice_init_pkg_info(hw, pkg);
	if (status)
		return status;
	state = ice_init_pkg_info(hw, pkg);
	if (state)
		return state;

	/* before downloading the package, check package version for
	 * compatibility with driver
	 */
	status = ice_chk_pkg_compat(hw, pkg, &seg);
	if (status)
		return status;
	state = ice_chk_pkg_compat(hw, pkg, &seg);
	if (state)
		return state;

	/* initialize package hints and then download package */
	ice_init_pkg_hints(hw, seg);
	status = ice_download_pkg(hw, seg);
	if (status == ICE_ERR_AQ_NO_WORK) {
	state = ice_download_pkg(hw, seg);
	if (state == ICE_DDP_PKG_ALREADY_LOADED) {
		ice_debug(hw, ICE_DBG_INIT, "package previously loaded - no work.\n");
		status = 0;
		already_loaded = true;
	}

	/* Get information on the package currently loaded in HW, then make sure
	 * the driver is compatible with this version.
	 */
	if (!status) {
		status = ice_get_pkg_info(hw);
		if (!status)
			status = ice_chk_pkg_version(&hw->active_pkg_ver);
	if (!state || state == ICE_DDP_PKG_ALREADY_LOADED) {
		state = ice_get_pkg_info(hw);
		if (!state)
			state = ice_get_ddp_pkg_state(hw, already_loaded);
	}

	if (!status) {
	if (ice_is_init_pkg_successful(state)) {
		hw->seg = seg;
		/* on successful package download update other required
		 * registers to support the package and fill HW tables
@@ -1564,10 +1611,10 @@ enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len)
		ice_get_prof_index_max(hw);
	} else {
		ice_debug(hw, ICE_DBG_INIT, "package load failed, %d\n",
			  status);
			  state);
	}

	return status;
	return state;
}

/**
@@ -1593,18 +1640,19 @@ enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len)
 * package buffer, as the new copy will be managed by this function and
 * related routines.
 */
enum ice_status ice_copy_and_init_pkg(struct ice_hw *hw, const u8 *buf, u32 len)
enum ice_ddp_state
ice_copy_and_init_pkg(struct ice_hw *hw, const u8 *buf, u32 len)
{
	enum ice_status status;
	enum ice_ddp_state state;
	u8 *buf_copy;

	if (!buf || !len)
		return ICE_ERR_PARAM;
		return ICE_DDP_PKG_ERR;

	buf_copy = devm_kmemdup(ice_hw_to_dev(hw), buf, len, GFP_KERNEL);

	status = ice_init_pkg(hw, buf_copy, len);
	if (status) {
	state = ice_init_pkg(hw, buf_copy, len);
	if (!ice_is_init_pkg_successful(state)) {
		/* Free the copy, since we failed to initialize the package */
		devm_kfree(ice_hw_to_dev(hw), buf_copy);
	} else {
@@ -1613,7 +1661,23 @@ enum ice_status ice_copy_and_init_pkg(struct ice_hw *hw, const u8 *buf, u32 len)
		hw->pkg_size = len;
	}

	return status;
	return state;
}

/**
 * ice_is_init_pkg_successful - check if DDP init was successful
 * @state: state of the DDP pkg after download
 */
bool ice_is_init_pkg_successful(enum ice_ddp_state state)
{
	switch (state) {
	case ICE_DDP_PKG_SUCCESS:
	case ICE_DDP_PKG_SAME_VERSION_ALREADY_LOADED:
	case ICE_DDP_PKG_COMPATIBLE_ALREADY_LOADED:
		return true;
	default:
		return false;
	}
}

/**
+60 −2
Original line number Diff line number Diff line
@@ -18,6 +18,63 @@

#define ICE_PKG_CNT 4

enum ice_ddp_state {
	/* Indicates that this call to ice_init_pkg
	 * successfully loaded the requested DDP package
	 */
	ICE_DDP_PKG_SUCCESS			= 0,

	/* Generic error for already loaded errors, it is mapped later to
	 * the more specific one (one of the next 3)
	 */
	ICE_DDP_PKG_ALREADY_LOADED			= -1,

	/* Indicates that a DDP package of the same version has already been
	 * loaded onto the device by a previous call or by another PF
	 */
	ICE_DDP_PKG_SAME_VERSION_ALREADY_LOADED		= -2,

	/* The device has a DDP package that is not supported by the driver */
	ICE_DDP_PKG_ALREADY_LOADED_NOT_SUPPORTED	= -3,

	/* The device has a compatible package
	 * (but different from the request) already loaded
	 */
	ICE_DDP_PKG_COMPATIBLE_ALREADY_LOADED		= -4,

	/* The firmware loaded on the device is not compatible with
	 * the DDP package loaded
	 */
	ICE_DDP_PKG_FW_MISMATCH				= -5,

	/* The DDP package file is invalid */
	ICE_DDP_PKG_INVALID_FILE			= -6,

	/* The version of the DDP package provided is higher than
	 * the driver supports
	 */
	ICE_DDP_PKG_FILE_VERSION_TOO_HIGH		= -7,

	/* The version of the DDP package provided is lower than the
	 * driver supports
	 */
	ICE_DDP_PKG_FILE_VERSION_TOO_LOW		= -8,

	/* The signature of the DDP package file provided is invalid */
	ICE_DDP_PKG_FILE_SIGNATURE_INVALID		= -9,

	/* The DDP package file security revision is too low and not
	 * supported by firmware
	 */
	ICE_DDP_PKG_FILE_REVISION_TOO_LOW		= -10,

	/* An error occurred in firmware while loading the DDP package */
	ICE_DDP_PKG_LOAD_ERROR				= -11,

	/* Other errors */
	ICE_DDP_PKG_ERR					= -12
};

enum ice_status
ice_acquire_change_lock(struct ice_hw *hw, enum ice_aq_res_access_type access);
void ice_release_change_lock(struct ice_hw *hw);
@@ -52,9 +109,10 @@ enum ice_status
ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl);
enum ice_status
ice_rem_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl);
enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buff, u32 len);
enum ice_status
enum ice_ddp_state ice_init_pkg(struct ice_hw *hw, u8 *buff, u32 len);
enum ice_ddp_state
ice_copy_and_init_pkg(struct ice_hw *hw, const u8 *buf, u32 len);
bool ice_is_init_pkg_successful(enum ice_ddp_state state);
enum ice_status ice_init_hw_tbls(struct ice_hw *hw);
void ice_free_seg(struct ice_hw *hw);
void ice_fill_blk_tbls(struct ice_hw *hw);
+68 −98
Original line number Diff line number Diff line
@@ -4082,50 +4082,40 @@ static void ice_set_safe_mode_vlan_cfg(struct ice_pf *pf)
/**
 * ice_log_pkg_init - log result of DDP package load
 * @hw: pointer to hardware info
 * @status: status of package load
 * @state: state of package load
 */
static void
ice_log_pkg_init(struct ice_hw *hw, enum ice_status *status)
static void ice_log_pkg_init(struct ice_hw *hw, enum ice_ddp_state state)
{
	struct ice_pf *pf = (struct ice_pf *)hw->back;
	struct device *dev = ice_pf_to_dev(pf);
	struct ice_pf *pf = hw->back;
	struct device *dev;

	switch (*status) {
	case ICE_SUCCESS:
		/* The package download AdminQ command returned success because
		 * this download succeeded or ICE_ERR_AQ_NO_WORK since there is
		 * already a package loaded on the device.
		 */
		if (hw->pkg_ver.major == hw->active_pkg_ver.major &&
		    hw->pkg_ver.minor == hw->active_pkg_ver.minor &&
		    hw->pkg_ver.update == hw->active_pkg_ver.update &&
		    hw->pkg_ver.draft == hw->active_pkg_ver.draft &&
		    !memcmp(hw->pkg_name, hw->active_pkg_name,
			    sizeof(hw->pkg_name))) {
			if (hw->pkg_dwnld_status == ICE_AQ_RC_EEXIST)
				dev_info(dev, "DDP package already present on device: %s version %d.%d.%d.%d\n",
	dev = ice_pf_to_dev(pf);

	switch (state) {
	case ICE_DDP_PKG_SUCCESS:
		dev_info(dev, "The DDP package was successfully loaded: %s version %d.%d.%d.%d\n",
			 hw->active_pkg_name,
			 hw->active_pkg_ver.major,
			 hw->active_pkg_ver.minor,
			 hw->active_pkg_ver.update,
			 hw->active_pkg_ver.draft);
			else
				dev_info(dev, "The DDP package was successfully loaded: %s version %d.%d.%d.%d\n",
		break;
	case ICE_DDP_PKG_SAME_VERSION_ALREADY_LOADED:
		dev_info(dev, "DDP package already present on device: %s version %d.%d.%d.%d\n",
			 hw->active_pkg_name,
			 hw->active_pkg_ver.major,
			 hw->active_pkg_ver.minor,
			 hw->active_pkg_ver.update,
			 hw->active_pkg_ver.draft);
		} else if (hw->active_pkg_ver.major != ICE_PKG_SUPP_VER_MAJ ||
			   hw->active_pkg_ver.minor != ICE_PKG_SUPP_VER_MNR) {
		break;
	case ICE_DDP_PKG_ALREADY_LOADED_NOT_SUPPORTED:
		dev_err(dev, "The device has a DDP package that is not supported by the driver.  The device has package '%s' version %d.%d.x.x.  The driver requires version %d.%d.x.x.  Entering Safe Mode.\n",
			hw->active_pkg_name,
			hw->active_pkg_ver.major,
			hw->active_pkg_ver.minor,
			ICE_PKG_SUPP_VER_MAJ, ICE_PKG_SUPP_VER_MNR);
			*status = ICE_ERR_NOT_SUPPORTED;
		} else if (hw->active_pkg_ver.major == ICE_PKG_SUPP_VER_MAJ &&
			   hw->active_pkg_ver.minor == ICE_PKG_SUPP_VER_MNR) {
		break;
	case ICE_DDP_PKG_COMPATIBLE_ALREADY_LOADED:
		dev_info(dev, "The driver could not load the DDP package file because a compatible DDP package is already present on the device.  The device has package '%s' version %d.%d.%d.%d.  The package file found by the driver: '%s' version %d.%d.%d.%d.\n",
			 hw->active_pkg_name,
			 hw->active_pkg_ver.major,
@@ -4137,54 +4127,35 @@ ice_log_pkg_init(struct ice_hw *hw, enum ice_status *status)
			 hw->pkg_ver.minor,
			 hw->pkg_ver.update,
			 hw->pkg_ver.draft);
		} else {
			dev_err(dev, "An unknown error occurred when loading the DDP package, please reboot the system.  If the problem persists, update the NVM.  Entering Safe Mode.\n");
			*status = ICE_ERR_NOT_SUPPORTED;
		}
		break;
	case ICE_ERR_FW_DDP_MISMATCH:
	case ICE_DDP_PKG_FW_MISMATCH:
		dev_err(dev, "The firmware loaded on the device is not compatible with the DDP package.  Please update the device's NVM.  Entering safe mode.\n");
		break;
	case ICE_ERR_BUF_TOO_SHORT:
	case ICE_ERR_CFG:
	case ICE_DDP_PKG_INVALID_FILE:
		dev_err(dev, "The DDP package file is invalid. Entering Safe Mode.\n");
		break;
	case ICE_ERR_NOT_SUPPORTED:
		/* Package File version not supported */
		if (hw->pkg_ver.major > ICE_PKG_SUPP_VER_MAJ ||
		    (hw->pkg_ver.major == ICE_PKG_SUPP_VER_MAJ &&
		     hw->pkg_ver.minor > ICE_PKG_SUPP_VER_MNR))
	case ICE_DDP_PKG_FILE_VERSION_TOO_HIGH:
		dev_err(dev, "The DDP package file version is higher than the driver supports.  Please use an updated driver.  Entering Safe Mode.\n");
		else if (hw->pkg_ver.major < ICE_PKG_SUPP_VER_MAJ ||
			 (hw->pkg_ver.major == ICE_PKG_SUPP_VER_MAJ &&
			  hw->pkg_ver.minor < ICE_PKG_SUPP_VER_MNR))
		break;
	case ICE_DDP_PKG_FILE_VERSION_TOO_LOW:
		dev_err(dev, "The DDP package file version is lower than the driver supports.  The driver requires version %d.%d.x.x.  Please use an updated DDP Package file.  Entering Safe Mode.\n",
			ICE_PKG_SUPP_VER_MAJ, ICE_PKG_SUPP_VER_MNR);
		break;
	case ICE_ERR_AQ_ERROR:
		switch (hw->pkg_dwnld_status) {
		case ICE_AQ_RC_ENOSEC:
		case ICE_AQ_RC_EBADSIG:
	case ICE_DDP_PKG_FILE_SIGNATURE_INVALID:
		dev_err(dev, "The DDP package could not be loaded because its signature is not valid.  Please use a valid DDP Package.  Entering Safe Mode.\n");
			return;
		case ICE_AQ_RC_ESVN:
		break;
	case ICE_DDP_PKG_FILE_REVISION_TOO_LOW:
		dev_err(dev, "The DDP Package could not be loaded because its security revision is too low.  Please use an updated DDP Package.  Entering Safe Mode.\n");
			return;
		case ICE_AQ_RC_EBADMAN:
		case ICE_AQ_RC_EBADBUF:
		break;
	case ICE_DDP_PKG_LOAD_ERROR:
		dev_err(dev, "An error occurred on the device while loading the DDP package.  The device will be reset.\n");
			/* poll for reset to complete */
			if (ice_check_reset(hw))
				dev_err(dev, "Error resetting device. Please reload the driver\n");
			return;
		default:
		break;
		}
		fallthrough;
	case ICE_DDP_PKG_ERR:
	default:
		dev_err(dev, "An unknown error (%d) occurred when loading the DDP package.  Entering Safe Mode.\n",
			*status);
		break;
		dev_err(dev, "An unknown error occurred when loading the DDP package.  Entering Safe Mode.\n");
	}
}

@@ -4199,24 +4170,24 @@ ice_log_pkg_init(struct ice_hw *hw, enum ice_status *status)
static void
ice_load_pkg(const struct firmware *firmware, struct ice_pf *pf)
{
	enum ice_status status = ICE_ERR_PARAM;
	enum ice_ddp_state state = ICE_DDP_PKG_ERR;
	struct device *dev = ice_pf_to_dev(pf);
	struct ice_hw *hw = &pf->hw;

	/* Load DDP Package */
	if (firmware && !hw->pkg_copy) {
		status = ice_copy_and_init_pkg(hw, firmware->data,
		state = ice_copy_and_init_pkg(hw, firmware->data,
					      firmware->size);
		ice_log_pkg_init(hw, &status);
		ice_log_pkg_init(hw, state);
	} else if (!firmware && hw->pkg_copy) {
		/* Reload package during rebuild after CORER/GLOBR reset */
		status = ice_init_pkg(hw, hw->pkg_copy, hw->pkg_size);
		ice_log_pkg_init(hw, &status);
		state = ice_init_pkg(hw, hw->pkg_copy, hw->pkg_size);
		ice_log_pkg_init(hw, state);
	} else {
		dev_err(dev, "The DDP package file failed to load. Entering Safe Mode.\n");
	}

	if (status) {
	if (!ice_is_init_pkg_successful(state)) {
		/* Safe Mode */
		clear_bit(ICE_FLAG_ADV_FEATURES, pf->flags);
		return;
@@ -4539,7 +4510,6 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
	 * true
	 */
	if (ice_is_safe_mode(pf)) {
		dev_err(dev, "Package download failed. Advanced features disabled - Device now in Safe Mode\n");
		/* we already got function/device capabilities but these don't
		 * reflect what the driver needs to do in safe mode. Instead of
		 * adding conditional logic everywhere to ignore these
+0 −2
Original line number Diff line number Diff line
@@ -873,8 +873,6 @@ struct ice_hw {
	u8 active_pkg_name[ICE_PKG_NAME_SIZE];
	u8 active_pkg_in_nvm;

	enum ice_aq_err pkg_dwnld_status;

	/* Driver's package ver - (from the Ice Metadata section) */
	struct ice_pkg_ver pkg_ver;
	u8 pkg_name[ICE_PKG_NAME_SIZE];