Skip to content

Commit

Permalink
net/mlx5e: TC, Separate get/update/replace meter functions
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Roi Dayan authored and Saeed Mahameed committed Jul 28, 2022
1 parent b50ce43 commit f8e9d41
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 27 deletions.
132 changes: 106 additions & 26 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc/meter.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc/meter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit f8e9d41

Please sign in to comment.