Skip to content

Commit 7f55f13

Browse files
KAGA-KOKOgregkh
authored andcommitted
genirq/matrix: Handle CPU offlining proper
commit 651ca2c upstream. At CPU hotunplug the corresponding per cpu matrix allocator is shut down and the allocated interrupt bits are discarded under the assumption that all allocated bits have been either migrated away or shut down through the managed interrupts mechanism. This is not true because interrupts which are not started up might have a vector allocated on the outgoing CPU. When the interrupt is started up later or completely shutdown and freed then the allocated vector is handed back, triggering warnings or causing accounting issues which result in suspend failures and other issues. Change the CPU hotplug mechanism of the matrix allocator so that the remaining allocations at unplug time are preserved and global accounting at hotplug is correctly readjusted to take the dormant vectors into account. Fixes: 2f75d9e ("genirq: Implement bitmap matrix allocator") Reported-by: Yuriy Vostrikov <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Tested-by: Yuriy Vostrikov <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Randy Dunlap <[email protected]> Cc: [email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 44975af commit 7f55f13

File tree

1 file changed

+14
-9
lines changed

1 file changed

+14
-9
lines changed

kernel/irq/matrix.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ struct cpumap {
1616
unsigned int available;
1717
unsigned int allocated;
1818
unsigned int managed;
19+
bool initialized;
1920
bool online;
2021
unsigned long alloc_map[IRQ_MATRIX_SIZE];
2122
unsigned long managed_map[IRQ_MATRIX_SIZE];
@@ -81,9 +82,11 @@ void irq_matrix_online(struct irq_matrix *m)
8182

8283
BUG_ON(cm->online);
8384

84-
bitmap_zero(cm->alloc_map, m->matrix_bits);
85-
cm->available = m->alloc_size - (cm->managed + m->systembits_inalloc);
86-
cm->allocated = 0;
85+
if (!cm->initialized) {
86+
cm->available = m->alloc_size;
87+
cm->available -= cm->managed + m->systembits_inalloc;
88+
cm->initialized = true;
89+
}
8790
m->global_available += cm->available;
8891
cm->online = true;
8992
m->online_maps++;
@@ -370,14 +373,16 @@ void irq_matrix_free(struct irq_matrix *m, unsigned int cpu,
370373
if (WARN_ON_ONCE(bit < m->alloc_start || bit >= m->alloc_end))
371374
return;
372375

373-
if (cm->online) {
374-
clear_bit(bit, cm->alloc_map);
375-
cm->allocated--;
376+
clear_bit(bit, cm->alloc_map);
377+
cm->allocated--;
378+
379+
if (cm->online)
376380
m->total_allocated--;
377-
if (!managed) {
378-
cm->available++;
381+
382+
if (!managed) {
383+
cm->available++;
384+
if (cm->online)
379385
m->global_available++;
380-
}
381386
}
382387
trace_irq_matrix_free(bit, cpu, m, cm);
383388
}

0 commit comments

Comments
 (0)