[ARM] 3692/1: ARM: coswitch irq handling to the generic implementation

Patch from Thomas Gleixner

From: Thomas Gleixner <tglx@linutronix.de>

Switch the ARM irq core handling to the generic implementation. The
ARM specific header files now contain mostly migration stubs and
helper macros. Note that each machine type must be converted after
this step seperately. This was seperated out from the patch for easier
review.

The main changes for the machine type code is the conversion of the
type handlers to a 'type flow' and 'chip' model. This affects only the
multiplex interrupt handlers. A conversion macro needs to be added to
those implementations, which defines the data structure which is
registered by the set_irq_chained_handler() macro.

Some minor fixups of include files and the conversion of data
structure access is necessary all over the place.

The mostly macro based conversion was provided to allow an easy
migration of the existing implementations.

The code compiles on all defconfigs available in arch/arm/configs
except those which were broken also before applying the conversion
patches.

The code has been boot and runtime tested on most ARM platforms. The
results of an extensive testing and bugfixing series can be found
at: http://www.linutronix.de/index.php?page=testing

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
Thomas Gleixner 2006-07-01 22:30:09 +01:00 committed by Russell King
parent f8b5473fcb
commit 4a2581a080
7 changed files with 93 additions and 1043 deletions

View file

@ -47,6 +47,18 @@ config MCA
<file:Documentation/mca.txt> (and especially the web page given
there) before attempting to build an MCA bus kernel.
config GENERIC_HARDIRQS
bool
default y
config HARDIRQS_SW_RESEND
bool
default y
config GENERIC_IRQ_PROBE
bool
default y
config RWSEM_GENERIC_SPINLOCK
bool
default y

View file

@ -38,6 +38,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/seq_file.h>
#include <asm/cacheflush.h>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,6 @@
#ifndef _ASMARM_DYNTICK_H
#define _ASMARM_DYNTICK_H
#include <asm/mach/time.h>
#endif /* _ASMARM_DYNTICK_H */

9
include/asm-arm/hw_irq.h Normal file
View file

@ -0,0 +1,9 @@
/*
* Nothing to see here yet
*/
#ifndef _ARCH_ARM_HW_IRQ_H
#define _ARCH_ARM_HW_IRQ_H
#include <asm/mach/irq.h>
#endif

View file

@ -21,18 +21,13 @@
struct irqaction;
extern void disable_irq_nosync(unsigned int);
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);
/*
* These correspond with the SA_TRIGGER_* defines, and therefore the
* IORESOURCE_IRQ_* defines.
* Migration helpers
*/
#define __IRQT_RISEDGE (1 << 0)
#define __IRQT_FALEDGE (1 << 1)
#define __IRQT_HIGHLVL (1 << 2)
#define __IRQT_LOWLVL (1 << 3)
#define __IRQT_FALEDGE IRQ_TYPE_EDGE_FALLING
#define __IRQT_RISEDGE IRQ_TYPE_EDGE_RISING
#define __IRQT_LOWLVL IRQ_TYPE_LEVEL_LOW
#define __IRQT_HIGHLVL IRQ_TYPE_LEVEL_HIGH
#define IRQT_NOEDGE (0)
#define IRQT_RISING (__IRQT_RISEDGE)
@ -40,12 +35,7 @@ extern void enable_irq(unsigned int);
#define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE)
#define IRQT_LOW (__IRQT_LOWLVL)
#define IRQT_HIGH (__IRQT_HIGHLVL)
#define IRQT_PROBE (1 << 4)
int set_irq_type(unsigned int irq, unsigned int type);
void disable_irq_wake(unsigned int irq);
void enable_irq_wake(unsigned int irq);
int setup_irq(unsigned int, struct irqaction *);
#define IRQT_PROBE IRQ_TYPE_PROBE
extern void migrate_irqs(void);
#endif

View file

