提交 247dd97d 编写于 作者: W Wojciech Drewek 提交者: Tony Nguyen

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: NJacob Keller <jacob.e.keller@intel.com>
Signed-off-by: NWojciech Drewek <wojciech.drewek@intel.com>
Tested-by: NTony Brelinski <tony.brelinski@intel.com>
Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
上级 fabf480b
...@@ -993,6 +993,22 @@ ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count) ...@@ -993,6 +993,22 @@ ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
return status; 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 * ice_dwnld_cfg_bufs
* @hw: pointer to the hardware structure * @hw: pointer to the hardware structure
...@@ -1003,15 +1019,17 @@ ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count) ...@@ -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 * to the firmware. Metadata buffers are skipped, and the first metadata buffer
* found indicates that the rest of the buffers are all metadata buffers. * 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) 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; enum ice_status status;
struct ice_buf_hdr *bh; struct ice_buf_hdr *bh;
enum ice_aq_err err;
u32 offset, info, i; u32 offset, info, i;
if (!bufs || !count) if (!bufs || !count)
return ICE_ERR_PARAM; return ICE_DDP_PKG_ERR;
/* If the first buffer's first section has its metadata bit set /* If the first buffer's first section has its metadata bit set
* then there are no buffers to be downloaded, and the operation is * 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) ...@@ -1019,20 +1037,13 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
*/ */
bh = (struct ice_buf_hdr *)bufs; bh = (struct ice_buf_hdr *)bufs;
if (le32_to_cpu(bh->section_entry[0].type) & ICE_METADATA_BUF) if (le32_to_cpu(bh->section_entry[0].type) & ICE_METADATA_BUF)
return 0; return ICE_DDP_PKG_SUCCESS;
/* reset pkg_dwnld_status in case this function is called in the
* reset/rebuild flow
*/
hw->pkg_dwnld_status = ICE_AQ_RC_OK;
status = ice_acquire_global_cfg_lock(hw, ICE_RES_WRITE); status = ice_acquire_global_cfg_lock(hw, ICE_RES_WRITE);
if (status) { if (status) {
if (status == ICE_ERR_AQ_NO_WORK) if (status == ICE_ERR_AQ_NO_WORK)
hw->pkg_dwnld_status = ICE_AQ_RC_EEXIST; return ICE_DDP_PKG_ALREADY_LOADED;
else return ice_map_aq_err_to_ddp_state(hw->adminq.sq_last_status);
hw->pkg_dwnld_status = hw->adminq.sq_last_status;
return status;
} }
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
...@@ -1058,11 +1069,11 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count) ...@@ -1058,11 +1069,11 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
&offset, &info, NULL); &offset, &info, NULL);
/* Save AQ status from download package */ /* Save AQ status from download package */
hw->pkg_dwnld_status = hw->adminq.sq_last_status;
if (status) { if (status) {
ice_debug(hw, ICE_DBG_PKG, "Pkg download failed: err %d off %d inf %d\n", ice_debug(hw, ICE_DBG_PKG, "Pkg download failed: err %d off %d inf %d\n",
status, offset, info); status, offset, info);
err = hw->adminq.sq_last_status;
state = ice_map_aq_err_to_ddp_state(err);
break; break;
} }
...@@ -1072,7 +1083,7 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count) ...@@ -1072,7 +1083,7 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
ice_release_global_cfg_lock(hw); ice_release_global_cfg_lock(hw);
return status; return state;
} }
/** /**
...@@ -1103,7 +1114,7 @@ ice_aq_get_pkg_info_list(struct ice_hw *hw, ...@@ -1103,7 +1114,7 @@ ice_aq_get_pkg_info_list(struct ice_hw *hw,
* *
* Handles the download of a complete package. * 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) ice_download_pkg(struct ice_hw *hw, struct ice_seg *ice_seg)
{ {
struct ice_buf_table *ice_buf_tbl; struct ice_buf_table *ice_buf_tbl;
...@@ -1134,13 +1145,13 @@ ice_download_pkg(struct ice_hw *hw, struct ice_seg *ice_seg) ...@@ -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. * 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) ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
{ {
struct ice_generic_seg_hdr *seg_hdr; struct ice_generic_seg_hdr *seg_hdr;
if (!pkg_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); seg_hdr = ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE, pkg_hdr);
if (seg_hdr) { if (seg_hdr) {
...@@ -1154,7 +1165,7 @@ ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr) ...@@ -1154,7 +1165,7 @@ ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
ICE_SID_METADATA); ICE_SID_METADATA);
if (!meta) { if (!meta) {
ice_debug(hw, ICE_DBG_INIT, "Did not find ice metadata section in package\n"); 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; hw->pkg_ver = meta->ver;
...@@ -1176,10 +1187,10 @@ ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr) ...@@ -1176,10 +1187,10 @@ ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
seg_hdr->seg_id); seg_hdr->seg_id);
} else { } else {
ice_debug(hw, ICE_DBG_INIT, "Did not find ice segment in driver package\n"); 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) ...@@ -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. * 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; struct ice_aqc_get_pkg_info_resp *pkg_info;
enum ice_status status;
u16 size; u16 size;
u32 i; u32 i;
size = struct_size(pkg_info, pkg_info, ICE_PKG_CNT); size = struct_size(pkg_info, pkg_info, ICE_PKG_CNT);
pkg_info = kzalloc(size, GFP_KERNEL); pkg_info = kzalloc(size, GFP_KERNEL);
if (!pkg_info) 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 (ice_aq_get_pkg_info_list(hw, pkg_info, size, NULL)) {
if (status) state = ICE_DDP_PKG_ERR;
goto init_pkg_free_alloc; goto init_pkg_free_alloc;
}
for (i = 0; i < le32_to_cpu(pkg_info->count); i++) { for (i = 0; i < le32_to_cpu(pkg_info->count); i++) {
#define ICE_PKG_FLAG_COUNT 4 #define ICE_PKG_FLAG_COUNT 4
...@@ -1237,7 +1249,7 @@ static enum ice_status ice_get_pkg_info(struct ice_hw *hw) ...@@ -1237,7 +1249,7 @@ static enum ice_status ice_get_pkg_info(struct ice_hw *hw)
init_pkg_free_alloc: init_pkg_free_alloc:
kfree(pkg_info); kfree(pkg_info);
return status; return state;
} }
/** /**
...@@ -1248,28 +1260,28 @@ static enum ice_status ice_get_pkg_info(struct ice_hw *hw) ...@@ -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 * Verifies various attributes of the package file, including length, format
* version, and the requirement of at least one segment. * 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 seg_count;
u32 i; u32 i;
if (len < struct_size(pkg, seg_offset, 1)) 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 || 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.minor != ICE_PKG_FMT_VER_MNR ||
pkg->pkg_format_ver.update != ICE_PKG_FMT_VER_UPD || pkg->pkg_format_ver.update != ICE_PKG_FMT_VER_UPD ||
pkg->pkg_format_ver.draft != ICE_PKG_FMT_VER_DFT) 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 */ /* pkg must have at least one segment */
seg_count = le32_to_cpu(pkg->seg_count); seg_count = le32_to_cpu(pkg->seg_count);
if (seg_count < 1) if (seg_count < 1)
return ICE_ERR_CFG; return ICE_DDP_PKG_INVALID_FILE;
/* make sure segment array fits in package length */ /* make sure segment array fits in package length */
if (len < struct_size(pkg, seg_offset, seg_count)) 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 */ /* all segments must fit within length */
for (i = 0; i < seg_count; i++) { 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) ...@@ -1278,16 +1290,16 @@ static enum ice_status ice_verify_pkg(struct ice_pkg_hdr *pkg, u32 len)
/* segment header must fit */ /* segment header must fit */
if (len < off + sizeof(*seg)) 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); seg = (struct ice_generic_seg_hdr *)((u8 *)pkg + off);
/* segment body must fit */ /* segment body must fit */
if (len < off + le32_to_cpu(seg->seg_size)) 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) ...@@ -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 * version must match our ICE_PKG_SUPP_VER_MAJ and ICE_PKG_SUPP_VER_MNR
* definitions. * 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 || if (pkg_ver->major > ICE_PKG_SUPP_VER_MAJ ||
pkg_ver->minor != ICE_PKG_SUPP_VER_MNR) (pkg_ver->major == ICE_PKG_SUPP_VER_MAJ &&
return ICE_ERR_NOT_SUPPORTED; 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) ...@@ -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 * 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, ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg,
struct ice_seg **seg) struct ice_seg **seg)
{ {
struct ice_aqc_get_pkg_info_resp *pkg; struct ice_aqc_get_pkg_info_resp *pkg;
enum ice_status status; enum ice_ddp_state state;
u16 size; u16 size;
u32 i; u32 i;
/* Check package version compatibility */ /* Check package version compatibility */
status = ice_chk_pkg_version(&hw->pkg_ver); state = ice_chk_pkg_version(&hw->pkg_ver);
if (status) { if (state) {
ice_debug(hw, ICE_DBG_INIT, "Package version check failed.\n"); ice_debug(hw, ICE_DBG_INIT, "Package version check failed.\n");
return status; return state;
} }
/* find ICE segment in given package */ /* find ICE segment in given package */
...@@ -1369,18 +1386,19 @@ ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg, ...@@ -1369,18 +1386,19 @@ ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg,
ospkg); ospkg);
if (!*seg) { if (!*seg) {
ice_debug(hw, ICE_DBG_INIT, "no ice segment in package.\n"); 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 */ /* Check if FW is compatible with the OS package */
size = struct_size(pkg, pkg_info, ICE_PKG_CNT); size = struct_size(pkg, pkg_info, ICE_PKG_CNT);
pkg = kzalloc(size, GFP_KERNEL); pkg = kzalloc(size, GFP_KERNEL);
if (!pkg) if (!pkg)
return ICE_ERR_NO_MEMORY; return ICE_DDP_PKG_ERR;
status = ice_aq_get_pkg_info_list(hw, pkg, size, NULL); if (ice_aq_get_pkg_info_list(hw, pkg, size, NULL)) {
if (status) state = ICE_DDP_PKG_LOAD_ERROR;
goto fw_ddp_compat_free_alloc; goto fw_ddp_compat_free_alloc;
}
for (i = 0; i < le32_to_cpu(pkg->count); i++) { for (i = 0; i < le32_to_cpu(pkg->count); i++) {
/* loop till we find the NVM package */ /* loop till we find the NVM package */
...@@ -1390,7 +1408,7 @@ ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg, ...@@ -1390,7 +1408,7 @@ ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg,
pkg->pkg_info[i].ver.major || pkg->pkg_info[i].ver.major ||
(*seg)->hdr.seg_format_ver.minor > (*seg)->hdr.seg_format_ver.minor >
pkg->pkg_info[i].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"); ice_debug(hw, ICE_DBG_INIT, "OS package is not compatible with NVM.\n");
} }
/* done processing NVM package so break */ /* done processing NVM package so break */
...@@ -1398,7 +1416,7 @@ ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg, ...@@ -1398,7 +1416,7 @@ ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg,
} }
fw_ddp_compat_free_alloc: fw_ddp_compat_free_alloc:
kfree(pkg); kfree(pkg);
return status; return state;
} }
/** /**
...@@ -1481,6 +1499,34 @@ static enum ice_status ice_get_prof_index_max(struct ice_hw *hw) ...@@ -1481,6 +1499,34 @@ static enum ice_status ice_get_prof_index_max(struct ice_hw *hw)
return 0; 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 * ice_init_pkg - initialize/download package
* @hw: pointer to the hardware structure * @hw: pointer to the hardware structure
...@@ -1506,53 +1552,54 @@ static enum ice_status ice_get_prof_index_max(struct ice_hw *hw) ...@@ -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 * ice_copy_and_init_pkg() instead of directly calling ice_init_pkg() in this
* case. * 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; struct ice_pkg_hdr *pkg;
enum ice_status status;
struct ice_seg *seg; struct ice_seg *seg;
if (!buf || !len) if (!buf || !len)
return ICE_ERR_PARAM; return ICE_DDP_PKG_ERR;
pkg = (struct ice_pkg_hdr *)buf; pkg = (struct ice_pkg_hdr *)buf;
status = ice_verify_pkg(pkg, len); state = ice_verify_pkg(pkg, len);
if (status) { if (state) {
ice_debug(hw, ICE_DBG_INIT, "failed to verify pkg (err: %d)\n", ice_debug(hw, ICE_DBG_INIT, "failed to verify pkg (err: %d)\n",
status); state);
return status; return state;
} }
/* initialize package info */ /* initialize package info */
status = ice_init_pkg_info(hw, pkg); state = ice_init_pkg_info(hw, pkg);
if (status) if (state)
return status; return state;
/* before downloading the package, check package version for /* before downloading the package, check package version for
* compatibility with driver * compatibility with driver
*/ */
status = ice_chk_pkg_compat(hw, pkg, &seg); state = ice_chk_pkg_compat(hw, pkg, &seg);
if (status) if (state)
return status; return state;
/* initialize package hints and then download package */ /* initialize package hints and then download package */
ice_init_pkg_hints(hw, seg); ice_init_pkg_hints(hw, seg);
status = ice_download_pkg(hw, seg); state = ice_download_pkg(hw, seg);
if (status == ICE_ERR_AQ_NO_WORK) { if (state == ICE_DDP_PKG_ALREADY_LOADED) {
ice_debug(hw, ICE_DBG_INIT, "package previously loaded - no work.\n"); 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 /* Get information on the package currently loaded in HW, then make sure
* the driver is compatible with this version. * the driver is compatible with this version.
*/ */
if (!status) { if (!state || state == ICE_DDP_PKG_ALREADY_LOADED) {
status = ice_get_pkg_info(hw); state = ice_get_pkg_info(hw);
if (!status) if (!state)
status = ice_chk_pkg_version(&hw->active_pkg_ver); state = ice_get_ddp_pkg_state(hw, already_loaded);
} }
if (!status) { if (ice_is_init_pkg_successful(state)) {
hw->seg = seg; hw->seg = seg;
/* on successful package download update other required /* on successful package download update other required
* registers to support the package and fill HW tables * 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) ...@@ -1564,10 +1611,10 @@ enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len)
ice_get_prof_index_max(hw); ice_get_prof_index_max(hw);
} else { } else {
ice_debug(hw, ICE_DBG_INIT, "package load failed, %d\n", 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) ...@@ -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 * package buffer, as the new copy will be managed by this function and
* related routines. * 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; u8 *buf_copy;
if (!buf || !len) 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); buf_copy = devm_kmemdup(ice_hw_to_dev(hw), buf, len, GFP_KERNEL);
status = ice_init_pkg(hw, buf_copy, len); state = ice_init_pkg(hw, buf_copy, len);
if (status) { if (!ice_is_init_pkg_successful(state)) {
/* Free the copy, since we failed to initialize the package */ /* Free the copy, since we failed to initialize the package */
devm_kfree(ice_hw_to_dev(hw), buf_copy); devm_kfree(ice_hw_to_dev(hw), buf_copy);
} else { } else {
...@@ -1613,7 +1661,23 @@ enum ice_status ice_copy_and_init_pkg(struct ice_hw *hw, const u8 *buf, u32 len) ...@@ -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; 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;
}
} }
/** /**
......
...@@ -18,6 +18,63 @@ ...@@ -18,6 +18,63 @@
#define ICE_PKG_CNT 4 #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 enum ice_status
ice_acquire_change_lock(struct ice_hw *hw, enum ice_aq_res_access_type access); ice_acquire_change_lock(struct ice_hw *hw, enum ice_aq_res_access_type access);
void ice_release_change_lock(struct ice_hw *hw); void ice_release_change_lock(struct ice_hw *hw);
...@@ -52,9 +109,10 @@ enum ice_status ...@@ -52,9 +109,10 @@ enum ice_status
ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl); ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl);
enum ice_status enum ice_status
ice_rem_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl); 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_ddp_state ice_init_pkg(struct ice_hw *hw, u8 *buff, u32 len);
enum ice_status enum ice_ddp_state
ice_copy_and_init_pkg(struct ice_hw *hw, const u8 *buf, u32 len); 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); enum ice_status ice_init_hw_tbls(struct ice_hw *hw);
void ice_free_seg(struct ice_hw *hw); void ice_free_seg(struct ice_hw *hw);
void ice_fill_blk_tbls(struct ice_hw *hw); void ice_fill_blk_tbls(struct ice_hw *hw);
......
...@@ -4082,109 +4082,80 @@ static void ice_set_safe_mode_vlan_cfg(struct ice_pf *pf) ...@@ -4082,109 +4082,80 @@ static void ice_set_safe_mode_vlan_cfg(struct ice_pf *pf)
/** /**
* ice_log_pkg_init - log result of DDP package load * ice_log_pkg_init - log result of DDP package load
* @hw: pointer to hardware info * @hw: pointer to hardware info
* @status: status of package load * @state: state of package load
*/ */
static void static void ice_log_pkg_init(struct ice_hw *hw, enum ice_ddp_state state)
ice_log_pkg_init(struct ice_hw *hw, enum ice_status *status)
{ {
struct ice_pf *pf = (struct ice_pf *)hw->back; struct ice_pf *pf = hw->back;
struct device *dev = ice_pf_to_dev(pf); struct device *dev;
switch (*status) { dev = ice_pf_to_dev(pf);
case ICE_SUCCESS:
/* The package download AdminQ command returned success because switch (state) {
* this download succeeded or ICE_ERR_AQ_NO_WORK since there is case ICE_DDP_PKG_SUCCESS:
* already a package loaded on the device. dev_info(dev, "The DDP package was successfully loaded: %s version %d.%d.%d.%d\n",
*/ hw->active_pkg_name,
if (hw->pkg_ver.major == hw->active_pkg_ver.major && hw->active_pkg_ver.major,
hw->pkg_ver.minor == hw->active_pkg_ver.minor && hw->active_pkg_ver.minor,
hw->pkg_ver.update == hw->active_pkg_ver.update && hw->active_pkg_ver.update,
hw->pkg_ver.draft == hw->active_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",
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",
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) {
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) {
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,
hw->active_pkg_ver.minor,
hw->active_pkg_ver.update,
hw->active_pkg_ver.draft,
hw->pkg_name,
hw->pkg_ver.major,
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; break;
case ICE_ERR_FW_DDP_MISMATCH: 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);
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);
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,
hw->active_pkg_ver.minor,
hw->active_pkg_ver.update,
hw->active_pkg_ver.draft,
hw->pkg_name,
hw->pkg_ver.major,
hw->pkg_ver.minor,
hw->pkg_ver.update,
hw->pkg_ver.draft);
break;
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"); 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; break;
case ICE_ERR_BUF_TOO_SHORT: case ICE_DDP_PKG_INVALID_FILE:
case ICE_ERR_CFG:
dev_err(dev, "The DDP package file is invalid. Entering Safe Mode.\n"); dev_err(dev, "The DDP package file is invalid. Entering Safe Mode.\n");
break; break;
case ICE_ERR_NOT_SUPPORTED: case ICE_DDP_PKG_FILE_VERSION_TOO_HIGH:
/* Package File version not supported */ dev_err(dev, "The DDP package file version is higher than the driver supports. Please use an updated driver. Entering Safe Mode.\n");
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))
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))
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; break;
case ICE_ERR_AQ_ERROR: case ICE_DDP_PKG_FILE_VERSION_TOO_LOW:
switch (hw->pkg_dwnld_status) { 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",
case ICE_AQ_RC_ENOSEC: ICE_PKG_SUPP_VER_MAJ, ICE_PKG_SUPP_VER_MNR);
case ICE_AQ_RC_EBADSIG: break;
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"); case ICE_DDP_PKG_FILE_SIGNATURE_INVALID:
return; 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");
case ICE_AQ_RC_ESVN: break;
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"); case ICE_DDP_PKG_FILE_REVISION_TOO_LOW:
return; 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");
case ICE_AQ_RC_EBADMAN: break;
case ICE_AQ_RC_EBADBUF: 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"); 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 */ /* poll for reset to complete */
if (ice_check_reset(hw)) if (ice_check_reset(hw))
dev_err(dev, "Error resetting device. Please reload the driver\n"); dev_err(dev, "Error resetting device. Please reload the driver\n");
return;
default:
break;
}
fallthrough;
default:
dev_err(dev, "An unknown error (%d) occurred when loading the DDP package. Entering Safe Mode.\n",
*status);
break; break;
case ICE_DDP_PKG_ERR:
default:
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) ...@@ -4199,24 +4170,24 @@ ice_log_pkg_init(struct ice_hw *hw, enum ice_status *status)
static void static void
ice_load_pkg(const struct firmware *firmware, struct ice_pf *pf) 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 device *dev = ice_pf_to_dev(pf);
struct ice_hw *hw = &pf->hw; struct ice_hw *hw = &pf->hw;
/* Load DDP Package */ /* Load DDP Package */
if (firmware && !hw->pkg_copy) { 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); firmware->size);
ice_log_pkg_init(hw, &status); ice_log_pkg_init(hw, state);
} else if (!firmware && hw->pkg_copy) { } else if (!firmware && hw->pkg_copy) {
/* Reload package during rebuild after CORER/GLOBR reset */ /* Reload package during rebuild after CORER/GLOBR reset */
status = ice_init_pkg(hw, hw->pkg_copy, hw->pkg_size); state = ice_init_pkg(hw, hw->pkg_copy, hw->pkg_size);
ice_log_pkg_init(hw, &status); ice_log_pkg_init(hw, state);
} else { } else {
dev_err(dev, "The DDP package file failed to load. Entering Safe Mode.\n"); 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 */ /* Safe Mode */
clear_bit(ICE_FLAG_ADV_FEATURES, pf->flags); clear_bit(ICE_FLAG_ADV_FEATURES, pf->flags);
return; return;
...@@ -4539,7 +4510,6 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) ...@@ -4539,7 +4510,6 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
* true * true
*/ */
if (ice_is_safe_mode(pf)) { 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 /* we already got function/device capabilities but these don't
* reflect what the driver needs to do in safe mode. Instead of * reflect what the driver needs to do in safe mode. Instead of
* adding conditional logic everywhere to ignore these * adding conditional logic everywhere to ignore these
......
...@@ -873,8 +873,6 @@ struct ice_hw { ...@@ -873,8 +873,6 @@ struct ice_hw {
u8 active_pkg_name[ICE_PKG_NAME_SIZE]; u8 active_pkg_name[ICE_PKG_NAME_SIZE];
u8 active_pkg_in_nvm; u8 active_pkg_in_nvm;
enum ice_aq_err pkg_dwnld_status;
/* Driver's package ver - (from the Ice Metadata section) */ /* Driver's package ver - (from the Ice Metadata section) */
struct ice_pkg_ver pkg_ver; struct ice_pkg_ver pkg_ver;
u8 pkg_name[ICE_PKG_NAME_SIZE]; u8 pkg_name[ICE_PKG_NAME_SIZE];
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册