Skip to content

Commit

Permalink
genirq: Warn when IRQ_NOAUTOEN is used with shared interrupts
Browse files Browse the repository at this point in the history
Shared interrupts do not go well with disabling auto enable:

1) The sharing interrupt might request it while it's still disabled and
   then wait for interrupts forever.

2) The interrupt might have been requested by the driver sharing the line
   before IRQ_NOAUTOEN has been set. So the driver which expects that
   disabled state after calling request_irq() will not get what it wants.
   Even worse, when it calls enable_irq() later, it will trigger the
   unbalanced enable_irq() warning.

Reported-by: Brian Norris <briannorris@chromium.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: dianders@chromium.org
Cc: jeffy <jeffy.chen@rock-chips.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: tfiga@chromium.org
Link: http://lkml.kernel.org/r/20170531100212.210682135@linutronix.de
  • Loading branch information
Thomas Gleixner committed Jun 4, 2017
1 parent 201d7f4 commit 04c848d
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 2 deletions.
7 changes: 7 additions & 0 deletions kernel/irq/chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,13 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set)

if (!desc)
return;

/*
* Warn when a driver sets the no autoenable flag on an already
* active interrupt.
*/
WARN_ON_ONCE(!desc->depth && (set & _IRQ_NOAUTOEN));

irq_settings_clr_and_set(desc, clr, set);

irqd_clear(&desc->irq_data, IRQD_NO_BALANCING | IRQD_PER_CPU |
Expand Down
12 changes: 10 additions & 2 deletions kernel/irq/manage.c
Original file line number Diff line number Diff line change
Expand Up @@ -1334,11 +1334,19 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
if (new->flags & IRQF_ONESHOT)
desc->istate |= IRQS_ONESHOT;

if (irq_settings_can_autoenable(desc))
if (irq_settings_can_autoenable(desc)) {
irq_startup(desc, true);
else
} else {
/*
* Shared interrupts do not go well with disabling
* auto enable. The sharing interrupt might request
* it while it's still disabled and then wait for
* interrupts forever.
*/
WARN_ON_ONCE(new->flags & IRQF_SHARED);
/* Undo nested disables: */
desc->depth = 1;
}

/* Exclude IRQ from balancing if requested */
if (new->flags & IRQF_NOBALANCING) {
Expand Down

0 comments on commit 04c848d

Please sign in to comment.