Support shared indirect QUOTA action.

flow configure 1 queues_number 4 queues_size 64 quotas_number 32
flow configure 0 queues_number 4 queues_size 64 quotas_number 0 \
     host_port 1 flags 2

flow indirect_action 1 create ingress action_id 8 \
      action quota_create limit 18000 mode l3 / end

flow actions_template 0 create ingress actions_template_id 1 \
     template shared_indirect / jump / end \
     mask quota_create / jump group 0 / end

flow queue 0 create 0 template_table 1 \
     pattern_template 0 actions_template 0 postpone no \
     pattern eth / end \
     actions shared_indirect 1 8 / jump group 2 / end

Signed-off-by: Gregory Etelson <getel...@nvidia.com>
---
 drivers/net/mlx5/mlx5.h            |  1 -
 drivers/net/mlx5/mlx5_flow_hw.c    |  2 +-
 drivers/net/mlx5/mlx5_flow_quota.c | 92 ++++++++++++++++++++----------
 3 files changed, 63 insertions(+), 32 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 2a82348135..9b7771abfb 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -1716,7 +1716,6 @@ struct mlx5_quota {
 
 /* Bulk management structure for flow quota. */
 struct mlx5_quota_ctx {
-       uint32_t nb_quotas; /* Total number of quota objects */
        struct mlx5dr_action *dr_action; /* HWS action */
        struct mlx5_devx_obj *devx_obj; /* DEVX ranged object. */
        struct mlx5_pmd_mr mr; /* MR for READ from MTR ASO */
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index b5137a822a..42e865cf42 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -7787,7 +7787,7 @@ flow_hw_configure(struct rte_eth_dev *dev,
                goto err;
        }
        /* Initialize quotas */
-       if (port_attr->nb_quotas) {
+       if (port_attr->nb_quotas || (host_priv && 
host_priv->quota_ctx.devx_obj)) {
                ret = mlx5_flow_quota_init(dev, port_attr->nb_quotas);
                if (ret)
                        goto err;
diff --git a/drivers/net/mlx5/mlx5_flow_quota.c 
b/drivers/net/mlx5/mlx5_flow_quota.c
index 19e1835c97..14a2a8b9b4 100644
--- a/drivers/net/mlx5/mlx5_flow_quota.c
+++ b/drivers/net/mlx5/mlx5_flow_quota.c
@@ -632,19 +632,22 @@ mlx5_flow_quota_destroy(struct rte_eth_dev *dev)
        struct mlx5_quota_ctx *qctx = &priv->quota_ctx;
        int ret;
 
-       if (qctx->quota_ipool)
-               mlx5_ipool_destroy(qctx->quota_ipool);
-       mlx5_quota_destroy_sq(priv);
-       mlx5_quota_destroy_read_buf(priv);
        if (qctx->dr_action) {
                ret = mlx5dr_action_destroy(qctx->dr_action);
                if (ret)
                        DRV_LOG(ERR, "QUOTA: failed to destroy DR action");
        }
-       if (qctx->devx_obj) {
-               ret = mlx5_devx_cmd_destroy(qctx->devx_obj);
-               if (ret)
-                       DRV_LOG(ERR, "QUOTA: failed to destroy MTR ASO object");
+       if (!priv->shared_host) {
+               if (qctx->quota_ipool)
+                       mlx5_ipool_destroy(qctx->quota_ipool);
+               mlx5_quota_destroy_sq(priv);
+               mlx5_quota_destroy_read_buf(priv);
+               if (qctx->devx_obj) {
+                       ret = mlx5_devx_cmd_destroy(qctx->devx_obj);
+                       if (ret)
+                               DRV_LOG(ERR,
+                                       "QUOTA: failed to destroy MTR ASO 
object");
+               }
        }
        memset(qctx, 0, sizeof(*qctx));
        return 0;
@@ -652,14 +655,27 @@ mlx5_flow_quota_destroy(struct rte_eth_dev *dev)
 
 #define MLX5_QUOTA_IPOOL_TRUNK_SIZE (1u << 12)
 #define MLX5_QUOTA_IPOOL_CACHE_SIZE (1u << 13)
-int
-mlx5_flow_quota_init(struct rte_eth_dev *dev, uint32_t nb_quotas)
+
+static int
+mlx5_quota_init_guest(struct mlx5_priv *priv)
+{
+       struct mlx5_quota_ctx *qctx = &priv->quota_ctx;
+       struct rte_eth_dev *host_dev = priv->shared_host;
+       struct mlx5_priv *host_priv = host_dev->data->dev_private;
+
+       /**
+        * Shared quota object can be used in flow rules only.
+        * DR5 flow action needs access to ASO abjects.
+        */
+       qctx->devx_obj = host_priv->quota_ctx.devx_obj;
+       return 0;
+}
+
+static int
+mlx5_quota_init_host(struct mlx5_priv *priv, uint32_t nb_quotas)
 {
-       struct mlx5_priv *priv = dev->data->dev_private;
        struct mlx5_dev_ctx_shared *sh = priv->sh;
        struct mlx5_quota_ctx *qctx = &priv->quota_ctx;
-       int reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
-       uint32_t flags = MLX5DR_ACTION_FLAG_HWS_RX | MLX5DR_ACTION_FLAG_HWS_TX;
        struct mlx5_indexed_pool_config quota_ipool_cfg = {
                .size = sizeof(struct mlx5_quota),
                .trunk_size = RTE_MIN(nb_quotas, MLX5_QUOTA_IPOOL_TRUNK_SIZE),
@@ -680,32 +696,18 @@ mlx5_flow_quota_init(struct rte_eth_dev *dev, uint32_t 
nb_quotas)
                DRV_LOG(DEBUG, "QUOTA: no MTR support");
                return -ENOTSUP;
        }
-       if (reg_id < 0) {
-               DRV_LOG(DEBUG, "QUOTA: MRT register not available");
-               return -ENOTSUP;
-       }
        qctx->devx_obj = mlx5_devx_cmd_create_flow_meter_aso_obj
                (sh->cdev->ctx, sh->cdev->pdn, rte_log2_u32(nb_quotas >> 1));
        if (!qctx->devx_obj) {
                DRV_LOG(DEBUG, "QUOTA: cannot allocate MTR ASO objects");
                return -ENOMEM;
        }
-       if (sh->config.dv_esw_en && priv->master)
-               flags |= MLX5DR_ACTION_FLAG_HWS_FDB;
-       qctx->dr_action = mlx5dr_action_create_aso_meter
-               (priv->dr_ctx, (struct mlx5dr_devx_obj *)qctx->devx_obj,
-                reg_id - REG_C_0, flags);
-       if (!qctx->dr_action) {
-               DRV_LOG(DEBUG, "QUOTA: failed to create DR action");
-               ret = -ENOMEM;
-               goto err;
-       }
        ret = mlx5_quota_alloc_read_buf(priv);
        if (ret)
-               goto err;
+               return ret;
        ret = mlx5_quota_alloc_sq(priv);
        if (ret)
-               goto err;
+               return ret;
        if (nb_quotas < MLX5_QUOTA_IPOOL_TRUNK_SIZE)
                quota_ipool_cfg.per_core_cache = 0;
        else if (nb_quotas < MLX5_HW_IPOOL_SIZE_THRESHOLD)
@@ -715,10 +717,40 @@ mlx5_flow_quota_init(struct rte_eth_dev *dev, uint32_t 
nb_quotas)
        qctx->quota_ipool = mlx5_ipool_create(&quota_ipool_cfg);
        if (!qctx->quota_ipool) {
                DRV_LOG(DEBUG, "QUOTA: failed to allocate quota pool");
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+int
+mlx5_flow_quota_init(struct rte_eth_dev *dev, uint32_t nb_quotas)
+{
+       struct mlx5_priv *priv = dev->data->dev_private;
+       struct mlx5_quota_ctx *qctx = &priv->quota_ctx;
+       uint32_t flags = MLX5DR_ACTION_FLAG_HWS_RX | MLX5DR_ACTION_FLAG_HWS_TX;
+       int reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
+       int ret;
+
+       if (reg_id < 0) {
+               DRV_LOG(DEBUG, "QUOTA: MRT register not available");
+               return -ENOTSUP;
+       }
+       if (!priv->shared_host)
+               ret = mlx5_quota_init_host(priv, nb_quotas);
+       else
+               ret = mlx5_quota_init_guest(priv);
+       if (ret)
+               goto err;
+       if (priv->sh->config.dv_esw_en && priv->master)
+               flags |= MLX5DR_ACTION_FLAG_HWS_FDB;
+       qctx->dr_action = mlx5dr_action_create_aso_meter
+               (priv->dr_ctx, (struct mlx5dr_devx_obj *)qctx->devx_obj,
+                reg_id - REG_C_0, flags);
+       if (!qctx->dr_action) {
+               DRV_LOG(DEBUG, "QUOTA: failed to create DR action");
                ret = -ENOMEM;
                goto err;
        }
-       qctx->nb_quotas = nb_quotas;
        return 0;
 err:
        mlx5_flow_quota_destroy(dev);
-- 
2.34.1

Reply via email to