Commit 47136855 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull core irq changes from Ingo Molnar:
 "A collection of small fixes."

By Thomas Gleixner
* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  hexagon: Remove select of not longer existing Kconfig switches
  arm: Select core options instead of redefining them
  genirq: Do not consider disabled wakeup irqs
  genirq: Allow check_wakeup_irqs to notice level-triggered interrupts
  genirq: Be more informative on irq type mismatch
  genirq: Reject bogus threaded irq requests
  genirq: Streamline irq_action
parents cb60e3e6 e0d8ffd1
...@@ -34,6 +34,8 @@ config ARM ...@@ -34,6 +34,8 @@ config ARM
select HARDIRQS_SW_RESEND select HARDIRQS_SW_RESEND
select GENERIC_IRQ_PROBE select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW select GENERIC_IRQ_SHOW
select GENERIC_IRQ_PROBE
select HARDIRQS_SW_RESEND
select CPU_PM if (SUSPEND || CPU_IDLE) select CPU_PM if (SUSPEND || CPU_IDLE)
select GENERIC_PCI_IOMAP select GENERIC_PCI_IOMAP
select HAVE_BPF_JIT select HAVE_BPF_JIT
......
...@@ -18,8 +18,6 @@ config HEXAGON ...@@ -18,8 +18,6 @@ config HEXAGON
select GENERIC_ATOMIC64 select GENERIC_ATOMIC64
select HAVE_PERF_EVENTS select HAVE_PERF_EVENTS
select HAVE_GENERIC_HARDIRQS select HAVE_GENERIC_HARDIRQS
select GENERIC_HARDIRQS_NO__DO_IRQ
select GENERIC_HARDIRQS_NO_DEPRECATED
# GENERIC_ALLOCATOR is used by dma_alloc_coherent() # GENERIC_ALLOCATOR is used by dma_alloc_coherent()
select GENERIC_ALLOCATOR select GENERIC_ALLOCATOR
select GENERIC_IRQ_SHOW select GENERIC_IRQ_SHOW
......
...@@ -93,27 +93,27 @@ typedef irqreturn_t (*irq_handler_t)(int, void *); ...@@ -93,27 +93,27 @@ typedef irqreturn_t (*irq_handler_t)(int, void *);
/** /**
* struct irqaction - per interrupt action descriptor * struct irqaction - per interrupt action descriptor
* @handler: interrupt handler function * @handler: interrupt handler function
* @flags: flags (see IRQF_* above)
* @name: name of the device * @name: name of the device
* @dev_id: cookie to identify the device * @dev_id: cookie to identify the device
* @percpu_dev_id: cookie to identify the device * @percpu_dev_id: cookie to identify the device
* @next: pointer to the next irqaction for shared interrupts * @next: pointer to the next irqaction for shared interrupts
* @irq: interrupt number * @irq: interrupt number
* @dir: pointer to the proc/irq/NN/name entry * @flags: flags (see IRQF_* above)
* @thread_fn: interrupt handler function for threaded interrupts * @thread_fn: interrupt handler function for threaded interrupts
* @thread: thread pointer for threaded interrupts * @thread: thread pointer for threaded interrupts
* @thread_flags: flags related to @thread * @thread_flags: flags related to @thread
* @thread_mask: bitmask for keeping track of @thread activity * @thread_mask: bitmask for keeping track of @thread activity
* @dir: pointer to the proc/irq/NN/name entry
*/ */
struct irqaction { struct irqaction {
irq_handler_t handler; irq_handler_t handler;
unsigned long flags;
void *dev_id; void *dev_id;
void __percpu *percpu_dev_id; void __percpu *percpu_dev_id;
struct irqaction *next; struct irqaction *next;
int irq;
irq_handler_t thread_fn; irq_handler_t thread_fn;
struct task_struct *thread; struct task_struct *thread;
unsigned int irq;
unsigned int flags;
unsigned long thread_flags; unsigned long thread_flags;
unsigned long thread_mask; unsigned long thread_mask;
const char *name; const char *name;
......
...@@ -379,8 +379,10 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) ...@@ -379,8 +379,10 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
* If its disabled or no action available * If its disabled or no action available
* keep it masked and get out of here * keep it masked and get out of here
*/ */
if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
desc->istate |= IRQS_PENDING;
goto out_unlock; goto out_unlock;
}
handle_irq_event(desc); handle_irq_event(desc);
......
...@@ -565,7 +565,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, ...@@ -565,7 +565,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
* IRQF_TRIGGER_* but the PIC does not support multiple * IRQF_TRIGGER_* but the PIC does not support multiple
* flow-types? * flow-types?
*/ */
pr_debug("No set_type function for IRQ %d (%s)\n", irq, pr_debug("genirq: No set_type function for IRQ %d (%s)\n", irq,
chip ? (chip->name ? : "unknown") : "unknown"); chip ? (chip->name ? : "unknown") : "unknown");
return 0; return 0;
} }
...@@ -600,7 +600,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, ...@@ -600,7 +600,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
ret = 0; ret = 0;
break; break;
default: default:
pr_err("setting trigger mode %lu for irq %u failed (%pF)\n", pr_err("genirq: Setting trigger mode %lu for irq %u failed (%pF)\n",
flags, irq, chip->irq_set_type); flags, irq, chip->irq_set_type);
} }
if (unmask) if (unmask)
...@@ -837,8 +837,7 @@ void exit_irq_thread(void) ...@@ -837,8 +837,7 @@ void exit_irq_thread(void)
action = kthread_data(tsk); action = kthread_data(tsk);
printk(KERN_ERR pr_err("genirq: exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
"exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
tsk->comm ? tsk->comm : "", tsk->pid, action->irq); tsk->comm ? tsk->comm : "", tsk->pid, action->irq);
desc = irq_to_desc(action->irq); desc = irq_to_desc(action->irq);
...@@ -878,7 +877,6 @@ static int ...@@ -878,7 +877,6 @@ static int
__setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
{ {
struct irqaction *old, **old_ptr; struct irqaction *old, **old_ptr;
const char *old_name = NULL;
unsigned long flags, thread_mask = 0; unsigned long flags, thread_mask = 0;
int ret, nested, shared = 0; int ret, nested, shared = 0;
cpumask_var_t mask; cpumask_var_t mask;
...@@ -972,10 +970,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) ...@@ -972,10 +970,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
*/ */
if (!((old->flags & new->flags) & IRQF_SHARED) || if (!((old->flags & new->flags) & IRQF_SHARED) ||
((old->flags ^ new->flags) & IRQF_TRIGGER_MASK) || ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK) ||
((old->flags ^ new->flags) & IRQF_ONESHOT)) { ((old->flags ^ new->flags) & IRQF_ONESHOT))
old_name = old->name;
goto mismatch; goto mismatch;
}
/* All handlers must agree on per-cpuness */ /* All handlers must agree on per-cpuness */
if ((old->flags & IRQF_PERCPU) != if ((old->flags & IRQF_PERCPU) !=
...@@ -1031,6 +1027,27 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) ...@@ -1031,6 +1027,27 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
* all existing action->thread_mask bits. * all existing action->thread_mask bits.
*/ */
new->thread_mask = 1 << ffz(thread_mask); new->thread_mask = 1 << ffz(thread_mask);
} else if (new->handler == irq_default_primary_handler) {
/*
* The interrupt was requested with handler = NULL, so
* we use the default primary handler for it. But it
* does not have the oneshot flag set. In combination
* with level interrupts this is deadly, because the
* default primary handler just wakes the thread, then
* the irq lines is reenabled, but the device still
* has the level irq asserted. Rinse and repeat....
*
* While this works for edge type interrupts, we play
* it safe and reject unconditionally because we can't
* say for sure which type this interrupt really
* has. The type flags are unreliable as the
* underlying chip implementation can override them.
*/
pr_err("genirq: Threaded irq requested with handler=NULL and !ONESHOT for irq %d\n",
irq);
ret = -EINVAL;
goto out_mask;
} }
if (!shared) { if (!shared) {
...@@ -1078,7 +1095,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) ...@@ -1078,7 +1095,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
if (nmsk != omsk) if (nmsk != omsk)
/* hope the handler works with current trigger mode */ /* hope the handler works with current trigger mode */
pr_warning("IRQ %d uses trigger mode %u; requested %u\n", pr_warning("genirq: irq %d uses trigger mode %u; requested %u\n",
irq, nmsk, omsk); irq, nmsk, omsk);
} }
...@@ -1115,14 +1132,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) ...@@ -1115,14 +1132,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
return 0; return 0;
mismatch: mismatch:
#ifdef CONFIG_DEBUG_SHIRQ
if (!(new->flags & IRQF_PROBE_SHARED)) { if (!(new->flags & IRQF_PROBE_SHARED)) {
printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq); pr_err("genirq: Flags mismatch irq %d. %08x (%s) vs. %08x (%s)\n",
if (old_name) irq, new->flags, new->name, old->flags, old->name);
printk(KERN_ERR "current handler: %s\n", old_name); #ifdef CONFIG_DEBUG_SHIRQ
dump_stack(); dump_stack();
}
#endif #endif
}
ret = -EBUSY; ret = -EBUSY;
out_mask: out_mask:
......
...@@ -103,8 +103,13 @@ int check_wakeup_irqs(void) ...@@ -103,8 +103,13 @@ int check_wakeup_irqs(void)
int irq; int irq;
for_each_irq_desc(irq, desc) { for_each_irq_desc(irq, desc) {
/*
* Only interrupts which are marked as wakeup source
* and have not been disabled before the suspend check
* can abort suspend.
*/
if (irqd_is_wakeup_set(&desc->irq_data)) { if (irqd_is_wakeup_set(&desc->irq_data)) {
if (desc->istate & IRQS_PENDING) if (desc->depth == 1 && desc->istate & IRQS_PENDING)
return -EBUSY; return -EBUSY;
continue; continue;
} }
......
...@@ -58,10 +58,13 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq) ...@@ -58,10 +58,13 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq)
/* /*
* We do not resend level type interrupts. Level type * We do not resend level type interrupts. Level type
* interrupts are resent by hardware when they are still * interrupts are resent by hardware when they are still
* active. * active. Clear the pending bit so suspend/resume does not
* get confused.
*/ */
if (irq_settings_is_level(desc)) if (irq_settings_is_level(desc)) {
desc->istate &= ~IRQS_PENDING;
return; return;
}
if (desc->istate & IRQS_REPLAY) if (desc->istate & IRQS_REPLAY)
return; return;
if (desc->istate & IRQS_PENDING) { if (desc->istate & IRQS_PENDING) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment