Commit f14c1a14 authored by Maher Sanalla's avatar Maher Sanalla Committed by Saeed Mahameed
Browse files

net/mlx5: Allocate completion EQs dynamically



This commit enables the dynamic allocation of EQs at runtime, allowing
for more flexibility in managing completion EQs and reducing the memory
overhead of driver load. Whenever a CQ is created for a given vector
index, the driver will lookup to see if there is an already mapped
completion EQ for that vector, if so, utilize it. Otherwise, allocate a
new EQ on demand and then utilize it for the CQ completion events.

Add a protection lock to the EQ table to protect from concurrent EQ
creation attempts.

While at it, replace mlx5_vector2irqn()/mlx5_vector2eqn() with
mlx5_comp_eqn_get() and mlx5_comp_irqn_get() which will allocate an
EQ on demand if no EQ is found for the given vector.

Signed-off-by: default avatarMaher Sanalla <msanalla@nvidia.com>
Reviewed-by: default avatarShay Drory <shayd@nvidia.com>
Reviewed-by: default avatarMoshe Shemesh <moshe@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
parent 54c52978
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -993,7 +993,7 @@ int mlx5_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
		INIT_WORK(&cq->notify_work, notify_soft_wc_handler);
	}

	err = mlx5_vector2eqn(dev->mdev, vector, &eqn);
	err = mlx5_comp_eqn_get(dev->mdev, vector, &eqn);
	if (err)
		goto err_cqb;

+1 −1
Original line number Diff line number Diff line
@@ -1002,7 +1002,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)(
		return PTR_ERR(c);
	dev = to_mdev(c->ibucontext.device);

	err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn);
	err = mlx5_comp_eqn_get(dev->mdev, user_vector, &dev_eqn);
	if (err < 0)
		return err;

+2 −2
Original line number Diff line number Diff line
@@ -1989,7 +1989,7 @@ static int mlx5e_create_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
	int eqn;
	int err;

	err = mlx5_vector2eqn(mdev, param->eq_ix, &eqn);
	err = mlx5_comp_eqn_get(mdev, param->eq_ix, &eqn);
	if (err)
		return err;

@@ -2452,7 +2452,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
	unsigned int irq;
	int err;

	err = mlx5_vector2irqn(priv->mdev, ix, &irq);
	err = mlx5_comp_irqn_get(priv->mdev, ix, &irq);
	if (err)
		return err;

+43 −37
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ struct mlx5_eq_table {
	struct mlx5_nb          cq_err_nb;

	struct mutex            lock; /* sync async eqs creations */
	struct mutex            comp_lock; /* sync comp eqs creations */
	int			curr_comp_eqs;
	int			max_comp_eqs;
	struct mlx5_irq_table	*irq_table;
@@ -457,6 +458,7 @@ int mlx5_eq_table_init(struct mlx5_core_dev *dev)
	cpumask_clear(&eq_table->used_cpus);
	xa_init(&eq_table->comp_eqs);
	xa_init(&eq_table->comp_irqs);
	mutex_init(&eq_table->comp_lock);
	eq_table->curr_comp_eqs = 0;
	return 0;
}
@@ -985,6 +987,7 @@ static u16 comp_eq_depth_devlink_param_get(struct mlx5_core_dev *dev)
	return MLX5_COMP_EQ_SIZE;
}

/* Must be called with EQ table comp_lock held */
static int create_comp_eq(struct mlx5_core_dev *dev, u16 vecidx)
{
	struct mlx5_eq_table *table = dev->priv.eq_table;
@@ -994,6 +997,13 @@ static int create_comp_eq(struct mlx5_core_dev *dev, u16 vecidx)
	int nent;
	int err;

	lockdep_assert_held(&table->comp_lock);
	if (table->curr_comp_eqs == table->max_comp_eqs) {
		mlx5_core_err(dev, "maximum number of vectors is allocated, %d\n",
			      table->max_comp_eqs);
		return -ENOMEM;
	}

	err = comp_irq_request(dev, vecidx);
	if (err)
		return err;
@@ -1033,7 +1043,7 @@ static int create_comp_eq(struct mlx5_core_dev *dev, u16 vecidx)
		goto disable_eq;

	table->curr_comp_eqs++;
	return 0;
	return eq->core.eqn;

disable_eq:
	mlx5_eq_disable(dev, &eq->core, &eq->irq_nb);
@@ -1044,32 +1054,47 @@ static int create_comp_eq(struct mlx5_core_dev *dev, u16 vecidx)
	return err;
}

static int vector2eqnirqn(struct mlx5_core_dev *dev, int vector, int *eqn,
			  unsigned int *irqn)
int mlx5_comp_eqn_get(struct mlx5_core_dev *dev, u16 vecidx, int *eqn)
{
	struct mlx5_eq_table *table = dev->priv.eq_table;
	struct mlx5_eq_comp *eq;
	int ret = 0;

	eq = xa_load(&table->comp_eqs, vector);
	if (!eq)
		return -ENOENT;

	if (irqn)
		*irqn = eq->core.irqn;
	if (eqn)
	mutex_lock(&table->comp_lock);
	eq = xa_load(&table->comp_eqs, vecidx);
	if (eq) {
		*eqn = eq->core.eqn;
	return 0;
		goto out;
	}

int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn)
{
	return vector2eqnirqn(dev, vector, eqn, NULL);
	ret = create_comp_eq(dev, vecidx);
	if (ret < 0) {
		mutex_unlock(&table->comp_lock);
		return ret;
	}
EXPORT_SYMBOL(mlx5_vector2eqn);

int mlx5_vector2irqn(struct mlx5_core_dev *dev, int vector, unsigned int *irqn)
	*eqn = ret;
out:
	mutex_unlock(&table->comp_lock);
	return 0;
}
EXPORT_SYMBOL(mlx5_comp_eqn_get);

int mlx5_comp_irqn_get(struct mlx5_core_dev *dev, int vector, unsigned int *irqn)
{
	return vector2eqnirqn(dev, vector, NULL, irqn);
	struct mlx5_eq_table *table = dev->priv.eq_table;
	struct mlx5_eq_comp *eq;
	int eqn;
	int err;

	/* Allocate the EQ if not allocated yet */
	err = mlx5_comp_eqn_get(dev, vector, &eqn);
	if (err)
		return err;

	eq = xa_load(&table->comp_eqs, vector);
	*irqn = eq->core.irqn;
	return 0;
}

unsigned int mlx5_comp_vectors_max(struct mlx5_core_dev *dev)
@@ -1119,10 +1144,9 @@ struct mlx5_eq_comp *mlx5_eqn2comp_eq(struct mlx5_core_dev *dev, int eqn)
	struct mlx5_eq_comp *eq;
	unsigned long index;

	xa_for_each(&table->comp_eqs, index, eq) {
	xa_for_each(&table->comp_eqs, index, eq)
		if (eq->core.eqn == eqn)
			return eq;
	}

	return ERR_PTR(-ENOENT);
}
@@ -1130,11 +1154,7 @@ struct mlx5_eq_comp *mlx5_eqn2comp_eq(struct mlx5_core_dev *dev, int eqn)
/* This function should only be called after mlx5_cmd_force_teardown_hca */
void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev)
{
	struct mlx5_eq_table *table = dev->priv.eq_table;

	mutex_lock(&table->lock); /* sync with create/destroy_async_eq */
	mlx5_irq_table_free_irqs(dev);
	mutex_unlock(&table->lock);
}

#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
@@ -1176,7 +1196,6 @@ int mlx5_eq_table_create(struct mlx5_core_dev *dev)
{
	struct mlx5_eq_table *eq_table = dev->priv.eq_table;
	int err;
	int i;

	eq_table->max_comp_eqs = get_num_eqs(dev);
	err = create_async_eqs(dev);
@@ -1191,21 +1210,8 @@ int mlx5_eq_table_create(struct mlx5_core_dev *dev)
		goto err_rmap;
	}

	for (i = 0; i < eq_table->max_comp_eqs; i++) {
		err = create_comp_eq(dev, i);
		if (err < 0)
			break;
	}

	if (!i) {
		mlx5_core_err(dev, "Failed to create completion EQs\n");
		goto err_comp_eqs;
	}

	return 0;

err_comp_eqs:
	free_rmap(dev);
err_rmap:
	destroy_async_eqs(dev);
err_async_eqs:
+1 −1
Original line number Diff line number Diff line
@@ -445,7 +445,7 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size)
		goto err_cqwq;
	}

	err = mlx5_vector2eqn(mdev, smp_processor_id(), &eqn);
	err = mlx5_comp_eqn_get(mdev, smp_processor_id(), &eqn);
	if (err) {
		kvfree(in);
		goto err_cqwq;
Loading