get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 41991,
    "url": "http://patches.dpdk.org/api/patches/41991/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1732118468c605f88826746a2e0b59f51927a40e.1530295732.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": "<1732118468c605f88826746a2e0b59f51927a40e.1530295732.git.rahul.lakkireddy@chelsio.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1732118468c605f88826746a2e0b59f51927a40e.1530295732.git.rahul.lakkireddy@chelsio.com",
    "date": "2018-06-29T18:12:19",
    "name": "[4/9] net/cxgbe: add support to offload flows to HASH region",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "d4fcb640d138f23cc5fa2e4ccb62efe77bb7381c",
    "submitter": {
        "id": 241,
        "url": "http://patches.dpdk.org/api/people/241/?format=api",
        "name": "Rahul Lakkireddy",
        "email": "rahul.lakkireddy@chelsio.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1732118468c605f88826746a2e0b59f51927a40e.1530295732.git.rahul.lakkireddy@chelsio.com/mbox/",
    "series": [
        {
            "id": 331,
            "url": "http://patches.dpdk.org/api/series/331/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=331",
            "date": "2018-06-29T18:12:15",
            "name": "net/cxgbe: add support for offloading flows to HASH region",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/331/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/41991/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/41991/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 [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id F12B31BA6F;\n\tFri, 29 Jun 2018 20:13:45 +0200 (CEST)",
            "from stargate.chelsio.com (stargate.chelsio.com [12.32.117.8])\n\tby dpdk.org (Postfix) with ESMTP id 5D95E1B911\n\tfor <dev@dpdk.org>; Fri, 29 Jun 2018 20:13:43 +0200 (CEST)",
            "from localhost (scalar.blr.asicdesigners.com [10.193.185.94])\n\tby stargate.chelsio.com (8.13.8/8.13.8) with ESMTP id w5TIDbWe028623; \n\tFri, 29 Jun 2018 11:13:38 -0700"
        ],
        "From": "Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>",
        "To": "dev@dpdk.org",
        "Cc": "shaguna@chelsio.com, indranil@chelsio.com, nirranjan@chelsio.com",
        "Date": "Fri, 29 Jun 2018 23:42:19 +0530",
        "Message-Id": "<1732118468c605f88826746a2e0b59f51927a40e.1530295732.git.rahul.lakkireddy@chelsio.com>",
        "X-Mailer": "git-send-email 2.5.3",
        "In-Reply-To": [
            "<cover.1530295732.git.rahul.lakkireddy@chelsio.com>",
            "<cover.1530295732.git.rahul.lakkireddy@chelsio.com>"
        ],
        "References": [
            "<cover.1530295732.git.rahul.lakkireddy@chelsio.com>",
            "<cover.1530295732.git.rahul.lakkireddy@chelsio.com>"
        ],
        "Subject": "[dpdk-dev] [PATCH 4/9] net/cxgbe: add support to offload flows to\n\tHASH region",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Shagun Agrawal <shaguna@chelsio.com>\n\nAdd interface to offload flows to HASH region. Translate internal\nfilter specification to requests to offload flows to HASH region.\nSave the returned hash index of the offloaded flow for deletion later.\n\nSigned-off-by: Shagun Agrawal <shaguna@chelsio.com>\nSigned-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>\n---\n drivers/net/cxgbe/base/adapter.h        |  11 ++\n drivers/net/cxgbe/base/t4_msg.h         | 110 +++++++++++++\n drivers/net/cxgbe/base/t4fw_interface.h |   6 +\n drivers/net/cxgbe/cxgbe_filter.c        | 265 +++++++++++++++++++++++++++++++-\n drivers/net/cxgbe/cxgbe_filter.h        |   1 +\n drivers/net/cxgbe/cxgbe_flow.c          |  10 +-\n drivers/net/cxgbe/cxgbe_main.c          |  56 +++++++\n drivers/net/cxgbe/cxgbe_ofld.h          |  25 +++\n 8 files changed, 481 insertions(+), 3 deletions(-)",
    "diff": "diff --git a/drivers/net/cxgbe/base/adapter.h b/drivers/net/cxgbe/base/adapter.h\nindex 3ed3252e8..e98dd2182 100644\n--- a/drivers/net/cxgbe/base/adapter.h\n+++ b/drivers/net/cxgbe/base/adapter.h\n@@ -771,6 +771,17 @@ static inline void t4_complete(struct t4_completion *c)\n \tt4_os_unlock(&c->lock);\n }\n \n+/**\n+ * cxgbe_port_viid - get the VI id of a port\n+ * @dev: the device for the port\n+ *\n+ * Return the VI id of the given port.\n+ */\n+static inline unsigned int cxgbe_port_viid(const struct rte_eth_dev *dev)\n+{\n+\treturn ethdev2pinfo(dev)->viid;\n+}\n+\n void *t4_alloc_mem(size_t size);\n void t4_free_mem(void *addr);\n #define t4_os_alloc(_size)     t4_alloc_mem((_size))\ndiff --git a/drivers/net/cxgbe/base/t4_msg.h b/drivers/net/cxgbe/base/t4_msg.h\nindex 43d1cb66f..4112ff212 100644\n--- a/drivers/net/cxgbe/base/t4_msg.h\n+++ b/drivers/net/cxgbe/base/t4_msg.h\n@@ -7,7 +7,10 @@\n #define T4_MSG_H\n \n enum {\n+\tCPL_ACT_OPEN_REQ      = 0x3,\n+\tCPL_ACT_OPEN_RPL      = 0x25,\n \tCPL_SET_TCB_RPL       = 0x3A,\n+\tCPL_ACT_OPEN_REQ6     = 0x83,\n \tCPL_SGE_EGR_UPDATE    = 0xA5,\n \tCPL_FW4_MSG           = 0xC0,\n \tCPL_FW6_MSG           = 0xE0,\n@@ -15,6 +18,15 @@ enum {\n \tCPL_TX_PKT_XT         = 0xEE,\n };\n \n+enum CPL_error {\n+\tCPL_ERR_NONE               = 0,\n+\tCPL_ERR_TCAM_FULL          = 3,\n+};\n+\n+enum {\n+\tULP_MODE_NONE          = 0,\n+};\n+\n enum {                     /* TX_PKT_XT checksum types */\n \tTX_CSUM_TCPIP  = 8,\n \tTX_CSUM_UDPIP  = 9,\n@@ -26,13 +38,24 @@ union opcode_tid {\n \t__u8 opcode;\n };\n \n+#define S_CPL_OPCODE    24\n+#define V_CPL_OPCODE(x) ((x) << S_CPL_OPCODE)\n+\n #define G_TID(x)    ((x) & 0xFFFFFF)\n \n+/* tid is assumed to be 24-bits */\n+#define MK_OPCODE_TID(opcode, tid) (V_CPL_OPCODE(opcode) | (tid))\n+\n #define OPCODE_TID(cmd) ((cmd)->ot.opcode_tid)\n \n /* extract the TID from a CPL command */\n #define GET_TID(cmd) (G_TID(be32_to_cpu(OPCODE_TID(cmd))))\n \n+/* partitioning of TID fields that also carry a queue id */\n+#define S_TID_TID    0\n+#define M_TID_TID    0x3fff\n+#define G_TID_TID(x) (((x) >> S_TID_TID) & M_TID_TID)\n+\n struct rss_header {\n \t__u8 opcode;\n #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN\n@@ -79,6 +102,93 @@ struct work_request_hdr {\n #define V_COOKIE(x) ((x) << S_COOKIE)\n #define G_COOKIE(x) (((x) >> S_COOKIE) & M_COOKIE)\n \n+/* option 0 fields */\n+#define S_DELACK    5\n+#define V_DELACK(x) ((x) << S_DELACK)\n+\n+#define S_NON_OFFLOAD    7\n+#define V_NON_OFFLOAD(x) ((x) << S_NON_OFFLOAD)\n+#define F_NON_OFFLOAD    V_NON_OFFLOAD(1U)\n+\n+#define S_ULP_MODE    8\n+#define V_ULP_MODE(x) ((x) << S_ULP_MODE)\n+\n+#define S_SMAC_SEL    28\n+#define V_SMAC_SEL(x) ((__u64)(x) << S_SMAC_SEL)\n+\n+#define S_TCAM_BYPASS    48\n+#define V_TCAM_BYPASS(x) ((__u64)(x) << S_TCAM_BYPASS)\n+#define F_TCAM_BYPASS    V_TCAM_BYPASS(1ULL)\n+\n+/* option 2 fields */\n+#define S_RSS_QUEUE    0\n+#define V_RSS_QUEUE(x) ((x) << S_RSS_QUEUE)\n+\n+#define S_RSS_QUEUE_VALID    10\n+#define V_RSS_QUEUE_VALID(x) ((x) << S_RSS_QUEUE_VALID)\n+#define F_RSS_QUEUE_VALID    V_RSS_QUEUE_VALID(1U)\n+\n+#define S_CONG_CNTRL    14\n+#define V_CONG_CNTRL(x) ((x) << S_CONG_CNTRL)\n+\n+#define S_RX_CHANNEL    26\n+#define V_RX_CHANNEL(x) ((x) << S_RX_CHANNEL)\n+#define F_RX_CHANNEL    V_RX_CHANNEL(1U)\n+\n+#define S_T5_OPT_2_VALID    31\n+#define V_T5_OPT_2_VALID(x) ((x) << S_T5_OPT_2_VALID)\n+#define F_T5_OPT_2_VALID    V_T5_OPT_2_VALID(1U)\n+\n+struct cpl_t6_act_open_req {\n+\tWR_HDR;\n+\tunion opcode_tid ot;\n+\t__be16 local_port;\n+\t__be16 peer_port;\n+\t__be32 local_ip;\n+\t__be32 peer_ip;\n+\t__be64 opt0;\n+\t__be32 rsvd;\n+\t__be32 opt2;\n+\t__be64 params;\n+\t__be32 rsvd2;\n+\t__be32 opt3;\n+};\n+\n+struct cpl_t6_act_open_req6 {\n+\tWR_HDR;\n+\tunion opcode_tid ot;\n+\t__be16 local_port;\n+\t__be16 peer_port;\n+\t__be64 local_ip_hi;\n+\t__be64 local_ip_lo;\n+\t__be64 peer_ip_hi;\n+\t__be64 peer_ip_lo;\n+\t__be64 opt0;\n+\t__be32 rsvd;\n+\t__be32 opt2;\n+\t__be64 params;\n+\t__be32 rsvd2;\n+\t__be32 opt3;\n+};\n+\n+#define S_FILTER_TUPLE\t24\n+#define V_FILTER_TUPLE(x) ((x) << S_FILTER_TUPLE)\n+\n+struct cpl_act_open_rpl {\n+\tRSS_HDR\n+\tunion opcode_tid ot;\n+\t__be32 atid_status;\n+};\n+\n+/* cpl_act_open_rpl.atid_status fields */\n+#define S_AOPEN_STATUS    0\n+#define M_AOPEN_STATUS    0xFF\n+#define G_AOPEN_STATUS(x) (((x) >> S_AOPEN_STATUS) & M_AOPEN_STATUS)\n+\n+#define S_AOPEN_ATID    8\n+#define M_AOPEN_ATID    0xFFFFFF\n+#define G_AOPEN_ATID(x) (((x) >> S_AOPEN_ATID) & M_AOPEN_ATID)\n+\n struct cpl_set_tcb_rpl {\n \tRSS_HDR\n \tunion opcode_tid ot;\ndiff --git a/drivers/net/cxgbe/base/t4fw_interface.h b/drivers/net/cxgbe/base/t4fw_interface.h\nindex 2433bf20c..19bcfc124 100644\n--- a/drivers/net/cxgbe/base/t4fw_interface.h\n+++ b/drivers/net/cxgbe/base/t4fw_interface.h\n@@ -55,6 +55,7 @@ enum fw_memtype {\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 \tFW_ETH_TX_PKT_VM_WR\t= 0x11,\n@@ -93,6 +94,11 @@ struct fw_wr_hdr {\n #define G_FW_WR_EQUEQ(x)\t(((x) >> S_FW_WR_EQUEQ) & M_FW_WR_EQUEQ)\n #define F_FW_WR_EQUEQ\t\tV_FW_WR_EQUEQ(1U)\n \n+/* flow context identifier (lo)\n+ */\n+#define S_FW_WR_FLOWID\t\t8\n+#define V_FW_WR_FLOWID(x)\t((x) << S_FW_WR_FLOWID)\n+\n /* length in units of 16-bytes (lo)\n  */\n #define S_FW_WR_LEN16\t\t0\ndiff --git a/drivers/net/cxgbe/cxgbe_filter.c b/drivers/net/cxgbe/cxgbe_filter.c\nindex bb2ebaa62..bac7aa291 100644\n--- a/drivers/net/cxgbe/cxgbe_filter.c\n+++ b/drivers/net/cxgbe/cxgbe_filter.c\n@@ -2,7 +2,7 @@\n  * Copyright(c) 2018 Chelsio Communications.\n  * All rights reserved.\n  */\n-\n+#include <rte_net.h>\n #include \"common.h\"\n #include \"t4_regs.h\"\n #include \"cxgbe_filter.h\"\n@@ -159,6 +159,210 @@ int cxgbe_alloc_ftid(struct adapter *adap, unsigned int family)\n \treturn pos < size ? pos : -1;\n }\n \n+/**\n+ * Construct hash filter ntuple.\n+ */\n+static u64 hash_filter_ntuple(const struct filter_entry *f)\n+{\n+\tstruct adapter *adap = ethdev2adap(f->dev);\n+\tstruct tp_params *tp = &adap->params.tp;\n+\tu64 ntuple = 0;\n+\tu16 tcp_proto = IPPROTO_TCP; /* TCP Protocol Number */\n+\n+\tif (tp->protocol_shift >= 0) {\n+\t\tif (!f->fs.val.proto)\n+\t\t\tntuple |= (u64)tcp_proto << tp->protocol_shift;\n+\t\telse\n+\t\t\tntuple |= (u64)f->fs.val.proto << tp->protocol_shift;\n+\t}\n+\n+\tif (tp->ethertype_shift >= 0 && f->fs.mask.ethtype)\n+\t\tntuple |= (u64)(f->fs.val.ethtype) << tp->ethertype_shift;\n+\n+\tif (ntuple != tp->hash_filter_mask)\n+\t\treturn 0;\n+\n+\treturn ntuple;\n+}\n+\n+/**\n+ * Build a ACT_OPEN_REQ6 message for setting IPv6 hash filter.\n+ */\n+static void mk_act_open_req6(struct filter_entry *f, struct rte_mbuf *mbuf,\n+\t\t\t     unsigned int qid_filterid, struct adapter *adap)\n+{\n+\tstruct cpl_t6_act_open_req6 *req = NULL;\n+\tu64 local_lo, local_hi, peer_lo, peer_hi;\n+\tu32 *lip = (u32 *)f->fs.val.lip;\n+\tu32 *fip = (u32 *)f->fs.val.fip;\n+\n+\tswitch (CHELSIO_CHIP_VERSION(adap->params.chip)) {\n+\tcase CHELSIO_T6:\n+\t\treq = rte_pktmbuf_mtod(mbuf, struct cpl_t6_act_open_req6 *);\n+\n+\t\tINIT_TP_WR(req, 0);\n+\t\tbreak;\n+\tdefault:\n+\t\tdev_err(adap, \"%s: unsupported chip type!\\n\", __func__);\n+\t\treturn;\n+\t}\n+\n+\tlocal_hi = ((u64)lip[1]) << 32 | lip[0];\n+\tlocal_lo = ((u64)lip[3]) << 32 | lip[2];\n+\tpeer_hi = ((u64)fip[1]) << 32 | fip[0];\n+\tpeer_lo = ((u64)fip[3]) << 32 | fip[2];\n+\n+\tOPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,\n+\t\t\t\t\t\t    qid_filterid));\n+\treq->local_port = cpu_to_be16(f->fs.val.lport);\n+\treq->peer_port = cpu_to_be16(f->fs.val.fport);\n+\treq->local_ip_hi = local_hi;\n+\treq->local_ip_lo = local_lo;\n+\treq->peer_ip_hi = peer_hi;\n+\treq->peer_ip_lo = peer_lo;\n+\treq->opt0 = cpu_to_be64(V_DELACK(f->fs.hitcnts) |\n+\t\t\t\tV_SMAC_SEL((cxgbe_port_viid(f->dev) & 0x7F)\n+\t\t\t\t\t   << 1) |\n+\t\t\t\tV_ULP_MODE(ULP_MODE_NONE) |\n+\t\t\t\tF_TCAM_BYPASS | F_NON_OFFLOAD);\n+\treq->params = cpu_to_be64(V_FILTER_TUPLE(hash_filter_ntuple(f)));\n+\treq->opt2 = cpu_to_be32(F_RSS_QUEUE_VALID |\n+\t\t\t    V_RSS_QUEUE(f->fs.iq) |\n+\t\t\t    F_T5_OPT_2_VALID |\n+\t\t\t    F_RX_CHANNEL |\n+\t\t\t    V_CONG_CNTRL((f->fs.action == FILTER_DROP) |\n+\t\t\t\t\t (f->fs.dirsteer << 1)));\n+}\n+\n+/**\n+ * Build a ACT_OPEN_REQ message for setting IPv4 hash filter.\n+ */\n+static void mk_act_open_req(struct filter_entry *f, struct rte_mbuf *mbuf,\n+\t\t\t    unsigned int qid_filterid, struct adapter *adap)\n+{\n+\tstruct cpl_t6_act_open_req *req = NULL;\n+\n+\tswitch (CHELSIO_CHIP_VERSION(adap->params.chip)) {\n+\tcase CHELSIO_T6:\n+\t\treq = rte_pktmbuf_mtod(mbuf, struct cpl_t6_act_open_req *);\n+\n+\t\tINIT_TP_WR(req, 0);\n+\t\tbreak;\n+\tdefault:\n+\t\tdev_err(adap, \"%s: unsupported chip type!\\n\", __func__);\n+\t\treturn;\n+\t}\n+\n+\tOPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,\n+\t\t\t\t\t\t    qid_filterid));\n+\treq->local_port = cpu_to_be16(f->fs.val.lport);\n+\treq->peer_port = cpu_to_be16(f->fs.val.fport);\n+\treq->local_ip = f->fs.val.lip[0] | f->fs.val.lip[1] << 8 |\n+\t\t\tf->fs.val.lip[2] << 16 | f->fs.val.lip[3] << 24;\n+\treq->peer_ip = f->fs.val.fip[0] | f->fs.val.fip[1] << 8 |\n+\t\t\tf->fs.val.fip[2] << 16 | f->fs.val.fip[3] << 24;\n+\treq->opt0 = cpu_to_be64(V_DELACK(f->fs.hitcnts) |\n+\t\t\t\tV_SMAC_SEL((cxgbe_port_viid(f->dev) & 0x7F)\n+\t\t\t\t\t   << 1) |\n+\t\t\t\tV_ULP_MODE(ULP_MODE_NONE) |\n+\t\t\t\tF_TCAM_BYPASS | F_NON_OFFLOAD);\n+\treq->params = cpu_to_be64(V_FILTER_TUPLE(hash_filter_ntuple(f)));\n+\treq->opt2 = cpu_to_be32(F_RSS_QUEUE_VALID |\n+\t\t\t    V_RSS_QUEUE(f->fs.iq) |\n+\t\t\t    F_T5_OPT_2_VALID |\n+\t\t\t    F_RX_CHANNEL |\n+\t\t\t    V_CONG_CNTRL((f->fs.action == FILTER_DROP) |\n+\t\t\t\t\t (f->fs.dirsteer << 1)));\n+}\n+\n+/**\n+ * Set the specified hash filter.\n+ */\n+static int cxgbe_set_hash_filter(struct rte_eth_dev *dev,\n+\t\t\t\t struct ch_filter_specification *fs,\n+\t\t\t\t struct filter_ctx *ctx)\n+{\n+\tstruct port_info *pi = ethdev2pinfo(dev);\n+\tstruct adapter *adapter = pi->adapter;\n+\tstruct tid_info *t = &adapter->tids;\n+\tstruct filter_entry *f;\n+\tstruct rte_mbuf *mbuf;\n+\tstruct sge_ctrl_txq *ctrlq;\n+\tunsigned int iq;\n+\tint atid, size;\n+\tint ret = 0;\n+\n+\tret = validate_filter(adapter, fs);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tiq = get_filter_steerq(dev, fs);\n+\n+\tctrlq = &adapter->sge.ctrlq[pi->port_id];\n+\n+\tf = t4_os_alloc(sizeof(*f));\n+\tif (!f)\n+\t\tgoto out_err;\n+\n+\tf->fs = *fs;\n+\tf->ctx = ctx;\n+\tf->dev = dev;\n+\tf->fs.iq = iq;\n+\n+\tatid = cxgbe_alloc_atid(t, f);\n+\tif (atid < 0)\n+\t\tgoto out_err;\n+\n+\tif (f->fs.type) {\n+\t\t/* IPv6 hash filter */\n+\t\tf->clipt = cxgbe_clip_alloc(f->dev, (u32 *)&f->fs.val.lip);\n+\t\tif (!f->clipt)\n+\t\t\tgoto free_atid;\n+\n+\t\tsize = sizeof(struct cpl_t6_act_open_req6);\n+\t\tmbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);\n+\t\tif (!mbuf) {\n+\t\t\tret = -ENOMEM;\n+\t\t\tgoto free_clip;\n+\t\t}\n+\n+\t\tmbuf->data_len = size;\n+\t\tmbuf->pkt_len = mbuf->data_len;\n+\n+\t\tmk_act_open_req6(f, mbuf,\n+\t\t\t\t ((adapter->sge.fw_evtq.abs_id << 14) | atid),\n+\t\t\t\t adapter);\n+\t} else {\n+\t\t/* IPv4 hash filter */\n+\t\tsize = sizeof(struct cpl_t6_act_open_req);\n+\t\tmbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);\n+\t\tif (!mbuf) {\n+\t\t\tret = -ENOMEM;\n+\t\t\tgoto free_atid;\n+\t\t}\n+\n+\t\tmbuf->data_len = size;\n+\t\tmbuf->pkt_len = mbuf->data_len;\n+\n+\t\tmk_act_open_req(f, mbuf,\n+\t\t\t\t((adapter->sge.fw_evtq.abs_id << 14) | atid),\n+\t\t\t\tadapter);\n+\t}\n+\n+\tf->pending = 1;\n+\tt4_mgmt_tx(ctrlq, mbuf);\n+\treturn 0;\n+\n+free_clip:\n+\tcxgbe_clip_release(f->dev, f->clipt);\n+free_atid:\n+\tcxgbe_free_atid(t, atid);\n+\n+out_err:\n+\tt4_os_free(f);\n+\treturn ret;\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@@ -425,6 +629,9 @@ int cxgbe_set_filter(struct rte_eth_dev *dev, unsigned int filter_id,\n \tuint8_t bitoff[16] = {0};\n \tint ret;\n \n+\tif (is_hashfilter(adapter) && fs->cap)\n+\t\treturn cxgbe_set_hash_filter(dev, fs, ctx);\n+\n \tif (filter_id >= adapter->tids.nftids)\n \t\treturn -ERANGE;\n \n@@ -578,6 +785,62 @@ int cxgbe_set_filter(struct rte_eth_dev *dev, unsigned int filter_id,\n \treturn ret;\n }\n \n+/**\n+ * Handle a Hash filter write reply.\n+ */\n+void hash_filter_rpl(struct adapter *adap, const struct cpl_act_open_rpl *rpl)\n+{\n+\tstruct tid_info *t = &adap->tids;\n+\tstruct filter_entry *f;\n+\tstruct filter_ctx *ctx = NULL;\n+\tunsigned int tid = GET_TID(rpl);\n+\tunsigned int ftid = G_TID_TID(G_AOPEN_ATID\n+\t\t\t\t      (be32_to_cpu(rpl->atid_status)));\n+\tunsigned int status  = G_AOPEN_STATUS(be32_to_cpu(rpl->atid_status));\n+\n+\tf = lookup_atid(t, ftid);\n+\tif (!f) {\n+\t\tdev_warn(adap, \"%s: could not find filter entry: %d\\n\",\n+\t\t\t __func__, ftid);\n+\t\treturn;\n+\t}\n+\n+\tctx = f->ctx;\n+\tf->ctx = NULL;\n+\n+\tswitch (status) {\n+\tcase CPL_ERR_NONE: {\n+\t\tf->tid = tid;\n+\t\tf->pending = 0;  /* asynchronous setup completed */\n+\t\tf->valid = 1;\n+\n+\t\tcxgbe_insert_tid(t, f, f->tid, 0);\n+\t\tcxgbe_free_atid(t, ftid);\n+\t\tif (ctx) {\n+\t\t\tctx->tid = f->tid;\n+\t\t\tctx->result = 0;\n+\t\t}\n+\t\tbreak;\n+\t}\n+\tdefault:\n+\t\tdev_warn(adap, \"%s: filter creation failed with status = %u\\n\",\n+\t\t\t __func__, status);\n+\n+\t\tif (ctx) {\n+\t\t\tif (status == CPL_ERR_TCAM_FULL)\n+\t\t\t\tctx->result = -EAGAIN;\n+\t\t\telse\n+\t\t\t\tctx->result = -EINVAL;\n+\t\t}\n+\n+\t\tcxgbe_free_atid(t, ftid);\n+\t\tt4_os_free(f);\n+\t}\n+\n+\tif (ctx)\n+\t\tt4_complete(&ctx->completion);\n+}\n+\n /**\n  * Handle a LE-TCAM filter write/deletion reply.\n  */\ndiff --git a/drivers/net/cxgbe/cxgbe_filter.h b/drivers/net/cxgbe/cxgbe_filter.h\nindex ce115f69f..7c469c895 100644\n--- a/drivers/net/cxgbe/cxgbe_filter.h\n+++ b/drivers/net/cxgbe/cxgbe_filter.h\n@@ -223,6 +223,7 @@ int cxgbe_del_filter(struct rte_eth_dev *dev, unsigned int filter_id,\n \t\t     struct filter_ctx *ctx);\n int cxgbe_alloc_ftid(struct adapter *adap, unsigned int family);\n int init_hash_filter(struct adapter *adap);\n+void hash_filter_rpl(struct adapter *adap, const struct cpl_act_open_rpl *rpl);\n int validate_filter(struct adapter *adap, struct ch_filter_specification *fs);\n int cxgbe_get_filter_count(struct adapter *adapter, unsigned int fidx,\n \t\t\t   u64 *c, bool get_byte);\ndiff --git a/drivers/net/cxgbe/cxgbe_flow.c b/drivers/net/cxgbe/cxgbe_flow.c\nindex dfb5fac2b..4950cb41c 100644\n--- a/drivers/net/cxgbe/cxgbe_flow.c\n+++ b/drivers/net/cxgbe/cxgbe_flow.c\n@@ -452,6 +452,7 @@ static int __cxgbe_flow_create(struct rte_eth_dev *dev, struct rte_flow *flow)\n {\n \tstruct ch_filter_specification *fs = &flow->fs;\n \tstruct adapter *adap = ethdev2adap(dev);\n+\tstruct tid_info *t = &adap->tids;\n \tstruct filter_ctx ctx;\n \tunsigned int fidx;\n \tint err;\n@@ -484,8 +485,13 @@ static int __cxgbe_flow_create(struct rte_eth_dev *dev, struct rte_flow *flow)\n \t\treturn ctx.result;\n \t}\n \n-\tflow->fidx = fidx;\n-\tflow->f = &adap->tids.ftid_tab[fidx];\n+\tif (fs->cap) { /* to destroy the filter */\n+\t\tflow->fidx = ctx.tid;\n+\t\tflow->f = lookup_tid(t, ctx.tid);\n+\t} else {\n+\t\tflow->fidx = fidx;\n+\t\tflow->f = &adap->tids.ftid_tab[fidx];\n+\t}\n \n \treturn 0;\n }\ndiff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c\nindex 2050fe4db..c550dd5be 100644\n--- a/drivers/net/cxgbe/cxgbe_main.c\n+++ b/drivers/net/cxgbe/cxgbe_main.c\n@@ -91,6 +91,10 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,\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_ACT_OPEN_RPL) {\n+\t\tconst struct cpl_act_open_rpl *p = (const void *)rsp;\n+\n+\t\thash_filter_rpl(q->adapter, p);\n \t} else {\n \t\tdev_err(adapter, \"unexpected CPL %#x on FW event queue\\n\",\n \t\t\topcode);\n@@ -263,6 +267,58 @@ int cxgb4_set_rspq_intr_params(struct sge_rspq *q, unsigned int us,\n \treturn 0;\n }\n \n+/**\n+ * Allocate an active-open TID and set it to the supplied value.\n+ */\n+int cxgbe_alloc_atid(struct tid_info *t, void *data)\n+{\n+\tint atid = -1;\n+\n+\tt4_os_lock(&t->atid_lock);\n+\tif (t->afree) {\n+\t\tunion aopen_entry *p = t->afree;\n+\n+\t\tatid = p - t->atid_tab;\n+\t\tt->afree = p->next;\n+\t\tp->data = data;\n+\t\tt->atids_in_use++;\n+\t}\n+\tt4_os_unlock(&t->atid_lock);\n+\treturn atid;\n+}\n+\n+/**\n+ * Release an active-open TID.\n+ */\n+void cxgbe_free_atid(struct tid_info *t, unsigned int atid)\n+{\n+\tunion aopen_entry *p = &t->atid_tab[atid];\n+\n+\tt4_os_lock(&t->atid_lock);\n+\tp->next = t->afree;\n+\tt->afree = p;\n+\tt->atids_in_use--;\n+\tt4_os_unlock(&t->atid_lock);\n+}\n+\n+/**\n+ * Insert a TID.\n+ */\n+void cxgbe_insert_tid(struct tid_info *t, void *data, unsigned int tid,\n+\t\t      unsigned short family)\n+{\n+\tt->tid_tab[tid] = data;\n+\tif (t->hash_base && tid >= t->hash_base) {\n+\t\tif (family == FILTER_TYPE_IPV4)\n+\t\t\trte_atomic32_inc(&t->hash_tids_in_use);\n+\t} else {\n+\t\tif (family == FILTER_TYPE_IPV4)\n+\t\t\trte_atomic32_inc(&t->tids_in_use);\n+\t}\n+\n+\trte_atomic32_inc(&t->conns_in_use);\n+}\n+\n /**\n  * Free TID tables.\n  */\ndiff --git a/drivers/net/cxgbe/cxgbe_ofld.h b/drivers/net/cxgbe/cxgbe_ofld.h\nindex e97c42469..798e39828 100644\n--- a/drivers/net/cxgbe/cxgbe_ofld.h\n+++ b/drivers/net/cxgbe/cxgbe_ofld.h\n@@ -10,6 +10,15 @@\n \n #include \"cxgbe_filter.h\"\n \n+#define INIT_TP_WR(w, tid) do { \\\n+\t(w)->wr.wr_hi = cpu_to_be32(V_FW_WR_OP(FW_TP_WR) | \\\n+\t\t\t\tV_FW_WR_IMMDLEN(sizeof(*w) - sizeof(w->wr))); \\\n+\t(w)->wr.wr_mid = cpu_to_be32( \\\n+\t\t\t\tV_FW_WR_LEN16(DIV_ROUND_UP(sizeof(*w), 16)) | \\\n+\t\t\t\tV_FW_WR_FLOWID(tid)); \\\n+\t(w)->wr.wr_lo = cpu_to_be64(0); \\\n+} while (0)\n+\n /*\n  * Max # of ATIDs.  The absolute HW max is 16K but we keep it lower.\n  */\n@@ -46,4 +55,20 @@ struct tid_info {\n \trte_spinlock_t atid_lock __rte_cache_aligned;\n \trte_spinlock_t ftid_lock;\n };\n+\n+static inline void *lookup_tid(const struct tid_info *t, unsigned int tid)\n+{\n+\treturn tid < t->ntids ? t->tid_tab[tid] : NULL;\n+}\n+\n+static inline void *lookup_atid(const struct tid_info *t, unsigned int atid)\n+{\n+\treturn atid < t->natids ? t->atid_tab[atid].data : NULL;\n+}\n+\n+int cxgbe_alloc_atid(struct tid_info *t, void *data);\n+void cxgbe_free_atid(struct tid_info *t, unsigned int atid);\n+void cxgbe_insert_tid(struct tid_info *t, void *data, unsigned int tid,\n+\t\t      unsigned short family);\n+\n #endif /* _CXGBE_OFLD_H_ */\n",
    "prefixes": [
        "4/9"
    ]
}