Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1225078/?format=api
{ "id": 1225078, "url": "http://patchwork.ozlabs.org/api/patches/1225078/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20200117153919.50321-2-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": "<20200117153919.50321-2-anthony.l.nguyen@intel.com>", "list_archive_url": null, "date": "2020-01-17T15:39:13", "name": "[S36,2/8] ice: Allocate flow profile", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "bc223b8e50ed13c4dbfc0301279c5297cd0af670", "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/20200117153919.50321-2-anthony.l.nguyen@intel.com/mbox/", "series": [ { "id": 153932, "url": "http://patchwork.ozlabs.org/api/series/153932/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=153932", "date": "2020-01-17T15:39:19", "name": "[S36,1/8] ice: Enable writing hardware filtering tables", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/153932/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1225078/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1225078/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; spf=pass (sender SPF authorized)\n\tsmtp.mailfrom=osuosl.org (client-ip=140.211.166.136;\n\thelo=silver.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 silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\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 47zyzr6cGKz9s1x\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat, 18 Jan 2020 11:12:24 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id 703FF2262B;\n\tSat, 18 Jan 2020 00:12:23 +0000 (UTC)", "from silver.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id 5DyEnwXM6ls9; Sat, 18 Jan 2020 00:12:06 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby silver.osuosl.org (Postfix) with ESMTP id A6FEA22610;\n\tSat, 18 Jan 2020 00:12:06 +0000 (UTC)", "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\tby ash.osuosl.org (Postfix) with ESMTP id 288FF1BF846\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tSat, 18 Jan 2020 00:12:03 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id 247FE22115\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tSat, 18 Jan 2020 00:12:03 +0000 (UTC)", "from silver.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id A3papuN49SOY for <intel-wired-lan@lists.osuosl.org>;\n\tSat, 18 Jan 2020 00:11:56 +0000 (UTC)", "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n\tby silver.osuosl.org (Postfix) with ESMTPS id B726722176\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tSat, 18 Jan 2020 00:11:56 +0000 (UTC)", "from orsmga005.jf.intel.com ([10.7.209.41])\n\tby fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t17 Jan 2020 16:11:55 -0800", "from unknown (HELO localhost.jf.intel.com) ([10.166.244.174])\n\tby orsmga005.jf.intel.com with ESMTP; 17 Jan 2020 16:11:55 -0800" ], "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.70,332,1574150400\"; d=\"scan'208\";a=\"398818583\"", "From": "Tony Nguyen <anthony.l.nguyen@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Fri, 17 Jan 2020 07:39:13 -0800", "Message-Id": "<20200117153919.50321-2-anthony.l.nguyen@intel.com>", "X-Mailer": "git-send-email 2.20.1", "In-Reply-To": "<20200117153919.50321-1-anthony.l.nguyen@intel.com>", "References": "<20200117153919.50321-1-anthony.l.nguyen@intel.com>", "MIME-Version": "1.0", "Subject": "[Intel-wired-lan] [PATCH S36 2/8] ice: Allocate flow profile", "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": "Create an extraction sequence based on the packet header protocols to be\nprogrammed and allocate a flow profile for the extraction sequence.\n\nSigned-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>\nSigned-off-by: Henry Tieman <henry.w.tieman@intel.com>\n---\n .../net/ethernet/intel/ice/ice_adminq_cmd.h | 6 +\n drivers/net/ethernet/intel/ice/ice_common.c | 75 +++\n drivers/net/ethernet/intel/ice/ice_common.h | 6 +\n .../net/ethernet/intel/ice/ice_flex_pipe.c | 216 ++++++++\n .../net/ethernet/intel/ice/ice_flex_pipe.h | 3 +\n .../net/ethernet/intel/ice/ice_flex_type.h | 15 +\n drivers/net/ethernet/intel/ice/ice_flow.c | 490 +++++++++++++++++-\n drivers/net/ethernet/intel/ice/ice_flow.h | 23 +\n .../net/ethernet/intel/ice/ice_lan_tx_rx.h | 8 +\n .../ethernet/intel/ice/ice_protocol_type.h | 24 +\n drivers/net/ethernet/intel/ice/ice_switch.c | 36 --\n drivers/net/ethernet/intel/ice/ice_type.h | 2 +\n 12 files changed, 864 insertions(+), 40 deletions(-)\n create mode 100644 drivers/net/ethernet/intel/ice/ice_protocol_type.h", "diff": "diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\nindex 2fe53f530517..6a45bbffbbbb 100644\n--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\n+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\n@@ -233,6 +233,12 @@ struct ice_aqc_get_sw_cfg_resp {\n */\n #define ICE_AQC_RES_TYPE_VSI_LIST_REP\t\t\t0x03\n #define ICE_AQC_RES_TYPE_VSI_LIST_PRUNE\t\t\t0x04\n+#define ICE_AQC_RES_TYPE_HASH_PROF_BLDR_PROFID\t\t0x60\n+\n+#define ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM\t\tBIT(12)\n+#define ICE_AQC_RES_TYPE_FLAG_IGNORE_INDEX\t\tBIT(13)\n+\n+#define ICE_AQC_RES_TYPE_FLAG_DEDICATED\t\t\t0x00\n \n /* Allocate Resources command (indirect 0x0208)\n * Free Resources command (indirect 0x0209)\ndiff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c\nindex 84ef40315948..463b1f25e261 100644\n--- a/drivers/net/ethernet/intel/ice/ice_common.c\n+++ b/drivers/net/ethernet/intel/ice/ice_common.c\n@@ -1497,6 +1497,81 @@ void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res)\n \t}\n }\n \n+/**\n+ * ice_aq_alloc_free_res - command to allocate/free resources\n+ * @hw: pointer to the HW struct\n+ * @num_entries: number of resource entries in buffer\n+ * @buf: Indirect buffer to hold data parameters and response\n+ * @buf_size: size of buffer for indirect commands\n+ * @opc: pass in the command opcode\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Helper function to allocate/free resources using the admin queue commands\n+ */\n+enum ice_status\n+ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries,\n+\t\t struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size,\n+\t\t enum ice_adminq_opc opc, struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_alloc_free_res_cmd *cmd;\n+\tstruct ice_aq_desc desc;\n+\n+\tcmd = &desc.params.sw_res_ctrl;\n+\n+\tif (!buf)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tif (buf_size < (num_entries * sizeof(buf->elem[0])))\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, opc);\n+\n+\tdesc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);\n+\n+\tcmd->num_entries = cpu_to_le16(num_entries);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);\n+}\n+\n+/**\n+ * ice_alloc_hw_res - allocate resource\n+ * @hw: pointer to the HW struct\n+ * @type: type of resource\n+ * @num: number of resources to allocate\n+ * @btm: allocate from bottom\n+ * @res: pointer to array that will receive the resources\n+ */\n+enum ice_status\n+ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res)\n+{\n+\tstruct ice_aqc_alloc_free_res_elem *buf;\n+\tenum ice_status status;\n+\tu16 buf_len;\n+\n+\tbuf_len = struct_size(buf, elem, num - 1);\n+\tbuf = kzalloc(buf_len, GFP_KERNEL);\n+\tif (!buf)\n+\t\treturn ICE_ERR_NO_MEMORY;\n+\n+\t/* Prepare buffer to allocate resource. */\n+\tbuf->num_elems = cpu_to_le16(num);\n+\tbuf->res_type = cpu_to_le16(type | ICE_AQC_RES_TYPE_FLAG_DEDICATED |\n+\t\t\t\t ICE_AQC_RES_TYPE_FLAG_IGNORE_INDEX);\n+\tif (btm)\n+\t\tbuf->res_type |= cpu_to_le16(ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM);\n+\n+\tstatus = ice_aq_alloc_free_res(hw, 1, buf, buf_len,\n+\t\t\t\t ice_aqc_opc_alloc_res, NULL);\n+\tif (status)\n+\t\tgoto ice_alloc_res_exit;\n+\n+\tmemcpy(res, buf->elem, sizeof(buf->elem) * num);\n+\n+ice_alloc_res_exit:\n+\tkfree(buf);\n+\treturn status;\n+}\n+\n /**\n * ice_get_num_per_func - determine number of resources per PF\n * @hw: pointer to the HW structure\ndiff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h\nindex a6beebff1379..00de178c9f52 100644\n--- a/drivers/net/ethernet/intel/ice/ice_common.h\n+++ b/drivers/net/ethernet/intel/ice/ice_common.h\n@@ -34,10 +34,16 @@ enum ice_status\n ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,\n \t\tenum ice_aq_res_access_type access, u32 timeout);\n void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res);\n+enum ice_status\n+ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res);\n enum ice_status ice_init_nvm(struct ice_hw *hw);\n enum ice_status\n ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, u16 *data);\n enum ice_status\n+ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries,\n+\t\t struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size,\n+\t\t enum ice_adminq_opc opc, struct ice_sq_cd *cd);\n+enum ice_status\n ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,\n \t\tstruct ice_aq_desc *desc, void *buf, u16 buf_size,\n \t\tstruct ice_sq_cd *cd);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\nindex f37eb536e7b7..5c09d3105b8b 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\n+++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\n@@ -1118,6 +1118,117 @@ ice_vsig_add_mv_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig)\n \treturn 0;\n }\n \n+/**\n+ * ice_find_prof_id - find profile ID for a given field vector\n+ * @hw: pointer to the hardware structure\n+ * @blk: HW block\n+ * @fv: field vector to search for\n+ * @prof_id: receives the profile ID\n+ */\n+static enum ice_status\n+ice_find_prof_id(struct ice_hw *hw, enum ice_block blk,\n+\t\t struct ice_fv_word *fv, u8 *prof_id)\n+{\n+\tstruct ice_es *es = &hw->blk[blk].es;\n+\tu16 off, i;\n+\n+\tfor (i = 0; i < es->count; i++) {\n+\t\toff = i * es->fvw;\n+\n+\t\tif (memcmp(&es->t[off], fv, es->fvw * sizeof(*fv)))\n+\t\t\tcontinue;\n+\n+\t\t*prof_id = i;\n+\t\treturn 0;\n+\t}\n+\n+\treturn ICE_ERR_DOES_NOT_EXIST;\n+}\n+\n+/**\n+ * ice_prof_id_rsrc_type - get profile ID resource type for a block type\n+ * @blk: the block type\n+ * @rsrc_type: pointer to variable to receive the resource type\n+ */\n+static bool ice_prof_id_rsrc_type(enum ice_block blk, u16 *rsrc_type)\n+{\n+\tswitch (blk) {\n+\tcase ICE_BLK_RSS:\n+\t\t*rsrc_type = ICE_AQC_RES_TYPE_HASH_PROF_BLDR_PROFID;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn false;\n+\t}\n+\treturn true;\n+}\n+\n+/**\n+ * ice_alloc_prof_id - allocate profile ID\n+ * @hw: pointer to the HW struct\n+ * @blk: the block to allocate the profile ID for\n+ * @prof_id: pointer to variable to receive the profile ID\n+ *\n+ * This function allocates a new profile ID, which also corresponds to a Field\n+ * Vector (Extraction Sequence) entry.\n+ */\n+static enum ice_status\n+ice_alloc_prof_id(struct ice_hw *hw, enum ice_block blk, u8 *prof_id)\n+{\n+\tenum ice_status status;\n+\tu16 res_type;\n+\tu16 get_prof;\n+\n+\tif (!ice_prof_id_rsrc_type(blk, &res_type))\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tstatus = ice_alloc_hw_res(hw, res_type, 1, false, &get_prof);\n+\tif (!status)\n+\t\t*prof_id = (u8)get_prof;\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_prof_inc_ref - increment reference count for profile\n+ * @hw: pointer to the HW struct\n+ * @blk: the block from which to free the profile ID\n+ * @prof_id: the profile ID for which to increment the reference count\n+ */\n+static enum ice_status\n+ice_prof_inc_ref(struct ice_hw *hw, enum ice_block blk, u8 prof_id)\n+{\n+\tif (prof_id > hw->blk[blk].es.count)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\thw->blk[blk].es.ref_count[prof_id]++;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_write_es - write an extraction sequence to hardware\n+ * @hw: pointer to the HW struct\n+ * @blk: the block in which to write the extraction sequence\n+ * @prof_id: the profile ID to write\n+ * @fv: pointer to the extraction sequence to write - NULL to clear extraction\n+ */\n+static void\n+ice_write_es(struct ice_hw *hw, enum ice_block blk, u8 prof_id,\n+\t struct ice_fv_word *fv)\n+{\n+\tu16 off;\n+\n+\toff = prof_id * hw->blk[blk].es.fvw;\n+\tif (!fv) {\n+\t\tmemset(&hw->blk[blk].es.t[off], 0,\n+\t\t hw->blk[blk].es.fvw * sizeof(*fv));\n+\t\thw->blk[blk].es.written[prof_id] = false;\n+\t} else {\n+\t\tmemcpy(&hw->blk[blk].es.t[off], fv,\n+\t\t hw->blk[blk].es.fvw * sizeof(*fv));\n+\t}\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@@ -1576,3 +1687,108 @@ enum ice_status ice_init_hw_tbls(struct ice_hw *hw)\n \tice_free_hw_tbls(hw);\n \treturn ICE_ERR_NO_MEMORY;\n }\n+\n+/**\n+ * ice_add_prof - add profile\n+ * @hw: pointer to the HW struct\n+ * @blk: hardware block\n+ * @id: profile tracking ID\n+ * @ptypes: array of bitmaps indicating ptypes (ICE_FLOW_PTYPE_MAX bits)\n+ * @es: extraction sequence (length of array is determined by the block)\n+ *\n+ * This function registers a profile, which matches a set of PTGs with a\n+ * particular extraction sequence. While the hardware profile is allocated\n+ * it will not be written until the first call to ice_add_flow that specifies\n+ * the ID value used here.\n+ */\n+enum ice_status\n+ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[],\n+\t struct ice_fv_word *es)\n+{\n+\tu32 bytes = DIV_ROUND_UP(ICE_FLOW_PTYPE_MAX, BITS_PER_BYTE);\n+\tDECLARE_BITMAP(ptgs_used, ICE_XLT1_CNT);\n+\tstruct ice_prof_map *prof;\n+\tenum ice_status status;\n+\tu32 byte = 0;\n+\tu8 prof_id;\n+\n+\tbitmap_zero(ptgs_used, ICE_XLT1_CNT);\n+\n+\tmutex_lock(&hw->blk[blk].es.prof_map_lock);\n+\n+\t/* search for existing profile */\n+\tstatus = ice_find_prof_id(hw, blk, es, &prof_id);\n+\tif (status) {\n+\t\t/* allocate profile ID */\n+\t\tstatus = ice_alloc_prof_id(hw, blk, &prof_id);\n+\t\tif (status)\n+\t\t\tgoto err_ice_add_prof;\n+\n+\t\t/* and write new es */\n+\t\tice_write_es(hw, blk, prof_id, es);\n+\t}\n+\n+\tice_prof_inc_ref(hw, blk, prof_id);\n+\n+\t/* add profile info */\n+\tprof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*prof), GFP_KERNEL);\n+\tif (!prof)\n+\t\tgoto err_ice_add_prof;\n+\n+\tprof->profile_cookie = id;\n+\tprof->prof_id = prof_id;\n+\tprof->ptg_cnt = 0;\n+\tprof->context = 0;\n+\n+\t/* build list of ptgs */\n+\twhile (bytes && prof->ptg_cnt < ICE_MAX_PTG_PER_PROFILE) {\n+\t\tu32 bit;\n+\n+\t\tif (!ptypes[byte]) {\n+\t\t\tbytes--;\n+\t\t\tbyte++;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* Examine 8 bits per byte */\n+\t\tfor_each_set_bit(bit, (unsigned long *)&ptypes[byte],\n+\t\t\t\t BITS_PER_BYTE) {\n+\t\t\tu16 ptype;\n+\t\t\tu8 ptg;\n+\t\t\tu8 m;\n+\n+\t\t\tptype = byte * BITS_PER_BYTE + bit;\n+\n+\t\t\t/* The package should place all ptypes in a non-zero\n+\t\t\t * PTG, so the following call should never fail.\n+\t\t\t */\n+\t\t\tif (ice_ptg_find_ptype(hw, blk, ptype, &ptg))\n+\t\t\t\tcontinue;\n+\n+\t\t\t/* If PTG is already added, skip and continue */\n+\t\t\tif (test_bit(ptg, ptgs_used))\n+\t\t\t\tcontinue;\n+\n+\t\t\tset_bit(ptg, ptgs_used);\n+\t\t\tprof->ptg[prof->ptg_cnt] = ptg;\n+\n+\t\t\tif (++prof->ptg_cnt >= ICE_MAX_PTG_PER_PROFILE)\n+\t\t\t\tbreak;\n+\n+\t\t\t/* nothing left in byte, then exit */\n+\t\t\tm = ~((1 << (bit + 1)) - 1);\n+\t\t\tif (!(ptypes[byte] & m))\n+\t\t\t\tbreak;\n+\t\t}\n+\n+\t\tbytes--;\n+\t\tbyte++;\n+\t}\n+\n+\tlist_add(&prof->list, &hw->blk[blk].es.prof_map);\n+\tstatus = 0;\n+\n+err_ice_add_prof:\n+\tmutex_unlock(&hw->blk[blk].es.prof_map_lock);\n+\treturn status;\n+}\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h\nindex 37eb282742d1..8cb7d7f09e0b 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h\n+++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h\n@@ -18,6 +18,9 @@\n \n #define ICE_PKG_CNT 4\n \n+enum ice_status\n+ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[],\n+\t struct ice_fv_word *es);\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);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flex_type.h b/drivers/net/ethernet/intel/ice/ice_flex_type.h\nindex 5d5a7eaffa30..3005f111fb3b 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flex_type.h\n+++ b/drivers/net/ethernet/intel/ice/ice_flex_type.h\n@@ -3,6 +3,9 @@\n \n #ifndef _ICE_FLEX_TYPE_H_\n #define _ICE_FLEX_TYPE_H_\n+\n+#define ICE_FV_OFFSET_INVAL\t0x1FF\n+\n /* Extraction Sequence (Field Vector) Table */\n struct ice_fv_word {\n \tu8 prot_id;\n@@ -280,6 +283,17 @@ struct ice_ptg_ptype {\n \tu8 ptg;\n };\n \n+#define ICE_MAX_PTG_PER_PROFILE\t\t32\n+\n+struct ice_prof_map {\n+\tstruct list_head list;\n+\tu64 profile_cookie;\n+\tu64 context;\n+\tu8 prof_id;\n+\tu8 ptg_cnt;\n+\tu8 ptg[ICE_MAX_PTG_PER_PROFILE];\n+};\n+\n struct ice_vsig_entry {\n \tstruct list_head prop_lst;\n \tstruct ice_vsig_vsi *first_vsi;\n@@ -371,4 +385,5 @@ struct ice_blk_info {\n \tu8 is_list_init;\n };\n \n+#define ICE_FLOW_PTYPE_MAX\t\tICE_XLT1_CNT\n #endif /* _ICE_FLEX_TYPE_H_ */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flow.c b/drivers/net/ethernet/intel/ice/ice_flow.c\nindex 4828c64abe98..24fe04f8baa2 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flow.c\n+++ b/drivers/net/ethernet/intel/ice/ice_flow.c\n@@ -40,6 +40,457 @@ struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {\n \tICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)),\n };\n \n+/* Bitmaps indicating relevant packet types for a particular protocol header\n+ *\n+ * Packet types for packets with an Outer/First/Single IPv4 header\n+ */\n+static const u32 ice_ptypes_ipv4_ofos[] = {\n+\t0x1DC00000, 0x04000800, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+};\n+\n+/* Packet types for packets with an Innermost/Last IPv4 header */\n+static const u32 ice_ptypes_ipv4_il[] = {\n+\t0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,\n+\t0x0000000E, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+};\n+\n+/* Packet types for packets with an Outer/First/Single IPv6 header */\n+static const u32 ice_ptypes_ipv6_ofos[] = {\n+\t0x00000000, 0x00000000, 0x77000000, 0x10002000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+};\n+\n+/* Packet types for packets with an Innermost/Last IPv6 header */\n+static const u32 ice_ptypes_ipv6_il[] = {\n+\t0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,\n+\t0x00000770, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+};\n+\n+/* UDP Packet types for non-tunneled packets or tunneled\n+ * packets with inner UDP.\n+ */\n+static const u32 ice_ptypes_udp_il[] = {\n+\t0x81000000, 0x20204040, 0x04000010, 0x80810102,\n+\t0x00000040, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+};\n+\n+/* Packet types for packets with an Innermost/Last TCP header */\n+static const u32 ice_ptypes_tcp_il[] = {\n+\t0x04000000, 0x80810102, 0x10000040, 0x02040408,\n+\t0x00000102, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+};\n+\n+/* Packet types for packets with an Innermost/Last SCTP header */\n+static const u32 ice_ptypes_sctp_il[] = {\n+\t0x08000000, 0x01020204, 0x20000081, 0x04080810,\n+\t0x00000204, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+\t0x00000000, 0x00000000, 0x00000000, 0x00000000,\n+};\n+\n+/* Manage parameters and info. used during the creation of a flow profile */\n+struct ice_flow_prof_params {\n+\tenum ice_block blk;\n+\tu16 entry_length; /* # of bytes formatted entry will require */\n+\tu8 es_cnt;\n+\tstruct ice_flow_prof *prof;\n+\n+\t/* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0\n+\t * This will give us the direction flags.\n+\t */\n+\tstruct ice_fv_word es[ICE_MAX_FV_WORDS];\n+\tDECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX);\n+};\n+\n+#define ICE_FLOW_SEG_HDRS_L3_MASK\t\\\n+\t(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)\n+#define ICE_FLOW_SEG_HDRS_L4_MASK\t\\\n+\t(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)\n+\n+/**\n+ * ice_flow_val_hdrs - validates packet segments for valid protocol headers\n+ * @segs: array of one or more packet segments that describe the flow\n+ * @segs_cnt: number of packet segments provided\n+ */\n+static enum ice_status\n+ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)\n+{\n+\tu8 i;\n+\n+\tfor (i = 0; i < segs_cnt; i++) {\n+\t\t/* Multiple L3 headers */\n+\t\tif (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&\n+\t\t !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))\n+\t\t\treturn ICE_ERR_PARAM;\n+\n+\t\t/* Multiple L4 headers */\n+\t\tif (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&\n+\t\t !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))\n+\t\t\treturn ICE_ERR_PARAM;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments\n+ * @params: information about the flow to be processed\n+ *\n+ * This function identifies the packet types associated with the protocol\n+ * headers being present in packet segments of the specified flow profile.\n+ */\n+static enum ice_status\n+ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)\n+{\n+\tstruct ice_flow_prof *prof;\n+\tu8 i;\n+\n+\tmemset(params->ptypes, 0xff, sizeof(params->ptypes));\n+\n+\tprof = params->prof;\n+\n+\tfor (i = 0; i < params->prof->segs_cnt; i++) {\n+\t\tconst unsigned long *src;\n+\t\tu32 hdrs;\n+\n+\t\thdrs = prof->segs[i].hdrs;\n+\n+\t\tif (hdrs & ICE_FLOW_SEG_HDR_IPV4) {\n+\t\t\tsrc = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos :\n+\t\t\t\t(const unsigned long *)ice_ptypes_ipv4_il;\n+\t\t\tbitmap_and(params->ptypes, params->ptypes, src,\n+\t\t\t\t ICE_FLOW_PTYPE_MAX);\n+\t\t} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {\n+\t\t\tsrc = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos :\n+\t\t\t\t(const unsigned long *)ice_ptypes_ipv6_il;\n+\t\t\tbitmap_and(params->ptypes, params->ptypes, src,\n+\t\t\t\t ICE_FLOW_PTYPE_MAX);\n+\t\t}\n+\n+\t\tif (hdrs & ICE_FLOW_SEG_HDR_UDP) {\n+\t\t\tsrc = (const unsigned long *)ice_ptypes_udp_il;\n+\t\t\tbitmap_and(params->ptypes, params->ptypes, src,\n+\t\t\t\t ICE_FLOW_PTYPE_MAX);\n+\t\t} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {\n+\t\t\tbitmap_and(params->ptypes, params->ptypes,\n+\t\t\t\t (const unsigned long *)ice_ptypes_tcp_il,\n+\t\t\t\t ICE_FLOW_PTYPE_MAX);\n+\t\t} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {\n+\t\t\tsrc = (const unsigned long *)ice_ptypes_sctp_il;\n+\t\t\tbitmap_and(params->ptypes, params->ptypes, src,\n+\t\t\t\t ICE_FLOW_PTYPE_MAX);\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_flow_xtract_fld - Create an extraction sequence entry for the given field\n+ * @hw: pointer to the HW struct\n+ * @params: information about the flow to be processed\n+ * @seg: packet segment index of the field to be extracted\n+ * @fld: ID of field to be extracted\n+ *\n+ * This function determines the protocol ID, offset, and size of the given\n+ * field. It then allocates one or more extraction sequence entries for the\n+ * given field, and fill the entries with protocol ID and offset information.\n+ */\n+static enum ice_status\n+ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,\n+\t\t u8 seg, enum ice_flow_field fld)\n+{\n+\tenum ice_prot_id prot_id = ICE_PROT_ID_INVAL;\n+\tu8 fv_words = hw->blk[params->blk].es.fvw;\n+\tstruct ice_flow_fld_info *flds;\n+\tu16 cnt, ese_bits, i;\n+\tu16 off;\n+\n+\tflds = params->prof->segs[seg].fields;\n+\n+\tswitch (fld) {\n+\tcase ICE_FLOW_FIELD_IDX_IPV4_SA:\n+\tcase ICE_FLOW_FIELD_IDX_IPV4_DA:\n+\t\tprot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;\n+\t\tbreak;\n+\tcase ICE_FLOW_FIELD_IDX_IPV6_SA:\n+\tcase ICE_FLOW_FIELD_IDX_IPV6_DA:\n+\t\tprot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;\n+\t\tbreak;\n+\tcase ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:\n+\tcase ICE_FLOW_FIELD_IDX_TCP_DST_PORT:\n+\t\tprot_id = ICE_PROT_TCP_IL;\n+\t\tbreak;\n+\tcase ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:\n+\tcase ICE_FLOW_FIELD_IDX_UDP_DST_PORT:\n+\t\tprot_id = ICE_PROT_UDP_IL_OR_S;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn ICE_ERR_NOT_IMPL;\n+\t}\n+\n+\t/* Each extraction sequence entry is a word in size, and extracts a\n+\t * word-aligned offset from a protocol header.\n+\t */\n+\tese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;\n+\n+\tflds[fld].xtrct.prot_id = prot_id;\n+\tflds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *\n+\t\tICE_FLOW_FV_EXTRACT_SZ;\n+\tflds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);\n+\tflds[fld].xtrct.idx = params->es_cnt;\n+\n+\t/* Adjust the next field-entry index after accommodating the number of\n+\t * entries this field consumes\n+\t */\n+\tcnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size,\n+\t\t\t ese_bits);\n+\n+\t/* Fill in the extraction sequence entries needed for this field */\n+\toff = flds[fld].xtrct.off;\n+\tfor (i = 0; i < cnt; i++) {\n+\t\tu8 idx;\n+\n+\t\t/* Make sure the number of extraction sequence required\n+\t\t * does not exceed the block's capability\n+\t\t */\n+\t\tif (params->es_cnt >= fv_words)\n+\t\t\treturn ICE_ERR_MAX_LIMIT;\n+\n+\t\t/* some blocks require a reversed field vector layout */\n+\t\tif (hw->blk[params->blk].es.reverse)\n+\t\t\tidx = fv_words - params->es_cnt - 1;\n+\t\telse\n+\t\t\tidx = params->es_cnt;\n+\n+\t\tparams->es[idx].prot_id = prot_id;\n+\t\tparams->es[idx].off = off;\n+\t\tparams->es_cnt++;\n+\n+\t\toff += ICE_FLOW_FV_EXTRACT_SZ;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments\n+ * @hw: pointer to the HW struct\n+ * @params: information about the flow to be processed\n+ *\n+ * This function iterates through all matched fields in the given segments, and\n+ * creates an extraction sequence for the fields.\n+ */\n+static enum ice_status\n+ice_flow_create_xtrct_seq(struct ice_hw *hw,\n+\t\t\t struct ice_flow_prof_params *params)\n+{\n+\tstruct ice_flow_prof *prof = params->prof;\n+\tenum ice_status status = 0;\n+\tu8 i;\n+\n+\tfor (i = 0; i < prof->segs_cnt; i++) {\n+\t\tu8 j;\n+\n+\t\tfor_each_set_bit(j, (unsigned long *)&prof->segs[i].match,\n+\t\t\t\t ICE_FLOW_FIELD_IDX_MAX) {\n+\t\t\tstatus = ice_flow_xtract_fld(hw, params, i,\n+\t\t\t\t\t\t (enum ice_flow_field)j);\n+\t\t\tif (status)\n+\t\t\t\treturn status;\n+\t\t}\n+\t}\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_flow_proc_segs - process all packet segments associated with a profile\n+ * @hw: pointer to the HW struct\n+ * @params: information about the flow to be processed\n+ */\n+static enum ice_status\n+ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)\n+{\n+\tenum ice_status status;\n+\n+\tstatus = ice_flow_proc_seg_hdrs(params);\n+\tif (status)\n+\t\treturn status;\n+\n+\tstatus = ice_flow_create_xtrct_seq(hw, params);\n+\tif (status)\n+\t\treturn status;\n+\n+\tswitch (params->blk) {\n+\tcase ICE_BLK_RSS:\n+\t\t/* Only header information is provided for RSS configuration.\n+\t\t * No further processing is needed.\n+\t\t */\n+\t\tstatus = 0;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn ICE_ERR_NOT_IMPL;\n+\t}\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields\n+ * @hw: pointer to the HW struct\n+ * @blk: classification stage\n+ * @dir: flow direction\n+ * @prof_id: unique ID to identify this flow profile\n+ * @segs: array of one or more packet segments that describe the flow\n+ * @segs_cnt: number of packet segments provided\n+ * @prof: stores the returned flow profile added\n+ *\n+ * Assumption: the caller has acquired the lock to the profile list\n+ */\n+static enum ice_status\n+ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,\n+\t\t enum ice_flow_dir dir, u64 prof_id,\n+\t\t struct ice_flow_seg_info *segs, u8 segs_cnt,\n+\t\t struct ice_flow_prof **prof)\n+{\n+\tstruct ice_flow_prof_params params;\n+\tenum ice_status status;\n+\tu8 i;\n+\n+\tif (!prof)\n+\t\treturn ICE_ERR_BAD_PTR;\n+\n+\tmemset(¶ms, 0, sizeof(params));\n+\tparams.prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params.prof),\n+\t\t\t\t GFP_KERNEL);\n+\tif (!params.prof)\n+\t\treturn ICE_ERR_NO_MEMORY;\n+\n+\t/* initialize extraction sequence to all invalid (0xff) */\n+\tfor (i = 0; i < ICE_MAX_FV_WORDS; i++) {\n+\t\tparams.es[i].prot_id = ICE_PROT_INVALID;\n+\t\tparams.es[i].off = ICE_FV_OFFSET_INVAL;\n+\t}\n+\n+\tparams.blk = blk;\n+\tparams.prof->id = prof_id;\n+\tparams.prof->dir = dir;\n+\tparams.prof->segs_cnt = segs_cnt;\n+\n+\t/* Make a copy of the segments that need to be persistent in the flow\n+\t * profile instance\n+\t */\n+\tfor (i = 0; i < segs_cnt; i++)\n+\t\tmemcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs));\n+\n+\tstatus = ice_flow_proc_segs(hw, ¶ms);\n+\tif (status) {\n+\t\tice_debug(hw, ICE_DBG_FLOW,\n+\t\t\t \"Error processing a flow's packet segments\\n\");\n+\t\tgoto out;\n+\t}\n+\n+\t/* Add a HW profile for this flow profile */\n+\tstatus = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);\n+\tif (status) {\n+\t\tice_debug(hw, ICE_DBG_FLOW, \"Error adding a HW flow profile\\n\");\n+\t\tgoto out;\n+\t}\n+\n+\tINIT_LIST_HEAD(¶ms.prof->entries);\n+\tmutex_init(¶ms.prof->entries_lock);\n+\t*prof = params.prof;\n+\n+out:\n+\tif (status)\n+\t\tdevm_kfree(ice_hw_to_dev(hw), params.prof);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_flow_add_prof - Add a flow profile for packet segments and matched fields\n+ * @hw: pointer to the HW struct\n+ * @blk: classification stage\n+ * @dir: flow direction\n+ * @prof_id: unique ID to identify this flow profile\n+ * @segs: array of one or more packet segments that describe the flow\n+ * @segs_cnt: number of packet segments provided\n+ */\n+static enum ice_status\n+ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,\n+\t\t u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt)\n+{\n+\tstruct ice_flow_prof *prof = NULL;\n+\tenum ice_status status;\n+\n+\tif (segs_cnt > ICE_FLOW_SEG_MAX)\n+\t\treturn ICE_ERR_MAX_LIMIT;\n+\n+\tif (!segs_cnt)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tif (!segs)\n+\t\treturn ICE_ERR_BAD_PTR;\n+\n+\tstatus = ice_flow_val_hdrs(segs, segs_cnt);\n+\tif (status)\n+\t\treturn status;\n+\n+\tmutex_lock(&hw->fl_profs_locks[blk]);\n+\n+\tstatus = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,\n+\t\t\t\t\t&prof);\n+\tif (!status)\n+\t\tlist_add(&prof->l_entry, &hw->fl_profs[blk]);\n+\n+\tmutex_unlock(&hw->fl_profs_locks[blk]);\n+\n+\treturn status;\n+}\n+\n /**\n * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer\n * @seg: packet segment the field being set belongs to\n@@ -161,10 +612,28 @@ ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,\n \treturn 0;\n }\n \n+#define ICE_FLOW_PROF_HASH_S\t0\n+#define ICE_FLOW_PROF_HASH_M\t(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)\n+#define ICE_FLOW_PROF_HDR_S\t32\n+#define ICE_FLOW_PROF_HDR_M\t(0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)\n+#define ICE_FLOW_PROF_ENCAP_S\t63\n+#define ICE_FLOW_PROF_ENCAP_M\t(BIT_ULL(ICE_FLOW_PROF_ENCAP_S))\n+\n #define ICE_RSS_OUTER_HEADERS\t1\n \n+/* Flow profile ID format:\n+ * [0:31] - Packet match fields\n+ * [32:62] - Protocol header\n+ * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled\n+ */\n+#define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \\\n+\t(u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \\\n+\t (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \\\n+\t ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))\n+\n /**\n * ice_add_rss_cfg_sync - add an RSS configuration\n+ * @hw: pointer to the hardware structure\n * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure\n * @addl_hdrs: protocol header fields\n * @segs_cnt: packet segment count\n@@ -172,7 +641,8 @@ ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,\n * Assumption: lock has already been acquired for RSS list\n */\n static enum ice_status\n-ice_add_rss_cfg_sync(u64 hashed_flds, u32 addl_hdrs, u8 segs_cnt)\n+ice_add_rss_cfg_sync(struct ice_hw *hw, u64 hashed_flds, u32 addl_hdrs,\n+\t\t u8 segs_cnt)\n {\n \tstruct ice_flow_seg_info *segs;\n \tenum ice_status status;\n@@ -187,7 +657,19 @@ ice_add_rss_cfg_sync(u64 hashed_flds, u32 addl_hdrs, u8 segs_cnt)\n \t/* Construct the packet segment info from the hashed fields */\n \tstatus = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,\n \t\t\t\t\t addl_hdrs);\n-\n+\tif (status)\n+\t\tgoto exit;\n+\n+\t/* Create a new flow profile with generated profile and packet\n+\t * segment information.\n+\t */\n+\tstatus = ice_flow_add_prof(hw, ICE_BLK_RSS, ICE_FLOW_RX,\n+\t\t\t\t ICE_FLOW_GEN_PROFID(hashed_flds,\n+\t\t\t\t\t\t segs[segs_cnt - 1].hdrs,\n+\t\t\t\t\t\t segs_cnt),\n+\t\t\t\t segs, segs_cnt);\n+\n+exit:\n \tkfree(segs);\n \treturn status;\n }\n@@ -214,7 +696,7 @@ ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,\n \t\treturn ICE_ERR_PARAM;\n \n \tmutex_lock(&hw->rss_locks);\n-\tstatus = ice_add_rss_cfg_sync(hashed_flds, addl_hdrs,\n+\tstatus = ice_add_rss_cfg_sync(hw, hashed_flds, addl_hdrs,\n \t\t\t\t ICE_RSS_OUTER_HEADERS);\n \tmutex_unlock(&hw->rss_locks);\n \n@@ -237,7 +719,7 @@ enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)\n \tmutex_lock(&hw->rss_locks);\n \tlist_for_each_entry(r, &hw->rss_list_head, l_entry) {\n \t\tif (test_bit(vsi_handle, r->vsis)) {\n-\t\t\tstatus = ice_add_rss_cfg_sync(r->hashed_flds,\n+\t\t\tstatus = ice_add_rss_cfg_sync(hw, r->hashed_flds,\n \t\t\t\t\t\t r->packet_hdr,\n \t\t\t\t\t\t ICE_RSS_OUTER_HEADERS);\n \t\t\tif (status)\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flow.h b/drivers/net/ethernet/intel/ice/ice_flow.h\nindex 48c0fc09d5ff..05b0dab4793c 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flow.h\n+++ b/drivers/net/ethernet/intel/ice/ice_flow.h\n@@ -56,7 +56,13 @@ enum ice_flow_field {\n \tICE_FLOW_FIELD_IDX_MAX\n };\n \n+enum ice_flow_dir {\n+\tICE_FLOW_RX\t\t= 0x02,\n+};\n+\n #define ICE_FLOW_SEG_MAX\t\t2\n+#define ICE_FLOW_FV_EXTRACT_SZ\t\t2\n+\n #define ICE_FLOW_SET_HDRS(seg, val)\t((seg)->hdrs |= (u32)(val))\n \n struct ice_flow_seg_xtrct {\n@@ -99,6 +105,23 @@ struct ice_flow_seg_info {\n \tstruct ice_flow_fld_info fields[ICE_FLOW_FIELD_IDX_MAX];\n };\n \n+struct ice_flow_prof {\n+\tstruct list_head l_entry;\n+\n+\tu64 id;\n+\tenum ice_flow_dir dir;\n+\tu8 segs_cnt;\n+\n+\t/* Keep track of flow entries associated with this flow profile */\n+\tstruct mutex entries_lock;\n+\tstruct list_head entries;\n+\n+\tstruct ice_flow_seg_info segs[ICE_FLOW_SEG_MAX];\n+\n+\t/* software VSI handles referenced by this flow profile */\n+\tDECLARE_BITMAP(vsis, ICE_MAX_VSI);\n+};\n+\n struct ice_rss_cfg {\n \tstruct list_head l_entry;\n \t/* bitmap of VSIs added to the RSS entry */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h\nindex 0997d352709b..878e125d8b42 100644\n--- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h\n+++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h\n@@ -199,6 +199,14 @@ enum ice_rxdid {\n /* Receive Flex Descriptor Rx opcode values */\n #define ICE_RX_OPC_MDID\t\t0x01\n \n+/* Receive Descriptor MDID values that access packet flags */\n+enum ice_flex_mdid_pkt_flags {\n+\tICE_RX_MDID_PKT_FLAGS_15_0\t= 20,\n+\tICE_RX_MDID_PKT_FLAGS_31_16,\n+\tICE_RX_MDID_PKT_FLAGS_47_32,\n+\tICE_RX_MDID_PKT_FLAGS_63_48,\n+};\n+\n /* Receive Descriptor MDID values */\n enum ice_flex_rx_mdid {\n \tICE_RX_MDID_FLOW_ID_LOWER\t= 5,\ndiff --git a/drivers/net/ethernet/intel/ice/ice_protocol_type.h b/drivers/net/ethernet/intel/ice/ice_protocol_type.h\nnew file mode 100644\nindex 000000000000..97db46ce7a21\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/ice/ice_protocol_type.h\n@@ -0,0 +1,24 @@\n+/* SPDX-License-Identifier: GPL-2.0 */\n+/* Copyright (c) 2019, Intel Corporation. */\n+\n+#ifndef _ICE_PROTOCOL_TYPE_H_\n+#define _ICE_PROTOCOL_TYPE_H_\n+/* Decoders for ice_prot_id:\n+ * - F: First\n+ * - I: Inner\n+ * - L: Last\n+ * - O: Outer\n+ * - S: Single\n+ */\n+enum ice_prot_id {\n+\tICE_PROT_ID_INVAL\t= 0,\n+\tICE_PROT_IPV4_OF_OR_S\t= 32,\n+\tICE_PROT_IPV4_IL\t= 33,\n+\tICE_PROT_IPV6_OF_OR_S\t= 40,\n+\tICE_PROT_IPV6_IL\t= 41,\n+\tICE_PROT_TCP_IL\t\t= 49,\n+\tICE_PROT_UDP_IL_OR_S\t= 53,\n+\tICE_PROT_META_ID\t= 255, /* when offset == metadata */\n+\tICE_PROT_INVALID\t= 255 /* when offset == ICE_FV_OFFSET_INVAL */\n+};\n+#endif /* _ICE_PROTOCOL_TYPE_H_ */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c\nindex 990b65aed039..1c4124835659 100644\n--- a/drivers/net/ethernet/intel/ice/ice_switch.c\n+++ b/drivers/net/ethernet/intel/ice/ice_switch.c\n@@ -49,42 +49,6 @@ static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,\n \t sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi) + \\\n \t ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi)))\n \n-/**\n- * ice_aq_alloc_free_res - command to allocate/free resources\n- * @hw: pointer to the HW struct\n- * @num_entries: number of resource entries in buffer\n- * @buf: Indirect buffer to hold data parameters and response\n- * @buf_size: size of buffer for indirect commands\n- * @opc: pass in the command opcode\n- * @cd: pointer to command details structure or NULL\n- *\n- * Helper function to allocate/free resources using the admin queue commands\n- */\n-static enum ice_status\n-ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries,\n-\t\t struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size,\n-\t\t enum ice_adminq_opc opc, struct ice_sq_cd *cd)\n-{\n-\tstruct ice_aqc_alloc_free_res_cmd *cmd;\n-\tstruct ice_aq_desc desc;\n-\n-\tcmd = &desc.params.sw_res_ctrl;\n-\n-\tif (!buf)\n-\t\treturn ICE_ERR_PARAM;\n-\n-\tif (buf_size < (num_entries * sizeof(buf->elem[0])))\n-\t\treturn ICE_ERR_PARAM;\n-\n-\tice_fill_dflt_direct_cmd_desc(&desc, opc);\n-\n-\tdesc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);\n-\n-\tcmd->num_entries = cpu_to_le16(num_entries);\n-\n-\treturn ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);\n-}\n-\n /**\n * ice_init_def_sw_recp - initialize the recipe book keeping tables\n * @hw: pointer to the HW struct\ndiff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h\nindex 67525f6cac89..5224b066730a 100644\n--- a/drivers/net/ethernet/intel/ice/ice_type.h\n+++ b/drivers/net/ethernet/intel/ice/ice_type.h\n@@ -13,6 +13,7 @@\n #include \"ice_controlq.h\"\n #include \"ice_lan_tx_rx.h\"\n #include \"ice_flex_type.h\"\n+#include \"ice_protocol_type.h\"\n \n static inline bool ice_is_tc_ena(unsigned long bitmap, u8 tc)\n {\n@@ -41,6 +42,7 @@ static inline u32 ice_round_to_num(u32 N, u32 R)\n #define ICE_DBG_QCTX\t\tBIT_ULL(6)\n #define ICE_DBG_NVM\t\tBIT_ULL(7)\n #define ICE_DBG_LAN\t\tBIT_ULL(8)\n+#define ICE_DBG_FLOW\t\tBIT_ULL(9)\n #define ICE_DBG_SW\t\tBIT_ULL(13)\n #define ICE_DBG_SCHED\t\tBIT_ULL(14)\n #define ICE_DBG_RDMA\t\tBIT_ULL(15)\n", "prefixes": [ "S36", "2/8" ] }