Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 35f6f453 authored by Amir Vadai's avatar Amir Vadai Committed by David S. Miller
Browse files

net/mlx4_en: Don't use irq_affinity_notifier to track changes in IRQ affinity map



IRQ affinity notifier can only have a single notifier - cpu_rmap
notifier. Can't use it to track changes in IRQ affinity map.
Detect IRQ affinity changes by comparing CPU to current IRQ affinity map
during NAPI poll thread.

CC: Thomas Gleixner <tglx@linutronix.de>
CC: Ben Hutchings <ben@decadent.org.uk>
Fixes: 2eacc23c ("net/mlx4_core: Enforce irq affinity changes immediatly")
Signed-off-by: default avatarAmir Vadai <amirv@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1b037474
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -294,8 +294,6 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent,
	init_completion(&cq->free);

	cq->irq = priv->eq_table.eq[cq->vector].irq;
	cq->irq_affinity_change = false;

	return 0;

err_radix:
+4 −0
Original line number Diff line number Diff line
@@ -128,6 +128,10 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
					mlx4_warn(mdev, "Failed assigning an EQ to %s, falling back to legacy EQ's\n",
						  name);
				}

				cq->irq_desc =
					irq_to_desc(mlx4_eq_get_irq(mdev->dev,
								    cq->vector));
			}
		} else {
			cq->vector = (cq->ring + 1 + priv->port) %
+13 −3
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/vmalloc.h>
#include <linux/irq.h>

#include "mlx4_en.h"

@@ -896,16 +897,25 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)

	/* If we used up all the quota - we're probably not done yet... */
	if (done == budget) {
		int cpu_curr;
		const struct cpumask *aff;

		INC_PERF_COUNTER(priv->pstats.napi_quota);
		if (unlikely(cq->mcq.irq_affinity_change)) {
			cq->mcq.irq_affinity_change = false;

		cpu_curr = smp_processor_id();
		aff = irq_desc_get_irq_data(cq->irq_desc)->affinity;

		if (unlikely(!cpumask_test_cpu(cpu_curr, aff))) {
			/* Current cpu is not according to smp_irq_affinity -
			 * probably affinity changed. need to stop this NAPI
			 * poll, and restart it on the right CPU
			 */
			napi_complete(napi);
			mlx4_en_arm_cq(priv, cq);
			return 0;
		}
	} else {
		/* Done for now */
		cq->mcq.irq_affinity_change = false;
		napi_complete(napi);
		mlx4_en_arm_cq(priv, cq);
	}
+0 −6
Original line number Diff line number Diff line
@@ -474,15 +474,9 @@ int mlx4_en_poll_tx_cq(struct napi_struct *napi, int budget)
	/* If we used up all the quota - we're probably not done yet... */
	if (done < budget) {
		/* Done for now */
		cq->mcq.irq_affinity_change = false;
		napi_complete(napi);
		mlx4_en_arm_cq(priv, cq);
		return done;
	} else if (unlikely(cq->mcq.irq_affinity_change)) {
		cq->mcq.irq_affinity_change = false;
		napi_complete(napi);
		mlx4_en_arm_cq(priv, cq);
		return 0;
	}
	return budget;
}
+8 −61
Original line number Diff line number Diff line
@@ -53,11 +53,6 @@ enum {
	MLX4_EQ_ENTRY_SIZE	= 0x20
};

struct mlx4_irq_notify {
	void *arg;
	struct irq_affinity_notify notify;
};

#define MLX4_EQ_STATUS_OK	   ( 0 << 28)
#define MLX4_EQ_STATUS_WRITE_FAIL  (10 << 28)
#define MLX4_EQ_OWNER_SW	   ( 0 << 24)
@@ -1088,57 +1083,6 @@ static void mlx4_unmap_clr_int(struct mlx4_dev *dev)
	iounmap(priv->clr_base);
}

static void mlx4_irq_notifier_notify(struct irq_affinity_notify *notify,
				     const cpumask_t *mask)
{
	struct mlx4_irq_notify *n = container_of(notify,
						 struct mlx4_irq_notify,
						 notify);
	struct mlx4_priv *priv = (struct mlx4_priv *)n->arg;
	struct radix_tree_iter iter;
	void **slot;

	radix_tree_for_each_slot(slot, &priv->cq_table.tree, &iter, 0) {
		struct mlx4_cq *cq = (struct mlx4_cq *)(*slot);

		if (cq->irq == notify->irq)
			cq->irq_affinity_change = true;
	}
}

static void mlx4_release_irq_notifier(struct kref *ref)
{
	struct mlx4_irq_notify *n = container_of(ref, struct mlx4_irq_notify,
						 notify.kref);
	kfree(n);
}

static void mlx4_assign_irq_notifier(struct mlx4_priv *priv,
				     struct mlx4_dev *dev, int irq)
{
	struct mlx4_irq_notify *irq_notifier = NULL;
	int err = 0;

	irq_notifier = kzalloc(sizeof(*irq_notifier), GFP_KERNEL);
	if (!irq_notifier) {
		mlx4_warn(dev, "Failed to allocate irq notifier. irq %d\n",
			  irq);
		return;
	}

	irq_notifier->notify.irq = irq;
	irq_notifier->notify.notify = mlx4_irq_notifier_notify;
	irq_notifier->notify.release = mlx4_release_irq_notifier;
	irq_notifier->arg = priv;
	err = irq_set_affinity_notifier(irq, &irq_notifier->notify);
	if (err) {
		kfree(irq_notifier);
		irq_notifier = NULL;
		mlx4_warn(dev, "Failed to set irq notifier. irq %d\n", irq);
	}
}


int mlx4_alloc_eq_table(struct mlx4_dev *dev)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
@@ -1409,8 +1353,6 @@ int mlx4_assign_eq(struct mlx4_dev *dev, char *name, struct cpu_rmap *rmap,
				continue;
				/*we dont want to break here*/
			}
			mlx4_assign_irq_notifier(priv, dev,
						 priv->eq_table.eq[vec].irq);

			eq_set_ci(&priv->eq_table.eq[vec], 1);
		}
@@ -1427,6 +1369,14 @@ int mlx4_assign_eq(struct mlx4_dev *dev, char *name, struct cpu_rmap *rmap,
}
EXPORT_SYMBOL(mlx4_assign_eq);

int mlx4_eq_get_irq(struct mlx4_dev *dev, int vec)
{
	struct mlx4_priv *priv = mlx4_priv(dev);

	return priv->eq_table.eq[vec].irq;
}
EXPORT_SYMBOL(mlx4_eq_get_irq);

void mlx4_release_eq(struct mlx4_dev *dev, int vec)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
@@ -1438,9 +1388,6 @@ void mlx4_release_eq(struct mlx4_dev *dev, int vec)
		  Belonging to a legacy EQ*/
		mutex_lock(&priv->msix_ctl.pool_lock);
		if (priv->msix_ctl.pool_bm & 1ULL << i) {
			irq_set_affinity_notifier(
				priv->eq_table.eq[vec].irq,
				NULL);
			free_irq(priv->eq_table.eq[vec].irq,
				 &priv->eq_table.eq[vec]);
			priv->msix_ctl.pool_bm &= ~(1ULL << i);
Loading