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

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

Merge branch 'irq-urgent-for-linus' of...

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

* 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  genirq: Ensure we locate the passed IRQ in irq_alloc_descs()
  genirq: Fix descriptor init on non-sparse IRQs
  irq: Handle spurios irq detection for threaded irqs
  genirq: Print threaded handler in spurious debug output
parents d681f120 c5182b88
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -8,9 +8,9 @@
 * @IRQ_WAKE_THREAD	handler requests to wake the handler thread
 */
enum irqreturn {
	IRQ_NONE,
	IRQ_HANDLED,
	IRQ_WAKE_THREAD,
	IRQ_NONE		= (0 << 0),
	IRQ_HANDLED		= (1 << 0),
	IRQ_WAKE_THREAD		= (1 << 1),
};

typedef enum irqreturn irqreturn_t;
+0 −6
Original line number Diff line number Diff line
@@ -132,12 +132,6 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)

		switch (res) {
		case IRQ_WAKE_THREAD:
			/*
			 * Set result to handled so the spurious check
			 * does not trigger.
			 */
			res = IRQ_HANDLED;

			/*
			 * Catch drivers which return WAKE_THREAD but
			 * did not set up a thread function
+9 −5
Original line number Diff line number Diff line
@@ -257,13 +257,11 @@ int __init early_irq_init(void)
	count = ARRAY_SIZE(irq_desc);

	for (i = 0; i < count; i++) {
		desc[i].irq_data.irq = i;
		desc[i].irq_data.chip = &no_irq_chip;
		desc[i].kstat_irqs = alloc_percpu(unsigned int);
		irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS);
		alloc_masks(desc + i, GFP_KERNEL, node);
		desc_smp_init(desc + i, node);
		alloc_masks(&desc[i], GFP_KERNEL, node);
		raw_spin_lock_init(&desc[i].lock);
		lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
		desc_set_defaults(i, &desc[i], node);
	}
	return arch_early_irq_init();
}
@@ -346,6 +344,12 @@ irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node)
	if (!cnt)
		return -EINVAL;

	if (irq >= 0) {
		if (from > irq)
			return -EINVAL;
		from = irq;
	}

	mutex_lock(&sparse_irq_lock);

	start = bitmap_find_next_zero_area(allocated_irqs, IRQ_BITMAP_BITS,
+18 −6
Original line number Diff line number Diff line
@@ -723,13 +723,16 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { }
 * context. So we need to disable bh here to avoid deadlocks and other
 * side effects.
 */
static void
static irqreturn_t
irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action)
{
	irqreturn_t ret;

	local_bh_disable();
	action->thread_fn(action->irq, action->dev_id);
	ret = action->thread_fn(action->irq, action->dev_id);
	irq_finalize_oneshot(desc, action, false);
	local_bh_enable();
	return ret;
}

/*
@@ -737,10 +740,14 @@ irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action)
 * preemtible - many of them need to sleep and wait for slow busses to
 * complete.
 */
static void irq_thread_fn(struct irq_desc *desc, struct irqaction *action)
static irqreturn_t irq_thread_fn(struct irq_desc *desc,
		struct irqaction *action)
{
	action->thread_fn(action->irq, action->dev_id);
	irqreturn_t ret;

	ret = action->thread_fn(action->irq, action->dev_id);
	irq_finalize_oneshot(desc, action, false);
	return ret;
}

/*
@@ -753,7 +760,8 @@ static int irq_thread(void *data)
	};
	struct irqaction *action = data;
	struct irq_desc *desc = irq_to_desc(action->irq);
	void (*handler_fn)(struct irq_desc *desc, struct irqaction *action);
	irqreturn_t (*handler_fn)(struct irq_desc *desc,
			struct irqaction *action);
	int wake;

	if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD,
@@ -783,8 +791,12 @@ static int irq_thread(void *data)
			desc->istate |= IRQS_PENDING;
			raw_spin_unlock_irq(&desc->lock);
		} else {
			irqreturn_t action_ret;

			raw_spin_unlock_irq(&desc->lock);
			handler_fn(desc, action);
			action_ret = handler_fn(desc, action);
			if (!noirqdebug)
				note_interrupt(action->irq, desc, action_ret);
		}

		wake = atomic_dec_and_test(&desc->threads_active);
+23 −8
Original line number Diff line number Diff line
@@ -167,6 +167,13 @@ static void poll_spurious_irqs(unsigned long dummy)
		  jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
}

static inline int bad_action_ret(irqreturn_t action_ret)
{
	if (likely(action_ret <= (IRQ_HANDLED | IRQ_WAKE_THREAD)))
		return 0;
	return 1;
}

/*
 * If 99,900 of the previous 100,000 interrupts have not been handled
 * then assume that the IRQ is stuck in some manner. Drop a diagnostic
@@ -182,7 +189,7 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc,
	struct irqaction *action;
	unsigned long flags;

	if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
	if (bad_action_ret(action_ret)) {
		printk(KERN_ERR "irq event %d: bogus return value %x\n",
				irq, action_ret);
	} else {
@@ -201,10 +208,11 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc,
	raw_spin_lock_irqsave(&desc->lock, flags);
	action = desc->action;
	while (action) {
		printk(KERN_ERR "[<%p>]", action->handler);
		print_symbol(" (%s)",
			(unsigned long)action->handler);
		printk("\n");
		printk(KERN_ERR "[<%p>] %pf", action->handler, action->handler);
		if (action->thread_fn)
			printk(KERN_CONT " threaded [<%p>] %pf",
					action->thread_fn, action->thread_fn);
		printk(KERN_CONT "\n");
		action = action->next;
	}
	raw_spin_unlock_irqrestore(&desc->lock, flags);
@@ -262,7 +270,16 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
	if (desc->istate & IRQS_POLL_INPROGRESS)
		return;

	if (unlikely(action_ret != IRQ_HANDLED)) {
	/* we get here again via the threaded handler */
	if (action_ret == IRQ_WAKE_THREAD)
		return;

	if (bad_action_ret(action_ret)) {
		report_bad_irq(irq, desc, action_ret);
		return;
	}

	if (unlikely(action_ret == IRQ_NONE)) {
		/*
		 * If we are seeing only the odd spurious IRQ caused by
		 * bus asynchronicity then don't eventually trigger an error,
@@ -274,8 +291,6 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
		else
			desc->irqs_unhandled++;
		desc->last_unhandled = jiffies;
		if (unlikely(action_ret != IRQ_NONE))
			report_bad_irq(irq, desc, action_ret);
	}

	if (unlikely(try_misrouted_irq(irq, desc, action_ret))) {