Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 47136855 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ config ARM
	select HARDIRQS_SW_RESEND
	select GENERIC_IRQ_PROBE
	select GENERIC_IRQ_SHOW
	select GENERIC_IRQ_PROBE
	select HARDIRQS_SW_RESEND
	select CPU_PM if (SUSPEND || CPU_IDLE)
	select GENERIC_PCI_IOMAP
	select HAVE_BPF_JIT
+0 −2
Original line number Diff line number Diff line
@@ -18,8 +18,6 @@ config HEXAGON
	select GENERIC_ATOMIC64
	select HAVE_PERF_EVENTS
	select HAVE_GENERIC_HARDIRQS
	select GENERIC_HARDIRQS_NO__DO_IRQ
	select GENERIC_HARDIRQS_NO_DEPRECATED
	# GENERIC_ALLOCATOR is used by dma_alloc_coherent()
	select GENERIC_ALLOCATOR
	select GENERIC_IRQ_SHOW
+4 −4
Original line number Diff line number Diff line
@@ -93,27 +93,27 @@ typedef irqreturn_t (*irq_handler_t)(int, void *);
/**
 * struct irqaction - per interrupt action descriptor
 * @handler:	interrupt handler function
 * @flags:	flags (see IRQF_* above)
 * @name:	name of the device
 * @dev_id:	cookie to identify the device
 * @percpu_dev_id:	cookie to identify the device
 * @next:	pointer to the next irqaction for shared interrupts
 * @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:	thread pointer for threaded interrupts
 * @thread_flags:	flags related to @thread
 * @thread_mask:	bitmask for keeping track of @thread activity
 * @dir:	pointer to the proc/irq/NN/name entry
 */
struct irqaction {
	irq_handler_t		handler;
	unsigned long		flags;
	void			*dev_id;
	void __percpu		*percpu_dev_id;
	struct irqaction	*next;
	int			irq;
	irq_handler_t		thread_fn;
	struct task_struct	*thread;
	unsigned int		irq;
	unsigned int		flags;
	unsigned long		thread_flags;
	unsigned long		thread_mask;
	const char		*name;
+3 −1
Original line number Diff line number Diff line
@@ -379,8 +379,10 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
	 * If its disabled or no action available
	 * 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;
	}

	handle_irq_event(desc);

+31 −15
Original line number Diff line number Diff line
@@ -565,7 +565,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
		 * IRQF_TRIGGER_* but the PIC does not support multiple
		 * 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");
		return 0;
	}
@@ -600,7 +600,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
		ret = 0;
		break;
	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);
	}
	if (unmask)
@@ -837,8 +837,7 @@ void exit_irq_thread(void)

	action = kthread_data(tsk);

	printk(KERN_ERR
	       "exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
	pr_err("genirq: exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
	       tsk->comm ? tsk->comm : "", tsk->pid, action->irq);

	desc = irq_to_desc(action->irq);
@@ -878,7 +877,6 @@ static int
__setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
{
	struct irqaction *old, **old_ptr;
	const char *old_name = NULL;
	unsigned long flags, thread_mask = 0;
	int ret, nested, shared = 0;
	cpumask_var_t mask;
@@ -972,10 +970,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
		 */
		if (!((old->flags & new->flags) & IRQF_SHARED) ||
		    ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK) ||
		    ((old->flags ^ new->flags) & IRQF_ONESHOT)) {
			old_name = old->name;
		    ((old->flags ^ new->flags) & IRQF_ONESHOT))
			goto mismatch;
		}

		/* All handlers must agree on per-cpuness */
		if ((old->flags & IRQF_PERCPU) !=
@@ -1031,6 +1027,27 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
		 * all existing action->thread_mask bits.
		 */
		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) {
@@ -1078,7 +1095,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)

		if (nmsk != omsk)
			/* 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);
	}

@@ -1115,14 +1132,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
	return 0;

mismatch:
#ifdef CONFIG_DEBUG_SHIRQ
	if (!(new->flags & IRQF_PROBE_SHARED)) {
		printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);
		if (old_name)
			printk(KERN_ERR "current handler: %s\n", old_name);
		pr_err("genirq: Flags mismatch irq %d. %08x (%s) vs. %08x (%s)\n",
		       irq, new->flags, new->name, old->flags, old->name);
#ifdef CONFIG_DEBUG_SHIRQ
		dump_stack();
	}
#endif
	}
	ret = -EBUSY;

out_mask:
Loading