[patch 21/50] genirq: core

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Thomas Gleixner <[email protected]>

core genirq support: add the irq-chip and irq-flow abstractions.

Signed-off-by: Thomas Gleixner <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
 include/linux/irq.h    |   86 ++++++++++++++++++++++++++++++++++++++++---------
 kernel/irq/autoprobe.c |    9 ++++-
 kernel/irq/handle.c    |   14 +++++++
 3 files changed, 93 insertions(+), 16 deletions(-)

Index: linux-genirq.q/include/linux/irq.h
===================================================================
--- linux-genirq.q.orig/include/linux/irq.h
+++ linux-genirq.q/include/linux/irq.h
@@ -43,8 +43,24 @@
 #define IRQ_NOPROBE	512	/* IRQ is not valid for probing */
 #define IRQ_NOREQUEST	1024	/* IRQ cannot be requested */
 #define IRQ_NOAUTOEN	2048	/* IRQ will not be enabled on request irq */
+
+/*
+ * IRQ types, see also include/linux/interrupt.h
+ */
+#define IRQ_TYPE_NONE		0x0000		/* Default, unspecified type */
+#define IRQ_TYPE_EDGE_RISING	0x0001		/* Edge rising type */
+#define IRQ_TYPE_EDGE_FALLING	0x0002		/* Edge falling type */
+#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
+#define IRQ_TYPE_LEVEL_HIGH	0x0004		/* Level high type */
+#define IRQ_TYPE_LEVEL_LOW	0x0008		/* Level low type */
+#define IRQ_TYPE_SIMPLE		0x0010		/* Simple type */
+#define IRQ_TYPE_PERCPU		0x0020		/* Per CPU type */
+#define IRQ_TYPE_PROBE		0x0040		/* Probing in progress */
+
+struct proc_dir_entry;
+
 /**
- * struct hw_interrupt_type - hardware interrupt type descriptor
+ * struct irq_chip - hardware interrupt chip descriptor
  *
  * @name:		name for /proc/interrupts
  * @startup:		start up the interrupt (defaults to ->enable if NULL)
@@ -65,16 +81,23 @@
  *
  * @release:		release function solely used by UML
  */
-struct hw_interrupt_type {
-	const char	*typename;
+struct irq_chip {
+	const char	*typename; /* will be renamed to 'name' */
 	unsigned int	(*startup)(unsigned int irq);
 	void		(*shutdown)(unsigned int irq);
 	void		(*enable)(unsigned int irq);
 	void		(*disable)(unsigned int irq);
+
 	void		(*ack)(unsigned int irq);
+	void		(*mask)(unsigned int irq);
+	void		(*mask_ack)(unsigned int irq);
+	void		(*unmask)(unsigned int irq);
+
 	void		(*end)(unsigned int irq);
 	void		(*set_affinity)(unsigned int irq, cpumask_t dest);
 	int		(*retrigger)(unsigned int irq);
+	int		(*set_type)(unsigned int irq, unsigned int flow_type);
+	int		(*set_wake)(unsigned int irq, int on);
 
 	/* Currently used only by UML, might disappear one day.*/
 #ifdef CONFIG_IRQ_RELEASE_METHOD
@@ -82,15 +105,15 @@ struct hw_interrupt_type {
 #endif
 };
 
-typedef struct hw_interrupt_type  hw_irq_controller;
-
-struct proc_dir_entry;
-
 /**
  * struct irq_desc - interrupt descriptor
  *
- * @handler:		interrupt type dependent handler functions
- * @handler_data:	data for the type handlers
+ * @handle:		highlevel irq-events handler [if NULL, __do_IRQ()]
+ * @handler:		low level interrupt hardware access
+ *			(this should be renamed to 'chip')
+ * @handler_data:	per-IRQ data for the irq_chip methods
+ * @chip_data:		platform-specific per-chip private data for the chip
+ *			methods, to allow shared chip implementations
  * @action:		the irq action chain
  * @status:		status information
  * @depth:		disable-depth, for nested irq_disable() calls
@@ -106,16 +129,22 @@ struct proc_dir_entry;
  * Pad this out to 32 bytes for cache and indexing reasons.
  */
 struct irq_desc {
-	hw_irq_controller	*handler;
+	void			(*handle)(unsigned int irq,
+					  struct irq_desc *desc,
+					  struct pt_regs *regs);
+	struct irq_chip		*handler;
 	void			*handler_data;
+	void			*chip_data;
 	struct irqaction	*action;	/* IRQ action list */
 	unsigned int		status;		/* IRQ status */
+
 	unsigned int		depth;		/* nested irq disables */
 	unsigned int		irq_count;	/* For detecting broken IRQs */
 	unsigned int		irqs_unhandled;
 	spinlock_t		lock;
 #ifdef CONFIG_SMP
 	cpumask_t		affinity;
+	unsigned int		cpu;
 #endif
 #if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
 	cpumask_t		pending_mask;
@@ -134,6 +163,9 @@ extern struct irq_desc irq_desc[NR_IRQS]
 /*
  * Migration helpers for obsolete names, they will go away:
  */
+#define hw_interrupt_type	irq_chip
+typedef struct irq_chip		hw_irq_controller;
+#define no_irq_type		no_irq_chip
 typedef struct irq_desc		irq_desc_t;
 
 /*
@@ -231,28 +263,52 @@ static inline int select_smp_affinity(un
 #endif
 
 extern int no_irq_affinity;
-extern int noirqdebug_setup(char *str);
 
+/* Handle irq action chains: */
 extern int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
 			    struct irqaction *action);
 
 /*
- * Explicit fastcall, because i386 4KSTACKS calls it from assembly:
+ * Built-in IRQ handlers for various IRQ types,
+ * callable via desc->handler->handle_irq()
+ */
+extern void handle_level_irq(unsigned int irq, struct irq_desc *desc,
+			     struct pt_regs *regs);
+extern void handle_edge_irq(unsigned int irq, struct irq_desc *desc,
+			    struct pt_regs *regs);
+extern void handle_simple_irq(unsigned int irq, struct irq_desc *desc,
+			      struct pt_regs *regs);
+extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc,
+			      struct pt_regs *regs);
+extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc,
+			   struct pt_regs *regs);
+
+/*
+ * Monolithic do_IRQ implementation.
+ * (is an explicit fastcall, because i386 4KSTACKS calls it from assembly)
  */
 extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
 
