Non-template HWS pre-allocates half of the device counter capacity
from hugepage memory. When that allocation fails, the PMD replaced
the specific error with "counters pool not initialized".

Log the failing allocation and return the original error. Document
that this pre-allocation can exhaust hugepages, and that the
application can reserve more hugepages or configure fewer counters.

Fixes: 4d368e1da3a4 ("net/mlx5: support flow counter action for HWS")
Cc: [email protected]

Signed-off-by: Maayan Kashani <[email protected]>
Acked-by: Dariusz Sosnowski <[email protected]>
---
 doc/guides/nics/mlx5.rst        | 10 ++++++++++
 drivers/net/mlx5/mlx5_flow_hw.c | 11 ++++-------
 drivers/net/mlx5/mlx5_hws_cnt.c | 20 ++++++++++++++++++--
 3 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 45d1a25ec18..64cd09c9944 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -2992,6 +2992,16 @@ With :ref:`HW steering <mlx5_hws>`:
    - Linux kernel >= 6.4 and rdma-core >= 60.0 for upstream drivers/libraries 
or,
    - DOCA >= 3.2.0 for drivers/libraries provided by NVIDIA.
 
+#. The non-template API pre-allocates half of the NIC counter capacity
+   from hugepage memory when the first ``COUNT`` action is created.
+   Other allocations, such as large mbuf pools, can use up the hugepage
+   heap first. Counter creation then fails.
+
+   Reserve more hugepages, or call ``rte_flow_configure()`` with a
+   smaller ``nb_counters`` before creating the first ``COUNT`` action.
+   An explicit configuration allocates only the requested number of
+   counters.
+
 
 .. _mlx5_age:
 
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 8b74f66770b..481b01a21e3 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -12768,13 +12768,10 @@ flow_hw_action_handle_validate(struct rte_eth_dev 
*dev, uint32_t queue,
                }
                break;
        case RTE_FLOW_ACTION_TYPE_COUNT:
-               if (!priv->hws_cpool) {
-                       if (flow_hw_allocate_actions(dev, 
MLX5_FLOW_ACTION_COUNT,
-                                                    error))
-                               return rte_flow_error_set
-                                       (error, EINVAL, 
RTE_FLOW_ERROR_TYPE_ACTION,
-                                        NULL, "counters pool not initialized");
-               }
+               if (!priv->hws_cpool)
+                       return flow_hw_allocate_actions(dev,
+                                                       MLX5_FLOW_ACTION_COUNT,
+                                                       error);
                break;
        case RTE_FLOW_ACTION_TYPE_CONNTRACK:
                if (priv->hws_ctpool == NULL) {
diff --git a/drivers/net/mlx5/mlx5_hws_cnt.c b/drivers/net/mlx5/mlx5_hws_cnt.c
index d6f713fd9bd..c2aa75c865e 100644
--- a/drivers/net/mlx5/mlx5_hws_cnt.c
+++ b/drivers/net/mlx5/mlx5_hws_cnt.c
@@ -31,8 +31,11 @@ __hws_cnt_id_load(struct mlx5_hws_cnt_pool *cpool)
 
        cnt_arr = mlx5_malloc(MLX5_MEM_ANY | MLX5_MEM_ZERO,
                              cnt_num * sizeof(cnt_id_t), 0, SOCKET_ID_ANY);
-       if (cnt_arr == NULL)
+       if (cnt_arr == NULL) {
+               DRV_LOG(ERR, "Failed to allocate counter ID array: %zu bytes.",
+                       cnt_num * sizeof(cnt_id_t));
                return -ENOMEM;
+       }
        /*
         * Counter ID order is important for tracking the max number of in used
         * counter for querying, which means counter internal index order must
@@ -290,6 +293,8 @@ mlx5_hws_cnt_raw_data_alloc(struct mlx5_dev_ctx_shared *sh, 
uint32_t n,
        mng->raw = mlx5_malloc(MLX5_MEM_ANY | MLX5_MEM_ZERO, sz, pgsz,
                        SOCKET_ID_ANY);
        if (mng->raw == NULL) {
+               DRV_LOG(ERR, "Failed to allocate raw counter memory: %zu 
bytes.",
+                       sz);
                rte_flow_error_set(error, ENOMEM,
                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
                                   NULL, "failed to allocate raw counters 
memory");
@@ -469,6 +474,9 @@ mlx5_hws_cnt_pool_init(struct mlx5_dev_ctx_shared *sh,
                                 sizeof(struct mlx5_hws_cnt) * cnt_num,
                                 0, SOCKET_ID_ANY);
        if (cntp->pool == NULL) {
+               DRV_LOG(ERR,
+                       "Failed to allocate counter pool: %zu bytes for %" 
PRIu64 " counters.",
+                       sizeof(struct mlx5_hws_cnt) * (size_t)cnt_num, cnt_num);
                rte_flow_error_set(error, ENOMEM,
                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
                                   "failed to allocate counter pool context");
@@ -773,8 +781,12 @@ mlx5_hws_cnt_pool_create(struct rte_eth_dev *dev,
                goto error;
        }
        ret = __hws_cnt_id_load(cpool);
-       if (ret != 0)
+       if (ret != 0) {
+               rte_flow_error_set(error, ENOMEM,
+                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+                                  "failed to allocate counter ID array");
                goto error;
+       }
        /*
         * Bump query gen right after pool create so the
         * pre-loaded counters can be used directly
@@ -805,6 +817,10 @@ mlx5_hws_cnt_pool_create(struct rte_eth_dev *dev,
        return 0;
 error:
        MLX5_ASSERT(ret);
+       DRV_LOG(ERR, "Port %u failed to create counter pool for %u counters: 
%s",
+               dev->data->port_id, nb_counters,
+               (error != NULL && error->message != NULL) ?
+               error->message : "unspecified error");
        mlx5_hws_cnt_pool_destroy(priv->sh, cpool);
        priv->hws_cpool = NULL;
        return ret;
-- 
2.25.1

Reply via email to