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

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
Loading
Loading
Loading
Loading
+106 −26
Original line number Diff line number Diff line
@@ -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;

err_update:
	if (--meter->refcnt == 0) {
		hash_del(&meter->hlist);
		__mlx5e_flow_meter_free(meter);
out:
	return err;
}
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
+5 −0
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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);