+/* Handling of unhandled and spurious interrupts: */
 extern void note_interrupt(unsigned int irq, struct irq_desc *desc,
 			   int action_ret, struct pt_regs *regs);
-extern int can_request_irq(unsigned int irq, unsigned long irqflags);
 
 /* Resending of interrupts :*/
 void check_irq_resend(struct irq_desc *desc, unsigned int irq);
 
+/* Initialize /proc/irq/ */
 extern void init_irq_proc(void);
 
-#endif /* CONFIG_GENERIC_HARDIRQS */
+/* Enable/disable irq debugging output: */
+extern int noirqdebug_setup(char *str);
+
+/* Checks whether the interrupt can be requested by request_irq(): */
+extern int can_request_irq(unsigned int irq, unsigned long irqflags);
 
-extern hw_irq_controller no_irq_type;  /* needed in every arch ? */
+/* Dummy irq-chip implementation: */
+extern struct irq_chip no_irq_chip;
+
+#endif /* CONFIG_GENERIC_HARDIRQS */
 
 #endif /* !CONFIG_S390 */
 
Index: linux-genirq.q/kernel/irq/autoprobe.c
===================================================================
--- linux-genirq.q.orig/kernel/irq/autoprobe.c
+++ linux-genirq.q/kernel/irq/autoprobe.c
@@ -40,8 +40,15 @@ unsigned long probe_irq_on(void)
 		desc = irq_desc + i;
 
 		spin_lock_irq(&desc->lock);
-		if (!desc->action && !(desc->status & IRQ_NOPROBE))
+		if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
+			/*
+			 * Some chips need to know about probing in
+			 * progress:
+			 */
+			if (desc->handler->set_type)
+				desc->handler->set_type(i, IRQ_TYPE_PROBE);
 			desc->handler->startup(i);
+		}
 		spin_unlock_irq(&desc->lock);
 	}
 
Index: linux-genirq.q/kernel/irq/handle.c
===================================================================
--- linux-genirq.q.orig/kernel/irq/handle.c
+++ linux-genirq.q/kernel/irq/handle.c
@@ -18,6 +18,18 @@
 
 #include "internals.h"
 
+/**
+ * handle_bad_irq - handle spurious and unhandled irqs
+ * @irq:	the interrupt number
+ * @desc:	the interrupt description structure for this irq
+ * @regs:	pointer to a register structure
+ */
+void
+handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
+{
+	ack_bad_irq(irq);
+}
+
 /*
  * Linux has a controller-independent interrupt architecture.
  * Every controller has a 'controller-template', that is used
@@ -36,7 +48,9 @@ struct irq_desc irq_desc[NR_IRQS] __cach
 	[0 ... NR_IRQS-1] = {
 		.status = IRQ_DISABLED,
 		.handler = &no_irq_type,
+		.handle = handle_bad_irq,
 		.lock = SPIN_LOCK_UNLOCKED,
+		.depth = 1,
 #ifdef CONFIG_SMP
 		.affinity = CPU_MASK_ALL
 #endif
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux