get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 10347,
    "url": "http://patches.dpdk.org/api/patches/10347/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/0dba64de5bbae054db3f807d3b4ed3db00abb9ff.1454408702.git.rahul.lakkireddy@chelsio.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<0dba64de5bbae054db3f807d3b4ed3db00abb9ff.1454408702.git.rahul.lakkireddy@chelsio.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/0dba64de5bbae054db3f807d3b4ed3db00abb9ff.1454408702.git.rahul.lakkireddy@chelsio.com",
    "date": "2016-02-03T08:32:31",
    "name": "[dpdk-dev,10/10] cxgbe: add flow director support and update documentation",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "7d73e59909dbf4a75199c61724fa8aecdb0d797c",
    "submitter": {
        "id": 241,
        "url": "http://patches.dpdk.org/api/people/241/?format=api",
        "name": "Rahul Lakkireddy",
        "email": "rahul.lakkireddy@chelsio.com"
    },
    "delegate": {
        "id": 10,
        "url": "http://patches.dpdk.org/api/users/10/?format=api",
        "username": "bruce",
        "first_name": "Bruce",
        "last_name": "Richardson",
        "email": "bruce.richardson@intel.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/0dba64de5bbae054db3f807d3b4ed3db00abb9ff.1454408702.git.rahul.lakkireddy@chelsio.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/10347/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/10347/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 41686C2DC;\n\tWed,  3 Feb 2016 09:33:12 +0100 (CET)",
            "from stargate3.asicdesigners.com (stargate.chelsio.com\n\t[12.32.117.8]) by dpdk.org (Postfix) with ESMTP id 77DF4C31E\n\tfor <dev@dpdk.org>; Wed,  3 Feb 2016 09:33:10 +0100 (CET)",
            "from localhost (scalar.blr.asicdesigners.com [10.193.185.94])\n\tby stargate3.asicdesigners.com (8.13.8/8.13.8) with ESMTP id\n\tu138X6xN024919; Wed, 3 Feb 2016 00:33:07 -0800"
        ],
        "From": "Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>",
        "To": "dev@dpdk.org",
        "Date": "Wed,  3 Feb 2016 14:02:31 +0530",
        "Message-Id": "<0dba64de5bbae054db3f807d3b4ed3db00abb9ff.1454408702.git.rahul.lakkireddy@chelsio.com>",
        "X-Mailer": "git-send-email 2.5.3",
        "In-Reply-To": [
            "<cover.1454408702.git.rahul.lakkireddy@chelsio.com>",
            "<cover.1454408702.git.rahul.lakkireddy@chelsio.com>"
        ],
        "References": [
            "<cover.1454408702.git.rahul.lakkireddy@chelsio.com>",
            "<cover.1454408702.git.rahul.lakkireddy@chelsio.com>"
        ],
        "Cc": "Kumar Sanghvi <kumaras@chelsio.com>,\n\tNirranjan Kirubaharan <nirranjan@chelsio.com>",
        "Subject": "[dpdk-dev] [PATCH 10/10] cxgbe: add flow director support and\n\tupdate documentation",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Add flow director support for setting/deleting LE-TCAM (maskfull)\nand HASH (maskless) filters.\n\nWait and poll firmware event queue for replies about the filter status.\nAlso, the firware event queue doesn't have any freelists.  So, there is\nno need to refill any.\n\nProvide stats showing the number of remaining free entries, and\nnumber of successful and failed added/deleted filters.\n\nAdd documentation explaining the usage of CXGBE Flow Director support.\n\nSigned-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>\nSigned-off-by: Kumar Sanghvi <kumaras@chelsio.com>\n---\n doc/guides/nics/cxgbe.rst            | 166 ++++++++\n doc/guides/rel_notes/release_2_3.rst |   7 +\n drivers/net/cxgbe/Makefile           |   1 +\n drivers/net/cxgbe/base/adapter.h     |   2 +\n drivers/net/cxgbe/cxgbe.h            |   3 +\n drivers/net/cxgbe/cxgbe_ethdev.c     |  18 +\n drivers/net/cxgbe/cxgbe_fdir.c       | 715 +++++++++++++++++++++++++++++++++++\n drivers/net/cxgbe/cxgbe_fdir.h       | 108 ++++++\n drivers/net/cxgbe/cxgbe_main.c       |  40 ++\n drivers/net/cxgbe/sge.c              |   3 +-\n 10 files changed, 1062 insertions(+), 1 deletion(-)\n create mode 100644 drivers/net/cxgbe/cxgbe_fdir.c\n create mode 100644 drivers/net/cxgbe/cxgbe_fdir.h",
    "diff": "diff --git a/doc/guides/nics/cxgbe.rst b/doc/guides/nics/cxgbe.rst\nindex d718f19..d2a0d74 100644\n--- a/doc/guides/nics/cxgbe.rst\n+++ b/doc/guides/nics/cxgbe.rst\n@@ -51,6 +51,7 @@ CXGBE PMD has support for:\n - All multicast mode\n - Port hardware statistics\n - Jumbo frames\n+- Packet classification and filtering\n \n Limitations\n -----------\n@@ -187,6 +188,13 @@ Unified Wire package for Linux operating system are as follows:\n \n       cxgbtool p1p1 loadcfg <path_to_uwire>/src/network/firmware/t5-config.txt\n \n+   .. note::\n+\n+      To enable HASH filters, a special firmware configuration file is needed.\n+      The file is located under the following directory:\n+\n+      <path_to_uwire>/src/network/firmware/hash_filter_config/t5-config.txt\n+\n #. Use cxgbtool to load the firmware image onto the card:\n \n    .. code-block:: console\n@@ -541,6 +549,66 @@ devices managed by librte_pmd_cxgbe in FreeBSD operating system.\n    Flow control pause TX/RX is disabled by default and can be enabled via\n    testpmd. Refer section :ref:`flow-control` for more details.\n \n+\n+.. _filtering:\n+\n+Packet Classification and Filtering\n+-----------------------------------\n+\n+Chelsio T5 NICs support packet classification and filtering in hardware.\n+This feature can be used in the ingress path to:\n+\n+- Steer ingress packets that meet ACL (Access Control List) accept criteria\n+  to a particular receive queue.\n+\n+- Switch (proxy) ingress packets that meet ACL accept criteria to an output\n+  port, with optional header rewrite.\n+\n+- Drop ingress packets that fail ACL accept criteria.\n+\n+There are two types of filters that can be set, namely LE-TCAM (Maskfull)\n+filters and HASH (Maskless) filters.  LE-TCAM filters allow specifying masks\n+to the accept criteria to allow specifying a match for a range of values;\n+whereas, HASH filters ignore masks and hence enforce a more strict accept\n+criteria.\n+\n+By default, only LE-TCAM filter rules can be created.  Creating HASH filters\n+requires a special firmware configuration file.  Instructions on how to\n+manually flash the firmware configuration file are given in section\n+:ref:`linux-installation`.\n+\n+The fields that can be specified for the accept criteria are based on the\n+filter selection combination set in the firmware configuration\n+(t5-config.txt) file flashed in section :ref:`linux-installation`.\n+\n+By default, the selection combination automatically includes source/\n+destination IPV4/IPV6 address, and source/destination layer 4 port\n+addresses.  In addition to the above, more combinations can be added by\n+modifying the t5-config.txt firmware configuration file.\n+\n+For example, consider the following combination that has been set in\n+t5-config.txt:\n+\n+.. code-block:: console\n+\n+   filterMode = ethertype, protocol, tos, vlan, port\n+   filterMask = ethertype, protocol, tos, vlan, port\n+\n+In the above example, in addition to source/destination IPV4/IPV6\n+addresses and layer 4 source/destination port addresses, a packet can also\n+be matched against ethertype field set in the ethernet header, IP protocol\n+and tos field set in the IP header, inner VLAN tag, and physical ingress\n+port number, respectively.\n+\n+You can create 496 LE-TCAM filters and ~0.5 million HASH filter rules.\n+For more information, please visit `Chelsio Communications Official Website\n+<http://www.chelsio.com>`_.\n+\n+To test packet classification and filtering on a Chelsio NIC, an\n+example app is provided in **examples/test-cxgbe-filters/** directory.\n+Please see :doc:`Test CXGBE Filters Application Guide\n+</sample_app_ug/test_cxgbe_filters>` to compile and run the example app.\n+\n Sample Application Notes\n ------------------------\n \n@@ -587,3 +655,101 @@ to configure the mtu of all the ports with a single command.\n \n      testpmd> port stop all\n      testpmd> port config all max-pkt-len 9000\n+\n+Add/Delete Filters\n+~~~~~~~~~~~~~~~~~~\n+\n+To test packet classification and filtering on a Chelsio NIC, an\n+example app is provided in **examples/test-cxgbe-filters/** directory.\n+Please see :doc:`Test CXGBE Filters Application Guide\n+</sample_app_ug/test_cxgbe_filters>` to compile and run the app.\n+The examples below have to be run on the **test_cxgbe_filters** app.\n+\n+The command line to add/delete filters is given below. Note that the\n+command is too long to fit on one line and hence is shown wrapped\n+at \"\\\\\" for display purposes.  In real prompt, these commands should\n+be on a single line without the \"\\\\\".\n+\n+  .. code-block:: console\n+\n+     cxgbe> filter (port_id) (add|del) (ipv4|ipv6) \\\n+            mode (maskfull|maskless) (no-prio|prio) \\\n+            ingress-port (iport) (iport_mask) \\\n+            ether (ether_type) (ether_type_mask) \\\n+            vlan (inner_vlan) (inner_vlan_mask) \\\n+            (outer_vlan) (outer_vlan_mask) \\\n+            ip (tos) (tos_mask) (proto) (proto_mask) \\\n+            (src_ip_address) (src_ip_mask) \\\n+            (dst_ip_address) (dst_ip_mask) \\\n+            (src_port) (src_port_mask) (dst_port) (dst_port_mask) \\\n+            (drop|fwd|switch) queue (queue_id) \\\n+            (port-none|port-redirect) (egress_port) \\\n+            (ether-none|mac-rewrite|mac-swap) (src_mac) (dst_mac) \\\n+            (vlan-none|vlan-rewrite|vlan-delete) (new_vlan) \\\n+            (nat-none|nat-rewrite) (nat_src_ip) (nat_dst_ip) \\\n+            (nat_src_port) (nat_dst_port) \\\n+            fd_id (fd_id_value)\n+\n+LE-TCAM (Maskfull) Filters\n+^^^^^^^^^^^^^^^^^^^^^^^^^^\n+\n+- To drop all traffic coming for 102.1.2.0/24 network, add a maskfull\n+  filter as follows:\n+\n+  .. code-block:: console\n+\n+     cxgbe> filter 0 add ipv4 mode maskfull \\\n+            no-prio ingress-port 0 0 ether 0 0 vlan 0 0 0 0 \\\n+            ip 0 0 0 0 0.0.0.0 0.0.0.0 102.1.2.0 255.255.255.0 0 0 0 0 \\\n+            drop queue 0 port-none 0 \\\n+            ether-none 00:00:00:00:00:00 00:00:00:00:00:00 \\\n+            vlan-none 0 nat-none 0.0.0.0 0.0.0.0 0 0 \\\n+            fd_id 0\n+\n+- To switch all traffic coming for 102.1.2.0/24 network out via port 1\n+  with source and destination mac addresses rewritten, add a maskfull\n+  filter as follows:\n+\n+  .. code-block:: console\n+\n+     cxgbe> filter 0 add ipv4 mode maskfull \\\n+            no-prio ingress-port 0 0 ether 0 0 vlan 0 0 0 0 \\\n+            ip 0 0 0 0 0.0.0.0 0.0.0.0 102.1.2.0 255.255.255.0 0 0 0 0 \\\n+            switch queue 0 port-redirect 1 \\\n+            mac-rewrite 00:07:43:04:96:48 00:07:43:12:D4:88 \\\n+            vlan-none 0 nat-none 0.0.0.0 0.0.0.0 0 0 \\\n+            fd_id 0\n+\n+HASH (Maskless) Filters\n+^^^^^^^^^^^^^^^^^^^^^^^\n+\n+Maskless filters require a special firmware configuration file. Please see\n+section :ref:`filtering` for more information.\n+\n+- To steer all traffic coming for 102.1.2.2 with destination port 12865\n+  from 102.1.2.1 with source port 12000 to port 1's rx queue, add a\n+  maskless filter as follows:\n+\n+  .. code-block:: console\n+\n+     cxgbe> filter 1 add ipv4 mode maskless \\\n+            no-prio ingress-port 0 0 ether 0 0 vlan 0 0 0 0 \\\n+            ip 0 0 0 0 102.1.2.1 0.0.0.0 102.1.2.2 0.0.0.0 12000 0 12865 0 \\\n+            fwd queue 0 port-none 0 \\\n+            ether-none 00:00:00:00:00:00 00:00:00:00:00:00 \\\n+            vlan-none 0 nat-none 0.0.0.0 0.0.0.0 0 0 \\\n+            fd_id 0\n+\n+- To swap the source and destination mac addresses of all traffic coming\n+  for 102.1.2.2 with destination port 12865 from 102.1.2.1 with source\n+  port 12000, add a maskless filter as follows:\n+\n+  .. code-block:: console\n+\n+     cxgbe> filter 0 add ipv4 mode maskless \\\n+            no-prio ingress-port 0 0 ether 0 0 vlan 0 0 0 0 \\\n+            ip 0 0 0 0 102.1.2.1 0.0.0.0 102.1.2.2 0.0.0.0 12000 0 12865 0 \\\n+            switch queue 0 port-redirect 1 \\\n+            mac-swap 00:00:00:00:00:00 00:00:00:00:00:00 \\\n+            vlan-none 0 nat-none 0.0.0.0 0.0.0.0 0 0 \\\n+            fd_id 0\ndiff --git a/doc/guides/rel_notes/release_2_3.rst b/doc/guides/rel_notes/release_2_3.rst\nindex 19ce954..2953f52 100644\n--- a/doc/guides/rel_notes/release_2_3.rst\n+++ b/doc/guides/rel_notes/release_2_3.rst\n@@ -4,6 +4,13 @@ DPDK Release 2.3\n New Features\n ------------\n \n+* **Added flow director support for Chelsio CXGBE driver.**\n+\n+  * Added flow director support to enable Chelsio T5 NIC hardware filtering\n+    features.\n+  * Added an example app under ``examples/test-cxgbe-filters`` directory\n+    to test Chelsio T5 NIC hardware filtering features.\n+\n \n Resolved Issues\n ---------------\ndiff --git a/drivers/net/cxgbe/Makefile b/drivers/net/cxgbe/Makefile\nindex 3201aff..0d52cb1 100644\n--- a/drivers/net/cxgbe/Makefile\n+++ b/drivers/net/cxgbe/Makefile\n@@ -82,6 +82,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += clip_tbl.c\n SRCS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += l2t.c\n SRCS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += smt.c\n SRCS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += cxgbe_filter.c\n+SRCS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += cxgbe_fdir.c\n \n # this lib depends upon:\n DEPDIRS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += lib/librte_eal lib/librte_ether\ndiff --git a/drivers/net/cxgbe/base/adapter.h b/drivers/net/cxgbe/base/adapter.h\nindex a64571d..a03048d 100644\n--- a/drivers/net/cxgbe/base/adapter.h\n+++ b/drivers/net/cxgbe/base/adapter.h\n@@ -342,6 +342,8 @@ struct adapter {\n \tstruct l2t_data *l2t;     /* Layer 2 table */\n \tstruct smt_data *smt;     /* Source MAC table */\n \tstruct tid_info tids;     /* Info used to access TID related tables */\n+\n+\tstruct cxgbe_fdir_map *fdir;  /* Flow Director */\n };\n \n #define CXGBE_PCI_REG(reg) (*((volatile uint32_t *)(reg)))\ndiff --git a/drivers/net/cxgbe/cxgbe.h b/drivers/net/cxgbe/cxgbe.h\nindex 9ca4388..f984103 100644\n--- a/drivers/net/cxgbe/cxgbe.h\n+++ b/drivers/net/cxgbe/cxgbe.h\n@@ -36,6 +36,7 @@\n \n #include \"common.h\"\n #include \"t4_regs.h\"\n+#include \"cxgbe_fdir.h\"\n \n #define CXGBE_MIN_RING_DESC_SIZE      128  /* Min TX/RX descriptor ring size */\n #define CXGBE_MAX_RING_DESC_SIZE      4096 /* Max TX/RX descriptor ring size */\n@@ -52,6 +53,8 @@ int cxgbe_down(struct port_info *pi);\n void cxgbe_close(struct adapter *adapter);\n void cxgbe_stats_get(struct port_info *pi, struct port_stats *stats);\n void cxgbe_stats_reset(struct port_info *pi);\n+int cxgbe_poll_for_completion(struct sge_rspq *q, unsigned int us,\n+\t\t\t      unsigned int cnt, struct t4_completion *c);\n int link_start(struct port_info *pi);\n void init_rspq(struct adapter *adap, struct sge_rspq *q, unsigned int us,\n \t       unsigned int cnt, unsigned int size, unsigned int iqe_size);\ndiff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c\nindex 2701bb6..7016026 100644\n--- a/drivers/net/cxgbe/cxgbe_ethdev.c\n+++ b/drivers/net/cxgbe/cxgbe_ethdev.c\n@@ -770,6 +770,23 @@ static int cxgbe_flow_ctrl_set(struct rte_eth_dev *eth_dev,\n \t\t\t     &pi->link_cfg);\n }\n \n+static int cxgbe_dev_filter_ctrl(struct rte_eth_dev *dev,\n+\t\t\t\t enum rte_filter_type filter_type,\n+\t\t\t\t enum rte_filter_op filter_op, void *arg)\n+{\n+\tint ret;\n+\n+\tswitch (filter_type) {\n+\tcase RTE_ETH_FILTER_FDIR:\n+\t\tret = cxgbe_fdir_ctrl_func(dev, filter_op, arg);\n+\t\tbreak;\n+\tdefault:\n+\t\tret = -ENOTSUP;\n+\t\tbreak;\n+\t}\n+\treturn ret;\n+}\n+\n static struct eth_dev_ops cxgbe_eth_dev_ops = {\n \t.dev_start\t\t= cxgbe_dev_start,\n \t.dev_stop\t\t= cxgbe_dev_stop,\n@@ -794,6 +811,7 @@ static struct eth_dev_ops cxgbe_eth_dev_ops = {\n \t.stats_reset\t\t= cxgbe_dev_stats_reset,\n \t.flow_ctrl_get\t\t= cxgbe_flow_ctrl_get,\n \t.flow_ctrl_set\t\t= cxgbe_flow_ctrl_set,\n+\t.filter_ctrl            = cxgbe_dev_filter_ctrl,\n };\n \n /*\ndiff --git a/drivers/net/cxgbe/cxgbe_fdir.c b/drivers/net/cxgbe/cxgbe_fdir.c\nnew file mode 100644\nindex 0000000..1c15e34\n--- /dev/null\n+++ b/drivers/net/cxgbe/cxgbe_fdir.c\n@@ -0,0 +1,715 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2015-2016 Chelsio Communications.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Chelsio Communications nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#include <rte_ether.h>\n+#include <rte_ethdev.h>\n+\n+#include \"cxgbe.h\"\n+#include \"common.h\"\n+#include \"cxgbe_filter.h\"\n+#include \"smt.h\"\n+#include \"clip_tbl.h\"\n+#include \"cxgbe_fdir.h\"\n+\n+/**\n+ * Check if the specified entry is set or not\n+ */\n+static bool is_fdir_map_set(struct cxgbe_fdir_map *map,\n+\t\t\t    unsigned int cap,\n+\t\t\t    unsigned int idx)\n+{\n+\tbool result = FALSE;\n+\n+\tt4_os_lock(&map->lock);\n+\tif (!cap) {\n+\t\tif (rte_bitmap_get(map->mfull_bmap, idx))\n+\t\t\tresult = TRUE;\n+\t} else {\n+\t\tif (rte_bitmap_get(map->mless_bmap, idx))\n+\t\t\tresult = TRUE;\n+\t}\n+\tt4_os_unlock(&map->lock);\n+\n+\treturn result;\n+}\n+\n+/**\n+ * Set/Clear bitmap entry\n+ */\n+static int cxgbe_fdir_add_del_map_entry(struct cxgbe_fdir_map *map,\n+\t\t\t\t\tunsigned int cap, unsigned int idx,\n+\t\t\t\t\tbool del)\n+{\n+\tstruct cxgbe_fdir_map_entry *e;\n+\n+\tif (cap && !map->maskless_size)\n+\t\treturn 0;\n+\n+\tif (cap && idx >= map->maskless_size)\n+\t\treturn -ERANGE;\n+\n+\tif (!cap && idx >= map->maskfull_size)\n+\t\treturn -ERANGE;\n+\n+\tt4_os_lock(&map->lock);\n+\tif (!cap) {\n+\t\te = &map->mfull_entry[idx];\n+\t\t/*\n+\t\t * IPv6 maskfull filters occupy 4 slots and IPv4 maskfull\n+\t\t * filters take up one slot. Set the map accordingly.\n+\t\t */\n+\t\tif (e->fs.type == FILTER_TYPE_IPV4) {\n+\t\t\tif (del)\n+\t\t\t\trte_bitmap_clear(map->mfull_bmap, idx);\n+\t\t\telse\n+\t\t\t\trte_bitmap_set(map->mfull_bmap, idx);\n+\t\t} else {\n+\t\t\tif (del) {\n+\t\t\t\trte_bitmap_clear(map->mfull_bmap, idx);\n+\t\t\t\trte_bitmap_clear(map->mfull_bmap, idx + 1);\n+\t\t\t\trte_bitmap_clear(map->mfull_bmap, idx + 2);\n+\t\t\t\trte_bitmap_clear(map->mfull_bmap, idx + 3);\n+\t\t\t} else {\n+\t\t\t\trte_bitmap_set(map->mfull_bmap, idx);\n+\t\t\t\trte_bitmap_set(map->mfull_bmap, idx + 1);\n+\t\t\t\trte_bitmap_set(map->mfull_bmap, idx + 2);\n+\t\t\t\trte_bitmap_set(map->mfull_bmap, idx + 3);\n+\t\t\t}\n+\t\t}\n+\t} else {\n+\t\te = &map->mless_entry[idx];\n+\t\t/*\n+\t\t * Maskless filters take up only one slot for both\n+\t\t * IPv4 and IPv6\n+\t\t */\n+\t\tif (del)\n+\t\t\trte_bitmap_clear(map->mless_bmap, idx);\n+\t\telse\n+\t\t\trte_bitmap_set(map->mless_bmap, idx);\n+\t}\n+\tt4_os_unlock(&map->lock);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * Fill up default masks\n+ */\n+static void fill_ch_spec_def_mask(struct ch_filter_specification *fs)\n+{\n+\tunsigned int i;\n+\tunsigned int lip = 0, lip_mask = 0;\n+\tunsigned int fip = 0, fip_mask = 0;\n+\tunsigned int cap = fs->cap;\n+\n+\tif (fs->val.iport && (!fs->mask.iport || cap))\n+\t\tfs->mask.iport |= ~0;\n+\tif (fs->val.ethtype && (!fs->mask.ethtype || cap))\n+\t\tfs->mask.ethtype |= ~0;\n+\tif (fs->val.ivlan && (!fs->mask.ivlan || cap))\n+\t\tfs->mask.ivlan |= ~0;\n+\tif (fs->val.ovlan && (!fs->mask.ovlan || cap))\n+\t\tfs->mask.ovlan |= ~0;\n+\tif (fs->val.tos && (!fs->mask.tos || cap))\n+\t\tfs->mask.tos |= ~0;\n+\tif (fs->val.proto && (!fs->mask.proto || cap))\n+\t\tfs->mask.proto |= ~0;\n+\n+\tfor (i = 0; i < ARRAY_SIZE(fs->val.lip); i++) {\n+\t\tlip |= fs->val.lip[i];\n+\t\tlip_mask |= fs->mask.lip[i];\n+\t\tfip |= fs->val.fip[i];\n+\t\tfip_mask |= fs->mask.fip[i];\n+\t}\n+\n+\tif (lip && (!lip_mask || cap))\n+\t\tmemset(fs->mask.lip, ~0, sizeof(fs->mask.lip));\n+\n+\tif (fip && (!fip_mask || cap))\n+\t\tmemset(fs->mask.fip, ~0, sizeof(fs->mask.lip));\n+\n+\tif (fs->val.lport && (!fs->mask.lport || cap))\n+\t\tfs->mask.lport = ~0;\n+\tif (fs->val.fport && (!fs->mask.fport || cap))\n+\t\tfs->mask.fport = ~0;\n+}\n+\n+/**\n+ * Translate match fields to Chelsio Filter Specification\n+ */\n+static int fill_ch_spec_match(const struct rte_eth_fdir_filter *fdir_filter,\n+\t\t\t      struct ch_filter_specification *fs)\n+{\n+\tstruct cxgbe_fdir_input_admin admin;\n+\tstruct cxgbe_fdir_input_flow val;\n+\tstruct cxgbe_fdir_input_flow mask;\n+\tconst uint8_t *raw_pkt_admin, *raw_pkt_match, *raw_pkt_mask;\n+\n+\traw_pkt_admin = &fdir_filter->input.flow.raw_pkt_flow[0];\n+\traw_pkt_match = raw_pkt_admin + sizeof(admin);\n+\traw_pkt_mask = &fdir_filter->input.flow_mask.raw_pkt_flow[0];\n+\n+\t/* Match arguments without masks */\n+\trte_memcpy(&admin, raw_pkt_admin, sizeof(admin));\n+\tfs->prio = admin.prio ? 1 : 0;\n+\tfs->type = admin.type ? 1 : 0;\n+\tfs->cap  = admin.cap ? 1 : 0;\n+\n+\t/* Match arguments with masks */\n+\trte_memcpy(&val, raw_pkt_match, sizeof(val));\n+\tfs->val.ethtype = be16_to_cpu(val.ethtype);\n+\tif (val.iport > 7)\n+\t\treturn -ERANGE;\n+\tfs->val.iport   = val.iport;\n+\n+\tfs->val.ivlan   = be16_to_cpu(val.ivlan);\n+\tfs->val.ovlan   = be16_to_cpu(val.ovlan);\n+\n+\tfs->val.proto   = val.proto;\n+\tfs->val.tos     = val.tos;\n+\trte_memcpy(&fs->val.lip[0], &val.lip[0], sizeof(val.lip));\n+\trte_memcpy(&fs->val.fip[0], &val.fip[0], sizeof(val.fip));\n+\n+\tfs->val.lport   = be16_to_cpu(val.lport);\n+\tfs->val.fport   = be16_to_cpu(val.fport);\n+\n+\t/* Masks for matched arguments */\n+\trte_memcpy(&mask, raw_pkt_mask, sizeof(mask));\n+\tfs->mask.ethtype = be16_to_cpu(mask.ethtype);\n+\tif (mask.iport > 7)\n+\t\treturn -ERANGE;\n+\tfs->mask.iport   = mask.iport;\n+\n+\tfs->mask.ivlan   = be16_to_cpu(mask.ivlan);\n+\tfs->mask.ovlan   = be16_to_cpu(mask.ovlan);\n+\n+\tfs->mask.proto   = mask.proto;\n+\tfs->mask.tos     = mask.tos;\n+\trte_memcpy(&fs->mask.lip[0], &mask.lip[0], sizeof(mask.lip));\n+\trte_memcpy(&fs->mask.fip[0], &mask.fip[0], sizeof(mask.fip));\n+\n+\tfs->mask.lport   = be16_to_cpu(mask.lport);\n+\tfs->mask.fport   = be16_to_cpu(mask.fport);\n+\n+\t/* Fill up matched field masks with defaults if not specified */\n+\tfill_ch_spec_def_mask(fs);\n+\n+\tif (fs->val.ivlan) {\n+\t\tfs->val.ivlan_vld = 1;\n+\t\tfs->mask.ivlan_vld = 1;\n+\t}\n+\n+\tif (fs->val.ovlan) {\n+\t\tfs->val.ovlan_vld = 1;\n+\t\tfs->mask.ovlan_vld = 1;\n+\t}\n+\n+\t/* Disable filter hit counting for Maskless filters */\n+\tif (fs->cap)\n+\t\tfs->hitcnts = 0;\n+\telse\n+\t\tfs->hitcnts = 1;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * Translate action fields to Chelsio Filter Specification\n+ */\n+static int fill_ch_spec_action(struct rte_eth_dev *dev,\n+\t\t\t       const struct rte_eth_fdir_filter *fdir_filter,\n+\t\t\t       struct ch_filter_specification *fs)\n+{\n+\tstruct port_info *pi = ethdev2pinfo(dev);\n+\tstruct cxgbe_fdir_action action;\n+\tint err = 0;\n+\tunsigned int drop_queue = dev->data->dev_conf.fdir_conf.drop_queue;\n+\tconst uint8_t *action_arg;\n+\n+\tif (fdir_filter->action.rx_queue > MAX_ETH_QSETS) {\n+\t\terr = -EINVAL;\n+\t\tgoto out;\n+\t}\n+\n+\t/* Action Arguments */\n+\tswitch (fdir_filter->action.behavior) {\n+\tcase RTE_ETH_FDIR_ACCEPT:\n+\t\tif (fdir_filter->action.rx_queue < pi->n_rx_qsets) {\n+\t\t\tfs->dirsteer = 1;\n+\t\t\tfs->iq = fdir_filter->action.rx_queue;\n+\t\t}\n+\t\tfs->action = FILTER_PASS;\n+\t\tbreak;\n+\tcase RTE_ETH_FDIR_REJECT:\n+\t\tif (fdir_filter->action.rx_queue == drop_queue) {\n+\t\t\tif (drop_queue < pi->n_rx_qsets) {\n+\t\t\t\t/* Send to drop queue */\n+\t\t\t\tfs->dirsteer = 1;\n+\t\t\t\tfs->iq = drop_queue;\n+\t\t\t\tfs->action = FILTER_PASS;\n+\t\t\t\terr = 0;\n+\t\t\t\tgoto out;\n+\t\t\t}\n+\t\t}\n+\t\t/* Drop in hardware */\n+\t\tfs->action = FILTER_DROP;\n+\t\tbreak;\n+\tcase RTE_ETH_FDIR_SWITCH:\n+\t\taction_arg = &fdir_filter->action.behavior_arg[0];\n+\n+\t\trte_memcpy(&action, action_arg, sizeof(action));\n+\t\tif (action.eport > 4) {\n+\t\t\terr = -ERANGE;\n+\t\t\tbreak;\n+\t\t}\n+\t\tfs->eport = action.eport;\n+\n+\t\tfs->newdmac = action.newdmac;\n+\t\tfs->newsmac = action.newsmac;\n+\t\tfs->swapmac = action.swapmac;\n+\t\trte_memcpy(&fs->dmac[0], &action.dmac[0], ETHER_ADDR_LEN);\n+\t\trte_memcpy(&fs->smac[0], &action.smac[0], ETHER_ADDR_LEN);\n+\n+\t\tif (action.newvlan > VLAN_REWRITE) {\n+\t\t\terr = -ERANGE;\n+\t\t\tbreak;\n+\t\t}\n+\t\tfs->newvlan = action.newvlan;\n+\t\tfs->vlan = be16_to_cpu(action.vlan);\n+\n+\t\tif (action.nat_mode && action.nat_mode != NAT_MODE_ALL) {\n+\t\t\terr = -ENOTSUP;\n+\t\t\tbreak;\n+\t\t}\n+\t\tfs->nat_mode = action.nat_mode;\n+\t\trte_memcpy(&fs->nat_lip[0], &action.nat_lip[0],\n+\t\t\t   sizeof(action.nat_lip));\n+\t\trte_memcpy(&fs->nat_fip[0], &action.nat_fip[0],\n+\t\t\t   sizeof(action.nat_fip));\n+\t\tfs->nat_lport = be16_to_cpu(action.nat_lport);\n+\t\tfs->nat_fport = be16_to_cpu(action.nat_fport);\n+\n+\t\tfs->action = FILTER_SWITCH;\n+\t\tbreak;\n+\tdefault:\n+\t\terr = -EINVAL;\n+\t\tbreak;\n+\t}\n+\n+out:\n+\treturn err;\n+}\n+\n+/**\n+ * cxgbe_add_del_fdir_filter - add or remove a flow diretor filter.\n+ * @dev: pointer to the structure rte_eth_dev\n+ * @filter: fdir filter entry\n+ * @fd_id: fdir index to insert/delete\n+ * @del: 1 - delete, 0 - add\n+ */\n+static int cxgbe_add_del_fdir_filter(struct rte_eth_dev *dev,\n+\t\t\t\t     const struct rte_eth_fdir_filter *filter,\n+\t\t\t\t     unsigned int fd_id, bool del)\n+{\n+\tstruct adapter *adapter = ethdev2adap(dev);\n+\tstruct cxgbe_fdir_map *map = adapter->fdir;\n+\tstruct cxgbe_fdir_map_entry *entry;\n+\tstruct ch_filter_specification fs;\n+\tstruct filter_ctx ctx;\n+\tunsigned int filter_id;\n+\tbool map_set;\n+\tint err = 0;\n+\n+\tif (filter->input.flow_type != RTE_ETH_FLOW_RAW_PKT)\n+\t\treturn -ENOTSUP;\n+\n+\tif (!(adapter->flags & FULL_INIT_DONE))\n+\t\treturn -EAGAIN;  /* can still change nfilters */\n+\n+\tt4_init_completion(&ctx.completion);\n+\n+\tmemset(&fs, 0, sizeof(fs));\n+\n+\t/* Fill in the Match arguments to create the filter */\n+\terr = fill_ch_spec_match(filter, &fs);\n+\tif (err) {\n+\t\tdev_err(adapter, \"FDIR filter invalid match argument\\n\");\n+\t\tgoto out;\n+\t}\n+\n+\t/* Sanity Check Filter ID */\n+\tif (fs.cap) {\n+\t\tif (!map->maskless_size) {\n+\t\t\tdev_err(adapter,\n+\t\t\t\t\"Maskless Filters have been disabled\\n\");\n+\t\t\treturn -ENOTSUP;\n+\t\t}\n+\n+\t\tif (fd_id > map->maskless_size) {\n+\t\t\tdev_err(adapter,\n+\t\t\t\t\"Maskless Filters fd_id range is 0 to %d\\n\",\n+\t\t\t\tmap->maskless_size - 1);\n+\t\t\treturn -ERANGE;\n+\t\t}\n+\t\tentry = &map->mless_entry[fd_id];\n+\t} else {\n+\t\tif (!map->maskfull_size) {\n+\t\t\tdev_err(adapter,\n+\t\t\t\t\"Maskfull Filters have been disabled\\n\");\n+\t\t\treturn -ENOTSUP;\n+\t\t}\n+\n+\t\tif (fd_id > map->maskfull_size) {\n+\t\t\tdev_err(adapter,\n+\t\t\t\t\"Maskfull Filters fd_id range is 0 to %d\\n\",\n+\t\t\t\tmap->maskfull_size - 1);\n+\t\t\treturn -ERANGE;\n+\t\t}\n+\t\tentry = &map->mfull_entry[fd_id];\n+\t}\n+\n+\t/*\n+\t * We are not bothered about action arguments to delete the filter, but\n+\t * we need to know if it is a maskfull or maskless filter that is\n+\t * requested to be deleted.\n+\t */\n+\tmap_set = is_fdir_map_set(map, fs.cap, fd_id);\n+\tif (del) {\n+\t\tif (!map_set) {\n+\t\t\tdev_err(adap, \"No entry with fd_id %d found\\n\", fd_id);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t} else {\n+\t\tif (map_set) {\n+\t\t\tdev_err(adap, \"Entry with fd_id %d occupied\\n\", fd_id);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\tfilter_id = fs.cap ? entry->tid : fd_id;\n+\tif (del) {\n+\t\terr = cxgbe_del_filter(dev, filter_id, &fs, &ctx);\n+\t\tif (!err) {\n+\t\t\t/* Poll the FW for reply */\n+\t\t\terr = cxgbe_poll_for_completion(&adapter->sge.fw_evtq,\n+\t\t\t\t\t\t\tCXGBE_FDIR_POLL_US,\n+\t\t\t\t\t\t\tCXGBE_FDIR_POLL_CNT,\n+\t\t\t\t\t\t\t&ctx.completion);\n+\t\t\tif (err) {\n+\t\t\t\tdev_err(adapter,\n+\t\t\t\t\t\"FDIR filter delete timeout\\n\");\n+\t\t\t\tgoto out;\n+\t\t\t} else {\n+\t\t\t\terr = ctx.result; /* Async Completion Done */\n+\t\t\t\tif (err)\n+\t\t\t\t\tgoto out;\n+\n+\t\t\t\tcxgbe_fdir_add_del_map_entry(map, fs.cap,\n+\t\t\t\t\t\t\t     fd_id, TRUE);\n+\t\t\t\tmemset(entry, 0, sizeof(*entry));\n+\t\t\t}\n+\t\t} else {\n+\t\t\tdev_err(adapter, \"Fail to delete FDIR filter!\\n\");\n+\t\t\tgoto out;\n+\t\t}\n+\t\treturn 0;\n+\t}\n+\n+\t/* Fill in the Action arguments to create the filter */\n+\terr = fill_ch_spec_action(dev, filter, &fs);\n+\tif (err) {\n+\t\tdev_err(adapter, \"FDIR filter invalid action argument\\n\");\n+\t\tgoto out;\n+\t}\n+\n+\t/* NAT not supported for LE-TCAM */\n+\tif (!fs.cap && fs.nat_mode) {\n+\t\tdev_err(adapter, \"Maskfull NAT is not supported\\n\");\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\t/* Create the filter */\n+\terr = cxgbe_set_filter(dev, filter_id, &fs, &ctx);\n+\tif (!err) {\n+\t\t/* Poll the FW for reply */\n+\t\terr = cxgbe_poll_for_completion(&adapter->sge.fw_evtq,\n+\t\t\t\t\t\tCXGBE_FDIR_POLL_US,\n+\t\t\t\t\t\tCXGBE_FDIR_POLL_CNT,\n+\t\t\t\t\t\t&ctx.completion);\n+\t\tif (err) {\n+\t\t\tdev_err(adapter, \"FDIR filter add timeout\\n\");\n+\t\t\tgoto out;\n+\t\t} else {\n+\t\t\terr = ctx.result; /* Asynchronous Completion Done */\n+\t\t\tif (err)\n+\t\t\t\tgoto out;\n+\n+\t\t\tentry->tid = ctx.tid;\n+\t\t\trte_memcpy(&entry->fs, &fs, sizeof(fs));\n+\t\t\tdev_debug(adapter, \"FDIR inserted at tid: %d\\n\",\n+\t\t\t\t  ctx.tid);\n+\t\t\tcxgbe_fdir_add_del_map_entry(map, fs.cap, fd_id, FALSE);\n+\t\t}\n+\t} else {\n+\t\tdev_err(adapter, \"Fail to add FDIR filter!\\n\");\n+\t\tgoto out;\n+\t}\n+\n+\treturn 0;\n+\n+out:\n+\treturn err;\n+}\n+\n+/**\n+ * Process the supported filter operations\n+ */\n+static int cxgbe_fdir_filter_op(struct rte_eth_dev *dev,\n+\t\t\t\tenum rte_filter_op filter_op,\n+\t\t\t\tstruct rte_eth_fdir_filter *fdir)\n+{\n+\tstruct adapter *adap = ethdev2adap(dev);\n+\tstruct cxgbe_fdir_map *map = adap->fdir;\n+\tstruct rte_eth_fdir_stats *stats = &map->stats;\n+\tunsigned int fd_id = fdir->soft_id;\n+\tint ret;\n+\n+\tif (fd_id >= (map->maskfull_size + map->maskless_size)) {\n+\t\tdev_err(adap, \"FD_ID must be < %d\\n\",\n+\t\t\tmap->maskfull_size + map->maskless_size);\n+\t\treturn -ERANGE;\n+\t}\n+\n+\tswitch (filter_op) {\n+\tcase RTE_ETH_FILTER_ADD:\n+\t\tret = cxgbe_add_del_fdir_filter(dev, fdir, fd_id, FALSE);\n+\t\tif (ret) {\n+\t\t\tstats->f_add++;\n+\t\t} else {\n+\t\t\tstats->free--;\n+\t\t\tstats->add++;\n+\t\t}\n+\t\tbreak;\n+\tcase RTE_ETH_FILTER_DELETE:\n+\t\tret = cxgbe_add_del_fdir_filter(dev, fdir, fd_id, TRUE);\n+\t\tif (ret) {\n+\t\t\tstats->f_remove++;\n+\t\t} else {\n+\t\t\tstats->free++;\n+\t\t\tstats->remove++;\n+\t\t}\n+\t\tbreak;\n+\tcase RTE_ETH_FILTER_UPDATE:\n+\tcase RTE_ETH_FILTER_FLUSH:\n+\tcase RTE_ETH_FILTER_GET:\n+\tcase RTE_ETH_FILTER_SET:\n+\t\tret = -ENOTSUP;\n+\t\tbreak;\n+\tdefault:\n+\t\tret = -EINVAL;\n+\t\tbreak;\n+\t}\n+\treturn ret;\n+}\n+\n+/**\n+ * Fill FDIR stats\n+ */\n+static void cxgbe_fdir_get_stats(struct rte_eth_dev *dev,\n+\t\t\t\t struct rte_eth_fdir_stats *fdir_stats)\n+{\n+\tstruct adapter *adap = ethdev2adap(dev);\n+\tstruct rte_eth_fdir_stats *stats = &adap->fdir->stats;\n+\n+\trte_memcpy(fdir_stats, stats, sizeof(*stats));\n+}\n+\n+/**\n+ * cxgbe_fdir_ctrl_func - deal with all operations on flow director.\n+ * @dev: pointer to the structure rte_eth_dev\n+ * @filter_op:operation will be taken\n+ * @arg: a pointer to specific structure corresponding to the filter_op\n+ */\n+int cxgbe_fdir_ctrl_func(struct rte_eth_dev *dev, enum rte_filter_op filter_op,\n+\t\t\t void *arg)\n+{\n+\tstruct adapter *adapter = ethdev2adap(dev);\n+\tint ret = 0;\n+\n+\tif (!adapter->fdir)\n+\t\treturn -ENOTSUP;\n+\n+\tif (filter_op == RTE_ETH_FILTER_NOP)\n+\t\treturn 0;\n+\n+\tif (!arg && filter_op != RTE_ETH_FILTER_FLUSH)\n+\t\treturn -EINVAL;\n+\n+\tswitch (filter_op) {\n+\tcase RTE_ETH_FILTER_ADD:\n+\tcase RTE_ETH_FILTER_DELETE:\n+\tcase RTE_ETH_FILTER_UPDATE:\n+\tcase RTE_ETH_FILTER_FLUSH:\n+\tcase RTE_ETH_FILTER_GET:\n+\tcase RTE_ETH_FILTER_SET:\n+\t\tret = cxgbe_fdir_filter_op(dev, filter_op,\n+\t\t\t\t\t   (struct rte_eth_fdir_filter *)arg);\n+\t\tbreak;\n+\tcase RTE_ETH_FILTER_INFO:\n+\t\tret = -ENOTSUP;\n+\t\tbreak;\n+\tcase RTE_ETH_FILTER_STATS:\n+\t\tcxgbe_fdir_get_stats(dev, (struct rte_eth_fdir_stats *)arg);\n+\t\tbreak;\n+\tdefault:\n+\t\tret = -EINVAL;\n+\t\tbreak;\n+\t}\n+\treturn ret;\n+}\n+\n+/**\n+ * Intitialize flow director\n+ */\n+struct cxgbe_fdir_map *cxgbe_init_fdir(struct adapter *adap)\n+{\n+\tstruct tid_info *t = &adap->tids;\n+\tstruct cxgbe_fdir_map *map;\n+\tunsigned int mfull_size, mless_size;\n+\tunsigned int mfull_bmap_size, mless_bmap_size;\n+\n+\tif (!t->tid_tab)\n+\t\treturn NULL;\n+\n+\tmfull_size = t->nftids;\n+\tif (is_hashfilter(adap))\n+\t\tmless_size = t->ntids - t->hash_base;\n+\telse\n+\t\tmless_size = 0;\n+\tmfull_bmap_size = rte_bitmap_get_memory_footprint(mfull_size);\n+\tmless_bmap_size = rte_bitmap_get_memory_footprint(mless_size);\n+\n+\tif ((mfull_size + mless_size) < 1)\n+\t\treturn NULL;\n+\n+\tmap = t4_os_alloc(sizeof(*map));\n+\tif (!map)\n+\t\treturn NULL;\n+\n+\tmap->maskfull_size = mfull_size;\n+\tmap->maskless_size = mless_size;\n+\n+\t/* Allocate Maskfull Entries */\n+\tmap->mfull_bmap_array = t4_os_alloc(mfull_bmap_size);\n+\tif (!map->mfull_bmap_array)\n+\t\tgoto free_map;\n+\tmap->mfull_bmap = rte_bitmap_init(mfull_size, map->mfull_bmap_array,\n+\t\t\t\t\t  mfull_bmap_size);\n+\tif (!map->mfull_bmap)\n+\t\tgoto free_mfull;\n+\n+\tmap->mfull_entry = t4_os_alloc(mfull_size *\n+\t\t\t\t       sizeof(struct cxgbe_fdir_map_entry));\n+\tif (!map->mfull_entry)\n+\t\tgoto free_mfull;\n+\n+\t/* Allocate Maskless Entries */\n+\tif (mless_size) {\n+\t\tmap->mless_bmap_array = t4_os_alloc(mless_bmap_size);\n+\t\tif (!map->mless_bmap_array)\n+\t\t\tgoto free_mfull;\n+\t\tmap->mless_bmap = rte_bitmap_init(mless_size,\n+\t\t\t\t\t\t  map->mless_bmap_array,\n+\t\t\t\t\t\t  mless_bmap_size);\n+\t\tif (!map->mless_bmap)\n+\t\t\tgoto free_mless;\n+\n+\t\tmap->mless_entry = t4_os_alloc(mless_size *\n+\t\t\t\t\tsizeof(struct cxgbe_fdir_map_entry));\n+\t\tif (!map->mless_entry)\n+\t\t\tgoto free_mless;\n+\t}\n+\n+\tt4_os_lock_init(&map->lock);\n+\n+\tmap->stats.free = mfull_size + mless_size;\n+\treturn map;\n+\n+free_mless:\n+\tif (map->mless_bmap)\n+\t\trte_bitmap_free(map->mless_bmap);\n+\n+\tif (map->mless_bmap_array)\n+\t\tt4_os_free(map->mless_bmap_array);\n+\n+free_mfull:\n+\tif (map->mfull_entry)\n+\t\tt4_os_free(map->mfull_entry);\n+\n+\tif (map->mfull_bmap)\n+\t\trte_bitmap_free(map->mfull_bmap);\n+\n+\tif (map->mfull_bmap_array)\n+\t\tt4_os_free(map->mfull_bmap_array);\n+\n+free_map:\n+\tt4_os_free(map);\n+\treturn NULL;\n+}\n+\n+/**\n+ * Cleanup flow director\n+ */\n+void cxgbe_cleanup_fdir(struct adapter *adap)\n+{\n+\tstruct cxgbe_fdir_map *map = adap->fdir;\n+\n+\tif (map) {\n+\t\tif (map->mfull_bmap) {\n+\t\t\trte_bitmap_free(map->mfull_bmap);\n+\t\t\tt4_os_free(map->mfull_bmap_array);\n+\t\t}\n+\n+\t\tif (map->mless_bmap) {\n+\t\t\trte_bitmap_free(map->mless_bmap);\n+\t\t\tt4_os_free(map->mless_bmap_array);\n+\t\t}\n+\n+\t\tif (map->mfull_entry)\n+\t\t\tt4_os_free(map->mfull_entry);\n+\t\tif (map->mless_entry)\n+\t\t\tt4_os_free(map->mless_entry);\n+\n+\t\tt4_os_free(map);\n+\t}\n+}\ndiff --git a/drivers/net/cxgbe/cxgbe_fdir.h b/drivers/net/cxgbe/cxgbe_fdir.h\nnew file mode 100644\nindex 0000000..d4ae183\n--- /dev/null\n+++ b/drivers/net/cxgbe/cxgbe_fdir.h\n@@ -0,0 +1,108 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2015-2016 Chelsio Communications.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Chelsio Communications nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#ifndef _CXGBE_FDIR_H_\n+#define _CXGBE_FDIR_H_\n+\n+#define CXGBE_FDIR_POLL_US  10\n+#define CXGBE_FDIR_POLL_CNT 10\n+\n+/* RTE_ETH_FLOW_RAW_PKT representation. */\n+struct cxgbe_fdir_input_admin {\n+\tuint8_t prio;\n+\tuint8_t type;\n+\tuint8_t cap;\n+};\n+\n+struct cxgbe_fdir_input_flow {\n+\tuint16_t ethtype;\n+\tuint8_t iport;\n+\tuint8_t proto;\n+\tuint8_t tos;\n+\tuint16_t ivlan;\n+\tuint16_t ovlan;\n+\n+\tuint8_t lip[16];\n+\tuint8_t fip[16];\n+\tuint16_t lport;\n+\tuint16_t fport;\n+};\n+\n+struct cxgbe_fdir_action {\n+\tuint8_t eport;\n+\tuint8_t newdmac;\n+\tuint8_t newsmac;\n+\tuint8_t swapmac;\n+\tuint8_t newvlan;\n+\tuint8_t nat_mode;\n+\tuint8_t dmac[ETHER_ADDR_LEN];\n+\tuint8_t smac[ETHER_ADDR_LEN];\n+\tuint16_t vlan;\n+\n+\tuint8_t nat_lip[16];\n+\tuint8_t nat_fip[16];\n+\tuint16_t nat_lport;\n+\tuint16_t nat_fport;\n+};\n+\n+/* The cxgbe_fdir_map is a mapping between the DPDK filter stack and the\n+ * CXGBE filtering support. Its main intention is to translate info between\n+ * the two.\n+ */\n+struct cxgbe_fdir_map_entry {\n+\tu32 tid;                           /* Filter index */\n+\tstruct ch_filter_specification fs; /* Filter specification */\n+};\n+\n+struct cxgbe_fdir_map {\n+\t/* DPDK related info */\n+\tstruct rte_eth_fdir_stats stats;\n+\n+\t/* CXGBE related info */\n+\tunsigned int maskfull_size;    /* Size of Maskfull region */\n+\tunsigned int maskless_size;    /* Size of Maskless region */\n+\trte_spinlock_t lock;           /* Lock to access an entry */\n+\n+\tuint8_t *mfull_bmap_array;     /* Bitmap array for maskfull entries */\n+\tstruct rte_bitmap *mfull_bmap; /* Bitmap for maskfull entries */\n+\tuint8_t *mless_bmap_array;     /* Bitmap array for maskless entries */\n+\tstruct rte_bitmap *mless_bmap; /* Bitmap for maskless entries */\n+\tstruct cxgbe_fdir_map_entry *mfull_entry; /* Maskfull fdir entries */\n+\tstruct cxgbe_fdir_map_entry *mless_entry; /* Maskless fdir entries */\n+};\n+\n+struct cxgbe_fdir_map *cxgbe_init_fdir(struct adapter *adap);\n+void cxgbe_cleanup_fdir(struct adapter *adap);\n+int cxgbe_fdir_ctrl_func(struct rte_eth_dev *dev,\n+\t\t\t enum rte_filter_op filter_op, void *arg);\n+#endif /* _CXGBE_FDIR_H_ */\ndiff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c\nindex 1f79ba3..f8168c6 100644\n--- a/drivers/net/cxgbe/cxgbe_main.c\n+++ b/drivers/net/cxgbe/cxgbe_main.c\n@@ -148,6 +148,38 @@ out:\n }\n \n /**\n+ * cxgbe_poll_for_completion: Poll rxq for completion\n+ * @q: rxq to poll\n+ * @us: microseconds to delay\n+ * @cnt: number of times to poll\n+ * @c: completion to check for 'done' status\n+ *\n+ * Polls the rxq for reples until completion is done or the count\n+ * expires.\n+ */\n+int cxgbe_poll_for_completion(struct sge_rspq *q, unsigned int us,\n+\t\t\t      unsigned int cnt, struct t4_completion *c)\n+{\n+\tunsigned int i;\n+\tunsigned int work_done, budget = 4;\n+\n+\tif (!c)\n+\t\treturn -EINVAL;\n+\n+\tfor (i = 0; i < cnt; i++) {\n+\t\tcxgbe_poll(q, NULL, budget, &work_done);\n+\t\tt4_os_lock(&c->lock);\n+\t\tif (c->done) {\n+\t\t\tt4_os_unlock(&c->lock);\n+\t\t\treturn 0;\n+\t\t}\n+\t\tt4_os_unlock(&c->lock);\n+\t\tudelay(us);\n+\t}\n+\treturn -ETIMEDOUT;\n+}\n+\n+/**\n  * Setup sge control queues to pass control information.\n  */\n int setup_sge_ctrl_txq(struct adapter *adapter)\n@@ -1355,6 +1387,7 @@ void cxgbe_close(struct adapter *adapter)\n \n \tif (adapter->flags & FULL_INIT_DONE) {\n \t\tcxgbe_clear_all_filters(adapter);\n+\t\tcxgbe_cleanup_fdir(adapter);\n \t\ttid_free(&adapter->tids);\n \t\tt4_cleanup_clip_tbl(adapter);\n \t\tt4_cleanup_l2t(adapter);\n@@ -1542,6 +1575,13 @@ allocate_mac:\n \t\t\t \"Maskless filter support disabled. Continuing\\n\");\n \t}\n \n+\tadapter->fdir = cxgbe_init_fdir(adapter);\n+\tif (!adapter->fdir) {\n+\t\t/* Disable Flow Director */\n+\t\tdev_warn(adapter, \"could not allocate FDIR \"\n+\t\t\t \"flow director support disabled. Continuing\\n\");\n+\t}\n+\n \terr = init_rss(adapter);\n \tif (err)\n \t\tgoto out_free;\ndiff --git a/drivers/net/cxgbe/sge.c b/drivers/net/cxgbe/sge.c\nindex bd4b381..83e833c 100644\n--- a/drivers/net/cxgbe/sge.c\n+++ b/drivers/net/cxgbe/sge.c\n@@ -1664,7 +1664,8 @@ static int process_responses(struct sge_rspq *q, int budget,\n \t\t\tunsigned int params;\n \t\t\tu32 val;\n \n-\t\t\tif (fl_cap(&rxq->fl) - rxq->fl.avail >= 64)\n+\t\t\tif (q->offset >= 0 &&\n+\t\t\t    fl_cap(&rxq->fl) - rxq->fl.avail >= 64)\n \t\t\t\t__refill_fl(q->adapter, &rxq->fl);\n \t\t\tparams = V_QINTR_TIMER_IDX(X_TIMERREG_UPDATE_CIDX);\n \t\t\tq->next_intr_params = params;\n",
    "prefixes": [
        "dpdk-dev",
        "10/10"
    ]
}