LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH 1/3] Delete unused irq functions on powerpc
@ 2006-12-06  5:15 Matthew Wilcox
  2006-12-06  5:15 ` [PATCH 2/3] Add the ability to template irq handlers in the generic irq code Matthew Wilcox
  0 siblings, 1 reply; 3+ messages in thread
From: Matthew Wilcox @ 2006-12-06  5:15 UTC (permalink / raw)
  To: linux-kernel; +Cc: parisc-linux, Matthew Wilcox, Benjamin Herrenschmidt

The ack_irq macro is unused and conflicts with James' work to template
the generic irq code.  mask_irq and unmask_irq are also unused, so delete
those macros too.

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
---
 include/asm-powerpc/hw_irq.h |   19 -------------------
 1 files changed, 0 insertions(+), 19 deletions(-)

diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
index d604863..9e4dd98 100644
--- a/include/asm-powerpc/hw_irq.h
+++ b/include/asm-powerpc/hw_irq.h
@@ -107,25 +107,6 @@ static inline void local_irq_save_ptr(un
 
 #endif /* CONFIG_PPC64 */
 
-#define mask_irq(irq)						\
-	({							\
-	 	irq_desc_t *desc = get_irq_desc(irq);		\
-		if (desc->chip && desc->chip->disable)	\
-			desc->chip->disable(irq);		\
-	})
-#define unmask_irq(irq)						\
-	({							\
-	 	irq_desc_t *desc = get_irq_desc(irq);		\
-		if (desc->chip && desc->chip->enable)	\
-			desc->chip->enable(irq);		\
-	})
-#define ack_irq(irq)						\
-	({							\
-	 	irq_desc_t *desc = get_irq_desc(irq);		\
-		if (desc->chip && desc->chip->ack)	\
-			desc->chip->ack(irq);		\
-	})
-
 /*
  * interrupt-retrigger: should we handle this via lost interrupts and IPIs
  * or should we not care like we do now ? --BenH.
-- 
1.4.3.3


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 2/3] Add the ability to template irq handlers in the generic irq code
  2006-12-06  5:15 [PATCH 1/3] Delete unused irq functions on powerpc Matthew Wilcox
@ 2006-12-06  5:15 ` Matthew Wilcox
  2006-12-06  5:15   ` [PATCH 3/3] Convert parisc to generic irq handling Matthew Wilcox
  0 siblings, 1 reply; 3+ messages in thread
From: Matthew Wilcox @ 2006-12-06  5:15 UTC (permalink / raw)
  To: linux-kernel; +Cc: parisc-linux, Matthew Wilcox, James Bottomley

On parisc, we have the issue that function call pointers are hugely
expensive, so we'd like to minimise their use in the interrupts.
Unfortunately, this involves directly calling the ack/eoi functions
instead of indirecting.  To permit this without losing the advantages of
centrally managed irq code, I introduced template builders for irq
handlers.  This allows us to construct special handlers on parisc that
don't indirect through function call pointers.

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>

Some fixes by Andrew Morton and Matthew Wilcox due to rapid code flux
in this area.

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
---
 kernel/irq/chip.c |  163 ++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 104 insertions(+), 59 deletions(-)

diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index ebfd24a..1b18c5c 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -17,6 +17,87 @@
 
 #include "internals.h"
 
+/* Helpers for constructing IRQ handlers */
+
+#ifdef CONFIG_SMP
+#define HANDLE_PERCPU_IRQ(NAME, ACK, EOI)				\
+void fastcall								\
+handle_percpu_irq##NAME(unsigned int irq, struct irq_desc *desc)	\
+{									\
+	irqreturn_t action_ret;						\
+									\
+	kstat_this_cpu.irqs[irq]++;					\
+									\
+	ACK(desc, irq);							\
+									\
+	action_ret = handle_IRQ_event(irq, desc->action);		\
+	if (!noirqdebug)						\
+		note_interrupt(irq, desc, action_ret);			\
+									\
+	EOI(desc,irq);							\
+}
+#else
+#define HANDLE_PERCPU_IRQ(NAME, ACK, END)
+#endif /* CONFIG_SMP */
+
+#define HANDLE_LEVEL_IRQ(NAME, MASK, UNMASK)				\
+void fastcall								\
+handle_level_irq##NAME(unsigned int irq, struct irq_desc *desc)		\
+{									\
+	unsigned int cpu = smp_processor_id();				\
+	struct irqaction *action;					\
+	irqreturn_t action_ret;						\
+									\
+	spin_lock(&desc->lock);						\
+	MASK(desc, irq);						\
+									\
+	if (unlikely(desc->status & IRQ_INPROGRESS))			\
+		goto out_unlock;					\
+	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);			\
+	kstat_cpu(cpu).irqs[irq]++;					\
+									\
+	/*								\
+	 * If its disabled or no action available			\
+	 * keep it masked and get out of here				\
+	 */								\
+	action = desc->action;						\
+	if (unlikely(!action || (desc->status & IRQ_DISABLED))) {	\
+		desc->status |= IRQ_PENDING;				\
+		goto out_unlock;					\
+	}								\
+									\
+	desc->status |= IRQ_INPROGRESS;					\
+	desc->status &= ~IRQ_PENDING;					\
+	spin_unlock(&desc->lock);					\
+									\
+	action_ret = handle_IRQ_event(irq, action);			\
+	if (!noirqdebug)						\
+		note_interrupt(irq, desc, action_ret);			\
+									\
+	spin_lock(&desc->lock);						\
+	desc->status &= ~IRQ_INPROGRESS;				\
+	UNMASK(desc,irq);						\
+out_unlock:								\
+	spin_unlock(&desc->lock);					\
+}
+
+#define HANDLE_SPECIFIC_IRQ(NAME, ACK, EOI, HANDLER)			\
+void fastcall								\
+handle_specific_irq##NAME(unsigned int irq, struct irq_desc *desc)	\
+{									\
+	irqreturn_t action_ret;						\
+									\
+	kstat_this_cpu.irqs[irq]++;					\
+									\
+	ACK(desc, irq);							\
+									\
+	action_ret = HANDLER(irq, desc->action->dev_id);		\
+	if (!noirqdebug)						\
+		note_interrupt(irq, desc, action_ret);			\
+									\
+	EOI(desc,irq);							\
+}
+
 /**
  *	dynamic_irq_init - initialize a dynamically allocated irq
  *	@irq:	irq number to initialize
@@ -247,6 +328,24 @@ static inline void mask_ack_irq(struct i
 	}
 }
 
+static inline void unmask_enabled_irq(struct irq_desc *desc, int irq)
+{
+	if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
+		desc->chip->unmask(irq);
+}
+
+static inline void ack_irq(struct irq_desc *desc, int irq)
+{
+	if (desc->chip->ack)
+		desc->chip->ack(irq);
+}
+
+static inline void eoi_irq(struct irq_desc *desc, int irq)
+{
+	if (desc->chip->eoi)
+		desc->chip->eoi(irq);
+}
+
 /**
  *	handle_simple_irq - Simple and software-decoded IRQs.
  *	@irq:	the interrupt number
@@ -300,46 +399,7 @@ out_unlock:
  *	it after the associated handler has acknowledged the device, so the
  *	interrupt line is back to inactive.
  */
-void fastcall
-handle_level_irq(unsigned int irq, struct irq_desc *desc)
-{
-	unsigned int cpu = smp_processor_id();
-	struct irqaction *action;
-	irqreturn_t action_ret;
-
-	spin_lock(&desc->lock);
-	mask_ack_irq(desc, irq);
-
-	if (unlikely(desc->status & IRQ_INPROGRESS))
-		goto out_unlock;
-	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
-	kstat_cpu(cpu).irqs[irq]++;
-
-	/*
-	 * If its disabled or no action available
-	 * keep it masked and get out of here
-	 */
-	action = desc->action;
-	if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
-		desc->status |= IRQ_PENDING;
-		goto out_unlock;
-	}
-
-	desc->status |= IRQ_INPROGRESS;
-	desc->status &= ~IRQ_PENDING;
-	spin_unlock(&desc->lock);
-
-	action_ret = handle_IRQ_event(irq, action);
-	if (!noirqdebug)
-		note_interrupt(irq, desc, action_ret);
-
-	spin_lock(&desc->lock);
-	desc->status &= ~IRQ_INPROGRESS;
-	if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
-		desc->chip->unmask(irq);
-out_unlock:
-	spin_unlock(&desc->lock);
-}
+HANDLE_LEVEL_IRQ(, mask_ack_irq, unmask_enabled_irq)
 
 /**
  *	handle_fasteoi_irq - irq handler for transparent controllers
@@ -472,7 +532,6 @@ out_unlock:
 	spin_unlock(&desc->lock);
 }
 
-#ifdef CONFIG_SMP
 /**
  *	handle_percpu_IRQ - Per CPU local irq handler
  *	@irq:	the interrupt number
@@ -480,25 +539,11 @@ out_unlock:
  *
  *	Per CPU interrupts on SMP machines without locking requirements
  */
-void fastcall
-handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
-{
-	irqreturn_t action_ret;
-
-	kstat_this_cpu.irqs[irq]++;
-
-	if (desc->chip->ack)
-		desc->chip->ack(irq);
+HANDLE_PERCPU_IRQ(, ack_irq, eoi_irq)
 
-	action_ret = handle_IRQ_event(irq, desc->action);
-	if (!noirqdebug)
-		note_interrupt(irq, desc, action_ret);
-
-	if (desc->chip->eoi)
-		desc->chip->eoi(irq);
-}
-
-#endif /* CONFIG_SMP */
+#ifdef ARCH_HAS_IRQ_HANDLERS
+#include <asm/irq-handlers.h>
+#endif
 
 void
 __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
-- 
1.4.3.3


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 3/3] Convert parisc to generic irq handling
  2006-12-06  5:15 ` [PATCH 2/3] Add the ability to template irq handlers in the generic irq code Matthew Wilcox
@ 2006-12-06  5:15   ` Matthew Wilcox
  0 siblings, 0 replies; 3+ messages in thread
From: Matthew Wilcox @ 2006-12-06  5:15 UTC (permalink / raw)
  To: linux-kernel; +Cc: parisc-linux, Matthew Wilcox, James Bottomley

Also make use of the specific ability to template interrupts for the
timer and IPI interrupts.

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>

Updated for pt_regs changes

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
---
 arch/parisc/kernel/irq.c          |   23 ++++++++++-------------
 drivers/parisc/iosapic.c          |    7 +++----
 include/asm-parisc/irq-handlers.h |   15 +++++++++++++++
 include/asm-parisc/irq.h          |   21 +++++++++++++++++++--
 4 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index b39c5b9..2a929a2 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -35,9 +35,6 @@
 
 #undef PARISC_IRQ_CR16_COUNTS
 
-extern irqreturn_t timer_interrupt(int, void *);
-extern irqreturn_t ipi_interrupt(int, void *);
-
 #define EIEM_MASK(irq)       (1UL<<(CPU_IRQ_MAX - irq))
 
 /* Bits in EIEM correlate with cpu_irq_action[].
@@ -88,7 +85,7 @@ static unsigned int cpu_startup_irq(unsi
 void no_ack_irq(unsigned int irq) { }
 void no_end_irq(unsigned int irq) { }
 
-void cpu_ack_irq(unsigned int irq)
+void cpu_ack_irq(struct irq_desc *dummy, unsigned int irq)
 {
 	unsigned long mask = EIEM_MASK(irq);
 	int cpu = smp_processor_id();
@@ -105,7 +102,7 @@ void cpu_ack_irq(unsigned int irq)
 	mtctl(mask, 23);
 }
 
-void cpu_end_irq(unsigned int irq)
+void cpu_end_irq(struct irq_desc *dummy, unsigned int irq)
 {
 	unsigned long mask = EIEM_MASK(irq);
 	int cpu = smp_processor_id();
@@ -155,8 +152,6 @@ static struct hw_interrupt_type cpu_inte
 	.shutdown	= cpu_disable_irq,
 	.enable		= cpu_enable_irq,
 	.disable	= cpu_disable_irq,
-	.ack		= cpu_ack_irq,
-	.end		= cpu_end_irq,
 #ifdef CONFIG_SMP
 	.set_affinity	= cpu_set_affinity_irq,
 #endif
@@ -253,8 +248,8 @@ int cpu_claim_irq(unsigned int irq, stru
 		return -EBUSY;
 
 	if (type) {
-		irq_desc[irq].chip = type;
-		irq_desc[irq].chip_data = data;
+		set_irq_chip(irq, type);
+		set_irq_chip_data(irq, data);
 		cpu_interrupt_type.enable(irq);
 	}
 	return 0;
@@ -377,7 +372,7 @@ void do_cpu_irq_mask(struct pt_regs *reg
 		goto set_out;
 	}
 #endif
-	__do_IRQ(irq);
+	generic_handle_irq(irq);
 
  out:
 	irq_exit();
@@ -406,15 +401,17 @@ static struct irqaction ipi_action = {
 static void claim_cpu_irqs(void)
 {
 	int i;
-	for (i = CPU_IRQ_BASE; i <= CPU_IRQ_MAX; i++) {
-		irq_desc[i].chip = &cpu_interrupt_type;
-	}
+	for (i = CPU_IRQ_BASE; i <= CPU_IRQ_MAX; i++)
+		set_irq_chip_and_handler(i, &cpu_interrupt_type,
+					 handle_level_irq_chip);
 
 	irq_desc[TIMER_IRQ].action = &timer_action;
 	irq_desc[TIMER_IRQ].status |= IRQ_PER_CPU;
+	set_irq_handler(TIMER_IRQ, handle_specific_irq_timer);
 #ifdef CONFIG_SMP
 	irq_desc[IPI_IRQ].action = &ipi_action;
 	irq_desc[IPI_IRQ].status = IRQ_PER_CPU;
+	set_irq_handler(IPI_IRQ, handle_specific_irq_ipi);
 #endif
 }
 
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 12bab64..4e9f660 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -686,13 +686,13 @@ printk("\n");
  * i386/ia64 support ISA devices and have to deal with
  * edge-triggered interrupts too.
  */
-static void iosapic_end_irq(unsigned int irq)
+void iosapic_end_irq(struct irq_desc *dummy, unsigned int irq)
 {
 	struct vector_info *vi = iosapic_get_vector(irq);
 	DBG(KERN_DEBUG "end_irq(%d): eoi(%p, 0x%x)\n", irq,
 			vi->eoi_addr, vi->eoi_data);
 	iosapic_eoi(vi->eoi_addr, vi->eoi_data);
-	cpu_end_irq(irq);
+	cpu_end_irq(NULL, irq);
 }
 
 static unsigned int iosapic_startup_irq(unsigned int irq)
@@ -729,8 +729,6 @@ static struct hw_interrupt_type iosapic_
 	.shutdown =	iosapic_disable_irq,
 	.enable =	iosapic_enable_irq,
 	.disable =	iosapic_disable_irq,
-	.ack =		cpu_ack_irq,
-	.end =		iosapic_end_irq,
 #ifdef CONFIG_SMP
 	.set_affinity =	iosapic_set_affinity_irq,
 #endif
@@ -819,6 +817,7 @@ int iosapic_fixup_irq(void *isi_obj, str
 	vi->eoi_data = cpu_to_le32(vi->txn_data);
 
 	cpu_claim_irq(vi->txn_irq, &iosapic_interrupt_type, vi);
+	set_irq_handler(vi->txn_irq, handle_level_irq_iosapic);
 
  out:
 	pcidev->irq = vi->txn_irq;
diff --git a/include/asm-parisc/irq-handlers.h b/include/asm-parisc/irq-handlers.h
new file mode 100644
index 0000000..95a9d1b
--- /dev/null
+++ b/include/asm-parisc/irq-handlers.h
@@ -0,0 +1,8 @@
+HANDLE_LEVEL_IRQ(_chip, cpu_ack_irq, cpu_end_irq)
+HANDLE_SPECIFIC_IRQ(_timer, cpu_ack_irq, cpu_end_irq, timer_interrupt)
+#ifdef CONFIG_SMP
+HANDLE_SPECIFIC_IRQ(_ipi, cpu_ack_irq, cpu_end_irq, ipi_interrupt)
+#endif
+#ifdef CONFIG_IOSAPIC
+HANDLE_LEVEL_IRQ(_iosapic, cpu_ack_irq, iosapic_end_irq)
+#endif
diff --git a/include/asm-parisc/irq.h b/include/asm-parisc/irq.h
index 399c819..ae29629 100644
--- a/include/asm-parisc/irq.h
+++ b/include/asm-parisc/irq.h
@@ -8,6 +8,7 @@
 #define _ASM_PARISC_IRQ_H
 
 #include <linux/cpumask.h>
+#include <linux/irqreturn.h>
 #include <asm/types.h>
 
 #define NO_IRQ		(-1)
@@ -26,6 +27,17 @@
 
 #define NR_IRQS		(CPU_IRQ_MAX + 1)
 
+#define ARCH_HAS_IRQ_HANDLERS
+
+struct irq_desc;
+
+void fastcall handle_level_irq_chip(unsigned int irq, struct irq_desc *desc);
+void fastcall handle_level_irq_iosapic(unsigned int irq, struct irq_desc *desc);
+void fastcall handle_percpu_irq_chip(unsigned int irq, struct irq_desc *desc);
+void fastcall handle_specific_irq_timer(unsigned int irq,
+					struct irq_desc *desc);
+void fastcall handle_specific_irq_ipi(unsigned int irq, struct irq_desc *desc);
+
 static __inline__ int irq_canonicalize(int irq)
 {
 	return (irq == 2) ? 9 : irq;
@@ -39,8 +51,9 @@ struct irq_chip;
  */
 void no_ack_irq(unsigned int irq);
 void no_end_irq(unsigned int irq);
-void cpu_ack_irq(unsigned int irq);
-void cpu_end_irq(unsigned int irq);
+void cpu_ack_irq(struct irq_desc *, unsigned int irq);
+void cpu_end_irq(struct irq_desc *, unsigned int irq);
+void iosapic_end_irq(struct irq_desc *, unsigned int irq);
 
 extern int txn_alloc_irq(unsigned int nbits);
 extern int txn_claim_irq(int);
@@ -51,6 +64,10 @@ extern unsigned long txn_affinity_addr(u
 extern int cpu_claim_irq(unsigned int irq, struct irq_chip *, void *);
 extern int cpu_check_affinity(unsigned int irq, cpumask_t *dest);
 
+/* Prototypes for the two directly called interrupts */
+extern irqreturn_t timer_interrupt(int, void *);
+extern irqreturn_t ipi_interrupt(int, void *);
+
 /* soft power switch support (power.c) */
 extern struct tasklet_struct power_tasklet;
 
-- 
1.4.3.3


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2006-12-06  5:15 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-12-06  5:15 [PATCH 1/3] Delete unused irq functions on powerpc Matthew Wilcox
2006-12-06  5:15 ` [PATCH 2/3] Add the ability to template irq handlers in the generic irq code Matthew Wilcox
2006-12-06  5:15   ` [PATCH 3/3] Convert parisc to generic irq handling Matthew Wilcox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).