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

Commit 1d99493b authored by David Woodhouse's avatar David Woodhouse Committed by Linus Torvalds
Browse files

Fix CONFIG_DEBUG_SHIRQ trigger on free_irq()



Andy Gospodarek pointed out that because we return in the middle of the
free_irq() function, we never actually do call the IRQ handler that just
got deregistered. This should fix it, although I expect Andrew will want
to convert those 'return's to 'break'. That's a separate change though.

Signed-off-by: default avatarDavid Woodhouse <dwmw2@infradead.org>
Cc: Andy Gospodarek <andy@greyhouse.net>
Cc: Fernando Luis Vzquez Cao <fernando@oss.ntt.co.jp>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent f13ef775
Loading
Loading
Loading
Loading
+15 −16
Original line number Diff line number Diff line
@@ -405,7 +405,6 @@ void free_irq(unsigned int irq, void *dev_id)
	struct irq_desc *desc;
	struct irqaction **p;
	unsigned long flags;
	irqreturn_t (*handler)(int, void *) = NULL;

	WARN_ON(in_interrupt());
	if (irq >= NR_IRQS)
@@ -445,28 +444,28 @@ void free_irq(unsigned int irq, void *dev_id)

			/* Make sure it's not being used on another CPU */
			synchronize_irq(irq);
			if (action->flags & IRQF_SHARED)
				handler = action->handler;
			kfree(action);
			return;
		}
		printk(KERN_ERR "Trying to free already-free IRQ %d\n", irq);
		spin_unlock_irqrestore(&desc->lock, flags);
		return;
	}
#ifdef CONFIG_DEBUG_SHIRQ
	if (handler) {
			/*
		 * It's a shared IRQ -- the driver ought to be prepared for it
		 * to happen even now it's being freed, so let's make sure....
		 * We do this after actually deregistering it, to make sure that
		 * a 'real' IRQ doesn't run in parallel with our fake
			 * It's a shared IRQ -- the driver ought to be
			 * prepared for it to happen even now it's
			 * being freed, so let's make sure....  We do
			 * this after actually deregistering it, to
			 * make sure that a 'real' IRQ doesn't run in
			 * parallel with our fake
			 */
			if (action->flags & IRQF_SHARED) {
				local_irq_save(flags);
		handler(irq, dev_id);
				action->handler(irq, dev_id);
				local_irq_restore(flags);
			}
#endif
			kfree(action);
			return;
		}
		printk(KERN_ERR "Trying to free already-free IRQ %d\n", irq);
		spin_unlock_irqrestore(&desc->lock, flags);
		return;
	}
}
EXPORT_SYMBOL(free_irq);