get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 10345,
    "url": "http://patches.dpdk.org/api/patches/10345/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/915126ab9ab710b26d5826cca4cfe09686c6268d.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": "<915126ab9ab710b26d5826cca4cfe09686c6268d.1454408702.git.rahul.lakkireddy@chelsio.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/915126ab9ab710b26d5826cca4cfe09686c6268d.1454408702.git.rahul.lakkireddy@chelsio.com",
    "date": "2016-02-03T08:32:29",
    "name": "[dpdk-dev,08/10] cxgbe: add LE-TCAM filtering support",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "bc52fd5a566f8de94b06e90db7c66fb4f6a27a96",
    "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/915126ab9ab710b26d5826cca4cfe09686c6268d.1454408702.git.rahul.lakkireddy@chelsio.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/10345/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/10345/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 7D32EB3D6;\n\tWed,  3 Feb 2016 09:33:05 +0100 (CET)",
            "from stargate3.asicdesigners.com (stargate.chelsio.com\n\t[12.32.117.8]) by dpdk.org (Postfix) with ESMTP id 949ADC11A\n\tfor <dev@dpdk.org>; Wed,  3 Feb 2016 09:33:03 +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\tu138Wxa4024913; Wed, 3 Feb 2016 00:33:00 -0800"
        ],
        "From": "Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>",
        "To": "dev@dpdk.org",
        "Date": "Wed,  3 Feb 2016 14:02:29 +0530",
        "Message-Id": "<915126ab9ab710b26d5826cca4cfe09686c6268d.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 08/10] cxgbe: add LE-TCAM filtering support",
        "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 support for setting LE-TCAM (Maskfull) filters.  IPv4 filters\noccupy one index per filter, but IPv6 filters occupy 4 indices per\nfilter and must be on boundary aligned by 4.  Filters with lower\nindex have higher priority over filters with higher index.  When\na filter is hit, the rest of the filters with a higher index\nare ignored and the action is taken immediately.\n\nSigned-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>\nSigned-off-by: Kumar Sanghvi <kumaras@chelsio.com>\n---\n drivers/net/cxgbe/Makefile              |   1 +\n drivers/net/cxgbe/base/adapter.h        |  21 +\n drivers/net/cxgbe/base/common.h         |   2 +\n drivers/net/cxgbe/base/t4_hw.c          |   3 +\n drivers/net/cxgbe/base/t4_msg.h         |  39 ++\n drivers/net/cxgbe/base/t4_tcb.h         |  74 +++\n drivers/net/cxgbe/base/t4fw_interface.h | 145 ++++++\n drivers/net/cxgbe/cxgbe_filter.c        | 802 ++++++++++++++++++++++++++++++++\n drivers/net/cxgbe/cxgbe_filter.h        |  18 +\n drivers/net/cxgbe/cxgbe_main.c          |   6 +\n drivers/net/cxgbe/cxgbe_ofld.h          |   5 +\n 11 files changed, 1116 insertions(+)\n create mode 100644 drivers/net/cxgbe/base/t4_tcb.h\n create mode 100644 drivers/net/cxgbe/cxgbe_filter.c",
    "diff": "diff --git a/drivers/net/cxgbe/Makefile b/drivers/net/cxgbe/Makefile\nindex f5f5828..3201aff 100644\n--- a/drivers/net/cxgbe/Makefile\n+++ b/drivers/net/cxgbe/Makefile\n@@ -81,6 +81,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += t4_hw.c\n 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 \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 6af5c8e..a866993 100644\n--- a/drivers/net/cxgbe/base/adapter.h\n+++ b/drivers/net/cxgbe/base/adapter.h\n@@ -575,6 +575,27 @@ static inline void t4_os_write_unlock(rte_rwlock_t *lock)\n }\n \n /**\n+ * t4_init_completion - initialize completion\n+ * @c: the completion context\n+ */\n+static inline void t4_init_completion(struct t4_completion *c)\n+{\n+\tc->done = 0;\n+\tt4_os_lock_init(&c->lock);\n+}\n+\n+/**\n+ * t4_complete - set completion as done\n+ * @c: the completion context\n+ */\n+static inline void t4_complete(struct t4_completion *c)\n+{\n+\tt4_os_lock(&c->lock);\n+\tc->done = 1;\n+\tt4_os_unlock(&c->lock);\n+}\n+\n+/**\n  * ethdev2pinfo - return the port_info structure associated with a rte_eth_dev\n  * @dev: the rte_eth_dev\n  *\ndiff --git a/drivers/net/cxgbe/base/common.h b/drivers/net/cxgbe/base/common.h\nindex 2b39c10..21dca32 100644\n--- a/drivers/net/cxgbe/base/common.h\n+++ b/drivers/net/cxgbe/base/common.h\n@@ -162,7 +162,9 @@ struct tp_params {\n \tint vlan_shift;\n \tint vnic_shift;\n \tint port_shift;\n+\tint tos_shift;\n \tint protocol_shift;\n+\tint ethertype_shift;\n };\n \n struct vpd_params {\ndiff --git a/drivers/net/cxgbe/base/t4_hw.c b/drivers/net/cxgbe/base/t4_hw.c\nindex de2e6b7..b35876c 100644\n--- a/drivers/net/cxgbe/base/t4_hw.c\n+++ b/drivers/net/cxgbe/base/t4_hw.c\n@@ -2574,8 +2574,11 @@ int t4_init_tp_params(struct adapter *adap)\n \tadap->params.tp.vlan_shift = t4_filter_field_shift(adap, F_VLAN);\n \tadap->params.tp.vnic_shift = t4_filter_field_shift(adap, F_VNIC_ID);\n \tadap->params.tp.port_shift = t4_filter_field_shift(adap, F_PORT);\n+\tadap->params.tp.tos_shift = t4_filter_field_shift(adap, F_TOS);\n \tadap->params.tp.protocol_shift = t4_filter_field_shift(adap,\n \t\t\t\t\t\t\t       F_PROTOCOL);\n+\tadap->params.tp.ethertype_shift = t4_filter_field_shift(adap,\n+\t\t\t\t\t\t\t\tF_ETHERTYPE);\n \n \t/*\n \t * If TP_INGRESS_CONFIG.VNID == 0, then TP_VLAN_PRI_MAP.VNIC_ID\ndiff --git a/drivers/net/cxgbe/base/t4_msg.h b/drivers/net/cxgbe/base/t4_msg.h\nindex 6dc255b..57534f0 100644\n--- a/drivers/net/cxgbe/base/t4_msg.h\n+++ b/drivers/net/cxgbe/base/t4_msg.h\n@@ -35,10 +35,12 @@\n #define T4_MSG_H\n \n enum {\n+\tCPL_SET_TCB_FIELD     = 0x5,\n \tCPL_L2T_WRITE_REQ     = 0x12,\n \tCPL_SMT_WRITE_REQ     = 0x14,\n \tCPL_L2T_WRITE_RPL     = 0x23,\n \tCPL_SMT_WRITE_RPL     = 0x2E,\n+\tCPL_SET_TCB_RPL       = 0x3A,\n \tCPL_SGE_EGR_UPDATE    = 0xA5,\n \tCPL_FW4_MSG           = 0xC0,\n \tCPL_FW6_MSG           = 0xE0,\n@@ -125,6 +127,43 @@ struct work_request_hdr {\n #define WR_HDR_SIZE 0\n #endif\n \n+/* cpl_get_tcb.reply_ctrl fields */\n+#define S_QUEUENO    0\n+#define V_QUEUENO(x) ((x) << S_QUEUENO)\n+\n+#define S_REPLY_CHAN    14\n+#define V_REPLY_CHAN(x) ((x) << S_REPLY_CHAN)\n+\n+#define S_NO_REPLY    15\n+#define V_NO_REPLY(x) ((x) << S_NO_REPLY)\n+\n+struct cpl_set_tcb_field {\n+\tWR_HDR;\n+\tunion opcode_tid ot;\n+\t__be16 reply_ctrl;\n+\t__be16 word_cookie;\n+\t__be64 mask;\n+\t__be64 val;\n+};\n+\n+/* cpl_set_tcb_field.word_cookie fields */\n+#define S_WORD    0\n+#define V_WORD(x) ((x) << S_WORD)\n+\n+#define S_COOKIE    5\n+#define M_COOKIE    0x7\n+#define V_COOKIE(x) ((x) << S_COOKIE)\n+#define G_COOKIE(x) (((x) >> S_COOKIE) & M_COOKIE)\n+\n+struct cpl_set_tcb_rpl {\n+\tRSS_HDR\n+\tunion opcode_tid ot;\n+\t__be16 rsvd;\n+\t__u8   cookie;\n+\t__u8   status;\n+\t__be64 oldval;\n+};\n+\n struct cpl_tx_data {\n \tunion opcode_tid ot;\n \t__be32 len;\ndiff --git a/drivers/net/cxgbe/base/t4_tcb.h b/drivers/net/cxgbe/base/t4_tcb.h\nnew file mode 100644\nindex 0000000..36afd56\n--- /dev/null\n+++ b/drivers/net/cxgbe/base/t4_tcb.h\n@@ -0,0 +1,74 @@\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 _T4_TCB_DEFS_H\n+#define _T4_TCB_DEFS_H\n+\n+/* 31:24 */\n+#define W_TCB_SMAC_SEL    0\n+#define S_TCB_SMAC_SEL    24\n+#define M_TCB_SMAC_SEL    0xffULL\n+#define V_TCB_SMAC_SEL(x) ((x) << S_TCB_SMAC_SEL)\n+\n+/* 95:32 */\n+#define W_TCB_T_FLAGS    1\n+\n+/* 105:96 */\n+#define W_TCB_RSS_INFO    3\n+#define S_TCB_RSS_INFO    0\n+#define M_TCB_RSS_INFO    0x3ffULL\n+#define V_TCB_RSS_INFO(x) ((x) << S_TCB_RSS_INFO)\n+\n+/* 191:160 */\n+#define W_TCB_TIMESTAMP    5\n+#define S_TCB_TIMESTAMP    0\n+#define M_TCB_TIMESTAMP    0xffffffffULL\n+#define V_TCB_TIMESTAMP(x) ((x) << S_TCB_TIMESTAMP)\n+\n+/* 223:192 */\n+#define S_TCB_T_RTT_TS_RECENT_AGE    0\n+#define M_TCB_T_RTT_TS_RECENT_AGE    0xffffffffULL\n+#define V_TCB_T_RTT_TS_RECENT_AGE(x) ((x) << S_TCB_T_RTT_TS_RECENT_AGE)\n+\n+#define S_TF_MIGRATING    0\n+#define V_TF_MIGRATING(x) ((x) << S_TF_MIGRATING)\n+\n+#define S_TF_NON_OFFLOAD    1\n+#define V_TF_NON_OFFLOAD(x) ((x) << S_TF_NON_OFFLOAD)\n+\n+#define S_TF_CCTRL_ECE    60\n+\n+#define S_TF_CCTRL_CWR    61\n+\n+#define S_TF_CCTRL_RFR    62\n+#endif /* _T4_TCB_DEFS_H */\ndiff --git a/drivers/net/cxgbe/base/t4fw_interface.h b/drivers/net/cxgbe/base/t4fw_interface.h\nindex 8a8652a..d3e4de5 100644\n--- a/drivers/net/cxgbe/base/t4fw_interface.h\n+++ b/drivers/net/cxgbe/base/t4fw_interface.h\n@@ -82,6 +82,7 @@ enum fw_memtype {\n  ********************************/\n \n enum fw_wr_opcodes {\n+\tFW_FILTER_WR\t\t= 0x02,\n \tFW_TP_WR\t\t= 0x05,\n \tFW_ETH_TX_PKT_WR\t= 0x08,\n \tFW_ETH_TX_PKTS_WR\t= 0x09,\n@@ -156,6 +157,150 @@ struct fw_eth_tx_pkts_wr {\n \t__u8   type;\n };\n \n+/* filter wr reply code in cookie in CPL_SET_TCB_RPL */\n+enum fw_filter_wr_cookie {\n+\tFW_FILTER_WR_SUCCESS,\n+\tFW_FILTER_WR_FLT_ADDED,\n+\tFW_FILTER_WR_FLT_DELETED,\n+\tFW_FILTER_WR_SMT_TBL_FULL,\n+\tFW_FILTER_WR_EINVAL,\n+};\n+\n+struct fw_filter_wr {\n+\t__be32 op_pkd;\n+\t__be32 len16_pkd;\n+\t__be64 r3;\n+\t__be32 tid_to_iq;\n+\t__be32 del_filter_to_l2tix;\n+\t__be16 ethtype;\n+\t__be16 ethtypem;\n+\t__u8   frag_to_ovlan_vldm;\n+\t__u8   smac_sel;\n+\t__be16 rx_chan_rx_rpl_iq;\n+\t__be32 maci_to_matchtypem;\n+\t__u8   ptcl;\n+\t__u8   ptclm;\n+\t__u8   ttyp;\n+\t__u8   ttypm;\n+\t__be16 ivlan;\n+\t__be16 ivlanm;\n+\t__be16 ovlan;\n+\t__be16 ovlanm;\n+\t__u8   lip[16];\n+\t__u8   lipm[16];\n+\t__u8   fip[16];\n+\t__u8   fipm[16];\n+\t__be16 lp;\n+\t__be16 lpm;\n+\t__be16 fp;\n+\t__be16 fpm;\n+\t__be16 r7;\n+\t__u8   sma[6];\n+};\n+\n+#define S_FW_FILTER_WR_TID\t12\n+#define V_FW_FILTER_WR_TID(x)\t((x) << S_FW_FILTER_WR_TID)\n+\n+#define S_FW_FILTER_WR_RQTYPE\t\t11\n+#define V_FW_FILTER_WR_RQTYPE(x)\t((x) << S_FW_FILTER_WR_RQTYPE)\n+\n+#define S_FW_FILTER_WR_NOREPLY\t\t10\n+#define V_FW_FILTER_WR_NOREPLY(x)\t((x) << S_FW_FILTER_WR_NOREPLY)\n+\n+#define S_FW_FILTER_WR_IQ\t0\n+#define V_FW_FILTER_WR_IQ(x)\t((x) << S_FW_FILTER_WR_IQ)\n+\n+#define S_FW_FILTER_WR_DEL_FILTER\t31\n+#define V_FW_FILTER_WR_DEL_FILTER(x)\t((x) << S_FW_FILTER_WR_DEL_FILTER)\n+#define F_FW_FILTER_WR_DEL_FILTER\tV_FW_FILTER_WR_DEL_FILTER(1U)\n+\n+#define S_FW_FILTER_WR_RPTTID\t\t25\n+#define V_FW_FILTER_WR_RPTTID(x)\t((x) << S_FW_FILTER_WR_RPTTID)\n+\n+#define S_FW_FILTER_WR_DROP\t24\n+#define V_FW_FILTER_WR_DROP(x)\t((x) << S_FW_FILTER_WR_DROP)\n+\n+#define S_FW_FILTER_WR_DIRSTEER\t\t23\n+#define V_FW_FILTER_WR_DIRSTEER(x)\t((x) << S_FW_FILTER_WR_DIRSTEER)\n+\n+#define S_FW_FILTER_WR_MASKHASH\t\t22\n+#define V_FW_FILTER_WR_MASKHASH(x)\t((x) << S_FW_FILTER_WR_MASKHASH)\n+\n+#define S_FW_FILTER_WR_DIRSTEERHASH\t21\n+#define V_FW_FILTER_WR_DIRSTEERHASH(x)\t((x) << S_FW_FILTER_WR_DIRSTEERHASH)\n+\n+#define S_FW_FILTER_WR_LPBK\t20\n+#define V_FW_FILTER_WR_LPBK(x)\t((x) << S_FW_FILTER_WR_LPBK)\n+\n+#define S_FW_FILTER_WR_DMAC\t19\n+#define V_FW_FILTER_WR_DMAC(x)\t((x) << S_FW_FILTER_WR_DMAC)\n+\n+#define S_FW_FILTER_WR_INSVLAN\t\t17\n+#define V_FW_FILTER_WR_INSVLAN(x)\t((x) << S_FW_FILTER_WR_INSVLAN)\n+\n+#define S_FW_FILTER_WR_RMVLAN\t\t16\n+#define V_FW_FILTER_WR_RMVLAN(x)\t((x) << S_FW_FILTER_WR_RMVLAN)\n+\n+#define S_FW_FILTER_WR_HITCNTS\t\t15\n+#define V_FW_FILTER_WR_HITCNTS(x)\t((x) << S_FW_FILTER_WR_HITCNTS)\n+\n+#define S_FW_FILTER_WR_TXCHAN\t\t13\n+#define V_FW_FILTER_WR_TXCHAN(x)\t((x) << S_FW_FILTER_WR_TXCHAN)\n+\n+#define S_FW_FILTER_WR_PRIO\t12\n+#define V_FW_FILTER_WR_PRIO(x)\t((x) << S_FW_FILTER_WR_PRIO)\n+\n+#define S_FW_FILTER_WR_L2TIX\t0\n+#define V_FW_FILTER_WR_L2TIX(x)\t((x) << S_FW_FILTER_WR_L2TIX)\n+\n+#define S_FW_FILTER_WR_FRAG\t7\n+#define V_FW_FILTER_WR_FRAG(x)\t((x) << S_FW_FILTER_WR_FRAG)\n+\n+#define S_FW_FILTER_WR_FRAGM\t6\n+#define V_FW_FILTER_WR_FRAGM(x)\t((x) << S_FW_FILTER_WR_FRAGM)\n+\n+#define S_FW_FILTER_WR_IVLAN_VLD\t5\n+#define V_FW_FILTER_WR_IVLAN_VLD(x)\t((x) << S_FW_FILTER_WR_IVLAN_VLD)\n+\n+#define S_FW_FILTER_WR_OVLAN_VLD\t4\n+#define V_FW_FILTER_WR_OVLAN_VLD(x)\t((x) << S_FW_FILTER_WR_OVLAN_VLD)\n+\n+#define S_FW_FILTER_WR_IVLAN_VLDM\t3\n+#define V_FW_FILTER_WR_IVLAN_VLDM(x)\t((x) << S_FW_FILTER_WR_IVLAN_VLDM)\n+\n+#define S_FW_FILTER_WR_OVLAN_VLDM\t2\n+#define V_FW_FILTER_WR_OVLAN_VLDM(x)\t((x) << S_FW_FILTER_WR_OVLAN_VLDM)\n+\n+#define S_FW_FILTER_WR_RX_CHAN\t\t15\n+#define V_FW_FILTER_WR_RX_CHAN(x)\t((x) << S_FW_FILTER_WR_RX_CHAN)\n+\n+#define S_FW_FILTER_WR_RX_RPL_IQ\t0\n+#define V_FW_FILTER_WR_RX_RPL_IQ(x)\t((x) << S_FW_FILTER_WR_RX_RPL_IQ)\n+\n+#define S_FW_FILTER_WR_MACI\t23\n+#define V_FW_FILTER_WR_MACI(x)\t((x) << S_FW_FILTER_WR_MACI)\n+\n+#define S_FW_FILTER_WR_MACIM\t14\n+#define V_FW_FILTER_WR_MACIM(x)\t((x) << S_FW_FILTER_WR_MACIM)\n+\n+#define S_FW_FILTER_WR_FCOE\t13\n+#define V_FW_FILTER_WR_FCOE(x)\t((x) << S_FW_FILTER_WR_FCOE)\n+\n+#define S_FW_FILTER_WR_FCOEM\t12\n+#define V_FW_FILTER_WR_FCOEM(x)\t((x) << S_FW_FILTER_WR_FCOEM)\n+\n+#define S_FW_FILTER_WR_PORT\t9\n+#define V_FW_FILTER_WR_PORT(x)\t((x) << S_FW_FILTER_WR_PORT)\n+\n+#define S_FW_FILTER_WR_PORTM\t6\n+#define V_FW_FILTER_WR_PORTM(x)\t((x) << S_FW_FILTER_WR_PORTM)\n+\n+#define S_FW_FILTER_WR_MATCHTYPE\t3\n+#define V_FW_FILTER_WR_MATCHTYPE(x)\t((x) << S_FW_FILTER_WR_MATCHTYPE)\n+\n+#define S_FW_FILTER_WR_MATCHTYPEM\t0\n+#define V_FW_FILTER_WR_MATCHTYPEM(x)\t((x) << S_FW_FILTER_WR_MATCHTYPEM)\n+\n /******************************************************************************\n  *  C O M M A N D s\n  *********************/\ndiff --git a/drivers/net/cxgbe/cxgbe_filter.c b/drivers/net/cxgbe/cxgbe_filter.c\nnew file mode 100644\nindex 0000000..d4e32b1\n--- /dev/null\n+++ b/drivers/net/cxgbe/cxgbe_filter.c\n@@ -0,0 +1,802 @@\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 \"common.h\"\n+#include \"t4_regs.h\"\n+#include \"t4_tcb.h\"\n+#include \"t4fw_interface.h\"\n+#include \"l2t.h\"\n+#include \"smt.h\"\n+#include \"clip_tbl.h\"\n+#include \"cxgbe_filter.h\"\n+\n+/**\n+ * Validate if the requested filter specification can be set by checking\n+ * if the requested features have been enabled\n+ */\n+static int validate_filter(struct adapter *adapter,\n+\t\t\t   struct ch_filter_specification *fs)\n+{\n+\tu32 fconf, iconf;\n+\n+\t/*\n+\t * Check for unconfigured fields being used.\n+\t */\n+\tfconf = adapter->params.tp.vlan_pri_map;\n+\ticonf = adapter->params.tp.ingress_config;\n+\n+#define S(_field) \\\n+\t(fs->val._field || fs->mask._field)\n+#define U(_mask, _field) \\\n+\t(!(fconf & (_mask)) && S(_field))\n+\n+\tif (U(F_FCOE, fcoe) || U(F_PORT, iport) || U(F_TOS, tos) ||\n+\t    U(F_ETHERTYPE, ethtype) || U(F_MACMATCH, macidx) ||\n+\t    U(F_MPSHITTYPE, matchtype) || U(F_FRAGMENTATION, frag) ||\n+\t    U(F_PROTOCOL, proto) ||\n+\t    U(F_VNIC_ID, pfvf_vld) ||\n+\t    U(F_VNIC_ID, ovlan_vld) ||\n+\t    U(F_VLAN, ivlan_vld))\n+\t\treturn -EOPNOTSUPP;\n+\n+\t/*\n+\t * We need to translate any PF/VF specification into that\n+\t * internal format below.\n+\t */\n+\tif (S(pfvf_vld) && S(ovlan_vld))\n+\t\treturn -EOPNOTSUPP;\n+\tif ((S(pfvf_vld) && !(iconf & F_VNIC)) ||\n+\t    (S(ovlan_vld) && (iconf & F_VNIC)))\n+\t\treturn -EOPNOTSUPP;\n+\tif (fs->val.pf > 0x7 || fs->val.vf > 0x7f)\n+\t\treturn -ERANGE;\n+\tfs->mask.pf &= 0x7;\n+\tfs->mask.vf &= 0x7f;\n+\n+#undef S\n+#undef U\n+\n+\t/*\n+\t * If the user is requesting that the filter action loop\n+\t * matching packets back out one of our ports, make sure that\n+\t * the egress port is in range.\n+\t */\n+\tif (fs->action == FILTER_SWITCH &&\n+\t    fs->eport >= adapter->params.nports)\n+\t\treturn -ERANGE;\n+\n+\t/*\n+\t * Don't allow various trivially obvious bogus out-of-range\n+\t * values ...\n+\t */\n+\tif (fs->val.iport >= adapter->params.nports)\n+\t\treturn -ERANGE;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * Get the queue to which the traffic must be steered to.\n+ */\n+static unsigned int get_filter_steerq(struct rte_eth_dev *dev,\n+\t\t\t\t      struct ch_filter_specification *fs)\n+{\n+\tstruct port_info *pi = ethdev2pinfo(dev);\n+\tstruct adapter *adapter = pi->adapter;\n+\tunsigned int iq;\n+\n+\t/*\n+\t * If the user has requested steering matching Ingress Packets\n+\t * to a specific Queue Set, we need to make sure it's in range\n+\t * for the port and map that into the Absolute Queue ID of the\n+\t * Queue Set's Response Queue.\n+\t */\n+\tif (!fs->dirsteer) {\n+\t\tiq = 0;\n+\t} else {\n+\t\t/*\n+\t\t * If the iq id is greater than the number of qsets,\n+\t\t * then assume it is an absolute qid.\n+\t\t */\n+\t\tif (fs->iq < pi->n_rx_qsets)\n+\t\t\tiq = adapter->sge.ethrxq[pi->first_qset +\n+\t\t\t\t\t\t fs->iq].rspq.abs_id;\n+\t\telse\n+\t\t\tiq = fs->iq;\n+\t}\n+\n+\treturn iq;\n+}\n+\n+/* Return an error number if the indicated filter isn't writable ... */\n+int writable_filter(struct filter_entry *f)\n+{\n+\tif (f->locked)\n+\t\treturn -EPERM;\n+\tif (f->pending)\n+\t\treturn -EBUSY;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * Send CPL_SET_TCB_FIELD message\n+ */\n+static void set_tcb_field(struct adapter *adapter, unsigned int ftid,\n+\t\t\t  u16 word, u64 mask, u64 val, int no_reply)\n+{\n+\tstruct rte_mbuf *mbuf;\n+\tstruct cpl_set_tcb_field *req;\n+\tstruct sge_ctrl_txq *ctrlq;\n+\n+\tctrlq = &adapter->sge.ctrlq[0];\n+\tmbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);\n+\tBUG_ON(!mbuf);\n+\n+\tmbuf->data_len = sizeof(*req);\n+\tmbuf->pkt_len = mbuf->data_len;\n+\n+\treq = rte_pktmbuf_mtod(mbuf, struct cpl_set_tcb_field *);\n+\tmemset(req, 0, sizeof(*req));\n+\tINIT_TP_WR_MIT_CPL(req, CPL_SET_TCB_FIELD, ftid);\n+\treq->reply_ctrl = cpu_to_be16(V_REPLY_CHAN(0) |\n+\t\t\t\t      V_QUEUENO(adapter->sge.fw_evtq.abs_id) |\n+\t\t\t\t      V_NO_REPLY(no_reply));\n+\treq->word_cookie = cpu_to_be16(V_WORD(word) | V_COOKIE(ftid));\n+\treq->mask = cpu_to_be64(mask);\n+\treq->val = cpu_to_be64(val);\n+\n+\tt4_mgmt_tx(ctrlq, mbuf);\n+}\n+\n+/**\n+ * Set one of the t_flags bits in the TCB.\n+ */\n+static void set_tcb_tflag(struct adapter *adap, unsigned int ftid,\n+\t\t\t  unsigned int bit_pos, unsigned int val, int no_reply)\n+{\n+\tset_tcb_field(adap, ftid,  W_TCB_T_FLAGS, 1ULL << bit_pos,\n+\t\t      (unsigned long long)val << bit_pos, no_reply);\n+}\n+\n+/**\n+ * Clear a filter and release any of its resources that we own.  This also\n+ * clears the filter's \"pending\" status.\n+ */\n+void clear_filter(struct filter_entry *f)\n+{\n+\t/*\n+\t * If the filter has loopback rewriteing rules then we'll need to free\n+\t * any existing Layer Two Table (L2T) entries of the filter rule.  The\n+\t * firmware will handle freeing up any Source MAC Table (SMT) entries\n+\t * used for rewriting Source MAC Addresses in loopback rules.\n+\t */\n+\tif (f->l2t)\n+\t\tcxgbe_l2t_release(f->l2t);\n+\n+\tif (f->smt)\n+\t\tcxgbe_smt_release(f->smt);\n+\n+\t/*\n+\t * The zeroing of the filter rule below clears the filter valid,\n+\t * pending, locked flags, l2t pointer, etc. so it's all we need for\n+\t * this operation.\n+\t */\n+\tmemset(f, 0, sizeof(*f));\n+}\n+\n+/**\n+ * Clear all set filters\n+ */\n+void cxgbe_clear_all_filters(struct adapter *adapter)\n+{\n+\tunsigned int i;\n+\n+\tif (adapter->tids.ftid_tab) {\n+\t\tstruct filter_entry *f = &adapter->tids.ftid_tab[0];\n+\n+\t\tfor (i = 0; i < adapter->tids.nftids; i++, f++)\n+\t\t\tif (f->valid || f->pending)\n+\t\t\t\tclear_filter(f);\n+\t}\n+}\n+\n+/**\n+ * Check if entry already filled.\n+ */\n+static bool is_filter_set(struct tid_info *t, int fidx, int family)\n+{\n+\tbool result = FALSE;\n+\tint i, max;\n+\n+\t/* IPv6 requires four slots and IPv4 requires only 1 slot.\n+\t * Ensure, there's enough slots available.\n+\t */\n+\tmax = family == FILTER_TYPE_IPV6 ? fidx + 3 : fidx;\n+\n+\tt4_os_lock(&t->ftid_lock);\n+\tfor (i = fidx; i <= max; i++) {\n+\t\tif (rte_bitmap_get(t->ftid_bmap, i)) {\n+\t\t\tresult = TRUE;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tt4_os_unlock(&t->ftid_lock);\n+\treturn result;\n+}\n+\n+/**\n+ * Set the corresponding entry in the bitmap. 4 slots are\n+ * marked for IPv6, whereas only 1 slot is marked for IPv4.\n+ */\n+static int cxgbe_set_ftid(struct tid_info *t, int fidx, int family)\n+{\n+\tt4_os_lock(&t->ftid_lock);\n+\tif (rte_bitmap_get(t->ftid_bmap, fidx)) {\n+\t\tt4_os_unlock(&t->ftid_lock);\n+\t\treturn -EBUSY;\n+\t}\n+\n+\tif (family == FILTER_TYPE_IPV4) {\n+\t\trte_bitmap_set(t->ftid_bmap, fidx);\n+\t} else {\n+\t\trte_bitmap_set(t->ftid_bmap, fidx);\n+\t\trte_bitmap_set(t->ftid_bmap, fidx + 1);\n+\t\trte_bitmap_set(t->ftid_bmap, fidx + 2);\n+\t\trte_bitmap_set(t->ftid_bmap, fidx + 3);\n+\t}\n+\tt4_os_unlock(&t->ftid_lock);\n+\treturn 0;\n+}\n+\n+/**\n+ * Clear the corresponding entry in the bitmap. 4 slots are\n+ * cleared for IPv6, whereas only 1 slot is cleared for IPv4.\n+ */\n+static void cxgbe_clear_ftid(struct tid_info *t, int fidx, int family)\n+{\n+\tt4_os_lock(&t->ftid_lock);\n+\tif (family == FILTER_TYPE_IPV4) {\n+\t\trte_bitmap_clear(t->ftid_bmap, fidx);\n+\t} else {\n+\t\trte_bitmap_clear(t->ftid_bmap, fidx);\n+\t\trte_bitmap_clear(t->ftid_bmap, fidx + 1);\n+\t\trte_bitmap_clear(t->ftid_bmap, fidx + 2);\n+\t\trte_bitmap_clear(t->ftid_bmap, fidx + 3);\n+\t}\n+\tt4_os_unlock(&t->ftid_lock);\n+}\n+\n+/**\n+ * t4_mk_filtdelwr - create a delete filter WR\n+ * @ftid: the filter ID\n+ * @wr: the filter work request to populate\n+ * @qid: ingress queue to receive the delete notification\n+ *\n+ * Creates a filter work request to delete the supplied filter.  If @qid is\n+ * negative the delete notification is suppressed.\n+ */\n+static void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid)\n+{\n+\tmemset(wr, 0, sizeof(*wr));\n+\twr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER_WR));\n+\twr->len16_pkd = cpu_to_be32(V_FW_WR_LEN16(sizeof(*wr) / 16));\n+\twr->tid_to_iq = cpu_to_be32(V_FW_FILTER_WR_TID(ftid) |\n+\t\t\t\t    V_FW_FILTER_WR_NOREPLY(qid < 0));\n+\twr->del_filter_to_l2tix = cpu_to_be32(F_FW_FILTER_WR_DEL_FILTER);\n+\tif (qid >= 0)\n+\t\twr->rx_chan_rx_rpl_iq =\n+\t\t\t\tcpu_to_be16(V_FW_FILTER_WR_RX_RPL_IQ(qid));\n+}\n+\n+/**\n+ * Create FW work request to delete the filter at a specified index\n+ */\n+static int del_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)\n+{\n+\tstruct adapter *adapter = ethdev2adap(dev);\n+\tstruct filter_entry *f = &adapter->tids.ftid_tab[fidx];\n+\tstruct rte_mbuf *mbuf;\n+\tstruct fw_filter_wr *fwr;\n+\tstruct sge_ctrl_txq *ctrlq;\n+\tunsigned int port_id = ethdev2pinfo(dev)->port_id;\n+\n+\tctrlq = &adapter->sge.ctrlq[port_id];\n+\tmbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);\n+\tif (!mbuf)\n+\t\treturn -ENOMEM;\n+\n+\tmbuf->data_len = sizeof(*fwr);\n+\tmbuf->pkt_len = mbuf->data_len;\n+\n+\tfwr = rte_pktmbuf_mtod(mbuf, struct fw_filter_wr *);\n+\tt4_mk_filtdelwr(f->tid, fwr, adapter->sge.fw_evtq.abs_id);\n+\n+\t/*\n+\t * Mark the filter as \"pending\" and ship off the Filter Work Request.\n+\t * When we get the Work Request Reply we'll clear the pending status.\n+\t */\n+\tf->pending = 1;\n+\tt4_mgmt_tx(ctrlq, mbuf);\n+\treturn 0;\n+}\n+\n+/**\n+ * Delete the filter at the specified index (if valid).  The checks for all\n+ * the common problems with doing this like the filter being locked, currently\n+ * pending in another operation, etc.\n+ */\n+int delete_filter(struct rte_eth_dev *dev, unsigned int fidx)\n+{\n+\tstruct adapter *adapter = ethdev2adap(dev);\n+\tstruct filter_entry *f;\n+\tint ret;\n+\tunsigned int max_fidx;\n+\n+\tmax_fidx = adapter->tids.nftids;\n+\tif (fidx >= max_fidx)\n+\t\treturn -ERANGE;\n+\n+\tf = &adapter->tids.ftid_tab[fidx];\n+\tret = writable_filter(f);\n+\tif (ret)\n+\t\treturn ret;\n+\tif (f->valid)\n+\t\treturn del_filter_wr(dev, fidx);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * Send a Work Request to write the filter at a specified index.  We construct\n+ * a Firmware Filter Work Request to have the work done and put the indicated\n+ * filter into \"pending\" mode which will prevent any further actions against\n+ * it till we get a reply from the firmware on the completion status of the\n+ * request.\n+ */\n+int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)\n+{\n+\tstruct adapter *adapter = ethdev2adap(dev);\n+\tstruct filter_entry *f = &adapter->tids.ftid_tab[fidx];\n+\tstruct rte_mbuf *mbuf;\n+\tstruct fw_filter_wr *fwr;\n+\tstruct sge_ctrl_txq *ctrlq;\n+\tunsigned int port_id = ethdev2pinfo(dev)->port_id;\n+\tint ret;\n+\n+\tctrlq = &adapter->sge.ctrlq[port_id];\n+\tmbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);\n+\tif (!mbuf) {\n+\t\tret = -ENOMEM;\n+\t\tgoto out;\n+\t}\n+\n+\tmbuf->data_len = sizeof(*fwr);\n+\tmbuf->pkt_len = mbuf->data_len;\n+\n+\tfwr = rte_pktmbuf_mtod(mbuf, struct fw_filter_wr *);\n+\tmemset(fwr, 0, sizeof(*fwr));\n+\n+\t/*\n+\t * If the new filter requires loopback Destination MAC and/or VLAN\n+\t * rewriting then we need to allocate a Layer 2 Table (L2T) entry for\n+\t * the filter.\n+\t */\n+\tif (f->fs.newdmac || f->fs.newvlan) {\n+\t\t/* allocate L2T entry for new filter */\n+\t\tf->l2t = cxgbe_l2t_alloc_switching(f->dev, f->fs.vlan,\n+\t\t\t\t\t\t   f->fs.eport, f->fs.dmac);\n+\t\tif (!f->l2t) {\n+\t\t\tret = -ENOMEM;\n+\t\t\tgoto error;\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * If the new filter requires loopback Source MAC rewriting then\n+\t * we need to allocate a SMT entry for the filter.\n+\t */\n+\tif (f->fs.newsmac) {\n+\t\tf->smt = cxgbe_smt_alloc_switching(f->dev, f->fs.smac);\n+\t\tif (!f->smt) {\n+\t\t\tif (f->l2t) {\n+\t\t\t\tcxgbe_l2t_release(f->l2t);\n+\t\t\t\tf->l2t = NULL;\n+\t\t\t}\n+\t\t\tret = -ENOMEM;\n+\t\t\tgoto error;\n+\t\t}\n+\t\tf->smtidx = f->smt->idx;\n+\t}\n+\n+\t/*\n+\t * Construct the work request to set the filter.\n+\t */\n+\tfwr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER_WR));\n+\tfwr->len16_pkd = cpu_to_be32(V_FW_WR_LEN16(sizeof(*fwr) / 16));\n+\tfwr->tid_to_iq =\n+\t\tcpu_to_be32(V_FW_FILTER_WR_TID(f->tid) |\n+\t\t\t    V_FW_FILTER_WR_RQTYPE(f->fs.type) |\n+\t\t\t    V_FW_FILTER_WR_NOREPLY(0) |\n+\t\t\t    V_FW_FILTER_WR_IQ(f->fs.iq));\n+\tfwr->del_filter_to_l2tix =\n+\t\tcpu_to_be32(V_FW_FILTER_WR_RPTTID(f->fs.rpttid) |\n+\t\t\t    V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) |\n+\t\t\t    V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) |\n+\t\t\t    V_FW_FILTER_WR_MASKHASH(f->fs.maskhash) |\n+\t\t\t    V_FW_FILTER_WR_DIRSTEERHASH(f->fs.dirsteerhash) |\n+\t\t\t    V_FW_FILTER_WR_LPBK(f->fs.action == FILTER_SWITCH) |\n+\t\t\t    V_FW_FILTER_WR_DMAC(f->fs.newdmac) |\n+\t\t\t    V_FW_FILTER_WR_INSVLAN(\n+\t\t\t\t    f->fs.newvlan == VLAN_INSERT ||\n+\t\t\t\t    f->fs.newvlan == VLAN_REWRITE) |\n+\t\t\t    V_FW_FILTER_WR_RMVLAN(\n+\t\t\t\t    f->fs.newvlan == VLAN_REMOVE ||\n+\t\t\t\t    f->fs.newvlan == VLAN_REWRITE) |\n+\t\t\t    V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) |\n+\t\t\t    V_FW_FILTER_WR_TXCHAN(f->fs.eport) |\n+\t\t\t    V_FW_FILTER_WR_PRIO(f->fs.prio) |\n+\t\t\t    V_FW_FILTER_WR_L2TIX(f->l2t ? f->l2t->idx : 0));\n+\tfwr->ethtype = cpu_to_be16(f->fs.val.ethtype);\n+\tfwr->ethtypem = cpu_to_be16(f->fs.mask.ethtype);\n+\tfwr->frag_to_ovlan_vldm =\n+\t\t     (V_FW_FILTER_WR_FRAG(f->fs.val.frag) |\n+\t\t      V_FW_FILTER_WR_FRAGM(f->fs.mask.frag) |\n+\t\t      V_FW_FILTER_WR_IVLAN_VLD(f->fs.val.ivlan_vld) |\n+\t\t      V_FW_FILTER_WR_OVLAN_VLD(f->fs.val.ovlan_vld) |\n+\t\t      V_FW_FILTER_WR_IVLAN_VLDM(f->fs.mask.ivlan_vld) |\n+\t\t      V_FW_FILTER_WR_OVLAN_VLDM(f->fs.mask.ovlan_vld));\n+\tfwr->smac_sel = 0;\n+\tfwr->rx_chan_rx_rpl_iq =\n+\t\tcpu_to_be16(V_FW_FILTER_WR_RX_CHAN(0) |\n+\t\t\t    V_FW_FILTER_WR_RX_RPL_IQ(\n+\t\t\t\t    adapter->sge.fw_evtq.abs_id));\n+\tfwr->maci_to_matchtypem =\n+\t\tcpu_to_be32(V_FW_FILTER_WR_MACI(f->fs.val.macidx) |\n+\t\t\t    V_FW_FILTER_WR_MACIM(f->fs.mask.macidx) |\n+\t\t\t    V_FW_FILTER_WR_FCOE(f->fs.val.fcoe) |\n+\t\t\t    V_FW_FILTER_WR_FCOEM(f->fs.mask.fcoe) |\n+\t\t\t    V_FW_FILTER_WR_PORT(f->fs.val.iport) |\n+\t\t\t    V_FW_FILTER_WR_PORTM(f->fs.mask.iport) |\n+\t\t\t    V_FW_FILTER_WR_MATCHTYPE(f->fs.val.matchtype) |\n+\t\t\t    V_FW_FILTER_WR_MATCHTYPEM(f->fs.mask.matchtype));\n+\tfwr->ptcl = f->fs.val.proto;\n+\tfwr->ptclm = f->fs.mask.proto;\n+\tfwr->ttyp = f->fs.val.tos;\n+\tfwr->ttypm = f->fs.mask.tos;\n+\tfwr->ivlan = cpu_to_be16(f->fs.val.ivlan);\n+\tfwr->ivlanm = cpu_to_be16(f->fs.mask.ivlan);\n+\tfwr->ovlan = cpu_to_be16(f->fs.val.ovlan);\n+\tfwr->ovlanm = cpu_to_be16(f->fs.mask.ovlan);\n+\trte_memcpy(fwr->lip, f->fs.val.lip, sizeof(fwr->lip));\n+\trte_memcpy(fwr->lipm, f->fs.mask.lip, sizeof(fwr->lipm));\n+\trte_memcpy(fwr->fip, f->fs.val.fip, sizeof(fwr->fip));\n+\trte_memcpy(fwr->fipm, f->fs.mask.fip, sizeof(fwr->fipm));\n+\tfwr->lp = cpu_to_be16(f->fs.val.lport);\n+\tfwr->lpm = cpu_to_be16(f->fs.mask.lport);\n+\tfwr->fp = cpu_to_be16(f->fs.val.fport);\n+\tfwr->fpm = cpu_to_be16(f->fs.mask.fport);\n+\n+\t/*\n+\t * Mark the filter as \"pending\" and ship off the Filter Work Request.\n+\t * When we get the Work Request Reply we'll clear the pending status.\n+\t */\n+\tf->pending = 1;\n+\tt4_mgmt_tx(ctrlq, mbuf);\n+\treturn 0;\n+\n+error:\n+\trte_pktmbuf_free(mbuf);\n+out:\n+\treturn ret;\n+}\n+\n+/**\n+ * Check a delete filter request for validity and send it to the hardware.\n+ * Return 0 on success, an error number otherwise.  We attach any provided\n+ * filter operation context to the internal filter specification in order to\n+ * facilitate signaling completion of the operation.\n+ */\n+int cxgbe_del_filter(struct rte_eth_dev *dev, unsigned int filter_id,\n+\t\t     struct ch_filter_specification *fs,\n+\t\t     struct filter_ctx *ctx)\n+{\n+\tstruct port_info *pi = (struct port_info *)(dev->data->dev_private);\n+\tstruct adapter *adapter = pi->adapter;\n+\tstruct filter_entry *f;\n+\tint ret;\n+\n+\tif (filter_id >= adapter->tids.nftids)\n+\t\treturn -ERANGE;\n+\n+\tret = is_filter_set(&adapter->tids, filter_id, fs->type);\n+\tif (!ret) {\n+\t\tdev_warn(adap, \"%s: could not find filter entry: %u\\n\",\n+\t\t\t __func__, filter_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tf = &adapter->tids.ftid_tab[filter_id];\n+\tret = writable_filter(f);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (f->valid) {\n+\t\tf->ctx = ctx;\n+\t\tcxgbe_clear_ftid(&adapter->tids,\n+\t\t\t\t f->tid - adapter->tids.ftid_base,\n+\t\t\t\t f->fs.type ? FILTER_TYPE_IPV6 :\n+\t\t\t\t\t      FILTER_TYPE_IPV4);\n+\t\treturn del_filter_wr(dev, filter_id);\n+\t}\n+\n+\t/*\n+\t * If the caller has passed in a Completion Context then we need to\n+\t * mark it as a successful completion so they don't stall waiting\n+\t * for it.\n+\t */\n+\tif (ctx) {\n+\t\tctx->result = 0;\n+\t\tt4_complete(&ctx->completion);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * Check a Chelsio Filter Request for validity, convert it into our internal\n+ * format and send it to the hardware.  Return 0 on success, an error number\n+ * otherwise.  We attach any provided filter operation context to the internal\n+ * filter specification in order to facilitate signaling completion of the\n+ * operation.\n+ */\n+int cxgbe_set_filter(struct rte_eth_dev *dev, unsigned int filter_id,\n+\t\t     struct ch_filter_specification *fs,\n+\t\t     struct filter_ctx *ctx)\n+{\n+\tstruct port_info *pi = ethdev2pinfo(dev);\n+\tstruct adapter *adapter = pi->adapter;\n+\tu32 iconf;\n+\tunsigned int fidx, iq, fid_bit = 0;\n+\tstruct filter_entry *f;\n+\tint ret;\n+\n+\tif (filter_id >= adapter->tids.nftids)\n+\t\treturn -ERANGE;\n+\n+\tret = validate_filter(adapter, fs);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = is_filter_set(&adapter->tids, filter_id, fs->type);\n+\tif (ret)\n+\t\treturn -EBUSY;\n+\n+\tiq = get_filter_steerq(dev, fs);\n+\n+\t/*\n+\t * IPv6 filters occupy four slots and must be aligned on\n+\t * four-slot boundaries.  IPv4 filters only occupy a single\n+\t * slot and have no alignment requirements but writing a new\n+\t * IPv4 filter into the middle of an existing IPv6 filter\n+\t * requires clearing the old IPv6 filter.\n+\t */\n+\tif (fs->type == FILTER_TYPE_IPV4) { /* IPv4 */\n+\t\t/*\n+\t\t * If our IPv4 filter isn't being written to a\n+\t\t * multiple of four filter index and there's an IPv6\n+\t\t * filter at the multiple of 4 base slot, then we need\n+\t\t * to delete that IPv6 filter ...\n+\t\t */\n+\t\tfidx = filter_id & ~0x3;\n+\t\tif (fidx != filter_id && adapter->tids.ftid_tab[fidx].fs.type) {\n+\t\t\tf = &adapter->tids.ftid_tab[fidx];\n+\t\t\tret = delete_filter(dev, fidx);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t\tif (f->valid) {\n+\t\t\t\tfid_bit = f->tid;\n+\t\t\t\tfid_bit -= adapter->tids.ftid_base;\n+\t\t\t\tcxgbe_clear_ftid(&adapter->tids,\n+\t\t\t\t\t\t fid_bit, FILTER_TYPE_IPV6);\n+\t\t\t}\n+\t\t}\n+\t} else { /* IPv6 */\n+\t\t/*\n+\t\t * Ensure that the IPv6 filter is aligned on a\n+\t\t * multiple of 4 boundary.\n+\t\t */\n+\t\tif (filter_id & 0x3)\n+\t\t\treturn -EINVAL;\n+\n+\t\t/*\n+\t\t * Check all except the base overlapping IPv4 filter\n+\t\t * slots.\n+\t\t */\n+\t\tfor (fidx = filter_id + 1; fidx < filter_id + 4; fidx++) {\n+\t\t\tf = &adapter->tids.ftid_tab[fidx];\n+\t\t\tret = delete_filter(dev, fidx);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t\tif (f->valid) {\n+\t\t\t\tfid_bit = f->tid;\n+\t\t\t\tfid_bit -=  adapter->tids.ftid_base;\n+\t\t\t\tcxgbe_clear_ftid(&adapter->tids,\n+\t\t\t\t\t\t fid_bit, FILTER_TYPE_IPV4);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Check to make sure that provided filter index is not\n+\t * already in use by someone else\n+\t */\n+\tf = &adapter->tids.ftid_tab[filter_id];\n+\tif (f->valid)\n+\t\treturn -EBUSY;\n+\n+\tfidx = adapter->tids.ftid_base + filter_id;\n+\tfid_bit = filter_id;\n+\tret = cxgbe_set_ftid(&adapter->tids, fid_bit,\n+\t\t\t     fs->type ? FILTER_TYPE_IPV6 : FILTER_TYPE_IPV4);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/*\n+\t * Check to make sure the filter requested is writable ...\n+\t */\n+\tret = writable_filter(f);\n+\tif (ret) {\n+\t\t/* Clear the bits we have set above */\n+\t\tcxgbe_clear_ftid(&adapter->tids, fid_bit,\n+\t\t\t\t fs->type ? FILTER_TYPE_IPV6 :\n+\t\t\t\t\t    FILTER_TYPE_IPV4);\n+\t\treturn ret;\n+\t}\n+\n+\t/*\n+\t * Clear out any old resources being used by the filter before\n+\t * we start constructing the new filter.\n+\t */\n+\tif (f->valid)\n+\t\tclear_filter(f);\n+\n+\t/*\n+\t * Convert the filter specification into our internal format.\n+\t * We copy the PF/VF specification into the Outer VLAN field\n+\t * here so the rest of the code -- including the interface to\n+\t * the firmware -- doesn't have to constantly do these checks.\n+\t */\n+\tf->fs = *fs;\n+\tf->fs.iq = iq;\n+\tf->dev = dev;\n+\n+\ticonf = adapter->params.tp.ingress_config;\n+\tif (iconf & F_VNIC) {\n+\t\tf->fs.val.ovlan = (fs->val.pf << 13) | fs->val.vf;\n+\t\tf->fs.mask.ovlan = (fs->mask.pf << 13) | fs->mask.vf;\n+\t\tf->fs.val.ovlan_vld = fs->val.pfvf_vld;\n+\t\tf->fs.mask.ovlan_vld = fs->mask.pfvf_vld;\n+\t}\n+\n+\t/*\n+\t * Attempt to set the filter.  If we don't succeed, we clear\n+\t * it and return the failure.\n+\t */\n+\tf->ctx = ctx;\n+\tf->tid = fidx; /* Save the actual tid */\n+\tret = set_filter_wr(dev, filter_id);\n+\tif (ret) {\n+\t\tfid_bit = f->tid - adapter->tids.ftid_base;\n+\t\tcxgbe_clear_ftid(&adapter->tids, fid_bit,\n+\t\t\t\t fs->type ? FILTER_TYPE_IPV6 :\n+\t\t\t\t\t    FILTER_TYPE_IPV4);\n+\t\tclear_filter(f);\n+\t}\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * Handle a LE-TCAM filter write/deletion reply.\n+ */\n+void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl)\n+{\n+\tstruct filter_entry *f = NULL;\n+\tunsigned int tid = GET_TID(rpl);\n+\tint idx, max_fidx = adap->tids.nftids;\n+\n+\t/* Get the corresponding filter entry for this tid */\n+\tif (adap->tids.ftid_tab) {\n+\t\t/* Check this in normal filter region */\n+\t\tidx = tid - adap->tids.ftid_base;\n+\t\tif (idx >= max_fidx)\n+\t\t\treturn;\n+\n+\t\tf = &adap->tids.ftid_tab[idx];\n+\t\tif (f->tid != tid)\n+\t\t\treturn;\n+\t}\n+\n+\t/* We found the filter entry for this tid */\n+\tif (f) {\n+\t\tunsigned int ret = G_COOKIE(rpl->cookie);\n+\t\tstruct filter_ctx *ctx;\n+\n+\t\t/*\n+\t\t * Pull off any filter operation context attached to the\n+\t\t * filter.\n+\t\t */\n+\t\tctx = f->ctx;\n+\t\tf->ctx = NULL;\n+\n+\t\tif (ret == FW_FILTER_WR_FLT_DELETED) {\n+\t\t\t/*\n+\t\t\t * Clear the filter when we get confirmation from the\n+\t\t\t * hardware that the filter has been deleted.\n+\t\t\t */\n+\t\t\tclear_filter(f);\n+\t\t\tif (ctx)\n+\t\t\t\tctx->result = 0;\n+\t\t} else if (ret == FW_FILTER_WR_FLT_ADDED) {\n+\t\t\tf->pending = 0;  /* asynchronous setup completed */\n+\t\t\tf->valid = 1;\n+\t\t\tif (ctx) {\n+\t\t\t\tctx->tid = f->tid;\n+\t\t\t\tctx->result = 0;\n+\t\t\t}\n+\n+\t\t\tif (f->fs.newsmac) {\n+\t\t\t\t/* do a set-tcb for smac-sel and CWR bit.. */\n+\t\t\t\tset_tcb_tflag(adap, f->tid, S_TF_CCTRL_CWR,\n+\t\t\t\t\t      1, 1);\n+\t\t\t\tset_tcb_field(adap, f->tid, W_TCB_SMAC_SEL,\n+\t\t\t\t\t      V_TCB_SMAC_SEL(M_TCB_SMAC_SEL),\n+\t\t\t\t\t      V_TCB_SMAC_SEL(f->smtidx), 1);\n+\t\t\t}\n+\t\t} else {\n+\t\t\t/*\n+\t\t\t * Something went wrong.  Issue a warning about the\n+\t\t\t * problem and clear everything out.\n+\t\t\t */\n+\t\t\tdev_warn(adap, \"filter %u setup failed with error %u\\n\",\n+\t\t\t\t idx, ret);\n+\t\t\tclear_filter(f);\n+\t\t\tif (ctx)\n+\t\t\t\tctx->result = -EINVAL;\n+\t\t}\n+\n+\t\tif (ctx)\n+\t\t\tt4_complete(&ctx->completion);\n+\t}\n+}\ndiff --git a/drivers/net/cxgbe/cxgbe_filter.h b/drivers/net/cxgbe/cxgbe_filter.h\nindex b03ccca..96c15d2 100644\n--- a/drivers/net/cxgbe/cxgbe_filter.h\n+++ b/drivers/net/cxgbe/cxgbe_filter.h\n@@ -34,6 +34,8 @@\n #ifndef _CXGBE_FILTER_H_\n #define _CXGBE_FILTER_H_\n \n+#include \"t4_msg.h\"\n+\n /*\n  * Defined bit width of user definable filter tuples\n  */\n@@ -232,4 +234,20 @@ struct filter_entry {\n \t */\n \tstruct ch_filter_specification fs;\n };\n+\n+struct adapter;\n+\n+void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl);\n+void clear_filter(struct filter_entry *f);\n+int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx);\n+int delete_filter(struct rte_eth_dev *dev, unsigned int fidx);\n+int writable_filter(struct filter_entry *f);\n+int cxgbe_set_filter(struct rte_eth_dev *dev, unsigned int filter_id,\n+\t\t     struct ch_filter_specification *fs,\n+\t\t     struct filter_ctx *ctx);\n+int cxgbe_del_filter(struct rte_eth_dev *dev, unsigned int filter_id,\n+\t\t     struct ch_filter_specification *fs,\n+\t\t     struct filter_ctx *ctx);\n+\n+void cxgbe_clear_all_filters(struct adapter *adapter);\n #endif /* _CXGBE_FILTER_H_ */\ndiff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c\nindex e7d017e..dfb6567 100644\n--- a/drivers/net/cxgbe/cxgbe_main.c\n+++ b/drivers/net/cxgbe/cxgbe_main.c\n@@ -69,6 +69,7 @@\n #include \"clip_tbl.h\"\n #include \"l2t.h\"\n #include \"smt.h\"\n+#include \"cxgbe_filter.h\"\n \n /**\n  * Allocate a chunk of memory. The allocated memory is cleared.\n@@ -118,6 +119,10 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,\n \t\tconst struct cpl_fw6_msg *msg = (const void *)rsp;\n \n \t\tt4_handle_fw_rpl(q->adapter, msg->data);\n+\t} else if (opcode == CPL_SET_TCB_RPL) {\n+\t\tconst struct cpl_set_tcb_rpl *p = (const void *)rsp;\n+\n+\t\tfilter_rpl(q->adapter, p);\n \t} else if (opcode == CPL_SMT_WRITE_RPL) {\n \t\tconst struct cpl_smt_write_rpl *p = (const void *)rsp;\n \n@@ -1232,6 +1237,7 @@ void cxgbe_close(struct adapter *adapter)\n \tint i;\n \n \tif (adapter->flags & FULL_INIT_DONE) {\n+\t\tcxgbe_clear_all_filters(adapter);\n \t\ttid_free(&adapter->tids);\n \t\tt4_cleanup_clip_tbl(adapter);\n \t\tt4_cleanup_l2t(adapter);\ndiff --git a/drivers/net/cxgbe/cxgbe_ofld.h b/drivers/net/cxgbe/cxgbe_ofld.h\nindex 19971e7..115472e 100644\n--- a/drivers/net/cxgbe/cxgbe_ofld.h\n+++ b/drivers/net/cxgbe/cxgbe_ofld.h\n@@ -47,6 +47,11 @@\n \t(w)->wr.wr_lo = cpu_to_be64(0); \\\n } while (0)\n \n+#define INIT_TP_WR_MIT_CPL(w, cpl, tid) do { \\\n+\tINIT_TP_WR(w, tid); \\\n+\tOPCODE_TID(w) = cpu_to_be32(MK_OPCODE_TID(cpl, tid)); \\\n+} while (0)\n+\n /*\n  * Max # of ATIDs.  The absolute HW max is 16K but we keep it lower.\n  */\n",
    "prefixes": [
        "dpdk-dev",
        "08/10"
    ]
}