The patch titled genirq: core has been added to the -mm tree. Its filename is genirq-core.patch See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: genirq: core From: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Core genirq support: add the irq-chip and irq-flow abstractions. Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Signed-off-by: Ingo Molnar <mingo@xxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- include/linux/irq.h | 160 ++++++++++++++++++++++++++++++++++----- kernel/irq/autoprobe.c | 9 +- kernel/irq/handle.c | 16 +++ kernel/irq/internals.h | 6 + kernel/irq/manage.c | 14 +++ kernel/irq/resend.c | 4 kernel/irq/spurious.c | 1 7 files changed, 188 insertions(+), 22 deletions(-) diff -puN include/linux/irq.h~genirq-core include/linux/irq.h --- devel/include/linux/irq.h~genirq-core 2006-05-22 15:14:53.000000000 -0700 +++ devel-akpm/include/linux/irq.h 2006-05-22 15:14:53.000000000 -0700 @@ -43,20 +43,36 @@ #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 */ +#define IRQ_DELAYED_DISABLE \ + 4096 /* IRQ disable (masking) happens delayed. */ + +/* + * 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) * @shutdown: shut down the interrupt (defaults to ->disable if NULL) * @enable: enable the interrupt (defaults to chip->unmask if NULL) * @disable: disable the interrupt (defaults to chip->mask if NULL) - * @handle_irq: irq flow handler called from the arch IRQ glue code * @ack: start of a new interrupt * @mask: mask an interrupt source * @mask_ack: ack and mask an interrupt source * @unmask: unmask an interrupt source - * @hold: same interrupt while the handler is running * @end: end of interrupt * @set_affinity: set the CPU affinity on SMP machines * @retrigger: resend an IRQ to the CPU @@ -64,33 +80,45 @@ * @set_wake: enable/disable power-management wake-on of an IRQ * * @release: release function solely used by UML + * @typename: obsoleted by name, kept as migration helper */ -struct hw_interrupt_type { - const char *typename; +struct irq_chip { + const char *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, unsigned int on); /* Currently used only by UML, might disappear one day.*/ #ifdef CONFIG_IRQ_RELEASE_METHOD void (*release)(unsigned int irq, void *dev_id); #endif + /* + * For compatibility, ->typename is copied into ->name. + * Will disappear. + */ + const char *typename; }; -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_irq: highlevel irq-events handler [if NULL, __do_IRQ()] + * @chip: low level interrupt hardware access + * @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 @@ -98,6 +126,7 @@ struct proc_dir_entry; * @irqs_unhandled: stats field for spurious unhandled interrupts * @lock: locking for SMP * @affinity: IRQ affinity on SMP + * @cpu: cpu index useful for balancing * @pending_mask: pending rebalanced interrupts * @move_irq: need to re-target IRQ destination * @dir: /proc/irq/ procfs entry @@ -106,16 +135,22 @@ struct proc_dir_entry; * Pad this out to 32 bytes for cache and indexing reasons. */ struct irq_desc { - hw_irq_controller *chip; + void fastcall (*handle_irq)(unsigned int irq, + struct irq_desc *desc, + struct pt_regs *regs); + struct irq_chip *chip; + 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; @@ -131,6 +166,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; /* @@ -138,6 +176,17 @@ typedef struct irq_desc irq_desc_t; */ #include <asm/hw_irq.h> +/* + * Architectures call this to let the generic IRQ layer + * handle an interrupt: + */ +static inline void generic_handle_irq(unsigned int irq, struct pt_regs *regs) +{ + struct irq_desc *desc = irq_desc + irq; + + desc->handle_irq(irq, desc, regs); +} + extern int setup_irq(unsigned int irq, struct irqaction *new); #ifdef CONFIG_GENERIC_HARDIRQS @@ -236,27 +285,100 @@ static inline int select_smp_affinity(un #endif extern int no_irq_affinity; -extern int noirqdebug_setup(char *str); -extern irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs, - struct irqaction *action); +/* Handle irq action chains: */ +extern int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, + struct irqaction *action); + +/* + * Built-in IRQ handlers for various IRQ types, + * callable via desc->chip->handle_irq() + */ +extern void fastcall +handle_level_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs); +extern void fastcall +handle_fastack_irq(unsigned int irq, struct irq_desc *desc, + struct pt_regs *regs); +extern void fastcall +handle_edge_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs); +extern void fastcall +handle_simple_irq(unsigned int irq, struct irq_desc *desc, + struct pt_regs *regs); +extern void fastcall +handle_percpu_irq(unsigned int irq, struct irq_desc *desc, + struct pt_regs *regs); +extern void fastcall +handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs); + +/* + * Get a descriptive string for the highlevel handler, for + * /proc/interrupts output: + */ +extern const char * +handle_irq_name(void fastcall (*handle)(unsigned int, struct irq_desc *, + struct pt_regs *)); + /* - * Explicit fastcall, because i386 4KSTACKS calls it from assembly: + * 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); + +/* Dummy irq-chip implementation: */ +extern struct irq_chip no_irq_chip; + +extern void +set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip, + void fastcall (*handle)(unsigned int, + struct irq_desc *, + struct pt_regs *)); +extern void +__set_irq_handler(unsigned int irq, + void fastcall (*handle)(unsigned int, struct irq_desc *, + struct pt_regs *), + int is_chained); -extern hw_irq_controller no_irq_type; /* needed in every arch ? */ +/* + * Set a highlevel flow handler for a given IRQ: + */ +static inline void +set_irq_handler(unsigned int irq, + void fastcall (*handle)(unsigned int, struct irq_desc *, + struct pt_regs *)) +{ + __set_irq_handler(irq, handle, 0); +} + +/* + * Set a highlevel chained flow handler for a given IRQ. + * (a chained handler is automatically enabled and set to + * IRQ_NOREQUEST and IRQ_NOPROBE) + */ +static inline void +set_irq_chained_handler(unsigned int irq, + void fastcall (*handle)(unsigned int, struct irq_desc *, + struct pt_regs *)) +{ + __set_irq_handler(irq, handle, 1); +} + +#endif /* CONFIG_GENERIC_HARDIRQS */ #endif /* !CONFIG_S390 */ diff -puN kernel/irq/autoprobe.c~genirq-core kernel/irq/autoprobe.c --- devel/kernel/irq/autoprobe.c~genirq-core 2006-05-22 15:14:53.000000000 -0700 +++ devel-akpm/kernel/irq/autoprobe.c 2006-05-22 15:14:53.000000000 -0700 @@ -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->chip->set_type) + desc->chip->set_type(i, IRQ_TYPE_PROBE); desc->chip->startup(i); + } spin_unlock_irq(&desc->lock); } diff -puN kernel/irq/handle.c~genirq-core kernel/irq/handle.c --- devel/kernel/irq/handle.c~genirq-core 2006-05-22 15:14:53.000000000 -0700 +++ devel-akpm/kernel/irq/handle.c 2006-05-22 15:14:53.000000000 -0700 @@ -18,6 +18,16 @@ #include "internals.h" +/** + * handle_bad_irq - handle spurious and unhandled irqs + */ +void fastcall +handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) +{ + kstat_this_cpu.irqs[irq]++; + ack_bad_irq(irq); +} + /* * Linux has a controller-independent interrupt architecture. * Every controller has a 'controller-template', that is used @@ -136,6 +146,12 @@ fastcall unsigned int __do_IRQ(unsigned struct irqaction *action; unsigned int status; + if (unlikely(desc->handle_irq)) { + desc->handle_irq(irq, desc, regs); + + return 1; + } + kstat_this_cpu.irqs[irq]++; if (CHECK_IRQ_PER_CPU(desc->status)) { irqreturn_t action_ret; diff -puN kernel/irq/internals.h~genirq-core kernel/irq/internals.h --- devel/kernel/irq/internals.h~genirq-core 2006-05-22 15:14:53.000000000 -0700 +++ devel-akpm/kernel/irq/internals.h 2006-05-22 15:14:53.000000000 -0700 @@ -4,6 +4,12 @@ extern int noirqdebug; +/* Set default functions for irq_chip structures: */ +extern void irq_chip_set_defaults(struct irq_chip *chip); + +/* Set default handler: */ +extern void compat_irq_chip_set_default_handler(struct irq_desc *desc); + #ifdef CONFIG_PROC_FS extern void register_irq_proc(unsigned int irq); extern void register_handler_proc(unsigned int irq, struct irqaction *action); diff -puN kernel/irq/manage.c~genirq-core kernel/irq/manage.c --- devel/kernel/irq/manage.c~genirq-core 2006-05-22 15:14:53.000000000 -0700 +++ devel-akpm/kernel/irq/manage.c 2006-05-22 15:14:53.000000000 -0700 @@ -153,6 +153,17 @@ int can_request_irq(unsigned int irq, un return !action; } +void compat_irq_chip_set_default_handler(struct irq_desc *desc) +{ + /* + * If the architecture still has not overriden + * the flow handler then zap the default. This + * should catch incorrect flow-type setting. + */ + if (desc->handle_irq == &handle_bad_irq) + desc->handle_irq = NULL; +} + /* * Internal function to register an irqaction - typically used to * allocate special interrupts that are part of the architecture. @@ -217,6 +228,9 @@ int setup_irq(unsigned int irq, struct i desc->status |= IRQ_PER_CPU; #endif if (!shared) { + irq_chip_set_defaults(desc->chip); + compat_irq_chip_set_default_handler(desc); + desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); diff -puN kernel/irq/resend.c~genirq-core kernel/irq/resend.c --- devel/kernel/irq/resend.c~genirq-core 2006-05-22 15:14:53.000000000 -0700 +++ devel-akpm/kernel/irq/resend.c 2006-05-22 15:14:53.000000000 -0700 @@ -37,9 +37,9 @@ static void resend_irqs(unsigned long ar irq = find_first_bit(irqs_resend, NR_IRQS); clear_bit(irq, irqs_resend); desc = irq_desc + irq; - spin_lock_irqsave(&desc->lock, flags); + local_irq_disable(); desc->handle_irq(irq, desc, NULL); - spin_unlock_irqrestore(&desc->lock, flags); + local_irq_enable(); } } diff -puN kernel/irq/spurious.c~genirq-core kernel/irq/spurious.c --- devel/kernel/irq/spurious.c~genirq-core 2006-05-22 15:14:53.000000000 -0700 +++ devel-akpm/kernel/irq/spurious.c 2006-05-22 15:14:53.000000000 -0700 @@ -166,6 +166,7 @@ void note_interrupt(unsigned int irq, st */ printk(KERN_EMERG "Disabling IRQ #%d\n", irq); desc->status |= IRQ_DISABLED; + desc->depth = 1; desc->chip->disable(irq); } desc->irqs_unhandled = 0; _ Patches currently in -mm which might be from tglx@xxxxxxxxxxxxx are origin.patch git-mtd.patch pi-futex-futex-code-cleanups.patch pi-futex-introduce-debug_check_no_locks_freed.patch pi-futex-add-plist-implementation.patch pi-futex-scheduler-support-for-pi.patch pi-futex-rt-mutex-core.patch pi-futex-rt-mutex-core-fix-timeout-race.patch pi-futex-rt-mutex-docs.patch pi-futex-rt-mutex-debug.patch pi-futex-rt-mutex-tester.patch pi-futex-rt-mutex-futex-api.patch pi-futex-futex_lock_pi-futex_unlock_pi-support.patch pi-futex-patchset-v4-fix.patch rtmutex-remove-buggy-bug_on-in-pi-boosting-code.patch futex-pi-enforce-waiter-bit-when-owner-died-is-detected.patch rtmutex-debug-printk-correct-task-information.patch futex-pi-make-use-of-restart_block-when-interrupted.patch document-futex-pi-design.patch document-futex-pi-design-fix.patch document-futex-pi-design-fix-fix.patch futex_requeue-optimization.patch genirq-rename-desc-handler-to-desc-chip.patch genirq-sem2mutex-probe_sem-probing_active.patch genirq-cleanup-merge-irq_affinity-into-irq_desc.patch genirq-cleanup-remove-irq_descp.patch genirq-cleanup-remove-fastcall.patch genirq-cleanup-misc-code-cleanups.patch genirq-cleanup-reduce-irq_desc_t-use-mark-it-obsolete.patch genirq-cleanup-include-linux-irqh.patch genirq-cleanup-merge-irq_dir-smp_affinity_entry-into-irq_desc.patch genirq-cleanup-merge-pending_irq_cpumask-into-irq_desc.patch genirq-cleanup-turn-arch_has_irq_per_cpu-into-config_irq_per_cpu.patch genirq-debug-better-debug-printout-in-enable_irq.patch genirq-add-retrigger-irq-op-to-consolidate-hw_irq_resend.patch genirq-doc-comment-include-linux-irqh-structures.patch genirq-doc-handle_irq_event-and-__do_irq-comments.patch genirq-cleanup-no_irq_type-cleanups.patch genirq-doc-add-design-documentation.patch genirq-add-genirq-sw-irq-retrigger.patch genirq-add-irq_noprobe-support.patch genirq-add-irq_norequest-support.patch genirq-add-irq_noautoen-support.patch genirq-update-copyrights.patch genirq-core.patch genirq-add-irq-chip-support.patch genirq-add-handle_bad_irq.patch genirq-add-irq-wake-power-management-support.patch genirq-add-sa_trigger-support.patch genirq-convert-the-x86_64-architecture-to-irq-chips.patch genirq-convert-the-i386-architecture-to-irq-chips.patch genirq-more-verbose-debugging-on-unexpected-irq-vectors.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html