get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 82567,
    "url": "https://patches.dpdk.org/api/patches/82567/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1603875616-272798-30-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-30-git-send-email-suanmingm@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1603875616-272798-30-git-send-email-suanmingm@nvidia.com",
    "date": "2020-10-28T09:00:10",
    "name": "[v5,29/34] net/mlx5: make sample and mirror action thread safe",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "44e1b1d523ba6544c60911fdb8396de1375137b5",
    "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-30-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/82567/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/82567/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 7E514A04DD;\n\tWed, 28 Oct 2020 10:09:51 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 029BFC96E;\n\tWed, 28 Oct 2020 10:03:47 +0100 (CET)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by dpdk.org (Postfix) with ESMTP id A22CAC80C\n for <dev@dpdk.org>; Wed, 28 Oct 2020 10:02:20 +0100 (CET)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n suanmingm@nvidia.com) with SMTP; 28 Oct 2020 11:01:37 +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 09S90JmT024495;\n Wed, 28 Oct 2020 11:01:35 +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:10 +0800",
        "Message-Id": "<1603875616-272798-30-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 29/34] net/mlx5: make sample and mirror action\n\tthread 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 uses cache list to make sample and mirror action 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 |  14 ++\n drivers/net/mlx5/mlx5.h          |   5 +-\n drivers/net/mlx5/mlx5_flow.h     |  28 ++-\n drivers/net/mlx5/mlx5_flow_dv.c  | 396 ++++++++++++++++++++++-----------------\n 4 files changed, 260 insertions(+), 183 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c\nindex 9ab3ba9..5856981 100644\n--- a/drivers/net/mlx5/linux/mlx5_os.c\n+++ b/drivers/net/mlx5/linux/mlx5_os.c\n@@ -248,6 +248,20 @@\n \t\t\t     flow_dv_push_vlan_create_cb,\n \t\t\t     flow_dv_push_vlan_match_cb,\n \t\t\t     flow_dv_push_vlan_remove_cb);\n+\t/* Init sample action cache list. */\n+\tsnprintf(s, sizeof(s), \"%s_sample_action_cache\", sh->ibdev_name);\n+\tmlx5_cache_list_init(&sh->sample_action_list, s, 0,\n+\t\t\t     &rte_eth_devices[priv->dev_data->port_id],\n+\t\t\t     flow_dv_sample_create_cb,\n+\t\t\t     flow_dv_sample_match_cb,\n+\t\t\t     flow_dv_sample_remove_cb);\n+\t/* Init dest array action cache list. */\n+\tsnprintf(s, sizeof(s), \"%s_dest_array_cache\", sh->ibdev_name);\n+\tmlx5_cache_list_init(&sh->dest_array_list, s, 0,\n+\t\t\t     &rte_eth_devices[priv->dev_data->port_id],\n+\t\t\t     flow_dv_dest_array_create_cb,\n+\t\t\t     flow_dv_dest_array_match_cb,\n+\t\t\t     flow_dv_dest_array_remove_cb);\n \t/* Create tags hash list table. */\n \tsnprintf(s, sizeof(s), \"%s_tags\", sh->ibdev_name);\n \tsh->tag_table = mlx5_hlist_create(s, MLX5_TAGS_HLIST_ARRAY_SIZE, 0,\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex 9efa354..ac7a026 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -661,8 +661,9 @@ struct mlx5_dev_ctx_shared {\n \tstruct mlx5_hlist *tag_table;\n \tstruct mlx5_cache_list port_id_action_list; /* Port ID action cache. */\n \tstruct mlx5_cache_list push_vlan_action_list; /* Push VLAN actions. */\n-\tuint32_t sample_action_list; /* List of sample actions. */\n-\tuint32_t dest_array_list; /* List of destination array actions. */\n+\tstruct mlx5_cache_list sample_action_list; /* List of sample actions. */\n+\tstruct mlx5_cache_list dest_array_list;\n+\t/* List of destination array actions. */\n \tstruct mlx5_flow_counter_mng cmng; /* Counters management structure. */\n \tvoid *default_miss_action; /* Default miss action. */\n \tstruct mlx5_indexed_pool *ipool[MLX5_IPOOL_MAX];\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex 500a580..4a8c2bf 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -562,9 +562,12 @@ struct mlx5_flow_sub_actions_idx {\n \n /* Sample action resource structure. */\n struct mlx5_flow_dv_sample_resource {\n-\tILIST_ENTRY(uint32_t)next; /**< Pointer to next element. */\n-\tuint32_t refcnt; /**< Reference counter. */\n-\tvoid *verbs_action; /**< Verbs sample action object. */\n+\tstruct mlx5_cache_entry entry; /**< Cache entry. */\n+\tunion {\n+\t\tvoid *verbs_action; /**< Verbs sample action object. */\n+\t\tvoid **sub_actions; /**< Sample sub-action array. */\n+\t};\n+\tuint32_t idx; /** Sample object index. */\n \tuint8_t ft_type; /** Flow Table Type */\n \tuint32_t ft_id; /** Flow Table Level */\n \tuint32_t ratio;   /** Sample Ratio */\n@@ -581,8 +584,8 @@ struct mlx5_flow_dv_sample_resource {\n \n /* Destination array action resource structure. */\n struct mlx5_flow_dv_dest_array_resource {\n-\tILIST_ENTRY(uint32_t)next; /**< Pointer to next element. */\n-\tuint32_t refcnt; /**< Reference counter. */\n+\tstruct mlx5_cache_entry entry; /**< Cache entry. */\n+\tuint32_t idx; /** Destination array action object index. */\n \tuint8_t ft_type; /** Flow Table Type */\n \tuint8_t num_of_dest; /**< Number of destination actions. */\n \tvoid *action; /**< Pointer to the rdma core action. */\n@@ -1449,4 +1452,19 @@ struct mlx5_cache_entry *flow_dv_push_vlan_create_cb\n void flow_dv_push_vlan_remove_cb(struct mlx5_cache_list *list,\n \t\t\t\t struct mlx5_cache_entry *entry);\n \n+int flow_dv_sample_match_cb(struct mlx5_cache_list *list,\n+\t\t\t    struct mlx5_cache_entry *entry, void *cb_ctx);\n+struct mlx5_cache_entry *flow_dv_sample_create_cb\n+\t\t\t\t(struct mlx5_cache_list *list,\n+\t\t\t\t struct mlx5_cache_entry *entry, void *cb_ctx);\n+void flow_dv_sample_remove_cb(struct mlx5_cache_list *list,\n+\t\t\t      struct mlx5_cache_entry *entry);\n+\n+int flow_dv_dest_array_match_cb(struct mlx5_cache_list *list,\n+\t\t\t\tstruct mlx5_cache_entry *entry, void *cb_ctx);\n+struct mlx5_cache_entry *flow_dv_dest_array_create_cb\n+\t\t\t\t(struct mlx5_cache_list *list,\n+\t\t\t\t struct mlx5_cache_entry *entry, void *cb_ctx);\n+void flow_dv_dest_array_remove_cb(struct mlx5_cache_list *list,\n+\t\t\t\t  struct mlx5_cache_entry *entry);\n #endif /* RTE_PMD_MLX5_FLOW_H_ */\ndiff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c\nindex 3b36704..79d1317 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -8636,30 +8636,43 @@ struct mlx5_hlist_entry *\n \t}\n }\n \n-/**\n- * Find existing sample resource or create and register a new one.\n- *\n- * @param[in, out] dev\n- *   Pointer to rte_eth_dev structure.\n- * @param[in] resource\n- *   Pointer to sample resource.\n- * @parm[in, out] dev_flow\n- *   Pointer to the dev_flow.\n- * @param[in, out] sample_dv_actions\n- *   Pointer to sample actions list.\n- * @param[out] error\n- *   pointer to error structure.\n- *\n- * @return\n- *   0 on success otherwise -errno and errno is set.\n- */\n-static int\n-flow_dv_sample_resource_register(struct rte_eth_dev *dev,\n-\t\t\t struct mlx5_flow_dv_sample_resource *resource,\n-\t\t\t struct mlx5_flow *dev_flow,\n-\t\t\t void **sample_dv_actions,\n-\t\t\t struct rte_flow_error *error)\n+int\n+flow_dv_sample_match_cb(struct mlx5_cache_list *list __rte_unused,\n+\t\t\tstruct mlx5_cache_entry *entry, void *cb_ctx)\n+{\n+\tstruct mlx5_flow_cb_ctx *ctx = cb_ctx;\n+\tstruct rte_eth_dev *dev = ctx->dev;\n+\tstruct mlx5_flow_dv_sample_resource *resource = ctx->data;\n+\tstruct mlx5_flow_dv_sample_resource *cache_resource =\n+\t\t\tcontainer_of(entry, typeof(*cache_resource), entry);\n+\n+\tif (resource->ratio == cache_resource->ratio &&\n+\t    resource->ft_type == cache_resource->ft_type &&\n+\t    resource->ft_id == cache_resource->ft_id &&\n+\t    resource->set_action == cache_resource->set_action &&\n+\t    !memcmp((void *)&resource->sample_act,\n+\t\t    (void *)&cache_resource->sample_act,\n+\t\t    sizeof(struct mlx5_flow_sub_actions_list))) {\n+\t\t/*\n+\t\t * Existing sample action should release the prepared\n+\t\t * sub-actions reference counter.\n+\t\t */\n+\t\tflow_dv_sample_sub_actions_release(dev,\n+\t\t\t\t\t\t&resource->sample_idx);\n+\t\treturn 0;\n+\t}\n+\treturn 1;\n+}\n+\n+struct mlx5_cache_entry *\n+flow_dv_sample_create_cb(struct mlx5_cache_list *list __rte_unused,\n+\t\t\t struct mlx5_cache_entry *entry __rte_unused,\n+\t\t\t void *cb_ctx)\n {\n+\tstruct mlx5_flow_cb_ctx *ctx = cb_ctx;\n+\tstruct rte_eth_dev *dev = ctx->dev;\n+\tstruct mlx5_flow_dv_sample_resource *resource = ctx->data;\n+\tvoid **sample_dv_actions = resource->sub_actions;\n \tstruct mlx5_flow_dv_sample_resource *cache_resource;\n \tstruct mlx5dv_dr_flow_sampler_attr sampler_attr;\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n@@ -8670,42 +8683,17 @@ struct mlx5_hlist_entry *\n \tuint32_t next_ft_id = resource->ft_id +\tnext_ft_step;\n \tuint8_t is_egress = 0;\n \tuint8_t is_transfer = 0;\n+\tstruct rte_flow_error *error = ctx->error;\n \n-\t/* Lookup a matching resource from cache. */\n-\tILIST_FOREACH(sh->ipool[MLX5_IPOOL_SAMPLE], sh->sample_action_list,\n-\t\t      idx, cache_resource, next) {\n-\t\tif (resource->ratio == cache_resource->ratio &&\n-\t\t    resource->ft_type == cache_resource->ft_type &&\n-\t\t    resource->ft_id == cache_resource->ft_id &&\n-\t\t    resource->set_action == cache_resource->set_action &&\n-\t\t    !memcmp((void *)&resource->sample_act,\n-\t\t\t    (void *)&cache_resource->sample_act,\n-\t\t\t    sizeof(struct mlx5_flow_sub_actions_list))) {\n-\t\t\tDRV_LOG(DEBUG, \"sample resource %p: refcnt %d++\",\n-\t\t\t\t(void *)cache_resource,\n-\t\t\t\t__atomic_load_n(&cache_resource->refcnt,\n-\t\t\t\t\t\t__ATOMIC_RELAXED));\n-\t\t\t__atomic_fetch_add(&cache_resource->refcnt, 1,\n-\t\t\t\t\t   __ATOMIC_RELAXED);\n-\t\t\tdev_flow->handle->dvh.rix_sample = idx;\n-\t\t\tdev_flow->dv.sample_res = cache_resource;\n-\t\t\t/*\n-\t\t\t * Existing smaple action should release the prepared\n-\t\t\t * sub-actions reference counter.\n-\t\t\t */\n-\t\t\tflow_dv_sample_sub_actions_release(dev,\n-\t\t\t\t\t\t\t&resource->sample_idx);\n-\t\t\treturn 0;\n-\t\t}\n-\t}\n \t/* Register new sample resource. */\n-\tcache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_SAMPLE],\n-\t\t\t\t       &dev_flow->handle->dvh.rix_sample);\n-\tif (!cache_resource)\n-\t\treturn rte_flow_error_set(error, ENOMEM,\n+\tcache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_SAMPLE], &idx);\n+\tif (!cache_resource) {\n+\t\trte_flow_error_set(error, ENOMEM,\n \t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n \t\t\t\t\t  NULL,\n \t\t\t\t\t  \"cannot allocate resource memory\");\n+\t\treturn NULL;\n+\t}\n \t*cache_resource = *resource;\n \t/* Create normal path table level */\n \tif (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)\n@@ -8714,7 +8702,7 @@ struct mlx5_hlist_entry *\n \t\tis_egress = 1;\n \ttbl = flow_dv_tbl_resource_get(dev, next_ft_id,\n \t\t\t\t\tis_egress, is_transfer,\n-\t\t\t\t\tdev_flow->external, NULL, 0, 0, error);\n+\t\t\t\t\ttrue, NULL, 0, 0, error);\n \tif (!tbl) {\n \t\trte_flow_error_set(error, ENOMEM,\n \t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n@@ -8753,15 +8741,8 @@ struct mlx5_hlist_entry *\n \t\t\t\t\tNULL, \"cannot create sample action\");\n \t\tgoto error;\n \t}\n-\t__atomic_store_n(&cache_resource->refcnt, 1, __ATOMIC_RELAXED);\n-\tILIST_INSERT(sh->ipool[MLX5_IPOOL_SAMPLE], &sh->sample_action_list,\n-\t\t     dev_flow->handle->dvh.rix_sample, cache_resource,\n-\t\t     next);\n-\tdev_flow->dv.sample_res = cache_resource;\n-\tDRV_LOG(DEBUG, \"new sample resource %p: refcnt %d++\",\n-\t\t(void *)cache_resource,\n-\t\t__atomic_load_n(&cache_resource->refcnt, __ATOMIC_RELAXED));\n-\treturn 0;\n+\tcache_resource->idx = idx;\n+\treturn &cache_resource->entry;\n error:\n \tif (cache_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB &&\n \t    cache_resource->default_miss)\n@@ -8773,19 +8754,18 @@ struct mlx5_hlist_entry *\n \tif (cache_resource->normal_path_tbl)\n \t\tflow_dv_tbl_resource_release(MLX5_SH(dev),\n \t\t\t\tcache_resource->normal_path_tbl);\n-\tmlx5_ipool_free(sh->ipool[MLX5_IPOOL_SAMPLE],\n-\t\t\t\tdev_flow->handle->dvh.rix_sample);\n-\tdev_flow->handle->dvh.rix_sample = 0;\n-\treturn -rte_errno;\n+\tmlx5_ipool_free(sh->ipool[MLX5_IPOOL_SAMPLE], idx);\n+\treturn NULL;\n+\n }\n \n /**\n- * Find existing destination array resource or create and register a new one.\n+ * Find existing sample resource or create and register a new one.\n  *\n  * @param[in, out] dev\n  *   Pointer to rte_eth_dev structure.\n  * @param[in] resource\n- *   Pointer to destination array resource.\n+ *   Pointer to sample resource.\n  * @parm[in, out] dev_flow\n  *   Pointer to the dev_flow.\n  * @param[out] error\n@@ -8795,56 +8775,86 @@ struct mlx5_hlist_entry *\n  *   0 on success otherwise -errno and errno is set.\n  */\n static int\n-flow_dv_dest_array_resource_register(struct rte_eth_dev *dev,\n-\t\t\t struct mlx5_flow_dv_dest_array_resource *resource,\n+flow_dv_sample_resource_register(struct rte_eth_dev *dev,\n+\t\t\t struct mlx5_flow_dv_sample_resource *resource,\n \t\t\t struct mlx5_flow *dev_flow,\n \t\t\t struct rte_flow_error *error)\n {\n+\tstruct mlx5_flow_dv_sample_resource *cache_resource;\n+\tstruct mlx5_cache_entry *entry;\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_flow_cb_ctx ctx = {\n+\t\t.dev = dev,\n+\t\t.error = error,\n+\t\t.data = resource,\n+\t};\n+\n+\tentry = mlx5_cache_register(&priv->sh->sample_action_list, &ctx);\n+\tif (!entry)\n+\t\treturn -rte_errno;\n+\tcache_resource = container_of(entry, typeof(*cache_resource), entry);\n+\tdev_flow->handle->dvh.rix_sample = cache_resource->idx;\n+\tdev_flow->dv.sample_res = cache_resource;\n+\treturn 0;\n+}\n+\n+int\n+flow_dv_dest_array_match_cb(struct mlx5_cache_list *list __rte_unused,\n+\t\t\t    struct mlx5_cache_entry *entry, void *cb_ctx)\n+{\n+\tstruct mlx5_flow_cb_ctx *ctx = cb_ctx;\n+\tstruct mlx5_flow_dv_dest_array_resource *resource = ctx->data;\n+\tstruct rte_eth_dev *dev = ctx->dev;\n+\tstruct mlx5_flow_dv_dest_array_resource *cache_resource =\n+\t\t\tcontainer_of(entry, typeof(*cache_resource), entry);\n+\tuint32_t idx = 0;\n+\n+\tif (resource->num_of_dest == cache_resource->num_of_dest &&\n+\t    resource->ft_type == cache_resource->ft_type &&\n+\t    !memcmp((void *)cache_resource->sample_act,\n+\t\t    (void *)resource->sample_act,\n+\t\t   (resource->num_of_dest *\n+\t\t   sizeof(struct mlx5_flow_sub_actions_list)))) {\n+\t\t/*\n+\t\t * Existing sample action should release the prepared\n+\t\t * sub-actions reference counter.\n+\t\t */\n+\t\tfor (idx = 0; idx < resource->num_of_dest; idx++)\n+\t\t\tflow_dv_sample_sub_actions_release(dev,\n+\t\t\t\t\t&resource->sample_idx[idx]);\n+\t\treturn 0;\n+\t}\n+\treturn 1;\n+}\n+\n+struct mlx5_cache_entry *\n+flow_dv_dest_array_create_cb(struct mlx5_cache_list *list __rte_unused,\n+\t\t\t struct mlx5_cache_entry *entry __rte_unused,\n+\t\t\t void *cb_ctx)\n+{\n+\tstruct mlx5_flow_cb_ctx *ctx = cb_ctx;\n+\tstruct rte_eth_dev *dev = ctx->dev;\n \tstruct mlx5_flow_dv_dest_array_resource *cache_resource;\n+\tstruct mlx5_flow_dv_dest_array_resource *resource = ctx->data;\n \tstruct mlx5dv_dr_action_dest_attr *dest_attr[MLX5_MAX_DEST_NUM] = { 0 };\n \tstruct mlx5dv_dr_action_dest_reformat dest_reformat[MLX5_MAX_DEST_NUM];\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_dev_ctx_shared *sh = priv->sh;\n \tstruct mlx5_flow_sub_actions_list *sample_act;\n \tstruct mlx5dv_dr_domain *domain;\n-\tuint32_t idx = 0;\n+\tuint32_t idx = 0, res_idx = 0;\n+\tstruct rte_flow_error *error = ctx->error;\n \n-\t/* Lookup a matching resource from cache. */\n-\tILIST_FOREACH(sh->ipool[MLX5_IPOOL_DEST_ARRAY],\n-\t\t      sh->dest_array_list,\n-\t\t      idx, cache_resource, next) {\n-\t\tif (resource->num_of_dest == cache_resource->num_of_dest &&\n-\t\t    resource->ft_type == cache_resource->ft_type &&\n-\t\t    !memcmp((void *)cache_resource->sample_act,\n-\t\t\t    (void *)resource->sample_act,\n-\t\t\t   (resource->num_of_dest *\n-\t\t\t   sizeof(struct mlx5_flow_sub_actions_list)))) {\n-\t\t\tDRV_LOG(DEBUG, \"dest array resource %p: refcnt %d++\",\n-\t\t\t\t(void *)cache_resource,\n-\t\t\t\t__atomic_load_n(&cache_resource->refcnt,\n-\t\t\t\t\t\t__ATOMIC_RELAXED));\n-\t\t\t__atomic_fetch_add(&cache_resource->refcnt, 1,\n-\t\t\t\t\t   __ATOMIC_RELAXED);\n-\t\t\tdev_flow->handle->dvh.rix_dest_array = idx;\n-\t\t\tdev_flow->dv.dest_array_res = cache_resource;\n-\t\t\t/*\n-\t\t\t * Existing smaple action should release the prepared\n-\t\t\t * sub-actions reference counter.\n-\t\t\t */\n-\t\t\tfor (idx = 0; idx < resource->num_of_dest; idx++)\n-\t\t\t\tflow_dv_sample_sub_actions_release(dev,\n-\t\t\t\t\t\t&resource->sample_idx[idx]);\n-\t\t\treturn 0;\n-\t\t}\n-\t}\n \t/* Register new destination array resource. */\n \tcache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DEST_ARRAY],\n-\t\t\t\t       &dev_flow->handle->dvh.rix_dest_array);\n-\tif (!cache_resource)\n-\t\treturn rte_flow_error_set(error, ENOMEM,\n+\t\t\t\t\t    &res_idx);\n+\tif (!cache_resource) {\n+\t\trte_flow_error_set(error, ENOMEM,\n \t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n \t\t\t\t\t  NULL,\n \t\t\t\t\t  \"cannot allocate resource memory\");\n+\t\treturn NULL;\n+\t}\n \t*cache_resource = *resource;\n \tif (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)\n \t\tdomain = sh->fdb_domain;\n@@ -8893,18 +8903,10 @@ struct mlx5_hlist_entry *\n \t\t\t\t   \"cannot create destination array action\");\n \t\tgoto error;\n \t}\n-\t__atomic_store_n(&cache_resource->refcnt, 1, __ATOMIC_RELAXED);\n-\tILIST_INSERT(sh->ipool[MLX5_IPOOL_DEST_ARRAY],\n-\t\t     &sh->dest_array_list,\n-\t\t     dev_flow->handle->dvh.rix_dest_array, cache_resource,\n-\t\t     next);\n-\tdev_flow->dv.dest_array_res = cache_resource;\n-\tDRV_LOG(DEBUG, \"new destination array resource %p: refcnt %d++\",\n-\t\t(void *)cache_resource,\n-\t\t__atomic_load_n(&cache_resource->refcnt, __ATOMIC_RELAXED));\n+\tcache_resource->idx = res_idx;\n \tfor (idx = 0; idx < resource->num_of_dest; idx++)\n \t\tmlx5_free(dest_attr[idx]);\n-\treturn 0;\n+\treturn &cache_resource->entry;\n error:\n \tfor (idx = 0; idx < resource->num_of_dest; idx++) {\n \t\tstruct mlx5_flow_sub_actions_idx *act_res =\n@@ -8925,10 +8927,47 @@ struct mlx5_hlist_entry *\n \t\t\tmlx5_free(dest_attr[idx]);\n \t}\n \n-\tmlx5_ipool_free(sh->ipool[MLX5_IPOOL_DEST_ARRAY],\n-\t\t\t\tdev_flow->handle->dvh.rix_dest_array);\n-\tdev_flow->handle->dvh.rix_dest_array = 0;\n-\treturn -rte_errno;\n+\tmlx5_ipool_free(sh->ipool[MLX5_IPOOL_DEST_ARRAY], res_idx);\n+\treturn NULL;\n+}\n+\n+/**\n+ * Find existing destination array resource or create and register a new one.\n+ *\n+ * @param[in, out] dev\n+ *   Pointer to rte_eth_dev structure.\n+ * @param[in] resource\n+ *   Pointer to destination array resource.\n+ * @parm[in, out] dev_flow\n+ *   Pointer to the dev_flow.\n+ * @param[out] error\n+ *   pointer to error structure.\n+ *\n+ * @return\n+ *   0 on success otherwise -errno and errno is set.\n+ */\n+static int\n+flow_dv_dest_array_resource_register(struct rte_eth_dev *dev,\n+\t\t\t struct mlx5_flow_dv_dest_array_resource *resource,\n+\t\t\t struct mlx5_flow *dev_flow,\n+\t\t\t struct rte_flow_error *error)\n+{\n+\tstruct mlx5_flow_dv_dest_array_resource *cache_resource;\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_cache_entry *entry;\n+\tstruct mlx5_flow_cb_ctx ctx = {\n+\t\t.dev = dev,\n+\t\t.error = error,\n+\t\t.data = resource,\n+\t};\n+\n+\tentry = mlx5_cache_register(&priv->sh->dest_array_list, &ctx);\n+\tif (!entry)\n+\t\treturn -rte_errno;\n+\tcache_resource = container_of(entry, typeof(*cache_resource), entry);\n+\tdev_flow->handle->dvh.rix_dest_array = cache_resource->idx;\n+\tdev_flow->dv.dest_array_res = cache_resource;\n+\treturn 0;\n }\n \n /**\n@@ -9235,8 +9274,8 @@ struct mlx5_hlist_entry *\n \t\t\t\t\t\t  NULL, \"can't create sample \"\n \t\t\t\t\t\t  \"action\");\n \t} else {\n-\t\tif (flow_dv_sample_resource_register(dev, res, dev_flow,\n-\t\t\t\t\t\t     sample_actions, error))\n+\t\tres->sub_actions = sample_actions;\n+\t\tif (flow_dv_sample_resource_register(dev, res, dev_flow, error))\n \t\t\treturn rte_flow_error_set(error, EINVAL,\n \t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n \t\t\t\t\t\t  NULL,\n@@ -10690,6 +10729,34 @@ struct mlx5_hlist_entry *\n \thandle->rix_fate = 0;\n }\n \n+void\n+flow_dv_sample_remove_cb(struct mlx5_cache_list *list,\n+\t\t\t struct mlx5_cache_entry *entry)\n+{\n+\tstruct rte_eth_dev *dev = list->ctx;\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_flow_dv_sample_resource *cache_resource =\n+\t\t\tcontainer_of(entry, typeof(*cache_resource), entry);\n+\n+\tif (cache_resource->verbs_action)\n+\t\tclaim_zero(mlx5_glue->destroy_flow_action\n+\t\t\t\t(cache_resource->verbs_action));\n+\tif (cache_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) {\n+\t\tif (cache_resource->default_miss)\n+\t\t\tclaim_zero(mlx5_glue->destroy_flow_action\n+\t\t\t  (cache_resource->default_miss));\n+\t}\n+\tif (cache_resource->normal_path_tbl)\n+\t\tflow_dv_tbl_resource_release(MLX5_SH(dev),\n+\t\t\tcache_resource->normal_path_tbl);\n+\tflow_dv_sample_sub_actions_release(dev,\n+\t\t\t\t&cache_resource->sample_idx);\n+\tmlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_SAMPLE],\n+\t\t\tcache_resource->idx);\n+\tDRV_LOG(DEBUG, \"sample resource %p: removed\",\n+\t\t(void *)cache_resource);\n+}\n+\n /**\n  * Release an sample resource.\n  *\n@@ -10706,41 +10773,38 @@ struct mlx5_hlist_entry *\n \t\t\t\t     struct mlx5_flow_handle *handle)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tuint32_t idx = handle->dvh.rix_sample;\n \tstruct mlx5_flow_dv_sample_resource *cache_resource;\n \n \tcache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_SAMPLE],\n-\t\t\t idx);\n+\t\t\t handle->dvh.rix_sample);\n \tif (!cache_resource)\n \t\treturn 0;\n \tMLX5_ASSERT(cache_resource->verbs_action);\n-\tDRV_LOG(DEBUG, \"sample resource %p: refcnt %d--\",\n-\t\t(void *)cache_resource,\n-\t\t__atomic_load_n(&cache_resource->refcnt, __ATOMIC_RELAXED));\n-\tif (__atomic_sub_fetch(&cache_resource->refcnt, 1,\n-\t\t\t       __ATOMIC_RELAXED) == 0) {\n-\t\tif (cache_resource->verbs_action)\n-\t\t\tclaim_zero(mlx5_glue->destroy_flow_action\n-\t\t\t\t\t(cache_resource->verbs_action));\n-\t\tif (cache_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) {\n-\t\t\tif (cache_resource->default_miss)\n-\t\t\t\tclaim_zero(mlx5_glue->destroy_flow_action\n-\t\t\t\t  (cache_resource->default_miss));\n-\t\t}\n-\t\tif (cache_resource->normal_path_tbl)\n-\t\t\tflow_dv_tbl_resource_release(MLX5_SH(dev),\n-\t\t\t\tcache_resource->normal_path_tbl);\n+\treturn mlx5_cache_unregister(&priv->sh->sample_action_list,\n+\t\t\t\t     &cache_resource->entry);\n+}\n+\n+void\n+flow_dv_dest_array_remove_cb(struct mlx5_cache_list *list,\n+\t\t\t     struct mlx5_cache_entry *entry)\n+{\n+\tstruct rte_eth_dev *dev = list->ctx;\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_flow_dv_dest_array_resource *cache_resource =\n+\t\t\tcontainer_of(entry, typeof(*cache_resource), entry);\n+\tuint32_t i = 0;\n+\n+\tMLX5_ASSERT(cache_resource->action);\n+\tif (cache_resource->action)\n+\t\tclaim_zero(mlx5_glue->destroy_flow_action\n+\t\t\t\t\t(cache_resource->action));\n+\tfor (; i < cache_resource->num_of_dest; i++)\n \t\tflow_dv_sample_sub_actions_release(dev,\n-\t\t\t\t\t&cache_resource->sample_idx);\n-\t\tILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_SAMPLE],\n-\t\t\t     &priv->sh->sample_action_list, idx,\n-\t\t\t     cache_resource, next);\n-\t\tmlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_SAMPLE], idx);\n-\t\tDRV_LOG(DEBUG, \"sample resource %p: removed\",\n-\t\t\t(void *)cache_resource);\n-\t\treturn 0;\n-\t}\n-\treturn 1;\n+\t\t\t\t&cache_resource->sample_idx[i]);\n+\tmlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY],\n+\t\t\tcache_resource->idx);\n+\tDRV_LOG(DEBUG, \"destination array resource %p: removed\",\n+\t\t(void *)cache_resource);\n }\n \n /**\n@@ -10756,38 +10820,18 @@ struct mlx5_hlist_entry *\n  */\n static int\n flow_dv_dest_array_resource_release(struct rte_eth_dev *dev,\n-\t\t\t\t     struct mlx5_flow_handle *handle)\n+\t\t\t\t    struct mlx5_flow_handle *handle)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_flow_dv_dest_array_resource *cache_resource;\n-\tuint32_t idx = handle->dvh.rix_dest_array;\n-\tuint32_t i = 0;\n+\tstruct mlx5_flow_dv_dest_array_resource *cache;\n \n-\tcache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY],\n-\t\t\t idx);\n-\tif (!cache_resource)\n-\t\treturn 0;\n-\tMLX5_ASSERT(cache_resource->action);\n-\tDRV_LOG(DEBUG, \"destination array resource %p: refcnt %d--\",\n-\t\t(void *)cache_resource,\n-\t\t__atomic_load_n(&cache_resource->refcnt, __ATOMIC_RELAXED));\n-\tif (__atomic_sub_fetch(&cache_resource->refcnt, 1,\n-\t\t\t       __ATOMIC_RELAXED) == 0) {\n-\t\tif (cache_resource->action)\n-\t\t\tclaim_zero(mlx5_glue->destroy_flow_action\n-\t\t\t\t\t\t(cache_resource->action));\n-\t\tfor (; i < cache_resource->num_of_dest; i++)\n-\t\t\tflow_dv_sample_sub_actions_release(dev,\n-\t\t\t\t\t&cache_resource->sample_idx[i]);\n-\t\tILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY],\n-\t\t\t     &priv->sh->dest_array_list, idx,\n-\t\t\t     cache_resource, next);\n-\t\tmlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY], idx);\n-\t\tDRV_LOG(DEBUG, \"destination array resource %p: removed\",\n-\t\t\t(void *)cache_resource);\n+\tcache = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY],\n+\t\t\t       handle->dvh.rix_dest_array);\n+\tif (!cache)\n \t\treturn 0;\n-\t}\n-\treturn 1;\n+\tMLX5_ASSERT(cache->action);\n+\treturn mlx5_cache_unregister(&priv->sh->dest_array_list,\n+\t\t\t\t     &cache->entry);\n }\n \n /**\n",
    "prefixes": [
        "v5",
        "29/34"
    ]
}