mlx5_init_fbc(eq->frag_buf.frags, log_eq_stride, log_eq_size, &eq->fbc);
init_eq_buf(eq);
- eq->irq = mlx5_irq_request(dev, vecidx);
+ eq->irq = mlx5_irq_request(dev, vecidx, param->affinity);
if (IS_ERR(eq->irq)) {
err = PTR_ERR(eq->irq);
goto err_buf;
eq->irq_nb.notifier_call = mlx5_eq_async_int;
spin_lock_init(&eq->lock);
+ if (!zalloc_cpumask_var(¶m->affinity, GFP_KERNEL))
+ return -ENOMEM;
err = create_async_eq(dev, &eq->core, param);
+ free_cpumask_var(param->affinity);
if (err) {
mlx5_core_warn(dev, "failed to create %s EQ %d\n", name, err);
return err;
struct mlx5_eq *eq = kvzalloc(sizeof(*eq), GFP_KERNEL);
int err;
+ if (!param->affinity)
+ return ERR_PTR(-EINVAL);
+
if (!eq)
return ERR_PTR(-ENOMEM);
.irq_index = vecidx,
.nent = nent,
};
- err = create_map_eq(dev, &eq->core, ¶m);
- if (err) {
- kfree(eq);
- goto clean;
+
+ if (!zalloc_cpumask_var(¶m.affinity, GFP_KERNEL)) {
+ err = -ENOMEM;
+ goto clean_eq;
}
+ cpumask_set_cpu(cpumask_local_spread(i, dev->priv.numa_node),
+ param.affinity);
+ err = create_map_eq(dev, &eq->core, ¶m);
+ free_cpumask_var(param.affinity);
+ if (err)
+ goto clean_eq;
err = mlx5_eq_enable(dev, &eq->core, &eq->irq_nb);
if (err) {
destroy_unmap_eq(dev, &eq->core);
- kfree(eq);
- goto clean;
+ goto clean_eq;
}
mlx5_core_dbg(dev, "allocated completion EQN %d\n", eq->core.eqn);
}
return 0;
+clean_eq:
+ kfree(eq);
clean:
destroy_comp_eqs(dev);
return err;
struct atomic_notifier_head nh;
cpumask_var_t mask;
char name[MLX5_MAX_IRQ_NAME];
+ spinlock_t lock; /* protects affinity assignment */
struct kref kref;
int irqn;
};
{
struct mlx5_irq *irq = container_of(kref, struct mlx5_irq, kref);
+ irq_set_affinity_hint(irq->irqn, NULL);
+ free_cpumask_var(irq->mask);
free_irq(irq->irqn, &irq->nh);
}
irq_put(irq);
}
-struct mlx5_irq *mlx5_irq_request(struct mlx5_core_dev *dev, int vecidx)
+struct mlx5_irq *mlx5_irq_request(struct mlx5_core_dev *dev, int vecidx,
+ struct cpumask *affinity)
{
struct mlx5_irq_table *table = mlx5_irq_table_get(dev);
struct mlx5_irq *irq = &table->irq[vecidx];
if (!err)
return ERR_PTR(-ENOENT);
+ spin_lock(&irq->lock);
+ if (!cpumask_empty(irq->mask)) {
+ /* already configured */
+ spin_unlock(&irq->lock);
+ return irq;
+ }
+
+ cpumask_copy(irq->mask, affinity);
+ irq_set_affinity_hint(irq->irqn, irq->mask);
+ spin_unlock(&irq->lock);
return irq;
}
mlx5_core_err(dev, "Failed to request irq\n");
goto err_request_irq;
}
+ if (!zalloc_cpumask_var(&irq->mask, GFP_KERNEL)) {
+ mlx5_core_warn(dev, "zalloc_cpumask_var failed\n");
+ err = -ENOMEM;
+ goto err_request_irq;
+ }
+ spin_lock_init(&irq->lock);
kref_init(&irq->kref);
}
return 0;
return err;
}
-/* Completion IRQ vectors */
-
-static int set_comp_irq_affinity_hint(struct mlx5_core_dev *mdev, int i)
-{
- int vecidx = MLX5_IRQ_VEC_COMP_BASE + i;
- struct mlx5_irq *irq;
-
- irq = mlx5_irq_get(mdev, vecidx);
- if (!zalloc_cpumask_var(&irq->mask, GFP_KERNEL)) {
- mlx5_core_warn(mdev, "zalloc_cpumask_var failed");
- return -ENOMEM;
- }
-
- cpumask_set_cpu(cpumask_local_spread(i, mdev->priv.numa_node),
- irq->mask);
- if (IS_ENABLED(CONFIG_SMP) &&
- irq_set_affinity_hint(irq->irqn, irq->mask))
- mlx5_core_warn(mdev, "irq_set_affinity_hint failed, irq 0x%.4x",
- irq->irqn);
-
- return 0;
-}
-
-static void clear_comp_irq_affinity_hint(struct mlx5_core_dev *mdev, int i)
-{
- int vecidx = MLX5_IRQ_VEC_COMP_BASE + i;
- struct mlx5_irq *irq;
-
- irq = mlx5_irq_get(mdev, vecidx);
- irq_set_affinity_hint(irq->irqn, NULL);
- free_cpumask_var(irq->mask);
-}
-
-static int set_comp_irq_affinity_hints(struct mlx5_core_dev *mdev)
-{
- int nvec = mlx5_irq_get_num_comp(mdev->priv.irq_table);
- int err;
- int i;
-
- for (i = 0; i < nvec; i++) {
- err = set_comp_irq_affinity_hint(mdev, i);
- if (err)
- goto err_out;
- }
-
- return 0;
-
-err_out:
- for (i--; i >= 0; i--)
- clear_comp_irq_affinity_hint(mdev, i);
-
- return err;
-}
-
-static void clear_comp_irqs_affinity_hints(struct mlx5_core_dev *mdev)
-{
- int nvec = mlx5_irq_get_num_comp(mdev->priv.irq_table);
- int i;
-
- for (i = 0; i < nvec; i++)
- clear_comp_irq_affinity_hint(mdev, i);
-}
-
struct cpumask *
mlx5_irq_get_affinity_mask(struct mlx5_irq_table *irq_table, int vecidx)
{
}
#endif
-static void unrequest_irqs(struct mlx5_core_dev *dev)
-{
- struct mlx5_irq_table *table = dev->priv.irq_table;
- int i;
-
- for (i = 0; i < table->nvec; i++)
- irq_put(mlx5_irq_get(dev, i));
-}
-
int mlx5_irq_table_create(struct mlx5_core_dev *dev)
{
struct mlx5_priv *priv = &dev->priv;
if (err)
goto err_request_irqs;
- err = set_comp_irq_affinity_hints(dev);
- if (err) {
- mlx5_core_err(dev, "Failed to alloc affinity hint cpumask\n");
- goto err_set_affinity;
- }
-
return 0;
-err_set_affinity:
- unrequest_irqs(dev);
err_request_irqs:
irq_clear_rmap(dev);
err_set_rmap:
* which should be called after alloc_irq but before request_irq.
*/
irq_clear_rmap(dev);
- clear_comp_irqs_affinity_hints(dev);
for (i = 0; i < table->nvec; i++)
irq_release(&mlx5_irq_get(dev, i)->kref);
pci_free_irq_vectors(dev->pdev);