get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 70108,
    "url": "https://patches.dpdk.org/api/patches/70108/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1589287933-91969-1-git-send-email-matan@mellanox.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": "<1589287933-91969-1-git-send-email-matan@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1589287933-91969-1-git-send-email-matan@mellanox.com",
    "date": "2020-05-12T12:52:13",
    "name": "net/mlx5: fix counter container resize",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "7684baef200e32c720883d16af14b33d47fbdfa8",
    "submitter": {
        "id": 796,
        "url": "https://patches.dpdk.org/api/people/796/?format=api",
        "name": "Matan Azrad",
        "email": "matan@mellanox.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/1589287933-91969-1-git-send-email-matan@mellanox.com/mbox/",
    "series": [
        {
            "id": 9998,
            "url": "https://patches.dpdk.org/api/series/9998/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=9998",
            "date": "2020-05-12T12:52:13",
            "name": "net/mlx5: fix counter container resize",
            "version": 1,
            "mbox": "https://patches.dpdk.org/series/9998/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/70108/comments/",
    "check": "fail",
    "checks": "https://patches.dpdk.org/api/patches/70108/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 3CF32A04A2;\n\tTue, 12 May 2020 14:52:36 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 1F7D61BFB9;\n\tTue, 12 May 2020 14:52:35 +0200 (CEST)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by dpdk.org (Postfix) with ESMTP id 00EF51BFB6\n for <dev@dpdk.org>; Tue, 12 May 2020 14:52:32 +0200 (CEST)",
            "from Internal Mail-Server by MTLPINE2 (envelope-from\n matan@mellanox.com)\n with ESMTPS (AES256-SHA encrypted); 12 May 2020 15:52:25 +0300",
            "from pegasus25.mtr.labs.mlnx. (pegasus25.mtr.labs.mlnx\n [10.210.16.10])\n by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 04CCqPWZ026326;\n Tue, 12 May 2020 15:52:25 +0300"
        ],
        "From": "Matan Azrad <matan@mellanox.com>",
        "To": "dev@dpdk.org",
        "Cc": "Viacheslav Ovsiienko <viacheslavo@mellanox.com>, stable@dpdk.org",
        "Date": "Tue, 12 May 2020 12:52:13 +0000",
        "Message-Id": "<1589287933-91969-1-git-send-email-matan@mellanox.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "Subject": "[dpdk-dev] [PATCH] net/mlx5: fix counter container resize",
        "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": "The design of counter container resize used double buffer algorithm in\norder to synchronize between the query thread to the control thread.\nWhen the control thread detected resize need, it created new bigger\nbuffer for the counter pools in a new container and change the container\nindex atomically.\nIn case the query thread had not detect the previous resize before a new\none need was detected by the control thread, the control thread returned\nEAGAIN to the flow creation API used a COUNT action.\n\nThe rte_flow API doesn't allow unblocked commands and doesn't expect to\nget EAGAIN error type.\n\nSo, when a lot of flows were created between 2 different periodic\nqueries, 2 different resizes might try to be created and caused EAGAIN\nerror.\nThis behavior may blame flow creations.\n\nChange the synchronization way to use lock instead of double buffer\nalgorithm.\n\nThe critical section of this lock is very small, so flow insertion\nrate should not be decreased.\n\nFixes: ebbac312e448 (\"net/mlx5: resize a full counter container\")\nCc: stable@dpdk.org\n\nSigned-off-by: Matan Azrad <matan@mellanox.com>\n---\n drivers/net/mlx5/mlx5.c            |  70 +++++++++++------------\n drivers/net/mlx5/mlx5.h            |  23 +++++---\n drivers/net/mlx5/mlx5_flow.c       |  37 ++++---------\n drivers/net/mlx5/mlx5_flow.h       |   6 --\n drivers/net/mlx5/mlx5_flow_dv.c    | 110 +++++++++++++++----------------------\n drivers/net/mlx5/mlx5_flow_verbs.c |   6 +-\n 6 files changed, 104 insertions(+), 148 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex 4f704cb..1445809 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -467,13 +467,13 @@ struct mlx5_flow_id_pool *\n static void\n mlx5_flow_counters_mng_init(struct mlx5_ibv_shared *sh)\n {\n-\tuint8_t i, age;\n+\tint i;\n \n-\tsh->cmng.age = 0;\n+\tmemset(&sh->cmng, 0, sizeof(sh->cmng));\n \tTAILQ_INIT(&sh->cmng.flow_counters);\n-\tfor (age = 0; age < RTE_DIM(sh->cmng.ccont[0]); ++age) {\n-\t\tfor (i = 0; i < RTE_DIM(sh->cmng.ccont); ++i)\n-\t\t\tTAILQ_INIT(&sh->cmng.ccont[i][age].pool_list);\n+\tfor (i = 0; i < MLX5_CCONT_TYPE_MAX; ++i) {\n+\t\tTAILQ_INIT(&sh->cmng.ccont[i].pool_list);\n+\t\trte_spinlock_init(&sh->cmng.ccont[i].resize_sl);\n \t}\n }\n \n@@ -504,7 +504,7 @@ struct mlx5_flow_id_pool *\n mlx5_flow_counters_mng_close(struct mlx5_ibv_shared *sh)\n {\n \tstruct mlx5_counter_stats_mem_mng *mng;\n-\tuint8_t i, age = 0;\n+\tint i;\n \tint j;\n \tint retries = 1024;\n \n@@ -515,42 +515,34 @@ struct mlx5_flow_id_pool *\n \t\t\tbreak;\n \t\trte_pause();\n \t}\n+\tfor (i = 0; i < MLX5_CCONT_TYPE_MAX; ++i) {\n+\t\tstruct mlx5_flow_counter_pool *pool;\n+\t\tuint32_t batch = !!(i > 1);\n \n-\tfor (age = 0; age < RTE_DIM(sh->cmng.ccont[0]); ++age) {\n-\t\tfor (i = 0; i < RTE_DIM(sh->cmng.ccont); ++i) {\n-\t\t\tstruct mlx5_flow_counter_pool *pool;\n-\t\t\tuint32_t batch = !!(i % 2);\n-\n-\t\t\tif (!sh->cmng.ccont[i][age].pools)\n-\t\t\t\tcontinue;\n-\t\t\tpool = TAILQ_FIRST(&sh->cmng.ccont[i][age].pool_list);\n-\t\t\twhile (pool) {\n-\t\t\t\tif (batch) {\n-\t\t\t\t\tif (pool->min_dcs)\n-\t\t\t\t\t\tclaim_zero\n-\t\t\t\t\t\t(mlx5_devx_cmd_destroy\n-\t\t\t\t\t\t(pool->min_dcs));\n-\t\t\t\t}\n-\t\t\t\tfor (j = 0; j < MLX5_COUNTERS_PER_POOL; ++j) {\n-\t\t\t\t\tif (MLX5_POOL_GET_CNT(pool, j)->action)\n-\t\t\t\t\t\tclaim_zero\n-\t\t\t\t\t\t(mlx5_glue->destroy_flow_action\n-\t\t\t\t\t\t (MLX5_POOL_GET_CNT\n-\t\t\t\t\t\t  (pool, j)->action));\n-\t\t\t\t\tif (!batch && MLX5_GET_POOL_CNT_EXT\n-\t\t\t\t\t    (pool, j)->dcs)\n-\t\t\t\t\t\tclaim_zero(mlx5_devx_cmd_destroy\n-\t\t\t\t\t\t\t  (MLX5_GET_POOL_CNT_EXT\n-\t\t\t\t\t\t\t  (pool, j)->dcs));\n-\t\t\t\t}\n-\t\t\t\tTAILQ_REMOVE(&sh->cmng.ccont[i][age].pool_list,\n-\t\t\t\t\tpool, next);\n-\t\t\t\trte_free(pool);\n-\t\t\t\tpool = TAILQ_FIRST\n-\t\t\t\t\t(&sh->cmng.ccont[i][age].pool_list);\n+\t\tif (!sh->cmng.ccont[i].pools)\n+\t\t\tcontinue;\n+\t\tpool = TAILQ_FIRST(&sh->cmng.ccont[i].pool_list);\n+\t\twhile (pool) {\n+\t\t\tif (batch && pool->min_dcs)\n+\t\t\t\tclaim_zero(mlx5_devx_cmd_destroy\n+\t\t\t\t\t\t\t       (pool->min_dcs));\n+\t\t\tfor (j = 0; j < MLX5_COUNTERS_PER_POOL; ++j) {\n+\t\t\t\tif (MLX5_POOL_GET_CNT(pool, j)->action)\n+\t\t\t\t\tclaim_zero\n+\t\t\t\t\t (mlx5_glue->destroy_flow_action\n+\t\t\t\t\t  (MLX5_POOL_GET_CNT\n+\t\t\t\t\t  (pool, j)->action));\n+\t\t\t\tif (!batch && MLX5_GET_POOL_CNT_EXT\n+\t\t\t\t    (pool, j)->dcs)\n+\t\t\t\t\tclaim_zero(mlx5_devx_cmd_destroy\n+\t\t\t\t\t\t   (MLX5_GET_POOL_CNT_EXT\n+\t\t\t\t\t\t    (pool, j)->dcs));\n \t\t\t}\n-\t\t\trte_free(sh->cmng.ccont[i][age].pools);\n+\t\t\tTAILQ_REMOVE(&sh->cmng.ccont[i].pool_list, pool, next);\n+\t\t\trte_free(pool);\n+\t\t\tpool = TAILQ_FIRST(&sh->cmng.ccont[i].pool_list);\n \t\t}\n+\t\trte_free(sh->cmng.ccont[i].pools);\n \t}\n \tmng = LIST_FIRST(&sh->cmng.mem_mngs);\n \twhile (mng) {\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex 1740d4a..d9f5d81 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -227,13 +227,11 @@ struct mlx5_drop {\n #define CNTEXT_SIZE (sizeof(struct mlx5_flow_counter_ext))\n #define AGE_SIZE (sizeof(struct mlx5_age_param))\n #define MLX5_AGING_TIME_DELAY\t7\n-\n #define CNT_POOL_TYPE_EXT\t(1 << 0)\n #define CNT_POOL_TYPE_AGE\t(1 << 1)\n #define IS_EXT_POOL(pool) (((pool)->type) & CNT_POOL_TYPE_EXT)\n #define IS_AGE_POOL(pool) (((pool)->type) & CNT_POOL_TYPE_AGE)\n #define MLX_CNT_IS_AGE(counter) ((counter) & MLX5_CNT_AGE_OFFSET ? 1 : 0)\n-\n #define MLX5_CNT_LEN(pool) \\\n \t(CNT_SIZE + \\\n \t(IS_AGE_POOL(pool) ? AGE_SIZE : 0) + \\\n@@ -270,6 +268,17 @@ enum {\n \tAGE_TMOUT, /* Timeout, wait for rte_flow_get_aged_flows and destroy. */\n };\n \n+#define MLX5_CNT_CONTAINER(sh, batch, age) (&(sh)->cmng.ccont \\\n+\t\t\t\t\t    [(batch) * 2 + (age)])\n+\n+enum {\n+\tMLX5_CCONT_TYPE_SINGLE,\n+\tMLX5_CCONT_TYPE_SINGLE_FOR_AGE,\n+\tMLX5_CCONT_TYPE_BATCH,\n+\tMLX5_CCONT_TYPE_BATCH_FOR_AGE,\n+\tMLX5_CCONT_TYPE_MAX,\n+};\n+\n /* Counter age parameter. */\n struct mlx5_age_param {\n \trte_atomic16_t state; /**< Age state. */\n@@ -313,7 +322,6 @@ struct mlx5_flow_counter_ext {\n \t};\n };\n \n-\n TAILQ_HEAD(mlx5_counters, mlx5_flow_counter);\n \n /* Generic counter pool structure - query is in pool resolution. */\n@@ -358,17 +366,16 @@ struct mlx5_counter_stats_raw {\n struct mlx5_pools_container {\n \trte_atomic16_t n_valid; /* Number of valid pools. */\n \tuint16_t n; /* Number of pools. */\n+\trte_spinlock_t resize_sl; /* The resize lock. */\n \tstruct mlx5_counter_pools pool_list; /* Counter pool list. */\n \tstruct mlx5_flow_counter_pool **pools; /* Counter pool array. */\n-\tstruct mlx5_counter_stats_mem_mng *init_mem_mng;\n+\tstruct mlx5_counter_stats_mem_mng *mem_mng;\n \t/* Hold the memory management for the next allocated pools raws. */\n };\n \n /* Counter global management structure. */\n struct mlx5_flow_counter_mng {\n-\tuint8_t mhi[2][2]; /* master \\ host and age \\ no age container index. */\n-\tstruct mlx5_pools_container ccont[2 * 2][2];\n-\t/* master \\ host and age \\ no age pools container. */\n+\tstruct mlx5_pools_container ccont[MLX5_CCONT_TYPE_MAX];\n \tstruct mlx5_counters flow_counters; /* Legacy flow counter list. */\n \tuint8_t pending_queries;\n \tuint8_t batch;\n@@ -378,6 +385,7 @@ struct mlx5_flow_counter_mng {\n \tLIST_HEAD(mem_mngs, mlx5_counter_stats_mem_mng) mem_mngs;\n \tLIST_HEAD(stat_raws, mlx5_counter_stats_raw) free_stat_raws;\n };\n+\n #define MLX5_AGE_EVENT_NEW\t\t1\n #define MLX5_AGE_TRIGGER\t\t2\n #define MLX5_AGE_SET(age_info, BIT) \\\n@@ -393,6 +401,7 @@ struct mlx5_age_info {\n \tstruct mlx5_counters aged_counters; /* Aged flow counter list. */\n \trte_spinlock_t aged_sl; /* Aged flow counter list lock. */\n };\n+\n /* Per port data of shared IB device. */\n struct mlx5_ibv_shared_port {\n \tuint32_t ih_port_id;\ndiff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex 08c7cdf..ae478a5 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -5801,16 +5801,11 @@ struct mlx5_meter_domains_infos *\n static uint32_t\n mlx5_get_all_valid_pool_count(struct mlx5_ibv_shared *sh)\n {\n-\tuint8_t age, i;\n+\tint i;\n \tuint32_t pools_n = 0;\n-\tstruct mlx5_pools_container *cont;\n \n-\tfor (age = 0; age < RTE_DIM(sh->cmng.ccont[0]); ++age) {\n-\t\tfor (i = 0; i < 2 ; ++i) {\n-\t\t\tcont = MLX5_CNT_CONTAINER(sh, i, 0, age);\n-\t\t\tpools_n += rte_atomic16_read(&cont->n_valid);\n-\t\t}\n-\t}\n+\tfor (i = 0; i < MLX5_CCONT_TYPE_MAX; ++i)\n+\t\tpools_n += rte_atomic16_read(&sh->cmng.ccont[i].n_valid);\n \treturn pools_n;\n }\n \n@@ -5855,32 +5850,19 @@ struct mlx5_meter_domains_infos *\n \tuint8_t age = sh->cmng.age;\n \tuint16_t pool_index = sh->cmng.pool_index;\n \tstruct mlx5_pools_container *cont;\n-\tstruct mlx5_pools_container *mcont;\n \tstruct mlx5_flow_counter_pool *pool;\n+\tint cont_loop = MLX5_CCONT_TYPE_MAX;\n \n \tif (sh->cmng.pending_queries >= MLX5_MAX_PENDING_QUERIES)\n \t\tgoto set_alarm;\n next_container:\n-\tcont = MLX5_CNT_CONTAINER(sh, batch, 1, age);\n-\tmcont = MLX5_CNT_CONTAINER(sh, batch, 0, age);\n-\t/* Check if resize was done and need to flip a container. */\n-\tif (cont != mcont) {\n-\t\tif (cont->pools) {\n-\t\t\t/* Clean the old container. */\n-\t\t\trte_free(cont->pools);\n-\t\t\tmemset(cont, 0, sizeof(*cont));\n-\t\t}\n-\t\trte_cio_wmb();\n-\t\t /* Flip the host container. */\n-\t\tsh->cmng.mhi[batch][age] ^= (uint8_t)2;\n-\t\tcont = mcont;\n-\t}\n+\tcont = MLX5_CNT_CONTAINER(sh, batch, age);\n+\trte_spinlock_lock(&cont->resize_sl);\n \tif (!cont->pools) {\n-\t\t/* 2 empty containers case is unexpected. */\n-\t\tif (unlikely(batch != sh->cmng.batch) &&\n-\t\t\tunlikely(age != sh->cmng.age)) {\n+\t\trte_spinlock_unlock(&cont->resize_sl);\n+\t\t/* Check if all the containers are empty. */\n+\t\tif (unlikely(--cont_loop == 0))\n \t\t\tgoto set_alarm;\n-\t\t}\n \t\tbatch ^= 0x1;\n \t\tpool_index = 0;\n \t\tif (batch == 0 && pool_index == 0) {\n@@ -5891,6 +5873,7 @@ struct mlx5_meter_domains_infos *\n \t\tgoto next_container;\n \t}\n \tpool = cont->pools[pool_index];\n+\trte_spinlock_unlock(&cont->resize_sl);\n \tif (pool->raw_hw)\n \t\t/* There is a pool query in progress. */\n \t\tgoto set_alarm;\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex 7f5e01f..2c96677 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -900,12 +900,6 @@ struct mlx5_flow_driver_ops {\n \tmlx5_flow_get_aged_flows_t get_aged_flows;\n };\n \n-\n-#define MLX5_CNT_CONTAINER(sh, batch, thread, age) (&(sh)->cmng.ccont \\\n-\t[(((sh)->cmng.mhi[batch][age] >> (thread)) & 0x1) * 2 + (batch)][age])\n-#define MLX5_CNT_CONTAINER_UNUSED(sh, batch, thread, age) (&(sh)->cmng.ccont \\\n-\t[(~((sh)->cmng.mhi[batch][age] >> (thread)) & 0x1) * 2 + (batch)][age])\n-\n /* mlx5_flow.c */\n \n struct mlx5_flow_id_pool *mlx5_flow_id_pool_alloc(uint32_t max_id);\ndiff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c\nindex 4ebb7ce..c46a589 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -4038,7 +4038,7 @@ struct field_modify_info modify_tcp[] = {\n \t\tidx -= MLX5_CNT_BATCH_OFFSET;\n \t\tbatch = 1;\n \t}\n-\tcont = MLX5_CNT_CONTAINER(priv->sh, batch, 0, age);\n+\tcont = MLX5_CNT_CONTAINER(priv->sh, batch, age);\n \tMLX5_ASSERT(idx / MLX5_COUNTERS_PER_POOL < cont->n);\n \tpool = cont->pools[idx / MLX5_COUNTERS_PER_POOL];\n \tMLX5_ASSERT(pool);\n@@ -4162,69 +4162,55 @@ struct field_modify_info modify_tcp[] = {\n  *   Whether the pool is for Aging counter.\n  *\n  * @return\n- *   The new container pointer on success, otherwise NULL and rte_errno is set.\n+ *   0 on success, otherwise negative errno value and rte_errno is set.\n  */\n-static struct mlx5_pools_container *\n+static int\n flow_dv_container_resize(struct rte_eth_dev *dev,\n \t\t\t\tuint32_t batch, uint32_t age)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_pools_container *cont =\n-\t\t\tMLX5_CNT_CONTAINER(priv->sh, batch, 0, age);\n-\tstruct mlx5_pools_container *new_cont =\n-\t\t\tMLX5_CNT_CONTAINER_UNUSED(priv->sh, batch, 0, age);\n+\tstruct mlx5_pools_container *cont = MLX5_CNT_CONTAINER(priv->sh, batch,\n+\t\t\t\t\t\t\t       age);\n \tstruct mlx5_counter_stats_mem_mng *mem_mng = NULL;\n+\tvoid *old_pools = cont->pools;\n \tuint32_t resize = cont->n + MLX5_CNT_CONTAINER_RESIZE;\n \tuint32_t mem_size = sizeof(struct mlx5_flow_counter_pool *) * resize;\n-\tint i;\n+\tvoid *pools = rte_calloc(__func__, 1, mem_size, 0);\n \n-\t/* Fallback mode has no background thread. Skip the check. */\n-\tif (!priv->counter_fallback &&\n-\t    cont != MLX5_CNT_CONTAINER(priv->sh, batch, 1, age)) {\n-\t\t/* The last resize still hasn't detected by the host thread. */\n-\t\trte_errno = EAGAIN;\n-\t\treturn NULL;\n-\t}\n-\tnew_cont->pools = rte_calloc(__func__, 1, mem_size, 0);\n-\tif (!new_cont->pools) {\n+\tif (!pools) {\n \t\trte_errno = ENOMEM;\n-\t\treturn NULL;\n+\t\treturn -ENOMEM;\n \t}\n-\tif (cont->n)\n-\t\tmemcpy(new_cont->pools, cont->pools, cont->n *\n-\t\t       sizeof(struct mlx5_flow_counter_pool *));\n+\tif (old_pools)\n+\t\tmemcpy(pools, old_pools, cont->n *\n+\t\t\t\t       sizeof(struct mlx5_flow_counter_pool *));\n \t/*\n \t * Fallback mode query the counter directly, no background query\n \t * resources are needed.\n \t */\n \tif (!priv->counter_fallback) {\n+\t\tint i;\n+\n \t\tmem_mng = flow_dv_create_counter_stat_mem_mng(dev,\n-\t\t\tMLX5_CNT_CONTAINER_RESIZE + MLX5_MAX_PENDING_QUERIES);\n+\t\t\t  MLX5_CNT_CONTAINER_RESIZE + MLX5_MAX_PENDING_QUERIES);\n \t\tif (!mem_mng) {\n-\t\t\trte_free(new_cont->pools);\n-\t\t\treturn NULL;\n+\t\t\trte_free(pools);\n+\t\t\treturn -ENOMEM;\n \t\t}\n \t\tfor (i = 0; i < MLX5_MAX_PENDING_QUERIES; ++i)\n \t\t\tLIST_INSERT_HEAD(&priv->sh->cmng.free_stat_raws,\n \t\t\t\t\t mem_mng->raws +\n \t\t\t\t\t MLX5_CNT_CONTAINER_RESIZE +\n \t\t\t\t\t i, next);\n-\t} else {\n-\t\t/*\n-\t\t * Release the old container pools directly as no background\n-\t\t * thread helps that.\n-\t\t */\n-\t\trte_free(cont->pools);\n \t}\n-\tnew_cont->n = resize;\n-\trte_atomic16_set(&new_cont->n_valid, rte_atomic16_read(&cont->n_valid));\n-\tTAILQ_INIT(&new_cont->pool_list);\n-\tTAILQ_CONCAT(&new_cont->pool_list, &cont->pool_list, next);\n-\tnew_cont->init_mem_mng = mem_mng;\n-\trte_cio_wmb();\n-\t /* Flip the master container. */\n-\tpriv->sh->cmng.mhi[batch][age] ^= (uint8_t)1;\n-\treturn new_cont;\n+\trte_spinlock_lock(&cont->resize_sl);\n+\tcont->n = resize;\n+\tcont->mem_mng = mem_mng;\n+\tcont->pools = pools;\n+\trte_spinlock_unlock(&cont->resize_sl);\n+\tif (old_pools)\n+\t\trte_free(old_pools);\n+\treturn 0;\n }\n \n /**\n@@ -4296,22 +4282,19 @@ struct field_modify_info modify_tcp[] = {\n  * @return\n  *   The pool container pointer on success, NULL otherwise and rte_errno is set.\n  */\n-static struct mlx5_pools_container *\n+static struct mlx5_flow_counter_pool *\n flow_dv_pool_create(struct rte_eth_dev *dev, struct mlx5_devx_obj *dcs,\n \t\t    uint32_t batch, uint32_t age)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_flow_counter_pool *pool;\n \tstruct mlx5_pools_container *cont = MLX5_CNT_CONTAINER(priv->sh, batch,\n-\t\t\t\t\t\t\t       0, age);\n+\t\t\t\t\t\t\t       age);\n \tint16_t n_valid = rte_atomic16_read(&cont->n_valid);\n \tuint32_t size = sizeof(*pool);\n \n-\tif (cont->n == n_valid) {\n-\t\tcont = flow_dv_container_resize(dev, batch, age);\n-\t\tif (!cont)\n-\t\t\treturn NULL;\n-\t}\n+\tif (cont->n == n_valid && flow_dv_container_resize(dev, batch, age))\n+\t\treturn NULL;\n \tsize += MLX5_COUNTERS_PER_POOL * CNT_SIZE;\n \tsize += (batch ? 0 : MLX5_COUNTERS_PER_POOL * CNTEXT_SIZE);\n \tsize += (!age ? 0 : MLX5_COUNTERS_PER_POOL * AGE_SIZE);\n@@ -4322,8 +4305,8 @@ struct field_modify_info modify_tcp[] = {\n \t}\n \tpool->min_dcs = dcs;\n \tif (!priv->counter_fallback)\n-\t\tpool->raw = cont->init_mem_mng->raws + n_valid %\n-\t\t\t\t\t\t     MLX5_CNT_CONTAINER_RESIZE;\n+\t\tpool->raw = cont->mem_mng->raws + n_valid %\n+\t\t\t\t\t\t      MLX5_CNT_CONTAINER_RESIZE;\n \tpool->raw_hw = NULL;\n \tpool->type = 0;\n \tpool->type |= (batch ? 0 :  CNT_POOL_TYPE_EXT);\n@@ -4351,7 +4334,7 @@ struct field_modify_info modify_tcp[] = {\n \t/* Pool initialization must be updated before host thread access. */\n \trte_cio_wmb();\n \trte_atomic16_add(&cont->n_valid, 1);\n-\treturn cont;\n+\treturn pool;\n }\n \n /**\n@@ -4375,7 +4358,7 @@ struct field_modify_info modify_tcp[] = {\n \tstruct mlx5_flow_counter_pool *other;\n \tstruct mlx5_pools_container *cont;\n \n-\tcont = MLX5_CNT_CONTAINER(priv->sh, batch, 0, (age ^ 0x1));\n+\tcont = MLX5_CNT_CONTAINER(priv->sh, batch, (age ^ 0x1));\n \tother = flow_dv_find_pool_by_id(cont, pool->min_dcs->id);\n \tif (!other)\n \t\treturn;\n@@ -4400,10 +4383,10 @@ struct field_modify_info modify_tcp[] = {\n  *   Whether the pool is for counter that was allocated for aging.\n  *\n  * @return\n- *   The counter container pointer and @p cnt_free is set on success,\n+ *   The counter pool pointer and @p cnt_free is set on success,\n  *   NULL otherwise and rte_errno is set.\n  */\n-static struct mlx5_pools_container *\n+static struct mlx5_flow_counter_pool *\n flow_dv_counter_pool_prepare(struct rte_eth_dev *dev,\n \t\t\t     struct mlx5_flow_counter **cnt_free,\n \t\t\t     uint32_t batch, uint32_t age)\n@@ -4415,7 +4398,7 @@ struct field_modify_info modify_tcp[] = {\n \tstruct mlx5_flow_counter *cnt;\n \tuint32_t i;\n \n-\tcont = MLX5_CNT_CONTAINER(priv->sh, batch, 0, age);\n+\tcont = MLX5_CNT_CONTAINER(priv->sh, batch, age);\n \tif (!batch) {\n \t\t/* bulk_bitmap must be 0 for single counter allocation. */\n \t\tdcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->ctx, 0);\n@@ -4423,12 +4406,11 @@ struct field_modify_info modify_tcp[] = {\n \t\t\treturn NULL;\n \t\tpool = flow_dv_find_pool_by_id(cont, dcs->id);\n \t\tif (!pool) {\n-\t\t\tcont = flow_dv_pool_create(dev, dcs, batch, age);\n-\t\t\tif (!cont) {\n+\t\t\tpool = flow_dv_pool_create(dev, dcs, batch, age);\n+\t\t\tif (!pool) {\n \t\t\t\tmlx5_devx_cmd_destroy(dcs);\n \t\t\t\treturn NULL;\n \t\t\t}\n-\t\t\tpool = TAILQ_FIRST(&cont->pool_list);\n \t\t} else if (dcs->id < pool->min_dcs->id) {\n \t\t\trte_atomic64_set(&pool->a64_dcs,\n \t\t\t\t\t (int64_t)(uintptr_t)dcs);\n@@ -4440,7 +4422,7 @@ struct field_modify_info modify_tcp[] = {\n \t\tTAILQ_INSERT_HEAD(&pool->counters, cnt, next);\n \t\tMLX5_GET_POOL_CNT_EXT(pool, i)->dcs = dcs;\n \t\t*cnt_free = cnt;\n-\t\treturn cont;\n+\t\treturn pool;\n \t}\n \t/* bulk_bitmap is in 128 counters units. */\n \tif (priv->config.hca_attr.flow_counter_bulk_alloc_bitmap & 0x4)\n@@ -4449,18 +4431,17 @@ struct field_modify_info modify_tcp[] = {\n \t\trte_errno = ENODATA;\n \t\treturn NULL;\n \t}\n-\tcont = flow_dv_pool_create(dev, dcs, batch, age);\n-\tif (!cont) {\n+\tpool = flow_dv_pool_create(dev, dcs, batch, age);\n+\tif (!pool) {\n \t\tmlx5_devx_cmd_destroy(dcs);\n \t\treturn NULL;\n \t}\n-\tpool = TAILQ_FIRST(&cont->pool_list);\n \tfor (i = 0; i < MLX5_COUNTERS_PER_POOL; ++i) {\n \t\tcnt = MLX5_POOL_GET_CNT(pool, i);\n \t\tTAILQ_INSERT_HEAD(&pool->counters, cnt, next);\n \t}\n \t*cnt_free = MLX5_POOL_GET_CNT(pool, 0);\n-\treturn cont;\n+\treturn pool;\n }\n \n /**\n@@ -4534,7 +4515,7 @@ struct field_modify_info modify_tcp[] = {\n \t */\n \tuint32_t batch = (group && !shared && !priv->counter_fallback) ? 1 : 0;\n \tstruct mlx5_pools_container *cont = MLX5_CNT_CONTAINER(priv->sh, batch,\n-\t\t\t\t\t\t\t       0, age);\n+\t\t\t\t\t\t\t       age);\n \tuint32_t cnt_idx;\n \n \tif (!priv->config.devx) {\n@@ -4573,10 +4554,9 @@ struct field_modify_info modify_tcp[] = {\n \t\tcnt_free = NULL;\n \t}\n \tif (!cnt_free) {\n-\t\tcont = flow_dv_counter_pool_prepare(dev, &cnt_free, batch, age);\n-\t\tif (!cont)\n+\t\tpool = flow_dv_counter_pool_prepare(dev, &cnt_free, batch, age);\n+\t\tif (!pool)\n \t\t\treturn 0;\n-\t\tpool = TAILQ_FIRST(&cont->pool_list);\n \t}\n \tif (!batch)\n \t\tcnt_ext = MLX5_CNT_TO_CNT_EXT(pool, cnt_free);\ndiff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c\nindex c403f72..01eec31 100644\n--- a/drivers/net/mlx5/mlx5_flow_verbs.c\n+++ b/drivers/net/mlx5/mlx5_flow_verbs.c\n@@ -56,8 +56,7 @@\n \t\t\t      struct mlx5_flow_counter_pool **ppool)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_pools_container *cont = MLX5_CNT_CONTAINER(priv->sh, 0, 0,\n-\t\t\t\t\t\t\t\t\t0);\n+\tstruct mlx5_pools_container *cont = MLX5_CNT_CONTAINER(priv->sh, 0, 0);\n \tstruct mlx5_flow_counter_pool *pool;\n \n \tidx--;\n@@ -152,8 +151,7 @@\n flow_verbs_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_pools_container *cont = MLX5_CNT_CONTAINER(priv->sh, 0, 0,\n-\t\t\t\t\t\t\t\t\t0);\n+\tstruct mlx5_pools_container *cont = MLX5_CNT_CONTAINER(priv->sh, 0, 0);\n \tstruct mlx5_flow_counter_pool *pool = NULL;\n \tstruct mlx5_flow_counter_ext *cnt_ext = NULL;\n \tstruct mlx5_flow_counter *cnt = NULL;\n",
    "prefixes": []
}