Skip to content

Commit

Permalink
genirq: Add force argument to irq_startup()
Browse files Browse the repository at this point in the history
In order to handle managed interrupts gracefully on irq_startup() so they
won't lose their assigned affinity, it's necessary to allow startups which
keep the interrupts in managed shutdown state, if none of the assigend CPUs
is online. This allows drivers to request interrupts w/o the CPUs being
online, which avoid online/offline churn in drivers.

Add a force argument which can override that decision and let only
request_irq() and enable_irq() allow the managed shutdown
handling. enable_irq() is required, because the interrupt might be
requested with IRQF_NOAUTOEN and enable_irq() invokes irq_startup() which
would then wreckage the assignment again. All other callers force startup
and potentially break the assigned affinity.

No functional change as this only adds the function argument.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Keith Busch <keith.busch@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Christoph Hellwig <hch@lst.de>
Link: http://lkml.kernel.org/r/20170619235447.112094565@linutronix.de
  • Loading branch information
Thomas Gleixner committed Jun 22, 2017
1 parent 708d174 commit 4cde9c6
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 7 deletions.
4 changes: 2 additions & 2 deletions kernel/irq/autoprobe.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ unsigned long probe_irq_on(void)
if (desc->irq_data.chip->irq_set_type)
desc->irq_data.chip->irq_set_type(&desc->irq_data,
IRQ_TYPE_PROBE);
irq_startup(desc, false);
irq_startup(desc, IRQ_NORESEND, IRQ_START_FORCE);
}
raw_spin_unlock_irq(&desc->lock);
}
Expand All @@ -70,7 +70,7 @@ unsigned long probe_irq_on(void)
raw_spin_lock_irq(&desc->lock);
if (!desc->action && irq_settings_can_probe(desc)) {
desc->istate |= IRQS_AUTODETECT | IRQS_WAITING;
if (irq_startup(desc, false))
if (irq_startup(desc, IRQ_NORESEND, IRQ_START_FORCE))
desc->istate |= IRQS_PENDING;
}
raw_spin_unlock_irq(&desc->lock);
Expand Down
4 changes: 2 additions & 2 deletions kernel/irq/chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ static int __irq_startup(struct irq_desc *desc)
return ret;
}

int irq_startup(struct irq_desc *desc, bool resend)
int irq_startup(struct irq_desc *desc, bool resend, bool force)
{
int ret = 0;

Expand Down Expand Up @@ -892,7 +892,7 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle,
irq_settings_set_norequest(desc);
irq_settings_set_nothread(desc);
desc->action = &chained_action;
irq_startup(desc, true);
irq_startup(desc, IRQ_RESEND, IRQ_START_FORCE);
}
}

Expand Down
9 changes: 8 additions & 1 deletion kernel/irq/internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,14 @@ extern int __irq_set_trigger(struct irq_desc *desc, unsigned long flags);
extern void __disable_irq(struct irq_desc *desc);
extern void __enable_irq(struct irq_desc *desc);

extern int irq_startup(struct irq_desc *desc, bool resend);
#define IRQ_RESEND true
#define IRQ_NORESEND false

#define IRQ_START_FORCE true
#define IRQ_START_COND false

extern int irq_startup(struct irq_desc *desc, bool resend, bool force);

extern void irq_shutdown(struct irq_desc *desc);
extern void irq_enable(struct irq_desc *desc);
extern void irq_disable(struct irq_desc *desc);
Expand Down
4 changes: 2 additions & 2 deletions kernel/irq/manage.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ void __enable_irq(struct irq_desc *desc)
* time. If it was already started up, then irq_startup()
* will invoke irq_enable() under the hood.
*/
irq_startup(desc, true);
irq_startup(desc, IRQ_RESEND, IRQ_START_COND);
break;
}
default:
Expand Down Expand Up @@ -1306,7 +1306,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
}

if (irq_settings_can_autoenable(desc)) {
irq_startup(desc, true);
irq_startup(desc, IRQ_RESEND, IRQ_START_COND);
} else {
/*
* Shared interrupts do not go well with disabling
Expand Down

0 comments on commit 4cde9c6

Please sign in to comment.