Skip to content

Commit

Permalink
net/mlx5: Use dynamic msix vectors allocation
Browse files Browse the repository at this point in the history
Current implementation calculates the number and the partitioaning of
available interrupts vectors and then allocates all the interrupt
vectors.

Here, whenever dynamic msix allocation is supported, we change this to
use msix vectors dynamically so a vectors is actually allocated only
when needed. The current pool logic is kept in place to take care of
partitioning the vectors between the consumers and take care of
reference counting. However, the vectors are allocated only when needed.

Subsequent patches will make use of this to allocate vectors for VDPA.

Signed-off-by: Eli Cohen <elic@nvidia.com>
Reviewed-by: Shay Drory <shayd@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
  • Loading branch information
elic307i authored and Saeed Mahameed committed Mar 24, 2023
1 parent b48a0f7 commit 3354822
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 91 deletions.
114 changes: 49 additions & 65 deletions drivers/net/ethernet/mellanox/mlx5/core/eq.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "lib/clock.h"
#include "diag/fw_tracer.h"
#include "mlx5_irq.h"
#include "pci_irq.h"
#include "devlink.h"
#include "en_accel/ipsec.h"

Expand Down Expand Up @@ -61,9 +62,7 @@ struct mlx5_eq_table {
struct mlx5_irq_table *irq_table;
struct mlx5_irq **comp_irqs;
struct mlx5_irq *ctrl_irq;
#ifdef CONFIG_RFS_ACCEL
struct cpu_rmap *rmap;
#endif
};

#define MLX5_ASYNC_EVENT_MASK ((1ull << MLX5_EVENT_TYPE_PATH_MIG) | \
Expand Down Expand Up @@ -839,7 +838,7 @@ static int comp_irqs_request_pci(struct mlx5_core_dev *dev)
}
spread_done:
rcu_read_unlock();
ret = mlx5_irqs_request_vectors(dev, cpus, ncomp_eqs, table->comp_irqs);
ret = mlx5_irqs_request_vectors(dev, cpus, ncomp_eqs, table->comp_irqs, &table->rmap);
kfree(cpus);
return ret;
}
Expand Down Expand Up @@ -888,6 +887,40 @@ static int comp_irqs_request(struct mlx5_core_dev *dev)
return ret;
}

#ifdef CONFIG_RFS_ACCEL
static int alloc_rmap(struct mlx5_core_dev *mdev)
{
struct mlx5_eq_table *eq_table = mdev->priv.eq_table;

/* rmap is a mapping between irq number and queue number.
* Each irq can be assigned only to a single rmap.
* Since SFs share IRQs, rmap mapping cannot function correctly
* for irqs that are shared between different core/netdev RX rings.
* Hence we don't allow netdev rmap for SFs.
*/
if (mlx5_core_is_sf(mdev))
return 0;

eq_table->rmap = alloc_irq_cpu_rmap(eq_table->num_comp_eqs);
if (!eq_table->rmap)
return -ENOMEM;
return 0;
}

static void free_rmap(struct mlx5_core_dev *mdev)
{
struct mlx5_eq_table *eq_table = mdev->priv.eq_table;

if (eq_table->rmap) {
free_irq_cpu_rmap(eq_table->rmap);
eq_table->rmap = NULL;
}
}
#else
static int alloc_rmap(struct mlx5_core_dev *mdev) { return 0; }
static void free_rmap(struct mlx5_core_dev *mdev) {}
#endif

static void destroy_comp_eqs(struct mlx5_core_dev *dev)
{
struct mlx5_eq_table *table = dev->priv.eq_table;
Expand All @@ -903,6 +936,7 @@ static void destroy_comp_eqs(struct mlx5_core_dev *dev)
kfree(eq);
}
comp_irqs_release(dev);
free_rmap(dev);
}

static u16 comp_eq_depth_devlink_param_get(struct mlx5_core_dev *dev)
Expand All @@ -929,9 +963,16 @@ static int create_comp_eqs(struct mlx5_core_dev *dev)
int err;
int i;

err = alloc_rmap(dev);
if (err)
return err;

ncomp_eqs = comp_irqs_request(dev);
if (ncomp_eqs < 0)
return ncomp_eqs;
if (ncomp_eqs < 0) {
err = ncomp_eqs;
goto err_irqs_req;
}

INIT_LIST_HEAD(&table->comp_eqs_list);
nent = comp_eq_depth_devlink_param_get(dev);

Expand Down Expand Up @@ -976,6 +1017,8 @@ static int create_comp_eqs(struct mlx5_core_dev *dev)
kfree(eq);
clean:
destroy_comp_eqs(dev);
err_irqs_req:
free_rmap(dev);
return err;
}

Expand Down Expand Up @@ -1054,55 +1097,12 @@ struct mlx5_eq_comp *mlx5_eqn2comp_eq(struct mlx5_core_dev *dev, int eqn)
return ERR_PTR(-ENOENT);
}

static void clear_rmap(struct mlx5_core_dev *dev)
{
#ifdef CONFIG_RFS_ACCEL
struct mlx5_eq_table *eq_table = dev->priv.eq_table;

free_irq_cpu_rmap(eq_table->rmap);
#endif
}

static int set_rmap(struct mlx5_core_dev *mdev)
{
int err = 0;
#ifdef CONFIG_RFS_ACCEL
struct mlx5_eq_table *eq_table = mdev->priv.eq_table;
int vecidx;

eq_table->rmap = alloc_irq_cpu_rmap(eq_table->num_comp_eqs);
if (!eq_table->rmap) {
err = -ENOMEM;
mlx5_core_err(mdev, "Failed to allocate cpu_rmap. err %d", err);
goto err_out;
}

for (vecidx = 0; vecidx < eq_table->num_comp_eqs; vecidx++) {
err = irq_cpu_rmap_add(eq_table->rmap,
pci_irq_vector(mdev->pdev, vecidx));
if (err) {
mlx5_core_err(mdev, "irq_cpu_rmap_add failed. err %d",
err);
goto err_irq_cpu_rmap_add;
}
}
return 0;

err_irq_cpu_rmap_add:
clear_rmap(mdev);
err_out:
#endif
return err;
}

/* 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 */
if (!mlx5_core_is_sf(dev))
clear_rmap(dev);
mlx5_irq_table_destroy(dev);
mutex_unlock(&table->lock);
}
Expand Down Expand Up @@ -1139,38 +1139,22 @@ int mlx5_eq_table_create(struct mlx5_core_dev *dev)
goto err_async_eqs;
}

if (!mlx5_core_is_sf(dev)) {
/* rmap is a mapping between irq number and queue number.
* each irq can be assign only to a single rmap.
* since SFs share IRQs, rmap mapping cannot function correctly
* for irqs that are shared for different core/netdev RX rings.
* Hence we don't allow netdev rmap for SFs
*/
err = set_rmap(dev);
if (err)
goto err_rmap;
}

err = create_comp_eqs(dev);
if (err) {
mlx5_core_err(dev, "Failed to create completion EQs\n");
goto err_comp_eqs;
}

return 0;

err_comp_eqs:
if (!mlx5_core_is_sf(dev))
clear_rmap(dev);
err_rmap:
destroy_async_eqs(dev);
err_async_eqs:
return err;
}

void mlx5_eq_table_destroy(struct mlx5_core_dev *dev)
{
if (!mlx5_core_is_sf(dev))
clear_rmap(dev);
destroy_comp_eqs(dev);
destroy_async_eqs(dev);
}
Expand Down
5 changes: 3 additions & 2 deletions drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ irq_pool_request_irq(struct mlx5_irq_pool *pool, struct irq_affinity_desc *af_de
cpu_get(pool, cpumask_first(&af_desc->mask));
}
return mlx5_irq_alloc(pool, irq_index,
cpumask_empty(&auto_desc.mask) ? af_desc : &auto_desc);
cpumask_empty(&auto_desc.mask) ? af_desc : &auto_desc,
NULL);
}

/* Looking for the IRQ with the smallest refcount that fits req_mask.
Expand Down Expand Up @@ -205,7 +206,7 @@ int mlx5_irq_affinity_irqs_request_auto(struct mlx5_core_dev *dev, int nirqs,
* The PF IRQs are already allocated and binded to CPU
* at this point. Hence, only an index is needed.
*/
irq = mlx5_irq_request(dev, i, NULL);
irq = mlx5_irq_request(dev, i, NULL, NULL);
if (IS_ERR(irq))
break;
irqs[i] = irq;
Expand Down
3 changes: 0 additions & 3 deletions drivers/net/ethernet/mellanox/mlx5/core/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@
#include <linux/kmod.h>
#include <linux/mlx5/mlx5_ifc.h>
#include <linux/mlx5/vport.h>
#ifdef CONFIG_RFS_ACCEL
#include <linux/cpu_rmap.h>
#endif
#include <linux/version.h>
#include <net/devlink.h>
#include "mlx5_core.h"
Expand Down
6 changes: 4 additions & 2 deletions drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define MLX5_COMP_EQS_PER_SF 8

struct mlx5_irq;
struct cpu_rmap;

int mlx5_irq_table_init(struct mlx5_core_dev *dev);
void mlx5_irq_table_cleanup(struct mlx5_core_dev *dev);
Expand All @@ -25,9 +26,10 @@ int mlx5_get_default_msix_vec_count(struct mlx5_core_dev *dev, int num_vfs);
struct mlx5_irq *mlx5_ctrl_irq_request(struct mlx5_core_dev *dev);
void mlx5_ctrl_irq_release(struct mlx5_irq *ctrl_irq);
struct mlx5_irq *mlx5_irq_request(struct mlx5_core_dev *dev, u16 vecidx,
struct irq_affinity_desc *af_desc);
struct irq_affinity_desc *af_desc,
struct cpu_rmap **rmap);
int mlx5_irqs_request_vectors(struct mlx5_core_dev *dev, u16 *cpus, int nirqs,
struct mlx5_irq **irqs);
struct mlx5_irq **irqs, struct cpu_rmap **rmap);
void mlx5_irqs_release_vectors(struct mlx5_irq **irqs, int nirqs);
int mlx5_irq_attach_nb(struct mlx5_irq *irq, struct notifier_block *nb);
int mlx5_irq_detach_nb(struct mlx5_irq *irq, struct notifier_block *nb);
Expand Down

0 comments on commit 3354822

Please sign in to comment.