Skip to content

Commit 2b32fc8

Browse files
computersforpeaceKAGA-KOKO
authored andcommitted
genirq/cpuhotplug: Rebalance managed interrupts across multi-CPU hotplug
Commit 788019e ("genirq: Retain disable depth for managed interrupts across CPU hotplug") intended to only decrement the disable depth once per managed shutdown, but instead it decrements for each CPU hotplug in the affinity mask, until its depth reaches a point where it finally gets re-started. For example, consider: 1. Interrupt is affine to CPU {M,N} 2. disable_irq() -> depth is 1 3. CPU M goes offline -> interrupt migrates to CPU N / depth is still 1 4. CPU N goes offline -> irq_shutdown() / depth is 2 5. CPU N goes online -> irq_restore_affinity_of_irq() -> irqd_is_managed_and_shutdown()==true -> irq_startup_managed() -> depth is 1 6. CPU M goes online -> irq_restore_affinity_of_irq() -> irqd_is_managed_and_shutdown()==true -> irq_startup_managed() -> depth is 0 *** BUG: driver expects the interrupt is still disabled *** -> irq_startup() -> irqd_clr_managed_shutdown() 7. enable_irq() -> depth underflow / unbalanced enable_irq() warning This should clear the managed-shutdown flag at step 6, so that further hotplugs don't cause further imbalance. Note: It might be cleaner to also remove the irqd_clr_managed_shutdown() invocation from __irq_startup_managed(). But this is currently not possible because of irq_update_affinity_desc() as it sets IRQD_MANAGED_SHUTDOWN and expects irq_startup() to clear it. Fixes: 788019e ("genirq: Retain disable depth for managed interrupts across CPU hotplug") Reported-by: Aleksandrs Vinarskis <[email protected]> Signed-off-by: Brian Norris <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Tested-by: Aleksandrs Vinarskis <[email protected]> Link: https://lore.kernel.org/all/[email protected]
1 parent 19272b3 commit 2b32fc8

File tree

1 file changed

+8
-0
lines changed

1 file changed

+8
-0
lines changed

kernel/irq/chip.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,14 @@ __irq_startup_managed(struct irq_desc *desc, const struct cpumask *aff,
205205

206206
void irq_startup_managed(struct irq_desc *desc)
207207
{
208+
struct irq_data *d = irq_desc_get_irq_data(desc);
209+
210+
/*
211+
* Clear managed-shutdown flag, so we don't repeat managed-startup for
212+
* multiple hotplugs, and cause imbalanced disable depth.
213+
*/
214+
irqd_clr_managed_shutdown(d);
215+
208216
/*
209217
* Only start it up when the disable depth is 1, so that a disable,
210218
* hotunplug, hotplug sequence does not end up enabling it during

0 commit comments

Comments
 (0)