net/ice/base: check DDP package compatibility
authorQi Zhang <qi.z.zhang@intel.com>
Mon, 23 Mar 2020 07:17:54 +0000 (15:17 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 21 Apr 2020 11:57:05 +0000 (13:57 +0200)
Check the OS and NVM package versions before downloading the package.
If the OS package version is not compatible with NVM then return an
appropriate error.

Split the 32-byte segment name into a 28-byte segment name and
a 4-byte Track-ID. Older packages will still work with this change
because no package has a name that will take up more than 28 bytes;
in this case the Track-ID will be 0.

Note that the driver will store the segment name as 32-bytes in the
ice_hw structure, in order to normalize the length of the various
package name strings that it uses.

Also add section ID and structure for the segment metadata section.

Signed-off-by: Victor Raj <victor.raj@intel.com>
Signed-off-by: Dan Nowlin <dan.nowlin@intel.com>
Signed-off-by: Paul M Stillwell Jr <paul.m.stillwell.jr@intel.com>
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
Acked-by: Qiming Yang <qiming.yang@intel.com>
drivers/net/ice/base/ice_adminq_cmd.h
drivers/net/ice/base/ice_flex_pipe.c
drivers/net/ice/base/ice_flex_type.h
drivers/net/ice/base/ice_status.h
drivers/net/ice/base/ice_type.h

index 9f25d34..d4c899d 100644 (file)
@@ -2590,10 +2590,12 @@ struct ice_pkg_ver {
 };
 
 #define ICE_PKG_NAME_SIZE      32
+#define ICE_SEG_NAME_SIZE      28
 
 struct ice_aqc_get_pkg_info {
        struct ice_pkg_ver ver;
-       char name[ICE_PKG_NAME_SIZE];
+       char name[ICE_SEG_NAME_SIZE];
+       __le32 track_id;
        u8 is_in_nvm;
        u8 is_active;
        u8 is_active_at_boot;
index dd0c183..851f027 100644 (file)
@@ -876,8 +876,9 @@ ice_find_seg_in_pkg(struct ice_hw *hw, u32 seg_type,
 
        ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
        ice_debug(hw, ICE_DBG_PKG, "Package format version: %d.%d.%d.%d\n",
-                 pkg_hdr->format_ver.major, pkg_hdr->format_ver.minor,
-                 pkg_hdr->format_ver.update, pkg_hdr->format_ver.draft);
+                 pkg_hdr->pkg_format_ver.major, pkg_hdr->pkg_format_ver.minor,
+                 pkg_hdr->pkg_format_ver.update,
+                 pkg_hdr->pkg_format_ver.draft);
 
        /* Search all package segments for the requested segment type */
        for (i = 0; i < LE32_TO_CPU(pkg_hdr->seg_count); i++) {
@@ -1048,13 +1049,15 @@ ice_download_pkg(struct ice_hw *hw, struct ice_seg *ice_seg)
        struct ice_buf_table *ice_buf_tbl;
 
        ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
-       ice_debug(hw, ICE_DBG_PKG, "Segment version: %d.%d.%d.%d\n",
-                 ice_seg->hdr.seg_ver.major, ice_seg->hdr.seg_ver.minor,
-                 ice_seg->hdr.seg_ver.update, ice_seg->hdr.seg_ver.draft);
+       ice_debug(hw, ICE_DBG_PKG, "Segment format version: %d.%d.%d.%d\n",
+                 ice_seg->hdr.seg_format_ver.major,
+                 ice_seg->hdr.seg_format_ver.minor,
+                 ice_seg->hdr.seg_format_ver.update,
+                 ice_seg->hdr.seg_format_ver.draft);
 
        ice_debug(hw, ICE_DBG_PKG, "Seg: type 0x%X, size %d, name %s\n",
                  LE32_TO_CPU(ice_seg->hdr.seg_type),
-                 LE32_TO_CPU(ice_seg->hdr.seg_size), ice_seg->hdr.seg_name);
+                 LE32_TO_CPU(ice_seg->hdr.seg_size), ice_seg->hdr.seg_id);
 
        ice_buf_tbl = ice_find_buf_table(ice_seg);
 
@@ -1101,14 +1104,16 @@ ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
 
        seg_hdr = ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE, pkg_hdr);
        if (seg_hdr) {
-               hw->ice_pkg_ver = seg_hdr->seg_ver;
-               ice_memcpy(hw->ice_pkg_name, seg_hdr->seg_name,
+               hw->ice_pkg_ver = seg_hdr->seg_format_ver;
+               ice_memcpy(hw->ice_pkg_name, seg_hdr->seg_id,
                           sizeof(hw->ice_pkg_name), ICE_NONDMA_TO_NONDMA);
 
-               ice_debug(hw, ICE_DBG_PKG, "Ice Pkg: %d.%d.%d.%d, %s\n",
-                         seg_hdr->seg_ver.major, seg_hdr->seg_ver.minor,
-                         seg_hdr->seg_ver.update, seg_hdr->seg_ver.draft,
-                         seg_hdr->seg_name);
+               ice_debug(hw, ICE_DBG_PKG, "Ice Seg: %d.%d.%d.%d, %s\n",
+                         seg_hdr->seg_format_ver.major,
+                         seg_hdr->seg_format_ver.minor,
+                         seg_hdr->seg_format_ver.update,
+                         seg_hdr->seg_format_ver.draft,
+                         seg_hdr->seg_id);
        } else {
                ice_debug(hw, ICE_DBG_INIT,
                          "Did not find ice segment in driver package\n");
@@ -1150,9 +1155,11 @@ static enum ice_status ice_get_pkg_info(struct ice_hw *hw)
                if (pkg_info->pkg_info[i].is_active) {
                        flags[place++] = 'A';
                        hw->active_pkg_ver = pkg_info->pkg_info[i].ver;
+                       hw->active_track_id =
+                               LE32_TO_CPU(pkg_info->pkg_info[i].track_id);
                        ice_memcpy(hw->active_pkg_name,
                                   pkg_info->pkg_info[i].name,
-                                  sizeof(hw->active_pkg_name),
+                                  sizeof(pkg_info->pkg_info[i].name),
                                   ICE_NONDMA_TO_NONDMA);
                        hw->active_pkg_in_nvm = pkg_info->pkg_info[i].is_in_nvm;
                }
@@ -1193,10 +1200,10 @@ static enum ice_status ice_verify_pkg(struct ice_pkg_hdr *pkg, u32 len)
        if (len < sizeof(*pkg))
                return ICE_ERR_BUF_TOO_SHORT;
 
-       if (pkg->format_ver.major != ICE_PKG_FMT_VER_MAJ ||
-           pkg->format_ver.minor != ICE_PKG_FMT_VER_MNR ||
-           pkg->format_ver.update != ICE_PKG_FMT_VER_UPD ||
-           pkg->format_ver.draft != ICE_PKG_FMT_VER_DFT)
+       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;
 
        /* pkg must have at least one segment */
@@ -1279,6 +1286,70 @@ static enum ice_status ice_chk_pkg_version(struct ice_pkg_ver *pkg_ver)
        return ICE_SUCCESS;
 }
 
+/**
+ * ice_chk_pkg_compat
+ * @hw: pointer to the hardware structure
+ * @ospkg: pointer to the package hdr
+ * @seg: pointer to the package segment hdr
+ *
+ * This function checks the package version compatibility with driver and NVM
+ */
+static enum ice_status
+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;
+       u16 size;
+       u32 i;
+
+       ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
+
+       /* Check package version compatibility */
+       status = ice_chk_pkg_version(&hw->pkg_ver);
+       if (status) {
+               ice_debug(hw, ICE_DBG_INIT, "Package version check failed.\n");
+               return status;
+       }
+
+       /* find ICE segment in given package */
+       *seg = (struct ice_seg *)ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE,
+                                                    ospkg);
+       if (!*seg) {
+               ice_debug(hw, ICE_DBG_INIT, "no ice segment in package.\n");
+               return ICE_ERR_CFG;
+       }
+
+       /* Check if FW is compatible with the OS package */
+       size = ice_struct_size(pkg, pkg_info, ICE_PKG_CNT - 1);
+       pkg = (struct ice_aqc_get_pkg_info_resp *)ice_malloc(hw, size);
+       if (!pkg)
+               return ICE_ERR_NO_MEMORY;
+
+       status = ice_aq_get_pkg_info_list(hw, pkg, size, NULL);
+       if (status)
+               goto fw_ddp_compat_free_alloc;
+
+       for (i = 0; i < LE32_TO_CPU(pkg->count); i++) {
+               /* loop till we find the NVM package */
+               if (!pkg->pkg_info[i].is_in_nvm)
+                       continue;
+               if ((*seg)->hdr.seg_format_ver.major !=
+                       pkg->pkg_info[i].ver.major ||
+                   (*seg)->hdr.seg_format_ver.minor >
+                       pkg->pkg_info[i].ver.minor) {
+                       status = ICE_ERR_FW_DDP_MISMATCH;
+                       ice_debug(hw, ICE_DBG_INIT,
+                                 "OS package is not compatible with NVM.\n");
+               }
+               /* done processing NVM package so break */
+               break;
+       }
+fw_ddp_compat_free_alloc:
+       ice_free(hw, pkg);
+       return status;
+}
+
 /**
  * ice_init_pkg - initialize/download package
  * @hw: pointer to the hardware structure
@@ -1329,17 +1400,10 @@ enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len)
        /* before downloading the package, check package version for
         * compatibility with driver
         */
