diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-21 10:39:58 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-21 10:39:58 -0800 |
commit | 66f816241895dc8a1614c1114c0a97b167e4ce64 (patch) | |
tree | dbbfe6fe049e3e44a25020c2df0a312704175d37 /kernel | |
parent | d517bb79f4994a87cfc2ddd4cc76bd1a627d4bed (diff) | |
parent | a0c9259dc4e1923a98356967ce8b732da1979df8 (diff) | |
download | linux-66f816241895dc8a1614c1114c0a97b167e4ce64.tar.bz2 |
Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq fix from Thomas Gleixner:
"A single fix for the new matrix allocator to prevent vector exhaustion
by certain network drivers which allocate gazillions of unused vectors
which cannot be put into reservation mode due to MSI and the lack of
MSI entry masking.
The fix/workaround is to spread the vectors across CPUs by searching
the supplied target CPU mask for the CPU with the smallest number of
allocated vectors"
* 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
irq/matrix: Spread interrupts on allocation
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/irq/matrix.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/kernel/irq/matrix.c b/kernel/irq/matrix.c index 0ba0dd8863a7..5187dfe809ac 100644 --- a/kernel/irq/matrix.c +++ b/kernel/irq/matrix.c @@ -321,15 +321,23 @@ void irq_matrix_remove_reserved(struct irq_matrix *m) int irq_matrix_alloc(struct irq_matrix *m, const struct cpumask *msk, bool reserved, unsigned int *mapped_cpu) { - unsigned int cpu; + unsigned int cpu, best_cpu, maxavl = 0; + struct cpumap *cm; + unsigned int bit; + best_cpu = UINT_MAX; for_each_cpu(cpu, msk) { - struct cpumap *cm = per_cpu_ptr(m->maps, cpu); - unsigned int bit; + cm = per_cpu_ptr(m->maps, cpu); - if (!cm->online) + if (!cm->online || cm->available <= maxavl) continue; + best_cpu = cpu; + maxavl = cm->available; + } + + if (maxavl) { + cm = per_cpu_ptr(m->maps, best_cpu); bit = matrix_alloc_area(m, cm, 1, false); if (bit < m->alloc_end) { cm->allocated++; @@ -338,8 +346,8 @@ int irq_matrix_alloc(struct irq_matrix *m, const struct cpumask *msk, m->global_available--; if (reserved) m->global_reserved--; - *mapped_cpu = cpu; - trace_irq_matrix_alloc(bit, cpu, m, cm); + *mapped_cpu = best_cpu; + trace_irq_matrix_alloc(bit, best_cpu, m, cm); return bit; } } |