net/ena: update version to 2.0.1
[dpdk.git] / drivers / net / ice / base / ice_flex_pipe.c
index babad94..c1f23ec 100644 (file)
@@ -7,19 +7,12 @@
 #include "ice_protocol_type.h"
 #include "ice_flow.h"
 
+/* To support tunneling entries by PF, the package will append the PF number to
+ * the label; for example TNL_VXLAN_PF0, TNL_VXLAN_PF1, TNL_VXLAN_PF2, etc.
+ */
 static const struct ice_tunnel_type_scan tnls[] = {
-       { TNL_VXLAN,            "TNL_VXLAN" },
-       { TNL_GTPC,             "TNL_GTPC" },
-       { TNL_GTPC_TEID,        "TNL_GTPC_TEID" },
-       { TNL_GTPU,             "TNL_GTPC" },
-       { TNL_GTPU_TEID,        "TNL_GTPU_TEID" },
-       { TNL_VXLAN_GPE,        "TNL_VXLAN_GPE" },
-       { TNL_GENEVE,           "TNL_GENEVE" },
-       { TNL_NAT,              "TNL_NAT" },
-       { TNL_ROCE_V2,          "TNL_ROCE_V2" },
-       { TNL_MPLSO_UDP,        "TNL_MPLSO_UDP" },
-       { TNL_UDP2_END,         "TNL_UDP2_END" },
-       { TNL_UPD_END,          "TNL_UPD_END" },
+       { TNL_VXLAN,            "TNL_VXLAN_PF" },
+       { TNL_GENEVE,           "TNL_GENEVE_PF" },
        { TNL_LAST,             "" }
 };
 
@@ -141,7 +134,7 @@ static struct ice_buf_table *ice_find_buf_table(struct ice_seg *ice_seg)
        nvms = (struct ice_nvm_table *)(ice_seg->device_table +
                LE32_TO_CPU(ice_seg->device_table_count));
 
-       return (struct ice_buf_table *)
+       return (_FORCE_ struct ice_buf_table *)
                (nvms->vers + LE32_TO_CPU(nvms->table_count));
 }
 
@@ -405,7 +398,7 @@ ice_find_boost_entry(struct ice_seg *ice_seg, u16 addr,
  * Handles enumeration of individual label entries.
  */
 static void *
-ice_label_enum_handler(u32 __always_unused sect_type, void *section, u32 index,
+ice_label_enum_handler(u32 __ALWAYS_UNUSED sect_type, void *section, u32 index,
                       u32 *offset)
 {
        struct ice_label_section *labels;
@@ -468,7 +461,7 @@ ice_enum_labels(struct ice_seg *ice_seg, u32 type, struct ice_pkg_enum *state,
  * since the first call to ice_enum_labels requires a pointer to an actual
  * ice_seg structure.
  */
-void ice_init_pkg_hints(struct ice_hw *hw, struct ice_seg *ice_seg)
+static void ice_init_pkg_hints(struct ice_hw *hw, struct ice_seg *ice_seg)
 {
        struct ice_pkg_enum state;
        char *label_name;
@@ -485,8 +478,17 @@ void ice_init_pkg_hints(struct ice_hw *hw, struct ice_seg *ice_seg)
 
        while (label_name && hw->tnl.count < ICE_TUNNEL_MAX_ENTRIES) {
                for (i = 0; tnls[i].type != TNL_LAST; i++) {
-                       if (!strncmp(label_name, tnls[i].label_prefix,
-                                    strlen(tnls[i].label_prefix))) {
+                       size_t len = strlen(tnls[i].label_prefix);
+
+                       /* Look for matching label start, before continuing */
+                       if (strncmp(label_name, tnls[i].label_prefix, len))
+                               continue;
+
+                       /* Make sure this label matches our PF. Note that the PF
+                        * character ('0' - '7') will be located where our
+                        * prefix string's null terminator is located.
+                        */
+                       if ((label_name[len] - '0') == hw->pf_id) {
                                hw->tnl.tbl[hw->tnl.count].type = tnls[i].type;
                                hw->tnl.tbl[hw->tnl.count].valid = false;
                                hw->tnl.tbl[hw->tnl.count].in_use = false;
@@ -638,7 +640,7 @@ static bool ice_bits_max_set(const u8 *mask, u16 size, u16 max)
  * @size: the size of the complete key in bytes (must be even)
  * @val: array of 8-bit values that makes up the value portion of the key
  * @upd: array of 8-bit masks that determine what key portion to update
- * @dc: array of 8-bit masks that make up the dont' care mask
+ * @dc: array of 8-bit masks that make up the don't care mask
  * @nm: array of 8-bit masks that make up the never match mask
  * @off: the offset of the first byte in the key to update
  * @len: the number of bytes in the key update
@@ -806,27 +808,6 @@ ice_aq_download_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf,
        return status;
 }
 
-/**
- * ice_aq_upload_section
- * @hw: pointer to the hardware structure
- * @pkg_buf: the package buffer which will receive the section
- * @buf_size: the size of the package buffer
- * @cd: pointer to command details structure or NULL
- *
- * Upload Section (0x0C41)
- */
-enum ice_status
-ice_aq_upload_section(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf,
-                     u16 buf_size, struct ice_sq_cd *cd)
-{
-       struct ice_aq_desc desc;
-
-       ice_debug(hw, ICE_DBG_TRACE, "ice_aq_upload_section");
-       ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_upload_section);
-       desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
-
-       return ice_aq_send_cmd(hw, &desc, pkg_buf, buf_size, cd);
-}
 
 /**
  * ice_aq_update_pkg
@@ -888,14 +869,14 @@ ice_aq_update_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf, u16 buf_size,
  * success it returns a pointer to the segment header, otherwise it will
  * return NULL.
  */
-struct ice_generic_seg_hdr *
+static struct ice_generic_seg_hdr *
 ice_find_seg_in_pkg(struct ice_hw *hw, u32 seg_type,
                    struct ice_pkg_hdr *pkg_hdr)
 {
        u32 i;
 
        ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
-       ice_debug(hw, ICE_DBG_PKG, "Package version: %d.%d.%d.%d\n",
+       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);
 
@@ -1003,9 +984,8 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
 
                bh = (struct ice_buf_hdr *)(bufs + i);
 
-               status = ice_aq_download_pkg(hw, bh, LE16_TO_CPU(bh->data_end),
-                                            last, &offset, &info, NULL);
-
+               status = ice_aq_download_pkg(hw, bh, ICE_PKG_BUF_SIZE, last,
+                                            &offset, &info, NULL);
                if (status) {
                        ice_debug(hw, ICE_DBG_PKG,
                                  "Pkg download failed: err %d off %d inf %d\n",
@@ -1051,7 +1031,8 @@ ice_aq_get_pkg_info_list(struct ice_hw *hw,
  *
  * Handles the download of a complete package.
  */
-enum ice_status ice_download_pkg(struct ice_hw *hw, struct ice_seg *ice_seg)
+static enum ice_status
+ice_download_pkg(struct ice_hw *hw, struct ice_seg *ice_seg)
 {
        struct ice_buf_table *ice_buf_tbl;
 
@@ -1080,15 +1061,11 @@ enum ice_status ice_download_pkg(struct ice_hw *hw, struct ice_seg *ice_seg)
  *
  * Saves off the package details into the HW structure.
  */
-enum ice_status
+static enum ice_status
 ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
 {
-       struct ice_aqc_get_pkg_info_resp *pkg_info;
        struct ice_global_metadata_seg *meta_seg;
        struct ice_generic_seg_hdr *seg_hdr;
-       enum ice_status status;
-       u16 size;
-       u32 i;
 
        ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
        if (!pkg_hdr)
@@ -1127,7 +1104,24 @@ ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
                return ICE_ERR_CFG;
        }
 
-#define ICE_PKG_CNT    4
+       return ICE_SUCCESS;
+}
+
+/**
+ * ice_get_pkg_info
+ * @hw: pointer to the hardware 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)
+{
+       struct ice_aqc_get_pkg_info_resp *pkg_info;
+       enum ice_status status;
+       u16 size;
+       u32 i;
+
+       ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
+
        size = sizeof(*pkg_info) + (sizeof(pkg_info->pkg_info[0]) *
                                    (ICE_PKG_CNT - 1));
        pkg_info = (struct ice_aqc_get_pkg_info_resp *)ice_malloc(hw, size);
@@ -1172,40 +1166,6 @@ init_pkg_free_alloc:
        return status;
 }
 
-/**
- * ice_find_label_value
- * @ice_seg: pointer to the ice segment (non-NULL)
- * @name: name of the label to search for
- * @type: the section type that will contain the label
- * @value: pointer to a value that will return the label's value if found
- *
- * Finds a label's value given the label name and the section type to search.
- * The ice_seg parameter must not be NULL since the first call to
- * ice_enum_labels requires a pointer to an actual ice_seg structure.
- */
-enum ice_status
-ice_find_label_value(struct ice_seg *ice_seg, char const *name, u32 type,
-                    u16 *value)
-{
-       struct ice_pkg_enum state;
-       char *label_name;
-       u16 val;
-
-       if (!ice_seg)
-               return ICE_ERR_PARAM;
-
-       do {
-               label_name = ice_enum_labels(ice_seg, type, &state, &val);
-               if (label_name && !strcmp(label_name, name)) {
-                       *value = val;
-                       return ICE_SUCCESS;
-               }
-
-               ice_seg = NULL;
-       } while (label_name);
-
-       return ICE_ERR_CFG;
-}
 
 /**
  * ice_verify_pkg - verify package
@@ -1310,6 +1270,32 @@ static void ice_init_pkg_regs(struct ice_hw *hw)
        ice_init_fd_mask_regs(hw);
 }
 
+/**
+ * ice_chk_pkg_version - check package version for compatibility with driver
+ * @hw: pointer to the hardware structure
+ * @pkg_ver: pointer to a version structure to check
+ *
+ * Check to make sure that the package about to be downloaded is compatible with
+ * the driver. To be compatible, the major and minor components of the package
+ * 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_hw *hw, struct ice_pkg_ver *pkg_ver)
+{
+       if (pkg_ver->major != ICE_PKG_SUPP_VER_MAJ ||
+           pkg_ver->minor != ICE_PKG_SUPP_VER_MNR) {
+               ice_info(hw, "ERROR: Incompatible package: %d.%d.%d.%d - requires package version: %d.%d.*.*\n",
+                        pkg_ver->major, pkg_ver->minor, pkg_ver->update,
+                        pkg_ver->draft, ICE_PKG_SUPP_VER_MAJ,
+                        ICE_PKG_SUPP_VER_MNR);
+
+               return ICE_ERR_NOT_SUPPORTED;
+       }
+
+       return ICE_SUCCESS;
+}
+
 /**
  * ice_init_pkg - initialize/download package
  * @hw: pointer to the hardware structure
@@ -1357,6 +1343,13 @@ enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len)
        if (status)
                return status;
 
+       /* before downloading the package, check package version for
+        * compatibility with driver
+        */
+       status = ice_chk_pkg_version(hw, &hw->pkg_ver);
+       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) {
@@ -1373,12 +1366,23 @@ enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len)
                status = ICE_SUCCESS;
        }
 
+       /* 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, &hw->active_pkg_ver);
+       }
+
        if (!status) {
                hw->seg = seg;
-               /* on successful package download, update other required
-                * registers to support the package
+               /* on successful package download update other required
+                * registers to support the package and fill HW tables
+                * with package content.
                 */
                ice_init_pkg_regs(hw);
+               ice_fill_blk_tbls(hw);
        } else {
                ice_debug(hw, ICE_DBG_INIT, "package load failed, %d\n",
                          status);
@@ -1440,7 +1444,7 @@ enum ice_status ice_copy_and_init_pkg(struct ice_hw *hw, const u8 *buf, u32 len)
  * Allocates a package buffer and returns a pointer to the buffer header.
  * Note: all package contents must be in Little Endian form.
  */
-struct ice_buf_build *ice_pkg_buf_alloc(struct ice_hw *hw)
+static struct ice_buf_build *ice_pkg_buf_alloc(struct ice_hw *hw)
 {
        struct ice_buf_build *bld;
        struct ice_buf_hdr *buf;
@@ -1564,40 +1568,15 @@ err:
 }
 
 /**
- * ice_pkg_buf_alloc_single_section
+ * ice_pkg_buf_free
  * @hw: pointer to the HW structure
- * @type: the section type value
- * @size: the size of the section to reserve (in bytes)
- * @section: returns pointer to the section
+ * @bld: pointer to pkg build (allocated by ice_pkg_buf_alloc())
  *
- * Allocates a package buffer with a single section.
- * Note: all package contents must be in Little Endian form.
+ * Frees a package buffer
  */
-static struct ice_buf_build *
-ice_pkg_buf_alloc_single_section(struct ice_hw *hw, u32 type, u16 size,
-                                void **section)
+static void ice_pkg_buf_free(struct ice_hw *hw, struct ice_buf_build *bld)
 {
-       struct ice_buf_build *buf;
-
-       if (!section)
-               return NULL;
-
-       buf = ice_pkg_buf_alloc(hw);
-       if (!buf)
-               return NULL;
-
-       if (ice_pkg_buf_reserve_section(buf, 1))
-               goto ice_pkg_buf_alloc_single_section_err;
-
-       *section = ice_pkg_buf_alloc_section(buf, type, size);
-       if (!*section)
-               goto ice_pkg_buf_alloc_single_section_err;
-
-       return buf;
-
-ice_pkg_buf_alloc_single_section_err:
-       ice_pkg_buf_free(hw, buf);
-       return NULL;
+       ice_free(hw, bld);
 }
 
 /**
@@ -1613,7 +1592,7 @@ ice_pkg_buf_alloc_single_section_err:
  * result in some wasted space in the buffer.
  * Note: all package contents must be in Little Endian form.
  */
-enum ice_status
+static enum ice_status
 ice_pkg_buf_reserve_section(struct ice_buf_build *bld, u16 count)
 {
        struct ice_buf_hdr *buf;
@@ -1641,48 +1620,6 @@ ice_pkg_buf_reserve_section(struct ice_buf_build *bld, u16 count)
        return ICE_SUCCESS;
 }
 
-/**
- * ice_pkg_buf_unreserve_section
- * @bld: pointer to pkg build (allocated by ice_pkg_buf_alloc())
- * @count: the number of sections to unreserve
- *
- * Unreserves one or more section table entries in a package buffer, releasing
- * space that can be used for section data. This routine can be called
- * multiple times as long as they are made before calling
- * ice_pkg_buf_alloc_section(). Once ice_pkg_buf_alloc_section()
- * is called once, the number of sections that can be allocated will not be able
- * to be increased; not using all reserved sections is fine, but this will
- * result in some wasted space in the buffer.
- * Note: all package contents must be in Little Endian form.
- */
-enum ice_status
-ice_pkg_buf_unreserve_section(struct ice_buf_build *bld, u16 count)
-{
-       struct ice_buf_hdr *buf;
-       u16 section_count;
-       u16 data_end;
-
-       if (!bld)
-               return ICE_ERR_PARAM;
-
-       buf = (struct ice_buf_hdr *)&bld->buf;
-
-       /* already an active section, can't decrease table size */
-       section_count = LE16_TO_CPU(buf->section_count);
-       if (section_count > 0)
-               return ICE_ERR_CFG;
-
-       if (count > bld->reserved_section_table_entries)
-               return ICE_ERR_CFG;
-       bld->reserved_section_table_entries -= count;
-
-       data_end = LE16_TO_CPU(buf->data_end) -
-                  (count * sizeof(buf->section_entry[0]));
-       buf->data_end = CPU_TO_LE16(data_end);
-
-       return ICE_SUCCESS;
-}
-
 /**
  * ice_pkg_buf_alloc_section
  * @bld: pointer to pkg build (allocated by ice_pkg_buf_alloc())
@@ -1695,7 +1632,7 @@ ice_pkg_buf_unreserve_section(struct ice_buf_build *bld, u16 count)
  * section contents.
  * Note: all package contents must be in Little Endian form.
  */
-void *
+static void *
 ice_pkg_buf_alloc_section(struct ice_buf_build *bld, u32 type, u16 size)
 {
        struct ice_buf_hdr *buf;
@@ -1736,24 +1673,6 @@ ice_pkg_buf_alloc_section(struct ice_buf_build *bld, u32 type, u16 size)
        return NULL;
 }
 
-/**
- * ice_pkg_buf_get_free_space
- * @bld: pointer to pkg build (allocated by ice_pkg_buf_alloc())
- *
- * Returns the number of free bytes remaining in the buffer.
- * Note: all package contents must be in Little Endian form.
- */
-u16 ice_pkg_buf_get_free_space(struct ice_buf_build *bld)
-{
-       struct ice_buf_hdr *buf;
-
-       if (!bld)
-               return 0;
-
-       buf = (struct ice_buf_hdr *)&bld->buf;
-       return ICE_MAX_S_DATA_END - LE16_TO_CPU(buf->data_end);
-}
-
 /**
  * ice_pkg_buf_get_active_sections
  * @bld: pointer to pkg build (allocated by ice_pkg_buf_alloc())
@@ -1764,7 +1683,7 @@ u16 ice_pkg_buf_get_free_space(struct ice_buf_build *bld)
  * not be used.
  * Note: all package contents must be in Little Endian form.
  */
-u16 ice_pkg_buf_get_active_sections(struct ice_buf_build *bld)
+static u16 ice_pkg_buf_get_active_sections(struct ice_buf_build *bld)
 {
        struct ice_buf_hdr *buf;
 
@@ -1781,7 +1700,7 @@ u16 ice_pkg_buf_get_active_sections(struct ice_buf_build *bld)
  *
  * Return a pointer to the buffer's header
  */
-struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld)
+static struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld)
 {
        if (!bld)
                return NULL;
@@ -1790,15 +1709,231 @@ struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld)
 }
 
 /**
- * ice_pkg_buf_free
+ * ice_tunnel_port_in_use
  * @hw: pointer to the HW structure
- * @bld: pointer to pkg build (allocated by ice_pkg_buf_alloc())
+ * @port: port to search for
+ * @index: optionally returns index
  *
- * Frees a package buffer
+ * Returns whether a port is already in use as a tunnel, and optionally its
+ * index
  */
-void ice_pkg_buf_free(struct ice_hw *hw, struct ice_buf_build *bld)
+bool ice_tunnel_port_in_use(struct ice_hw *hw, u16 port, u16 *index)
 {
-       ice_free(hw, bld);
+       u16 i;
+
+       for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
+               if (hw->tnl.tbl[i].in_use && hw->tnl.tbl[i].port == port) {
+                       if (index)
+                               *index = i;
+                       return true;
+               }
+
+       return false;
+}
+
+/**
+ * ice_tunnel_get_type
+ * @hw: pointer to the HW structure
+ * @port: port to search for
+ * @type: returns tunnel index
+ *
+ * For a given port number, will return the type of tunnel.
+ */
+bool
+ice_tunnel_get_type(struct ice_hw *hw, u16 port, enum ice_tunnel_type *type)
+{
+       u16 i;
+
+       for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
+               if (hw->tnl.tbl[i].in_use && hw->tnl.tbl[i].port == port) {
+                       *type = hw->tnl.tbl[i].type;
+                       return true;
+               }
+
+       return false;
+}
+
+/**
+ * ice_find_free_tunnel_entry
+ * @hw: pointer to the HW structure
+ * @type: tunnel type
+ * @index: optionally returns index
+ *
+ * Returns whether there is a free tunnel entry, and optionally its index
+ */
+static bool
+ice_find_free_tunnel_entry(struct ice_hw *hw, enum ice_tunnel_type type,
+                          u16 *index)
+{
+       u16 i;
+
+       for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
+               if (hw->tnl.tbl[i].valid && !hw->tnl.tbl[i].in_use &&
+                   hw->tnl.tbl[i].type == type) {
+                       if (index)
+                               *index = i;
+                       return true;
+               }
+
+       return false;
+}
+
+/**
+ * ice_create_tunnel
+ * @hw: pointer to the HW structure
+ * @type: type of tunnel
+ * @port: port to use for vxlan tunnel
+ *
+ * Creates a tunnel
+ */
+enum ice_status
+ice_create_tunnel(struct ice_hw *hw, enum ice_tunnel_type type, u16 port)
+{
+       struct ice_boost_tcam_section *sect_rx, *sect_tx;
+       enum ice_status status = ICE_ERR_MAX_LIMIT;
+       struct ice_buf_build *bld;
+       u16 index;
+
+       if (ice_tunnel_port_in_use(hw, port, NULL))
+               return ICE_ERR_ALREADY_EXISTS;
+
+       if (!ice_find_free_tunnel_entry(hw, type, &index))
+               return ICE_ERR_OUT_OF_RANGE;
+
+       bld = ice_pkg_buf_alloc(hw);
+       if (!bld)
+               return ICE_ERR_NO_MEMORY;
+
+       /* allocate 2 sections, one for RX parser, one for TX parser */
+       if (ice_pkg_buf_reserve_section(bld, 2))
+               goto ice_create_tunnel_err;
+
+       sect_rx = (struct ice_boost_tcam_section *)
+               ice_pkg_buf_alloc_section(bld, ICE_SID_RXPARSER_BOOST_TCAM,
+                                         sizeof(*sect_rx));
+       if (!sect_rx)
+               goto ice_create_tunnel_err;
+       sect_rx->count = CPU_TO_LE16(1);
+
+       sect_tx = (struct ice_boost_tcam_section *)
+               ice_pkg_buf_alloc_section(bld, ICE_SID_TXPARSER_BOOST_TCAM,
+                                         sizeof(*sect_tx));
+       if (!sect_tx)
+               goto ice_create_tunnel_err;
+       sect_tx->count = CPU_TO_LE16(1);
+
+       /* copy original boost entry to update package buffer */
+       ice_memcpy(sect_rx->tcam, hw->tnl.tbl[index].boost_entry,
+                  sizeof(*sect_rx->tcam), ICE_NONDMA_TO_NONDMA);
+
+       /* over-write the never-match dest port key bits with the encoded port
+        * bits
+        */
+       ice_set_key((u8 *)&sect_rx->tcam[0].key, sizeof(sect_rx->tcam[0].key),
+                   (u8 *)&port, NULL, NULL, NULL,
+                   offsetof(struct ice_boost_key_value, hv_dst_port_key),
+                   sizeof(sect_rx->tcam[0].key.key.hv_dst_port_key));
+
+       /* exact copy of entry to TX section entry */
+       ice_memcpy(sect_tx->tcam, sect_rx->tcam, sizeof(*sect_tx->tcam),
+                  ICE_NONDMA_TO_NONDMA);
+
+       status = ice_update_pkg(hw, ice_pkg_buf(bld), 1);
+       if (!status) {
+               hw->tnl.tbl[index].port = port;
+               hw->tnl.tbl[index].in_use = true;
+       }
+
+ice_create_tunnel_err:
+       ice_pkg_buf_free(hw, bld);
+
+       return status;
+}
+
+/**
+ * ice_destroy_tunnel
+ * @hw: pointer to the HW structure
+ * @port: port of tunnel to destroy (ignored if the all parameter is true)
+ * @all: flag that states to destroy all tunnels
+ *
+ * Destroys a tunnel or all tunnels by creating an update package buffer
+ * targeting the specific updates requested and then performing an update
+ * package.
+ */
+enum ice_status ice_destroy_tunnel(struct ice_hw *hw, u16 port, bool all)
+{
+       struct ice_boost_tcam_section *sect_rx, *sect_tx;
+       enum ice_status status = ICE_ERR_MAX_LIMIT;
+       struct ice_buf_build *bld;
+       u16 count = 0;
+       u16 size;
+       u16 i;
+
+       /* determine count */
+       for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
+               if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].in_use &&
+                   (all || hw->tnl.tbl[i].port == port))
+                       count++;
+
+       if (!count)
+               return ICE_ERR_PARAM;
+
+       /* size of section - there is at least one entry */
+       size = (count - 1) * sizeof(*sect_rx->tcam) + sizeof(*sect_rx);
+
+       bld = ice_pkg_buf_alloc(hw);
+       if (!bld)
+               return ICE_ERR_NO_MEMORY;
+
+       /* allocate 2 sections, one for RX parser, one for TX parser */
+       if (ice_pkg_buf_reserve_section(bld, 2))
+               goto ice_destroy_tunnel_err;
+
+       sect_rx = (struct ice_boost_tcam_section *)
+               ice_pkg_buf_alloc_section(bld, ICE_SID_RXPARSER_BOOST_TCAM,
+                                         size);
+       if (!sect_rx)
+               goto ice_destroy_tunnel_err;
+       sect_rx->count = CPU_TO_LE16(1);
+
+       sect_tx = (struct ice_boost_tcam_section *)
+               ice_pkg_buf_alloc_section(bld, ICE_SID_TXPARSER_BOOST_TCAM,
+                                         size);
+       if (!sect_tx)
+               goto ice_destroy_tunnel_err;
+       sect_tx->count = CPU_TO_LE16(1);
+
+       /* copy original boost entry to update package buffer, one copy to RX
+        * section, another copy to the TX section
+        */
+       for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
+               if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].in_use &&
+                   (all || hw->tnl.tbl[i].port == port)) {
+                       ice_memcpy(sect_rx->tcam + i,
+                                  hw->tnl.tbl[i].boost_entry,
+                                  sizeof(*sect_rx->tcam),
+                                  ICE_NONDMA_TO_NONDMA);
+                       ice_memcpy(sect_tx->tcam + i,
+                                  hw->tnl.tbl[i].boost_entry,
+                                  sizeof(*sect_tx->tcam),
+                                  ICE_NONDMA_TO_NONDMA);
+                       hw->tnl.tbl[i].marked = true;
+               }
+
+       status = ice_update_pkg(hw, ice_pkg_buf(bld), 1);
+       if (!status)
+               for (i = 0; i < hw->tnl.count &&
+                    i < ICE_TUNNEL_MAX_ENTRIES; i++)
+                       if (hw->tnl.tbl[i].marked) {
+                               hw->tnl.tbl[i].port = 0;
+                               hw->tnl.tbl[i].in_use = false;
+                               hw->tnl.tbl[i].marked = false;
+                       }
+
+ice_destroy_tunnel_err:
+       ice_pkg_buf_free(hw, bld);
+
+       return status;
 }
 
 /**
@@ -1832,38 +1967,6 @@ ice_find_prot_off(struct ice_hw *hw, enum ice_block blk, u8 prof, u8 fv_idx,
 
 /* PTG Management */
 
-/**
- * ice_ptg_update_xlt1 - Updates packet type groups in HW via XLT1 table
- * @hw: pointer to the hardware structure
- * @blk: HW block
- *
- * This function will update the XLT1 hardware table to reflect the new
- * packet type group configuration.
- */
-enum ice_status ice_ptg_update_xlt1(struct ice_hw *hw, enum ice_block blk)
-{
-       struct ice_xlt1_section *sect;
-       struct ice_buf_build *bld;
-       enum ice_status status;
-       u16 index;
-
-       bld = ice_pkg_buf_alloc_single_section(hw, ice_sect_id(blk, ICE_XLT1),
-                                              ICE_XLT1_SIZE(ICE_XLT1_CNT),
-                                              (void **)&sect);
-       if (!bld)
-               return ICE_ERR_NO_MEMORY;
-
-       sect->count = CPU_TO_LE16(ICE_XLT1_CNT);
-       sect->offset = CPU_TO_LE16(0);
-       for (index = 0; index < ICE_XLT1_CNT; index++)
-               sect->value[index] = hw->blk[blk].xlt1.ptypes[index].ptg;
-
-       status = ice_update_pkg(hw, ice_pkg_buf(bld), 1);
-
-       ice_pkg_buf_free(hw, bld);
-
-       return status;
-}
 
 /**
  * ice_ptg_find_ptype - Search for packet type group using packet type (ptype)
@@ -1876,7 +1979,7 @@ enum ice_status ice_ptg_update_xlt1(struct ice_hw *hw, enum ice_block blk)
  * PTG ID that contains it through the ptg parameter, with the value of
  * ICE_DEFAULT_PTG (0) meaning it is part the default PTG.
  */
-enum ice_status
+static enum ice_status
 ice_ptg_find_ptype(struct ice_hw *hw, enum ice_block blk, u16 ptype, u8 *ptg)
 {
        if (ptype >= ICE_XLT1_CNT || !ptg)
@@ -1910,7 +2013,7 @@ void ice_ptg_alloc_val(struct ice_hw *hw, enum ice_block blk, u8 ptg)
  * that 0 is the default packet type group, so successfully created PTGs will
  * have a non-zero ID value; which means a 0 return value indicates an error.
  */
-u8 ice_ptg_alloc(struct ice_hw *hw, enum ice_block blk)
+static u8 ice_ptg_alloc(struct ice_hw *hw, enum ice_block blk)
 {
        u16 i;
 
@@ -1925,31 +2028,6 @@ u8 ice_ptg_alloc(struct ice_hw *hw, enum ice_block blk)
        return 0;
 }
 
-/**
- * ice_ptg_free - Frees a packet type group
- * @hw: pointer to the hardware structure
- * @blk: HW block
- * @ptg: the ptg ID to free
- *
- * This function frees a packet type group, and returns all the current ptypes
- * within it to the default PTG.
- */
-void ice_ptg_free(struct ice_hw *hw, enum ice_block blk, u8 ptg)
-{
-       struct ice_ptg_ptype *p, *temp;
-
-       hw->blk[blk].xlt1.ptg_tbl[ptg].in_use = false;
-       p = hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype;
-       while (p) {
-               p->ptg = ICE_DEFAULT_PTG;
-               temp = p->next_ptype;
-               p->next_ptype = NULL;
-               p = temp;
-       }
-
-       hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype = NULL;
-}
-
 /**
  * ice_ptg_remove_ptype - Removes ptype from a particular packet type group
  * @hw: pointer to the hardware structure
@@ -2007,7 +2085,7 @@ ice_ptg_remove_ptype(struct ice_hw *hw, enum ice_block blk, u16 ptype, u8 ptg)
  * a destination PTG ID of ICE_DEFAULT_PTG (0) will move the ptype to the
  * default PTG.
  */
-enum ice_status
+static enum ice_status
 ice_ptg_add_mv_ptype(struct ice_hw *hw, enum ice_block blk, u16 ptype, u8 ptg)
 {
        enum ice_status status;
@@ -2143,70 +2221,6 @@ ice_match_prop_lst(struct LIST_HEAD_TYPE *list1, struct LIST_HEAD_TYPE *list2)
 
 /* VSIG Management */
 
-/**
- * ice_vsig_update_xlt2_sect - update one section of XLT2 table
- * @hw: pointer to the hardware structure
- * @blk: HW block
- * @vsi: HW VSI number to program
- * @vsig: vsig for the VSI
- *
- * This function will update the XLT2 hardware table with the input VSI
- * group configuration.
- */
-static enum ice_status
-ice_vsig_update_xlt2_sect(struct ice_hw *hw, enum ice_block blk, u16 vsi,
-                         u16 vsig)
-{
-       struct ice_xlt2_section *sect;
-       struct ice_buf_build *bld;
-       enum ice_status status;
-
-       bld = ice_pkg_buf_alloc_single_section(hw, ice_sect_id(blk, ICE_XLT2),
-                                              sizeof(struct ice_xlt2_section),
-                                              (void **)&sect);
-       if (!bld)
-               return ICE_ERR_NO_MEMORY;
-
-       sect->count = CPU_TO_LE16(1);
-       sect->offset = CPU_TO_LE16(vsi);
-       sect->value[0] = CPU_TO_LE16(vsig);
-
-       status = ice_update_pkg(hw, ice_pkg_buf(bld), 1);
-
-       ice_pkg_buf_free(hw, bld);
-
-       return status;
-}
-
-/**
- * ice_vsig_update_xlt2 - update XLT2 table with VSIG configuration
- * @hw: pointer to the hardware structure
- * @blk: HW block
- *
- * This function will update the XLT2 hardware table with the input VSI
- * group configuration of used vsis.
- */
-enum ice_status ice_vsig_update_xlt2(struct ice_hw *hw, enum ice_block blk)
-{
-       u16 vsi;
-
-       for (vsi = 0; vsi < ICE_MAX_VSI; vsi++) {
-               /* update only vsis that have been changed */
-               if (hw->blk[blk].xlt2.vsis[vsi].changed) {
-                       enum ice_status status;
-                       u16 vsig;
-
-                       vsig = hw->blk[blk].xlt2.vsis[vsi].vsig;
-                       status = ice_vsig_update_xlt2_sect(hw, blk, vsi, vsig);
-                       if (status)
-                               return status;
-
-                       hw->blk[blk].xlt2.vsis[vsi].changed = 0;
-               }
-       }
-
-       return ICE_SUCCESS;
-}
 
 /**
  * ice_vsig_find_vsi - find a VSIG that contains a specified VSI
@@ -2287,7 +2301,7 @@ static u16 ice_vsig_alloc(struct ice_hw *hw, enum ice_block blk)
  * for, the list must match exactly, including the order in which the
  * characteristics are listed.
  */
-enum ice_status
+static enum ice_status
 ice_find_dup_props_vsig(struct ice_hw *hw, enum ice_block blk,
                        struct LIST_HEAD_TYPE *chs, u16 *vsig)
 {
@@ -2314,7 +2328,7 @@ ice_find_dup_props_vsig(struct ice_hw *hw, enum ice_block blk,
  * The function will remove all VSIs associated with the input VSIG and move
  * them to the DEFAULT_VSIG and mark the VSIG available.
  */
-enum ice_status
+static enum ice_status
 ice_vsig_free(struct ice_hw *hw, enum ice_block blk, u16 vsig)
 {
        struct ice_vsig_prof *dtmp, *del;
@@ -2357,68 +2371,10 @@ ice_vsig_free(struct ice_hw *hw, enum ice_block blk, u16 vsig)
                ice_free(hw, del);
        }
 
-       return ICE_SUCCESS;
-}
-
-/**
- * ice_vsig_add_mv_vsi - add or move a VSI to a VSI group
- * @hw: pointer to the hardware structure
- * @blk: HW block
- * @vsi: VSI to move
- * @vsig: destination VSI group
- *
- * This function will move or add the input VSI to the target VSIG.
- * The function will find the original VSIG the VSI belongs to and
- * move the entry to the DEFAULT_VSIG, update the original VSIG and
- * then move entry to the new VSIG.
- */
-enum ice_status
-ice_vsig_add_mv_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig)
-{
-       struct ice_vsig_vsi *tmp;
-       enum ice_status status;
-       u16 orig_vsig, idx;
-
-       idx = vsig & ICE_VSIG_IDX_M;
-
-       if (vsi >= ICE_MAX_VSI || idx >= ICE_MAX_VSIGS)
-               return ICE_ERR_PARAM;
-
-       /* if VSIG not in use and VSIG is not default type this VSIG
-        * doesn't exist.
+       /* if VSIG characteristic list was cleared for reset
+        * re-initialize the list head
         */
-       if (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use &&
-           vsig != ICE_DEFAULT_VSIG)
-               return ICE_ERR_DOES_NOT_EXIST;
-
-       status = ice_vsig_find_vsi(hw, blk, vsi, &orig_vsig);
-       if (status)
-               return status;
-
-       /* no update required if vsigs match */
-       if (orig_vsig == vsig)
-               return ICE_SUCCESS;
-
-       if (orig_vsig != ICE_DEFAULT_VSIG) {
-               /* remove entry from orig_vsig and add to default VSIG */
-               status = ice_vsig_remove_vsi(hw, blk, vsi, orig_vsig);
-               if (status)
-                       return status;
-       }
-
-       if (idx == ICE_DEFAULT_VSIG)
-               return ICE_SUCCESS;
-
-       /* Create VSI entry and add VSIG and prop_mask values */
-       hw->blk[blk].xlt2.vsis[vsi].vsig = vsig;
-       hw->blk[blk].xlt2.vsis[vsi].changed = 1;
-
-       /* Add new entry to the head of the VSIG list */
-       tmp = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi;
-       hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi =
-               &hw->blk[blk].xlt2.vsis[vsi];
-       hw->blk[blk].xlt2.vsis[vsi].next_vsi = tmp;
-       hw->blk[blk].xlt2.t[vsi] = vsig;
+       INIT_LIST_HEAD(&hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst);
 
        return ICE_SUCCESS;
 }
@@ -2433,7 +2389,7 @@ ice_vsig_add_mv_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig)
  * The function will remove the input VSI from its VSI group and move it
  * to the DEFAULT_VSIG.
  */
-enum ice_status
+static enum ice_status
 ice_vsig_remove_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig)
 {
        struct ice_vsig_vsi **vsi_head, *vsi_cur, *vsi_tgt;
@@ -2479,6 +2435,69 @@ ice_vsig_remove_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig)
        return ICE_SUCCESS;
 }
 
+/**
+ * ice_vsig_add_mv_vsi - add or move a VSI to a VSI group
+ * @hw: pointer to the hardware structure
+ * @blk: HW block
+ * @vsi: VSI to move
+ * @vsig: destination VSI group
+ *
+ * This function will move or add the input VSI to the target VSIG.
+ * The function will find the original VSIG the VSI belongs to and
+ * move the entry to the DEFAULT_VSIG, update the original VSIG and
+ * then move entry to the new VSIG.
+ */
+static enum ice_status
+ice_vsig_add_mv_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig)
+{
+       struct ice_vsig_vsi *tmp;
+       enum ice_status status;
+       u16 orig_vsig, idx;
+
+       idx = vsig & ICE_VSIG_IDX_M;
+
+       if (vsi >= ICE_MAX_VSI || idx >= ICE_MAX_VSIGS)
+               return ICE_ERR_PARAM;
+
+       /* if VSIG not in use and VSIG is not default type this VSIG
+        * doesn't exist.
+        */
+       if (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use &&
+           vsig != ICE_DEFAULT_VSIG)
+               return ICE_ERR_DOES_NOT_EXIST;
+
+       status = ice_vsig_find_vsi(hw, blk, vsi, &orig_vsig);
+       if (status)
+               return status;
+
+       /* no update required if vsigs match */
+       if (orig_vsig == vsig)
+               return ICE_SUCCESS;
+
+       if (orig_vsig != ICE_DEFAULT_VSIG) {
+               /* remove entry from orig_vsig and add to default VSIG */
+               status = ice_vsig_remove_vsi(hw, blk, vsi, orig_vsig);
+               if (status)
+                       return status;
+       }
+
+       if (idx == ICE_DEFAULT_VSIG)
+               return ICE_SUCCESS;
+
+       /* Create VSI entry and add VSIG and prop_mask values */
+       hw->blk[blk].xlt2.vsis[vsi].vsig = vsig;
+       hw->blk[blk].xlt2.vsis[vsi].changed = 1;
+
+       /* Add new entry to the head of the VSIG list */
+       tmp = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi;
+       hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi =
+               &hw->blk[blk].xlt2.vsis[vsi];
+       hw->blk[blk].xlt2.vsis[vsi].next_vsi = tmp;
+       hw->blk[blk].xlt2.t[vsi] = vsig;
+
+       return ICE_SUCCESS;
+}
+
 /**
  * ice_find_prof_id - find profile ID for a given field vector
  * @hw: pointer to the hardware structure
@@ -2755,6 +2774,65 @@ static const u32 ice_blk_sids[ICE_BLK_COUNT][ICE_SID_OFF_COUNT] = {
        }
 };
 
+/**
+ * ice_init_sw_xlt1_db - init software XLT1 database from HW tables
+ * @hw: pointer to the hardware structure
+ * @blk: the HW block to initialize
+ */
+static
+void ice_init_sw_xlt1_db(struct ice_hw *hw, enum ice_block blk)
+{
+       u16 pt;
+
+       for (pt = 0; pt < hw->blk[blk].xlt1.count; pt++) {
+               u8 ptg;
+
+               ptg = hw->blk[blk].xlt1.t[pt];
+               if (ptg != ICE_DEFAULT_PTG) {
+                       ice_ptg_alloc_val(hw, blk, ptg);
+                       ice_ptg_add_mv_ptype(hw, blk, pt, ptg);
+               }
+       }
+}
+
+/**
+ * ice_init_sw_xlt2_db - init software XLT2 database from HW tables
+ * @hw: pointer to the hardware structure
+ * @blk: the HW block to initialize
+ */
+static void ice_init_sw_xlt2_db(struct ice_hw *hw, enum ice_block blk)
+{
+       u16 vsi;
+
+       for (vsi = 0; vsi < hw->blk[blk].xlt2.count; vsi++) {
+               u16 vsig;
+
+               vsig = hw->blk[blk].xlt2.t[vsi];
+               if (vsig) {
+                       ice_vsig_alloc_val(hw, blk, vsig);
+                       ice_vsig_add_mv_vsi(hw, blk, vsi, vsig);
+                       /* no changes at this time, since this has been
+                        * initialized from the original package
+                        */
+                       hw->blk[blk].xlt2.vsis[vsi].changed = 0;
+               }
+       }
+}
+
+/**
+ * ice_init_sw_db - init software database from HW tables
+ * @hw: pointer to the hardware structure
+ */
+static void ice_init_sw_db(struct ice_hw *hw)
+{
+       u16 i;
+
+       for (i = 0; i < ICE_BLK_COUNT; i++) {
+               ice_init_sw_xlt1_db(hw, (enum ice_block)i);
+               ice_init_sw_xlt2_db(hw, (enum ice_block)i);
+       }
+}
+
 /**
  * ice_fill_tbl - Reads content of a single table type into database
  * @hw: pointer to the hardware structure
@@ -2813,7 +2891,7 @@ static void ice_fill_tbl(struct ice_hw *hw, enum ice_block block_id, u32 sid)
                case ICE_SID_XLT2_ACL:
                case ICE_SID_XLT2_PE:
                        xlt2 = (struct ice_xlt2_section *)sect;
-                       src = (u8 *)xlt2->value;
+                       src = (_FORCE_ u8 *)xlt2->value;
                        sect_len = LE16_TO_CPU(xlt2->count) *
                                sizeof(*hw->blk[block_id].xlt2.t);
                        dst = (u8 *)hw->blk[block_id].xlt2.t;
@@ -2853,12 +2931,12 @@ static void ice_fill_tbl(struct ice_hw *hw, enum ice_block block_id, u32 sid)
                case ICE_SID_FLD_VEC_PE:
                        es = (struct ice_sw_fv_section *)sect;
                        src = (u8 *)es->fv;
-                       sect_len = LE16_TO_CPU(es->count) *
-                               hw->blk[block_id].es.fvw *
+                       sect_len = (u32)(LE16_TO_CPU(es->count) *
+                                        hw->blk[block_id].es.fvw) *
                                sizeof(*hw->blk[block_id].es.t);
                        dst = (u8 *)hw->blk[block_id].es.t;
-                       dst_len = hw->blk[block_id].es.count *
-                               hw->blk[block_id].es.fvw *
+                       dst_len = (u32)(hw->blk[block_id].es.count *
+                                       hw->blk[block_id].es.fvw) *
                                sizeof(*hw->blk[block_id].es.t);
                        break;
                default:
@@ -2886,75 +2964,79 @@ static void ice_fill_tbl(struct ice_hw *hw, enum ice_block block_id, u32 sid)
 }
 
 /**
- * ice_fill_blk_tbls - Read package content for tables of a block
+ * ice_fill_blk_tbls - Read package context for tables
  * @hw: pointer to the hardware structure
- * @block_id: The block ID which contains the tables to be copied
  *
  * Reads the current package contents and populates the driver
- * database with the data it contains to allow for advanced driver
- * features.
- */
-static void ice_fill_blk_tbls(struct ice_hw *hw, enum ice_block block_id)
-{
-       ice_fill_tbl(hw, block_id, hw->blk[block_id].xlt1.sid);
-       ice_fill_tbl(hw, block_id, hw->blk[block_id].xlt2.sid);
-       ice_fill_tbl(hw, block_id, hw->blk[block_id].prof.sid);
-       ice_fill_tbl(hw, block_id, hw->blk[block_id].prof_redir.sid);
-       ice_fill_tbl(hw, block_id, hw->blk[block_id].es.sid);
-}
-
-/**
- * ice_free_flow_profs - free flow profile entries
- * @hw: pointer to the hardware structure
+ * database with the data iteratively for all advanced feature
+ * blocks. Assume that the Hw tables have been allocated.
  */
-static void ice_free_flow_profs(struct ice_hw *hw)
+void ice_fill_blk_tbls(struct ice_hw *hw)
 {
        u8 i;
 
        for (i = 0; i < ICE_BLK_COUNT; i++) {
-               struct ice_flow_prof *p, *tmp;
-
-               if (!&hw->fl_profs[i])
-                       continue;
+               enum ice_block blk_id = (enum ice_block)i;
 
-               /* This call is being made as part of resource deallocation
-                * during unload. Lock acquire and release will not be
-                * necessary here.
-                */
-               LIST_FOR_EACH_ENTRY_SAFE(p, tmp, &hw->fl_profs[i],
-                                        ice_flow_prof, l_entry) {
-                       struct ice_flow_entry *e, *t;
+               ice_fill_tbl(hw, blk_id, hw->blk[blk_id].xlt1.sid);
+               ice_fill_tbl(hw, blk_id, hw->blk[blk_id].xlt2.sid);
+               ice_fill_tbl(hw, blk_id, hw->blk[blk_id].prof.sid);
+               ice_fill_tbl(hw, blk_id, hw->blk[blk_id].prof_redir.sid);
+               ice_fill_tbl(hw, blk_id, hw->blk[blk_id].es.sid);
+       }
 
-                       LIST_FOR_EACH_ENTRY_SAFE(e, t, &p->entries,
-                                                ice_flow_entry, l_entry)
-                               ice_flow_rem_entry(hw, ICE_FLOW_ENTRY_HNDL(e));
+       ice_init_sw_db(hw);
+}
 
-                       LIST_DEL(&p->l_entry);
-                       if (p->acts)
-                               ice_free(hw, p->acts);
-                       ice_free(hw, p);
-               }
+/**
+ * ice_free_prof_map - free profile map
+ * @hw: pointer to the hardware structure
+ * @blk_idx: HW block index
+ */
+static void ice_free_prof_map(struct ice_hw *hw, u8 blk_idx)
+{
+       struct ice_es *es = &hw->blk[blk_idx].es;
+       struct ice_prof_map *del, *tmp;
 
-               ice_destroy_lock(&hw->fl_profs_locks[i]);
+       ice_acquire_lock(&es->prof_map_lock);
+       LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &es->prof_map,
+                                ice_prof_map, list) {
+               LIST_DEL(&del->list);
+               ice_free(hw, del);
        }
+       INIT_LIST_HEAD(&es->prof_map);
+       ice_release_lock(&es->prof_map_lock);
 }
 
 /**
- * ice_free_prof_map - frees the profile map
+ * ice_free_flow_profs - free flow profile entries
  * @hw: pointer to the hardware structure
- * @blk: the HW block which contains the profile map to be freed
+ * @blk_idx: HW block index
  */
-static void ice_free_prof_map(struct ice_hw *hw, enum ice_block blk)
+static void ice_free_flow_profs(struct ice_hw *hw, u8 blk_idx)
 {
-       struct ice_prof_map *del, *tmp;
+       struct ice_flow_prof *p, *tmp;
 
-       if (LIST_EMPTY(&hw->blk[blk].es.prof_map))
-               return;
+       ice_acquire_lock(&hw->fl_profs_locks[blk_idx]);
+       LIST_FOR_EACH_ENTRY_SAFE(p, tmp, &hw->fl_profs[blk_idx],
+                                ice_flow_prof, l_entry) {
+               struct ice_flow_entry *e, *t;
 
-       LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &hw->blk[blk].es.prof_map,
-                                ice_prof_map, list) {
-               ice_rem_prof(hw, blk, del->profile_cookie);
+               LIST_FOR_EACH_ENTRY_SAFE(e, t, &p->entries,
+                                        ice_flow_entry, l_entry)
+                       ice_flow_rem_entry(hw, ICE_FLOW_ENTRY_HNDL(e));
+
+               LIST_DEL(&p->l_entry);
+               if (p->acts)
+                       ice_free(hw, p->acts);
+               ice_free(hw, p);
        }
+       ice_release_lock(&hw->fl_profs_locks[blk_idx]);
+
+       /* if driver is in reset and tables are being cleared
+        * re-initialize the flow profile list heads
+        */
+       INIT_LIST_HEAD(&hw->fl_profs[blk_idx]);
 }
 
 /**
@@ -2980,10 +3062,20 @@ static void ice_free_vsig_tbl(struct ice_hw *hw, enum ice_block blk)
  */
 void ice_free_hw_tbls(struct ice_hw *hw)
 {
+       struct ice_rss_cfg *r, *rt;
        u8 i;
 
        for (i = 0; i < ICE_BLK_COUNT; i++) {
-               ice_free_prof_map(hw, (enum ice_block)i);
+               if (hw->blk[i].is_list_init) {
+                       struct ice_es *es = &hw->blk[i].es;
+
+                       ice_free_prof_map(hw, i);
+                       ice_destroy_lock(&es->prof_map_lock);
+                       ice_free_flow_profs(hw, i);
+                       ice_destroy_lock(&hw->fl_profs_locks[i]);
+
+                       hw->blk[i].is_list_init = false;
+               }
                ice_free_vsig_tbl(hw, (enum ice_block)i);
                ice_free(hw, hw->blk[i].xlt1.ptypes);
                ice_free(hw, hw->blk[i].xlt1.ptg_tbl);
@@ -2998,84 +3090,24 @@ void ice_free_hw_tbls(struct ice_hw *hw)
                ice_free(hw, hw->blk[i].es.written);
        }
 
+       LIST_FOR_EACH_ENTRY_SAFE(r, rt, &hw->rss_list_head,
+                                ice_rss_cfg, l_entry) {
+               LIST_DEL(&r->l_entry);
+               ice_free(hw, r);
+       }
+       ice_destroy_lock(&hw->rss_locks);
        ice_memset(hw->blk, 0, sizeof(hw->blk), ICE_NONDMA_MEM);
-
-       ice_free_flow_profs(hw);
 }
 
 /**
  * ice_init_flow_profs - init flow profile locks and list heads
  * @hw: pointer to the hardware structure
+ * @blk_idx: HW block index
  */
-static void ice_init_flow_profs(struct ice_hw *hw)
-{
-       u8 i;
-
-       for (i = 0; i < ICE_BLK_COUNT; i++) {
-               ice_init_lock(&hw->fl_profs_locks[i]);
-               INIT_LIST_HEAD(&hw->fl_profs[i]);
-       }
-}
-
-/**
- * ice_init_sw_xlt1_db - init software XLT1 database from HW tables
- * @hw: pointer to the hardware structure
- * @blk: the HW block to initialize
- */
-static
-void ice_init_sw_xlt1_db(struct ice_hw *hw, enum ice_block blk)
-{
-       u16 pt;
-
-       for (pt = 0; pt < hw->blk[blk].xlt1.count; pt++) {
-               u8 ptg;
-
-               ptg = hw->blk[blk].xlt1.t[pt];
-               if (ptg != ICE_DEFAULT_PTG) {
-                       ice_ptg_alloc_val(hw, blk, ptg);
-                       ice_ptg_add_mv_ptype(hw, blk, pt, ptg);
-               }
-       }
-}
-
-/**
- * ice_init_sw_xlt2_db - init software XLT2 database from HW tables
- * @hw: pointer to the hardware structure
- * @blk: the HW block to initialize
- */
-static
-void ice_init_sw_xlt2_db(struct ice_hw *hw, enum ice_block blk)
-{
-       u16 vsi;
-
-       for (vsi = 0; vsi < hw->blk[blk].xlt2.count; vsi++) {
-               u16 vsig;
-
-               vsig = hw->blk[blk].xlt2.t[vsi];
-               if (vsig) {
-                       ice_vsig_alloc_val(hw, blk, vsig);
-                       ice_vsig_add_mv_vsi(hw, blk, vsi, vsig);
-                       /* no changes at this time, since this has been
-                        * initialized from the original package
-                        */
-                       hw->blk[blk].xlt2.vsis[vsi].changed = 0;
-               }
-       }
-}
-
-/**
- * ice_init_sw_db - init software database from HW tables
- * @hw: pointer to the hardware structure
- */
-static
-void ice_init_sw_db(struct ice_hw *hw)
+static void ice_init_flow_profs(struct ice_hw *hw, u8 blk_idx)
 {
-       u16 i;
-
-       for (i = 0; i < ICE_BLK_COUNT; i++) {
-               ice_init_sw_xlt1_db(hw, (enum ice_block)i);
-               ice_init_sw_xlt2_db(hw, (enum ice_block)i);
-       }
+       ice_init_lock(&hw->fl_profs_locks[blk_idx]);
+       INIT_LIST_HEAD(&hw->fl_profs[blk_idx]);
 }
 
 /**
@@ -3086,14 +3118,23 @@ enum ice_status ice_init_hw_tbls(struct ice_hw *hw)
 {
        u8 i;
 
-       ice_init_flow_profs(hw);
-
+       ice_init_lock(&hw->rss_locks);
+       INIT_LIST_HEAD(&hw->rss_list_head);
        for (i = 0; i < ICE_BLK_COUNT; i++) {
                struct ice_prof_redir *prof_redir = &hw->blk[i].prof_redir;
                struct ice_prof_tcam *prof = &hw->blk[i].prof;
                struct ice_xlt1 *xlt1 = &hw->blk[i].xlt1;
                struct ice_xlt2 *xlt2 = &hw->blk[i].xlt2;
                struct ice_es *es = &hw->blk[i].es;
+               u16 j;
+
+               if (hw->blk[i].is_list_init)
+                       continue;
+
+               ice_init_flow_profs(hw, i);
+               ice_init_lock(&es->prof_map_lock);
+               INIT_LIST_HEAD(&es->prof_map);
+               hw->blk[i].is_list_init = true;
 
                hw->blk[i].overwrite = blk_sizes[i].overwrite;
                es->reverse = blk_sizes[i].reverse;
@@ -3131,6 +3172,9 @@ enum ice_status ice_init_hw_tbls(struct ice_hw *hw)
                if (!xlt2->vsig_tbl)
                        goto err;
 
+               for (j = 0; j < xlt2->count; j++)
+                       INIT_LIST_HEAD(&xlt2->vsig_tbl[j].prop_lst);
+
                xlt2->t = (u16 *)ice_calloc(hw, xlt2->count, sizeof(*xlt2->t));
                if (!xlt2->t)
                        goto err;
@@ -3157,8 +3201,8 @@ enum ice_status ice_init_hw_tbls(struct ice_hw *hw)
                es->count = blk_sizes[i].es;
                es->fvw = blk_sizes[i].fvw;
                es->t = (struct ice_fv_word *)
-                       ice_calloc(hw, es->count * es->fvw, sizeof(*es->t));
-
+                       ice_calloc(hw, (u32)(es->count * es->fvw),
+                                  sizeof(*es->t));
                if (!es->t)
                        goto err;
 
@@ -3170,15 +3214,7 @@ enum ice_status ice_init_hw_tbls(struct ice_hw *hw)
 
                if (!es->ref_count)
                        goto err;
-
-               INIT_LIST_HEAD(&es->prof_map);
-
-               /* Now that tables are allocated, read in package data */
-               ice_fill_blk_tbls(hw, (enum ice_block)i);
        }
-
-       ice_init_sw_db(hw);
-
        return ICE_SUCCESS;
 
 err:
@@ -3689,7 +3725,7 @@ ice_update_fd_swap(struct ice_hw *hw, u16 prof_id, struct ice_fv_word *es)
        u32 mask_sel = 0;
        u8 i, j, k;
 
-       ice_memset(pair_list, 0, sizeof(pair_list), ICE_NONDMA_MEM);
+       ice_zero_bitmap(pair_list, ICE_FD_SRC_DST_PAIR_COUNT);
 
        ice_init_fd_mask_regs(hw);
 
@@ -3755,7 +3791,7 @@ ice_update_fd_swap(struct ice_hw *hw, u16 prof_id, struct ice_fv_word *es)
 
        /* fill in the swap array */
        si = hw->blk[ICE_BLK_FD].es.fvw - 1;
-       do {
+       while (si >= 0) {
                u8 indexes_used = 1;
 
                /* assume flat at this index */
@@ -3787,7 +3823,7 @@ ice_update_fd_swap(struct ice_hw *hw, u16 prof_id, struct ice_fv_word *es)
                }
 
                si -= indexes_used;
-       } while (si >= 0);
+       }
 
        /* for each set of 4 swap indexes, write the appropriate register */
        for (j = 0; j < hw->blk[ICE_BLK_FD].es.fvw / 4; j++) {
@@ -3798,7 +3834,7 @@ ice_update_fd_swap(struct ice_hw *hw, u16 prof_id, struct ice_fv_word *es)
 
                        idx = (j * 4) + k;
                        if (used[idx])
-                               raw_entry |= used[idx] << (k * 8);
+                               raw_entry |= used[idx] << (k * BITS_PER_BYTE);
                }
 
                /* write the appropriate register set, based on HW block */
@@ -3839,6 +3875,8 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[],
        u32 byte = 0;
        u8 prof_id;
 
+       ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
+
        /* search for existing profile */
        status = ice_find_prof_id(hw, blk, es, &prof_id);
        if (status) {
@@ -3891,7 +3929,7 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[],
                                u16 ptype;
                                u8 m;
 
-                               ptype = byte * 8 + bit;
+                               ptype = byte * BITS_PER_BYTE + bit;
                                if (ptype < ICE_FLOW_PTYPE_MAX) {
                                        prof->ptype[prof->ptype_count] = ptype;
 
@@ -3910,24 +3948,26 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[],
                bytes--;
                byte++;
        }
-       LIST_ADD(&prof->list, &hw->blk[blk].es.prof_map);
 
-       return ICE_SUCCESS;
+       LIST_ADD(&prof->list, &hw->blk[blk].es.prof_map);
+       status = ICE_SUCCESS;
 
 err_ice_add_prof:
+       ice_release_lock(&hw->blk[blk].es.prof_map_lock);
        return status;
 }
 
 /**
- * ice_search_prof_id - Search for a profile tracking ID
+ * ice_search_prof_id_low - Search for a profile tracking ID low level
  * @hw: pointer to the HW struct
  * @blk: hardware block
  * @id: profile tracking ID
  *
- * This will search for a profile tracking ID which was previously added.
+ * This will search for a profile tracking ID which was previously added. This
+ * version assumes that the caller has already acquired the prof map lock.
  */
