Skip to contentSkip to conversation

IRQ: Modularize the setup_irq code (1)

RFC PATCH New Ahmed S. Darwish 1 participant 2 messages Oct 5, 2007 IRQ

lore
Share & tools
lore
#0 lore raw

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

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.

---

 manage.c |   92 +++++++++++++++++++++++++++++++++++++--------------------------
 1 file changed, 55 insertions(+), 37 deletions(-)
kernel/irq/manage.c +55 -37
index 7230d91..6a0d778 100644
@@ -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;
 }
 
 /**
Signature · 3 lines
Ahmed S. Darwish
HomePage: http://darwish.07.googlepages.com
Blog: http://darwish-07.blogspot.com
#1 lore raw

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

Introduce irq_desc_match_fist_irqaction() to support setup_irq() code modularity.

---

Any ideas for a better method name ?

 manage.c |   89 ++++++++++++++++++++++++++++++++++++---------------------------
 1 file changed, 51 insertions(+), 38 deletions(-)
kernel/irq/manage.c +51 -38
index 6a0d778..4e96d56 100644
@@ -293,6 +293,55 @@ int can_add_irqaction_on_allocated_irq(unsigned int irq, struct irqaction *new)
 }
 
 /*
+ * Configure the passed irq descriptor to satisfy our first newly
+ * added irqaction needs
+ * must be called with the irq_desc[irq]->lock held
+ */
+void irq_desc_match_fist_irqaction(unsigned int irq, struct irqaction *new)
+{
+	struct irq_desc *desc = irq_desc + irq;
+
+	/* We must be the first and the only irqaction */
+	BUG_ON(desc->action != new || new->next);
+
+	irq_chip_set_defaults(desc->chip);
+
+#if defined(CONFIG_IRQ_PER_CPU)
+	if (new->flags & IRQF_PERCPU)
+		desc->status |= IRQ_PER_CPU;
+#endif
+
+	/* Setup the type (level, edge polarity) if configured: */
+	if (new->flags & IRQF_TRIGGER_MASK) {
+		if (desc->chip && desc->chip->set_type)
+			desc->chip->set_type(irq,
+					     new->flags & IRQF_TRIGGER_MASK);
+		else
+			/*
+			 * IRQF_TRIGGER_* but the PIC does not support
+			 * multiple flow-types?
+			 */
+			printk(KERN_WARNING "No IRQF_TRIGGER set_type "
+			       "function for IRQ %d (%s)\n", irq,
+			       desc->chip ? desc->chip->name : "unknown");
+	} else
+		compat_irq_chip_set_default_handler(desc);
+
+	desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
+
+	if (!(desc->status & IRQ_NOAUTOEN)) {
+		desc->depth = 0;
+		desc->status &= ~IRQ_DISABLED;
+		if (desc->chip->startup)
+			desc->chip->startup(irq);
+		else
+			desc->chip->enable(irq);
+	} else
+		/* Undo nested disables: */
+		desc->depth = 1;
+}
+
+/*
  * Internal function to register an irqaction - typically used to
  * allocate special interrupts that are part of the architecture.
  */
@@ -352,45 +401,9 @@ int setup_irq(unsigned int irq, struct irqaction *new)
 	if (new->flags & IRQF_NOBALANCING)
 		desc->status |= IRQ_NO_BALANCING;
 
-	if (!shared) {
-		irq_chip_set_defaults(desc->chip);
+	if (!shared)
+		irq_desc_match_fist_irqaction(irq, new);
 
-#if defined(CONFIG_IRQ_PER_CPU)
-		if (new->flags & IRQF_PERCPU)
-			desc->status |= IRQ_PER_CPU;
-#endif
-
-		/* Setup the type (level, edge polarity) if configured: */
-		if (new->flags & IRQF_TRIGGER_MASK) {
-			if (desc->chip && desc->chip->set_type)
-				desc->chip->set_type(irq,
-						new->flags & IRQF_TRIGGER_MASK);
-			else
-				/*
-				 * IRQF_TRIGGER_* but the PIC does not support
-				 * multiple flow-types?
-				 */
-				printk(KERN_WARNING "No IRQF_TRIGGER set_type "
-				       "function for IRQ %d (%s)\n", irq,
-				       desc->chip ? desc->chip->name :
-				       "unknown");
-		} else
-			compat_irq_chip_set_default_handler(desc);
-
-		desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING |
-				  IRQ_INPROGRESS);
-
-		if (!(desc->status & IRQ_NOAUTOEN)) {
-			desc->depth = 0;
-			desc->status &= ~IRQ_DISABLED;
-			if (desc->chip->startup)
-				desc->chip->startup(irq);
-			else
-				desc->chip->enable(irq);
-		} else
-			/* Undo nested disables: */
-			desc->depth = 1;
-	}
 	/* Reset broken irq detection when installing new handler */
 	desc->irq_count = 0;
 	desc->irqs_unhandled = 0;
Signature · 3 lines
Ahmed S. Darwish
HomePage: http://darwish.07.googlepages.com
Blog: http://darwish-07.blogspot.com