net/mlx5e: TC, Separate get/update/replace meter functions
authorRoi Dayan <roid@nvidia.com>
Sun, 24 Jul 2022 11:14:55 +0000 (14:14 +0300)
committerSaeed Mahameed <saeedm@nvidia.com>
Thu, 28 Jul 2022 20:55:26 +0000 (13:55 -0700)
mlx5e_tc_meter_get() to get an existing meter.
mlx5e_tc_meter_update() to update an existing meter without refcount.
mlx5e_tc_meter_replace() to get/create a meter and update if needed.

Signed-off-by: Roi Dayan <roid@nvidia.com>
Reviewed-by: Jianbo Liu <jianbol@nvidia.com>
Reviewed-by: Oz Shlomo <ozsh@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
drivers/net/ethernet/mellanox/mlx5/core/en/tc/meter.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc/meter.h
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c

index 6409e4f..17529cc 100644 (file)
@@ -344,69 +344,149 @@ __mlx5e_flow_meter_free(struct mlx5e_flow_meter_handle *meter)
        kfree(meter);
 }
 
+static struct mlx5e_flow_meter_handle *
+__mlx5e_tc_meter_get(struct mlx5e_flow_meters *flow_meters, u32 index)
+{
+       struct mlx5e_flow_meter_handle *meter;
+
+       hash_for_each_possible(flow_meters->hashtbl, meter, hlist, index)
+               if (meter->params.index == index)
+                       goto add_ref;
+
+       return ERR_PTR(-ENOENT);
+
+add_ref:
+       meter->refcnt++;
+
+       return meter;
+}
+
 struct mlx5e_flow_meter_handle *
 mlx5e_tc_meter_get(struct mlx5_core_dev *mdev, struct mlx5e_flow_meter_params *params)
 {
        struct mlx5e_flow_meters *flow_meters;
        struct mlx5e_flow_meter_handle *meter;
-       int err;
 
        flow_meters = mlx5e_get_flow_meters(mdev);
        if (!flow_meters)
                return ERR_PTR(-EOPNOTSUPP);
 
        mutex_lock(&flow_meters->sync_lock);
-       hash_for_each_possible(flow_meters->hashtbl, meter, hlist, params->index)
-               if (meter->params.index == params->index)
-                       goto add_ref;
+       meter = __mlx5e_tc_meter_get(flow_meters, params->index);
+       mutex_unlock(&flow_meters->sync_lock);
 
-       meter = __mlx5e_flow_meter_alloc(flow_meters);
-       if (IS_ERR(meter)) {
-               err = PTR_ERR(meter);
-               goto err_alloc;
+       return meter;
+}
+
+static void
+__mlx5e_tc_meter_put(struct mlx5e_flow_meter_handle *meter)
+{
+       if (--meter->refcnt == 0) {
+               hash_del(&meter->hlist);
+               __mlx5e_flow_meter_free(meter);
        }
+}
+
+void
+mlx5e_tc_meter_put(struct mlx5e_flow_meter_handle *meter)
+{
+       struct mlx5e_flow_meters *flow_meters = meter->flow_meters;
+
+       mutex_lock(&flow_meters->sync_lock);
+       __mlx5e_tc_meter_put(meter);
+       mutex_unlock(&flow_meters->sync_lock);
+}
+
+static struct mlx5e_flow_meter_handle *
+mlx5e_tc_meter_alloc(struct mlx5e_flow_meters *flow_meters,
+                    struct mlx5e_flow_meter_params *params)
+{
+       struct mlx5e_flow_meter_handle *meter;
+
+       meter = __mlx5e_flow_meter_alloc(flow_meters);
+       if (IS_ERR(meter))
+               return meter;
 
        hash_add(flow_meters->hashtbl, &meter->hlist, params->index);
        meter->params.index = params->index;
-
-add_ref:
        meter->refcnt++;
 
+       return meter;
+}
+
+static int
+__mlx5e_tc_meter_update(struct mlx5e_flow_meter_handle *meter,
+                       struct mlx5e_flow_meter_params *params)
+{
+       struct mlx5_core_dev *mdev = meter->flow_meters->mdev;
+       int err = 0;
+
        if (meter->params.mode != params->mode || meter->params.rate != params->rate ||
            meter->params.burst != params->burst) {
                err = mlx5e_tc_meter_modify(mdev, meter, params);
                if (err)
-                       goto err_update;
+                       goto out;
 
                meter->params.mode = params->mode;
                meter->params.rate = params->rate;
                meter->params.burst = params->burst;
        }
 
-       mutex_unlock(&flow_meters->sync_lock);
-       return meter;
+out:
+       return err;
+}
 
-err_update:
-       if (--meter->refcnt == 0) {
-               hash_del(&meter->hlist);
-               __mlx5e_flow_meter_free(meter);
-       }
-err_alloc:
+int
+mlx5e_tc_meter_update(struct mlx5e_flow_meter_handle *meter,
+                     struct mlx5e_flow_meter_params *params)
+{
+       struct mlx5_core_dev *mdev = meter->flow_meters->mdev;
+       struct mlx5e_flow_meters *flow_meters;
+       int err;
+
+       flow_meters = mlx5e_get_flow_meters(mdev);
+       if (!flow_meters)
+               return -EOPNOTSUPP;
+
+       mutex_lock(&flow_meters->sync_lock);
+       err = __mlx5e_tc_meter_update(meter, params);
        mutex_unlock(&flow_meters->sync_lock);
-       return ERR_PTR(err);
+       return err;
 }
 
-void
-mlx5e_tc_meter_put(struct mlx5e_flow_meter_handle *meter)
+struct mlx5e_flow_meter_handle *
+mlx5e_tc_meter_replace(struct mlx5_core_dev *mdev, struct mlx5e_flow_meter_params *params)
 {
-       struct mlx5e_flow_meters *flow_meters = meter->flow_meters;
+       struct mlx5e_flow_meters *flow_meters;
+       struct mlx5e_flow_meter_handle *meter;
+       int err;
+
+       flow_meters = mlx5e_get_flow_meters(mdev);
+       if (!flow_meters)
+               return ERR_PTR(-EOPNOTSUPP);
 
        mutex_lock(&flow_meters->sync_lock);
-       if (--meter->refcnt == 0) {
-               hash_del(&meter->hlist);
-               __mlx5e_flow_meter_free(meter);
+       meter = __mlx5e_tc_meter_get(flow_meters, params->index);
+       if (IS_ERR(meter)) {
+               meter = mlx5e_tc_meter_alloc(flow_meters, params);
+               if (IS_ERR(meter)) {
+                       err = PTR_ERR(meter);
+                       goto err_get;
+               }
        }
+
+       err = __mlx5e_tc_meter_update(meter, params);
+       if (err)
+               goto err_update;
+
        mutex_unlock(&flow_meters->sync_lock);
+       return meter;
+
+err_update:
+       __mlx5e_tc_meter_put(meter);
+err_get:
+       mutex_unlock(&flow_meters->sync_lock);
+       return ERR_PTR(err);
 }
 
 enum mlx5_flow_namespace_type
index a73ebf9..71ffa86 100644 (file)
@@ -51,6 +51,11 @@ struct mlx5e_flow_meter_handle *
 mlx5e_tc_meter_get(struct mlx5_core_dev *mdev, struct mlx5e_flow_meter_params *params);
 void
 mlx5e_tc_meter_put(struct mlx5e_flow_meter_handle *meter);
+int
+mlx5e_tc_meter_update(struct mlx5e_flow_meter_handle *meter,
+                     struct mlx5e_flow_meter_params *params);
+struct mlx5e_flow_meter_handle *
+mlx5e_tc_meter_replace(struct mlx5_core_dev *mdev, struct mlx5e_flow_meter_params *params);
 
 enum mlx5_flow_namespace_type
 mlx5e_tc_meter_get_namespace(struct mlx5e_flow_meters *flow_meters);
index a38e150..c3ec23f 100644 (file)
@@ -361,7 +361,7 @@ mlx5e_tc_add_flow_meter(struct mlx5e_priv *priv,
        enum mlx5_flow_namespace_type ns_type;
        struct mlx5e_flow_meter_handle *meter;
 
-       meter = mlx5e_tc_meter_get(priv->mdev, &attr->meter_attr.params);
+       meter = mlx5e_tc_meter_replace(priv->mdev, &attr->meter_attr.params);
        if (IS_ERR(meter)) {
                mlx5_core_err(priv->mdev, "Failed to get flow meter\n");
                return PTR_ERR(meter);