Commit f8e9d413 authored by Roi Dayan's avatar Roi Dayan Committed by Saeed Mahameed

net/mlx5e: TC, Separate get/update/replace meter functions

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: default avatarRoi Dayan <roid@nvidia.com>
Reviewed-by: default avatarJianbo Liu <jianbol@nvidia.com>
Reviewed-by: default avatarOz Shlomo <ozsh@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
parent b50ce435
...@@ -344,69 +344,149 @@ __mlx5e_flow_meter_free(struct mlx5e_flow_meter_handle *meter) ...@@ -344,69 +344,149 @@ __mlx5e_flow_meter_free(struct mlx5e_flow_meter_handle *meter)
kfree(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 * struct mlx5e_flow_meter_handle *
mlx5e_tc_meter_get(struct mlx5_core_dev *mdev, struct mlx5e_flow_meter_params *params) mlx5e_tc_meter_get(struct mlx5_core_dev *mdev, struct mlx5e_flow_meter_params *params)
{ {
struct mlx5e_flow_meters *flow_meters; struct mlx5e_flow_meters *flow_meters;
struct mlx5e_flow_meter_handle *meter; struct mlx5e_flow_meter_handle *meter;
int err;
flow_meters = mlx5e_get_flow_meters(mdev); flow_meters = mlx5e_get_flow_meters(mdev);
if (!flow_meters) if (!flow_meters)
return ERR_PTR(-EOPNOTSUPP); return ERR_PTR(-EOPNOTSUPP);
mutex_lock(&flow_meters->sync_lock); mutex_lock(&flow_meters->sync_lock);
hash_for_each_possible(flow_meters->hashtbl, meter, hlist, params->index) meter = __mlx5e_tc_meter_get(flow_meters, params->index);
if (meter->params.index == params->index) mutex_unlock(&flow_meters->sync_lock);
goto add_ref;
meter = __mlx5e_flow_meter_alloc(flow_meters); return meter;
if (IS_ERR(meter)) { }
err = PTR_ERR(meter);
goto err_alloc; 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); hash_add(flow_meters->hashtbl, &meter->hlist, params->index);
meter->params.index = params->index; meter->params.index = params->index;
add_ref:
meter->refcnt++; 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 || if (meter->params.mode != params->mode || meter->params.rate != params->rate ||
meter->params.burst != params->burst) { meter->params.burst != params->burst) {
err = mlx5e_tc_meter_modify(mdev, meter, params); err = mlx5e_tc_meter_modify(mdev, meter, params);
if (err) if (err)
goto err_update; goto out;
meter->params.mode = params->mode; meter->params.mode = params->mode;
meter->params.rate = params->rate; meter->params.rate = params->rate;
meter->params.burst = params->burst; meter->params.burst = params->burst;
} }
mutex_unlock(&flow_meters->sync_lock); out:
return meter; return err;
}
err_update: int
if (--meter->refcnt == 0) { mlx5e_tc_meter_update(struct mlx5e_flow_meter_handle *meter,
hash_del(&meter->hlist); struct mlx5e_flow_meter_params *params)
__mlx5e_flow_meter_free(meter); {
} struct mlx5_core_dev *mdev = meter->flow_meters->mdev;
err_alloc: 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); mutex_unlock(&flow_meters->sync_lock);
return ERR_PTR(err); return err;
} }
void struct mlx5e_flow_meter_handle *
mlx5e_tc_meter_put(struct mlx5e_flow_meter_handle *meter) 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); mutex_lock(&flow_meters->sync_lock);
if (--meter->refcnt == 0) { meter = __mlx5e_tc_meter_get(flow_meters, params->index);
hash_del(&meter->hlist); if (IS_ERR(meter)) {
__mlx5e_flow_meter_free(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); 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 enum mlx5_flow_namespace_type
......
...@@ -51,6 +51,11 @@ struct mlx5e_flow_meter_handle * ...@@ -51,6 +51,11 @@ struct mlx5e_flow_meter_handle *
mlx5e_tc_meter_get(struct mlx5_core_dev *mdev, struct mlx5e_flow_meter_params *params); mlx5e_tc_meter_get(struct mlx5_core_dev *mdev, struct mlx5e_flow_meter_params *params);
void void
mlx5e_tc_meter_put(struct mlx5e_flow_meter_handle *meter); 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 enum mlx5_flow_namespace_type
mlx5e_tc_meter_get_namespace(struct mlx5e_flow_meters *flow_meters); mlx5e_tc_meter_get_namespace(struct mlx5e_flow_meters *flow_meters);
......
...@@ -361,7 +361,7 @@ mlx5e_tc_add_flow_meter(struct mlx5e_priv *priv, ...@@ -361,7 +361,7 @@ mlx5e_tc_add_flow_meter(struct mlx5e_priv *priv,
enum mlx5_flow_namespace_type ns_type; enum mlx5_flow_namespace_type ns_type;
struct mlx5e_flow_meter_handle *meter; 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)) { if (IS_ERR(meter)) {
mlx5_core_err(priv->mdev, "Failed to get flow meter\n"); mlx5_core_err(priv->mdev, "Failed to get flow meter\n");
return PTR_ERR(meter); return PTR_ERR(meter);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment