Commit db058a18 authored by Saeed Mahameed's avatar Saeed Mahameed Committed by David S. Miller

net/mlx5_core: Set irq affinity hints

Preparation for upcoming ethernet driver.
- Move msix array from eq_table struct to priv since its not related to
  eq_table
- Intorduce irq_info struct to hold all irq information
- Move name from mlx5_eq to irq_info struct since it is irq property.
- Set IRQ affinity hints
Signed-off-by: default avatarAchiad Shochat <achiad@mellanox.com>
Signed-off-by: default avatarRana Shahout <ranas@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
Signed-off-by: default avatarAmir Vadai <amirv@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 64ffaa21
...@@ -339,7 +339,7 @@ static void init_eq_buf(struct mlx5_eq *eq) ...@@ -339,7 +339,7 @@ static void init_eq_buf(struct mlx5_eq *eq)
int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx, int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
int nent, u64 mask, const char *name, struct mlx5_uar *uar) int nent, u64 mask, const char *name, struct mlx5_uar *uar)
{ {
struct mlx5_eq_table *table = &dev->priv.eq_table; struct mlx5_priv *priv = &dev->priv;
struct mlx5_create_eq_mbox_in *in; struct mlx5_create_eq_mbox_in *in;
struct mlx5_create_eq_mbox_out out; struct mlx5_create_eq_mbox_out out;
int err; int err;
...@@ -377,14 +377,15 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx, ...@@ -377,14 +377,15 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
goto err_in; goto err_in;
} }
snprintf(eq->name, MLX5_MAX_EQ_NAME, "%s@pci:%s", snprintf(priv->irq_info[vecidx].name, MLX5_MAX_IRQ_NAME, "%s@pci:%s",
name, pci_name(dev->pdev)); name, pci_name(dev->pdev));
eq->eqn = out.eq_number; eq->eqn = out.eq_number;
eq->irqn = vecidx; eq->irqn = vecidx;
eq->dev = dev; eq->dev = dev;
eq->doorbell = uar->map + MLX5_EQ_DOORBEL_OFFSET; eq->doorbell = uar->map + MLX5_EQ_DOORBEL_OFFSET;
err = request_irq(table->msix_arr[vecidx].vector, mlx5_msix_handler, 0, err = request_irq(priv->msix_arr[vecidx].vector, mlx5_msix_handler, 0,
eq->name, eq); priv->irq_info[vecidx].name, eq);
if (err) if (err)
goto err_eq; goto err_eq;
...@@ -400,7 +401,7 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx, ...@@ -400,7 +401,7 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
return 0; return 0;
err_irq: err_irq:
free_irq(table->msix_arr[vecidx].vector, eq); free_irq(priv->msix_arr[vecidx].vector, eq);
err_eq: err_eq:
mlx5_cmd_destroy_eq(dev, eq->eqn); mlx5_cmd_destroy_eq(dev, eq->eqn);
...@@ -416,16 +417,15 @@ EXPORT_SYMBOL_GPL(mlx5_create_map_eq); ...@@ -416,16 +417,15 @@ EXPORT_SYMBOL_GPL(mlx5_create_map_eq);
int mlx5_destroy_unmap_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq) int mlx5_destroy_unmap_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq)
{ {
struct mlx5_eq_table *table = &dev->priv.eq_table;
int err; int err;
mlx5_debug_eq_remove(dev, eq); mlx5_debug_eq_remove(dev, eq);
free_irq(table->msix_arr[eq->irqn].vector, eq); free_irq(dev->priv.msix_arr[eq->irqn].vector, eq);
err = mlx5_cmd_destroy_eq(dev, eq->eqn); err = mlx5_cmd_destroy_eq(dev, eq->eqn);
if (err) if (err)
mlx5_core_warn(dev, "failed to destroy a previously created eq: eqn %d\n", mlx5_core_warn(dev, "failed to destroy a previously created eq: eqn %d\n",
eq->eqn); eq->eqn);
synchronize_irq(table->msix_arr[eq->irqn].vector); synchronize_irq(dev->priv.msix_arr[eq->irqn].vector);
mlx5_buf_free(dev, &eq->buf); mlx5_buf_free(dev, &eq->buf);
return err; return err;
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/io-mapping.h> #include <linux/io-mapping.h>
#include <linux/interrupt.h>
#include <linux/mlx5/driver.h> #include <linux/mlx5/driver.h>
#include <linux/mlx5/cq.h> #include <linux/mlx5/cq.h>
#include <linux/mlx5/qp.h> #include <linux/mlx5/qp.h>
...@@ -208,7 +209,8 @@ static void release_bar(struct pci_dev *pdev) ...@@ -208,7 +209,8 @@ static void release_bar(struct pci_dev *pdev)
static int mlx5_enable_msix(struct mlx5_core_dev *dev) static int mlx5_enable_msix(struct mlx5_core_dev *dev)
{ {
struct mlx5_eq_table *table = &dev->priv.eq_table; struct mlx5_priv *priv = &dev->priv;
struct mlx5_eq_table *table = &priv->eq_table;
int num_eqs = 1 << dev->caps.gen.log_max_eq; int num_eqs = 1 << dev->caps.gen.log_max_eq;
int nvec; int nvec;
int i; int i;
...@@ -218,14 +220,16 @@ static int mlx5_enable_msix(struct mlx5_core_dev *dev) ...@@ -218,14 +220,16 @@ static int mlx5_enable_msix(struct mlx5_core_dev *dev)
if (nvec <= MLX5_EQ_VEC_COMP_BASE) if (nvec <= MLX5_EQ_VEC_COMP_BASE)
return -ENOMEM; return -ENOMEM;
table->msix_arr = kzalloc(nvec * sizeof(*table->msix_arr), GFP_KERNEL); priv->msix_arr = kcalloc(nvec, sizeof(*priv->msix_arr), GFP_KERNEL);
if (!table->msix_arr)
return -ENOMEM; priv->irq_info = kcalloc(nvec, sizeof(*priv->irq_info), GFP_KERNEL);
if (!priv->msix_arr || !priv->irq_info)
goto err_free_msix;
for (i = 0; i < nvec; i++) for (i = 0; i < nvec; i++)
table->msix_arr[i].entry = i; priv->msix_arr[i].entry = i;
nvec = pci_enable_msix_range(dev->pdev, table->msix_arr, nvec = pci_enable_msix_range(dev->pdev, priv->msix_arr,
MLX5_EQ_VEC_COMP_BASE + 1, nvec); MLX5_EQ_VEC_COMP_BASE + 1, nvec);
if (nvec < 0) if (nvec < 0)
return nvec; return nvec;
...@@ -233,14 +237,20 @@ static int mlx5_enable_msix(struct mlx5_core_dev *dev) ...@@ -233,14 +237,20 @@ static int mlx5_enable_msix(struct mlx5_core_dev *dev)
table->num_comp_vectors = nvec - MLX5_EQ_VEC_COMP_BASE; table->num_comp_vectors = nvec - MLX5_EQ_VEC_COMP_BASE;
return 0; return 0;
err_free_msix:
kfree(priv->irq_info);
kfree(priv->msix_arr);
return -ENOMEM;
} }
static void mlx5_disable_msix(struct mlx5_core_dev *dev) static void mlx5_disable_msix(struct mlx5_core_dev *dev)
{ {
struct mlx5_eq_table *table = &dev->priv.eq_table; struct mlx5_priv *priv = &dev->priv;
pci_disable_msix(dev->pdev); pci_disable_msix(dev->pdev);
kfree(table->msix_arr); kfree(priv->irq_info);
kfree(priv->msix_arr);
} }
struct mlx5_reg_host_endianess { struct mlx5_reg_host_endianess {
...@@ -507,6 +517,77 @@ static int mlx5_core_disable_hca(struct mlx5_core_dev *dev) ...@@ -507,6 +517,77 @@ static int mlx5_core_disable_hca(struct mlx5_core_dev *dev)
return 0; return 0;
} }
static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
{
struct mlx5_priv *priv = &mdev->priv;
struct msix_entry *msix = priv->msix_arr;
int irq = msix[i + MLX5_EQ_VEC_COMP_BASE].vector;
int numa_node = dev_to_node(&mdev->pdev->dev);
int err;
if (!zalloc_cpumask_var(&priv->irq_info[i].mask, GFP_KERNEL)) {
mlx5_core_warn(mdev, "zalloc_cpumask_var failed");
return -ENOMEM;
}
err = cpumask_set_cpu_local_first(i, numa_node, priv->irq_info[i].mask);
if (err) {
mlx5_core_warn(mdev, "cpumask_set_cpu_local_first failed");
goto err_clear_mask;
}
err = irq_set_affinity_hint(irq, priv->irq_info[i].mask);
if (err) {
mlx5_core_warn(mdev, "irq_set_affinity_hint failed,irq 0x%.4x",
irq);
goto err_clear_mask;
}
return 0;
err_clear_mask:
free_cpumask_var(priv->irq_info[i].mask);
return err;
}
static void mlx5_irq_clear_affinity_hint(struct mlx5_core_dev *mdev, int i)
{
struct mlx5_priv *priv = &mdev->priv;
struct msix_entry *msix = priv->msix_arr;
int irq = msix[i + MLX5_EQ_VEC_COMP_BASE].vector;
irq_set_affinity_hint(irq, NULL);
free_cpumask_var(priv->irq_info[i].mask);
}
static int mlx5_irq_set_affinity_hints(struct mlx5_core_dev *mdev)
{
int err;
int i;
for (i = 0; i < mdev->priv.eq_table.num_comp_vectors; i++) {
err = mlx5_irq_set_affinity_hint(mdev, i);
if (err)
goto err_out;
}
return 0;
err_out:
for (i--; i >= 0; i--)
mlx5_irq_clear_affinity_hint(mdev, i);
return err;
}
static void mlx5_irq_clear_affinity_hints(struct mlx5_core_dev *mdev)
{
int i;
for (i = 0; i < mdev->priv.eq_table.num_comp_vectors; i++)
mlx5_irq_clear_affinity_hint(mdev, i);
}
int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn, int *irqn) int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn, int *irqn)
{ {
struct mlx5_eq_table *table = &dev->priv.eq_table; struct mlx5_eq_table *table = &dev->priv.eq_table;
...@@ -549,7 +630,7 @@ static void free_comp_eqs(struct mlx5_core_dev *dev) ...@@ -549,7 +630,7 @@ static void free_comp_eqs(struct mlx5_core_dev *dev)
static int alloc_comp_eqs(struct mlx5_core_dev *dev) static int alloc_comp_eqs(struct mlx5_core_dev *dev)
{ {
struct mlx5_eq_table *table = &dev->priv.eq_table; struct mlx5_eq_table *table = &dev->priv.eq_table;
char name[MLX5_MAX_EQ_NAME]; char name[MLX5_MAX_IRQ_NAME];
struct mlx5_eq *eq; struct mlx5_eq *eq;
int ncomp_vec; int ncomp_vec;
int nent; int nent;
...@@ -566,7 +647,7 @@ static int alloc_comp_eqs(struct mlx5_core_dev *dev) ...@@ -566,7 +647,7 @@ static int alloc_comp_eqs(struct mlx5_core_dev *dev)
goto clean; goto clean;
} }
snprintf(name, MLX5_MAX_EQ_NAME, "mlx5_comp%d", i); snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d", i);
err = mlx5_create_map_eq(dev, eq, err = mlx5_create_map_eq(dev, eq,
i + MLX5_EQ_VEC_COMP_BASE, nent, 0, i + MLX5_EQ_VEC_COMP_BASE, nent, 0,
name, &dev->priv.uuari.uars[0]); name, &dev->priv.uuari.uars[0]);
...@@ -730,6 +811,12 @@ static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev) ...@@ -730,6 +811,12 @@ static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
goto err_stop_eqs; goto err_stop_eqs;
} }
err = mlx5_irq_set_affinity_hints(dev);
if (err) {
dev_err(&pdev->dev, "Failed to alloc affinity hint cpumask\n");
goto err_free_comp_eqs;
}
MLX5_INIT_DOORBELL_LOCK(&priv->cq_uar_lock); MLX5_INIT_DOORBELL_LOCK(&priv->cq_uar_lock);
mlx5_init_cq_table(dev); mlx5_init_cq_table(dev);
...@@ -739,6 +826,9 @@ static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev) ...@@ -739,6 +826,9 @@ static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
return 0; return 0;
err_free_comp_eqs:
free_comp_eqs(dev);
err_stop_eqs: err_stop_eqs:
mlx5_stop_eqs(dev); mlx5_stop_eqs(dev);
...@@ -793,6 +883,7 @@ static void mlx5_dev_cleanup(struct mlx5_core_dev *dev) ...@@ -793,6 +883,7 @@ static void mlx5_dev_cleanup(struct mlx5_core_dev *dev)
mlx5_cleanup_srq_table(dev); mlx5_cleanup_srq_table(dev);
mlx5_cleanup_qp_table(dev); mlx5_cleanup_qp_table(dev);
mlx5_cleanup_cq_table(dev); mlx5_cleanup_cq_table(dev);
mlx5_irq_clear_affinity_hints(dev);
free_comp_eqs(dev); free_comp_eqs(dev);
mlx5_stop_eqs(dev); mlx5_stop_eqs(dev);
mlx5_free_uuars(dev, &priv->uuari); mlx5_free_uuars(dev, &priv->uuari);
......
...@@ -85,7 +85,7 @@ enum { ...@@ -85,7 +85,7 @@ enum {
}; };
enum { enum {
MLX5_MAX_EQ_NAME = 32 MLX5_MAX_IRQ_NAME = 32
}; };
enum { enum {
...@@ -349,7 +349,6 @@ struct mlx5_eq { ...@@ -349,7 +349,6 @@ struct mlx5_eq {
u8 eqn; u8 eqn;
int nent; int nent;
u64 mask; u64 mask;
char name[MLX5_MAX_EQ_NAME];
struct list_head list; struct list_head list;
int index; int index;
struct mlx5_rsc_debug *dbg; struct mlx5_rsc_debug *dbg;
...@@ -412,7 +411,6 @@ struct mlx5_eq_table { ...@@ -412,7 +411,6 @@ struct mlx5_eq_table {
struct mlx5_eq pages_eq; struct mlx5_eq pages_eq;
struct mlx5_eq async_eq; struct mlx5_eq async_eq;
struct mlx5_eq cmd_eq; struct mlx5_eq cmd_eq;
struct msix_entry *msix_arr;
int num_comp_vectors; int num_comp_vectors;
/* protect EQs list /* protect EQs list
*/ */
...@@ -465,9 +463,16 @@ struct mlx5_mr_table { ...@@ -465,9 +463,16 @@ struct mlx5_mr_table {
struct radix_tree_root tree; struct radix_tree_root tree;
}; };
struct mlx5_irq_info {
cpumask_var_t mask;
char name[MLX5_MAX_IRQ_NAME];
};
struct mlx5_priv { struct mlx5_priv {
char name[MLX5_MAX_NAME_LEN]; char name[MLX5_MAX_NAME_LEN];
struct mlx5_eq_table eq_table; struct mlx5_eq_table eq_table;
struct msix_entry *msix_arr;
struct mlx5_irq_info *irq_info;
struct mlx5_uuar_info uuari; struct mlx5_uuar_info uuari;
MLX5_DECLARE_DOORBELL_LOCK(cq_uar_lock); MLX5_DECLARE_DOORBELL_LOCK(cq_uar_lock);
......
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