Skip to content

Commit e509bd7

Browse files
westeriKAGA-KOKO
authored andcommitted
genirq: Allow migration of chained interrupts by installing default action
When a CPU is offlined all interrupts that have an action are migrated to other still online CPUs. However, if the interrupt has chained handler installed this is not done. Chained handlers are used by GPIO drivers which support interrupts, for instance. When the affinity is not corrected properly we end up in situation where most interrupts are not arriving to the online CPUs anymore. For example on Intel Braswell system which has SD-card card detection signal connected to a GPIO the IO-APIC routing entries look like below after CPU1 is offlined: pin30, enabled , level, low , V(52), IRR(0), S(0), logical , D(03), M(1) pin31, enabled , level, low , V(42), IRR(0), S(0), logical , D(03), M(1) pin32, enabled , level, low , V(62), IRR(0), S(0), logical , D(03), M(1) pin5b, enabled , level, low , V(72), IRR(0), S(0), logical , D(03), M(1) The problem here is that the destination mask still contains both CPUs even if CPU1 is already offline. This means that the IO-APIC still routes interrupts to the other CPU as well. We solve the problem by providing a default action for chained interrupts. This action allows the migration code to correct affinity (as it finds desc->action != NULL). Also make the default action handler to emit a warning if for some reason a chained handler ends up calling it. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Cc: Jiang Liu <jiang.liu@linux.intel.com> Link: http://lkml.kernel.org/r/1444039935-30475-1-git-send-email-mika.westerberg@linux.intel.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
1 parent 9e7e2b0 commit e509bd7

File tree

3 files changed

+20
-1
lines changed

3 files changed

+20
-1
lines changed

kernel/irq/chip.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@
2121

2222
#include "internals.h"
2323

24+
static irqreturn_t bad_chained_irq(int irq, void *dev_id)
25+
{
26+
WARN_ONCE(1, "Chained irq %d should not call an action\n", irq);
27+
return IRQ_NONE;
28+
}
29+
30+
/*
31+
* Chained handlers should never call action on their IRQ. This default
32+
* action will emit warning if such thing happens.
33+
*/
34+
struct irqaction chained_action = {
35+
.handler = bad_chained_irq,
36+
};
37+
2438
/**
2539
* irq_set_chip - set the irq chip for an irq
2640
* @irq: irq number
@@ -746,6 +760,8 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle,
746760
if (desc->irq_data.chip != &no_irq_chip)
747761
mask_ack_irq(desc);
748762
irq_state_set_disabled(desc);
763+
if (is_chained)
764+
desc->action = NULL;
749765
desc->depth = 1;
750766
}
751767
desc->handle_irq = handle;
@@ -755,6 +771,7 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle,
755771
irq_settings_set_noprobe(desc);
756772
irq_settings_set_norequest(desc);
757773
irq_settings_set_nothread(desc);
774+
desc->action = &chained_action;
758775
irq_startup(desc, true);
759776
}
760777
}

kernel/irq/internals.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
extern bool noirqdebug;
2020

21+
extern struct irqaction chained_action;
22+
2123
/*
2224
* Bits used by threaded handlers:
2325
* IRQTF_RUNTHREAD - signals that the interrupt handler thread should run

kernel/irq/proc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ int show_interrupts(struct seq_file *p, void *v)
460460
for_each_online_cpu(j)
461461
any_count |= kstat_irqs_cpu(i, j);
462462
action = desc->action;
463-
if (!action && !any_count)
463+
if ((!action || action == &chained_action) && !any_count)
464464
goto out;
465465

466466
seq_printf(p, "%*d: ", prec, i);

0 commit comments

Comments
 (0)