Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1225074/?format=api
{ "id": 1225074, "url": "http://patchwork.ozlabs.org/api/patches/1225074/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20200117153919.50321-1-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-1-anthony.l.nguyen@intel.com>", "list_archive_url": null, "date": "2020-01-17T15:39:12", "name": "[S36,1/8] ice: Enable writing hardware filtering tables", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "cde358b69f96fabade2c673427f66b6b0af89daa", "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-1-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/1225074/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1225074/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 47zyzb6D6Tz9s1x\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat, 18 Jan 2020 11:12:11 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id BA1A82264A;\n\tSat, 18 Jan 2020 00:12:09 +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 JH6ot5aT4HAG; Sat, 18 Jan 2020 00:12:03 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby silver.osuosl.org (Postfix) with ESMTP id 6ED4022176;\n\tSat, 18 Jan 2020 00:12:03 +0000 (UTC)", "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\tby ash.osuosl.org (Postfix) with ESMTP id 0F3011BF846\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tSat, 18 Jan 2020 00:12:01 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id 0C18622618\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tSat, 18 Jan 2020 00:12:01 +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 bpcFttt8fKHu 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 563DC22115\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=\"398818582\"", "From": "Tony Nguyen <anthony.l.nguyen@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Fri, 17 Jan 2020 07:39:12 -0800", "Message-Id": "<20200117153919.50321-1-anthony.l.nguyen@intel.com>", "X-Mailer": "git-send-email 2.20.1", "MIME-Version": "1.0", "Subject": "[Intel-wired-lan] [PATCH S36 1/8] ice: Enable writing hardware\n\tfiltering tables", "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": "Enable the driver to write the filtering hardware tables to allow for\nchanging of RSS rules. Upon loading of DDP package, a minimal configuration\nshould be written to hardware.\n\nIntroduce and initialize structures for storing configuration and make\nthe top level calls to configure the RSS tables to initial values. A packet\nsegment will be created but nothing is written to hardware yet.\n\nSigned-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>\nSigned-off-by: Henry Tieman <henry.w.tieman@intel.com>\n---\n drivers/net/ethernet/intel/ice/Makefile | 3 +-\n drivers/net/ethernet/intel/ice/ice_common.c | 6 +-\n .../net/ethernet/intel/ice/ice_flex_pipe.c | 31 ++-\n drivers/net/ethernet/intel/ice/ice_flow.c | 250 ++++++++++++++++++\n drivers/net/ethernet/intel/ice/ice_flow.h | 114 ++++++++\n drivers/net/ethernet/intel/ice/ice_lib.c | 87 +++++-\n drivers/net/ethernet/intel/ice/ice_type.h | 4 +\n 7 files changed, 491 insertions(+), 4 deletions(-)\n create mode 100644 drivers/net/ethernet/intel/ice/ice_flow.c\n create mode 100644 drivers/net/ethernet/intel/ice/ice_flow.h", "diff": "diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile\nindex b5ffe4ea6071..30aa4013186d 100644\n--- a/drivers/net/ethernet/intel/ice/Makefile\n+++ b/drivers/net/ethernet/intel/ice/Makefile\n@@ -18,7 +18,8 @@ ice-y := ice_main.o\t\\\n \t ice_txrx_lib.o\t\\\n \t ice_txrx.o\t\\\n \t ice_flex_pipe.o\t\\\n-\t ice_idc.o\t\\\n+\t ice_flow.o\t\t\\\n+\t ice_idc.o\t\t\\\n \t ice_ethtool.o\n ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o ice_sriov.o\n ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_nl.o ice_dcb_lib.o\ndiff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c\nindex c6e2c583c101..84ef40315948 100644\n--- a/drivers/net/ethernet/intel/ice/ice_common.c\n+++ b/drivers/net/ethernet/intel/ice/ice_common.c\n@@ -4,6 +4,7 @@\n #include \"ice_common.h\"\n #include \"ice_sched.h\"\n #include \"ice_adminq_cmd.h\"\n+#include \"ice_flow.h\"\n \n #define ICE_PF_RESET_WAIT_COUNT\t200\n \n@@ -3609,7 +3610,10 @@ enum ice_status ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle)\n \t\tif (status)\n \t\t\treturn status;\n \t}\n-\n+\t/* Replay per VSI all RSS configurations */\n+\tstatus = ice_replay_rss_cfg(hw, vsi_handle);\n+\tif (status)\n+\t\treturn status;\n \t/* Replay per VSI all filters */\n \tstatus = ice_replay_vsi_all_fltr(hw, vsi_handle);\n \treturn status;\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\nindex cbd53b586c36..f37eb536e7b7 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\n+++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\n@@ -3,6 +3,7 @@\n \n #include \"ice_common.h\"\n #include \"ice_flex_pipe.h\"\n+#include \"ice_flow.h\"\n \n /**\n * ice_pkg_val_buf\n@@ -1379,11 +1380,18 @@ void ice_fill_blk_tbls(struct ice_hw *hw)\n */\n void ice_free_hw_tbls(struct ice_hw *hw)\n {\n+\tstruct ice_rss_cfg *r, *rt;\n \tu8 i;\n \n \tfor (i = 0; i < ICE_BLK_COUNT; i++) {\n-\t\thw->blk[i].is_list_init = false;\n+\t\tif (hw->blk[i].is_list_init) {\n+\t\t\tstruct ice_es *es = &hw->blk[i].es;\n \n+\t\t\tmutex_destroy(&es->prof_map_lock);\n+\t\t\tmutex_destroy(&hw->fl_profs_locks[i]);\n+\n+\t\t\thw->blk[i].is_list_init = false;\n+\t\t}\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@@ -1397,9 +1405,25 @@ void ice_free_hw_tbls(struct ice_hw *hw)\n \t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.written);\n \t}\n \n+\tlist_for_each_entry_safe(r, rt, &hw->rss_list_head, l_entry) {\n+\t\tlist_del(&r->l_entry);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), r);\n+\t}\n+\tmutex_destroy(&hw->rss_locks);\n \tmemset(hw->blk, 0, sizeof(hw->blk));\n }\n \n+/**\n+ * ice_init_flow_profs - init flow profile locks and list heads\n+ * @hw: pointer to the hardware structure\n+ * @blk_idx: HW block index\n+ */\n+static void ice_init_flow_profs(struct ice_hw *hw, u8 blk_idx)\n+{\n+\tmutex_init(&hw->fl_profs_locks[blk_idx]);\n+\tINIT_LIST_HEAD(&hw->fl_profs[blk_idx]);\n+}\n+\n /**\n * ice_clear_hw_tbls - clear HW tables and flow profiles\n * @hw: pointer to the hardware structure\n@@ -1443,6 +1467,8 @@ enum ice_status ice_init_hw_tbls(struct ice_hw *hw)\n {\n \tu8 i;\n \n+\tmutex_init(&hw->rss_locks);\n+\tINIT_LIST_HEAD(&hw->rss_list_head);\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@@ -1454,6 +1480,9 @@ enum ice_status ice_init_hw_tbls(struct ice_hw *hw)\n \t\tif (hw->blk[i].is_list_init)\n \t\t\tcontinue;\n \n+\t\tice_init_flow_profs(hw, i);\n+\t\tmutex_init(&es->prof_map_lock);\n+\t\tINIT_LIST_HEAD(&es->prof_map);\n \t\thw->blk[i].is_list_init = true;\n \n \t\thw->blk[i].overwrite = blk_sizes[i].overwrite;\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flow.c b/drivers/net/ethernet/intel/ice/ice_flow.c\nnew file mode 100644\nindex 000000000000..4828c64abe98\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/ice/ice_flow.c\n@@ -0,0 +1,250 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/* Copyright (c) 2019, Intel Corporation. */\n+\n+#include \"ice_common.h\"\n+#include \"ice_flow.h\"\n+\n+/* Describe properties of a protocol header field */\n+struct ice_flow_field_info {\n+\tenum ice_flow_seg_hdr hdr;\n+\ts16 off;\t/* Offset from start of a protocol header, in bits */\n+\tu16 size;\t/* Size of fields in bits */\n+};\n+\n+#define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \\\n+\t.hdr = _hdr, \\\n+\t.off = (_offset_bytes) * BITS_PER_BYTE, \\\n+\t.size = (_size_bytes) * BITS_PER_BYTE, \\\n+}\n+\n+/* Table containing properties of supported protocol header fields */\n+static const\n+struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {\n+\t/* IPv4 / IPv6 */\n+\t/* ICE_FLOW_FIELD_IDX_IPV4_SA */\n+\tICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)),\n+\t/* ICE_FLOW_FIELD_IDX_IPV4_DA */\n+\tICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)),\n+\t/* ICE_FLOW_FIELD_IDX_IPV6_SA */\n+\tICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)),\n+\t/* ICE_FLOW_FIELD_IDX_IPV6_DA */\n+\tICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, sizeof(struct in6_addr)),\n+\t/* Transport */\n+\t/* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */\n+\tICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)),\n+\t/* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */\n+\tICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)),\n+\t/* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */\n+\tICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)),\n+\t/* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */\n+\tICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)),\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+ * @fld: field to be set\n+ * @type: type of the field\n+ * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from\n+ * entry's input buffer\n+ * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's\n+ * input buffer\n+ * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from\n+ * entry's input buffer\n+ *\n+ * This helper function stores information of a field being matched, including\n+ * the type of the field and the locations of the value to match, the mask, and\n+ * and the upper-bound value in the start of the input buffer for a flow entry.\n+ * This function should only be used for fixed-size data structures.\n+ *\n+ * This function also opportunistically determines the protocol headers to be\n+ * present based on the fields being set. Some fields cannot be used alone to\n+ * determine the protocol headers present. Sometimes, fields for particular\n+ * protocol headers are not matched. In those cases, the protocol headers\n+ * must be explicitly set.\n+ */\n+static void\n+ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,\n+\t\t enum ice_flow_fld_match_type type, u16 val_loc,\n+\t\t u16 mask_loc, u16 last_loc)\n+{\n+\tu64 bit = BIT_ULL(fld);\n+\n+\tseg->match |= bit;\n+\tif (type == ICE_FLOW_FLD_TYPE_RANGE)\n+\t\tseg->range |= bit;\n+\n+\tseg->fields[fld].type = type;\n+\tseg->fields[fld].src.val = val_loc;\n+\tseg->fields[fld].src.mask = mask_loc;\n+\tseg->fields[fld].src.last = last_loc;\n+\n+\tICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);\n+}\n+\n+/**\n+ * ice_flow_set_fld - specifies locations of field from entry's input buffer\n+ * @seg: packet segment the field being set belongs to\n+ * @fld: field to be set\n+ * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from\n+ * entry's input buffer\n+ * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's\n+ * input buffer\n+ * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from\n+ * entry's input buffer\n+ * @range: indicate if field being matched is to be in a range\n+ *\n+ * This function specifies the locations, in the form of byte offsets from the\n+ * start of the input buffer for a flow entry, from where the value to match,\n+ * the mask value, and upper value can be extracted. These locations are then\n+ * stored in the flow profile. When adding a flow entry associated with the\n+ * flow profile, these locations will be used to quickly extract the values and\n+ * create the content of a match entry. This function should only be used for\n+ * fixed-size data structures.\n+ */\n+static void\n+ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,\n+\t\t u16 val_loc, u16 mask_loc, u16 last_loc, bool range)\n+{\n+\tenum ice_flow_fld_match_type t = range ?\n+\t\tICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;\n+\n+\tice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);\n+}\n+\n+#define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \\\n+\t(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)\n+\n+#define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \\\n+\t(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)\n+\n+#define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \\\n+\t(ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \\\n+\t ICE_FLOW_RSS_SEG_HDR_L4_MASKS)\n+\n+/**\n+ * ice_flow_set_rss_seg_info - setup packet segments for RSS\n+ * @segs: pointer to the flow field segment(s)\n+ * @hash_fields: fields to be hashed on for the segment(s)\n+ * @flow_hdr: protocol header fields within a packet segment\n+ *\n+ * Helper function to extract fields from hash bitmap and use flow\n+ * header value to set flow field segment for further use in flow\n+ * profile entry or removal.\n+ */\n+static enum ice_status\n+ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,\n+\t\t\t u32 flow_hdr)\n+{\n+\tu64 val;\n+\tu8 i;\n+\n+\tfor_each_set_bit(i, (unsigned long *)&hash_fields,\n+\t\t\t ICE_FLOW_FIELD_IDX_MAX)\n+\t\tice_flow_set_fld(segs, (enum ice_flow_field)i,\n+\t\t\t\t ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,\n+\t\t\t\t ICE_FLOW_FLD_OFF_INVAL, false);\n+\n+\tICE_FLOW_SET_HDRS(segs, flow_hdr);\n+\n+\tif (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tval = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);\n+\tif (val && !is_power_of_2(val))\n+\t\treturn ICE_ERR_CFG;\n+\n+\tval = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);\n+\tif (val && !is_power_of_2(val))\n+\t\treturn ICE_ERR_CFG;\n+\n+\treturn 0;\n+}\n+\n+#define ICE_RSS_OUTER_HEADERS\t1\n+\n+/**\n+ * ice_add_rss_cfg_sync - add an RSS configuration\n+ * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure\n+ * @addl_hdrs: protocol header fields\n+ * @segs_cnt: packet segment count\n+ *\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+{\n+\tstruct ice_flow_seg_info *segs;\n+\tenum ice_status status;\n+\n+\tif (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tsegs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);\n+\tif (!segs)\n+\t\treturn ICE_ERR_NO_MEMORY;\n+\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+\tkfree(segs);\n+\treturn status;\n+}\n+\n+/**\n+ * ice_add_rss_cfg - add an RSS configuration with specified hashed fields\n+ * @hw: pointer to the hardware structure\n+ * @vsi_handle: software VSI handle\n+ * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure\n+ * @addl_hdrs: protocol header fields\n+ *\n+ * This function will generate a flow profile based on fields associated with\n+ * the input fields to hash on, the flow type and use the VSI number to add\n+ * a flow entry to the profile.\n+ */\n+enum ice_status\n+ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,\n+\t\tu32 addl_hdrs)\n+{\n+\tenum ice_status status;\n+\n+\tif (hashed_flds == ICE_HASH_INVALID ||\n+\t !ice_is_vsi_valid(hw, vsi_handle))\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+\t\t\t\t ICE_RSS_OUTER_HEADERS);\n+\tmutex_unlock(&hw->rss_locks);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_replay_rss_cfg - replay RSS configurations associated with VSI\n+ * @hw: pointer to the hardware structure\n+ * @vsi_handle: software VSI handle\n+ */\n+enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)\n+{\n+\tenum ice_status status = 0;\n+\tstruct ice_rss_cfg *r;\n+\n+\tif (!ice_is_vsi_valid(hw, vsi_handle))\n+\t\treturn ICE_ERR_PARAM;\n+\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\t\t\t\t r->packet_hdr,\n+\t\t\t\t\t\t ICE_RSS_OUTER_HEADERS);\n+\t\t\tif (status)\n+\t\t\t\tbreak;\n+\t\t}\n+\t}\n+\tmutex_unlock(&hw->rss_locks);\n+\n+\treturn status;\n+}\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flow.h b/drivers/net/ethernet/intel/ice/ice_flow.h\nnew file mode 100644\nindex 000000000000..48c0fc09d5ff\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/ice/ice_flow.h\n@@ -0,0 +1,114 @@\n+/* SPDX-License-Identifier: GPL-2.0 */\n+/* Copyright (c) 2019, Intel Corporation. */\n+\n+#ifndef _ICE_FLOW_H_\n+#define _ICE_FLOW_H_\n+\n+#define ICE_FLOW_FLD_OFF_INVAL\t\t0xffff\n+\n+/* Generate flow hash field from flow field type(s) */\n+#define ICE_FLOW_HASH_IPV4\t\\\n+\t(BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) | \\\n+\t BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA))\n+#define ICE_FLOW_HASH_IPV6\t\\\n+\t(BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA) | \\\n+\t BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA))\n+#define ICE_FLOW_HASH_TCP_PORT\t\\\n+\t(BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT) | \\\n+\t BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT))\n+#define ICE_FLOW_HASH_UDP_PORT\t\\\n+\t(BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT) | \\\n+\t BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT))\n+\n+#define ICE_HASH_INVALID\t0\n+#define ICE_HASH_TCP_IPV4\t(ICE_FLOW_HASH_IPV4 | ICE_FLOW_HASH_TCP_PORT)\n+#define ICE_HASH_TCP_IPV6\t(ICE_FLOW_HASH_IPV6 | ICE_FLOW_HASH_TCP_PORT)\n+#define ICE_HASH_UDP_IPV4\t(ICE_FLOW_HASH_IPV4 | ICE_FLOW_HASH_UDP_PORT)\n+#define ICE_HASH_UDP_IPV6\t(ICE_FLOW_HASH_IPV6 | ICE_FLOW_HASH_UDP_PORT)\n+\n+/* Protocol header fields within a packet segment. A segment consists of one or\n+ * more protocol headers that make up a logical group of protocol headers. Each\n+ * logical group of protocol headers encapsulates or is encapsulated using/by\n+ * tunneling or encapsulation protocols for network virtualization such as GRE,\n+ * VxLAN, etc.\n+ */\n+enum ice_flow_seg_hdr {\n+\tICE_FLOW_SEG_HDR_NONE\t\t= 0x00000000,\n+\tICE_FLOW_SEG_HDR_IPV4\t\t= 0x00000004,\n+\tICE_FLOW_SEG_HDR_IPV6\t\t= 0x00000008,\n+\tICE_FLOW_SEG_HDR_TCP\t\t= 0x00000040,\n+\tICE_FLOW_SEG_HDR_UDP\t\t= 0x00000080,\n+\tICE_FLOW_SEG_HDR_SCTP\t\t= 0x00000100,\n+};\n+\n+enum ice_flow_field {\n+\t/* L3 */\n+\tICE_FLOW_FIELD_IDX_IPV4_SA,\n+\tICE_FLOW_FIELD_IDX_IPV4_DA,\n+\tICE_FLOW_FIELD_IDX_IPV6_SA,\n+\tICE_FLOW_FIELD_IDX_IPV6_DA,\n+\t/* L4 */\n+\tICE_FLOW_FIELD_IDX_TCP_SRC_PORT,\n+\tICE_FLOW_FIELD_IDX_TCP_DST_PORT,\n+\tICE_FLOW_FIELD_IDX_UDP_SRC_PORT,\n+\tICE_FLOW_FIELD_IDX_UDP_DST_PORT,\n+\t/* The total number of enums must not exceed 64 */\n+\tICE_FLOW_FIELD_IDX_MAX\n+};\n+\n+#define ICE_FLOW_SEG_MAX\t\t2\n+#define ICE_FLOW_SET_HDRS(seg, val)\t((seg)->hdrs |= (u32)(val))\n+\n+struct ice_flow_seg_xtrct {\n+\tu8 prot_id;\t/* Protocol ID of extracted header field */\n+\tu16 off;\t/* Starting offset of the field in header in bytes */\n+\tu8 idx;\t\t/* Index of FV entry used */\n+\tu8 disp;\t/* Displacement of field in bits fr. FV entry's start */\n+};\n+\n+enum ice_flow_fld_match_type {\n+\tICE_FLOW_FLD_TYPE_REG,\t\t/* Value, mask */\n+\tICE_FLOW_FLD_TYPE_RANGE,\t/* Value, mask, last (upper bound) */\n+\tICE_FLOW_FLD_TYPE_PREFIX,\t/* IP address, prefix, size of prefix */\n+\tICE_FLOW_FLD_TYPE_SIZE,\t\t/* Value, mask, size of match */\n+};\n+\n+struct ice_flow_fld_loc {\n+\t/* Describe offsets of field information relative to the beginning of\n+\t * input buffer provided when adding flow entries.\n+\t */\n+\tu16 val;\t/* Offset where the value is located */\n+\tu16 mask;\t/* Offset where the mask/prefix value is located */\n+\tu16 last;\t/* Length or offset where the upper value is located */\n+};\n+\n+struct ice_flow_fld_info {\n+\tenum ice_flow_fld_match_type type;\n+\t/* Location where to retrieve data from an input buffer */\n+\tstruct ice_flow_fld_loc src;\n+\t/* Location where to put the data into the final entry buffer */\n+\tstruct ice_flow_fld_loc entry;\n+\tstruct ice_flow_seg_xtrct xtrct;\n+};\n+\n+struct ice_flow_seg_info {\n+\tu32 hdrs;\t/* Bitmask indicating protocol headers present */\n+\tu64 match;\t/* Bitmask indicating header fields to be matched */\n+\tu64 range;\t/* Bitmask indicating header fields matched as ranges */\n+\n+\tstruct ice_flow_fld_info fields[ICE_FLOW_FIELD_IDX_MAX];\n+};\n+\n+struct ice_rss_cfg {\n+\tstruct list_head l_entry;\n+\t/* bitmap of VSIs added to the RSS entry */\n+\tDECLARE_BITMAP(vsis, ICE_MAX_VSI);\n+\tu64 hashed_flds;\n+\tu32 packet_hdr;\n+};\n+\n+enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle);\n+enum ice_status\n+ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,\n+\t\tu32 addl_hdrs);\n+#endif /* _ICE_FLOW_H_ */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c\nindex 1f47c39f4e86..3b4e6462b8ab 100644\n--- a/drivers/net/ethernet/intel/ice/ice_lib.c\n+++ b/drivers/net/ethernet/intel/ice/ice_lib.c\n@@ -3,6 +3,7 @@\n \n #include \"ice.h\"\n #include \"ice_base.h\"\n+#include \"ice_flow.h\"\n #include \"ice_lib.h\"\n #include \"ice_dcb_lib.h\"\n \n@@ -1097,6 +1098,88 @@ static int ice_vsi_cfg_rss_lut_key(struct ice_vsi *vsi)\n \treturn err;\n }\n \n+/**\n+ * ice_vsi_set_rss_flow_fld - Sets RSS input set for different flows\n+ * @vsi: VSI to be configured\n+ *\n+ * This function will only be called after successful download package call\n+ * during initialization of PF. Since the downloaded package will erase the\n+ * RSS section, this function will configure RSS input sets for different\n+ * flow types. The last profile added has the highest priority, therefore 2\n+ * tuple profiles (i.e. IPv4 src/dst) are added before 4 tuple profiles\n+ * (i.e. IPv4 src/dst TCP src/dst port).\n+ */\n+static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi)\n+{\n+\tu16 vsi_handle = vsi->idx, vsi_num = vsi->vsi_num;\n+\tstruct ice_pf *pf = vsi->back;\n+\tstruct ice_hw *hw = &pf->hw;\n+\tenum ice_status status;\n+\tstruct device *dev;\n+\n+\tdev = ice_pf_to_dev(pf);\n+\tif (ice_is_safe_mode(pf)) {\n+\t\tdev_dbg(dev, \"Advanced RSS disabled. Package download failed, vsi num = %d\\n\",\n+\t\t\tvsi_num);\n+\t\treturn;\n+\t}\n+\t/* configure RSS for IPv4 with input set IP src/dst */\n+\tstatus = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4,\n+\t\t\t\t ICE_FLOW_SEG_HDR_IPV4);\n+\tif (status)\n+\t\tdev_dbg(dev, \"ice_add_rss_cfg failed for ipv4 flow, vsi = %d, error = %d\\n\",\n+\t\t\tvsi_num, status);\n+\n+\t/* configure RSS for IPv6 with input set IPv6 src/dst */\n+\tstatus = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6,\n+\t\t\t\t ICE_FLOW_SEG_HDR_IPV6);\n+\tif (status)\n+\t\tdev_dbg(dev, \"ice_add_rss_cfg failed for ipv6 flow, vsi = %d, error = %d\\n\",\n+\t\t\tvsi_num, status);\n+\n+\t/* configure RSS for tcp4 with input set IP src/dst, TCP src/dst */\n+\tstatus = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV4,\n+\t\t\t\t ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV4);\n+\tif (status)\n+\t\tdev_dbg(dev, \"ice_add_rss_cfg failed for tcp4 flow, vsi = %d, error = %d\\n\",\n+\t\t\tvsi_num, status);\n+\n+\t/* configure RSS for udp4 with input set IP src/dst, UDP src/dst */\n+\tstatus = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV4,\n+\t\t\t\t ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV4);\n+\tif (status)\n+\t\tdev_dbg(dev, \"ice_add_rss_cfg failed for udp4 flow, vsi = %d, error = %d\\n\",\n+\t\t\tvsi_num, status);\n+\n+\t/* configure RSS for sctp4 with input set IP src/dst */\n+\tstatus = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4,\n+\t\t\t\t ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV4);\n+\tif (status)\n+\t\tdev_dbg(dev, \"ice_add_rss_cfg failed for sctp4 flow, vsi = %d, error = %d\\n\",\n+\t\t\tvsi_num, status);\n+\n+\t/* configure RSS for tcp6 with input set IPv6 src/dst, TCP src/dst */\n+\tstatus = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV6,\n+\t\t\t\t ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV6);\n+\tif (status)\n+\t\tdev_dbg(dev, \"ice_add_rss_cfg failed for tcp6 flow, vsi = %d, error = %d\\n\",\n+\t\t\tvsi_num, status);\n+\n+\t/* configure RSS for udp6 with input set IPv6 src/dst, UDP src/dst */\n+\tstatus = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV6,\n+\t\t\t\t ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV6);\n+\tif (status)\n+\t\tdev_dbg(dev, \"ice_add_rss_cfg failed for udp6 flow, vsi = %d, error = %d\\n\",\n+\t\t\tvsi_num, status);\n+\n+\t/* configure RSS for sctp6 with input set IPv6 src/dst */\n+\tstatus = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6,\n+\t\t\t\t ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV6);\n+\tif (status)\n+\t\tdev_dbg(dev, \"ice_add_rss_cfg failed for sctp6 flow, vsi = %d, error = %d\\n\",\n+\t\t\tvsi_num, status);\n+}\n+\n /**\n * ice_add_mac_to_list - Add a MAC address filter entry to the list\n * @vsi: the VSI to be forwarded to\n@@ -1936,8 +2019,10 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,\n \t\t * receive traffic on first queue. Hence no need to capture\n \t\t * return value\n \t\t */\n-\t\tif (test_bit(ICE_FLAG_RSS_ENA, pf->flags))\n+\t\tif (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {\n \t\t\tice_vsi_cfg_rss_lut_key(vsi);\n+\t\t\tice_vsi_set_rss_flow_fld(vsi);\n+\t\t}\n \t\tbreak;\n \tcase ICE_VSI_VF:\n \t\t/* VF driver will take care of creating netdev for this type and\ndiff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h\nindex 060dc95b660d..67525f6cac89 100644\n--- a/drivers/net/ethernet/intel/ice/ice_type.h\n+++ b/drivers/net/ethernet/intel/ice/ice_type.h\n@@ -563,6 +563,10 @@ struct ice_hw {\n \n \t/* HW block tables */\n \tstruct ice_blk_info blk[ICE_BLK_COUNT];\n+\tstruct mutex fl_profs_locks[ICE_BLK_COUNT];\t/* lock fltr profiles */\n+\tstruct list_head fl_profs[ICE_BLK_COUNT];\n+\tstruct mutex rss_locks;\t/* protect RSS configuration */\n+\tstruct list_head rss_list_head;\n };\n \n /* Statistics collected by each port, VSI, VEB, and S-channel */\n", "prefixes": [ "S36", "1/8" ] }