mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
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: Jacob Keller <jacob.e.keller@intel.com> Signed-off-by: Wojciech Drewek <wojciech.drewek@intel.com> Tested-by: Tony Brelinski <tony.brelinski@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
parent
fabf480bf9
commit
247dd97d71
4 changed files with 272 additions and 182 deletions
|
@ -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 @@ init_pkg_free_alloc:
|
|||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
* @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",
|
||||
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;
|
||||
}
|
||||
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);
|
||||
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");
|
||||
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))
|
||||
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);
|
||||
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");
|
||||
break;
|
||||
case ICE_ERR_AQ_ERROR:
|
||||
switch (hw->pkg_dwnld_status) {
|
||||
case ICE_AQ_RC_ENOSEC:
|
||||
case ICE_AQ_RC_EBADSIG:
|
||||
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:
|
||||
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:
|
||||
dev_err(dev, "An error occurred on the device while loading the DDP package. The device will be reset.\n");
|
||||
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_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");
|
||||
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");
|
||||
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;
|
||||
default:
|
||||
dev_err(dev, "An unknown error (%d) occurred when loading the DDP package. Entering Safe Mode.\n",
|
||||
*status);
|
||||
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)
|
|||
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,
|
||||
firmware->size);
|
||||
ice_log_pkg_init(hw, &status);
|
||||
state = ice_copy_and_init_pkg(hw, firmware->data,
|
||||
firmware->size);
|
||||
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
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue