get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/1159941/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 1159941,
    "url": "http://patchwork.ozlabs.org/api/patches/1159941/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20190909134747.10415-4-anthony.l.nguyen@intel.com/",
    "project": {
        "id": 46,
        "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api",
        "name": "Intel Wired Ethernet development",
        "link_name": "intel-wired-lan",
        "list_id": "intel-wired-lan.osuosl.org",
        "list_email": "intel-wired-lan@osuosl.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20190909134747.10415-4-anthony.l.nguyen@intel.com>",
    "list_archive_url": null,
    "date": "2019-09-09T13:47:45",
    "name": "[S29,v3,4/6] ice: Initialize DDP package structures",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "a1f51102c463426a3c41d5edc3f5e9a46671f59a",
    "submitter": {
        "id": 68875,
        "url": "http://patchwork.ozlabs.org/api/people/68875/?format=api",
        "name": "Tony Nguyen",
        "email": "anthony.l.nguyen@intel.com"
    },
    "delegate": {
        "id": 68,
        "url": "http://patchwork.ozlabs.org/api/users/68/?format=api",
        "username": "jtkirshe",
        "first_name": "Jeff",
        "last_name": "Kirsher",
        "email": "jeffrey.t.kirsher@intel.com"
    },
    "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20190909134747.10415-4-anthony.l.nguyen@intel.com/mbox/",
    "series": [
        {
            "id": 129833,
            "url": "http://patchwork.ozlabs.org/api/series/129833/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=129833",
            "date": "2019-09-09T13:47:42",
            "name": "[S29,v3,1/6] ice: send driver version to firmware",
            "version": 3,
            "mbox": "http://patchwork.ozlabs.org/series/129833/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/1159941/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/1159941/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<intel-wired-lan-bounces@osuosl.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "intel-wired-lan@lists.osuosl.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@bilbo.ozlabs.org",
            "intel-wired-lan@lists.osuosl.org"
        ],
        "Authentication-Results": [
            "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=osuosl.org\n\t(client-ip=140.211.166.138; helo=whitealder.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)",
            "ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=intel.com"
        ],
        "Received": [
            "from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 46S2b24hpyz9sP7\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 10 Sep 2019 08:17:18 +1000 (AEST)",
            "from localhost (localhost [127.0.0.1])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 6C0D285C13;\n\tMon,  9 Sep 2019 22:17:16 +0000 (UTC)",
            "from whitealder.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id QofMvbrjKdh4; Mon,  9 Sep 2019 22:17:10 +0000 (UTC)",
            "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 1FE8185C10;\n\tMon,  9 Sep 2019 22:17:10 +0000 (UTC)",
            "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id BF29D1BF96A\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tMon,  9 Sep 2019 22:17:07 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id ADF65878A5\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tMon,  9 Sep 2019 22:17:07 +0000 (UTC)",
            "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id KETQG0Srto8J for <intel-wired-lan@lists.osuosl.org>;\n\tMon,  9 Sep 2019 22:17:04 +0000 (UTC)",
            "from mga06.intel.com (mga06.intel.com [134.134.136.31])\n\tby hemlock.osuosl.org (Postfix) with ESMTPS id 5DFE7878A8\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tMon,  9 Sep 2019 22:17:04 +0000 (UTC)",
            "from fmsmga003.fm.intel.com ([10.253.24.29])\n\tby orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t09 Sep 2019 15:17:03 -0700",
            "from unknown (HELO localhost.jf.intel.com) ([10.166.244.174])\n\tby FMSMGA003.fm.intel.com with ESMTP; 09 Sep 2019 15:17:03 -0700"
        ],
        "X-Virus-Scanned": [
            "amavisd-new at osuosl.org",
            "amavisd-new at osuosl.org"
        ],
        "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6",
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.64,487,1559545200\"; d=\"scan'208\";a=\"191631118\"",
        "From": "Tony Nguyen <anthony.l.nguyen@intel.com>",
        "To": "intel-wired-lan@lists.osuosl.org",
        "Date": "Mon,  9 Sep 2019 06:47:45 -0700",
        "Message-Id": "<20190909134747.10415-4-anthony.l.nguyen@intel.com>",
        "X-Mailer": "git-send-email 2.20.1",
        "In-Reply-To": "<20190909134747.10415-1-anthony.l.nguyen@intel.com>",
        "References": "<20190909134747.10415-1-anthony.l.nguyen@intel.com>",
        "MIME-Version": "1.0",
        "Subject": "[Intel-wired-lan] [PATCH S29 v3 4/6] ice: Initialize DDP package\n\tstructures",
        "X-BeenThere": "intel-wired-lan@osuosl.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.osuosl.org>",
        "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>",
        "List-Post": "<mailto:intel-wired-lan@osuosl.org>",
        "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>",
        "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "intel-wired-lan-bounces@osuosl.org",
        "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>"
    },
    "content": "Add functions to initialize, parse, and clean structures representing\nthe DDP package.\n\nUpon completion of package download, read and store the DDP package\ncontents to these structures.  This configuration is used to\nidentify the default behavior and later used to update the HW table\nentries.\n\nSigned-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>\n---\n drivers/net/ethernet/intel/ice/ice_common.c   |   5 +-\n .../net/ethernet/intel/ice/ice_flex_pipe.c    | 945 +++++++++++++++++-\n .../net/ethernet/intel/ice/ice_flex_pipe.h    |   3 +\n .../net/ethernet/intel/ice/ice_flex_type.h    |   2 +\n 4 files changed, 953 insertions(+), 2 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c\nindex 20956643036c..91472e049231 100644\n--- a/drivers/net/ethernet/intel/ice/ice_common.c\n+++ b/drivers/net/ethernet/intel/ice/ice_common.c\n@@ -882,7 +882,9 @@ enum ice_status ice_init_hw(struct ice_hw *hw)\n \n \tice_init_flex_flds(hw, ICE_RXDID_FLEX_NIC);\n \tice_init_flex_flds(hw, ICE_RXDID_FLEX_NIC_2);\n-\n+\tstatus = ice_init_hw_tbls(hw);\n+\tif (status)\n+\t\tgoto err_unroll_fltr_mgmt_struct;\n \treturn 0;\n \n err_unroll_fltr_mgmt_struct:\n@@ -911,6 +913,7 @@ void ice_deinit_hw(struct ice_hw *hw)\n \tice_sched_cleanup_all(hw);\n \tice_sched_clear_agg(hw);\n \tice_free_seg(hw);\n+\tice_free_hw_tbls(hw);\n \n \tif (hw->port_info) {\n \t\tdevm_kfree(ice_hw_to_dev(hw), hw->port_info);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\nindex 4e965dc5eb93..cc8922bd61b5 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\n+++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\n@@ -4,6 +4,33 @@\n #include \"ice_common.h\"\n #include \"ice_flex_pipe.h\"\n \n+static void ice_fill_blk_tbls(struct ice_hw *hw);\n+\n+/**\n+ * ice_pkg_val_buf\n+ * @buf: pointer to the ice buffer\n+ *\n+ * This helper function validates a buffer's header.\n+ */\n+static struct ice_buf_hdr *ice_pkg_val_buf(struct ice_buf *buf)\n+{\n+\tstruct ice_buf_hdr *hdr;\n+\tu16 section_count;\n+\tu16 data_end;\n+\n+\thdr = (struct ice_buf_hdr *)buf->buf;\n+\t/* verify data */\n+\tsection_count = le16_to_cpu(hdr->section_count);\n+\tif (section_count < ICE_MIN_S_COUNT || section_count > ICE_MAX_S_COUNT)\n+\t\treturn NULL;\n+\n+\tdata_end = le16_to_cpu(hdr->data_end);\n+\tif (data_end < ICE_MIN_S_DATA_END || data_end > ICE_MAX_S_DATA_END)\n+\t\treturn NULL;\n+\n+\treturn hdr;\n+}\n+\n /**\n  * ice_find_buf_table\n  * @ice_seg: pointer to the ice segment\n@@ -22,6 +49,117 @@ static struct ice_buf_table *ice_find_buf_table(struct ice_seg *ice_seg)\n \t\t(nvms->vers + le32_to_cpu(nvms->table_count));\n }\n \n+/**\n+ * ice_pkg_enum_buf\n+ * @ice_seg: pointer to the ice segment (or NULL on subsequent calls)\n+ * @state: pointer to the enum state\n+ *\n+ * This function will enumerate all the buffers in the ice segment. The first\n+ * call is made with the ice_seg parameter non-NULL; on subsequent calls,\n+ * ice_seg is set to NULL which continues the enumeration. When the function\n+ * returns a NULL pointer, then the end of the buffers has been reached, or an\n+ * unexpected value has been detected (for example an invalid section count or\n+ * an invalid buffer end value).\n+ */\n+static struct ice_buf_hdr *\n+ice_pkg_enum_buf(struct ice_seg *ice_seg, struct ice_pkg_enum *state)\n+{\n+\tif (ice_seg) {\n+\t\tstate->buf_table = ice_find_buf_table(ice_seg);\n+\t\tif (!state->buf_table)\n+\t\t\treturn NULL;\n+\n+\t\tstate->buf_idx = 0;\n+\t\treturn ice_pkg_val_buf(state->buf_table->buf_array);\n+\t}\n+\n+\tif (++state->buf_idx < le32_to_cpu(state->buf_table->buf_count))\n+\t\treturn ice_pkg_val_buf(state->buf_table->buf_array +\n+\t\t\t\t       state->buf_idx);\n+\telse\n+\t\treturn NULL;\n+}\n+\n+/**\n+ * ice_pkg_advance_sect\n+ * @ice_seg: pointer to the ice segment (or NULL on subsequent calls)\n+ * @state: pointer to the enum state\n+ *\n+ * This helper function will advance the section within the ice segment,\n+ * also advancing the buffer if needed.\n+ */\n+static bool\n+ice_pkg_advance_sect(struct ice_seg *ice_seg, struct ice_pkg_enum *state)\n+{\n+\tif (!ice_seg && !state->buf)\n+\t\treturn false;\n+\n+\tif (!ice_seg && state->buf)\n+\t\tif (++state->sect_idx < le16_to_cpu(state->buf->section_count))\n+\t\t\treturn true;\n+\n+\tstate->buf = ice_pkg_enum_buf(ice_seg, state);\n+\tif (!state->buf)\n+\t\treturn false;\n+\n+\t/* start of new buffer, reset section index */\n+\tstate->sect_idx = 0;\n+\treturn true;\n+}\n+\n+/**\n+ * ice_pkg_enum_section\n+ * @ice_seg: pointer to the ice segment (or NULL on subsequent calls)\n+ * @state: pointer to the enum state\n+ * @sect_type: section type to enumerate\n+ *\n+ * This function will enumerate all the sections of a particular type in the\n+ * ice segment. The first call is made with the ice_seg parameter non-NULL;\n+ * on subsequent calls, ice_seg is set to NULL which continues the enumeration.\n+ * When the function returns a NULL pointer, then the end of the matching\n+ * sections has been reached.\n+ */\n+static void *\n+ice_pkg_enum_section(struct ice_seg *ice_seg, struct ice_pkg_enum *state,\n+\t\t     u32 sect_type)\n+{\n+\tu16 offset, size;\n+\n+\tif (ice_seg)\n+\t\tstate->type = sect_type;\n+\n+\tif (!ice_pkg_advance_sect(ice_seg, state))\n+\t\treturn NULL;\n+\n+\t/* scan for next matching section */\n+\twhile (state->buf->section_entry[state->sect_idx].type !=\n+\t       cpu_to_le32(state->type))\n+\t\tif (!ice_pkg_advance_sect(NULL, state))\n+\t\t\treturn NULL;\n+\n+\t/* validate section */\n+\toffset = le16_to_cpu(state->buf->section_entry[state->sect_idx].offset);\n+\tif (offset < ICE_MIN_S_OFF || offset > ICE_MAX_S_OFF)\n+\t\treturn NULL;\n+\n+\tsize = le16_to_cpu(state->buf->section_entry[state->sect_idx].size);\n+\tif (size < ICE_MIN_S_SZ || size > ICE_MAX_S_SZ)\n+\t\treturn NULL;\n+\n+\t/* make sure the section fits in the buffer */\n+\tif (offset + size > ICE_PKG_BUF_SIZE)\n+\t\treturn NULL;\n+\n+\tstate->sect_type =\n+\t\tle32_to_cpu(state->buf->section_entry[state->sect_idx].type);\n+\n+\t/* calc pointer to this section */\n+\tstate->sect = ((u8 *)state->buf) +\n+\t\tle16_to_cpu(state->buf->section_entry[state->sect_idx].offset);\n+\n+\treturn state->sect;\n+}\n+\n /**\n  * ice_acquire_global_cfg_lock\n  * @hw: pointer to the HW structure\n@@ -458,6 +596,21 @@ void ice_free_seg(struct ice_hw *hw)\n \thw->seg = NULL;\n }\n \n+/**\n+ * ice_init_pkg_regs - initialize additional package registers\n+ * @hw: pointer to the hardware structure\n+ */\n+static void ice_init_pkg_regs(struct ice_hw *hw)\n+{\n+#define ICE_SW_BLK_INP_MASK_L 0xFFFFFFFF\n+#define ICE_SW_BLK_INP_MASK_H 0x0000FFFF\n+#define ICE_SW_BLK_IDX\t0\n+\n+\t/* setup Switch block input mask, which is 48-bits in two parts */\n+\twr32(hw, GL_PREEXT_L2_PMASK0(ICE_SW_BLK_IDX), ICE_SW_BLK_INP_MASK_L);\n+\twr32(hw, GL_PREEXT_L2_PMASK1(ICE_SW_BLK_IDX), ICE_SW_BLK_INP_MASK_H);\n+}\n+\n /**\n  * ice_chk_pkg_version - check package version for compatibility with driver\n  * @pkg_ver: pointer to a version structure to check\n@@ -554,9 +707,18 @@ enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len)\n \t\t\tstatus = ice_chk_pkg_version(&hw->active_pkg_ver);\n \t}\n \n-\tif (status)\n+\tif (!status) {\n+\t\thw->seg = seg;\n+\t\t/* on successful package download update other required\n+\t\t * registers to support the package and fill HW tables\n+\t\t * with package content.\n+\t\t */\n+\t\tice_init_pkg_regs(hw);\n+\t\tice_fill_blk_tbls(hw);\n+\t} else {\n \t\tice_debug(hw, ICE_DBG_INIT, \"package load failed, %d\\n\",\n \t\t\t  status);\n+\t}\n \n \treturn status;\n }\n@@ -606,3 +768,784 @@ enum ice_status ice_copy_and_init_pkg(struct ice_hw *hw, const u8 *buf, u32 len)\n \n \treturn status;\n }\n+\n+/* PTG Management */\n+\n+/**\n+ * ice_ptg_find_ptype - Search for packet type group using packet type (ptype)\n+ * @hw: pointer to the hardware structure\n+ * @blk: HW block\n+ * @ptype: the ptype to search for\n+ * @ptg: pointer to variable that receives the PTG\n+ *\n+ * This function will search the PTGs for a particular ptype, returning the\n+ * PTG ID that contains it through the PTG parameter, with the value of\n+ * ICE_DEFAULT_PTG (0) meaning it is part the default PTG.\n+ */\n+static enum ice_status\n+ice_ptg_find_ptype(struct ice_hw *hw, enum ice_block blk, u16 ptype, u8 *ptg)\n+{\n+\tif (ptype >= ICE_XLT1_CNT || !ptg)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\t*ptg = hw->blk[blk].xlt1.ptypes[ptype].ptg;\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_ptg_alloc_val - Allocates a new packet type group ID by value\n+ * @hw: pointer to the hardware structure\n+ * @blk: HW block\n+ * @ptg: the PTG to allocate\n+ *\n+ * This function allocates a given packet type group ID specified by the PTG\n+ * parameter.\n+ */\n+static void ice_ptg_alloc_val(struct ice_hw *hw, enum ice_block blk, u8 ptg)\n+{\n+\thw->blk[blk].xlt1.ptg_tbl[ptg].in_use = true;\n+}\n+\n+/**\n+ * ice_ptg_remove_ptype - Removes ptype from a particular packet type group\n+ * @hw: pointer to the hardware structure\n+ * @blk: HW block\n+ * @ptype: the ptype to remove\n+ * @ptg: the PTG to remove the ptype from\n+ *\n+ * This function will remove the ptype from the specific PTG, and move it to\n+ * the default PTG (ICE_DEFAULT_PTG).\n+ */\n+static enum ice_status\n+ice_ptg_remove_ptype(struct ice_hw *hw, enum ice_block blk, u16 ptype, u8 ptg)\n+{\n+\tstruct ice_ptg_ptype **ch;\n+\tstruct ice_ptg_ptype *p;\n+\n+\tif (ptype > ICE_XLT1_CNT - 1)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tif (!hw->blk[blk].xlt1.ptg_tbl[ptg].in_use)\n+\t\treturn ICE_ERR_DOES_NOT_EXIST;\n+\n+\t/* Should not happen if .in_use is set, bad config */\n+\tif (!hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype)\n+\t\treturn ICE_ERR_CFG;\n+\n+\t/* find the ptype within this PTG, and bypass the link over it */\n+\tp = hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype;\n+\tch = &hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype;\n+\twhile (p) {\n+\t\tif (ptype == (p - hw->blk[blk].xlt1.ptypes)) {\n+\t\t\t*ch = p->next_ptype;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tch = &p->next_ptype;\n+\t\tp = p->next_ptype;\n+\t}\n+\n+\thw->blk[blk].xlt1.ptypes[ptype].ptg = ICE_DEFAULT_PTG;\n+\thw->blk[blk].xlt1.ptypes[ptype].next_ptype = NULL;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_ptg_add_mv_ptype - Adds/moves ptype to a particular packet type group\n+ * @hw: pointer to the hardware structure\n+ * @blk: HW block\n+ * @ptype: the ptype to add or move\n+ * @ptg: the PTG to add or move the ptype to\n+ *\n+ * This function will either add or move a ptype to a particular PTG depending\n+ * on if the ptype is already part of another group. Note that using a\n+ * a destination PTG ID of ICE_DEFAULT_PTG (0) will move the ptype to the\n+ * default PTG.\n+ */\n+static enum ice_status\n+ice_ptg_add_mv_ptype(struct ice_hw *hw, enum ice_block blk, u16 ptype, u8 ptg)\n+{\n+\tenum ice_status status;\n+\tu8 original_ptg;\n+\n+\tif (ptype > ICE_XLT1_CNT - 1)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tif (!hw->blk[blk].xlt1.ptg_tbl[ptg].in_use && ptg != ICE_DEFAULT_PTG)\n+\t\treturn ICE_ERR_DOES_NOT_EXIST;\n+\n+\tstatus = ice_ptg_find_ptype(hw, blk, ptype, &original_ptg);\n+\tif (status)\n+\t\treturn status;\n+\n+\t/* Is ptype already in the correct PTG? */\n+\tif (original_ptg == ptg)\n+\t\treturn 0;\n+\n+\t/* Remove from original PTG and move back to the default PTG */\n+\tif (original_ptg != ICE_DEFAULT_PTG)\n+\t\tice_ptg_remove_ptype(hw, blk, ptype, original_ptg);\n+\n+\t/* Moving to default PTG? Then we're done with this request */\n+\tif (ptg == ICE_DEFAULT_PTG)\n+\t\treturn 0;\n+\n+\t/* Add ptype to PTG at beginning of list */\n+\thw->blk[blk].xlt1.ptypes[ptype].next_ptype =\n+\t\thw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype;\n+\thw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype =\n+\t\t&hw->blk[blk].xlt1.ptypes[ptype];\n+\n+\thw->blk[blk].xlt1.ptypes[ptype].ptg = ptg;\n+\thw->blk[blk].xlt1.t[ptype] = ptg;\n+\n+\treturn 0;\n+}\n+\n+/* Block / table size info */\n+struct ice_blk_size_details {\n+\tu16 xlt1;\t\t\t/* # XLT1 entries */\n+\tu16 xlt2;\t\t\t/* # XLT2 entries */\n+\tu16 prof_tcam;\t\t\t/* # profile ID TCAM entries */\n+\tu16 prof_id;\t\t\t/* # profile IDs */\n+\tu8 prof_cdid_bits;\t\t/* # CDID one-hot bits used in key */\n+\tu16 prof_redir;\t\t\t/* # profile redirection entries */\n+\tu16 es;\t\t\t\t/* # extraction sequence entries */\n+\tu16 fvw;\t\t\t/* # field vector words */\n+\tu8 overwrite;\t\t\t/* overwrite existing entries allowed */\n+\tu8 reverse;\t\t\t/* reverse FV order */\n+};\n+\n+static const struct ice_blk_size_details blk_sizes[ICE_BLK_COUNT] = {\n+\t/**\n+\t * Table Definitions\n+\t * XLT1 - Number of entries in XLT1 table\n+\t * XLT2 - Number of entries in XLT2 table\n+\t * TCAM - Number of entries Profile ID TCAM table\n+\t * CDID - Control Domain ID of the hardware block\n+\t * PRED - Number of entries in the Profile Redirection Table\n+\t * FV   - Number of entries in the Field Vector\n+\t * FVW  - Width (in WORDs) of the Field Vector\n+\t * OVR  - Overwrite existing table entries\n+\t * REV  - Reverse FV\n+\t */\n+\t/*          XLT1        , XLT2        ,TCAM, PID,CDID,PRED,   FV, FVW */\n+\t/*          Overwrite   , Reverse FV */\n+\t/* SW  */ { ICE_XLT1_CNT, ICE_XLT2_CNT, 512, 256,   0,  256, 256,  48,\n+\t\t    false, false },\n+\t/* ACL */ { ICE_XLT1_CNT, ICE_XLT2_CNT, 512, 128,   0,  128, 128,  32,\n+\t\t    false, false },\n+\t/* FD  */ { ICE_XLT1_CNT, ICE_XLT2_CNT, 512, 128,   0,  128, 128,  24,\n+\t\t    false, true  },\n+\t/* RSS */ { ICE_XLT1_CNT, ICE_XLT2_CNT, 512, 128,   0,  128, 128,  24,\n+\t\t    true,  true  },\n+\t/* PE  */ { ICE_XLT1_CNT, ICE_XLT2_CNT,  64,  32,   0,   32,  32,  24,\n+\t\t    false, false },\n+};\n+\n+enum ice_sid_all {\n+\tICE_SID_XLT1_OFF = 0,\n+\tICE_SID_XLT2_OFF,\n+\tICE_SID_PR_OFF,\n+\tICE_SID_PR_REDIR_OFF,\n+\tICE_SID_ES_OFF,\n+\tICE_SID_OFF_COUNT,\n+};\n+\n+/* VSIG Management */\n+\n+/**\n+ * ice_vsig_find_vsi - find a VSIG that contains a specified VSI\n+ * @hw: pointer to the hardware structure\n+ * @blk: HW block\n+ * @vsi: VSI of interest\n+ * @vsig: pointer to receive the VSI group\n+ *\n+ * This function will lookup the VSI entry in the XLT2 list and return\n+ * the VSI group its associated with.\n+ */\n+static enum ice_status\n+ice_vsig_find_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 *vsig)\n+{\n+\tif (!vsig || vsi >= ICE_MAX_VSI)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\t/* As long as there's a default or valid VSIG associated with the input\n+\t * VSI, the functions returns a success. Any handling of VSIG will be\n+\t * done by the following add, update or remove functions.\n+\t */\n+\t*vsig = hw->blk[blk].xlt2.vsis[vsi].vsig;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_vsig_alloc_val - allocate a new VSIG by value\n+ * @hw: pointer to the hardware structure\n+ * @blk: HW block\n+ * @vsig: the VSIG to allocate\n+ *\n+ * This function will allocate a given VSIG specified by the VSIG parameter.\n+ */\n+static u16 ice_vsig_alloc_val(struct ice_hw *hw, enum ice_block blk, u16 vsig)\n+{\n+\tu16 idx = vsig & ICE_VSIG_IDX_M;\n+\n+\tif (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use) {\n+\t\tINIT_LIST_HEAD(&hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst);\n+\t\thw->blk[blk].xlt2.vsig_tbl[idx].in_use = true;\n+\t}\n+\n+\treturn ICE_VSIG_VALUE(idx, hw->pf_id);\n+}\n+\n+/**\n+ * ice_vsig_remove_vsi - remove VSI from VSIG\n+ * @hw: pointer to the hardware structure\n+ * @blk: HW block\n+ * @vsi: VSI to remove\n+ * @vsig: VSI group to remove from\n+ *\n+ * The function will remove the input VSI from its VSI group and move it\n+ * to the DEFAULT_VSIG.\n+ */\n+static enum ice_status\n+ice_vsig_remove_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig)\n+{\n+\tstruct ice_vsig_vsi **vsi_head, *vsi_cur, *vsi_tgt;\n+\tu16 idx;\n+\n+\tidx = vsig & ICE_VSIG_IDX_M;\n+\n+\tif (vsi >= ICE_MAX_VSI || idx >= ICE_MAX_VSIGS)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tif (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use)\n+\t\treturn ICE_ERR_DOES_NOT_EXIST;\n+\n+\t/* entry already in default VSIG, don't have to remove */\n+\tif (idx == ICE_DEFAULT_VSIG)\n+\t\treturn 0;\n+\n+\tvsi_head = &hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi;\n+\tif (!(*vsi_head))\n+\t\treturn ICE_ERR_CFG;\n+\n+\tvsi_tgt = &hw->blk[blk].xlt2.vsis[vsi];\n+\tvsi_cur = (*vsi_head);\n+\n+\t/* iterate the VSI list, skip over the entry to be removed */\n+\twhile (vsi_cur) {\n+\t\tif (vsi_tgt == vsi_cur) {\n+\t\t\t(*vsi_head) = vsi_cur->next_vsi;\n+\t\t\tbreak;\n+\t\t}\n+\t\tvsi_head = &vsi_cur->next_vsi;\n+\t\tvsi_cur = vsi_cur->next_vsi;\n+\t}\n+\n+\t/* verify if VSI was removed from group list */\n+\tif (!vsi_cur)\n+\t\treturn ICE_ERR_DOES_NOT_EXIST;\n+\n+\tvsi_cur->vsig = ICE_DEFAULT_VSIG;\n+\tvsi_cur->changed = 1;\n+\tvsi_cur->next_vsi = NULL;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_vsig_add_mv_vsi - add or move a VSI to a VSI group\n+ * @hw: pointer to the hardware structure\n+ * @blk: HW block\n+ * @vsi: VSI to move\n+ * @vsig: destination VSI group\n+ *\n+ * This function will move or add the input VSI to the target VSIG.\n+ * The function will find the original VSIG the VSI belongs to and\n+ * move the entry to the DEFAULT_VSIG, update the original VSIG and\n+ * then move entry to the new VSIG.\n+ */\n+static enum ice_status\n+ice_vsig_add_mv_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig)\n+{\n+\tstruct ice_vsig_vsi *tmp;\n+\tenum ice_status status;\n+\tu16 orig_vsig, idx;\n+\n+\tidx = vsig & ICE_VSIG_IDX_M;\n+\n+\tif (vsi >= ICE_MAX_VSI || idx >= ICE_MAX_VSIGS)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\t/* if VSIG not in use and VSIG is not default type this VSIG\n+\t * doesn't exist.\n+\t */\n+\tif (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use &&\n+\t    vsig != ICE_DEFAULT_VSIG)\n+\t\treturn ICE_ERR_DOES_NOT_EXIST;\n+\n+\tstatus = ice_vsig_find_vsi(hw, blk, vsi, &orig_vsig);\n+\tif (status)\n+\t\treturn status;\n+\n+\t/* no update required if vsigs match */\n+\tif (orig_vsig == vsig)\n+\t\treturn 0;\n+\n+\tif (orig_vsig != ICE_DEFAULT_VSIG) {\n+\t\t/* remove entry from orig_vsig and add to default VSIG */\n+\t\tstatus = ice_vsig_remove_vsi(hw, blk, vsi, orig_vsig);\n+\t\tif (status)\n+\t\t\treturn status;\n+\t}\n+\n+\tif (idx == ICE_DEFAULT_VSIG)\n+\t\treturn 0;\n+\n+\t/* Create VSI entry and add VSIG and prop_mask values */\n+\thw->blk[blk].xlt2.vsis[vsi].vsig = vsig;\n+\thw->blk[blk].xlt2.vsis[vsi].changed = 1;\n+\n+\t/* Add new entry to the head of the VSIG list */\n+\ttmp = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi;\n+\thw->blk[blk].xlt2.vsig_tbl[idx].first_vsi =\n+\t\t&hw->blk[blk].xlt2.vsis[vsi];\n+\thw->blk[blk].xlt2.vsis[vsi].next_vsi = tmp;\n+\thw->blk[blk].xlt2.t[vsi] = vsig;\n+\n+\treturn 0;\n+}\n+\n+/* Block / table section IDs */\n+static const u32 ice_blk_sids[ICE_BLK_COUNT][ICE_SID_OFF_COUNT] = {\n+\t/* SWITCH */\n+\t{\tICE_SID_XLT1_SW,\n+\t\tICE_SID_XLT2_SW,\n+\t\tICE_SID_PROFID_TCAM_SW,\n+\t\tICE_SID_PROFID_REDIR_SW,\n+\t\tICE_SID_FLD_VEC_SW\n+\t},\n+\n+\t/* ACL */\n+\t{\tICE_SID_XLT1_ACL,\n+\t\tICE_SID_XLT2_ACL,\n+\t\tICE_SID_PROFID_TCAM_ACL,\n+\t\tICE_SID_PROFID_REDIR_ACL,\n+\t\tICE_SID_FLD_VEC_ACL\n+\t},\n+\n+\t/* FD */\n+\t{\tICE_SID_XLT1_FD,\n+\t\tICE_SID_XLT2_FD,\n+\t\tICE_SID_PROFID_TCAM_FD,\n+\t\tICE_SID_PROFID_REDIR_FD,\n+\t\tICE_SID_FLD_VEC_FD\n+\t},\n+\n+\t/* RSS */\n+\t{\tICE_SID_XLT1_RSS,\n+\t\tICE_SID_XLT2_RSS,\n+\t\tICE_SID_PROFID_TCAM_RSS,\n+\t\tICE_SID_PROFID_REDIR_RSS,\n+\t\tICE_SID_FLD_VEC_RSS\n+\t},\n+\n+\t/* PE */\n+\t{\tICE_SID_XLT1_PE,\n+\t\tICE_SID_XLT2_PE,\n+\t\tICE_SID_PROFID_TCAM_PE,\n+\t\tICE_SID_PROFID_REDIR_PE,\n+\t\tICE_SID_FLD_VEC_PE\n+\t}\n+};\n+\n+/**\n+ * ice_init_sw_xlt1_db - init software XLT1 database from HW tables\n+ * @hw: pointer to the hardware structure\n+ * @blk: the HW block to initialize\n+ */\n+static void ice_init_sw_xlt1_db(struct ice_hw *hw, enum ice_block blk)\n+{\n+\tu16 pt;\n+\n+\tfor (pt = 0; pt < hw->blk[blk].xlt1.count; pt++) {\n+\t\tu8 ptg;\n+\n+\t\tptg = hw->blk[blk].xlt1.t[pt];\n+\t\tif (ptg != ICE_DEFAULT_PTG) {\n+\t\t\tice_ptg_alloc_val(hw, blk, ptg);\n+\t\t\tice_ptg_add_mv_ptype(hw, blk, pt, ptg);\n+\t\t}\n+\t}\n+}\n+\n+/**\n+ * ice_init_sw_xlt2_db - init software XLT2 database from HW tables\n+ * @hw: pointer to the hardware structure\n+ * @blk: the HW block to initialize\n+ */\n+static void ice_init_sw_xlt2_db(struct ice_hw *hw, enum ice_block blk)\n+{\n+\tu16 vsi;\n+\n+\tfor (vsi = 0; vsi < hw->blk[blk].xlt2.count; vsi++) {\n+\t\tu16 vsig;\n+\n+\t\tvsig = hw->blk[blk].xlt2.t[vsi];\n+\t\tif (vsig) {\n+\t\t\tice_vsig_alloc_val(hw, blk, vsig);\n+\t\t\tice_vsig_add_mv_vsi(hw, blk, vsi, vsig);\n+\t\t\t/* no changes at this time, since this has been\n+\t\t\t * initialized from the original package\n+\t\t\t */\n+\t\t\thw->blk[blk].xlt2.vsis[vsi].changed = 0;\n+\t\t}\n+\t}\n+}\n+\n+/**\n+ * ice_init_sw_db - init software database from HW tables\n+ * @hw: pointer to the hardware structure\n+ */\n+static void ice_init_sw_db(struct ice_hw *hw)\n+{\n+\tu16 i;\n+\n+\tfor (i = 0; i < ICE_BLK_COUNT; i++) {\n+\t\tice_init_sw_xlt1_db(hw, (enum ice_block)i);\n+\t\tice_init_sw_xlt2_db(hw, (enum ice_block)i);\n+\t}\n+}\n+\n+/**\n+ * ice_fill_tbl - Reads content of a single table type into database\n+ * @hw: pointer to the hardware structure\n+ * @block_id: Block ID of the table to copy\n+ * @sid: Section ID of the table to copy\n+ *\n+ * Will attempt to read the entire content of a given table of a single block\n+ * into the driver database. We assume that the buffer will always\n+ * be as large or larger than the data contained in the package. If\n+ * this condition is not met, there is most likely an error in the package\n+ * contents.\n+ */\n+static void ice_fill_tbl(struct ice_hw *hw, enum ice_block block_id, u32 sid)\n+{\n+\tu32 dst_len, sect_len, offset = 0;\n+\tstruct ice_prof_redir_section *pr;\n+\tstruct ice_prof_id_section *pid;\n+\tstruct ice_xlt1_section *xlt1;\n+\tstruct ice_xlt2_section *xlt2;\n+\tstruct ice_sw_fv_section *es;\n+\tstruct ice_pkg_enum state;\n+\tu8 *src, *dst;\n+\tvoid *sect;\n+\n+\t/* if the HW segment pointer is null then the first iteration of\n+\t * ice_pkg_enum_section() will fail. In this case the HW tables will\n+\t * not be filled and return success.\n+\t */\n+\tif (!hw->seg) {\n+\t\tice_debug(hw, ICE_DBG_PKG, \"hw->seg is NULL, tables are not filled\\n\");\n+\t\treturn;\n+\t}\n+\n+\tmemset(&state, 0, sizeof(state));\n+\n+\tsect = ice_pkg_enum_section(hw->seg, &state, sid);\n+\n+\twhile (sect) {\n+\t\tswitch (sid) {\n+\t\tcase ICE_SID_XLT1_SW:\n+\t\tcase ICE_SID_XLT1_FD:\n+\t\tcase ICE_SID_XLT1_RSS:\n+\t\tcase ICE_SID_XLT1_ACL:\n+\t\tcase ICE_SID_XLT1_PE:\n+\t\t\txlt1 = (struct ice_xlt1_section *)sect;\n+\t\t\tsrc = xlt1->value;\n+\t\t\tsect_len = le16_to_cpu(xlt1->count) *\n+\t\t\t\tsizeof(*hw->blk[block_id].xlt1.t);\n+\t\t\tdst = hw->blk[block_id].xlt1.t;\n+\t\t\tdst_len = hw->blk[block_id].xlt1.count *\n+\t\t\t\tsizeof(*hw->blk[block_id].xlt1.t);\n+\t\t\tbreak;\n+\t\tcase ICE_SID_XLT2_SW:\n+\t\tcase ICE_SID_XLT2_FD:\n+\t\tcase ICE_SID_XLT2_RSS:\n+\t\tcase ICE_SID_XLT2_ACL:\n+\t\tcase ICE_SID_XLT2_PE:\n+\t\t\txlt2 = (struct ice_xlt2_section *)sect;\n+\t\t\tsrc = (__force u8 *)xlt2->value;\n+\t\t\tsect_len = le16_to_cpu(xlt2->count) *\n+\t\t\t\tsizeof(*hw->blk[block_id].xlt2.t);\n+\t\t\tdst = (u8 *)hw->blk[block_id].xlt2.t;\n+\t\t\tdst_len = hw->blk[block_id].xlt2.count *\n+\t\t\t\tsizeof(*hw->blk[block_id].xlt2.t);\n+\t\t\tbreak;\n+\t\tcase ICE_SID_PROFID_TCAM_SW:\n+\t\tcase ICE_SID_PROFID_TCAM_FD:\n+\t\tcase ICE_SID_PROFID_TCAM_RSS:\n+\t\tcase ICE_SID_PROFID_TCAM_ACL:\n+\t\tcase ICE_SID_PROFID_TCAM_PE:\n+\t\t\tpid = (struct ice_prof_id_section *)sect;\n+\t\t\tsrc = (u8 *)pid->entry;\n+\t\t\tsect_len = le16_to_cpu(pid->count) *\n+\t\t\t\tsizeof(*hw->blk[block_id].prof.t);\n+\t\t\tdst = (u8 *)hw->blk[block_id].prof.t;\n+\t\t\tdst_len = hw->blk[block_id].prof.count *\n+\t\t\t\tsizeof(*hw->blk[block_id].prof.t);\n+\t\t\tbreak;\n+\t\tcase ICE_SID_PROFID_REDIR_SW:\n+\t\tcase ICE_SID_PROFID_REDIR_FD:\n+\t\tcase ICE_SID_PROFID_REDIR_RSS:\n+\t\tcase ICE_SID_PROFID_REDIR_ACL:\n+\t\tcase ICE_SID_PROFID_REDIR_PE:\n+\t\t\tpr = (struct ice_prof_redir_section *)sect;\n+\t\t\tsrc = pr->redir_value;\n+\t\t\tsect_len = le16_to_cpu(pr->count) *\n+\t\t\t\tsizeof(*hw->blk[block_id].prof_redir.t);\n+\t\t\tdst = hw->blk[block_id].prof_redir.t;\n+\t\t\tdst_len = hw->blk[block_id].prof_redir.count *\n+\t\t\t\tsizeof(*hw->blk[block_id].prof_redir.t);\n+\t\t\tbreak;\n+\t\tcase ICE_SID_FLD_VEC_SW:\n+\t\tcase ICE_SID_FLD_VEC_FD:\n+\t\tcase ICE_SID_FLD_VEC_RSS:\n+\t\tcase ICE_SID_FLD_VEC_ACL:\n+\t\tcase ICE_SID_FLD_VEC_PE:\n+\t\t\tes = (struct ice_sw_fv_section *)sect;\n+\t\t\tsrc = (u8 *)es->fv;\n+\t\t\tsect_len = (u32)(le16_to_cpu(es->count) *\n+\t\t\t\t\t hw->blk[block_id].es.fvw) *\n+\t\t\t\tsizeof(*hw->blk[block_id].es.t);\n+\t\t\tdst = (u8 *)hw->blk[block_id].es.t;\n+\t\t\tdst_len = (u32)(hw->blk[block_id].es.count *\n+\t\t\t\t\thw->blk[block_id].es.fvw) *\n+\t\t\t\tsizeof(*hw->blk[block_id].es.t);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn;\n+\t\t}\n+\n+\t\t/* if the section offset exceeds destination length, terminate\n+\t\t * table fill.\n+\t\t */\n+\t\tif (offset > dst_len)\n+\t\t\treturn;\n+\n+\t\t/* if the sum of section size and offset exceed destination size\n+\t\t * then we are out of bounds of the HW table size for that PF.\n+\t\t * Changing section length to fill the remaining table space\n+\t\t * of that PF.\n+\t\t */\n+\t\tif ((offset + sect_len) > dst_len)\n+\t\t\tsect_len = dst_len - offset;\n+\n+\t\tmemcpy(dst + offset, src, sect_len);\n+\t\toffset += sect_len;\n+\t\tsect = ice_pkg_enum_section(NULL, &state, sid);\n+\t}\n+}\n+\n+/**\n+ * ice_fill_blk_tbls - Read package context for tables\n+ * @hw: pointer to the hardware structure\n+ *\n+ * Reads the current package contents and populates the driver\n+ * database with the data iteratively for all advanced feature\n+ * blocks. Assume that the HW tables have been allocated.\n+ */\n+static void ice_fill_blk_tbls(struct ice_hw *hw)\n+{\n+\tu8 i;\n+\n+\tfor (i = 0; i < ICE_BLK_COUNT; i++) {\n+\t\tenum ice_block blk_id = (enum ice_block)i;\n+\n+\t\tice_fill_tbl(hw, blk_id, hw->blk[blk_id].xlt1.sid);\n+\t\tice_fill_tbl(hw, blk_id, hw->blk[blk_id].xlt2.sid);\n+\t\tice_fill_tbl(hw, blk_id, hw->blk[blk_id].prof.sid);\n+\t\tice_fill_tbl(hw, blk_id, hw->blk[blk_id].prof_redir.sid);\n+\t\tice_fill_tbl(hw, blk_id, hw->blk[blk_id].es.sid);\n+\t}\n+\n+\tice_init_sw_db(hw);\n+}\n+\n+/**\n+ * ice_free_hw_tbls - free hardware table memory\n+ * @hw: pointer to the hardware structure\n+ */\n+void ice_free_hw_tbls(struct ice_hw *hw)\n+{\n+\tu8 i;\n+\n+\tfor (i = 0; i < ICE_BLK_COUNT; i++) {\n+\t\thw->blk[i].is_list_init = false;\n+\n+\t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].xlt1.ptypes);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].xlt1.ptg_tbl);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].xlt1.t);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].xlt2.t);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].xlt2.vsig_tbl);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].xlt2.vsis);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].prof.t);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].prof_redir.t);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.t);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.ref_count);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.written);\n+\t}\n+\n+\tmemset(hw->blk, 0, sizeof(hw->blk));\n+}\n+\n+/**\n+ * ice_clear_hw_tbls - clear HW tables and flow profiles\n+ * @hw: pointer to the hardware structure\n+ */\n+void ice_clear_hw_tbls(struct ice_hw *hw)\n+{\n+\tu8 i;\n+\n+\tfor (i = 0; i < ICE_BLK_COUNT; i++) {\n+\t\tstruct ice_prof_redir *prof_redir = &hw->blk[i].prof_redir;\n+\t\tstruct ice_prof_tcam *prof = &hw->blk[i].prof;\n+\t\tstruct ice_xlt1 *xlt1 = &hw->blk[i].xlt1;\n+\t\tstruct ice_xlt2 *xlt2 = &hw->blk[i].xlt2;\n+\t\tstruct ice_es *es = &hw->blk[i].es;\n+\n+\t\tmemset(xlt1->ptypes, 0, xlt1->count * sizeof(*xlt1->ptypes));\n+\t\tmemset(xlt1->ptg_tbl, 0,\n+\t\t       ICE_MAX_PTGS * sizeof(*xlt1->ptg_tbl));\n+\t\tmemset(xlt1->t, 0, xlt1->count * sizeof(*xlt1->t));\n+\n+\t\tmemset(xlt2->vsis, 0, xlt2->count * sizeof(*xlt2->vsis));\n+\t\tmemset(xlt2->vsig_tbl, 0,\n+\t\t       xlt2->count * sizeof(*xlt2->vsig_tbl));\n+\t\tmemset(xlt2->t, 0, xlt2->count * sizeof(*xlt2->t));\n+\n+\t\tmemset(prof->t, 0, prof->count * sizeof(*prof->t));\n+\t\tmemset(prof_redir->t, 0,\n+\t\t       prof_redir->count * sizeof(*prof_redir->t));\n+\n+\t\tmemset(es->t, 0, es->count * sizeof(*es->t));\n+\t\tmemset(es->ref_count, 0, es->count * sizeof(*es->ref_count));\n+\t\tmemset(es->written, 0, es->count * sizeof(*es->written));\n+\t}\n+}\n+\n+/**\n+ * ice_init_hw_tbls - init hardware table memory\n+ * @hw: pointer to the hardware structure\n+ */\n+enum ice_status ice_init_hw_tbls(struct ice_hw *hw)\n+{\n+\tu8 i;\n+\n+\tfor (i = 0; i < ICE_BLK_COUNT; i++) {\n+\t\tstruct ice_prof_redir *prof_redir = &hw->blk[i].prof_redir;\n+\t\tstruct ice_prof_tcam *prof = &hw->blk[i].prof;\n+\t\tstruct ice_xlt1 *xlt1 = &hw->blk[i].xlt1;\n+\t\tstruct ice_xlt2 *xlt2 = &hw->blk[i].xlt2;\n+\t\tstruct ice_es *es = &hw->blk[i].es;\n+\t\tu16 j;\n+\n+\t\tif (hw->blk[i].is_list_init)\n+\t\t\tcontinue;\n+\n+\t\thw->blk[i].is_list_init = true;\n+\n+\t\thw->blk[i].overwrite = blk_sizes[i].overwrite;\n+\t\tes->reverse = blk_sizes[i].reverse;\n+\n+\t\txlt1->sid = ice_blk_sids[i][ICE_SID_XLT1_OFF];\n+\t\txlt1->count = blk_sizes[i].xlt1;\n+\n+\t\txlt1->ptypes = devm_kcalloc(ice_hw_to_dev(hw), xlt1->count,\n+\t\t\t\t\t    sizeof(*xlt1->ptypes), GFP_KERNEL);\n+\n+\t\tif (!xlt1->ptypes)\n+\t\t\tgoto err;\n+\n+\t\txlt1->ptg_tbl = devm_kcalloc(ice_hw_to_dev(hw), ICE_MAX_PTGS,\n+\t\t\t\t\t     sizeof(*xlt1->ptg_tbl),\n+\t\t\t\t\t     GFP_KERNEL);\n+\n+\t\tif (!xlt1->ptg_tbl)\n+\t\t\tgoto err;\n+\n+\t\txlt1->t = devm_kcalloc(ice_hw_to_dev(hw), xlt1->count,\n+\t\t\t\t       sizeof(*xlt1->t), GFP_KERNEL);\n+\t\tif (!xlt1->t)\n+\t\t\tgoto err;\n+\n+\t\txlt2->sid = ice_blk_sids[i][ICE_SID_XLT2_OFF];\n+\t\txlt2->count = blk_sizes[i].xlt2;\n+\n+\t\txlt2->vsis = devm_kcalloc(ice_hw_to_dev(hw), xlt2->count,\n+\t\t\t\t\t  sizeof(*xlt2->vsis), GFP_KERNEL);\n+\n+\t\tif (!xlt2->vsis)\n+\t\t\tgoto err;\n+\n+\t\txlt2->vsig_tbl = devm_kcalloc(ice_hw_to_dev(hw), xlt2->count,\n+\t\t\t\t\t      sizeof(*xlt2->vsig_tbl),\n+\t\t\t\t\t      GFP_KERNEL);\n+\t\tif (!xlt2->vsig_tbl)\n+\t\t\tgoto err;\n+\n+\t\tfor (j = 0; j < xlt2->count; j++)\n+\t\t\tINIT_LIST_HEAD(&xlt2->vsig_tbl[j].prop_lst);\n+\n+\t\txlt2->t = devm_kcalloc(ice_hw_to_dev(hw), xlt2->count,\n+\t\t\t\t       sizeof(*xlt2->t), GFP_KERNEL);\n+\t\tif (!xlt2->t)\n+\t\t\tgoto err;\n+\n+\t\tprof->sid = ice_blk_sids[i][ICE_SID_PR_OFF];\n+\t\tprof->count = blk_sizes[i].prof_tcam;\n+\t\tprof->max_prof_id = blk_sizes[i].prof_id;\n+\t\tprof->cdid_bits = blk_sizes[i].prof_cdid_bits;\n+\t\tprof->t = devm_kcalloc(ice_hw_to_dev(hw), prof->count,\n+\t\t\t\t       sizeof(*prof->t), GFP_KERNEL);\n+\n+\t\tif (!prof->t)\n+\t\t\tgoto err;\n+\n+\t\tprof_redir->sid = ice_blk_sids[i][ICE_SID_PR_REDIR_OFF];\n+\t\tprof_redir->count = blk_sizes[i].prof_redir;\n+\t\tprof_redir->t = devm_kcalloc(ice_hw_to_dev(hw),\n+\t\t\t\t\t     prof_redir->count,\n+\t\t\t\t\t     sizeof(*prof_redir->t),\n+\t\t\t\t\t     GFP_KERNEL);\n+\n+\t\tif (!prof_redir->t)\n+\t\t\tgoto err;\n+\n+\t\tes->sid = ice_blk_sids[i][ICE_SID_ES_OFF];\n+\t\tes->count = blk_sizes[i].es;\n+\t\tes->fvw = blk_sizes[i].fvw;\n+\t\tes->t = devm_kcalloc(ice_hw_to_dev(hw),\n+\t\t\t\t     (u32)(es->count * es->fvw),\n+\t\t\t\t     sizeof(*es->t), GFP_KERNEL);\n+\t\tif (!es->t)\n+\t\t\tgoto err;\n+\n+\t\tes->ref_count = devm_kcalloc(ice_hw_to_dev(hw), es->count,\n+\t\t\t\t\t     sizeof(*es->ref_count),\n+\t\t\t\t\t     GFP_KERNEL);\n+\n+\t\tes->written = devm_kcalloc(ice_hw_to_dev(hw), es->count,\n+\t\t\t\t\t   sizeof(*es->written), GFP_KERNEL);\n+\t\tif (!es->ref_count)\n+\t\t\tgoto err;\n+\t}\n+\treturn 0;\n+\n+err:\n+\tice_free_hw_tbls(hw);\n+\treturn ICE_ERR_NO_MEMORY;\n+}\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h\nindex 3843c462bc42..9edf1e7589c7 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h\n+++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h\n@@ -21,5 +21,8 @@\n enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buff, u32 len);\n enum ice_status\n ice_copy_and_init_pkg(struct ice_hw *hw, const u8 *buf, u32 len);\n+enum ice_status ice_init_hw_tbls(struct ice_hw *hw);\n void ice_free_seg(struct ice_hw *hw);\n+void ice_clear_hw_tbls(struct ice_hw *hw);\n+void ice_free_hw_tbls(struct ice_hw *hw);\n #endif /* _ICE_FLEX_PIPE_H_ */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flex_type.h b/drivers/net/ethernet/intel/ice/ice_flex_type.h\nindex b7fb90594faf..5d5a7eaffa30 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flex_type.h\n+++ b/drivers/net/ethernet/intel/ice/ice_flex_type.h\n@@ -294,6 +294,7 @@ struct ice_vsig_vsi {\n };\n \n #define ICE_XLT1_CNT\t1024\n+#define ICE_MAX_PTGS\t256\n \n /* XLT1 Table */\n struct ice_xlt1 {\n@@ -304,6 +305,7 @@ struct ice_xlt1 {\n \tu16 count;\n };\n \n+#define ICE_XLT2_CNT\t768\n #define ICE_MAX_VSIGS\t768\n \n /* VSIG bit layout:\n",
    "prefixes": [
        "S29",
        "v3",
        "4/6"
    ]
}