Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1645404 > unrolled thread

spread MSI(-X) vectors to all possible CPUs V2

Started byChristoph Hellwig <hch@lst.de>
First post2017-05-19 11:00 +0200
Last post2017-05-23 11:40 +0200
Articles 5 — 2 participants

Back to article view | Back to linux.kernel


Contents

  spread MSI(-X) vectors to all possible CPUs V2 Christoph Hellwig <hch@lst.de> - 2017-05-19 11:00 +0200
    [PATCH 1/7] genirq: allow assigning affinity to present but not online CPUs Christoph Hellwig <hch@lst.de> - 2017-05-19 11:00 +0200
    [PATCH 2/7] genirq/affinity: assign vectors to all present CPUs Christoph Hellwig <hch@lst.de> - 2017-05-19 11:00 +0200
      Re: [PATCH 2/7] genirq/affinity: assign vectors to all present  CPUs Thomas Gleixner <tglx@linutronix.de> - 2017-05-21 20:40 +0200
        Re: [PATCH 2/7] genirq/affinity: assign vectors to all present CPUs Christoph Hellwig <hch@lst.de> - 2017-05-23 11:40 +0200

#1645404 — spread MSI(-X) vectors to all possible CPUs V2

FromChristoph Hellwig <hch@lst.de>
Date2017-05-19 11:00 +0200
Subjectspread MSI(-X) vectors to all possible CPUs V2
Message-ID<tILVn-84l-11@gated-at.bofh.it>
Hi all,

this series changes our automatic MSI-X vector assignment so that it
takes all present CPUs into account instead of all online ones.  This
allows to better deal with cpu hotplug events, which could happen
frequently due to power management for example.

Changes since V1:
 - rebase to current Linus' tree
 - add irq_lock_sparse calls
 - move memory allocations outside of (raw) spinlocks
 - remove the irq_force_complete_move call
 - factor some common code into helpers
 - identation fixups

[toc] | [next] | [standalone]


#1645405 — [PATCH 1/7] genirq: allow assigning affinity to present but not online CPUs

FromChristoph Hellwig <hch@lst.de>
Date2017-05-19 11:00 +0200
Subject[PATCH 1/7] genirq: allow assigning affinity to present but not online CPUs
Message-ID<tILVo-84l-31@gated-at.bofh.it>
In reply to#1645404
This will allow us to spread MSI/MSI-X affinity over all present CPUs and
thus better deal with systems where cpus are take on and offline all the
time.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 kernel/irq/manage.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 070be980c37a..5c25d4a5dc46 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -361,17 +361,17 @@ static int setup_affinity(struct irq_desc *desc, struct cpumask *mask)
 	if (irqd_affinity_is_managed(&desc->irq_data) ||
 	    irqd_has_set(&desc->irq_data, IRQD_AFFINITY_SET)) {
 		if (cpumask_intersects(desc->irq_common_data.affinity,
-				       cpu_online_mask))
+				       cpu_present_mask))
 			set = desc->irq_common_data.affinity;
 		else
 			irqd_clear(&desc->irq_data, IRQD_AFFINITY_SET);
 	}
 
-	cpumask_and(mask, cpu_online_mask, set);
+	cpumask_and(mask, cpu_present_mask, set);
 	if (node != NUMA_NO_NODE) {
 		const struct cpumask *nodemask = cpumask_of_node(node);
 
-		/* make sure at least one of the cpus in nodemask is online */
+		/* make sure at least one of the cpus in nodemask is present */
 		if (cpumask_intersects(mask, nodemask))
 			cpumask_and(mask, mask, nodemask);
 	}
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1645406 — [PATCH 2/7] genirq/affinity: assign vectors to all present CPUs

FromChristoph Hellwig <hch@lst.de>
Date2017-05-19 11:00 +0200
Subject[PATCH 2/7] genirq/affinity: assign vectors to all present CPUs
Message-ID<tILVo-84l-35@gated-at.bofh.it>
In reply to#1645404
Currently we only assign spread vectors to online CPUs, which ties the
IRQ mapping to the currently online devices and doesn't deal nicely with
the fact that CPUs could come and go rapidly due to e.g. power management.

Instead assign vectors to all present CPUs to avoid this churn.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 kernel/irq/affinity.c | 43 ++++++++++++++++++++++++++++---------------
 1 file changed, 28 insertions(+), 15 deletions(-)

diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c
index e2d356dd7581..414b0be64bfc 100644
--- a/kernel/irq/affinity.c
+++ b/kernel/irq/affinity.c
@@ -4,6 +4,8 @@
 #include <linux/slab.h>
 #include <linux/cpu.h>
 