-struct ice_prof_map *
-ice_search_prof_id(struct ice_hw *hw, enum ice_block blk, u64 id)
+static struct ice_prof_map *
+ice_search_prof_id_low(struct ice_hw *hw, enum ice_block blk, u64 id)
 {
        struct ice_prof_map *entry = NULL;
        struct ice_prof_map *map;
@@ -3944,39 +3984,21 @@ ice_search_prof_id(struct ice_hw *hw, enum ice_block blk, u64 id)
 }
 
 /**
- * ice_set_prof_context - Set context for a given profile
- * @hw: pointer to the HW struct
- * @blk: hardware block
- * @id: profile tracking ID
- * @cntxt: context
- */
-struct ice_prof_map *
-ice_set_prof_context(struct ice_hw *hw, enum ice_block blk, u64 id, u64 cntxt)
-{
-       struct ice_prof_map *entry;
-
-       entry = ice_search_prof_id(hw, blk, id);
-       if (entry)
-               entry->context = cntxt;
-
-       return entry;
-}
-
-/**
- * ice_get_prof_context - Get context for a given profile
+ * ice_search_prof_id - Search for a profile tracking ID
  * @hw: pointer to the HW struct
  * @blk: hardware block
  * @id: profile tracking ID
- * @cntxt: pointer to variable to receive the context
+ *
+ * This will search for a profile tracking ID which was previously added.
  */
 struct ice_prof_map *