-       status = ice_chk_pkg_version(&hw->pkg_ver);
+       status = ice_chk_pkg_compat(hw, pkg, &seg);
        if (status)
                return status;
 
-       /* find segment in given package */
-       seg = (struct ice_seg *)ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE, pkg);
-       if (!seg) {
-               ice_debug(hw, ICE_DBG_INIT, "no ice segment in package.\n");
-               return ICE_ERR_CFG;
-       }
-
        /* initialize package hints and then download package */
        ice_init_pkg_hints(hw, seg);
        status = ice_download_pkg(hw, seg);
index 8f2f6ed..2c58608 100644 (file)
@@ -25,7 +25,7 @@ struct ice_fv {
 
 /* Package and segment headers and tables */
 struct ice_pkg_hdr {
-       struct ice_pkg_ver format_ver;
+       struct ice_pkg_ver pkg_format_ver;
        __le32 seg_count;
        __le32 seg_offset[1];
 };
@@ -35,9 +35,9 @@ struct ice_generic_seg_hdr {
 #define SEGMENT_TYPE_METADATA  0x00000001
 #define SEGMENT_TYPE_ICE       0x00000010
        __le32 seg_type;
-       struct ice_pkg_ver seg_ver;
+       struct ice_pkg_ver seg_format_ver;
        __le32 seg_size;
-       char seg_name[ICE_PKG_NAME_SIZE];
+       char seg_id[ICE_PKG_NAME_SIZE];
 };
 
 /* ice specific segment */
@@ -80,7 +80,7 @@ struct ice_buf_table {
 struct ice_global_metadata_seg {
        struct ice_generic_seg_hdr hdr;
        struct ice_pkg_ver pkg_ver;
-       __le32 track_id;
+       __le32 rsvd;
        char pkg_name[ICE_PKG_NAME_SIZE];
 };
 
index 9a9984d..7bcccd3 100644 (file)
@@ -28,6 +28,7 @@ enum ice_status {
        ICE_ERR_MAX_LIMIT                       = -17,
        ICE_ERR_RESET_ONGOING                   = -18,
        ICE_ERR_HW_TABLE                        = -19,
+       ICE_ERR_FW_DDP_MISMATCH                 = -20,
 
        /* NVM specific error codes: Range -50..-59 */
        ICE_ERR_NVM                             = -50,
index 9ee0d40..394867f 100644 (file)
@@ -866,6 +866,7 @@ struct ice_hw {
 
        /* Active package version (currently active) */
        struct ice_pkg_ver active_pkg_ver;
+       u32 active_track_id;
        u8 active_pkg_name[ICE_PKG_NAME_SIZE];
        u8 active_pkg_in_nvm;