@ -10,114 +10,32 @@
#ifndef __ASM_ARM_MACH_IRQ_H
#define __ASM_ARM_MACH_IRQ_H
struct irqdesc;
struct pt_regs;
#include <linux/irq.h>
struct seq_file;
typedef void (*irq_handler_t)(unsigned int, struct irqdesc *, struct pt_regs *);
typedef void (*irq_control_t)(unsigned int);
struct irqchip {
/*
* Acknowledge the IRQ.
* If this is a level-based IRQ, then it is expected to mask the IRQ
* as well.
*/
void (*ack)(unsigned int);
/*
* Mask the IRQ in hardware.
*/
void (*mask)(unsigned int);
/*
* Unmask the IRQ in hardware.
*/
void (*unmask)(unsigned int);
/*
* Ask the hardware to re-trigger the IRQ.
* Note: This method _must_ _not_ call the interrupt handler.
* If you are unable to retrigger the interrupt, do not
* provide a function, or if you do, return non-zero.
*/
int (*retrigger)(unsigned int);
/*
* Set the type of the IRQ.
*/
int (*set_type)(unsigned int, unsigned int);
/*
* Set wakeup-enable on the selected IRQ
*/
int (*set_wake)(unsigned int, unsigned int);
#ifdef CONFIG_SMP
/*
* Route an interrupt to a CPU
*/
void (*set_cpu)(struct irqdesc *desc, unsigned int irq, unsigned int cpu);
#endif
};
struct irqdesc {
irq_handler_t handle;
struct irqchip *chip;
struct irqaction *action;
struct list_head pend;
void __iomem *base;
void *data;
unsigned int disable_depth;
unsigned int triggered: 1; /* IRQ has occurred */
unsigned int running : 1; /* IRQ is running */
unsigned int pending : 1; /* IRQ is pending */
unsigned int probing : 1; /* IRQ in use for a probe */
unsigned int probe_ok : 1; /* IRQ can be used for probe */
unsigned int valid : 1; /* IRQ claimable */
unsigned int noautoenable : 1; /* don't automatically enable IRQ */
unsigned int unused :25;
unsigned int irqs_unhandled;
struct proc_dir_entry *procdir;
#ifdef CONFIG_SMP
cpumask_t affinity;
unsigned int cpu;
#endif
/*
* IRQ lock detection
*/
unsigned int lck_cnt;
unsigned int lck_pc;
unsigned int lck_jif;
};
extern struct irqdesc irq_desc[];
/*
* Helpful inline function for calling irq descriptor handlers.
*/
static inline void desc_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
desc->handle(irq, desc, regs);
}
/*
* This is internal. Do not use it.
*/
extern void (*init_arch_irq)(void);
extern void init_FIQ(void);
extern int show_fiq_list(struct seq_file *, void *);
void __set_irq_handler(unsigned int irq, irq_handler_t, int);
/*
* External stuff.
* Function wrappers
*/
#define set_irq_handler(irq,handler) __set_irq_handler(irq,handler,0)
#define set_irq_chained_handler(irq,handler) __set_irq_handler(irq,handler,1)
#define set_irq_data(irq,d) do { irq_desc[irq].data = d; } while (0)
#define set_irq_chipdata(irq,d) do { irq_desc[irq].base = d; } while (0)
#define get_irq_chipdata(irq) (irq_desc[irq].base)
#define set_irq_chipdata(irq, d) set_irq_chip_data(irq, d)
#define get_irq_chipdata(irq) get_irq_chip_data(irq)
/*
* Obsolete inline function for calling irq descriptor handlers.
*/
static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc,
struct pt_regs *regs)
{
desc->handle_irq(irq, desc, regs);
}
void set_irq_chip(unsigned int irq, struct irqchip *);
void set_irq_flags(unsigned int irq, unsigned int flags);
#define IRQF_VALID (1 << 0)
@ -125,12 +43,25 @@ void set_irq_flags(unsigned int irq, unsigned int flags);
#define IRQF_NOAUTOEN (1 << 2)
/*
* Built-in IRQ handlers.
* This is for easy migration, but should be changed in the source
*/
void do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs);
void do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs);
void do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs);
void do_bad_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs);
void dummy_mask_unmask_irq(unsigned int irq);
#define do_level_IRQ handle_level_irq
#define do_edge_IRQ handle_edge_irq
#define do_simple_IRQ handle_simple_irq
#define irqdesc irq_desc
#define irqchip irq_chip
#define do_bad_IRQ(irq,desc,regs) \
do { \
spin_lock(&desc->lock); \
handle_bad_irq(irq, desc, regs); \
spin_unlock(&desc->lock); \
} while(0)
extern unsigned long irq_err_count;
static inline void ack_bad_irq(int irq)
{
irq_err_count++;
}
#endif