+static cpumask_var_t node_to_present_cpumask[MAX_NUMNODES] __read_mostly;
+
 static void irq_spread_init_one(struct cpumask *irqmsk, struct cpumask *nmsk,
 				int cpus_per_vec)
 {
@@ -40,8 +42,8 @@ static int get_nodes_in_cpumask(const struct cpumask *mask, nodemask_t *nodemsk)
 	int n, nodes = 0;
 
 	/* Calculate the number of nodes in the supplied affinity mask */
-	for_each_online_node(n) {
-		if (cpumask_intersects(mask, cpumask_of_node(n))) {
+	for_each_node(n) {
+		if (cpumask_intersects(mask, node_to_present_cpumask[n])) {
 			node_set(n, *nodemsk);
 			nodes++;
 		}
@@ -77,9 +79,7 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
 	for (curvec = 0; curvec < affd->pre_vectors; curvec++)
 		cpumask_copy(masks + curvec, irq_default_affinity);
 
-	/* Stabilize the cpumasks */
-	get_online_cpus();
-	nodes = get_nodes_in_cpumask(cpu_online_mask, &nodemsk);
+	nodes = get_nodes_in_cpumask(cpu_present_mask, &nodemsk);
 
 	/*
 	 * If the number of nodes in the mask is greater than or equal the
@@ -87,7 +87,8 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
 	 */
 	if (affv <= nodes) {
 		for_each_node_mask(n, nodemsk) {
-			cpumask_copy(masks + curvec, cpumask_of_node(n));
+			cpumask_copy(masks + curvec,
+				     node_to_present_cpumask[n]);
 			if (++curvec == last_affv)
 				break;
 		}
@@ -101,7 +102,7 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
 		vecs_per_node = (affv - (curvec - affd->pre_vectors)) / nodes;
 
 		/* Get the cpus on this node which are in the mask */
-		cpumask_and(nmsk, cpu_online_mask, cpumask_of_node(n));
+		cpumask_and(nmsk, cpu_present_mask, node_to_present_cpumask[n]);
 
 		/* Calculate the number of cpus per vector */
 		ncpus = cpumask_weight(nmsk);
@@ -128,8 +129,6 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
 	}
 
 done:
-	put_online_cpus();
-
 	/* Fill out vectors at the end that don't need affinity */
 	for (; curvec < nvecs; curvec++)
 		cpumask_copy(masks + curvec, irq_default_affinity);
@@ -147,12 +146,26 @@ int irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd)
 {
 	int resv = affd->pre_vectors + affd->post_vectors;
 	int vecs = maxvec - resv;
-	int cpus;
 
-	/* Stabilize the cpumasks */
-	get_online_cpus();
-	cpus = cpumask_weight(cpu_online_mask);
-	put_online_cpus();
+	return min_t(int, cpumask_weight(cpu_present_mask), vecs) + resv;
+}
+
+static int __init irq_build_cpumap(void)
+{
+	int node, cpu;
+
+	for (node = 0; node < nr_node_ids; node++) {
+		if (!zalloc_cpumask_var(&node_to_present_cpumask[node],
+				GFP_KERNEL))
+			panic("can't allocate early memory\n");
+	}
 
-	return min(cpus, vecs) + resv;
+	for_each_present_cpu(cpu) {
+		node = cpu_to_node(cpu);
+		cpumask_set_cpu(cpu, node_to_present_cpumask[node]);
+	}
+
+	return 0;
 }
+
+subsys_initcall(irq_build_cpumap);
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1646390 — Re: [PATCH 2/7] genirq/affinity: assign vectors to all present CPUs

FromThomas Gleixner <tglx@linutronix.de>
Date2017-05-21 20:40 +0200
SubjectRe: [PATCH 2/7] genirq/affinity: assign vectors to all present CPUs
Message-ID<tJDVL-2VV-1@gated-at.bofh.it>
In reply to#1645406
On Fri, 19 May 2017, Christoph Hellwig wrote:
> -	/* Stabilize the cpumasks */
> -	get_online_cpus();

How is that protected against physical CPU hotplug? Physical CPU hotplug
manipulates the present mask.

> -	nodes = get_nodes_in_cpumask(cpu_online_mask, &nodemsk);
> +	nodes = get_nodes_in_cpumask(cpu_present_mask, &nodemsk);
> +static int __init irq_build_cpumap(void)
> +{
> +	int node, cpu;
> +
> +	for (node = 0; node < nr_node_ids; node++) {
> +		if (!zalloc_cpumask_var(&node_to_present_cpumask[node],
> +				GFP_KERNEL))
> +			panic("can't allocate early memory\n");
> +	}
>  
> -	return min(cpus, vecs) + resv;
> +	for_each_present_cpu(cpu) {
> +		node = cpu_to_node(cpu);
> +		cpumask_set_cpu(cpu, node_to_present_cpumask[node]);
> +	}

This mask needs updating on physical hotplug as well.

Thanks,

	tglx

[toc] | [prev] | [next] | [standalone]


#1647882 — Re: [PATCH 2/7] genirq/affinity: assign vectors to all present CPUs

FromChristoph Hellwig <hch@lst.de>
Date2017-05-23 11:40 +0200
SubjectRe: [PATCH 2/7] genirq/affinity: assign vectors to all present CPUs
Message-ID<tKesh-1hY-5@gated-at.bofh.it>
In reply to#1646390
On Sun, May 21, 2017 at 08:31:47PM +0200, Thomas Gleixner wrote:
> On Fri, 19 May 2017, Christoph Hellwig wrote:
> > -	/* Stabilize the cpumasks */
> > -	get_online_cpus();
> 
> How is that protected against physical CPU hotplug? Physical CPU hotplug
> manipulates the present mask.

It does indeed seem to.  Documentation/core-api/cpu_hotplug.rst claims
there are no locking rules for manipulations of cpu_present_mask,
maybe it needs and update to mention get/put_online_cpus() ?

Or maybe I should just switch to possible_cpu mask here like a lot of
code seems to do to avoid the hot plug issues, but that might be a bit
of a waste.

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web