get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 862513,
    "url": "http://patchwork.ozlabs.org/api/patches/862513/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20180117161607.49344-12-avinash.dayanand@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": "<20180117161607.49344-12-avinash.dayanand@intel.com>",
    "list_archive_url": null,
    "date": "2018-01-17T16:16:06",
    "name": "[v2,next-queue,11/12] i40evf: Add support to apply cloud filters",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "7b554d472dae922b016d95361dad97fdcc304ad2",
    "submitter": {
        "id": 67689,
        "url": "http://patchwork.ozlabs.org/api/people/67689/?format=api",
        "name": "Dayanand, Avinash",
        "email": "avinash.dayanand@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/20180117161607.49344-12-avinash.dayanand@intel.com/mbox/",
    "series": [
        {
            "id": 23980,
            "url": "http://patchwork.ozlabs.org/api/series/23980/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=23980",
            "date": "2018-01-17T16:15:55",
            "name": "Enable queue channel and cloud filter support on i40evf",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/23980/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/862513/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/862513/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.133; helo=hemlock.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)",
        "Received": [
            "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3zMH0m34rNz9t4B\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 18 Jan 2018 06:17:44 +1100 (AEDT)",
            "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id EB3AA898B3;\n\tWed, 17 Jan 2018 19:17:42 +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 Nb7seP2IIJiI; Wed, 17 Jan 2018 19:17:33 +0000 (UTC)",
            "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 9C6FB89B4C;\n\tWed, 17 Jan 2018 19:17:33 +0000 (UTC)",
            "from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n\tby ash.osuosl.org (Postfix) with ESMTP id 782791C156B\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed, 17 Jan 2018 19:17:27 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 73C3D893EC\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed, 17 Jan 2018 19:17:27 +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 dFx-1y-96HcN for <intel-wired-lan@lists.osuosl.org>;\n\tWed, 17 Jan 2018 19:17:25 +0000 (UTC)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby whitealder.osuosl.org (Postfix) with ESMTPS id 8487B89422\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed, 17 Jan 2018 19:17:25 +0000 (UTC)",
            "from fmsmga005.fm.intel.com ([10.253.24.32])\n\tby orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t17 Jan 2018 11:17:25 -0800",
            "from avi-linux2.jf.intel.com ([10.166.244.156])\n\tby fmsmga005.fm.intel.com with ESMTP; 17 Jan 2018 11:17:24 -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.46,372,1511856000\"; d=\"scan'208\";a=\"196382234\"",
        "From": "Avinash Dayanand <avinash.dayanand@intel.com>",
        "To": "intel-wired-lan@lists.osuosl.org",
        "Date": "Wed, 17 Jan 2018 08:16:06 -0800",
        "Message-Id": "<20180117161607.49344-12-avinash.dayanand@intel.com>",
        "X-Mailer": "git-send-email 2.9.4",
        "In-Reply-To": "<20180117161607.49344-1-avinash.dayanand@intel.com>",
        "References": "<20180117161607.49344-1-avinash.dayanand@intel.com>",
        "Subject": "[Intel-wired-lan] [PATCH v2 next-queue 11/12] i40evf: Add support\n\tto apply cloud filters",
        "X-BeenThere": "intel-wired-lan@osuosl.org",
        "X-Mailman-Version": "2.1.24",
        "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>",
        "MIME-Version": "1.0",
        "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": "From: Harshitha Ramamurthy <harshitha.ramamurthy@intel.com>\n\nThis patch enables a tc filter to be applied as a cloud\nfilter for the VF. This patch adds functions which parse the\ntc filter, extract the necessary fields needed to configure the\nfilter and package them in a virtchnl message to be sent to the\nPF to apply them.\n\nv2: made i40evf_print_cloud_filter function static.\n\nSigned-off-by: Harshitha Ramamurthy <harshitha.ramamurthy@intel.com>\n---\n drivers/net/ethernet/intel/i40evf/i40evf.h         |  48 ++\n drivers/net/ethernet/intel/i40evf/i40evf_main.c    | 574 ++++++++++++++++++++-\n .../net/ethernet/intel/i40evf/i40evf_virtchnl.c    | 187 +++++++\n 3 files changed, 805 insertions(+), 4 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h\nindex 150d676..e46555a 100644\n--- a/drivers/net/ethernet/intel/i40evf/i40evf.h\n+++ b/drivers/net/ethernet/intel/i40evf/i40evf.h\n@@ -54,6 +54,8 @@\n #include <net/ip6_checksum.h>\n #include <net/pkt_cls.h>\n #include <net/udp.h>\n+#include <net/tc_act/tc_gact.h>\n+#include <net/tc_act/tc_mirred.h>\n \n #include \"i40e_type.h\"\n #include <linux/avf/virtchnl.h>\n@@ -184,6 +186,14 @@ struct i40evf_channel_config {\n \tu8 total_qps;\n };\n \n+/* State of cloud filter */\n+enum i40evf_cloud_filter_state_t {\n+\t__I40EVF_CF_INVALID,\t /* cloud filter not added */\n+\t__I40EVF_CF_ADD_PENDING, /* cloud filter pending add by the PF */\n+\t__I40EVF_CF_DEL_PENDING, /* cloud filter pending del by the PF */\n+\t__I40EVF_CF_ACTIVE,\t /* cloud filter is active */\n+};\n+\n /* Driver state. The order of these is important! */\n enum i40evf_state_t {\n \t__I40EVF_STARTUP,\t\t/* driver loaded, probe complete */\n@@ -205,6 +215,36 @@ enum i40evf_critical_section_t {\n \t__I40EVF_IN_REMOVE_TASK,\t/* device being removed */\n };\n \n+#define I40EVF_CLOUD_FIELD_OMAC\t\t0x01\n+#define I40EVF_CLOUD_FIELD_IMAC\t\t0x02\n+#define I40EVF_CLOUD_FIELD_IVLAN\t0x04\n+#define I40EVF_CLOUD_FIELD_TEN_ID\t0x08\n+#define I40EVF_CLOUD_FIELD_IIP\t\t0x10\n+\n+#define I40EVF_CF_FLAGS_OMAC\tI40EVF_CLOUD_FIELD_OMAC\n+#define I40EVF_CF_FLAGS_IMAC\tI40EVF_CLOUD_FIELD_IMAC\n+#define I40EVF_CF_FLAGS_IMAC_IVLAN\t(I40EVF_CLOUD_FIELD_IMAC |\\\n+\t\t\t\t\t I40EVF_CLOUD_FIELD_IVLAN)\n+#define I40EVF_CF_FLAGS_IMAC_TEN_ID\t(I40EVF_CLOUD_FIELD_IMAC |\\\n+\t\t\t\t\t I40EVF_CLOUD_FIELD_TEN_ID)\n+#define I40EVF_CF_FLAGS_OMAC_TEN_ID_IMAC\t(I40EVF_CLOUD_FIELD_OMAC |\\\n+\t\t\t\t\t\t I40EVF_CLOUD_FIELD_IMAC |\\\n+\t\t\t\t\t\t I40EVF_CLOUD_FIELD_TEN_ID)\n+#define I40EVF_CF_FLAGS_IMAC_IVLAN_TEN_ID\t(I40EVF_CLOUD_FIELD_IMAC |\\\n+\t\t\t\t\t\t I40EVF_CLOUD_FIELD_IVLAN |\\\n+\t\t\t\t\t\t I40EVF_CLOUD_FIELD_TEN_ID)\n+#define I40EVF_CF_FLAGS_IIP\tI40E_CLOUD_FIELD_IIP\n+\n+/* bookkeeping of cloud filters */\n+struct i40evf_cloud_filter {\n+\tenum i40evf_cloud_filter_state_t state;\n+\tstruct list_head list;\n+\tstruct virtchnl_filter f;\n+\tunsigned long cookie;\n+\tbool del;\t\t/* filter needs to be deleted */\n+\tbool add;\t\t/* filter needs to be added */\n+};\n+\n /* board specific private data structure */\n struct i40evf_adapter {\n \tstruct timer_list watchdog_timer;\n@@ -287,6 +327,8 @@ struct i40evf_adapter {\n #define I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING\tBIT(20)\n #define I40EVF_FLAG_AQ_ENABLE_CHANNELS\t\tBIT(21)\n #define I40EVF_FLAG_AQ_DISABLE_CHANNELS\t\tBIT(22)\n+#define I40EVF_FLAG_AQ_ADD_CLOUD_FILTER\t\tBIT(23)\n+#define I40EVF_FLAG_AQ_DEL_CLOUD_FILTER\t\tBIT(24)\n \n \t/* OS defined structs */\n \tstruct net_device *netdev;\n@@ -335,6 +377,10 @@ struct i40evf_adapter {\n \t/* ADQ related members */\n \tstruct i40evf_channel_config ch_config;\n \tu8 num_tc;\n+\tstruct list_head cloud_filter_list;\n+\t/* lock to protest access to the cloud filter list */\n+\tspinlock_t cloud_filter_list_lock;\n+\tu16 num_cloud_filters;\n };\n \n \n@@ -403,4 +449,6 @@ void i40evf_notify_client_open(struct i40e_vsi *vsi);\n void i40evf_notify_client_close(struct i40e_vsi *vsi, bool reset);\n void i40evf_enable_channels(struct i40evf_adapter *adapter);\n void i40evf_disable_channels(struct i40evf_adapter *adapter);\n+void i40evf_add_cloud_filter(struct i40evf_adapter *adapter);\n+void i40evf_del_cloud_filter(struct i40evf_adapter *adapter);\n #endif /* _I40EVF_H_ */\ndiff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c\nindex 91fff5f..f78ed62 100644\n--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c\n+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c\n@@ -1028,6 +1028,7 @@ void i40evf_down(struct i40evf_adapter *adapter)\n {\n \tstruct net_device *netdev = adapter->netdev;\n \tstruct i40evf_mac_filter *f;\n+\tstruct i40evf_cloud_filter *cf;\n \n \tif (adapter->state <= __I40EVF_DOWN_PENDING)\n \t\treturn;\n@@ -1051,6 +1052,13 @@ void i40evf_down(struct i40evf_adapter *adapter)\n \n \tspin_unlock_bh(&adapter->mac_vlan_list_lock);\n \n+\t/* remove all cloud filters */\n+\tspin_lock_bh(&adapter->cloud_filter_list_lock);\n+\tlist_for_each_entry(cf, &adapter->cloud_filter_list, list) {\n+\t\tcf->del = true;\n+\t}\n+\tspin_unlock_bh(&adapter->cloud_filter_list_lock);\n+\n \tif (!(adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) &&\n \t    adapter->state != __I40EVF_RESETTING) {\n \t\t/* cancel any current operation */\n@@ -1061,6 +1069,7 @@ void i40evf_down(struct i40evf_adapter *adapter)\n \t\t */\n \t\tadapter->aq_required = I40EVF_FLAG_AQ_DEL_MAC_FILTER;\n \t\tadapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER;\n+\t\tadapter->aq_required |= I40EVF_FLAG_AQ_DEL_CLOUD_FILTER;\n \t\tadapter->aq_required |= I40EVF_FLAG_AQ_DISABLE_QUEUES;\n \t}\n \n@@ -1738,6 +1747,16 @@ static void i40evf_watchdog_task(struct work_struct *work)\n \t\tgoto watchdog_done;\n \t}\n \n+\tif (adapter->aq_required & I40EVF_FLAG_AQ_ADD_CLOUD_FILTER) {\n+\t\ti40evf_add_cloud_filter(adapter);\n+\t\tgoto watchdog_done;\n+\t}\n+\n+\tif (adapter->aq_required & I40EVF_FLAG_AQ_DEL_CLOUD_FILTER) {\n+\t\ti40evf_del_cloud_filter(adapter);\n+\t\tgoto watchdog_done;\n+\t}\n+\n \tschedule_delayed_work(&adapter->client_task, msecs_to_jiffies(5));\n \n \tif (adapter->state == __I40EVF_RUNNING)\n@@ -1761,6 +1780,7 @@ static void i40evf_disable_vf(struct i40evf_adapter *adapter)\n {\n \tstruct i40evf_mac_filter *f, *ftmp;\n \tstruct i40evf_vlan_filter *fv, *fvtmp;\n+\tstruct i40evf_cloud_filter *cf, *cftmp;\n \n \tadapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;\n \n@@ -1782,7 +1802,7 @@ static void i40evf_disable_vf(struct i40evf_adapter *adapter)\n \n \tspin_lock_bh(&adapter->mac_vlan_list_lock);\n \n-\t/* Delete all of the filters, both MAC and VLAN. */\n+\t/* Delete all of the filters */\n \tlist_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {\n \t\tlist_del(&f->list);\n \t\tkfree(f);\n@@ -1795,6 +1815,14 @@ static void i40evf_disable_vf(struct i40evf_adapter *adapter)\n \n \tspin_unlock_bh(&adapter->mac_vlan_list_lock);\n \n+\tspin_lock_bh(&adapter->cloud_filter_list_lock);\n+\tlist_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list, list) {\n+\t\tlist_del(&cf->list);\n+\t\tkfree(cf);\n+\t\tadapter->num_cloud_filters--;\n+\t}\n+\tspin_unlock_bh(&adapter->cloud_filter_list_lock);\n+\n \ti40evf_free_misc_irq(adapter);\n \ti40evf_reset_interrupt_capability(adapter);\n \ti40evf_free_queues(adapter);\n@@ -1824,9 +1852,11 @@ static void i40evf_reset_task(struct work_struct *work)\n \tstruct i40evf_adapter *adapter = container_of(work,\n \t\t\t\t\t\t      struct i40evf_adapter,\n \t\t\t\t\t\t      reset_task);\n+\tstruct virtchnl_vf_resource *vfres = adapter->vf_res;\n \tstruct net_device *netdev = adapter->netdev;\n \tstruct i40e_hw *hw = &adapter->hw;\n \tstruct i40evf_vlan_filter *vlf;\n+\tstruct i40evf_cloud_filter *cf;\n \tstruct i40evf_mac_filter *f;\n \tu32 reg_val;\n \tint i = 0, err;\n@@ -1951,8 +1981,19 @@ static void i40evf_reset_task(struct work_struct *work)\n \n \tspin_unlock_bh(&adapter->mac_vlan_list_lock);\n \n+\t/* check if TCs are running and re-add all cloud filters */\n+\tspin_lock_bh(&adapter->cloud_filter_list_lock);\n+\tif ((vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&\n+\t    adapter->num_tc) {\n+\t\tlist_for_each_entry(cf, &adapter->cloud_filter_list, list) {\n+\t\t\tcf->add = true;\n+\t\t}\n+\t}\n+\tspin_unlock_bh(&adapter->cloud_filter_list_lock);\n+\n \tadapter->aq_required |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;\n \tadapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER;\n+\tadapter->aq_required |= I40EVF_FLAG_AQ_ADD_CLOUD_FILTER;\n \ti40evf_misc_irq_enable(adapter);\n \n \tmod_timer(&adapter->watchdog_timer, jiffies + 2);\n@@ -2303,6 +2344,24 @@ static int i40evf_validate_ch_config(struct i40evf_adapter *adapter,\n }\n \n /**\n+ * i40evf_del_all_cloud_filters - delete all cloud filters\n+ * on the traffic classes\n+ **/\n+static void i40evf_del_all_cloud_filters(struct i40evf_adapter *adapter)\n+{\n+\tstruct i40evf_cloud_filter *cf, *cftmp;\n+\n+\tspin_lock_bh(&adapter->cloud_filter_list_lock);\n+\tlist_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list,\n+\t\t\t\t list) {\n+\t\tlist_del(&cf->list);\n+\t\tkfree(cf);\n+\t\tadapter->num_cloud_filters--;\n+\t}\n+\tspin_unlock_bh(&adapter->cloud_filter_list_lock);\n+}\n+\n+/**\n  * __i40evf_setup_tc - configure multiple traffic classes\n  * @netdev: network interface device structure\n  * @type_date: tc offload data\n@@ -2335,6 +2394,7 @@ static int __i40evf_setup_tc(struct net_device *netdev, void *type_data)\n \t\t\tadapter->num_tc = 0;\n \t\t\tnetif_tx_stop_all_queues(netdev);\n \t\t\tnetif_tx_disable(netdev);\n+\t\t\ti40evf_del_all_cloud_filters(adapter);\n \t\t\tadapter->aq_required = I40EVF_FLAG_AQ_DISABLE_CHANNELS;\n \t\t\tgoto exit;\n \t\t} else {\n@@ -2400,6 +2460,495 @@ static int __i40evf_setup_tc(struct net_device *netdev, void *type_data)\n }\n \n /**\n+ * i40evf_parse_cls_flower - Parse tc flower filters provided by kernel\n+ * @adapter: board private structure\n+ * @cls_flower: pointer to struct tc_cls_flower_offload\n+ * @filter: pointer to cloud filter structure\n+ */\n+static int i40evf_parse_cls_flower(struct i40evf_adapter *adapter,\n+\t\t\t\t   struct tc_cls_flower_offload *f,\n+\t\t\t\t   struct i40evf_cloud_filter *filter)\n+{\n+\tu16 n_proto_mask = 0;\n+\tu16 n_proto_key = 0;\n+\tu8 field_flags = 0;\n+\tu16 addr_type = 0;\n+\tu16 n_proto = 0;\n+\tint i = 0;\n+\n+\tif (f->dissector->used_keys &\n+\t    ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |\n+\t      BIT(FLOW_DISSECTOR_KEY_BASIC) |\n+\t      BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |\n+\t      BIT(FLOW_DISSECTOR_KEY_VLAN) |\n+\t      BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |\n+\t      BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |\n+\t      BIT(FLOW_DISSECTOR_KEY_PORTS) |\n+\t      BIT(FLOW_DISSECTOR_KEY_ENC_KEYID))) {\n+\t\tdev_err(&adapter->pdev->dev, \"Unsupported key used: 0x%x\\n\",\n+\t\t\tf->dissector->used_keys);\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+\n+\tif (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {\n+\t\tstruct flow_dissector_key_keyid *mask =\n+\t\t\tskb_flow_dissector_target(f->dissector,\n+\t\t\t\t\t\t  FLOW_DISSECTOR_KEY_ENC_KEYID,\n+\t\t\t\t\t\t  f->mask);\n+\n+\t\tif (mask->keyid != 0)\n+\t\t\tfield_flags |= I40EVF_CLOUD_FIELD_TEN_ID;\n+\t}\n+\n+\tif (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {\n+\t\tstruct flow_dissector_key_basic *key =\n+\t\t\tskb_flow_dissector_target(f->dissector,\n+\t\t\t\t\t\t  FLOW_DISSECTOR_KEY_BASIC,\n+\t\t\t\t\t\t  f->key);\n+\n+\t\tstruct flow_dissector_key_basic *mask =\n+\t\t\tskb_flow_dissector_target(f->dissector,\n+\t\t\t\t\t\t  FLOW_DISSECTOR_KEY_BASIC,\n+\t\t\t\t\t\t  f->mask);\n+\t\tn_proto_key = ntohs(key->n_proto);\n+\t\tn_proto_mask = ntohs(mask->n_proto);\n+\n+\t\tif (n_proto_key == ETH_P_ALL) {\n+\t\t\tn_proto_key = 0;\n+\t\t\tn_proto_mask = 0;\n+\t\t}\n+\t\tn_proto = n_proto_key & n_proto_mask;\n+\t\tif (n_proto != ETH_P_IP && n_proto != ETH_P_IPV6)\n+\t\t\treturn -EINVAL;\n+\t\tif (n_proto == ETH_P_IPV6) {\n+\t\t\t/* specify flow type as TCP IPv6 */\n+\t\t\tfilter->f.flow_type = VIRTCHNL_TCP_V6_FLOW;\n+\t\t}\n+\n+\t\tif (key->ip_proto != IPPROTO_TCP) {\n+\t\t\tdev_info(&adapter->pdev->dev, \"Only TCP transport is supported\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\tif (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {\n+\t\tstruct flow_dissector_key_eth_addrs *key =\n+\t\t\tskb_flow_dissector_target(f->dissector,\n+\t\t\t\t\t\t  FLOW_DISSECTOR_KEY_ETH_ADDRS,\n+\t\t\t\t\t\t  f->key);\n+\n+\t\tstruct flow_dissector_key_eth_addrs *mask =\n+\t\t\tskb_flow_dissector_target(f->dissector,\n+\t\t\t\t\t\t  FLOW_DISSECTOR_KEY_ETH_ADDRS,\n+\t\t\t\t\t\t  f->mask);\n+\t\t/* use is_broadcast and is_zero to check for all 0xf or 0 */\n+\t\tif (!is_zero_ether_addr(mask->dst)) {\n+\t\t\tif (is_broadcast_ether_addr(mask->dst)) {\n+\t\t\t\tfield_flags |= I40EVF_CLOUD_FIELD_OMAC;\n+\t\t\t} else {\n+\t\t\t\tdev_err(&adapter->pdev->dev, \"Bad ether dest mask %pM\\n\",\n+\t\t\t\t\tmask->dst);\n+\t\t\t\treturn I40E_ERR_CONFIG;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (!is_zero_ether_addr(mask->src)) {\n+\t\t\tif (is_broadcast_ether_addr(mask->src)) {\n+\t\t\t\tfield_flags |= I40EVF_CLOUD_FIELD_IMAC;\n+\t\t\t} else {\n+\t\t\t\tdev_err(&adapter->pdev->dev, \"Bad ether src mask %pM\\n\",\n+\t\t\t\t\tmask->src);\n+\t\t\t\treturn I40E_ERR_CONFIG;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (!is_zero_ether_addr(key->dst))\n+\t\t\tif (is_valid_ether_addr(key->dst) ||\n+\t\t\t    is_multicast_ether_addr(key->dst)) {\n+\t\t\t\t/* set the mask if a valid dst_mac address */\n+\t\t\t\tfor (i = 0; i < ETH_ALEN; i++)\n+\t\t\t\t\tfilter->f.mask.tcp_spec.dst_mac[i] |=\n+\t\t\t\t\t\t\t\t\t0xff;\n+\t\t\t\tether_addr_copy(filter->f.data.tcp_spec.dst_mac,\n+\t\t\t\t\t\tkey->dst);\n+\t\t\t}\n+\n+\t\tif (!is_zero_ether_addr(key->src))\n+\t\t\tif (is_valid_ether_addr(key->src) ||\n+\t\t\t    is_multicast_ether_addr(key->src)) {\n+\t\t\t\t/* set the mask if a valid dst_mac address */\n+\t\t\t\tfor (i = 0; i < ETH_ALEN; i++)\n+\t\t\t\t\tfilter->f.mask.tcp_spec.src_mac[i] |=\n+\t\t\t\t\t\t\t\t\t0xff;\n+\t\t\t\tether_addr_copy(filter->f.data.tcp_spec.src_mac,\n+\t\t\t\t\t\tkey->src);\n+\t\t}\n+\t}\n+\n+\tif (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {\n+\t\tstruct flow_dissector_key_vlan *key =\n+\t\t\tskb_flow_dissector_target(f->dissector,\n+\t\t\t\t\t\t  FLOW_DISSECTOR_KEY_VLAN,\n+\t\t\t\t\t\t  f->key);\n+\t\tstruct flow_dissector_key_vlan *mask =\n+\t\t\tskb_flow_dissector_target(f->dissector,\n+\t\t\t\t\t\t  FLOW_DISSECTOR_KEY_VLAN,\n+\t\t\t\t\t\t  f->mask);\n+\n+\t\tif (mask->vlan_id) {\n+\t\t\tif (mask->vlan_id == VLAN_VID_MASK) {\n+\t\t\t\tfield_flags |= I40EVF_CLOUD_FIELD_IVLAN;\n+\t\t\t} else {\n+\t\t\t\tdev_err(&adapter->pdev->dev, \"Bad vlan mask %u\\n\",\n+\t\t\t\t\tmask->vlan_id);\n+\t\t\t\treturn I40E_ERR_CONFIG;\n+\t\t\t}\n+\t\t}\n+\t\tfilter->f.mask.tcp_spec.vlan_id |= 0xffff;\n+\t\tfilter->f.data.tcp_spec.vlan_id = cpu_to_be16(key->vlan_id);\n+\t}\n+\n+\tif (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {\n+\t\tstruct flow_dissector_key_control *key =\n+\t\t\tskb_flow_dissector_target(f->dissector,\n+\t\t\t\t\t\t  FLOW_DISSECTOR_KEY_CONTROL,\n+\t\t\t\t\t\t  f->key);\n+\n+\t\taddr_type = key->addr_type;\n+\t}\n+\n+\tif (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {\n+\t\tstruct flow_dissector_key_ipv4_addrs *key =\n+\t\t\tskb_flow_dissector_target(f->dissector,\n+\t\t\t\t\t\t  FLOW_DISSECTOR_KEY_IPV4_ADDRS,\n+\t\t\t\t\t\t  f->key);\n+\t\tstruct flow_dissector_key_ipv4_addrs *mask =\n+\t\t\tskb_flow_dissector_target(f->dissector,\n+\t\t\t\t\t\t  FLOW_DISSECTOR_KEY_IPV4_ADDRS,\n+\t\t\t\t\t\t  f->mask);\n+\n+\t\tif (mask->dst) {\n+\t\t\tif (mask->dst == cpu_to_be32(0xffffffff)) {\n+\t\t\t\tfield_flags |= I40EVF_CLOUD_FIELD_IIP;\n+\t\t\t} else {\n+\t\t\t\tdev_err(&adapter->pdev->dev, \"Bad ip dst mask 0x%08x\\n\",\n+\t\t\t\t\tbe32_to_cpu(mask->dst));\n+\t\t\t\treturn I40E_ERR_CONFIG;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (mask->src) {\n+\t\t\tif (mask->src == cpu_to_be32(0xffffffff)) {\n+\t\t\t\tfield_flags |= I40EVF_CLOUD_FIELD_IIP;\n+\t\t\t} else {\n+\t\t\t\tdev_err(&adapter->pdev->dev, \"Bad ip src mask 0x%08x\\n\",\n+\t\t\t\t\tbe32_to_cpu(mask->dst));\n+\t\t\t\treturn I40E_ERR_CONFIG;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (field_flags & I40EVF_CLOUD_FIELD_TEN_ID) {\n+\t\t\tdev_info(&adapter->pdev->dev, \"Tenant id not allowed for ip filter\\n\");\n+\t\t\treturn I40E_ERR_CONFIG;\n+\t\t}\n+\t\tif (key->dst) {\n+\t\t\tfilter->f.mask.tcp_spec.dst_ip[0] |= 0xffffffff;\n+\t\t\tfilter->f.data.tcp_spec.dst_ip[0] = key->dst;\n+\t\t}\n+\t\tif (key->src) {\n+\t\t\tfilter->f.mask.tcp_spec.src_ip[0] |= 0xffffffff;\n+\t\t\tfilter->f.data.tcp_spec.src_ip[0] = key->src;\n+\t\t}\n+\t}\n+\n+\tif (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {\n+\t\tstruct flow_dissector_key_ipv6_addrs *key =\n+\t\t\tskb_flow_dissector_target(f->dissector,\n+\t\t\t\t\t\t  FLOW_DISSECTOR_KEY_IPV6_ADDRS,\n+\t\t\t\t\t\t  f->key);\n+\t\tstruct flow_dissector_key_ipv6_addrs *mask =\n+\t\t\tskb_flow_dissector_target(f->dissector,\n+\t\t\t\t\t\t  FLOW_DISSECTOR_KEY_IPV6_ADDRS,\n+\t\t\t\t\t\t  f->mask);\n+\n+\t\t/* validate mask, make sure it is not IPV6_ADDR_ANY */\n+\t\tif (ipv6_addr_any(&mask->dst)) {\n+\t\t\tdev_err(&adapter->pdev->dev, \"Bad ipv6 dst mask 0x%02x\\n\",\n+\t\t\t\tIPV6_ADDR_ANY);\n+\t\t\treturn I40E_ERR_CONFIG;\n+\t\t}\n+\n+\t\t/* src and dest IPv6 address should not be LOOPBACK\n+\t\t * (0:0:0:0:0:0:0:1) which can be represented as ::1\n+\t\t */\n+\t\tif (ipv6_addr_loopback(&key->dst) ||\n+\t\t    ipv6_addr_loopback(&key->src)) {\n+\t\t\tdev_err(&adapter->pdev->dev,\n+\t\t\t\t\"ipv6 addr should not be loopback\\n\");\n+\t\t\treturn I40E_ERR_CONFIG;\n+\t\t}\n+\t\tif (!ipv6_addr_any(&mask->dst) || !ipv6_addr_any(&mask->src))\n+\t\t\tfield_flags |= I40EVF_CLOUD_FIELD_IIP;\n+\n+\t\tif (key->dst.s6_addr) {\n+\t\t\tfor (i = 0; i < 4; i++)\n+\t\t\t\tfilter->f.mask.tcp_spec.dst_ip[i] |= 0xffffffff;\n+\t\t\tmemcpy(&filter->f.data.tcp_spec.dst_ip,\n+\t\t\t       &key->dst.s6_addr32,\n+\t\t\t       sizeof(filter->f.data.tcp_spec.dst_ip));\n+\t\t}\n+\t\tif (key->src.s6_addr) {\n+\t\t\tfor (i = 0; i < 4; i++)\n+\t\t\t\tfilter->f.mask.tcp_spec.src_ip[i] |= 0xffffffff;\n+\t\t\tmemcpy(&filter->f.data.tcp_spec.src_ip,\n+\t\t\t       &key->src.s6_addr32,\n+\t\t\t       sizeof(filter->f.data.tcp_spec.src_ip));\n+\t\t}\n+\t}\n+\tif (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {\n+\t\tstruct flow_dissector_key_ports *key =\n+\t\t\tskb_flow_dissector_target(f->dissector,\n+\t\t\t\t\t\t  FLOW_DISSECTOR_KEY_PORTS,\n+\t\t\t\t\t\t  f->key);\n+\t\tstruct flow_dissector_key_ports *mask =\n+\t\t\tskb_flow_dissector_target(f->dissector,\n+\t\t\t\t\t\t  FLOW_DISSECTOR_KEY_PORTS,\n+\t\t\t\t\t\t  f->mask);\n+\n+\t\tif (mask->src) {\n+\t\t\tif (mask->src == cpu_to_be16(0xffff)) {\n+\t\t\t\tfield_flags |= I40EVF_CLOUD_FIELD_IIP;\n+\t\t\t} else {\n+\t\t\t\tdev_err(&adapter->pdev->dev, \"Bad src port mask %u\\n\",\n+\t\t\t\t\tbe16_to_cpu(mask->src));\n+\t\t\t\treturn I40E_ERR_CONFIG;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (mask->dst) {\n+\t\t\tif (mask->dst == cpu_to_be16(0xffff)) {\n+\t\t\t\tfield_flags |= I40EVF_CLOUD_FIELD_IIP;\n+\t\t\t} else {\n+\t\t\t\tdev_err(&adapter->pdev->dev, \"Bad dst port mask %u\\n\",\n+\t\t\t\t\tbe16_to_cpu(mask->dst));\n+\t\t\t\treturn I40E_ERR_CONFIG;\n+\t\t\t}\n+\t\t}\n+\t\tif (key->dst) {\n+\t\t\tfilter->f.mask.tcp_spec.dst_port |= 0xffff;\n+\t\t\tfilter->f.data.tcp_spec.dst_port = key->dst;\n+\t\t}\n+\n+\t\tif (key->src) {\n+\t\t\tfilter->f.mask.tcp_spec.src_port |= 0xffff;\n+\t\t\tfilter->f.data.tcp_spec.src_port = key->dst;\n+\t\t}\n+\t}\n+\tfilter->f.field_flags = field_flags;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * i40evf_handle_tclass - Forward to a traffic class on the device\n+ * @adapter: board private structure\n+ * @tc: traffic class index on the device\n+ * @filter: pointer to cloud filter structure\n+ */\n+static int i40evf_handle_tclass(struct i40evf_adapter *adapter, u32 tc,\n+\t\t\t\tstruct i40evf_cloud_filter *filter)\n+{\n+\tif (tc == 0)\n+\t\treturn 0;\n+\tif (tc < adapter->num_tc) {\n+\t\tif (!filter->f.data.tcp_spec.dst_port) {\n+\t\t\tdev_err(&adapter->pdev->dev,\n+\t\t\t\t\"Specify destination port to redirect to traffic class other than TC0\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\t/* redirect to a traffic class on the same device */\n+\tfilter->f.action = VIRTCHNL_ACTION_TC_REDIRECT;\n+\tfilter->f.action_meta = tc;\n+\treturn 0;\n+}\n+\n+/**\n+ * i40evf_configure_clsflower - Add tc flower filters\n+ * @adapter: board private structure\n+ * @cls_flower: Pointer to struct tc_cls_flower_offload\n+ */\n+static int i40evf_configure_clsflower(struct i40evf_adapter *adapter,\n+\t\t\t\t      struct tc_cls_flower_offload *cls_flower)\n+{\n+\tint tc = tc_classid_to_hwtc(adapter->netdev, cls_flower->classid);\n+\tstruct i40evf_cloud_filter *filter = NULL;\n+\tint err = 0, count = 50;\n+\n+\twhile (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,\n+\t\t\t\t&adapter->crit_section)) {\n+\t\tudelay(1);\n+\t\tif (--count == 0)\n+\t\t\treturn -EINVAL;\n+\t}\n+\n+\tif (tc < 0) {\n+\t\tdev_err(&adapter->pdev->dev, \"Invalid traffic class\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfilter = kzalloc(sizeof(*filter), GFP_KERNEL);\n+\tif (!filter) {\n+\t\terr = -ENOMEM;\n+\t\tgoto clearout;\n+\t}\n+\tfilter->cookie = cls_flower->cookie;\n+\n+\t/* set the mask to all zeroes to begin with */\n+\tmemset(&filter->f.mask.tcp_spec, 0, sizeof(struct virtchnl_l4_spec));\n+\t/* start out with flow type and eth type IPv4 to begin with */\n+\tfilter->f.flow_type = VIRTCHNL_TCP_V4_FLOW;\n+\terr = i40evf_parse_cls_flower(adapter, cls_flower, filter);\n+\tif (err < 0)\n+\t\tgoto err;\n+\n+\terr = i40evf_handle_tclass(adapter, tc, filter);\n+\tif (err < 0)\n+\t\tgoto err;\n+\n+\t/* add filter to the list */\n+\tspin_lock_bh(&adapter->cloud_filter_list_lock);\n+\tlist_add_tail(&filter->list, &adapter->cloud_filter_list);\n+\tadapter->num_cloud_filters++;\n+\tfilter->add = true;\n+\tadapter->aq_required |= I40EVF_FLAG_AQ_ADD_CLOUD_FILTER;\n+\tspin_unlock_bh(&adapter->cloud_filter_list_lock);\n+err:\n+\tif (err)\n+\t\tkfree(filter);\n+clearout:\n+\tclear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);\n+\treturn err;\n+}\n+\n+/* i40evf_find_cf - Find the cloud filter in the list\n+ * @adapter: Board private structure\n+ * @cookie: filter specific cookie\n+ *\n+ * Returns ptr to the filter object or NULL. Must be called while holding the\n+ * cloud_filter_list_lock.\n+ */\n+static struct i40evf_cloud_filter *i40evf_find_cf(struct i40evf_adapter *adapter,\n+\t\t\t\t\t\t  unsigned long *cookie)\n+{\n+\tstruct i40evf_cloud_filter *filter = NULL;\n+\n+\tif (!cookie)\n+\t\treturn NULL;\n+\n+\tlist_for_each_entry(filter, &adapter->cloud_filter_list, list) {\n+\t\tif (!memcmp(cookie, &filter->cookie, sizeof(filter->cookie)))\n+\t\t\treturn filter;\n+\t}\n+\treturn NULL;\n+}\n+\n+/**\n+ * i40evf_delete_clsflower - Remove tc flower filters\n+ * @adapter: board private structure\n+ * @cls_flower: Pointer to struct tc_cls_flower_offload\n+ */\n+static int i40evf_delete_clsflower(struct i40evf_adapter *adapter,\n+\t\t\t\t   struct tc_cls_flower_offload *cls_flower)\n+{\n+\tstruct i40evf_cloud_filter *filter = NULL;\n+\tint err = 0;\n+\n+\tspin_lock_bh(&adapter->cloud_filter_list_lock);\n+\tfilter = i40evf_find_cf(adapter, &cls_flower->cookie);\n+\tif (filter) {\n+\t\tfilter->del = true;\n+\t\tadapter->aq_required |= I40EVF_FLAG_AQ_DEL_CLOUD_FILTER;\n+\t} else {\n+\t\terr = -EINVAL;\n+\t}\n+\tspin_unlock_bh(&adapter->cloud_filter_list_lock);\n+\n+\treturn err;\n+}\n+\n+/**\n+ * i40evf_setup_tc_cls_flower - flower classifier offloads\n+ * @netdev: net device to configure\n+ * @type_data: offload data\n+ */\n+static int i40evf_setup_tc_cls_flower(struct i40evf_adapter *adapter,\n+\t\t\t\t      struct tc_cls_flower_offload *cls_flower)\n+{\n+\tif (cls_flower->common.chain_index)\n+\t\treturn -EOPNOTSUPP;\n+\n+\tswitch (cls_flower->command) {\n+\tcase TC_CLSFLOWER_REPLACE:\n+\t\treturn i40evf_configure_clsflower(adapter, cls_flower);\n+\tcase TC_CLSFLOWER_DESTROY:\n+\t\treturn i40evf_delete_clsflower(adapter, cls_flower);\n+\tcase TC_CLSFLOWER_STATS:\n+\t\treturn -EOPNOTSUPP;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+}\n+\n+/**\n+ * i40evf_setup_tc_block_cb - block callback for tc\n+ * @type: type of offload\n+ * @type_data: offload data\n+ * @cb_priv:\n+ *\n+ * This function is the block callback for traffic classes\n+ **/\n+static int i40evf_setup_tc_block_cb(enum tc_setup_type type, void *type_data,\n+\t\t\t\t    void *cb_priv)\n+{\n+\tswitch (type) {\n+\tcase TC_SETUP_CLSFLOWER:\n+\t\treturn i40evf_setup_tc_cls_flower(cb_priv, type_data);\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+}\n+\n+/**\n+ * i40evf_setup_tc_block - register callbacks for tc\n+ * @netdev: network interface device structure\n+ * @f: tc offload data\n+ *\n+ * This function registers block callbacks for tc\n+ * offloads\n+ **/\n+static int i40evf_setup_tc_block(struct net_device *dev,\n+\t\t\t\t struct tc_block_offload *f)\n+{\n+\tstruct i40evf_adapter *adapter = netdev_priv(dev);\n+\n+\tif (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)\n+\t\treturn -EOPNOTSUPP;\n+\n+\tswitch (f->command) {\n+\tcase TC_BLOCK_BIND:\n+\t\treturn tcf_block_cb_register(f->block, i40evf_setup_tc_block_cb,\n+\t\t\t\t\t     adapter, adapter);\n+\tcase TC_BLOCK_UNBIND:\n+\t\ttcf_block_cb_unregister(f->block, i40evf_setup_tc_block_cb,\n+\t\t\t\t\tadapter);\n+\t\treturn 0;\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+}\n+\n+/**\n  * i40evf_setup_tc - configure multiple traffic classes\n  * @netdev: network interface device structure\n  * @type: type of offload\n@@ -2413,10 +2962,14 @@ static int __i40evf_setup_tc(struct net_device *netdev, void *type_data)\n static int i40evf_setup_tc(struct net_device *netdev, enum tc_setup_type type,\n \t\t\t   void *type_data)\n {\n-\tif (type != TC_SETUP_QDISC_MQPRIO)\n+\tswitch (type) {\n+\tcase TC_SETUP_QDISC_MQPRIO:\n+\t\treturn __i40evf_setup_tc(netdev, type_data);\n+\tcase TC_SETUP_BLOCK:\n+\t\treturn i40evf_setup_tc_block(netdev, type_data);\n+\tdefault:\n \t\treturn -EOPNOTSUPP;\n-\n-\treturn __i40evf_setup_tc(netdev, type_data);\n+\t}\n }\n \n /**\n@@ -2801,6 +3354,9 @@ int i40evf_process_config(struct i40evf_adapter *adapter)\n \tif (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)\n \t\thw_features |= (NETIF_F_HW_VLAN_CTAG_TX |\n \t\t\t\tNETIF_F_HW_VLAN_CTAG_RX);\n+\t/* Enable cloud filter if ADQ is supported */\n+\tif (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ)\n+\t\thw_features |= NETIF_F_HW_TC;\n \n \tnetdev->hw_features |= hw_features;\n \n@@ -3168,9 +3724,11 @@ static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\n \tmutex_init(&hw->aq.arq_mutex);\n \n \tspin_lock_init(&adapter->mac_vlan_list_lock);\n+\tspin_lock_init(&adapter->cloud_filter_list_lock);\n \n \tINIT_LIST_HEAD(&adapter->mac_filter_list);\n \tINIT_LIST_HEAD(&adapter->vlan_filter_list);\n+\tINIT_LIST_HEAD(&adapter->cloud_filter_list);\n \n \tINIT_WORK(&adapter->reset_task, i40evf_reset_task);\n \tINIT_WORK(&adapter->adminq_task, i40evf_adminq_task);\n@@ -3296,6 +3854,7 @@ static void i40evf_remove(struct pci_dev *pdev)\n \tstruct net_device *netdev = pci_get_drvdata(pdev);\n \tstruct i40evf_adapter *adapter = netdev_priv(netdev);\n \tstruct i40evf_mac_filter *f, *ftmp;\n+\tstruct i40evf_cloud_filter *cf, *cftmp;\n \tstruct i40e_hw *hw = &adapter->hw;\n \tint err;\n \t/* Indicate we are in remove and not to run reset_task */\n@@ -3365,6 +3924,13 @@ static void i40evf_remove(struct pci_dev *pdev)\n \n \tspin_unlock_bh(&adapter->mac_vlan_list_lock);\n \n+\tspin_lock_bh(&adapter->cloud_filter_list_lock);\n+\tlist_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list, list) {\n+\t\tlist_del(&cf->list);\n+\t\tkfree(cf);\n+\t}\n+\tspin_unlock_bh(&adapter->cloud_filter_list_lock);\n+\n \tfree_netdev(netdev);\n \n \tpci_disable_pcie_error_reporting(pdev);\ndiff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c\nindex b5a509f..61cae3b 100644\n--- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c\n+++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c\n@@ -1041,6 +1041,134 @@ void i40evf_disable_channels(struct i40evf_adapter *adapter)\n }\n \n /**\n+ * i40evf_print_cloud_filter\n+ * @adapter: adapter structure\n+ * @f: cloud filter to print\n+ *\n+ * Print the cloud filter\n+ **/\n+static void i40evf_print_cloud_filter(struct i40evf_adapter *adapter,\n+\t\t\t\t      struct virtchnl_filter f)\n+{\n+\tswitch (f.flow_type) {\n+\tcase VIRTCHNL_TCP_V4_FLOW:\n+\t\tdev_info(&adapter->pdev->dev, \"dst_mac: %pM src_mac: %pM vlan_id: %hu dst_ip: %pI4 src_ip %pI4 dst_port %hu src_port %hu\\n\",\n+\t\t\t &f.data.tcp_spec.dst_mac, &f.data.tcp_spec.src_mac,\n+\t\t\t ntohs(f.data.tcp_spec.vlan_id),\n+\t\t\t &f.data.tcp_spec.dst_ip[0], &f.data.tcp_spec.src_ip[0],\n+\t\t\t ntohs(f.data.tcp_spec.dst_port),\n+\t\t\t ntohs(f.data.tcp_spec.src_port));\n+\t\tbreak;\n+\tcase VIRTCHNL_TCP_V6_FLOW:\n+\t\tdev_info(&adapter->pdev->dev, \"dst_mac: %pM src_mac: %pM vlan_id: %hu dst_ip: %pI6 src_ip %pI6 dst_port %hu src_port %hu\\n\",\n+\t\t\t &f.data.tcp_spec.dst_mac, &f.data.tcp_spec.src_mac,\n+\t\t\t ntohs(f.data.tcp_spec.vlan_id),\n+\t\t\t &f.data.tcp_spec.dst_ip, &f.data.tcp_spec.src_ip,\n+\t\t\t ntohs(f.data.tcp_spec.dst_port),\n+\t\t\t ntohs(f.data.tcp_spec.src_port));\n+\t\tbreak;\n+\t}\n+}\n+\n+/**\n+ * i40evf_add_cloud_filter\n+ * @adapter: adapter structure\n+ *\n+ * Request that the PF add cloud filters as specified\n+ * by the user via tc tool.\n+ **/\n+void i40evf_add_cloud_filter(struct i40evf_adapter *adapter)\n+{\n+\tstruct i40evf_cloud_filter *cf;\n+\tstruct virtchnl_filter *f;\n+\tint len = 0, count = 0;\n+\n+\tif (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {\n+\t\t/* bail because we already have a command pending */\n+\t\tdev_err(&adapter->pdev->dev, \"Cannot add cloud filter, command %d pending\\n\",\n+\t\t\tadapter->current_op);\n+\t\treturn;\n+\t}\n+\tlist_for_each_entry(cf, &adapter->cloud_filter_list, list) {\n+\t\tif (cf->add) {\n+\t\t\tcount++;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tif (!count) {\n+\t\tadapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_CLOUD_FILTER;\n+\t\treturn;\n+\t}\n+\tadapter->current_op = VIRTCHNL_OP_ADD_CLOUD_FILTER;\n+\n+\tlen = sizeof(struct virtchnl_filter);\n+\tf = kzalloc(len, GFP_KERNEL);\n+\tif (!f)\n+\t\treturn;\n+\n+\tlist_for_each_entry(cf, &adapter->cloud_filter_list, list) {\n+\t\tif (cf->add) {\n+\t\t\tmemcpy(f, &cf->f, sizeof(struct virtchnl_filter));\n+\t\t\tcf->add = false;\n+\t\t\tcf->state = __I40EVF_CF_ADD_PENDING;\n+\t\t\ti40evf_send_pf_msg(adapter,\n+\t\t\t\t\t   VIRTCHNL_OP_ADD_CLOUD_FILTER,\n+\t\t\t\t\t   (u8 *)f, len);\n+\t\t}\n+\t}\n+\tkfree(f);\n+}\n+\n+/**\n+ * i40evf_del_cloud_filter\n+ * @adapter: adapter structure\n+ *\n+ * Request that the PF delete cloud filters as specified\n+ * by the user via tc tool.\n+ **/\n+void i40evf_del_cloud_filter(struct i40evf_adapter *adapter)\n+{\n+\tstruct i40evf_cloud_filter *cf, *cftmp;\n+\tstruct virtchnl_filter *f;\n+\tint len = 0, count = 0;\n+\n+\tif (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {\n+\t\t/* bail because we already have a command pending */\n+\t\tdev_err(&adapter->pdev->dev, \"Cannot remove cloud filter, command %d pending\\n\",\n+\t\t\tadapter->current_op);\n+\t\treturn;\n+\t}\n+\tlist_for_each_entry(cf, &adapter->cloud_filter_list, list) {\n+\t\tif (cf->del) {\n+\t\t\tcount++;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tif (!count) {\n+\t\tadapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_CLOUD_FILTER;\n+\t\treturn;\n+\t}\n+\tadapter->current_op = VIRTCHNL_OP_DEL_CLOUD_FILTER;\n+\n+\tlen = sizeof(struct virtchnl_filter);\n+\tf = kzalloc(len, GFP_KERNEL);\n+\tif (!f)\n+\t\treturn;\n+\n+\tlist_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list, list) {\n+\t\tif (cf->del) {\n+\t\t\tmemcpy(f, &cf->f, sizeof(struct virtchnl_filter));\n+\t\t\tcf->del = false;\n+\t\t\tcf->state = __I40EVF_CF_DEL_PENDING;\n+\t\t\ti40evf_send_pf_msg(adapter,\n+\t\t\t\t\t   VIRTCHNL_OP_DEL_CLOUD_FILTER,\n+\t\t\t\t\t   (u8 *)f, len);\n+\t\t}\n+\t}\n+\tkfree(f);\n+}\n+\n+/**\n  * i40evf_request_reset\n  * @adapter: adapter structure\n  *\n@@ -1163,6 +1291,42 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,\n \t\t\tadapter->ch_config.state = __I40EVF_TC_RUNNING;\n \t\t\tnetif_tx_start_all_queues(netdev);\n \t\t\tbreak;\n+\t\tcase VIRTCHNL_OP_ADD_CLOUD_FILTER: {\n+\t\t\tstruct i40evf_cloud_filter *cf, *cftmp;\n+\n+\t\t\tlist_for_each_entry_safe(cf, cftmp,\n+\t\t\t\t\t\t &adapter->cloud_filter_list,\n+\t\t\t\t\t\t list) {\n+\t\t\t\tif (cf->state == __I40EVF_CF_ADD_PENDING) {\n+\t\t\t\t\tcf->state = __I40EVF_CF_INVALID;\n+\t\t\t\t\tdev_info(&adapter->pdev->dev, \"Failed to add cloud filter, error %s\\n\",\n+\t\t\t\t\t\t i40evf_stat_str(&adapter->hw,\n+\t\t\t\t\t\t\t\t v_retval));\n+\t\t\t\t\ti40evf_print_cloud_filter(adapter,\n+\t\t\t\t\t\t\t\t  cf->f);\n+\t\t\t\t\tlist_del(&cf->list);\n+\t\t\t\t\tkfree(cf);\n+\t\t\t\t\tadapter->num_cloud_filters--;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase VIRTCHNL_OP_DEL_CLOUD_FILTER: {\n+\t\t\tstruct i40evf_cloud_filter *cf;\n+\n+\t\t\tlist_for_each_entry(cf, &adapter->cloud_filter_list,\n+\t\t\t\t\t    list) {\n+\t\t\t\tif (cf->state == __I40EVF_CF_DEL_PENDING) {\n+\t\t\t\t\tcf->state = __I40EVF_CF_ACTIVE;\n+\t\t\t\t\tdev_info(&adapter->pdev->dev, \"Failed to del cloud filter, error %s\\n\",\n+\t\t\t\t\t\t i40evf_stat_str(&adapter->hw,\n+\t\t\t\t\t\t\t\t v_retval));\n+\t\t\t\t\ti40evf_print_cloud_filter(adapter,\n+\t\t\t\t\t\t\t\t  cf->f);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\t}\n+\t\t\tbreak;\n \t\tdefault:\n \t\t\tdev_err(&adapter->pdev->dev, \"PF returned error %d (%s) to our request %d\\n\",\n \t\t\t\tv_retval,\n@@ -1257,6 +1421,29 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,\n \t\t}\n \t\t}\n \t\tbreak;\n+\tcase VIRTCHNL_OP_ADD_CLOUD_FILTER: {\n+\t\tstruct i40evf_cloud_filter *cf;\n+\n+\t\tlist_for_each_entry(cf, &adapter->cloud_filter_list, list) {\n+\t\t\tif (cf->state == __I40EVF_CF_ADD_PENDING)\n+\t\t\t\tcf->state = __I40EVF_CF_ACTIVE;\n+\t\t}\n+\t\t}\n+\t\tbreak;\n+\tcase VIRTCHNL_OP_DEL_CLOUD_FILTER: {\n+\t\tstruct i40evf_cloud_filter *cf, *cftmp;\n+\n+\t\tlist_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list,\n+\t\t\t\t\t list) {\n+\t\t\tif (cf->state == __I40EVF_CF_DEL_PENDING) {\n+\t\t\t\tcf->state = __I40EVF_CF_INVALID;\n+\t\t\t\tlist_del(&cf->list);\n+\t\t\t\tkfree(cf);\n+\t\t\t\tadapter->num_cloud_filters--;\n+\t\t\t}\n+\t\t}\n+\t\t}\n+\t\tbreak;\n \tdefault:\n \t\tif (adapter->current_op && (v_opcode != adapter->current_op))\n \t\t\tdev_warn(&adapter->pdev->dev, \"Expected response %d from PF, received %d\\n\",\n",
    "prefixes": [
        "v2",
        "next-queue",
        "11/12"
    ]
}