-ice_get_prof_context(struct ice_hw *hw, enum ice_block blk, u64 id, u64 *cntxt)
+ice_search_prof_id(struct ice_hw *hw, enum ice_block blk, u64 id)
 {
        struct ice_prof_map *entry;
 
-       entry = ice_search_prof_id(hw, blk, id);
-       if (entry)
-               *cntxt = entry->context;
+       ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
+       entry = ice_search_prof_id_low(hw, blk, id);
+       ice_release_lock(&hw->blk[blk].es.prof_map_lock);
 
        return entry;
 }
@@ -4195,29 +4217,33 @@ err_ice_rem_flow_all:
  */
 enum ice_status ice_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 id)
 {
-       enum ice_status status;
        struct ice_prof_map *pmap;
+       enum ice_status status;
 
-       pmap = ice_search_prof_id(hw, blk, id);
-       if (!pmap)
-               return ICE_ERR_DOES_NOT_EXIST;
+       ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
+
+       pmap = ice_search_prof_id_low(hw, blk, id);
+       if (!pmap) {
+               status = ICE_ERR_DOES_NOT_EXIST;
+               goto err_ice_rem_prof;
+       }
 
        /* remove all flows with this profile */
        status = ice_rem_flow_all(hw, blk, pmap->profile_cookie);
        if (status)
-               return status;
+               goto err_ice_rem_prof;
 
-       /* remove profile */
-       status = ice_free_prof_id(hw, blk, pmap->prof_id);
-       if (status)
-               return status;
        /* dereference profile, and possibly remove */
        ice_prof_dec_ref(hw, blk, pmap->prof_id);
 
        LIST_DEL(&pmap->list);
        ice_free(hw, pmap);
 
-       return ICE_SUCCESS;
+       status = ICE_SUCCESS;
+
+err_ice_rem_prof:
+       ice_release_lock(&hw->blk[blk].es.prof_map_lock);
+       return status;
 }
 
 /**
@@ -4383,6 +4409,7 @@ ice_move_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig,
        status = ice_vsig_find_vsi(hw, blk, vsi, &orig_vsig);
        if (!status)
                status = ice_vsig_add_mv_vsi(hw, blk, vsi, vsig);
+
        if (status) {
                ice_free(hw, p);
                return status;
@@ -4474,7 +4501,7 @@ ice_adj_prof_priorities(struct ice_hw *hw, enum ice_block blk, u16 vsig,
        enum ice_status status;
        u16 idx;
 
-       ice_memset(ptgs_used, 0, sizeof(ptgs_used), ICE_NONDMA_MEM);
+       ice_zero_bitmap(ptgs_used, ICE_XLT1_CNT);
        idx = vsig & ICE_VSIG_IDX_M;
 
        /* Priority is based on the order in which the profiles are added. The
@@ -4891,34 +4918,6 @@ err_ice_add_prof_id_flow:
        return status;
 }
 
-/**
- * ice_add_flow - add flow
- * @hw: pointer to the HW struct
- * @blk: hardware block
- * @vsi: array of VSIs to enable with the profile specified by ID
- * @count: number of elements in the VSI array
- * @id: profile tracking ID
- *
- * Calling this function will update the hardware tables to enable the
- * profile indicated by the ID parameter for the VSIs specified in the VSI
- * array. Once successfully called, the flow will be enabled.
- */
-enum ice_status
-ice_add_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi[], u8 count,
-            u64 id)
-{
-       enum ice_status status;
-       u16 i;
-
-       for (i = 0; i < count; i++) {
-               status = ice_add_prof_id_flow(hw, blk, vsi[i], id);
-               if (status)
-                       return status;
-       }
-
-       return ICE_SUCCESS;
-}
-
 /**
  * ice_rem_prof_from_list - remove a profile from list
  * @hw: pointer to the HW struct
@@ -5072,31 +5071,3 @@ err_ice_rem_prof_id_flow:
 
        return status;
 }
-
-/**
- * ice_rem_flow - remove flow
- * @hw: pointer to the HW struct
- * @blk: hardware block
- * @vsi: array of VSIs from which to remove the profile specified by ID
- * @count: number of elements in the VSI array
- * @id: profile tracking ID
- *
- * The function will remove flows from the specified VSIs that were enabled
- * using ice_add_flow. The ID value will indicated which profile will be
- * removed. Once successfully called, the flow will be disabled.
- */
-enum ice_status
-ice_rem_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi[], u8 count,
-            u64 id)
-{
-       enum ice_status status;
-       u16 i;
-
-       for (i = 0; i < count; i++) {
-               status = ice_rem_prof_id_flow(hw, blk, vsi[i], id);
-               if (status)
-                       return status;
-       }
-
-       return ICE_SUCCESS;
-}