[PATCH RFC 1/2] IRQ: Modularize the setup_irq code (1)

From: Ahmed S. Darwish
Date: Fri Oct 05 2007 - 01:31:33 EST


Hi Thomas/lkml,

setup_irq() code contains a big chunk of 130 code lines that
can be divided to several smaller methods. These 2 patches introduce
those small functions to aid toward setup_irq() code modularity.
No major code logic changes exist.

Patches can be applied cleanly over v2.6.23-rc9.

Thanks,

==> (Description for Logs)

Introduce can_add_irqaction_on_allocated_irq and warn_about_irqaction_mismatch
methods to support setup_irq() code modularity.

Signed-off-by: Ahmed S. Darwish <darwish.07@xxxxxxxxx>
---

manage.c | 92 +++++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 55 insertions(+), 37 deletions(-)

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 7230d91..6a0d778 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -248,6 +248,50 @@ void compat_irq_chip_set_default_handler(struct irq_desc *desc)
desc->handle_irq = NULL;
}

+static inline void warn_about_irqaction_mismatch(unsigned int irq,
+ struct irqaction *new)
+{
+#ifdef CONFIG_DEBUG_SHIRQ
+ const char *name = irq_desc[irq].action->name;
+ /* If device doesn't expect the mismatch */
+ if (!(new->flags & IRQF_PROBE_SHARED)) {
+ printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);
+ if (name)
+ printk(KERN_ERR "current handler: %s\n", name);
+ dump_stack();
+ }
+#endif
+}
+
+/*
+ * Test if an irqaction can be added to the passed allocated IRQ line
+ * Must be called with the irq_desc[irq]->lock held.
+ */
+int can_add_irqaction_on_allocated_irq(unsigned int irq, struct irqaction *new)
+{
+ struct irqaction *old = irq_desc[irq].action;
+
+ BUG_ON(!old);
+ /*
+ * Can't share interrupts unless both agree to and are
+ * the same type (level, edge, polarity). So both flag
+ * fields must have IRQF_SHARED set and the bits which
+ * set the trigger type must match.
+ */
+ if (!((old->flags & new->flags) & IRQF_SHARED) ||
+ ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK))
+ return 0;
+
+#if defined(CONFIG_IRQ_PER_CPU)
+ /* All handlers must agree on per-cpuness */
+ if ((old->flags & IRQF_PERCPU) !=
+ (new->flags & IRQF_PERCPU))
+ return 0;
+#endif
+
+ return 1;
+}
+
/*
* Internal function to register an irqaction - typically used to
* allocate special interrupts that are part of the architecture.
@@ -256,7 +300,6 @@ int setup_irq(unsigned int irq, struct irqaction *new)
{
struct irq_desc *desc = irq_desc + irq;
struct irqaction *old, **p;
- const char *old_name = NULL;
unsigned long flags;
int shared = 0;

@@ -289,31 +332,18 @@ int setup_irq(unsigned int irq, struct irqaction *new)
p = &desc->action;
old = *p;
if (old) {
- /*
- * Can't share interrupts unless both agree to and are
- * the same type (level, edge, polarity). So both flag
- * fields must have IRQF_SHARED set and the bits which
- * set the trigger type must match.
- */
- if (!((old->flags & new->flags) & IRQF_SHARED) ||
- ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK)) {
- old_name = old->name;
- goto mismatch;
- }
-
-#if defined(CONFIG_IRQ_PER_CPU)
- /* All handlers must agree on per-cpuness */
- if ((old->flags & IRQF_PERCPU) !=
- (new->flags & IRQF_PERCPU))
- goto mismatch;
-#endif
-
- /* add new interrupt at end of irq queue */
- do {
- p = &old->next;
- old = *p;
- } while (old);
shared = 1;
+ if (can_add_irqaction_on_allocated_irq(irq, new)) {
+ /* add new interrupt at end of irq queue */
+ do {
+ p = &old->next;
+ old = *p;
+ } while (old);
+ } else {
+ warn_about_irqaction_mismatch(irq, new);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ return -EBUSY;
+ }
}

*p = new;
@@ -372,18 +402,6 @@ int setup_irq(unsigned int irq, struct irqaction *new)
register_handler_proc(irq, 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);
- dump_stack();
- }
-#endif
- spin_unlock_irqrestore(&desc->lock, flags);
- return -EBUSY;
}

/**


--
Ahmed S. Darwish
HomePage: http://darwish.07.googlepages.com
Blog: http://darwish-07.blogspot.com
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/