get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 82559,
    "url": "https://patches.dpdk.org/api/patches/82559/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1603875616-272798-24-git-send-email-suanmingm@nvidia.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<1603875616-272798-24-git-send-email-suanmingm@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1603875616-272798-24-git-send-email-suanmingm@nvidia.com",
    "date": "2020-10-28T09:00:04",
    "name": "[v5,23/34] net/mlx5: make Rx queue thread safe",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "47abd6585f8862a7d815a942639edfd549f35dc9",
    "submitter": {
        "id": 1887,
        "url": "https://patches.dpdk.org/api/people/1887/?format=api",
        "name": "Suanming Mou",
        "email": "suanmingm@nvidia.com"
    },
    "delegate": {
        "id": 3268,
        "url": "https://patches.dpdk.org/api/users/3268/?format=api",
        "username": "rasland",
        "first_name": "Raslan",
        "last_name": "Darawsheh",
        "email": "rasland@nvidia.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1603875616-272798-24-git-send-email-suanmingm@nvidia.com/mbox/",
    "series": [
        {
            "id": 13411,
            "url": "https://patches.dpdk.org/api/series/13411/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=13411",
            "date": "2020-10-28T08:59:42",
            "name": "net/mlx5: support multiple-thread flow operations",
            "version": 5,
            "mbox": "https://patches.dpdk.org/series/13411/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/82559/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/82559/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 58398A04DD;\n\tWed, 28 Oct 2020 10:07:25 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id A078DC8DC;\n\tWed, 28 Oct 2020 10:03:34 +0100 (CET)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by dpdk.org (Postfix) with ESMTP id 03039C804\n for <dev@dpdk.org>; Wed, 28 Oct 2020 10:02:18 +0100 (CET)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n suanmingm@nvidia.com) with SMTP; 28 Oct 2020 11:01:21 +0200",
            "from nvidia.com (mtbc-r640-04.mtbc.labs.mlnx [10.75.70.9])\n by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 09S90JmN024495;\n Wed, 28 Oct 2020 11:01:19 +0200"
        ],
        "From": "Suanming Mou <suanmingm@nvidia.com>",
        "To": "Matan Azrad <matan@nvidia.com>, Shahaf Shuler <shahafs@nvidia.com>,\n Viacheslav Ovsiienko <viacheslavo@nvidia.com>",
        "Cc": "dev@dpdk.org, rasland@nvidia.com",
        "Date": "Wed, 28 Oct 2020 17:00:04 +0800",
        "Message-Id": "<1603875616-272798-24-git-send-email-suanmingm@nvidia.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1603875616-272798-1-git-send-email-suanmingm@nvidia.com>",
        "References": "<1601984948-313027-1-git-send-email-suanmingm@nvidia.com>\n <1603875616-272798-1-git-send-email-suanmingm@nvidia.com>",
        "Subject": "[dpdk-dev] [PATCH v5 23/34] net/mlx5: make Rx queue thread safe",
        "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 <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 <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This commit applies the cache linked list to Rx queue to make it thread\nsafe.\n\nSigned-off-by: Suanming Mou <suanmingm@nvidia.com>\nAcked-by: Matan Azrad <matan@nvidia.com>\n---\n drivers/net/mlx5/linux/mlx5_os.c   |   5 +\n drivers/net/mlx5/mlx5.c            |   1 +\n drivers/net/mlx5/mlx5.h            |  28 +++-\n drivers/net/mlx5/mlx5_flow.h       |  16 ---\n drivers/net/mlx5/mlx5_flow_dv.c    |  74 ++++------\n drivers/net/mlx5/mlx5_flow_verbs.c |  21 +--\n drivers/net/mlx5/mlx5_rxq.c        | 281 ++++++++++++++++++++-----------------\n drivers/net/mlx5/mlx5_rxtx.h       |  20 +--\n 8 files changed, 228 insertions(+), 218 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c\nindex d017c23..10fc7c5 100644\n--- a/drivers/net/mlx5/linux/mlx5_os.c\n+++ b/drivers/net/mlx5/linux/mlx5_os.c\n@@ -1468,6 +1468,10 @@\n \t\t\terr = ENOTSUP;\n \t\t\tgoto error;\n \t}\n+\tmlx5_cache_list_init(&priv->hrxqs, \"hrxq\", 0, eth_dev,\n+\t\t\t     mlx5_hrxq_create_cb,\n+\t\t\t     mlx5_hrxq_match_cb,\n+\t\t\t     mlx5_hrxq_remove_cb);\n \t/* Query availability of metadata reg_c's. */\n \terr = mlx5_flow_discover_mreg_c(eth_dev);\n \tif (err < 0) {\n@@ -1520,6 +1524,7 @@\n \t\t\tmlx5_drop_action_destroy(eth_dev);\n \t\tif (own_domain_id)\n \t\t\tclaim_zero(rte_eth_switch_domain_free(priv->domain_id));\n+\t\tmlx5_cache_list_destroy(&priv->hrxqs);\n \t\tmlx5_free(priv);\n \t\tif (eth_dev != NULL)\n \t\t\teth_dev->data->dev_private = NULL;\ndiff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex 1d25a8e..862bd40 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -1286,6 +1286,7 @@ struct mlx5_dev_ctx_shared *\n \tif (ret)\n \t\tDRV_LOG(WARNING, \"port %u some flows still remain\",\n \t\t\tdev->data->port_id);\n+\tmlx5_cache_list_destroy(&priv->hrxqs);\n \t/*\n \t * Free the shared context in last turn, because the cleanup\n \t * routines above may use some shared fields, like\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex 9f96bd0..7804d3a 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -65,6 +65,13 @@ enum mlx5_reclaim_mem_mode {\n \tMLX5_RCM_AGGR, /* Reclaim PMD and rdma-core level. */\n };\n \n+/* Hash and cache list callback context. */\n+struct mlx5_flow_cb_ctx {\n+\tstruct rte_eth_dev *dev;\n+\tstruct rte_flow_error *error;\n+\tvoid *data;\n+};\n+\n /* Device attributes used in mlx5 PMD */\n struct mlx5_dev_attr {\n \tuint64_t\tdevice_cap_flags_ex;\n@@ -684,6 +691,22 @@ struct mlx5_proc_priv {\n /* MTR list. */\n TAILQ_HEAD(mlx5_flow_meters, mlx5_flow_meter);\n \n+/* RSS description. */\n+struct mlx5_flow_rss_desc {\n+\tuint32_t level;\n+\tuint32_t queue_num; /**< Number of entries in @p queue. */\n+\tuint64_t types; /**< Specific RSS hash types (see ETH_RSS_*). */\n+\tuint64_t hash_fields; /* Verbs Hash fields. */\n+\tuint8_t key[MLX5_RSS_HASH_KEY_LEN]; /**< RSS hash key. */\n+\tuint32_t key_len; /**< RSS hash key len. */\n+\tuint32_t tunnel; /**< Queue in tunnel. */\n+\tunion {\n+\t\tuint16_t *queue; /**< Destination queues. */\n+\t\tconst uint16_t *const_q; /**< Const pointer convert. */\n+\t};\n+\tbool standalone; /**< Queue is standalone or not. */\n+};\n+\n #define MLX5_PROC_PRIV(port_id) \\\n \t((struct mlx5_proc_priv *)rte_eth_devices[port_id].process_private)\n \n@@ -723,7 +746,7 @@ struct mlx5_ind_table_obj {\n /* Hash Rx queue. */\n __extension__\n struct mlx5_hrxq {\n-\tILIST_ENTRY(uint32_t)next; /* Index to the next element. */\n+\tstruct mlx5_cache_entry entry; /* Cache entry. */\n \tuint32_t refcnt; /* Reference counter. */\n \tuint32_t standalone:1; /* This object used in shared action. */\n \tstruct mlx5_ind_table_obj *ind_table; /* Indirection table. */\n@@ -737,6 +760,7 @@ struct mlx5_hrxq {\n #endif\n \tuint64_t hash_fields; /* Verbs Hash fields. */\n \tuint32_t rss_key_len; /* Hash key length in bytes. */\n+\tuint32_t idx; /* Hash Rx queue index. */\n \tuint8_t rss_key[]; /* Hash key. */\n };\n \n@@ -853,7 +877,7 @@ struct mlx5_priv {\n \tstruct mlx5_obj_ops obj_ops; /* HW objects operations. */\n \tLIST_HEAD(rxq, mlx5_rxq_ctrl) rxqsctrl; /* DPDK Rx queues. */\n \tLIST_HEAD(rxqobj, mlx5_rxq_obj) rxqsobj; /* Verbs/DevX Rx queues. */\n-\tuint32_t hrxqs; /* Verbs Hash Rx queues. */\n+\tstruct mlx5_cache_list hrxqs; /* Hash Rx queues. */\n \tLIST_HEAD(txq, mlx5_txq_ctrl) txqsctrl; /* DPDK Tx queues. */\n \tLIST_HEAD(txqobj, mlx5_txq_obj) txqsobj; /* Verbs/DevX Tx queues. */\n \t/* Indirection tables. */\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex d0a1000..84988c6 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -384,13 +384,6 @@ enum mlx5_flow_fate_type {\n \tMLX5_FLOW_FATE_MAX,\n };\n \n-/* Hash list callback context */\n-struct mlx5_flow_cb_ctx {\n-\tstruct rte_eth_dev *dev;\n-\tstruct rte_flow_error *error;\n-\tvoid *data;\n-};\n-\n /* Matcher PRM representation */\n struct mlx5_flow_dv_match_params {\n \tsize_t size;\n@@ -609,15 +602,6 @@ struct ibv_spec_header {\n \tuint16_t size;\n };\n \n-/* RSS description. */\n-struct mlx5_flow_rss_desc {\n-\tuint32_t level;\n-\tuint32_t queue_num; /**< Number of entries in @p queue. */\n-\tuint64_t types; /**< Specific RSS hash types (see ETH_RSS_*). */\n-\tuint8_t key[MLX5_RSS_HASH_KEY_LEN]; /**< RSS hash key. */\n-\tuint16_t *queue; /**< Destination queues. */\n-};\n-\n /* PMD flow priority for tunnel */\n #define MLX5_TUNNEL_PRIO_GET(rss_desc) \\\n \t((rss_desc)->level >= 2 ? MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4)\ndiff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c\nindex 3a55f76..78984f9 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -8527,7 +8527,7 @@ struct mlx5_hlist_entry *\n }\n \n /**\n- * Create an Rx Hash queue.\n+ * Prepare an Rx Hash queue.\n  *\n  * @param dev\n  *   Pointer to Ethernet device.\n@@ -8542,29 +8542,23 @@ struct mlx5_hlist_entry *\n  *   The Verbs/DevX object initialised, NULL otherwise and rte_errno is set.\n  */\n static struct mlx5_hrxq *\n-flow_dv_handle_rx_queue(struct rte_eth_dev *dev,\n-\t\t\tstruct mlx5_flow *dev_flow,\n-\t\t\tstruct mlx5_flow_rss_desc *rss_desc,\n-\t\t\tuint32_t *hrxq_idx)\n+flow_dv_hrxq_prepare(struct rte_eth_dev *dev,\n+\t\t     struct mlx5_flow *dev_flow,\n+\t\t     struct mlx5_flow_rss_desc *rss_desc,\n+\t\t     uint32_t *hrxq_idx)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_flow_handle *dh = dev_flow->handle;\n \tstruct mlx5_hrxq *hrxq;\n \n \tMLX5_ASSERT(rss_desc->queue_num);\n-\t*hrxq_idx = mlx5_hrxq_get(dev, rss_desc->key, MLX5_RSS_HASH_KEY_LEN,\n-\t\t\t\t  dev_flow->hash_fields,\n-\t\t\t\t  rss_desc->queue, rss_desc->queue_num);\n-\tif (!*hrxq_idx) {\n-\t\t*hrxq_idx = mlx5_hrxq_new\n-\t\t\t\t(dev, rss_desc->key, MLX5_RSS_HASH_KEY_LEN,\n-\t\t\t\t dev_flow->hash_fields,\n-\t\t\t\t rss_desc->queue, rss_desc->queue_num,\n-\t\t\t\t !!(dh->layers & MLX5_FLOW_LAYER_TUNNEL),\n-\t\t\t\t false);\n-\t\tif (!*hrxq_idx)\n-\t\t\treturn NULL;\n-\t}\n+\trss_desc->key_len = MLX5_RSS_HASH_KEY_LEN;\n+\trss_desc->hash_fields = dev_flow->hash_fields;\n+\trss_desc->tunnel = !!(dh->layers & MLX5_FLOW_LAYER_TUNNEL);\n+\trss_desc->standalone = false;\n+\t*hrxq_idx = mlx5_hrxq_get(dev, rss_desc);\n+\tif (!*hrxq_idx)\n+\t\treturn NULL;\n \thrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],\n \t\t\t      *hrxq_idx);\n \treturn hrxq;\n@@ -8927,8 +8921,8 @@ struct mlx5_hlist_entry *\n \t\t\tqueue = sub_actions->conf;\n \t\t\trss_desc->queue_num = 1;\n \t\t\trss_desc->queue[0] = queue->index;\n-\t\t\thrxq = flow_dv_handle_rx_queue(dev, dev_flow,\n-\t\t\t\t\trss_desc, &hrxq_idx);\n+\t\t\thrxq = flow_dv_hrxq_prepare(dev, dev_flow,\n+\t\t\t\t\t\t    rss_desc, &hrxq_idx);\n \t\t\tif (!hrxq)\n \t\t\t\treturn rte_flow_error_set\n \t\t\t\t\t(error, rte_errno,\n@@ -9125,8 +9119,8 @@ struct mlx5_hlist_entry *\n \tif (num_of_dest > 1) {\n \t\tif (sample_act->action_flags & MLX5_FLOW_ACTION_QUEUE) {\n \t\t\t/* Handle QP action for mirroring */\n-\t\t\thrxq = flow_dv_handle_rx_queue(dev, dev_flow,\n-\t\t\t\t\t\t       rss_desc, &hrxq_idx);\n+\t\t\thrxq = flow_dv_hrxq_prepare(dev, dev_flow,\n+\t\t\t\t\t\t    rss_desc, &hrxq_idx);\n \t\t\tif (!hrxq)\n \t\t\t\treturn rte_flow_error_set\n \t\t\t\t     (error, rte_errno,\n@@ -10261,24 +10255,8 @@ struct mlx5_hlist_entry *\n \t\tstruct mlx5_flow_rss_desc *rss_desc =\n \t\t\t\t&wks->rss_desc[!!wks->flow_nested_idx];\n \n-\t\tMLX5_ASSERT(rss_desc->queue_num);\n-\t\thrxq_idx = mlx5_hrxq_get(dev, rss_desc->key,\n-\t\t\t\t\t MLX5_RSS_HASH_KEY_LEN,\n-\t\t\t\t\t dev_flow->hash_fields,\n-\t\t\t\t\t rss_desc->queue, rss_desc->queue_num);\n-\t\tif (!hrxq_idx) {\n-\t\t\thrxq_idx = mlx5_hrxq_new(dev,\n-\t\t\t\t\t\t rss_desc->key,\n-\t\t\t\t\t\t MLX5_RSS_HASH_KEY_LEN,\n-\t\t\t\t\t\t dev_flow->hash_fields,\n-\t\t\t\t\t\t rss_desc->queue,\n-\t\t\t\t\t\t rss_desc->queue_num,\n-\t\t\t\t\t\t !!(dev_flow->handle->layers &\n-\t\t\t\t\t\t MLX5_FLOW_LAYER_TUNNEL),\n-\t\t\t\t\t\t false);\n-\t\t}\n-\t\t*hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],\n-\t\t\t\t       hrxq_idx);\n+\t\t*hrxq = flow_dv_hrxq_prepare(dev, dev_flow, rss_desc,\n+\t\t\t\t\t     &hrxq_idx);\n \t}\n \treturn hrxq_idx;\n }\n@@ -10332,7 +10310,6 @@ struct mlx5_hlist_entry *\n \t\t\tstruct mlx5_hrxq *hrxq = NULL;\n \t\t\tuint32_t hrxq_idx = __flow_dv_rss_get_hrxq\n \t\t\t\t\t\t(dev, flow, dev_flow, &hrxq);\n-\n \t\t\tif (!hrxq) {\n \t\t\t\trte_flow_error_set\n \t\t\t\t\t(error, rte_errno,\n@@ -10954,21 +10931,24 @@ struct mlx5_hlist_entry *\n \t\t\tstruct mlx5_shared_action_rss *action,\n \t\t\tstruct rte_flow_error *error)\n {\n+\tstruct mlx5_flow_rss_desc rss_desc = { 0 };\n \tsize_t i;\n \tint err;\n \n+\tmemcpy(rss_desc.key, action->origin.key, MLX5_RSS_HASH_KEY_LEN);\n+\trss_desc.key_len = MLX5_RSS_HASH_KEY_LEN;\n+\trss_desc.const_q = action->origin.queue;\n+\trss_desc.queue_num = action->origin.queue_num;\n+\trss_desc.standalone = true;\n \tfor (i = 0; i < MLX5_RSS_HASH_FIELDS_LEN; i++) {\n \t\tuint32_t hrxq_idx;\n \t\tuint64_t hash_fields = mlx5_rss_hash_fields[i];\n \t\tint tunnel;\n \n \t\tfor (tunnel = 0; tunnel < 2; tunnel++) {\n-\t\t\thrxq_idx = mlx5_hrxq_new(dev, action->origin.key,\n-\t\t\t\t\tMLX5_RSS_HASH_KEY_LEN,\n-\t\t\t\t\thash_fields,\n-\t\t\t\t\taction->origin.queue,\n-\t\t\t\t\taction->origin.queue_num,\n-\t\t\t\t\ttunnel, true);\n+\t\t\trss_desc.tunnel = tunnel;\n+\t\t\trss_desc.hash_fields = hash_fields;\n+\t\t\thrxq_idx = mlx5_hrxq_get(dev, &rss_desc);\n \t\t\tif (!hrxq_idx) {\n \t\t\t\trte_flow_error_set\n \t\t\t\t\t(error, rte_errno,\ndiff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c\nindex 3c04727..28fd120 100644\n--- a/drivers/net/mlx5/mlx5_flow_verbs.c\n+++ b/drivers/net/mlx5/mlx5_flow_verbs.c\n@@ -1968,21 +1968,12 @@\n \t\t\t\t&wks->rss_desc[!!wks->flow_nested_idx];\n \n \t\t\tMLX5_ASSERT(rss_desc->queue_num);\n-\t\t\thrxq_idx = mlx5_hrxq_get(dev, rss_desc->key,\n-\t\t\t\t\t\t MLX5_RSS_HASH_KEY_LEN,\n-\t\t\t\t\t\t dev_flow->hash_fields,\n-\t\t\t\t\t\t rss_desc->queue,\n-\t\t\t\t\t\t rss_desc->queue_num);\n-\t\t\tif (!hrxq_idx)\n-\t\t\t\thrxq_idx = mlx5_hrxq_new\n-\t\t\t\t\t\t(dev, rss_desc->key,\n-\t\t\t\t\t\t MLX5_RSS_HASH_KEY_LEN,\n-\t\t\t\t\t\t dev_flow->hash_fields,\n-\t\t\t\t\t\t rss_desc->queue,\n-\t\t\t\t\t\t rss_desc->queue_num,\n-\t\t\t\t\t\t !!(handle->layers &\n-\t\t\t\t\t\t MLX5_FLOW_LAYER_TUNNEL),\n-\t\t\t\t\t\t false);\n+\t\t\trss_desc->key_len = MLX5_RSS_HASH_KEY_LEN;\n+\t\t\trss_desc->hash_fields = dev_flow->hash_fields;\n+\t\t\trss_desc->tunnel = !!(handle->layers &\n+\t\t\t\t\t      MLX5_FLOW_LAYER_TUNNEL);\n+\t\t\trss_desc->standalone = false;\n+\t\t\thrxq_idx = mlx5_hrxq_get(dev, rss_desc);\n \t\t\thrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],\n \t\t\t\t\t      hrxq_idx);\n \t\t\tif (!hrxq) {\ndiff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c\nindex 7579407..a733eda 100644\n--- a/drivers/net/mlx5/mlx5_rxq.c\n+++ b/drivers/net/mlx5/mlx5_rxq.c\n@@ -2039,54 +2039,38 @@ struct mlx5_ind_table_obj *\n }\n \n /**\n- * Get an Rx Hash queue.\n+ * Match an Rx Hash queue.\n  *\n- * @param dev\n- *   Pointer to Ethernet device.\n- * @param rss_conf\n- *   RSS configuration for the Rx hash queue.\n- * @param queues\n- *   Queues entering in hash queue. In case of empty hash_fields only the\n- *   first queue index will be taken for the indirection table.\n- * @param queues_n\n- *   Number of queues.\n+ * @param list\n+ *   Cache list pointer.\n+ * @param entry\n+ *   Hash queue entry pointer.\n+ * @param cb_ctx\n+ *   Context of the callback function.\n  *\n  * @return\n- *   An hash Rx queue index on success.\n+ *   0 if match, none zero if not match.\n  */\n-uint32_t\n-mlx5_hrxq_get(struct rte_eth_dev *dev,\n-\t      const uint8_t *rss_key, uint32_t rss_key_len,\n-\t      uint64_t hash_fields,\n-\t      const uint16_t *queues, uint32_t queues_n)\n+int\n+mlx5_hrxq_match_cb(struct mlx5_cache_list *list,\n+\t\t   struct mlx5_cache_entry *entry,\n+\t\t   void *cb_ctx)\n {\n-\tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_hrxq *hrxq;\n-\tuint32_t idx;\n-\n-\tqueues_n = hash_fields ? queues_n : 1;\n-\tILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_HRXQ], priv->hrxqs, idx,\n-\t\t      hrxq, next) {\n-\t\tstruct mlx5_ind_table_obj *ind_tbl;\n+\tstruct rte_eth_dev *dev = list->ctx;\n+\tstruct mlx5_flow_cb_ctx *ctx = cb_ctx;\n+\tstruct mlx5_flow_rss_desc *rss_desc = ctx->data;\n+\tstruct mlx5_hrxq *hrxq = container_of(entry, typeof(*hrxq), entry);\n+\tstruct mlx5_ind_table_obj *ind_tbl;\n \n-\t\tif (hrxq->rss_key_len != rss_key_len)\n-\t\t\tcontinue;\n-\t\tif (memcmp(hrxq->rss_key, rss_key, rss_key_len))\n-\t\t\tcontinue;\n-\t\tif (hrxq->hash_fields != hash_fields)\n-\t\t\tcontinue;\n-\t\tind_tbl = mlx5_ind_table_obj_get(dev, queues, queues_n);\n-\t\tif (!ind_tbl)\n-\t\t\tcontinue;\n-\t\tif (ind_tbl != hrxq->ind_table) {\n-\t\t\tmlx5_ind_table_obj_release(dev, ind_tbl,\n-\t\t\t\t\t\t   hrxq->standalone);\n-\t\t\tcontinue;\n-\t\t}\n-\t\t__atomic_fetch_add(&hrxq->refcnt, 1, __ATOMIC_RELAXED);\n-\t\treturn idx;\n-\t}\n-\treturn 0;\n+\tif (hrxq->rss_key_len != rss_desc->key_len ||\n+\t    memcmp(hrxq->rss_key, rss_desc->key, rss_desc->key_len) ||\n+\t    hrxq->hash_fields != rss_desc->hash_fields)\n+\t\treturn 1;\n+\tind_tbl = mlx5_ind_table_obj_get(dev, rss_desc->queue,\n+\t\t\t\t\t rss_desc->queue_num);\n+\tif (ind_tbl)\n+\t\tmlx5_ind_table_obj_release(dev, ind_tbl, hrxq->standalone);\n+\treturn ind_tbl != hrxq->ind_table;\n }\n \n /**\n@@ -2171,114 +2155,163 @@ struct mlx5_ind_table_obj *\n \treturn -rte_errno;\n }\n \n-/**\n- * Release the hash Rx queue.\n- *\n- * @param dev\n- *   Pointer to Ethernet device.\n- * @param hrxq\n- *   Index to Hash Rx queue to release.\n- *\n- * @return\n- *   1 while a reference on it exists, 0 when freed.\n- */\n-int\n-mlx5_hrxq_release(struct rte_eth_dev *dev, uint32_t hrxq_idx)\n+static void\n+__mlx5_hrxq_remove(struct rte_eth_dev *dev, struct mlx5_hrxq *hrxq)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_hrxq *hrxq;\n \n-\thrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq_idx);\n-\tif (!hrxq)\n-\t\treturn 0;\n-\tif (__atomic_sub_fetch(&hrxq->refcnt, 1, __ATOMIC_RELAXED) == 0) {\n #ifdef HAVE_IBV_FLOW_DV_SUPPORT\n-\t\tmlx5_glue->destroy_flow_action(hrxq->action);\n+\tmlx5_glue->destroy_flow_action(hrxq->action);\n #endif\n-\t\tpriv->obj_ops.hrxq_destroy(hrxq);\n-\t\tmlx5_ind_table_obj_release(dev, hrxq->ind_table,\n-\t\t\t\t\t   hrxq->standalone);\n-\t\tif (!hrxq->standalone)\n-\t\t\tILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_HRXQ],\n-\t\t\t\t     &priv->hrxqs, hrxq_idx, hrxq, next);\n-\t\tmlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq_idx);\n-\t\treturn 0;\n-\t}\n-\tclaim_nonzero(mlx5_ind_table_obj_release(dev, hrxq->ind_table,\n-\t\t\t\t\t\t hrxq->standalone));\n-\treturn 1;\n+\tpriv->obj_ops.hrxq_destroy(hrxq);\n+\tmlx5_ind_table_obj_release(dev, hrxq->ind_table, hrxq->standalone);\n+\tmlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq->idx);\n }\n \n /**\n- * Create an Rx Hash queue.\n+ * Release the hash Rx queue.\n  *\n  * @param dev\n  *   Pointer to Ethernet device.\n- * @param rss_key\n- *   RSS key for the Rx hash queue.\n- * @param rss_key_len\n- *   RSS key length.\n- * @param hash_fields\n- *   Verbs protocol hash field to make the RSS on.\n- * @param queues\n- *   Queues entering in hash queue. In case of empty hash_fields only the\n- *   first queue index will be taken for the indirection table.\n- * @param queues_n\n- *   Number of queues.\n- * @param tunnel\n- *   Tunnel type.\n- * @param standalone\n- *   Object of Rx Hash queue will be used in standalone shared action or not.\n+ * @param hrxq\n+ *   Index to Hash Rx queue to release.\n  *\n- * @return\n- *   The DevX object initialized index, 0 otherwise and rte_errno is set.\n+ * @param list\n+ *   Cache list pointer.\n+ * @param entry\n+ *   Hash queue entry pointer.\n  */\n-uint32_t\n-mlx5_hrxq_new(struct rte_eth_dev *dev,\n-\t      const uint8_t *rss_key, uint32_t rss_key_len,\n-\t      uint64_t hash_fields,\n-\t      const uint16_t *queues, uint32_t queues_n,\n-\t      int tunnel, bool standalone)\n+void\n+mlx5_hrxq_remove_cb(struct mlx5_cache_list *list,\n+\t\t    struct mlx5_cache_entry *entry)\n+{\n+\tstruct rte_eth_dev *dev = list->ctx;\n+\tstruct mlx5_hrxq *hrxq = container_of(entry, typeof(*hrxq), entry);\n+\n+\t__mlx5_hrxq_remove(dev, hrxq);\n+}\n+\n+static struct mlx5_hrxq *\n+__mlx5_hrxq_create(struct rte_eth_dev *dev,\n+\t\t   struct mlx5_flow_rss_desc *rss_desc)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tconst uint8_t *rss_key = rss_desc->key;\n+\tuint32_t rss_key_len =  rss_desc->key_len;\n+\tconst uint16_t *queues =\n+\t\trss_desc->standalone ? rss_desc->const_q : rss_desc->queue;\n+\tuint32_t queues_n = rss_desc->queue_num;\n \tstruct mlx5_hrxq *hrxq = NULL;\n \tuint32_t hrxq_idx = 0;\n \tstruct mlx5_ind_table_obj *ind_tbl;\n \tint ret;\n \n-\tqueues_n = hash_fields ? queues_n : 1;\n+\tqueues_n = rss_desc->hash_fields ? queues_n : 1;\n \tind_tbl = mlx5_ind_table_obj_get(dev, queues, queues_n);\n \tif (!ind_tbl)\n \t\tind_tbl = mlx5_ind_table_obj_new(dev, queues, queues_n,\n-\t\t\t\t\t\t standalone);\n-\tif (!ind_tbl) {\n-\t\trte_errno = ENOMEM;\n-\t\treturn 0;\n-\t}\n+\t\t\t\t\t\t rss_desc->standalone);\n+\tif (!ind_tbl)\n+\t\treturn NULL;\n \thrxq = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_HRXQ], &hrxq_idx);\n \tif (!hrxq)\n \t\tgoto error;\n-\thrxq->standalone = !!standalone;\n+\thrxq->standalone = rss_desc->standalone;\n+\thrxq->idx = hrxq_idx;\n \thrxq->ind_table = ind_tbl;\n \thrxq->rss_key_len = rss_key_len;\n-\thrxq->hash_fields = hash_fields;\n+\thrxq->hash_fields = rss_desc->hash_fields;\n \tmemcpy(hrxq->rss_key, rss_key, rss_key_len);\n-\tret = priv->obj_ops.hrxq_new(dev, hrxq, tunnel);\n-\tif (ret < 0) {\n-\t\trte_errno = errno;\n+\tret = priv->obj_ops.hrxq_new(dev, hrxq, rss_desc->tunnel);\n+\tif (ret < 0)\n \t\tgoto error;\n-\t}\n-\t__atomic_fetch_add(&hrxq->refcnt, 1, __ATOMIC_RELAXED);\n-\tif (!hrxq->standalone)\n-\t\tILIST_INSERT(priv->sh->ipool[MLX5_IPOOL_HRXQ], &priv->hrxqs,\n-\t\t\t     hrxq_idx, hrxq, next);\n-\treturn hrxq_idx;\n+\treturn hrxq;\n error:\n-\tret = rte_errno; /* Save rte_errno before cleanup. */\n-\tmlx5_ind_table_obj_release(dev, ind_tbl, standalone);\n+\tmlx5_ind_table_obj_release(dev, ind_tbl, rss_desc->standalone);\n \tif (hrxq)\n \t\tmlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq_idx);\n-\trte_errno = ret; /* Restore rte_errno. */\n+\treturn NULL;\n+}\n+\n+/**\n+ * Create an Rx Hash queue.\n+ *\n+ * @param list\n+ *   Cache list pointer.\n+ * @param entry\n+ *   Hash queue entry pointer.\n+ * @param cb_ctx\n+ *   Context of the callback function.\n+ *\n+ * @return\n+ *   queue entry on success, NULL otherwise.\n+ */\n+struct mlx5_cache_entry *\n+mlx5_hrxq_create_cb(struct mlx5_cache_list *list,\n+\t\t    struct mlx5_cache_entry *entry __rte_unused,\n+\t\t    void *cb_ctx)\n+{\n+\tstruct rte_eth_dev *dev = list->ctx;\n+\tstruct mlx5_flow_cb_ctx *ctx = cb_ctx;\n+\tstruct mlx5_flow_rss_desc *rss_desc = ctx->data;\n+\tstruct mlx5_hrxq *hrxq;\n+\n+\thrxq = __mlx5_hrxq_create(dev, rss_desc);\n+\treturn hrxq ? &hrxq->entry : NULL;\n+}\n+\n+/**\n+ * Get an Rx Hash queue.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device.\n+ * @param rss_desc\n+ *   RSS configuration for the Rx hash queue.\n+ *\n+ * @return\n+ *   An hash Rx queue index on success.\n+ */\n+uint32_t mlx5_hrxq_get(struct rte_eth_dev *dev,\n+\t\t       struct mlx5_flow_rss_desc *rss_desc)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_hrxq *hrxq;\n+\tstruct mlx5_cache_entry *entry;\n+\tstruct mlx5_flow_cb_ctx ctx = {\n+\t\t.data = rss_desc,\n+\t};\n+\n+\tif (rss_desc->standalone) {\n+\t\thrxq = __mlx5_hrxq_create(dev, rss_desc);\n+\t} else {\n+\t\tentry = mlx5_cache_register(&priv->hrxqs, &ctx);\n+\t\tif (!entry)\n+\t\t\treturn 0;\n+\t\thrxq = container_of(entry, typeof(*hrxq), entry);\n+\t}\n+\treturn hrxq->idx;\n+}\n+\n+/**\n+ * Release the hash Rx queue.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device.\n+ * @param hrxq_idx\n+ *   Index to Hash Rx queue to release.\n+ *\n+ * @return\n+ *   1 while a reference on it exists, 0 when freed.\n+ */\n+int mlx5_hrxq_release(struct rte_eth_dev *dev, uint32_t hrxq_idx)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_hrxq *hrxq;\n+\n+\thrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq_idx);\n+\tif (!hrxq->standalone)\n+\t\treturn mlx5_cache_unregister(&priv->hrxqs, &hrxq->entry);\n+\t__mlx5_hrxq_remove(dev, hrxq);\n \treturn 0;\n }\n \n@@ -2364,22 +2397,12 @@ struct mlx5_hrxq *\n  * @return\n  *   The number of object not released.\n  */\n-int\n+uint32_t\n mlx5_hrxq_verify(struct rte_eth_dev *dev)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_hrxq *hrxq;\n-\tuint32_t idx;\n-\tint ret = 0;\n \n-\tILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_HRXQ], priv->hrxqs, idx,\n-\t\t      hrxq, next) {\n-\t\tDRV_LOG(DEBUG,\n-\t\t\t\"port %u hash Rx queue %p still referenced\",\n-\t\t\tdev->data->port_id, (void *)hrxq);\n-\t\t++ret;\n-\t}\n-\treturn ret;\n+\treturn mlx5_cache_list_get_entry_num(&priv->hrxqs);\n }\n \n /**\ndiff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h\nindex 8fe0473..c361bbd 100644\n--- a/drivers/net/mlx5/mlx5_rxtx.h\n+++ b/drivers/net/mlx5/mlx5_rxtx.h\n@@ -349,17 +349,19 @@ struct mlx5_ind_table_obj *mlx5_ind_table_obj_get(struct rte_eth_dev *dev,\n int mlx5_ind_table_obj_release(struct rte_eth_dev *dev,\n \t\t\t       struct mlx5_ind_table_obj *ind_tbl,\n \t\t\t       bool standalone);\n-uint32_t mlx5_hrxq_new(struct rte_eth_dev *dev,\n-\t\t       const uint8_t *rss_key, uint32_t rss_key_len,\n-\t\t       uint64_t hash_fields,\n-\t\t       const uint16_t *queues, uint32_t queues_n,\n-\t\t       int tunnel, bool standalone);\n+struct mlx5_cache_entry *mlx5_hrxq_create_cb(struct mlx5_cache_list *list,\n+\t\tstruct mlx5_cache_entry *entry __rte_unused, void *cb_ctx);\n+int mlx5_hrxq_match_cb(struct mlx5_cache_list *list,\n+\t\t       struct mlx5_cache_entry *entry,\n+\t\t       void *cb_ctx);\n+void mlx5_hrxq_remove_cb(struct mlx5_cache_list *list,\n+\t\t\t struct mlx5_cache_entry *entry);\n uint32_t mlx5_hrxq_get(struct rte_eth_dev *dev,\n-\t\t       const uint8_t *rss_key, uint32_t rss_key_len,\n-\t\t       uint64_t hash_fields,\n-\t\t       const uint16_t *queues, uint32_t queues_n);\n+\t\t       struct mlx5_flow_rss_desc *rss_desc);\n int mlx5_hrxq_release(struct rte_eth_dev *dev, uint32_t hxrq_idx);\n-int mlx5_hrxq_verify(struct rte_eth_dev *dev);\n+uint32_t mlx5_hrxq_verify(struct rte_eth_dev *dev);\n+\n+\n enum mlx5_rxq_type mlx5_rxq_get_type(struct rte_eth_dev *dev, uint16_t idx);\n const struct rte_eth_hairpin_conf *mlx5_rxq_get_hairpin_conf\n \t(struct rte_eth_dev *dev, uint16_t idx);\n",
    "prefixes": [
        "v5",
        "23/34"
    ]
}