From: Daniel Wagner <[email protected]> Pass a cpumask to irq_create_affinity_masks as an additional constraint to consider when creating the affinity masks. This allows the caller to exclude specific CPUs, e.g., isolated CPUs (see the 'isolcpus' kernel command-line parameter).
Signed-off-by: Daniel Wagner <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> Signed-off-by: Aaron Tomlin <[email protected]> --- include/linux/interrupt.h | 16 ++++++++++------ kernel/irq/affinity.c | 12 ++++++++++-- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 6cd26ffb0505..afd5a2c75b43 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -287,18 +287,22 @@ struct irq_affinity_notify { * @nr_sets: The number of interrupt sets for which affinity * spreading is required * @set_size: Array holding the size of each interrupt set + * @mask: cpumask that constrains which CPUs to consider when + * calculating the number and size of the interrupt sets * @calc_sets: Callback for calculating the number and size * of interrupt sets * @priv: Private data for usage by @calc_sets, usually a * pointer to driver/device specific data. */ struct irq_affinity { - unsigned int pre_vectors; - unsigned int post_vectors; - unsigned int nr_sets; - unsigned int set_size[IRQ_AFFINITY_MAX_SETS]; - void (*calc_sets)(struct irq_affinity *, unsigned int nvecs); - void *priv; + unsigned int pre_vectors; + unsigned int post_vectors; + unsigned int nr_sets; + unsigned int set_size[IRQ_AFFINITY_MAX_SETS]; + const struct cpumask *mask; + void (*calc_sets)(struct irq_affinity *, + unsigned int nvecs); + void *priv; }; /** diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c index 78f2418a8925..e0cf70a99339 100644 --- a/kernel/irq/affinity.c +++ b/kernel/irq/affinity.c @@ -70,7 +70,13 @@ irq_create_affinity_masks(unsigned int nvecs, struct irq_affinity *affd) */ for (i = 0, usedvecs = 0; i < affd->nr_sets; i++) { unsigned int nr_masks, this_vecs = affd->set_size[i]; - struct cpumask *result = group_cpus_evenly(this_vecs, &nr_masks); + struct cpumask *result; + + if (affd->mask) + result = group_mask_cpus_evenly(this_vecs, affd->mask, + &nr_masks); + else + result = group_cpus_evenly(this_vecs, &nr_masks); if (!result) { kfree(masks); @@ -115,7 +121,9 @@ unsigned int irq_calc_affinity_vectors(unsigned int minvec, unsigned int maxvec, if (resv > minvec) return 0; - if (affd->calc_sets) + if (affd->mask) + set_vecs = cpumask_weight(affd->mask); + else if (affd->calc_sets) set_vecs = maxvec - resv; else set_vecs = cpumask_weight(cpu_possible_mask); -- 2.51.0

