diff -urN --exclude='*~' linux-2.6.13-rc2/Documentation/DocBook/Makefile linux-2.6.13-rc2-armirq/Documentation/DocBook/Makefile --- linux-2.6.13-rc2/Documentation/DocBook/Makefile 2005-07-09 13:08:03.000000000 +0200 +++ linux-2.6.13-rc2-armirq/Documentation/DocBook/Makefile 2005-07-09 13:10:41.000000000 +0200 @@ -10,7 +10,7 @@ kernel-hacking.xml kernel-locking.xml deviceiobook.xml \ procfs-guide.xml writing_usb_driver.xml \ sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \ - gadget.xml libata.xml mtdnand.xml librs.xml + gadget.xml libata.xml mtdnand.xml librs.xml genericirq.xml ### # The build process is as follows (targets): diff -urN --exclude='*~' linux-2.6.13-rc2/Documentation/DocBook/genericirq.tmpl linux-2.6.13-rc2-armirq/Documentation/DocBook/genericirq.tmpl --- linux-2.6.13-rc2/Documentation/DocBook/genericirq.tmpl 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.13-rc2-armirq/Documentation/DocBook/genericirq.tmpl 2005-07-09 13:10:41.000000000 +0200 @@ -0,0 +1,559 @@ + + + + + Linux generic IRQ handling + + + + Thomas + Gleixner + +
+ tglx@linutronix.de +
+
+
+ + Ingo + Molnar + +
+ mingo@elte.hu +
+
+
+
+ + + 2005 + Thomas Gleixner + + + 2005 + Ingo Molnar + + + + + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License version 2 as published by the Free Software Foundation. + + + + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + + Introduction + + The generic interrupt handling layer is designed to provide a + complete abstraction of interrupt handling for device drivers + and is able to handle all different types of interrupt controller + hardware. Device drivers use generic API function to request, enable, + disable and free interrupts. The drivers do not have to know anything + about interrupt hardware, so they can be used on different hardware + platforms without code changes. + + + This documentation is provided for developers who want to implement + architecture interrupt support based on the Generic IRQ handling layer. + + + + + Rationale + + The original implementation of interrupt handling in Linux is using + the __do_IRQ() super-handler, which must be able to deal with every + type of interrupt logic. This is achieved by an 'interrupt type' + structure and runtime flags to handle special cases. + Furthermore the superhandler assumed a certain type of interrupt + handling hardware and turned out to be not capable of handling all + kind of interrupt controller hardware which can be found through + the architectures. The all in one approach also adds unnecessary + complexity for every user. + + + Originally, Russell King identified different types of handlers to + build a quite universal set for the ARM interrupt handler + implementation in Linux 2.5/2.6. He distiguished between: + + Level type + Edge type + Simple type + + In the SMP world of the __do_IRQ() super-handler another type + was identified: + + Per CPU type + + + + This split implementation of handlers allows to optimize the flow + of the interrupt handling for each specific interrupt type. + This reduces complexitiy in that particular code path and allows + the optimized handling of a given type. + + + The original general implementation uses interrupt_type structures + to differentiate the flow control in the super-handler. This + leads to a mix of flow logic and code related to hardware details. + Russell Kings ARM implementation which replaced the type by a chip + abstraction did the mix the other way around. + + + The natural conclusion was a clean seperation of the 'type flow' + and the 'chip'. Analysing a couple of architecture implementations + reveals that many of them can use a generic set of 'type flow' + implementations and only need to add the chip level specific code. + The seperation is also valuable for the (sub)architectures, + which need specific quirks in the type flow itself, because it + provides a more transparent design. + + + Each interrupt type implementation has assigned its own flow + handler, which should be normally one of the generic + implementations. The flow handler implementation makes it + simple to provide demultiplexing handlers which can be found in + embedded platforms on various architectures. + + + The seperation makes the generic interrupt handling more flexible + and extensible. An (sub)architecture can use a generic type flow + implementation for e.g. 'level type' interrupts and add a + (sub)architecture specific 'edge type' implementation. + + + To make the transition to the new model easier and prevent the + breakage of existing implementations the __do_IRQ() super-handler + is still available. This leads to a kind of duality for the time + being. Over time the new model should achieve a homogeneous + implementation scheme over all architectures with enhanced + maintainability and cleanliness. + + + + Known Bugs And Assumptions + + None (hopefully). + + + + + Abstraction layers + + There are three main levels of abstraction in the interrupt code: + + Highlevel driver API + Abstract interrupt type + Chiplevel hardware encapsulation + + + + The seperation of interrupt type and chip level functionality + provides the most flexible design. This implementation can handle + all kinds of interrupt hardware and the necessary workarounds for + the interrupt types without the need of redundant implementations. + The seperation handles also edge and level type interrupts + on the same hardware chip. + + + Interrupt control flow + + Each interrupt is described by an interrupt description structure + irq_desc. The interrupt is referenced by an 'unsigned int' numeric + value which selects the corresponding interrupt decription structure + in the description structures array. + The description structure contains status information and pointers + to the interrupt type structure and the interrupt chip structure + which are assigned to this interrupt. + + + Whenever an interrupt triggers, the lowlevel arch code calls into + the generic interrupt code by calling desc->handler->handle_irq(). + This highlevel IRQ handling function only uses other + desc->handler primitives which describe the control flow operation + necessary for the interrupt type. These operations are calling + the chip primitives referenced by the assigned chip description + structure. + + + + Highlevel Driver API + + The highlevel Driver API consists of following functions: + + request_irq() + free_irq() + disable_irq() + enable_irq() + disable_irq_nosync() (SMP only) + synchronize_irq() (SMP only) + set_irq_type() + set_irq_wake() + set_irq_data() + set_irq_chip() + set_irq_chip_data() + + See the autogenerated function documentation for details. + + + + Abstract interrupt type + + The 'interrupt type' (struct irq_type) abstraction mainly consists of + methods which implement the 'interrupt handling flow'. The generic + layer provides a set of pre-defined types: + + default_level_type + default_edge_type + default_simple_type + default_percpu_type + + The default type implementations use the generic type handlers. + + handle_level_type + handle_edge_type + handle_simple_type + handle_percpu_type + + The interrupt types (either predefined or architecture specific) are + assigned to specific interrupts by the architecture either during + bootup or during device initialization. + + + Default type implementations + + Helper functions + + The helper functions call the chip primitives and + are used by the default type implementations. + Following helper functions are implemented (simplified excerpt): + +default_enable(irq) +{ + desc->chip->unmask(irq); +} + +default_disable(irq) +{ + desc->chip->mask(irq); +} + +default_ack(irq) +{ + chip->ack(irq); +} + +default_mask_ack(irq) +{ + if (chip->mask_ack) { + chip->mask_ack(irq); + } else { + chip->mask(irq); + chip->ack(irq); + } +} + +noop(irq) +{ +} + +default_set_type(irq, type) +{ + if (desc->chip->set_type) { + if (desc->chip->set_type(irq, type)) + return NULL; + } + + return default_handler for type; +} + + + + + Default Level IRQ type + + The default Level IRQ type implements the functions + + enabledefault_enable + disabledefault_disable + startdefault_mask_ack + enddefault_enable + handle_irqhandle_level_irq + set_typedefault_set_type + + + + + Default Edge IRQ type + + The default Edge IRQ type implements the functions + + enabledefault_enable + disabledefault_disable + startdefault_ack + holddefault_mask_ack + endnoop + handle_irqhandle_edge_irq + set_typedefault_set_type + + + + + Default simple IRQ type + + The default simple IRQ type implements the functions + + enablenoop + disablenoop + handle_irqhandle_simple_irq + + + + + Default per CPU IRQ type + + The default per CPU IRQ type implements the functions + + enabledefault_enable + disabledefault_disable + startdefault_ack + enddefault_enable + handle_irqhandle_percpu_irq + + + + + + Default type handler implementations + + Default Level IRQ type handler + + handle_level_type provides a generic implementation + for level type interrupts. + + + Following control flow is implemented (simplified excerpt): + +desc->handler->start(); +handle_IRQ_event(desc->action); +desc->handler->end(); + + + + + Default Edge IRQ type handler + + handle_edge_type provides a generic implementation + for edge type interrupts. + + + Following control flow is implemented (simplified excerpt): + +if (desc->status & running) { + desc->handler->hold(); + desc->status |= pending | masked; + return; +} +desc->handler->start(); +desc->status |= running; +do { + if (desc->status & masked) + desc->handler->enable(); + desc-status &= ~pending; + handle_IRQ_event(desc->action); +} while (status & pending); +desc-status &= ~running; +desc->handler->end(); + + + + + Default simple IRQ type handler + + handle_simple_type provides a generic implementation + for simple type interrupts. + + + Note: The simple type handler does not call any + handler/chip primitives. + + + Following control flow is implemented (simplified excerpt): + +handle_IRQ_event(desc->action); + + + + + Default per CPU type handler + + handle_percpu_type provides a generic implementation + for per CPU type interrupts. + + + Per CPU interrupts are only available on SMP and + the handler provides a simplified version without + locking. + + + Following control flow is implemented (simplified excerpt): + +desc->handler->start(); +handle_IRQ_event(desc->action); +desc->handler->end(); + + + + + + Architecture specific type implementation + + If an architecture needs to implement its own type structures, then + the following primitives have to be implemented: + + handle_irq() - The handle_irq function pointer should preferably point to + one of the generic type handler functions + startup() - Optional + shutdown() - Optional + enable() + disable() + start() + hold() - For edge type interupts only + end() + set_type - Optional + set_affinity - SMP only + + + + + Quirks and optimizations + + The generic functions are intended for 'clean' architectures and chips, + which have no platform-specific IRQ handling quirks. If an architecture + needs to implement quirks on the 'flow' level then it can do so by + overriding the irqtype. This is also done for compatibility reasons, as + most architectures use irqtypes only at the moment. + + + An architecture could implement all of its IRQ logic via pushing + chip handling details into the irqtype's ->start()/->end()/->hold() + functions. This is only recommended when the underlying primitives + are pure chip primitives without additional quirks. The direct pointer + to the chip functions reduces the indirection level by one. + + + + + Chiplevel hardware encapsulation + + The chip level hardware description structure irq_chip + contains all the direct chip relevant functions, which + can be utilized by the irq_type implementations. + + ack() + mask_ack() - Optional, recommended for performance + mask() + unmask() + retrigger() - Optional + set_type() - Optional + set_wake() - Optional + + These primitives are strictly intended to mean what they say: ack means + ACK, masking means masking of an IRQ line, etc. It is up to the flow + handler(s) to use these basic units of lowlevel functionality. + + + + + + __do_IRQ entry point + + The original implementation __do_IRQ() is an alternative entry + point for all types of interrupts. + + + This handler turned out to be not suitable for all + interrupt hardware and was therefor reimplemented with split + functionality for egde/level/simple/percpu interrupts. This is not + only a functional optimization. It also shortenes code pathes for + interrupts. + + + To make use of the split implementation, replace the call to + __do_IRQ by a call to desc->handler->handle_irq() and associate + the appropriate handler function to desc->handler->handle_irq(). + In most cases the generic type and handler implementations should + be sufficient. + + + + + Locking on SMP + + The locking of chip registers is up to the architecture that + defines the chip primitives. There is a chip->lock field that can be used + for serialization, but the generic layer does not touch it. The per-irq + structure is protected via desc->lock, by the generic layer. + + + + Structures + + This chapter contains the autogenerated documentation of the structures which are + used in the generic IRQ layer. + +!Iinclude/linux/irq.h + + + + Public Functions Provided + + This chapter contains the autogenerated documentation of the kernel API functions + which are exported. + +!Ekernel/irq/manage.c + + + + Internal Functions Provided + + This chapter contains the autogenerated documentation of the internal functions. + +!Ikernel/irq/handle.c +!Ikernel/irq/manage.c + + + + Credits + + The following people have contributed to this document: + + Thomas Gleixnertglx@linutronix.de + Ingo Molnarmingo@elte.hu + + + +
diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/Kconfig linux-2.6.13-rc2-armirq/arch/arm/Kconfig --- linux-2.6.13-rc2/arch/arm/Kconfig 2005-07-09 13:08:04.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/Kconfig 2005-07-09 13:10:41.000000000 +0200 @@ -50,6 +50,10 @@ bool default y +config GENERIC_HARDIRQS + bool + default y + config RWSEM_GENERIC_SPINLOCK bool default y diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/common/locomo.c linux-2.6.13-rc2-armirq/arch/arm/common/locomo.c --- linux-2.6.13-rc2/arch/arm/common/locomo.c 2005-07-09 13:04:33.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/common/locomo.c 2005-07-09 13:10:41.000000000 +0200 @@ -177,7 +177,7 @@ d = irq_desc + irq; for (i = 0; i <= 3; i++, d++, irq++) { if (req & (0x0100 << i)) { - d->handle(irq, d, regs); + desc_lock_handle_irq(irq, d, regs); } } @@ -220,7 +220,7 @@ if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) { d = irq_desc + LOCOMO_IRQ_KEY_START; - d->handle(LOCOMO_IRQ_KEY_START, d, regs); + desc_lock_handle_irq(LOCOMO_IRQ_KEY_START, d, regs); } } @@ -273,7 +273,7 @@ d = irq_desc + LOCOMO_IRQ_GPIO_START; for (i = 0; i <= 15; i++, irq++, d++) { if (req & (0x0001 << i)) { - d->handle(irq, d, regs); + desc_lock_handle_irq(irq, d, regs); } } } @@ -328,7 +328,7 @@ if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) { d = irq_desc + LOCOMO_IRQ_LT_START; - d->handle(LOCOMO_IRQ_LT_START, d, regs); + desc_lock_handle_irq(LOCOMO_IRQ_LT_START, d, regs); } } @@ -379,7 +379,7 @@ for (i = 0; i <= 3; i++, irq++, d++) { if (req & (0x0001 << i)) { - d->handle(irq, d, regs); + desc_lock_handle_irq(irq, d, regs); } } } @@ -426,6 +426,12 @@ .unmask = locomo_spi_unmask_irq, }; +static DEFINE_IRQ_CHAINED_TYPE(locomo_handler); +static DEFINE_IRQ_CHAINED_TYPE(locomo_key_handler); +static DEFINE_IRQ_CHAINED_TYPE(locomo_gpio_handler); +static DEFINE_IRQ_CHAINED_TYPE(locomo_lt_handler); +static DEFINE_IRQ_CHAINED_TYPE(locomo_spi_handler); + static void locomo_setup_irq(struct locomo *lchip) { int irq; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/common/sa1111.c linux-2.6.13-rc2-armirq/arch/arm/common/sa1111.c --- linux-2.6.13-rc2/arch/arm/common/sa1111.c 2005-07-09 13:08:04.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/common/sa1111.c 2005-07-09 13:10:41.000000000 +0200 @@ -159,11 +159,11 @@ for (i = IRQ_SA1111_START; stat0; i++, stat0 >>= 1) if (stat0 & 1) - do_edge_IRQ(i, irq_desc + i, regs); + handle_edge_irq(i, irq_desc + i, regs); for (i = IRQ_SA1111_START + 32; stat1; i++, stat1 >>= 1) if (stat1 & 1) - do_edge_IRQ(i, irq_desc + i, regs); + handle_edge_irq(i, irq_desc + i, regs); /* For level-based interrupts */ desc->chip->unmask(irq); @@ -268,8 +268,8 @@ .mask = sa1111_mask_lowirq, .unmask = sa1111_unmask_lowirq, .retrigger = sa1111_retrigger_lowirq, - .type = sa1111_type_lowirq, - .wake = sa1111_wake_lowirq, + .set_type = sa1111_type_lowirq, + .set_wake = sa1111_wake_lowirq, }; static void sa1111_mask_highirq(unsigned int irq) @@ -364,10 +364,12 @@ .mask = sa1111_mask_highirq, .unmask = sa1111_unmask_highirq, .retrigger = sa1111_retrigger_highirq, - .type = sa1111_type_highirq, - .wake = sa1111_wake_highirq, + .set_type = sa1111_type_highirq, + .set_wake = sa1111_wake_highirq, }; +static DEFINE_IRQ_CHAINED_TYPE(sa1111_irq_handler); + static void sa1111_setup_irq(struct sa1111 *sachip) { void __iomem *irqbase = sachip->base + SA1111_INTC; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/common/time-acorn.c linux-2.6.13-rc2-armirq/arch/arm/common/time-acorn.c --- linux-2.6.13-rc2/arch/arm/common/time-acorn.c 2005-07-09 13:04:33.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/common/time-acorn.c 2005-07-09 13:10:41.000000000 +0200 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/kernel/ecard.c linux-2.6.13-rc2-armirq/arch/arm/kernel/ecard.c --- linux-2.6.13-rc2/arch/arm/kernel/ecard.c 2005-07-09 13:08:04.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/kernel/ecard.c 2005-07-09 13:10:41.000000000 +0200 @@ -585,7 +585,7 @@ if (pending) { struct irqdesc *d = irq_desc + ec->irq; - d->handle(ec->irq, d, regs); + desc_lock_handle_irq(ec->irq, d, regs); called ++; } } @@ -619,7 +619,7 @@ ecard_t *ec = slot_to_ecard(slot); if (ec->claimed) { - struct irqdesc *d = irqdesc + ec->irq; + struct irqdesc *d = irq_desc + ec->irq; /* * this ugly code is so that we can operate a * prioritorising system: @@ -632,7 +632,7 @@ * Serial cards should go in 0/1, ethernet/scsi in 2/3 * otherwise you will lose serial data at high speeds! */ - d->handle(ec->irq, d, regs); + desc_lock_handle_irq(ec->irq, d, regs); } else { printk(KERN_WARNING "card%d: interrupt from unclaimed " "card???\n", slot); @@ -1052,6 +1052,9 @@ return rc; } +static DEFINE_IRQ_CHAINED_TYPE(ecard_irqexp_handler); +static DEFINE_IRQ_CHAINED_TYPE(ecard_irq_handler); + /* * Initialise the expansion card system. * Locate all hardware - interrupt management and @@ -1081,8 +1084,10 @@ irqhw = ecard_probeirqhw(); - set_irq_chained_handler(IRQ_EXPANSIONCARD, - irqhw ? ecard_irqexp_handler : ecard_irq_handler); + if (irqhw) + set_irq_chained_handler(IRQ_EXPANSIONCARD, ecard_irqexp_handler); + else + set_irq_chained_handler(IRQ_EXPANSIONCARD, ecard_irq_handler); ecard_proc_init(); diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/kernel/fiq.c linux-2.6.13-rc2-armirq/arch/arm/kernel/fiq.c --- linux-2.6.13-rc2/arch/arm/kernel/fiq.c 2005-07-09 13:04:33.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/kernel/fiq.c 2005-07-09 13:10:41.000000000 +0200 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/kernel/irq.c linux-2.6.13-rc2-armirq/arch/arm/kernel/irq.c --- linux-2.6.13-rc2/arch/arm/kernel/irq.c 2005-07-09 13:08:04.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/kernel/irq.c 2005-07-11 15:06:22.000000000 +0200 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -38,193 +39,11 @@ #include #include -#include #include -#include #include -/* - * Maximum IRQ count. Currently, this is arbitary. However, it should - * not be set too low to prevent false triggering. Conversely, if it - * is set too high, then you could miss a stuck IRQ. - * - * Maybe we ought to set a timer and re-enable the IRQ at a later time? - */ -#define MAX_IRQ_CNT 100000 - -static int noirqdebug; -static volatile unsigned long irq_err_count; -static DEFINE_SPINLOCK(irq_controller_lock); -static LIST_HEAD(irq_pending); - -struct irqdesc irq_desc[NR_IRQS]; void (*init_arch_irq)(void) __initdata = NULL; -/* - * No architecture-specific irq_finish function defined in arm/arch/irqs.h. - */ -#ifndef irq_finish -#define irq_finish(irq) do { } while (0) -#endif - -/* - * Dummy mask/unmask handler - */ -void dummy_mask_unmask_irq(unsigned int irq) -{ -} - -irqreturn_t no_action(int irq, void *dev_id, struct pt_regs *regs) -{ - return IRQ_NONE; -} - -void do_bad_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) -{ - irq_err_count += 1; - printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); -} - -static struct irqchip bad_chip = { - .ack = dummy_mask_unmask_irq, - .mask = dummy_mask_unmask_irq, - .unmask = dummy_mask_unmask_irq, -}; - -static struct irqdesc bad_irq_desc = { - .chip = &bad_chip, - .handle = do_bad_IRQ, - .pend = LIST_HEAD_INIT(bad_irq_desc.pend), - .disable_depth = 1, -}; - -#ifdef CONFIG_SMP -void synchronize_irq(unsigned int irq) -{ - struct irqdesc *desc = irq_desc + irq; - - while (desc->running) - barrier(); -} -EXPORT_SYMBOL(synchronize_irq); - -#define smp_set_running(desc) do { desc->running = 1; } while (0) -#define smp_clear_running(desc) do { desc->running = 0; } while (0) -#else -#define smp_set_running(desc) do { } while (0) -#define smp_clear_running(desc) do { } while (0) -#endif - -/** - * disable_irq_nosync - disable an irq without waiting - * @irq: Interrupt to disable - * - * Disable the selected interrupt line. Enables and disables - * are nested. We do this lazily. - * - * This function may be called from IRQ context. - */ -void disable_irq_nosync(unsigned int irq) -{ - struct irqdesc *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&irq_controller_lock, flags); - desc->disable_depth++; - list_del_init(&desc->pend); - spin_unlock_irqrestore(&irq_controller_lock, flags); -} -EXPORT_SYMBOL(disable_irq_nosync); - -/** - * disable_irq - disable an irq and wait for completion - * @irq: Interrupt to disable - * - * Disable the selected interrupt line. Enables and disables - * are nested. This functions waits for any pending IRQ - * handlers for this interrupt to complete before returning. - * If you use this function while holding a resource the IRQ - * handler may need you will deadlock. - * - * This function may be called - with care - from IRQ context. - */ -void disable_irq(unsigned int irq) -{ - struct irqdesc *desc = irq_desc + irq; - - disable_irq_nosync(irq); - if (desc->action) - synchronize_irq(irq); -} -EXPORT_SYMBOL(disable_irq); - -/** - * enable_irq - enable interrupt handling on an irq - * @irq: Interrupt to enable - * - * Re-enables the processing of interrupts on this IRQ line. - * Note that this may call the interrupt handler, so you may - * get unexpected results if you hold IRQs disabled. - * - * This function may be called from IRQ context. - */ -void enable_irq(unsigned int irq) -{ - struct irqdesc *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&irq_controller_lock, flags); - if (unlikely(!desc->disable_depth)) { - printk("enable_irq(%u) unbalanced from %p\n", irq, - __builtin_return_address(0)); - } else if (!--desc->disable_depth) { - desc->probing = 0; - desc->chip->unmask(irq); - - /* - * If the interrupt is waiting to be processed, - * try to re-run it. We can't directly run it - * from here since the caller might be in an - * interrupt-protected region. - */ - if (desc->pending && list_empty(&desc->pend)) { - desc->pending = 0; - if (!desc->chip->retrigger || - desc->chip->retrigger(irq)) - list_add(&desc->pend, &irq_pending); - } - } - spin_unlock_irqrestore(&irq_controller_lock, flags); -} -EXPORT_SYMBOL(enable_irq); - -/* - * Enable wake on selected irq - */ -void enable_irq_wake(unsigned int irq) -{ - struct irqdesc *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&irq_controller_lock, flags); - if (desc->chip->wake) - desc->chip->wake(irq, 1); - spin_unlock_irqrestore(&irq_controller_lock, flags); -} -EXPORT_SYMBOL(enable_irq_wake); - -void disable_irq_wake(unsigned int irq) -{ - struct irqdesc *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&irq_controller_lock, flags); - if (desc->chip->wake) - desc->chip->wake(irq, 0); - spin_unlock_irqrestore(&irq_controller_lock, flags); -} -EXPORT_SYMBOL(disable_irq_wake); - int show_interrupts(struct seq_file *p, void *v) { int i = *(loff_t *) v, cpu; @@ -243,7 +62,7 @@ } if (i < NR_IRQS) { - spin_lock_irqsave(&irq_controller_lock, flags); + spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) goto unlock; @@ -257,7 +76,7 @@ seq_putc(p, '\n'); unlock: - spin_unlock_irqrestore(&irq_controller_lock, flags); + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } else if (i == NR_IRQS) { #ifdef CONFIG_ARCH_ACORN show_fiq_list(p, v); @@ -265,270 +84,21 @@ #ifdef CONFIG_SMP show_ipi_list(p); #endif +#ifdef FIXME_TGLX seq_printf(p, "Err: %10lu\n", irq_err_count); - } - return 0; -} - -/* - * IRQ lock detection. - * - * Hopefully, this should get us out of a few locked situations. - * However, it may take a while for this to happen, since we need - * a large number if IRQs to appear in the same jiffie with the - * same instruction pointer (or within 2 instructions). - */ -static int check_irq_lock(struct irqdesc *desc, int irq, struct pt_regs *regs) -{ - unsigned long instr_ptr = instruction_pointer(regs); - - if (desc->lck_jif == jiffies && - desc->lck_pc >= instr_ptr && desc->lck_pc < instr_ptr + 8) { - desc->lck_cnt += 1; - - if (desc->lck_cnt > MAX_IRQ_CNT) { - printk(KERN_ERR "IRQ LOCK: IRQ%d is locking the system, disabled\n", irq); - return 1; - } - } else { - desc->lck_cnt = 0; - desc->lck_pc = instruction_pointer(regs); - desc->lck_jif = jiffies; - } - return 0; -} - -static void -report_bad_irq(unsigned int irq, struct pt_regs *regs, struct irqdesc *desc, int ret) -{ - static int count = 100; - struct irqaction *action; - - if (!count || noirqdebug) - return; - - count--; - - if (ret != IRQ_HANDLED && ret != IRQ_NONE) { - printk("irq%u: bogus retval mask %x\n", irq, ret); - } else { - printk("irq%u: nobody cared\n", irq); - } - show_regs(regs); - dump_stack(); - printk(KERN_ERR "handlers:"); - action = desc->action; - do { - printk("\n" KERN_ERR "[<%p>]", action->handler); - print_symbol(" (%s)", (unsigned long)action->handler); - action = action->next; - } while (action); - printk("\n"); -} - -static int -__do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) -{ - unsigned int status; - int ret, retval = 0; - - spin_unlock(&irq_controller_lock); - -#ifdef CONFIG_NO_IDLE_HZ - if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) { - write_seqlock(&xtime_lock); - if (system_timer->dyn_tick->state & DYN_TICK_ENABLED) - system_timer->dyn_tick->handler(irq, 0, regs); - write_sequnlock(&xtime_lock); - } #endif - - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); - - status = 0; - do { - ret = action->handler(irq, action->dev_id, regs); - if (ret == IRQ_HANDLED) - status |= action->flags; - retval |= ret; - action = action->next; - } while (action); - - if (status & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - - spin_lock_irq(&irq_controller_lock); - - return retval; -} - -/* - * This is for software-decoded IRQs. The caller is expected to - * handle the ack, clear, mask and unmask issues. - */ -void -do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) -{ - struct irqaction *action; - const unsigned int cpu = smp_processor_id(); - - desc->triggered = 1; - - kstat_cpu(cpu).irqs[irq]++; - - smp_set_running(desc); - - action = desc->action; - if (action) { - int ret = __do_irq(irq, action, regs); - if (ret != IRQ_HANDLED) - report_bad_irq(irq, regs, desc, ret); - } - - smp_clear_running(desc); -} - -/* - * Most edge-triggered IRQ implementations seem to take a broken - * approach to this. Hence the complexity. - */ -void -do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) -{ - const unsigned int cpu = smp_processor_id(); - - desc->triggered = 1; - - /* - * If we're currently running this IRQ, or its disabled, - * we shouldn't process the IRQ. Instead, turn on the - * hardware masks. - */ - if (unlikely(desc->running || desc->disable_depth)) - goto running; - - /* - * Acknowledge and clear the IRQ, but don't mask it. - */ - desc->chip->ack(irq); - - /* - * Mark the IRQ currently in progress. - */ - desc->running = 1; - - kstat_cpu(cpu).irqs[irq]++; - - do { - struct irqaction *action; - - action = desc->action; - if (!action) - break; - - if (desc->pending && !desc->disable_depth) { - desc->pending = 0; - desc->chip->unmask(irq); - } - - __do_irq(irq, action, regs); - } while (desc->pending && !desc->disable_depth); - - desc->running = 0; - - /* - * If we were disabled or freed, shut down the handler. - */ - if (likely(desc->action && !check_irq_lock(desc, irq, regs))) - return; - - running: - /* - * We got another IRQ while this one was masked or - * currently running. Delay it. - */ - desc->pending = 1; - desc->chip->mask(irq); - desc->chip->ack(irq); -} - -/* - * Level-based IRQ handler. Nice and simple. - */ -void -do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) -{ - struct irqaction *action; - const unsigned int cpu = smp_processor_id(); - - desc->triggered = 1; - - /* - * Acknowledge, clear _AND_ disable the interrupt. - */ - desc->chip->ack(irq); - - if (likely(!desc->disable_depth)) { - kstat_cpu(cpu).irqs[irq]++; - - smp_set_running(desc); - - /* - * Return with this interrupt masked if no action - */ - action = desc->action; - if (action) { - int ret = __do_irq(irq, desc->action, regs); - - if (ret != IRQ_HANDLED) - report_bad_irq(irq, regs, desc, ret); - - if (likely(!desc->disable_depth && - !check_irq_lock(desc, irq, regs))) - desc->chip->unmask(irq); - } - - smp_clear_running(desc); } + return 0; } -static void do_pending_irqs(struct pt_regs *regs) -{ - struct list_head head, *l, *n; - - do { - struct irqdesc *desc; - - /* - * First, take the pending interrupts off the list. - * The act of calling the handlers may add some IRQs - * back onto the list. - */ - head = irq_pending; - INIT_LIST_HEAD(&irq_pending); - head.next->prev = &head; - head.prev->next = &head; - - /* - * Now run each entry. We must delete it from our - * list before calling the handler. - */ - list_for_each_safe(l, n, &head) { - desc = list_entry(l, struct irqdesc, pend); - list_del_init(&desc->pend); - desc->handle(desc - irq_desc, desc, regs); - } - - /* - * The list must be empty. - */ - BUG_ON(!list_empty(&head)); - } while (!list_empty(&irq_pending)); -} +/* Handle bad interrupts */ +static struct irq_desc bad_irq = { + .handler = &no_irq_type, + .lock = SPIN_LOCK_UNLOCKED +}; /* - * do_IRQ handles all hardware IRQ's. Decoded IRQs should not + * asm_do_IRQ handles all hardware IRQ's. Decoded IRQs should not * come via this function. Instead, they should provide their * own 'handler' */ @@ -539,100 +109,58 @@ /* * Some hardware gives randomly wrong interrupts. Rather * than crashing, do something sensible. + * + * TGLX_FIXME */ if (irq >= NR_IRQS) - desc = &bad_irq_desc; + desc = &bad_irq; irq_enter(); - spin_lock(&irq_controller_lock); - desc->handle(irq, desc, regs); - /* - * Now re-run any pending interrupts. - */ - if (!list_empty(&irq_pending)) - do_pending_irqs(regs); + desc_lock_handle_irq(irq, desc, regs); - irq_finish(irq); - - spin_unlock(&irq_controller_lock); irq_exit(); } -void __set_irq_handler(unsigned int irq, irq_handler_t handle, int is_chained) +void __set_irq_handler(unsigned int irq, struct irq_type *type, int is_chained) { struct irqdesc *desc; unsigned long flags; if (irq >= NR_IRQS) { - printk(KERN_ERR "Trying to install handler for IRQ%d\n", irq); + printk(KERN_ERR "Trying to install type control for IRQ%d\n", irq); return; } - if (handle == NULL) - handle = do_bad_IRQ; - desc = irq_desc + irq; - if (is_chained && desc->chip == &bad_chip) - printk(KERN_WARNING "Trying to install chained handler for IRQ%d\n", irq); - - spin_lock_irqsave(&irq_controller_lock, flags); - if (handle == do_bad_IRQ) { - desc->chip->mask(irq); - desc->chip->ack(irq); - desc->disable_depth = 1; - } - desc->handle = handle; - if (handle != do_bad_IRQ && is_chained) { - desc->valid = 0; - desc->probe_ok = 0; - desc->disable_depth = 0; - desc->chip->unmask(irq); + /* Uninstall ? */ + if (type == NULL || type == &no_irq_type) { + spin_lock_irqsave(&desc->lock, flags); + if (desc->chip) { + desc->chip->mask(irq); + desc->chip->ack(irq); + } + desc->depth = 1; + spin_unlock_irqrestore(&desc->lock, flags); } - spin_unlock_irqrestore(&irq_controller_lock, flags); -} - -void set_irq_chip(unsigned int irq, struct irqchip *chip) -{ - struct irqdesc *desc; - unsigned long flags; - if (irq >= NR_IRQS) { - printk(KERN_ERR "Trying to install chip for IRQ%d\n", irq); + /* Install the irq_type */ + if (generic_set_irq_type(irq, type)) return; - } - if (chip == NULL) - chip = &bad_chip; + spin_lock_irqsave(&desc->lock, flags); + if (is_chained && (desc->handler == &no_irq_type || !desc->chip)) + printk(KERN_WARNING "Trying to install chained interrupt type for IRQ%d\n", irq); - desc = irq_desc + irq; - spin_lock_irqsave(&irq_controller_lock, flags); - desc->chip = chip; - spin_unlock_irqrestore(&irq_controller_lock, flags); -} - -int set_irq_type(unsigned int irq, unsigned int type) -{ - struct irqdesc *desc; - unsigned long flags; - int ret = -ENXIO; - - if (irq >= NR_IRQS) { - printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq); - return -ENODEV; - } - - desc = irq_desc + irq; - if (desc->chip->type) { - spin_lock_irqsave(&irq_controller_lock, flags); - ret = desc->chip->type(irq, type); - spin_unlock_irqrestore(&irq_controller_lock, flags); + if (type != NULL && is_chained) { + desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE; + desc->depth = 0; + if (desc->chip) + desc->chip->unmask(irq); } - - return ret; + spin_unlock_irqrestore(&desc->lock, flags); } -EXPORT_SYMBOL(set_irq_type); void set_irq_flags(unsigned int irq, unsigned int iflags) { @@ -645,408 +173,28 @@ } desc = irq_desc + irq; - spin_lock_irqsave(&irq_controller_lock, flags); - desc->valid = (iflags & IRQF_VALID) != 0; - desc->probe_ok = (iflags & IRQF_PROBE) != 0; - desc->noautoenable = (iflags & IRQF_NOAUTOEN) != 0; - spin_unlock_irqrestore(&irq_controller_lock, flags); -} - -int setup_irq(unsigned int irq, struct irqaction *new) -{ - int shared = 0; - struct irqaction *old, **p; - unsigned long flags; - struct irqdesc *desc; - - /* - * Some drivers like serial.c use request_irq() heavily, - * so we have to be careful not to interfere with a - * running system. - */ - if (new->flags & SA_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * Yes, this might clear the entropy pool if the wrong - * driver is attempted to be loaded, without actually - * installing a new handler, but is this really a problem, - * only the sysadmin is able to do this. - */ - rand_initialize_irq(irq); - } - - /* - * The following block of code has to be executed atomically - */ - desc = irq_desc + irq; - spin_lock_irqsave(&irq_controller_lock, flags); - p = &desc->action; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) { - spin_unlock_irqrestore(&irq_controller_lock, flags); - return -EBUSY; - } - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - - *p = new; - - if (!shared) { - desc->probing = 0; - desc->running = 0; - desc->pending = 0; - desc->disable_depth = 1; - if (!desc->noautoenable) { - desc->disable_depth = 0; - desc->chip->unmask(irq); - } - } - - spin_unlock_irqrestore(&irq_controller_lock, flags); - return 0; -} - -/** - * request_irq - allocate an interrupt line - * @irq: Interrupt line to allocate - * @handler: Function to be called when the IRQ occurs - * @irqflags: Interrupt type flags - * @devname: An ascii name for the claiming device - * @dev_id: A cookie passed back to the handler function - * - * This call allocates interrupt resources and enables the - * interrupt line and IRQ handling. From the point this - * call is made your handler function may be invoked. Since - * your handler function must clear any interrupt the board - * raises, you must take care both to initialise your hardware - * and to set up the interrupt handler in the right order. - * - * Dev_id must be globally unique. Normally the address of the - * device data structure is used as the cookie. Since the handler - * receives this value it makes sense to use it. - * - * If your interrupt is shared you must pass a non NULL dev_id - * as this is required when freeing the interrupt. - * - * Flags: - * - * SA_SHIRQ Interrupt is shared - * - * SA_INTERRUPT Disable local interrupts while processing - * - * SA_SAMPLE_RANDOM The interrupt can be used for entropy - * - */ -int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irq_flags, const char * devname, void *dev_id) -{ - unsigned long retval; - struct irqaction *action; - - if (irq >= NR_IRQS || !irq_desc[irq].valid || !handler || - (irq_flags & SA_SHIRQ && !dev_id)) - return -EINVAL; - - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irq_flags; - cpus_clear(action->mask); - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - retval = setup_irq(irq, action); - - if (retval) - kfree(action); - return retval; -} - -EXPORT_SYMBOL(request_irq); - -/** - * free_irq - free an interrupt - * @irq: Interrupt line to free - * @dev_id: Device identity to free - * - * Remove an interrupt handler. The handler is removed and if the - * interrupt line is no longer in use by any driver it is disabled. - * On a shared IRQ the caller must ensure the interrupt is disabled - * on the card it drives before calling this function. - * - * This function must not be called from interrupt context. - */ -void free_irq(unsigned int irq, void *dev_id) -{ - struct irqaction * action, **p; - unsigned long flags; - - if (irq >= NR_IRQS || !irq_desc[irq].valid) { - printk(KERN_ERR "Trying to free IRQ%d\n",irq); - dump_stack(); - return; - } - - spin_lock_irqsave(&irq_controller_lock, flags); - for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) { - if (action->dev_id != dev_id) - continue; - - /* Found it - now free it */ - *p = action->next; - break; - } - spin_unlock_irqrestore(&irq_controller_lock, flags); - - if (!action) { - printk(KERN_ERR "Trying to free free IRQ%d\n",irq); - dump_stack(); - } else { - synchronize_irq(irq); - kfree(action); - } -} - -EXPORT_SYMBOL(free_irq); - -static DECLARE_MUTEX(probe_sem); - -/* Start the interrupt probing. Unlike other architectures, - * we don't return a mask of interrupts from probe_irq_on, - * but return the number of interrupts enabled for the probe. - * The interrupts which have been enabled for probing is - * instead recorded in the irq_desc structure. - */ -unsigned long probe_irq_on(void) -{ - unsigned int i, irqs = 0; - unsigned long delay; - - down(&probe_sem); - - /* - * first snaffle up any unassigned but - * probe-able interrupts - */ - spin_lock_irq(&irq_controller_lock); - for (i = 0; i < NR_IRQS; i++) { - if (!irq_desc[i].probe_ok || irq_desc[i].action) - continue; - - irq_desc[i].probing = 1; - irq_desc[i].triggered = 0; - if (irq_desc[i].chip->type) - irq_desc[i].chip->type(i, IRQT_PROBE); - irq_desc[i].chip->unmask(i); - irqs += 1; - } - spin_unlock_irq(&irq_controller_lock); - - /* - * wait for spurious interrupts to mask themselves out again - */ - for (delay = jiffies + HZ/10; time_before(jiffies, delay); ) - /* min 100ms delay */; - - /* - * now filter out any obviously spurious interrupts - */ - spin_lock_irq(&irq_controller_lock); - for (i = 0; i < NR_IRQS; i++) { - if (irq_desc[i].probing && irq_desc[i].triggered) { - irq_desc[i].probing = 0; - irqs -= 1; - } - } - spin_unlock_irq(&irq_controller_lock); - - return irqs; -} - -EXPORT_SYMBOL(probe_irq_on); - -unsigned int probe_irq_mask(unsigned long irqs) -{ - unsigned int mask = 0, i; - - spin_lock_irq(&irq_controller_lock); - for (i = 0; i < 16 && i < NR_IRQS; i++) - if (irq_desc[i].probing && irq_desc[i].triggered) - mask |= 1 << i; - spin_unlock_irq(&irq_controller_lock); - - up(&probe_sem); - - return mask; -} -EXPORT_SYMBOL(probe_irq_mask); - -/* - * Possible return values: - * >= 0 - interrupt number - * -1 - no interrupt/many interrupts - */ -int probe_irq_off(unsigned long irqs) -{ - unsigned int i; - int irq_found = NO_IRQ; - - /* - * look at the interrupts, and find exactly one - * that we were probing has been triggered - */ - spin_lock_irq(&irq_controller_lock); - for (i = 0; i < NR_IRQS; i++) { - if (irq_desc[i].probing && - irq_desc[i].triggered) { - if (irq_found != NO_IRQ) { - irq_found = NO_IRQ; - goto out; - } - irq_found = i; - } - } - - if (irq_found == -1) - irq_found = NO_IRQ; -out: - spin_unlock_irq(&irq_controller_lock); - - up(&probe_sem); - - return irq_found; -} - -EXPORT_SYMBOL(probe_irq_off); - -#ifdef CONFIG_SMP -static void route_irq(struct irqdesc *desc, unsigned int irq, unsigned int cpu) -{ - pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->cpu, cpu); - - spin_lock_irq(&irq_controller_lock); - desc->cpu = cpu; - desc->chip->set_cpu(desc, irq, cpu); - spin_unlock_irq(&irq_controller_lock); -} - -#ifdef CONFIG_PROC_FS -static int -irq_affinity_read_proc(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - struct irqdesc *desc = irq_desc + ((int)data); - int len = cpumask_scnprintf(page, count, desc->affinity); - - if (count - len < 2) - return -EINVAL; - page[len++] = '\n'; - page[len] = '\0'; - - return len; -} - -static int -irq_affinity_write_proc(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - unsigned int irq = (unsigned int)data; - struct irqdesc *desc = irq_desc + irq; - cpumask_t affinity, tmp; - int ret = -EIO; - - if (!desc->chip->set_cpu) - goto out; - - ret = cpumask_parse(buffer, count, affinity); - if (ret) - goto out; - - cpus_and(tmp, affinity, cpu_online_map); - if (cpus_empty(tmp)) { - ret = -EINVAL; - goto out; - } - - desc->affinity = affinity; - route_irq(desc, irq, first_cpu(tmp)); - ret = count; - - out: - return ret; -} -#endif -#endif - -void __init init_irq_proc(void) -{ -#if defined(CONFIG_SMP) && defined(CONFIG_PROC_FS) - struct proc_dir_entry *dir; - int irq; - - dir = proc_mkdir("irq", 0); - if (!dir) - return; - - for (irq = 0; irq < NR_IRQS; irq++) { - struct proc_dir_entry *entry; - struct irqdesc *desc; - char name[16]; - - desc = irq_desc + irq; - memset(name, 0, sizeof(name)); - snprintf(name, sizeof(name) - 1, "%u", irq); - - desc->procdir = proc_mkdir(name, dir); - if (!desc->procdir) - continue; - - entry = create_proc_entry("smp_affinity", 0600, desc->procdir); - if (entry) { - entry->nlink = 1; - entry->data = (void *)irq; - entry->read_proc = irq_affinity_read_proc; - entry->write_proc = irq_affinity_write_proc; - } - } -#endif + spin_lock_irqsave(&desc->lock, flags); + desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE; + if (iflags & IRQF_VALID) + desc->status &= ~IRQ_NOREQUEST; + if (iflags & IRQF_PROBE) + desc->status &= ~IRQ_NOPROBE; + spin_unlock_irqrestore(&desc->lock, flags); } void __init init_IRQ(void) { - struct irqdesc *desc; extern void init_dma(void); int irq; + for (irq = 0; irq < NR_IRQS; irq++) + irq_desc[irq].status |= IRQ_NOREQUEST; + #ifdef CONFIG_SMP bad_irq_desc.affinity = CPU_MASK_ALL; bad_irq_desc.cpu = smp_processor_id(); #endif - for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) { - *desc = bad_irq_desc; - INIT_LIST_HEAD(&desc->pend); - } - init_arch_irq(); init_dma(); } - -static int __init noirqdebug_setup(char *str) -{ - noirqdebug = 1; - return 1; -} - -__setup("noirqdebug", noirqdebug_setup); diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-clps711x/time.c linux-2.6.13-rc2-armirq/arch/arm/mach-clps711x/time.c --- linux-2.6.13-rc2/arch/arm/mach-clps711x/time.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-clps711x/time.c 2005-07-09 13:10:41.000000000 +0200 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-clps7500/core.c linux-2.6.13-rc2-armirq/arch/arm/mach-clps7500/core.c --- linux-2.6.13-rc2/arch/arm/mach-clps7500/core.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-clps7500/core.c 2005-07-09 13:10:41.000000000 +0200 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-footbridge/dc21285-timer.c linux-2.6.13-rc2-armirq/arch/arm/mach-footbridge/dc21285-timer.c --- linux-2.6.13-rc2/arch/arm/mach-footbridge/dc21285-timer.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-footbridge/dc21285-timer.c 2005-07-09 13:10:41.000000000 +0200 @@ -6,6 +6,7 @@ */ #include #include +#include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-footbridge/isa-irq.c linux-2.6.13-rc2-armirq/arch/arm/mach-footbridge/isa-irq.c --- linux-2.6.13-rc2/arch/arm/mach-footbridge/isa-irq.c 2005-07-09 13:04:33.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-footbridge/isa-irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -95,13 +95,24 @@ } desc = irq_desc + isa_irq; - desc->handle(isa_irq, desc, regs); + desc_lock_handle_irq(isa_irq, desc, regs); } static struct irqaction irq_cascade = { .handler = no_action, .name = "cascade", }; static struct resource pic1_resource = { "pic1", 0x20, 0x3f }; static struct resource pic2_resource = { "pic2", 0xa0, 0xbf }; +static DEFINE_IRQ_CHAINED_TYPE(isa_irq_handler); + +static unsigned int startup_irq_disabled(unsigned int irq) +{ + return 0; +} + +/* Interrupt type for irqs which must not be + * automatically enabled in reqeust_irq */ +static struct irq_type level_type_nostart; + void __init isa_init_irq(unsigned int host_irq) { unsigned int irq; @@ -159,9 +170,11 @@ * There appears to be a missing pull-up * resistor on this line. */ - if (machine_is_netwinder()) - set_irq_flags(_ISA_IRQ(11), IRQF_VALID | - IRQF_PROBE | IRQF_NOAUTOEN); + if (machine_is_netwinder()) { + level_type_nostart = default_level_type; + level_type_nostart.startup = startup_irq_disabled; + set_irq_handler(_ISA_IRQ(11), &level_type_nostart); + } } } diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-footbridge/isa-timer.c linux-2.6.13-rc2-armirq/arch/arm/mach-footbridge/isa-timer.c --- linux-2.6.13-rc2/arch/arm/mach-footbridge/isa-timer.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-footbridge/isa-timer.c 2005-07-09 13:10:41.000000000 +0200 @@ -6,6 +6,7 @@ */ #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-h720x/common.c linux-2.6.13-rc2-armirq/arch/arm/mach-h720x/common.c --- linux-2.6.13-rc2/arch/arm/mach-h720x/common.c 2005-07-09 13:04:34.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-h720x/common.c 2005-07-09 13:10:41.000000000 +0200 @@ -108,7 +108,7 @@ while (mask) { if (mask & 1) { IRQDBG("handling irq %d\n", irq); - desc->handle(irq, desc, regs); + desc_lock_handle_irq(irq, desc, regs); } irq++; desc++; @@ -163,6 +163,11 @@ h720x_gpio_handler(mask, irq, desc, regs); } +static DEFINE_IRQ_CHAINED_TYPE(h720x_gpioa_demux_handler); +static DEFINE_IRQ_CHAINED_TYPE(h720x_gpiob_demux_handler); +static DEFINE_IRQ_CHAINED_TYPE(h720x_gpioc_demux_handler); +static DEFINE_IRQ_CHAINED_TYPE(h720x_gpiod_demux_handler); + #ifdef CONFIG_CPU_H7202 static void h720x_gpioe_demux_handler(unsigned int irq_unused, struct irqdesc *desc, @@ -175,6 +180,7 @@ IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq); h720x_gpio_handler(mask, irq, desc, regs); } +static DEFINE_IRQ_CHAINED_TYPE(h720x_gpioe_demux_handler); #endif static struct irqchip h720x_global_chip = { diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-h720x/cpu-h7202.c linux-2.6.13-rc2-armirq/arch/arm/mach-h720x/cpu-h7202.c --- linux-2.6.13-rc2/arch/arm/mach-h720x/cpu-h7202.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-h720x/cpu-h7202.c 2005-07-09 13:10:41.000000000 +0200 @@ -126,7 +126,7 @@ desc = irq_desc + irq; while (mask) { if (mask & 1) - desc->handle(irq, desc, regs); + desc_lock_handle_irq(irq, desc, regs); irq++; desc++; mask >>= 1; @@ -175,6 +175,8 @@ .handler = h7202_timer_interrupt, }; +static DEFINE_IRQ_CHAINED_TYPE(h7202_timerx_demux_handler); + /* * Setup TIMER0 as system timer */ diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-imx/irq.c linux-2.6.13-rc2-armirq/arch/arm/mach-imx/irq.c --- linux-2.6.13-rc2/arch/arm/mach-imx/irq.c 2005-07-09 13:04:34.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-imx/irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -152,7 +152,7 @@ while (mask) { if (mask & 1) { DEBUG_IRQ("handling irq %d\n", irq); - desc->handle(irq, desc, regs); + desc_lock_handle_irq(irq, desc, regs); } irq++; desc++; @@ -214,9 +214,14 @@ .ack = imx_gpio_ack_irq, .mask = imx_gpio_mask_irq, .unmask = imx_gpio_unmask_irq, - .type = imx_gpio_irq_type, + .set_type = imx_gpio_irq_type, }; +static DEFINE_IRQ_CHAINED_TYPE(imx_gpioa_demux_handler); +static DEFINE_IRQ_CHAINED_TYPE(imx_gpiob_demux_handler); +static DEFINE_IRQ_CHAINED_TYPE(imx_gpioc_demux_handler); +static DEFINE_IRQ_CHAINED_TYPE(imx_gpiod_demux_handler); + void __init imx_init_irq(void) { diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-imx/time.c linux-2.6.13-rc2-armirq/arch/arm/mach-imx/time.c --- linux-2.6.13-rc2/arch/arm/mach-imx/time.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-imx/time.c 2005-07-09 13:10:41.000000000 +0200 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-integrator/core.c linux-2.6.13-rc2-armirq/arch/arm/mach-integrator/core.c --- linux-2.6.13-rc2/arch/arm/mach-integrator/core.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-integrator/core.c 2005-07-09 13:10:41.000000000 +0200 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-integrator/integrator_cp.c linux-2.6.13-rc2-armirq/arch/arm/mach-integrator/integrator_cp.c --- linux-2.6.13-rc2/arch/arm/mach-integrator/integrator_cp.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-integrator/integrator_cp.c 2005-07-09 13:10:41.000000000 +0200 @@ -170,7 +170,7 @@ irq += IRQ_SIC_START; desc = irq_desc + irq; - desc->handle(irq, desc, regs); + desc_lock_handle_irq(irq, desc, regs); } while (status); } diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-ixp2000/core.c linux-2.6.13-rc2-armirq/arch/arm/mach-ixp2000/core.c --- linux-2.6.13-rc2/arch/arm/mach-ixp2000/core.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-ixp2000/core.c 2005-07-09 16:46:40.000000000 +0200 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -31,14 +32,12 @@ #include #include #include -#include #include #include #include #include #include -#include #include @@ -264,7 +263,7 @@ local_irq_save(flags); if (direction == GPIO_OUT) { - irq_desc[line + IRQ_IXP2000_GPIO0].valid = 0; + set_irq_flags(line + IRQ_IXP2000_GPIO0, 0); /* if it's an output, it ain't an interrupt anymore */ GPIO_IRQ_falling_edge &= ~(1 << line); @@ -292,7 +291,7 @@ for (i = 0; i <= 7; i++) { if (status & (1<handle(i + IRQ_IXP2000_GPIO0, desc, regs); + desc_lock_handle_irq(i + IRQ_IXP2000_GPIO0, desc, regs); } } } @@ -330,8 +329,7 @@ /* * Finally, mark the corresponding IRQ as valid. */ - irq_desc[irq].valid = 1; - + set_irq_flags(irq, IRQF_VALID); return 0; } @@ -355,10 +353,10 @@ } static struct irqchip ixp2000_GPIO_irq_chip = { - .type = ixp2000_GPIO_irq_type, - .ack = ixp2000_GPIO_irq_mask_ack, - .mask = ixp2000_GPIO_irq_mask, - .unmask = ixp2000_GPIO_irq_unmask + .set_type = ixp2000_GPIO_irq_type, + .ack = ixp2000_GPIO_irq_mask_ack, + .mask = ixp2000_GPIO_irq_mask, + .unmask = ixp2000_GPIO_irq_unmask }; static void ixp2000_pci_irq_mask(unsigned int irq) @@ -401,6 +399,8 @@ .unmask = ixp2000_irq_unmask }; +static DEFINE_IRQ_CHAINED_TYPE(ixp2000_GPIO_irq_handler); + void __init ixp2000_init_irq(void) { int irq; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-ixp2000/ixdp2x00.c linux-2.6.13-rc2-armirq/arch/arm/mach-ixp2000/ixdp2x00.c --- linux-2.6.13-rc2/arch/arm/mach-ixp2000/ixdp2x00.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-ixp2000/ixdp2x00.c 2005-07-09 13:10:41.000000000 +0200 @@ -133,7 +133,7 @@ struct irqdesc *cpld_desc; int cpld_irq = IXP2000_BOARD_IRQ(0) + i; cpld_desc = irq_desc + cpld_irq; - cpld_desc->handle(cpld_irq, cpld_desc, regs); + desc_lock_handle_irq(cpld_irq, cpld_desc, regs); } } @@ -146,6 +146,8 @@ .unmask = ixdp2x00_irq_unmask }; +static DEFINE_IRQ_CHAINED_TYPE(ixdp2x00_irq_handler); + void ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long *mask_reg, unsigned long nr_irqs) { unsigned int irq; @@ -168,7 +170,7 @@ } /* Hook into PCI interrupt */ - set_irq_chained_handler(IRQ_IXP2000_PCIB, &ixdp2x00_irq_handler); + set_irq_chained_handler(IRQ_IXP2000_PCIB, ixdp2x00_irq_handler); } /************************************************************************* diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-ixp2000/ixdp2x01.c linux-2.6.13-rc2-armirq/arch/arm/mach-ixp2000/ixdp2x01.c --- linux-2.6.13-rc2/arch/arm/mach-ixp2000/ixdp2x01.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-ixp2000/ixdp2x01.c 2005-07-09 13:10:41.000000000 +0200 @@ -82,7 +82,7 @@ struct irqdesc *cpld_desc; int cpld_irq = IXP2000_BOARD_IRQ(0) + i; cpld_desc = irq_desc + cpld_irq; - cpld_desc->handle(cpld_irq, cpld_desc, regs); + desc_lock_handle_irq(cpld_irq, cpld_desc, regs); } } @@ -95,6 +95,8 @@ .unmask = ixdp2x01_irq_unmask }; +static DEFINE_IRQ_CHAINED_TYPE(ixdp2x01_irq_handler); + /* * We only do anything if we are the master NPU on the board. * The slave NPU only has the ethernet chip going directly to @@ -127,7 +129,7 @@ } /* Hook into PCI interrupts */ - set_irq_chained_handler(IRQ_IXP2000_PCIB, &ixdp2x01_irq_handler); + set_irq_chained_handler(IRQ_IXP2000_PCIB, ixdp2x01_irq_handler); } diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-l7200/core.c linux-2.6.13-rc2-armirq/arch/arm/mach-l7200/core.c --- linux-2.6.13-rc2/arch/arm/mach-l7200/core.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-l7200/core.c 2005-07-09 13:10:41.000000000 +0200 @@ -7,6 +7,7 @@ */ #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-lh7a40x/arch-kev7a400.c linux-2.6.13-rc2-armirq/arch/arm/mach-lh7a40x/arch-kev7a400.c --- linux-2.6.13-rc2/arch/arm/mach-lh7a40x/arch-kev7a400.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-lh7a40x/arch-kev7a400.c 2005-07-09 13:10:41.000000000 +0200 @@ -72,6 +72,8 @@ } } +static DEFINE_IRQ_CHAINED_TYPE(kev7a400_cpld_handler); + void __init lh7a40x_init_board_irq (void) { int irq; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-lh7a40x/arch-lpd7a40x.c linux-2.6.13-rc2-armirq/arch/arm/mach-lh7a40x/arch-lpd7a40x.c --- linux-2.6.13-rc2/arch/arm/mach-lh7a40x/arch-lpd7a40x.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-lh7a40x/arch-lpd7a40x.c 2005-07-09 13:10:41.000000000 +0200 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -173,6 +174,7 @@ desc->chip->unmask (irq); /* Level-triggered need this */ } +static DEFINE_IRQ_CHAINED_TYPE(lpd7a40x_cpld_handler); void __init lh7a40x_init_board_irq (void) { diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-lh7a40x/common.h linux-2.6.13-rc2-armirq/arch/arm/mach-lh7a40x/common.h --- linux-2.6.13-rc2/arch/arm/mach-lh7a40x/common.h 2005-07-09 13:04:33.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-lh7a40x/common.h 2005-07-09 13:10:41.000000000 +0200 @@ -13,4 +13,4 @@ extern void lh7a400_init_irq (void); extern void lh7a404_init_irq (void); -#define IRQ_DISPATCH(irq) irq_desc[irq].handle ((irq), &irq_desc[irq], regs) +#define IRQ_DISPATCH(irq) desc_lock_handle_irq((irq),(irq_desc + irq), regs) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-lh7a40x/irq-kev7a400.c linux-2.6.13-rc2-armirq/arch/arm/mach-lh7a40x/irq-kev7a400.c --- linux-2.6.13-rc2/arch/arm/mach-lh7a40x/irq-kev7a400.c 2005-07-09 13:04:33.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-lh7a40x/irq-kev7a400.c 2005-07-09 13:10:41.000000000 +0200 @@ -60,6 +60,8 @@ } } +static DEFINE_IRQ_CHAINED_TYPE(kev7a400_cpld_handler); + /* IRQ initialization */ void __init diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-lh7a40x/irq-lpd7a40x.c linux-2.6.13-rc2-armirq/arch/arm/mach-lh7a40x/irq-lpd7a40x.c --- linux-2.6.13-rc2/arch/arm/mach-lh7a40x/irq-lpd7a40x.c 2005-07-09 13:04:33.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-lh7a40x/irq-lpd7a40x.c 2005-07-09 13:10:41.000000000 +0200 @@ -71,6 +71,7 @@ desc->chip->unmask (irq); /* Level-triggered need this */ } +static DEFINE_IRQ_CHAINED_TYPE(lh7a40x_cpld_handler); /* IRQ initialization */ diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-lh7a40x/time.c linux-2.6.13-rc2-armirq/arch/arm/mach-lh7a40x/time.c --- linux-2.6.13-rc2/arch/arm/mach-lh7a40x/time.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-lh7a40x/time.c 2005-07-09 13:10:41.000000000 +0200 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-omap/fpga.c linux-2.6.13-rc2-armirq/arch/arm/mach-omap/fpga.c --- linux-2.6.13-rc2/arch/arm/mach-omap/fpga.c 2005-07-09 13:04:34.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-omap/fpga.c 2005-07-09 13:10:41.000000000 +0200 @@ -102,7 +102,7 @@ fpga_irq++, stat >>= 1) { if (stat & 1) { d = irq_desc + fpga_irq; - d->handle(fpga_irq, d, regs); + desc_lock_handle_irq(fpga_irq, d, regs); } } } @@ -120,6 +120,8 @@ .unmask = fpga_unmask_irq, }; +static DEFINE_IRQ_CHAINED_TYPE(innovator_fpga_IRQ_demux); + /* * All of the FPGA interrupt request inputs except for the touchscreen are * edge-sensitive; the touchscreen is level-sensitive. The edge-sensitive diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-omap/gpio.c linux-2.6.13-rc2-armirq/arch/arm/mach-omap/gpio.c --- linux-2.6.13-rc2/arch/arm/mach-omap/gpio.c 2005-07-09 13:04:34.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-omap/gpio.c 2005-07-09 13:10:41.000000000 +0200 @@ -590,7 +590,7 @@ if (!(isr & 1)) continue; d = irq_desc + gpio_irq; - d->handle(gpio_irq, d, regs); + desc_lock_handle_irq(gpio_irq, d, regs); } } @@ -656,6 +656,8 @@ .unmask = mpuio_unmask_irq }; +static DEFINE_IRQ_CHAINED_TYPE(gpio_irq_handler); + static int initialized = 0; static int __init _omap_gpio_init(void) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-pxa/idp.c linux-2.6.13-rc2-armirq/arch/arm/mach-pxa/idp.c --- linux-2.6.13-rc2/arch/arm/mach-pxa/idp.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-pxa/idp.c 2005-07-09 13:10:41.000000000 +0200 @@ -18,6 +18,7 @@ #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-pxa/irq.c linux-2.6.13-rc2-armirq/arch/arm/mach-pxa/irq.c --- linux-2.6.13-rc2/arch/arm/mach-pxa/irq.c 2005-07-09 13:04:33.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-pxa/irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -133,7 +133,7 @@ .ack = pxa_ack_low_gpio, .mask = pxa_mask_low_irq, .unmask = pxa_unmask_low_irq, - .type = pxa_gpio_irq_type, + .set_type = pxa_gpio_irq_type, }; /* @@ -157,7 +157,7 @@ mask >>= 2; do { if (mask & 1) - desc->handle(irq, desc, regs); + desc_lock_handle_irq(irq, desc, regs); irq++; desc++; mask >>= 1; @@ -172,7 +172,7 @@ desc = irq_desc + irq; do { if (mask & 1) - desc->handle(irq, desc, regs); + desc_lock_handle_irq(irq, desc, regs); irq++; desc++; mask >>= 1; @@ -187,7 +187,7 @@ desc = irq_desc + irq; do { if (mask & 1) - desc->handle(irq, desc, regs); + desc_lock_handle_irq(irq, desc, regs); irq++; desc++; mask >>= 1; @@ -203,7 +203,7 @@ desc = irq_desc + irq; do { if (mask & 1) - desc->handle(irq, desc, regs); + desc_lock_handle_irq(irq, desc, regs); irq++; desc++; mask >>= 1; @@ -241,9 +241,10 @@ .ack = pxa_ack_muxed_gpio, .mask = pxa_mask_muxed_gpio, .unmask = pxa_unmask_muxed_gpio, - .type = pxa_gpio_irq_type, + .set_type = pxa_gpio_irq_type, }; +static DEFINE_IRQ_CHAINED_TYPE(pxa_gpio_demux_handler); void __init pxa_init_irq(void) { diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-pxa/lubbock.c linux-2.6.13-rc2-armirq/arch/arm/mach-pxa/lubbock.c --- linux-2.6.13-rc2/arch/arm/mach-pxa/lubbock.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-pxa/lubbock.c 2005-07-09 13:10:41.000000000 +0200 @@ -84,12 +84,14 @@ if (likely(pending)) { irq = LUBBOCK_IRQ(0) + __ffs(pending); desc = irq_desc + irq; - desc->handle(irq, desc, regs); + desc_lock_handle_irq(irq, desc, regs); } pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled; } while (pending); } +static DEFINE_IRQ_CHAINED_TYPE(lubbock_irq_handler); + static void __init lubbock_init_irq(void) { int irq; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-pxa/mainstone.c linux-2.6.13-rc2-armirq/arch/arm/mach-pxa/mainstone.c --- linux-2.6.13-rc2/arch/arm/mach-pxa/mainstone.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-pxa/mainstone.c 2005-07-09 13:10:41.000000000 +0200 @@ -72,12 +72,14 @@ if (likely(pending)) { irq = MAINSTONE_IRQ(0) + __ffs(pending); desc = irq_desc + irq; - desc->handle(irq, desc, regs); + desc_lock_handle_irq(irq, desc, regs); } pending = MST_INTSETCLR & mainstone_irq_enabled; } while (pending); } +static DEFINE_IRQ_CHAINED_TYPE(mainstone_irq_handler); + static void __init mainstone_init_irq(void) { int irq; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-rpc/irq.c linux-2.6.13-rc2-armirq/arch/arm/mach-rpc/irq.c --- linux-2.6.13-rc2/arch/arm/mach-rpc/irq.c 2005-07-09 13:04:34.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-rpc/irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -112,6 +112,15 @@ .unmask = iomd_unmask_irq_fiq, }; +static unsigned int startup_irq_disabled(unsigned int irq) +{ + return 0; +} + +/* Interrupt type for irqs which must not be + * automatically enabled in reqeust_irq */ +static struct irq_type level_type_nostart; + void __init rpc_init_irq(void) { unsigned int irq, flags; @@ -121,16 +130,15 @@ iomd_writeb(0, IOMD_FIQMASK); iomd_writeb(0, IOMD_DMAMASK); + level_type_nostart = default_level_type; + level_type_nostart.startup = startup_irq_disabled; + for (irq = 0; irq < NR_IRQS; irq++) { flags = IRQF_VALID; if (irq <= 6 || (irq >= 9 && irq <= 15)) flags |= IRQF_PROBE; - if (irq == 21 || (irq >= 16 && irq <= 19) || - irq == IRQ_KEYBOARDTX) - flags |= IRQF_NOAUTOEN; - switch (irq) { case 0 ... 7: set_irq_chip(irq, &iomd_a_chip); @@ -155,6 +163,10 @@ set_irq_flags(irq, IRQF_VALID); break; } + + if (irq == 21 || (irq >= 16 && irq <= 19) || + irq == IRQ_KEYBOARDTX) + set_irq_handler(irq, &level_type_nostart); } init_FIQ(); diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-s3c2410/bast-irq.c linux-2.6.13-rc2-armirq/arch/arm/mach-s3c2410/bast-irq.c --- linux-2.6.13-rc2/arch/arm/mach-s3c2410/bast-irq.c 2005-07-09 13:04:33.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-s3c2410/bast-irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -124,7 +124,7 @@ irqno = bast_pc104_irqs[i]; desc = irq_desc + irqno; - desc->handle(irqno, desc, regs); + desc_lock_handle_irq(irqno, desc, regs); } stat >>= 1; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-s3c2410/irq.c linux-2.6.13-rc2-armirq/arch/arm/mach-s3c2410/irq.c --- linux-2.6.13-rc2/arch/arm/mach-s3c2410/irq.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-s3c2410/irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -185,14 +185,14 @@ .ack = s3c_irq_maskack, .mask = s3c_irq_mask, .unmask = s3c_irq_unmask, - .wake = s3c_irq_wake + .set_wake = s3c_irq_wake }; static struct irqchip s3c_irq_chip = { .ack = s3c_irq_ack, .mask = s3c_irq_mask, .unmask = s3c_irq_unmask, - .wake = s3c_irq_wake + .set_wake = s3c_irq_wake }; /* S3C2410_EINTMASK @@ -351,16 +351,16 @@ .mask = s3c_irqext_mask, .unmask = s3c_irqext_unmask, .ack = s3c_irqext_ack, - .type = s3c_irqext_type, - .wake = s3c_irqext_wake + .set_type = s3c_irqext_type, + .set_wake = s3c_irqext_wake }; static struct irqchip s3c_irq_eint0t4 = { .ack = s3c_irq_ack, .mask = s3c_irq_mask, .unmask = s3c_irq_unmask, - .wake = s3c_irq_wake, - .type = s3c_irqext_type, + .set_wake = s3c_irq_wake, + .set_type = s3c_irqext_type, }; /* mask values for the parent registers for each of the interrupt types */ @@ -575,11 +575,11 @@ if (subsrc != 0) { if (subsrc & 1) { mydesc = irq_desc + IRQ_TC; - mydesc->handle( IRQ_TC, mydesc, regs); + desc_lock_handle_irq( IRQ_TC, mydesc, regs); } if (subsrc & 2) { mydesc = irq_desc + IRQ_ADC; - mydesc->handle(IRQ_ADC, mydesc, regs); + desc_lock_handle_irq(IRQ_ADC, mydesc, regs); } } } @@ -608,17 +608,17 @@ desc = irq_desc + start; if (subsrc & 1) - desc->handle(start, desc, regs); + desc_lock_handle_irq(start, desc, regs); desc++; if (subsrc & 2) - desc->handle(start+1, desc, regs); + desc_lock_handle_irq(start+1, desc, regs); desc++; if (subsrc & 4) - desc->handle(start+2, desc, regs); + desc_lock_handle_irq(start+2, desc, regs); } } @@ -652,6 +652,11 @@ } +static DEFINE_IRQ_CHAINED_TYPE(s3c_irq_demux_uart0); +static DEFINE_IRQ_CHAINED_TYPE(s3c_irq_demux_uart1); +static DEFINE_IRQ_CHAINED_TYPE(s3c_irq_demux_uart2); +static DEFINE_IRQ_CHAINED_TYPE(s3c_irq_demux_adc); + /* s3c24xx_init_irq * * Initialise S3C2410 IRQ system @@ -822,11 +827,11 @@ if (subsrc != 0) { if (subsrc & 1) { mydesc = irq_desc + IRQ_S3C2440_WDT; - mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs); + desc_lock_handle_irq(IRQ_S3C2440_WDT, mydesc, regs); } if (subsrc & 2) { mydesc = irq_desc + IRQ_S3C2440_AC97; - mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs); + desc_lock_handle_irq(IRQ_S3C2440_AC97, mydesc, regs); } } } @@ -880,11 +885,11 @@ if (subsrc != 0) { if (subsrc & 1) { mydesc = irq_desc + IRQ_S3C2440_CAM_C; - mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs); + desc_lock_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs); } if (subsrc & 2) { mydesc = irq_desc + IRQ_S3C2440_CAM_P; - mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs); + desc_lock_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs); } } } @@ -915,6 +920,9 @@ .ack = s3c_irq_cam_ack, }; +static DEFINE_IRQ_CHAINED_TYPE(s3c_irq_demux_wdtac97); +static DEFINE_IRQ_CHAINED_TYPE(s3c_irq_demux_cam); + static int s3c2440_irq_add(struct sys_device *sysdev) { unsigned int irqno; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-s3c2410/time.c linux-2.6.13-rc2-armirq/arch/arm/mach-s3c2410/time.c --- linux-2.6.13-rc2/arch/arm/mach-s3c2410/time.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-s3c2410/time.c 2005-07-09 13:10:41.000000000 +0200 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-sa1100/cerf.c linux-2.6.13-rc2-armirq/arch/arm/mach-sa1100/cerf.c --- linux-2.6.13-rc2/arch/arm/mach-sa1100/cerf.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-sa1100/cerf.c 2005-07-09 13:10:41.000000000 +0200 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-sa1100/h3600.c linux-2.6.13-rc2-armirq/arch/arm/mach-sa1100/h3600.c --- linux-2.6.13-rc2/arch/arm/mach-sa1100/h3600.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-sa1100/h3600.c 2005-07-09 13:10:41.000000000 +0200 @@ -788,6 +788,8 @@ H3800_ASIC2_GPIINTSTAT |= mask; } +static DEFINE_IRQ_CHAINED_TYPE(h3800_IRQ_demux); + static void __init h3800_init_irq(void) { int i; @@ -826,7 +828,7 @@ } #endif set_irq_type(IRQ_GPIO_H3800_ASIC, IRQT_RISING); - set_irq_chained_handler(IRQ_GPIO_H3800_ASIC, &h3800_IRQ_demux); + set_irq_chained_handler(IRQ_GPIO_H3800_ASIC, h3800_IRQ_demux); } diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-sa1100/irq.c linux-2.6.13-rc2-armirq/arch/arm/mach-sa1100/irq.c --- linux-2.6.13-rc2/arch/arm/mach-sa1100/irq.c 2005-07-09 13:04:34.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-sa1100/irq.c 2005-07-09 16:10:08.000000000 +0200 @@ -11,12 +11,13 @@ */ #include #include +#include +#include #include #include #include #include -#include #include #include "generic.h" @@ -98,8 +99,8 @@ .ack = sa1100_low_gpio_ack, .mask = sa1100_low_gpio_mask, .unmask = sa1100_low_gpio_unmask, - .type = sa1100_gpio_type, - .wake = sa1100_low_gpio_wake, + .set_type = sa1100_gpio_type, + .set_wake = sa1100_low_gpio_wake, }; /* @@ -126,7 +127,7 @@ mask >>= 11; do { if (mask & 1) - desc->handle(irq, desc, regs); + desc_lock_handle_irq(irq, desc, regs); mask >>= 1; irq++; desc++; @@ -181,8 +182,8 @@ .ack = sa1100_high_gpio_ack, .mask = sa1100_high_gpio_mask, .unmask = sa1100_high_gpio_unmask, - .type = sa1100_gpio_type, - .wake = sa1100_high_gpio_wake, + .set_type = sa1100_gpio_type, + .set_wake = sa1100_high_gpio_wake, }; /* @@ -281,6 +282,8 @@ return sysdev_register(&sa1100irq_device); } +static DEFINE_IRQ_CHAINED_TYPE(sa1100_high_gpio_handler); + device_initcall(sa1100irq_init_devicefs); void __init sa1100_init_irq(void) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-sa1100/neponset.c linux-2.6.13-rc2-armirq/arch/arm/mach-sa1100/neponset.c --- linux-2.6.13-rc2/arch/arm/mach-sa1100/neponset.c 2005-07-09 13:04:34.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-sa1100/neponset.c 2005-07-09 13:10:41.000000000 +0200 @@ -61,12 +61,12 @@ if (irr & IRR_ETHERNET) { d = irq_desc + IRQ_NEPONSET_SMC9196; - d->handle(IRQ_NEPONSET_SMC9196, d, regs); + desc_lock_handle_irq(IRQ_NEPONSET_SMC9196, d, regs); } if (irr & IRR_USAR) { d = irq_desc + IRQ_NEPONSET_USAR; - d->handle(IRQ_NEPONSET_USAR, d, regs); + desc_lock_handle_irq(IRQ_NEPONSET_USAR, d, regs); } desc->chip->unmask(irq); @@ -74,7 +74,7 @@ if (irr & IRR_SA1111) { d = irq_desc + IRQ_NEPONSET_SA1111; - d->handle(IRQ_NEPONSET_SA1111, d, regs); + desc_lock_handle_irq(IRQ_NEPONSET_SA1111, d, regs); } } } @@ -137,6 +137,8 @@ .get_mctrl = neponset_get_mctrl, }; +static DEFINE_IRQ_CHAINED_TYPE(neponset_irq_handler); + static int neponset_probe(struct device *dev) { sa1100_register_uart_fns(&neponset_port_fns); diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-sa1100/pleb.c linux-2.6.13-rc2-armirq/arch/arm/mach-sa1100/pleb.c --- linux-2.6.13-rc2/arch/arm/mach-sa1100/pleb.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-sa1100/pleb.c 2005-07-09 13:10:41.000000000 +0200 @@ -7,6 +7,7 @@ #include #include #include +#include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-sa1100/time.c linux-2.6.13-rc2-armirq/arch/arm/mach-sa1100/time.c --- linux-2.6.13-rc2/arch/arm/mach-sa1100/time.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-sa1100/time.c 2005-07-09 13:10:41.000000000 +0200 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-shark/core.c linux-2.6.13-rc2-armirq/arch/arm/mach-shark/core.c --- linux-2.6.13-rc2/arch/arm/mach-shark/core.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-shark/core.c 2005-07-10 21:42:25.000000000 +0200 @@ -6,6 +6,7 @@ #include #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/arch/arm/mach-versatile/core.c linux-2.6.13-rc2-armirq/arch/arm/mach-versatile/core.c --- linux-2.6.13-rc2/arch/arm/mach-versatile/core.c 2005-07-09 13:08:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/arm/mach-versatile/core.c 2005-07-09 13:10:41.000000000 +0200 @@ -108,10 +108,12 @@ irq += IRQ_SIC_START; desc = irq_desc + irq; - desc->handle(irq, desc, regs); + desc_lock_handle_irq(irq, desc, regs); } while (status); } +static DEFINE_IRQ_CHAINED_TYPE(sic_handle_irq); + #if 1 #define IRQ_MMCI0A IRQ_VICSOURCE22 #define IRQ_AACI IRQ_VICSOURCE24 @@ -161,7 +163,7 @@ } } - set_irq_handler(IRQ_VICSOURCE31, sic_handle_irq); + set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq); vic_unmask_irq(IRQ_VICSOURCE31); /* Do second interrupt controller */ diff -urN --exclude='*~' linux-2.6.13-rc2/arch/ia64/sn/kernel/irq.c linux-2.6.13-rc2-armirq/arch/ia64/sn/kernel/irq.c --- linux-2.6.13-rc2/arch/ia64/sn/kernel/irq.c 2005-07-09 13:04:29.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/ia64/sn/kernel/irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -183,14 +183,14 @@ } struct hw_interrupt_type irq_type_sn = { - "SN hub", - sn_startup_irq, - sn_shutdown_irq, - sn_enable_irq, - sn_disable_irq, - sn_ack_irq, - sn_end_irq, - sn_set_affinity_irq + .typename = "SN hub", + .startup = sn_startup_irq, + .shutdown = sn_shutdown_irq, + .enable = sn_enable_irq, + .disable = sn_disable_irq, + .ack = sn_ack_irq, + .end = sn_end_irq, + .set_affinity = sn_set_affinity_irq }; unsigned int sn_local_vector_to_irq(u8 vector) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/au1000/common/irq.c linux-2.6.13-rc2-armirq/arch/mips/au1000/common/irq.c --- linux-2.6.13-rc2/arch/mips/au1000/common/irq.c 2005-07-09 13:04:25.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/au1000/common/irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -253,47 +253,43 @@ static struct hw_interrupt_type rise_edge_irq_type = { - "Au1000 Rise Edge", - startup_irq, - shutdown_irq, - local_enable_irq, - local_disable_irq, - mask_and_ack_rise_edge_irq, - end_irq, - NULL + .typename = "Au1000 Rise Edge", + .startup = startup_irq, + .shutdown = shutdown_irq, + .enable = local_enable_irq, + .disable = local_disable_irq, + .ack = mask_and_ack_rise_edge_irq, + .end = end_irq, }; static struct hw_interrupt_type fall_edge_irq_type = { - "Au1000 Fall Edge", - startup_irq, - shutdown_irq, - local_enable_irq, - local_disable_irq, - mask_and_ack_fall_edge_irq, - end_irq, - NULL + .typename = "Au1000 Fall Edge", + .startup = startup_irq, + .shutdown = shutdown_irq, + .enable = local_enable_irq, + .disable = local_disable_irq, + .ack = mask_and_ack_fall_edge_irq, + .end = end_irq, }; static struct hw_interrupt_type either_edge_irq_type = { - "Au1000 Rise or Fall Edge", - startup_irq, - shutdown_irq, - local_enable_irq, - local_disable_irq, - mask_and_ack_either_edge_irq, - end_irq, - NULL + .typename = "Au1000 Rise or Fall Edge", + .startup = startup_irq, + .shutdown = shutdown_irq, + .enable = local_enable_irq, + .disable = local_disable_irq, + .ack = mask_and_ack_either_edge_irq, + .end = end_irq, }; static struct hw_interrupt_type level_irq_type = { - "Au1000 Level", - startup_irq, - shutdown_irq, - local_enable_irq, - local_disable_irq, - mask_and_ack_level_irq, - end_irq, - NULL + .typename = "Au1000 Level", + .startup = startup_irq, + .shutdown = shutdown_irq, + .enable = local_enable_irq, + .disable = local_disable_irq, + .ack = mask_and_ack_level_irq, + .end = end_irq, }; #ifdef CONFIG_PM diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/ddb5xxx/ddb5074/nile4_pic.c linux-2.6.13-rc2-armirq/arch/mips/ddb5xxx/ddb5074/nile4_pic.c --- linux-2.6.13-rc2/arch/mips/ddb5xxx/ddb5074/nile4_pic.c 2005-07-09 13:04:25.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/ddb5xxx/ddb5074/nile4_pic.c 2005-07-09 13:10:41.000000000 +0200 @@ -209,14 +209,13 @@ #define nile4_irq_shutdown nile4_disable_irq static hw_irq_controller nile4_irq_controller = { - "nile4", - nile4_irq_startup, - nile4_irq_shutdown, - nile4_enable_irq, - nile4_disable_irq, - nile4_ack_irq, - nile4_irq_end, - NULL + .typename = "nile4", + .startup = nile4_irq_startup, + .shutdown = nile4_irq_shutdown, + .enable = nile4_enable_irq, + .disable = nile4_disable_irq, + .ack = nile4_ack_irq, + .end = nile4_irq_end, }; void nile4_irq_setup(u32 base) { diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c linux-2.6.13-rc2-armirq/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c --- linux-2.6.13-rc2/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c 2005-07-09 13:04:25.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -53,14 +53,13 @@ } static hw_irq_controller vrc5476_irq_controller = { - "vrc5476", - vrc5476_irq_startup, - vrc5476_irq_shutdown, - vrc5476_irq_enable, - vrc5476_irq_disable, - vrc5476_irq_ack, - vrc5476_irq_end, - NULL /* no affinity stuff for UP */ + .typename = "vrc5476", + .startup = vrc5476_irq_startup, + .shutdown = vrc5476_irq_shutdown, + .enable = vrc5476_irq_enable, + .disable = vrc5476_irq_disable, + .ack = vrc5476_irq_ack, + .end = vrc5476_irq_end }; void __init diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/ddb5xxx/ddb5477/irq_5477.c linux-2.6.13-rc2-armirq/arch/mips/ddb5xxx/ddb5477/irq_5477.c --- linux-2.6.13-rc2/arch/mips/ddb5xxx/ddb5477/irq_5477.c 2005-07-09 13:04:25.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/ddb5xxx/ddb5477/irq_5477.c 2005-07-09 13:10:41.000000000 +0200 @@ -90,14 +90,13 @@ } hw_irq_controller vrc5477_irq_controller = { - "vrc5477_irq", - vrc5477_irq_startup, - vrc5477_irq_shutdown, - vrc5477_irq_enable, - vrc5477_irq_disable, - vrc5477_irq_ack, - vrc5477_irq_end, - NULL /* no affinity stuff for UP */ + .typename = "vrc5477_irq", + .startup = vrc5477_irq_startup, + .shutdown = vrc5477_irq_shutdown, + .enable = vrc5477_irq_enable, + .disable = vrc5477_irq_disable, + .ack = vrc5477_irq_ack, + .end = vrc5477_irq_end }; void __init vrc5477_irq_init(u32 irq_base) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/ite-boards/generic/irq.c linux-2.6.13-rc2-armirq/arch/mips/ite-boards/generic/irq.c --- linux-2.6.13-rc2/arch/mips/ite-boards/generic/irq.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/ite-boards/generic/irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -138,14 +138,13 @@ } static struct hw_interrupt_type it8172_irq_type = { - "ITE8172", - startup_ite_irq, - shutdown_ite_irq, - enable_it8172_irq, - disable_it8172_irq, - mask_and_ack_ite_irq, - end_ite_irq, - NULL + .typename = "ITE8172", + .startup = startup_ite_irq, + .shutdown = shutdown_ite_irq, + .enable = enable_it8172_irq, + .disable = disable_it8172_irq, + .ack = mask_and_ack_ite_irq, + .end = end_ite_irq, }; @@ -159,13 +158,13 @@ #define end_none enable_none static struct hw_interrupt_type cp0_irq_type = { - "CP0 Count", - startup_none, - shutdown_none, - enable_none, - disable_none, - ack_none, - end_none + .typename = "CP0 Count", + .startup = startup_none, + .shutdown = shutdown_none, + .enable = enable_none, + .disable = disable_none, + .ack = ack_none, + .end = end_none }; void enable_cpu_timer(void) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/jazz/irq.c linux-2.6.13-rc2-armirq/arch/mips/jazz/irq.c --- linux-2.6.13-rc2/arch/mips/jazz/irq.c 2005-07-09 13:04:25.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/jazz/irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -58,14 +58,13 @@ } static struct hw_interrupt_type r4030_irq_type = { - "R4030", - startup_r4030_irq, - shutdown_r4030_irq, - enable_r4030_irq, - disable_r4030_irq, - mask_and_ack_r4030_irq, - end_r4030_irq, - NULL + .typename = "R4030", + .startup = startup_r4030_irq, + .shutdown = shutdown_r4030_irq, + .enable = enable_r4030_irq, + .disable = disable_r4030_irq, + .ack = mask_and_ack_r4030_irq, + .end = end_r4030_irq, }; void __init init_r4030_ints(void) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/jmr3927/rbhma3100/irq.c linux-2.6.13-rc2-armirq/arch/mips/jmr3927/rbhma3100/irq.c --- linux-2.6.13-rc2/arch/mips/jmr3927/rbhma3100/irq.c 2005-07-09 13:04:25.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/jmr3927/rbhma3100/irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -412,13 +412,13 @@ } static hw_irq_controller jmr3927_irq_controller = { - "jmr3927_irq", - jmr3927_irq_startup, - jmr3927_irq_shutdown, - jmr3927_irq_enable, - jmr3927_irq_disable, - jmr3927_irq_ack, - jmr3927_irq_end, + .typename = "jmr3927_irq", + .startup = jmr3927_irq_startup, + .shutdown = jmr3927_irq_shutdown, + .enable = jmr3927_irq_enable, + .disable = jmr3927_irq_disable, + .ack = jmr3927_irq_ack, + .end = jmr3927_irq_end, }; void jmr3927_irq_init(u32 irq_base) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/kernel/i8259.c linux-2.6.13-rc2-armirq/arch/mips/kernel/i8259.c --- linux-2.6.13-rc2/arch/mips/kernel/i8259.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/kernel/i8259.c 2005-07-09 13:10:41.000000000 +0200 @@ -52,14 +52,13 @@ } static struct hw_interrupt_type i8259A_irq_type = { - "XT-PIC", - startup_8259A_irq, - shutdown_8259A_irq, - enable_8259A_irq, - disable_8259A_irq, - mask_and_ack_8259A, - end_8259A_irq, - NULL + .typename = "XT-PIC", + .startup = startup_8259A_irq, + .shutdown = shutdown_8259A_irq, + .enable = enable_8259A_irq, + .disable = disable_8259A_irq, + .ack = mask_and_ack_8259A, + .end = end_8259A_irq, }; /* diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/kernel/irq-msc01.c linux-2.6.13-rc2-armirq/arch/mips/kernel/irq-msc01.c --- linux-2.6.13-rc2/arch/mips/kernel/irq-msc01.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/kernel/irq-msc01.c 2005-07-09 13:10:41.000000000 +0200 @@ -129,25 +129,23 @@ #define shutdown_msc_irq disable_msc_irq struct hw_interrupt_type msc_levelirq_type = { - "SOC-it-Level", - startup_msc_irq, - shutdown_msc_irq, - enable_msc_irq, - disable_msc_irq, - level_mask_and_ack_msc_irq, - end_msc_irq, - NULL + .typename = "SOC-it-Level", + .startup = startup_msc_irq, + .shutdown = shutdown_msc_irq, + .enable = enable_msc_irq, + .disable = disable_msc_irq, + .ack = level_mask_and_ack_msc_irq, + .end = end_msc_irq, }; struct hw_interrupt_type msc_edgeirq_type = { - "SOC-it-Edge", - startup_msc_irq, - shutdown_msc_irq, - enable_msc_irq, - disable_msc_irq, - edge_mask_and_ack_msc_irq, - end_msc_irq, - NULL + .typename = "SOC-it-Edge", + .startup =startup_msc_irq, + .shutdown = shutdown_msc_irq, + .enable = enable_msc_irq, + .disable = disable_msc_irq, + .ack = edge_mask_and_ack_msc_irq, + .end = end_msc_irq, }; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/kernel/irq-mv6434x.c linux-2.6.13-rc2-armirq/arch/mips/kernel/irq-mv6434x.c --- linux-2.6.13-rc2/arch/mips/kernel/irq-mv6434x.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/kernel/irq-mv6434x.c 2005-07-09 13:10:41.000000000 +0200 @@ -135,14 +135,13 @@ #define shutdown_mv64340_irq disable_mv64340_irq struct hw_interrupt_type mv64340_irq_type = { - "MV-64340", - startup_mv64340_irq, - shutdown_mv64340_irq, - enable_mv64340_irq, - disable_mv64340_irq, - mask_and_ack_mv64340_irq, - end_mv64340_irq, - NULL + .typename = "MV-64340", + .startup = startup_mv64340_irq, + .shutdown = shutdown_mv64340_irq, + .enable = enable_mv64340_irq, + .disable = disable_mv64340_irq, + .ack = mask_and_ack_mv64340_irq, + .end = end_mv64340_irq, }; void __init mv64340_irq_init(unsigned int base) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/kernel/irq-rm7000.c linux-2.6.13-rc2-armirq/arch/mips/kernel/irq-rm7000.c --- linux-2.6.13-rc2/arch/mips/kernel/irq-rm7000.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/kernel/irq-rm7000.c 2005-07-09 13:10:41.000000000 +0200 @@ -72,13 +72,13 @@ } static hw_irq_controller rm7k_irq_controller = { - "RM7000", - rm7k_cpu_irq_startup, - rm7k_cpu_irq_shutdown, - rm7k_cpu_irq_enable, - rm7k_cpu_irq_disable, - rm7k_cpu_irq_ack, - rm7k_cpu_irq_end, + .typename = "RM7000", + .startup = rm7k_cpu_irq_startup, + .shutdown = rm7k_cpu_irq_shutdown, + .enable = rm7k_cpu_irq_enable, + .disable = rm7k_cpu_irq_disable, + .ack = rm7k_cpu_irq_ack, + .end = rm7k_cpu_irq_end, }; void __init rm7k_cpu_irq_init(int base) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/kernel/irq-rm9000.c linux-2.6.13-rc2-armirq/arch/mips/kernel/irq-rm9000.c --- linux-2.6.13-rc2/arch/mips/kernel/irq-rm9000.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/kernel/irq-rm9000.c 2005-07-09 13:10:41.000000000 +0200 @@ -106,23 +106,23 @@ } static hw_irq_controller rm9k_irq_controller = { - "RM9000", - rm9k_cpu_irq_startup, - rm9k_cpu_irq_shutdown, - rm9k_cpu_irq_enable, - rm9k_cpu_irq_disable, - rm9k_cpu_irq_ack, - rm9k_cpu_irq_end, + .typename = "RM9000", + .startup = rm9k_cpu_irq_startup, + .shutdown = rm9k_cpu_irq_shutdown, + .enable = rm9k_cpu_irq_enable, + .disable = rm9k_cpu_irq_disable, + .ack = rm9k_cpu_irq_ack, + .end = rm9k_cpu_irq_end, }; static hw_irq_controller rm9k_perfcounter_irq = { - "RM9000", - rm9k_perfcounter_irq_startup, - rm9k_perfcounter_irq_shutdown, - rm9k_cpu_irq_enable, - rm9k_cpu_irq_disable, - rm9k_cpu_irq_ack, - rm9k_cpu_irq_end, + .typename = "RM9000", + .startup = rm9k_perfcounter_irq_startup, + .shutdown = rm9k_perfcounter_irq_shutdown, + .enable = rm9k_cpu_irq_enable, + .disable = rm9k_cpu_irq_disable, + .ack = rm9k_cpu_irq_ack, + .end = rm9k_cpu_irq_end, }; unsigned int rm9000_perfcount_irq; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/kernel/irq_cpu.c linux-2.6.13-rc2-armirq/arch/mips/kernel/irq_cpu.c --- linux-2.6.13-rc2/arch/mips/kernel/irq_cpu.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/kernel/irq_cpu.c 2005-07-09 13:10:41.000000000 +0200 @@ -92,14 +92,13 @@ } static hw_irq_controller mips_cpu_irq_controller = { - "MIPS", - mips_cpu_irq_startup, - mips_cpu_irq_shutdown, - mips_cpu_irq_enable, - mips_cpu_irq_disable, - mips_cpu_irq_ack, - mips_cpu_irq_end, - NULL /* no affinity stuff for UP */ + .typename = "MIPS", + .startup = mips_cpu_irq_startup, + .shutdown = mips_cpu_irq_shutdown, + .enable = mips_cpu_irq_enable, + .disable = mips_cpu_irq_disable, + .ack = mips_cpu_irq_ack, + .end = mips_cpu_irq_end, }; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/lasat/interrupt.c linux-2.6.13-rc2-armirq/arch/mips/lasat/interrupt.c --- linux-2.6.13-rc2/arch/mips/lasat/interrupt.c 2005-07-09 13:04:25.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/lasat/interrupt.c 2005-07-09 13:10:41.000000000 +0200 @@ -71,14 +71,13 @@ } static struct hw_interrupt_type lasat_irq_type = { - "Lasat", - startup_lasat_irq, - shutdown_lasat_irq, - enable_lasat_irq, - disable_lasat_irq, - mask_and_ack_lasat_irq, - end_lasat_irq, - NULL + .typename = "Lasat", + .startup = startup_lasat_irq, + .shutdown = shutdown_lasat_irq, + .enable = enable_lasat_irq, + .disable = disable_lasat_irq, + .ack = mask_and_ack_lasat_irq, + .end = end_lasat_irq, }; static inline int ls1bit32(unsigned int x) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/mips-boards/atlas/atlas_int.c linux-2.6.13-rc2-armirq/arch/mips/mips-boards/atlas/atlas_int.c --- linux-2.6.13-rc2/arch/mips/mips-boards/atlas/atlas_int.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/mips-boards/atlas/atlas_int.c 2005-07-09 13:10:41.000000000 +0200 @@ -76,14 +76,13 @@ } static struct hw_interrupt_type atlas_irq_type = { - "Atlas", - startup_atlas_irq, - shutdown_atlas_irq, - enable_atlas_irq, - disable_atlas_irq, - mask_and_ack_atlas_irq, - end_atlas_irq, - NULL + .typename = "Atlas", + .startup = startup_atlas_irq, + .shutdown = shutdown_atlas_irq, + .enable = enable_atlas_irq, + .disable = disable_atlas_irq, + .ack = mask_and_ack_atlas_irq, + .end = end_atlas_irq, }; static inline int ls1bit32(unsigned int x) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/momentum/ocelot_c/cpci-irq.c linux-2.6.13-rc2-armirq/arch/mips/momentum/ocelot_c/cpci-irq.c --- linux-2.6.13-rc2/arch/mips/momentum/ocelot_c/cpci-irq.c 2005-07-09 13:04:25.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/momentum/ocelot_c/cpci-irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -129,14 +129,13 @@ #define shutdown_cpci_irq disable_cpci_irq struct hw_interrupt_type cpci_irq_type = { - "CPCI/FPGA", - startup_cpci_irq, - shutdown_cpci_irq, - enable_cpci_irq, - disable_cpci_irq, - mask_and_ack_cpci_irq, - end_cpci_irq, - NULL + .typename = "CPCI/FPGA", + .startup = startup_cpci_irq, + .shutdown = shutdown_cpci_irq, + .enable = enable_cpci_irq, + .disable = disable_cpci_irq, + .ack = mask_and_ack_cpci_irq, + .end = end_cpci_irq, }; void cpci_irq_init(void) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/momentum/ocelot_c/uart-irq.c linux-2.6.13-rc2-armirq/arch/mips/momentum/ocelot_c/uart-irq.c --- linux-2.6.13-rc2/arch/mips/momentum/ocelot_c/uart-irq.c 2005-07-09 13:04:25.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/momentum/ocelot_c/uart-irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -122,14 +122,13 @@ #define shutdown_uart_irq disable_uart_irq struct hw_interrupt_type uart_irq_type = { - "UART/FPGA", - startup_uart_irq, - shutdown_uart_irq, - enable_uart_irq, - disable_uart_irq, - mask_and_ack_uart_irq, - end_uart_irq, - NULL + .typename = "UART/FPGA", + .startup = startup_uart_irq, + .shutdown = shutdown_uart_irq, + .enable = enable_uart_irq, + .disable = disable_uart_irq, + .ack = mask_and_ack_uart_irq, + .end = end_uart_irq, }; void uart_irq_init(void) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/sgi-ip32/ip32-irq.c linux-2.6.13-rc2-armirq/arch/mips/sgi-ip32/ip32-irq.c --- linux-2.6.13-rc2/arch/mips/sgi-ip32/ip32-irq.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/sgi-ip32/ip32-irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -163,14 +163,13 @@ #define mask_and_ack_cpu_irq disable_cpu_irq static struct hw_interrupt_type ip32_cpu_interrupt = { - "IP32 CPU", - startup_cpu_irq, - shutdown_cpu_irq, - enable_cpu_irq, - disable_cpu_irq, - mask_and_ack_cpu_irq, - end_cpu_irq, - NULL + .typename = "IP32 CPU", + .startup = startup_cpu_irq, + .shutdown = shutdown_cpu_irq, + .enable = enable_cpu_irq, + .disable = disable_cpu_irq, + .ack = mask_and_ack_cpu_irq, + .end = end_cpu_irq, }; /* @@ -234,14 +233,13 @@ #define shutdown_crime_irq disable_crime_irq static struct hw_interrupt_type ip32_crime_interrupt = { - "IP32 CRIME", - startup_crime_irq, - shutdown_crime_irq, - enable_crime_irq, - disable_crime_irq, - mask_and_ack_crime_irq, - end_crime_irq, - NULL + .typename = "IP32 CRIME", + .startup = startup_crime_irq, + .shutdown = shutdown_crime_irq, + .enable = enable_crime_irq, + .disable = disable_crime_irq, + .ack = mask_and_ack_crime_irq, + .end = end_crime_irq, }; /* @@ -294,14 +292,13 @@ #define mask_and_ack_macepci_irq disable_macepci_irq static struct hw_interrupt_type ip32_macepci_interrupt = { - "IP32 MACE PCI", - startup_macepci_irq, - shutdown_macepci_irq, - enable_macepci_irq, - disable_macepci_irq, - mask_and_ack_macepci_irq, - end_macepci_irq, - NULL + .typename = "IP32 MACE PCI", + .startup = startup_macepci_irq, + .shutdown = shutdown_macepci_irq, + .enable = enable_macepci_irq, + .disable = disable_macepci_irq, + .ack = mask_and_ack_macepci_irq, + .end = end_macepci_irq, }; /* This is used for MACE ISA interrupts. That means bits 4-6 in the @@ -425,14 +422,13 @@ #define shutdown_maceisa_irq disable_maceisa_irq static struct hw_interrupt_type ip32_maceisa_interrupt = { - "IP32 MACE ISA", - startup_maceisa_irq, - shutdown_maceisa_irq, - enable_maceisa_irq, - disable_maceisa_irq, - mask_and_ack_maceisa_irq, - end_maceisa_irq, - NULL + .typename = "IP32 MACE ISA", + .startup = startup_maceisa_irq, + .shutdown = shutdown_maceisa_irq, + .enable = enable_maceisa_irq, + .disable = disable_maceisa_irq, + .ack = mask_and_ack_maceisa_irq, + .end = end_maceisa_irq, }; /* This is used for regular non-ISA, non-PCI MACE interrupts. That means @@ -476,14 +472,13 @@ #define mask_and_ack_mace_irq disable_mace_irq static struct hw_interrupt_type ip32_mace_interrupt = { - "IP32 MACE", - startup_mace_irq, - shutdown_mace_irq, - enable_mace_irq, - disable_mace_irq, - mask_and_ack_mace_irq, - end_mace_irq, - NULL + .typename = "IP32 MACE", + .startup = startup_mace_irq, + .shutdown = shutdown_mace_irq, + .enable = enable_mace_irq, + .disable = disable_mace_irq, + .ack = mask_and_ack_mace_irq, + .end = end_mace_irq, }; static void ip32_unknown_interrupt(struct pt_regs *regs) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/sibyte/sb1250/irq.c linux-2.6.13-rc2-armirq/arch/mips/sibyte/sb1250/irq.c --- linux-2.6.13-rc2/arch/mips/sibyte/sb1250/irq.c 2005-07-09 13:04:25.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/sibyte/sb1250/irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -71,17 +71,15 @@ #endif static struct hw_interrupt_type sb1250_irq_type = { - "SB1250-IMR", - startup_sb1250_irq, - shutdown_sb1250_irq, - enable_sb1250_irq, - disable_sb1250_irq, - ack_sb1250_irq, - end_sb1250_irq, + .typename = "SB1250-IMR", + .startup = startup_sb1250_irq, + .shutdown = shutdown_sb1250_irq, + .enable = enable_sb1250_irq, + .disable = disable_sb1250_irq, + .ack = ack_sb1250_irq, + .end = end_sb1250_irq, #ifdef CONFIG_SMP - sb1250_set_affinity -#else - NULL + .set_affinity = sb1250_set_affinity #endif }; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/sni/irq.c linux-2.6.13-rc2-armirq/arch/mips/sni/irq.c --- linux-2.6.13-rc2/arch/mips/sni/irq.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/sni/irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -58,14 +58,13 @@ } static struct hw_interrupt_type pciasic_irq_type = { - "ASIC-PCI", - startup_pciasic_irq, - shutdown_pciasic_irq, - enable_pciasic_irq, - disable_pciasic_irq, - mask_and_ack_pciasic_irq, - end_pciasic_irq, - NULL + .typename = "ASIC-PCI", + .startup = startup_pciasic_irq, + .shutdown = shutdown_pciasic_irq, + .enable = enable_pciasic_irq, + .disable = disable_pciasic_irq, + .ack = mask_and_ack_pciasic_irq, + .end = end_pciasic_irq, }; /* diff -urN --exclude='*~' linux-2.6.13-rc2/arch/mips/vr4181/common/irq.c linux-2.6.13-rc2-armirq/arch/mips/vr4181/common/irq.c --- linux-2.6.13-rc2/arch/mips/vr4181/common/irq.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/mips/vr4181/common/irq.c 2005-07-09 13:10:41.000000000 +0200 @@ -86,14 +86,13 @@ } static hw_irq_controller sys_irq_controller = { - "vr4181_sys_irq", - sys_irq_startup, - sys_irq_shutdown, - sys_irq_enable, - sys_irq_disable, - sys_irq_ack, - sys_irq_end, - NULL /* no affinity stuff for UP */ + .typename = "vr4181_sys_irq", + .startup = sys_irq_startup, + .shutdown = sys_irq_shutdown, + .enable = sys_irq_enable, + .disable = sys_irq_disable, + .ack = sys_irq_ack, + .end = sys_irq_end, }; /* ---------------------- gpio irq ------------------------ */ @@ -162,14 +161,13 @@ } static hw_irq_controller gpio_irq_controller = { - "vr4181_gpio_irq", - gpio_irq_startup, - gpio_irq_shutdown, - gpio_irq_enable, - gpio_irq_disable, - gpio_irq_ack, - gpio_irq_end, - NULL /* no affinity stuff for UP */ + .typename = "vr4181_gpio_irq", + .startup = gpio_irq_startup, + .shutdown = gpio_irq_shutdown, + .enable = gpio_irq_enable, + .disable = gpio_irq_disable, + .ack = gpio_irq_ack, + .end = gpio_irq_end, }; /* --------------------- IRQ init stuff ---------------------- */ diff -urN --exclude='*~' linux-2.6.13-rc2/arch/ppc/platforms/adir_pic.c linux-2.6.13-rc2-armirq/arch/ppc/platforms/adir_pic.c --- linux-2.6.13-rc2/arch/ppc/platforms/adir_pic.c 2005-07-09 13:04:31.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/ppc/platforms/adir_pic.c 2005-07-09 13:10:41.000000000 +0200 @@ -73,14 +73,10 @@ } static struct hw_interrupt_type adir_onboard_pic = { - " ADIR PIC ", - NULL, - NULL, - adir_onboard_pic_enable, /* unmask */ - adir_onboard_pic_disable, /* mask */ - adir_onboard_pic_disable, /* mask and ack */ - NULL, - NULL + .typename = " ADIR PIC ", + .enable = adir_onboard_pic_enable, /* unmask */ + .disable = adir_onboard_pic_disable, /* mask */ + .ack = adir_onboard_pic_disable, /* mask and ack */ }; static struct irqaction noop_action = { diff -urN --exclude='*~' linux-2.6.13-rc2/arch/ppc/syslib/cpc700_pic.c linux-2.6.13-rc2-armirq/arch/ppc/syslib/cpc700_pic.c --- linux-2.6.13-rc2/arch/ppc/syslib/cpc700_pic.c 2005-07-09 13:04:31.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/ppc/syslib/cpc700_pic.c 2005-07-09 13:10:41.000000000 +0200 @@ -90,14 +90,10 @@ } static struct hw_interrupt_type cpc700_pic = { - "CPC700 PIC", - NULL, - NULL, - cpc700_unmask_irq, - cpc700_mask_irq, - cpc700_mask_and_ack_irq, - NULL, - NULL + .typename = "CPC700 PIC", + .enable = cpc700_unmask_irq, + .disable = cpc700_mask_irq, + .ack = cpc700_mask_and_ack_irq, }; __init static void diff -urN --exclude='*~' linux-2.6.13-rc2/arch/ppc/syslib/i8259.c linux-2.6.13-rc2-armirq/arch/ppc/syslib/i8259.c --- linux-2.6.13-rc2/arch/ppc/syslib/i8259.c 2005-07-09 13:04:31.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/ppc/syslib/i8259.c 2005-07-09 13:10:41.000000000 +0200 @@ -129,14 +129,11 @@ } struct hw_interrupt_type i8259_pic = { - " i8259 ", - NULL, - NULL, - i8259_unmask_irq, - i8259_mask_irq, - i8259_mask_and_ack_irq, - i8259_end_irq, - NULL + .typename = " i8259 ", + .enable = i8259_unmask_irq, + .disable = i8259_mask_irq, + .ack = i8259_mask_and_ack_irq, + .end = i8259_end_irq, }; static struct resource pic1_iores = { diff -urN --exclude='*~' linux-2.6.13-rc2/arch/ppc/syslib/open_pic2.c linux-2.6.13-rc2-armirq/arch/ppc/syslib/open_pic2.c --- linux-2.6.13-rc2/arch/ppc/syslib/open_pic2.c 2005-07-09 13:08:08.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/ppc/syslib/open_pic2.c 2005-07-09 13:10:41.000000000 +0200 @@ -82,13 +82,11 @@ static void openpic2_ack_irq(unsigned int irq_nr); struct hw_interrupt_type open_pic2 = { - " OpenPIC2 ", - NULL, - NULL, - openpic2_enable_irq, - openpic2_disable_irq, - openpic2_ack_irq, - openpic2_end_irq, + .typename = " OpenPIC2 ", + .enable = openpic2_enable_irq, + .disable = openpic2_disable_irq, + .ack = openpic2_ack_irq, + .end = openpic2_end_irq, }; /* diff -urN --exclude='*~' linux-2.6.13-rc2/arch/ppc/syslib/ppc403_pic.c linux-2.6.13-rc2-armirq/arch/ppc/syslib/ppc403_pic.c --- linux-2.6.13-rc2/arch/ppc/syslib/ppc403_pic.c 2005-07-09 13:04:31.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/ppc/syslib/ppc403_pic.c 2005-07-09 13:10:41.000000000 +0200 @@ -34,13 +34,10 @@ static void ppc403_aic_disable_and_ack(unsigned int irq); static struct hw_interrupt_type ppc403_aic = { - "403GC AIC", - NULL, - NULL, - ppc403_aic_enable, - ppc403_aic_disable, - ppc403_aic_disable_and_ack, - 0 + .typename = "403GC AIC", + .enable = ppc403_aic_enable, + .disable = ppc403_aic_disable, + .ack = ppc403_aic_disable_and_ack, }; int diff -urN --exclude='*~' linux-2.6.13-rc2/arch/ppc/syslib/xilinx_pic.c linux-2.6.13-rc2-armirq/arch/ppc/syslib/xilinx_pic.c --- linux-2.6.13-rc2/arch/ppc/syslib/xilinx_pic.c 2005-07-09 13:04:31.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/ppc/syslib/xilinx_pic.c 2005-07-09 13:10:41.000000000 +0200 @@ -79,14 +79,11 @@ } static struct hw_interrupt_type xilinx_intc = { - "Xilinx Interrupt Controller", - NULL, - NULL, - xilinx_intc_enable, - xilinx_intc_disable, - xilinx_intc_disable_and_ack, - xilinx_intc_end, - 0 + .typename = "Xilinx Interrupt Controller", + .enable = xilinx_intc_enable, + .disable = xilinx_intc_disable, + .ack = xilinx_intc_disable_and_ack, + .end = xilinx_intc_end, }; int diff -urN --exclude='*~' linux-2.6.13-rc2/arch/sh/boards/adx/irq_maskreg.c linux-2.6.13-rc2-armirq/arch/sh/boards/adx/irq_maskreg.c --- linux-2.6.13-rc2/arch/sh/boards/adx/irq_maskreg.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/sh/boards/adx/irq_maskreg.c 2005-07-09 13:10:42.000000000 +0200 @@ -37,13 +37,13 @@ /* hw_interrupt_type */ static struct hw_interrupt_type maskreg_irq_type = { - " Mask Register", - startup_maskreg_irq, - shutdown_maskreg_irq, - enable_maskreg_irq, - disable_maskreg_irq, - mask_and_ack_maskreg, - end_maskreg_irq + .typename = " Mask Register", + .startup = startup_maskreg_irq, + .shutdown = shutdown_maskreg_irq, + .enable = enable_maskreg_irq, + .disable = disable_maskreg_irq, + .ack = mask_and_ack_maskreg, + .end = end_maskreg_irq }; /* actual implementatin */ diff -urN --exclude='*~' linux-2.6.13-rc2/arch/sh/boards/bigsur/irq.c linux-2.6.13-rc2-armirq/arch/sh/boards/bigsur/irq.c --- linux-2.6.13-rc2/arch/sh/boards/bigsur/irq.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/sh/boards/bigsur/irq.c 2005-07-09 13:10:42.000000000 +0200 @@ -228,23 +228,23 @@ /* Define the IRQ structures for the L1 and L2 IRQ types */ static struct hw_interrupt_type bigsur_l1irq_type = { - "BigSur-CPLD-Level1-IRQ", - startup_bigsur_irq, - shutdown_bigsur_irq, - enable_bigsur_l1irq, - disable_bigsur_l1irq, - mask_and_ack_bigsur, - end_bigsur_irq + .typename = "BigSur-CPLD-Level1-IRQ", + .startup = startup_bigsur_irq, + .shutdown = shutdown_bigsur_irq, + .enable = enable_bigsur_l1irq, + .disable = disable_bigsur_l1irq, + .ack = mask_and_ack_bigsur, + .end = end_bigsur_irq }; static struct hw_interrupt_type bigsur_l2irq_type = { - "BigSur-CPLD-Level2-IRQ", - startup_bigsur_irq, - shutdown_bigsur_irq, - enable_bigsur_l2irq, - disable_bigsur_l2irq, - mask_and_ack_bigsur, - end_bigsur_irq + .typename = "BigSur-CPLD-Level2-IRQ", + .startup = startup_bigsur_irq, + .shutdown =shutdown_bigsur_irq, + .enable = enable_bigsur_l2irq, + .disable = disable_bigsur_l2irq, + .ack = mask_and_ack_bigsur, + .end = end_bigsur_irq }; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/sh/boards/cqreek/irq.c linux-2.6.13-rc2-armirq/arch/sh/boards/cqreek/irq.c --- linux-2.6.13-rc2/arch/sh/boards/cqreek/irq.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/sh/boards/cqreek/irq.c 2005-07-09 13:10:42.000000000 +0200 @@ -83,13 +83,13 @@ } static struct hw_interrupt_type cqreek_irq_type = { - "CqREEK-IRQ", - startup_cqreek_irq, - shutdown_cqreek_irq, - enable_cqreek_irq, - disable_cqreek_irq, - mask_and_ack_cqreek, - end_cqreek_irq + .typename = "CqREEK-IRQ", + .startup = startup_cqreek_irq, + .shutdown = shutdown_cqreek_irq, + .enable = enable_cqreek_irq, + .disable = disable_cqreek_irq, + .ack = mask_and_ack_cqreek, + .end = end_cqreek_irq }; int cqreek_has_ide, cqreek_has_isa; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/sh/boards/harp/irq.c linux-2.6.13-rc2-armirq/arch/sh/boards/harp/irq.c --- linux-2.6.13-rc2/arch/sh/boards/harp/irq.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/sh/boards/harp/irq.c 2005-07-09 13:10:42.000000000 +0200 @@ -39,13 +39,13 @@ } static struct hw_interrupt_type harp_irq_type = { - "Harp-IRQ", - startup_harp_irq, - shutdown_harp_irq, - enable_harp_irq, - disable_harp_irq, - mask_and_ack_harp, - end_harp_irq + .typename = "Harp-IRQ", + .startup = startup_harp_irq, + .shutdown = shutdown_harp_irq, + .enable = enable_harp_irq, + .disable = disable_harp_irq, + .ack = mask_and_ack_harp, + .end = end_harp_irq }; static void disable_harp_irq(unsigned int irq) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/sh/boards/overdrive/irq.c linux-2.6.13-rc2-armirq/arch/sh/boards/overdrive/irq.c --- linux-2.6.13-rc2/arch/sh/boards/overdrive/irq.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/sh/boards/overdrive/irq.c 2005-07-09 13:10:42.000000000 +0200 @@ -86,13 +86,13 @@ } static struct hw_interrupt_type od_irq_type = { - "Overdrive-IRQ", - startup_od_irq, - shutdown_od_irq, - enable_od_irq, - disable_od_irq, - mask_and_ack_od, - end_od_irq + .typename = "Overdrive-IRQ", + .startup = startup_od_irq, + .shutdown = shutdown_od_irq, + .enable = enable_od_irq, + .disable = disable_od_irq, + .ack = mask_and_ack_od, + .end = end_od_irq }; static void disable_od_irq(unsigned int irq) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/sh/boards/renesas/hs7751rvoip/irq.c linux-2.6.13-rc2-armirq/arch/sh/boards/renesas/hs7751rvoip/irq.c --- linux-2.6.13-rc2/arch/sh/boards/renesas/hs7751rvoip/irq.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/sh/boards/renesas/hs7751rvoip/irq.c 2005-07-09 13:10:42.000000000 +0200 @@ -74,13 +74,13 @@ } static struct hw_interrupt_type hs7751rvoip_irq_type = { - "HS7751RVoIP IRQ", - startup_hs7751rvoip_irq, - shutdown_hs7751rvoip_irq, - enable_hs7751rvoip_irq, - disable_hs7751rvoip_irq, - ack_hs7751rvoip_irq, - end_hs7751rvoip_irq, + .typename = "HS7751RVoIP IRQ", + .startup = startup_hs7751rvoip_irq, + .shutdown = shutdown_hs7751rvoip_irq, + .enable = enable_hs7751rvoip_irq, + .disable = disable_hs7751rvoip_irq, + .ack = ack_hs7751rvoip_irq, + .end = end_hs7751rvoip_irq, }; static void make_hs7751rvoip_irq(unsigned int irq) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/sh/boards/renesas/rts7751r2d/irq.c linux-2.6.13-rc2-armirq/arch/sh/boards/renesas/rts7751r2d/irq.c --- linux-2.6.13-rc2/arch/sh/boards/renesas/rts7751r2d/irq.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/sh/boards/renesas/rts7751r2d/irq.c 2005-07-09 13:10:42.000000000 +0200 @@ -88,13 +88,13 @@ } static struct hw_interrupt_type rts7751r2d_irq_type = { - "RTS7751R2D IRQ", - startup_rts7751r2d_irq, - shutdown_rts7751r2d_irq, - enable_rts7751r2d_irq, - disable_rts7751r2d_irq, - ack_rts7751r2d_irq, - end_rts7751r2d_irq, + .typename = "RTS7751R2D IRQ", + .startup = startup_rts7751r2d_irq, + .shutdown = shutdown_rts7751r2d_irq, + .enable = enable_rts7751r2d_irq, + .disable = disable_rts7751r2d_irq, + .ack = ack_rts7751r2d_irq, + .end = end_rts7751r2d_irq, }; static void make_rts7751r2d_irq(unsigned int irq) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/sh/boards/renesas/systemh/irq.c linux-2.6.13-rc2-armirq/arch/sh/boards/renesas/systemh/irq.c --- linux-2.6.13-rc2/arch/sh/boards/renesas/systemh/irq.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/sh/boards/renesas/systemh/irq.c 2005-07-09 13:10:42.000000000 +0200 @@ -35,13 +35,13 @@ /* hw_interrupt_type */ static struct hw_interrupt_type systemh_irq_type = { - " SystemH Register", - startup_systemh_irq, - shutdown_systemh_irq, - enable_systemh_irq, - disable_systemh_irq, - mask_and_ack_systemh, - end_systemh_irq + .typename = " SystemH Register", + .startup = startup_systemh_irq, + .shutdown = shutdown_systemh_irq, + .enable = enable_systemh_irq, + .disable = disable_systemh_irq, + .ack = mask_and_ack_systemh, + .end = end_systemh_irq }; static unsigned int startup_systemh_irq(unsigned int irq) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/sh/boards/superh/microdev/irq.c linux-2.6.13-rc2-armirq/arch/sh/boards/superh/microdev/irq.c --- linux-2.6.13-rc2/arch/sh/boards/superh/microdev/irq.c 2005-07-09 13:04:24.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/sh/boards/superh/microdev/irq.c 2005-07-09 13:10:42.000000000 +0200 @@ -83,13 +83,13 @@ } static struct hw_interrupt_type microdev_irq_type = { - "MicroDev-IRQ", - startup_microdev_irq, - shutdown_microdev_irq, - enable_microdev_irq, - disable_microdev_irq, - mask_and_ack_microdev, - end_microdev_irq + .typename = "MicroDev-IRQ", + .startup = startup_microdev_irq, + .shutdown = shutdown_microdev_irq, + .enable = enable_microdev_irq, + .disable = disable_microdev_irq, + .ack = mask_and_ack_microdev, + .end = end_microdev_irq }; static void disable_microdev_irq(unsigned int irq) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/sh/cchips/voyagergx/irq.c linux-2.6.13-rc2-armirq/arch/sh/cchips/voyagergx/irq.c --- linux-2.6.13-rc2/arch/sh/cchips/voyagergx/irq.c 2005-07-09 13:04:23.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/sh/cchips/voyagergx/irq.c 2005-07-09 13:10:42.000000000 +0200 @@ -87,13 +87,13 @@ } static struct hw_interrupt_type voyagergx_irq_type = { - "VOYAGERGX-IRQ", - startup_voyagergx_irq, - shutdown_voyagergx_irq, - enable_voyagergx_irq, - disable_voyagergx_irq, - mask_and_ack_voyagergx, - end_voyagergx_irq, + .typename = "VOYAGERGX-IRQ", + .startup = startup_voyagergx_irq, + .shutdown = shutdown_voyagergx_irq, + .enable = enable_voyagergx_irq, + .disable = disable_voyagergx_irq, + .ack = mask_and_ack_voyagergx, + .end = end_voyagergx_irq, }; static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, struct pt_regs *regs) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/sh/kernel/cpu/irq_imask.c linux-2.6.13-rc2-armirq/arch/sh/kernel/cpu/irq_imask.c --- linux-2.6.13-rc2/arch/sh/kernel/cpu/irq_imask.c 2005-07-09 13:04:23.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/sh/kernel/cpu/irq_imask.c 2005-07-09 13:10:42.000000000 +0200 @@ -46,13 +46,13 @@ } static struct hw_interrupt_type imask_irq_type = { - "SR.IMASK", - startup_imask_irq, - shutdown_imask_irq, - enable_imask_irq, - disable_imask_irq, - mask_and_ack_imask, - end_imask_irq + .typename = "SR.IMASK", + .startup = startup_imask_irq, + .shutdown = shutdown_imask_irq, + .enable = enable_imask_irq, + .disable = disable_imask_irq, + .ack = mask_and_ack_imask, + .end = end_imask_irq }; void static inline set_interrupt_registers(int ip) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/sh/kernel/cpu/irq_ipr.c linux-2.6.13-rc2-armirq/arch/sh/kernel/cpu/irq_ipr.c --- linux-2.6.13-rc2/arch/sh/kernel/cpu/irq_ipr.c 2005-07-09 13:04:23.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/sh/kernel/cpu/irq_ipr.c 2005-07-09 13:10:42.000000000 +0200 @@ -48,13 +48,13 @@ } static struct hw_interrupt_type ipr_irq_type = { - "IPR-IRQ", - startup_ipr_irq, - shutdown_ipr_irq, - enable_ipr_irq, - disable_ipr_irq, - mask_and_ack_ipr, - end_ipr_irq + .typename = "IPR-IRQ", + .startup = startup_ipr_irq, + .shutdown = shutdown_ipr_irq, + .enable = enable_ipr_irq, + .disable = disable_ipr_irq, + .ack = mask_and_ack_ipr, + .end = end_ipr_irq }; static void disable_ipr_irq(unsigned int irq) @@ -142,13 +142,13 @@ } static struct hw_interrupt_type pint_irq_type = { - "PINT-IRQ", - startup_pint_irq, - shutdown_pint_irq, - enable_pint_irq, - disable_pint_irq, - mask_and_ack_pint, - end_pint_irq + .typename = "PINT-IRQ", + .startup = startup_pint_irq, + .shutdown = shutdown_pint_irq, + .enable = enable_pint_irq, + .disable = disable_pint_irq, + .ack = mask_and_ack_pint, + .end = end_pint_irq }; static void disable_pint_irq(unsigned int irq) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/sh/kernel/cpu/sh4/irq_intc2.c linux-2.6.13-rc2-armirq/arch/sh/kernel/cpu/sh4/irq_intc2.c --- linux-2.6.13-rc2/arch/sh/kernel/cpu/sh4/irq_intc2.c 2005-07-09 13:04:23.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/sh/kernel/cpu/sh4/irq_intc2.c 2005-07-09 13:10:42.000000000 +0200 @@ -48,13 +48,13 @@ } static struct hw_interrupt_type intc2_irq_type = { - "INTC2-IRQ", - startup_intc2_irq, - shutdown_intc2_irq, - enable_intc2_irq, - disable_intc2_irq, - mask_and_ack_intc2, - end_intc2_irq + .typename = "INTC2-IRQ", + .startup = startup_intc2_irq, + .shutdown = shutdown_intc2_irq, + .enable = enable_intc2_irq, + .disable = disable_intc2_irq, + .ack = mask_and_ack_intc2, + .end = end_intc2_irq }; static void disable_intc2_irq(unsigned int irq) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/sh64/kernel/irq_intc.c linux-2.6.13-rc2-armirq/arch/sh64/kernel/irq_intc.c --- linux-2.6.13-rc2/arch/sh64/kernel/irq_intc.c 2005-07-09 13:04:23.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/sh64/kernel/irq_intc.c 2005-07-09 13:10:42.000000000 +0200 @@ -107,13 +107,13 @@ static void end_intc_irq(unsigned int irq); static struct hw_interrupt_type intc_irq_type = { - "INTC", - startup_intc_irq, - shutdown_intc_irq, - enable_intc_irq, - disable_intc_irq, - mask_and_ack_intc, - end_intc_irq + .typename = "INTC", + .startup = startup_intc_irq, + .shutdown = shutdown_intc_irq, + .enable = enable_intc_irq, + .disable = disable_intc_irq, + .ack = mask_and_ack_intc, + .end = end_intc_irq }; static int irlm; /* IRL mode */ diff -urN --exclude='*~' linux-2.6.13-rc2/arch/v850/kernel/irq.c linux-2.6.13-rc2-armirq/arch/v850/kernel/irq.c --- linux-2.6.13-rc2/arch/v850/kernel/irq.c 2005-07-09 13:04:28.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/v850/kernel/irq.c 2005-07-09 13:10:42.000000000 +0200 @@ -67,13 +67,13 @@ #define end_none enable_none struct hw_interrupt_type no_irq_type = { - "none", - startup_none, - shutdown_none, - enable_none, - disable_none, - ack_none, - end_none + .typename = "none", + .startup = startup_none, + .shutdown = shutdown_none, + .enable = enable_none, + .disable = disable_none, + .ack = ack_none, + .end = end_none }; volatile unsigned long irq_err_count, spurious_count; diff -urN --exclude='*~' linux-2.6.13-rc2/arch/v850/kernel/setup.c linux-2.6.13-rc2-armirq/arch/v850/kernel/setup.c --- linux-2.6.13-rc2/arch/v850/kernel/setup.c 2005-07-09 13:04:28.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/v850/kernel/setup.c 2005-07-09 13:10:42.000000000 +0200 @@ -128,13 +128,13 @@ } static struct hw_interrupt_type nmi_irq_type = { - "NMI", - irq_zero, /* startup */ - irq_nop, /* shutdown */ - irq_nop, /* enable */ - irq_nop, /* disable */ - irq_nop, /* ack */ - nmi_end, /* end */ + .typename = "NMI", + .startup = irq_zero, /* startup */ + .shutdown = irq_nop, /* shutdown */ + .enable = irq_nop, /* enable */ + .disable = irq_nop, /* disable */ + .ack = irq_nop, /* ack */ + .end = nmi_end, /* end */ }; void __init init_IRQ (void) diff -urN --exclude='*~' linux-2.6.13-rc2/arch/v850/kernel/sim.c linux-2.6.13-rc2-armirq/arch/v850/kernel/sim.c --- linux-2.6.13-rc2/arch/v850/kernel/sim.c 2005-07-09 13:04:28.000000000 +0200 +++ linux-2.6.13-rc2-armirq/arch/v850/kernel/sim.c 2005-07-09 13:10:42.000000000 +0200 @@ -73,13 +73,13 @@ static unsigned irq_zero (unsigned irq) { return 0; } static struct hw_interrupt_type sim_irq_type = { - "IRQ", - irq_zero, /* startup */ - irq_nop, /* shutdown */ - irq_nop, /* enable */ - irq_nop, /* disable */ - irq_nop, /* ack */ - irq_nop, /* end */ + .typename = "IRQ", + .startup = irq_zero, /* startup */ + .shutdown = irq_nop, /* shutdown */ + .enable = irq_nop, /* enable */ + .disable = irq_nop, /* disable */ + .ack = irq_nop, /* ack */ + .end = irq_nop, /* end */ }; void __init mach_init_irqs (void) diff -urN --exclude='*~' linux-2.6.13-rc2/drivers/char/s3c2410-rtc.c linux-2.6.13-rc2-armirq/drivers/char/s3c2410-rtc.c --- linux-2.6.13-rc2/drivers/char/s3c2410-rtc.c 2005-07-09 13:04:05.000000000 +0200 +++ linux-2.6.13-rc2-armirq/drivers/char/s3c2410-rtc.c 2005-07-09 13:10:42.000000000 +0200 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/drivers/i2c/chips/tps65010.c linux-2.6.13-rc2-armirq/drivers/i2c/chips/tps65010.c --- linux-2.6.13-rc2/drivers/i2c/chips/tps65010.c 2005-07-09 13:08:12.000000000 +0200 +++ linux-2.6.13-rc2-armirq/drivers/i2c/chips/tps65010.c 2005-07-10 10:24:59.000000000 +0200 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -34,7 +35,6 @@ #include #include -#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/drivers/input/serio/sa1111ps2.c linux-2.6.13-rc2-armirq/drivers/input/serio/sa1111ps2.c --- linux-2.6.13-rc2/drivers/input/serio/sa1111ps2.c 2005-07-09 13:03:54.000000000 +0200 +++ linux-2.6.13-rc2-armirq/drivers/input/serio/sa1111ps2.c 2005-07-09 13:10:42.000000000 +0200 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/drivers/net/smc91x.c linux-2.6.13-rc2-armirq/drivers/net/smc91x.c --- linux-2.6.13-rc2/drivers/net/smc91x.c 2005-07-09 13:08:20.000000000 +0200 +++ linux-2.6.13-rc2-armirq/drivers/net/smc91x.c 2005-07-11 00:03:39.000000000 +0200 @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include @@ -1998,7 +1999,7 @@ if (retval) goto err_out; - set_irq_type(dev->irq, SMC_IRQ_TRIGGER_TYPE); + SMC_SET_IRQ_TYPE(dev->irq, SMC_IRQ_TRIGGER_TYPE); #ifdef SMC_USE_PXA_DMA { diff -urN --exclude='*~' linux-2.6.13-rc2/drivers/net/smc91x.h linux-2.6.13-rc2-armirq/drivers/net/smc91x.h --- linux-2.6.13-rc2/drivers/net/smc91x.h 2005-07-09 13:08:20.000000000 +0200 +++ linux-2.6.13-rc2-armirq/drivers/net/smc91x.h 2005-07-12 21:36:55.000000000 +0200 @@ -90,7 +90,7 @@ __l--; \ } \ } while (0) -#define set_irq_type(irq, type) +#define SMC_SET_IRQ_TYPE(irq, type) #elif defined(CONFIG_SA1100_PLEB) /* We can only do 16-bit reads and writes in the static memory space. */ @@ -109,7 +109,7 @@ #define SMC_outw(v, a, r) outw(v, (a) + (r)) #define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l) -#define set_irq_type(irq, type) do {} while (0) +#define SMC_SET_IRQ_TYPE(irq, type) do {} while (0) #elif defined(CONFIG_SA1100_ASSABET) @@ -209,7 +209,7 @@ #define SMC_insw(a, r, p, l) insw((a) + (r) - 0xa0000000, p, l) #define SMC_outsw(a, r, p, l) outsw((a) + (r) - 0xa0000000, p, l) -#define set_irq_type(irq, type) do {} while(0) +#define SMC_SET_IRQ_TYPE(irq, type) do {} while(0) #elif defined(CONFIG_ISA) @@ -237,7 +237,7 @@ #define SMC_insw(a, r, p, l) insw((a) + (r) - 0xa0000000, p, l) #define SMC_outsw(a, r, p, l) outsw((a) + (r) - 0xa0000000, p, l) -#define set_irq_type(irq, type) do {} while(0) +#define SMC_SET_IRQ_TYPE(irq, type) do {} while(0) #define RPC_LSA_DEFAULT RPC_LED_TX_RX #define RPC_LSB_DEFAULT RPC_LED_100_10 @@ -310,6 +310,14 @@ #endif +#ifndef SMC_SET_IRQ_TYPE +#ifdef IRQT_RISING +#define SMC_SET_IRQ_TYPE set_irq_type +#else +#define SMC_SET_IRQ_TYPE(irq, type) do {} while(0) +#endif +#endif + #ifndef SMC_IRQ_TRIGGER_TYPE #define SMC_IRQ_TRIGGER_TYPE IRQT_RISING #endif diff -urN --exclude='*~' linux-2.6.13-rc2/drivers/pci/pci-driver.c linux-2.6.13-rc2-armirq/drivers/pci/pci-driver.c --- linux-2.6.13-rc2/drivers/pci/pci-driver.c 2005-07-09 13:08:21.000000000 +0200 +++ linux-2.6.13-rc2-armirq/drivers/pci/pci-driver.c 2005-07-09 17:20:00.000000000 +0200 @@ -17,13 +17,13 @@ * Dynamic device IDs are disabled for !CONFIG_HOTPLUG */ -#ifdef CONFIG_HOTPLUG - struct pci_dynid { struct list_head node; struct pci_device_id id; }; +#ifdef CONFIG_HOTPLUG + /** * store_new_id * diff -urN --exclude='*~' linux-2.6.13-rc2/drivers/pcmcia/soc_common.c linux-2.6.13-rc2-armirq/drivers/pcmcia/soc_common.c --- linux-2.6.13-rc2/drivers/pcmcia/soc_common.c 2005-07-09 13:04:14.000000000 +0200 +++ linux-2.6.13-rc2-armirq/drivers/pcmcia/soc_common.c 2005-07-09 13:10:42.000000000 +0200 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include diff -urN --exclude='*~' linux-2.6.13-rc2/drivers/video/fbmem.c linux-2.6.13-rc2-armirq/drivers/video/fbmem.c --- linux-2.6.13-rc2/drivers/video/fbmem.c 2005-07-09 13:08:27.000000000 +0200 +++ linux-2.6.13-rc2-armirq/drivers/video/fbmem.c 2005-07-09 13:10:42.000000000 +0200 @@ -1252,6 +1252,8 @@ return retval; } +extern const char *global_mode_option; + /** * video_setup - process command line options * @options: string of options diff -urN --exclude='*~' linux-2.6.13-rc2/include/asm-arm/hw_irq.h linux-2.6.13-rc2-armirq/include/asm-arm/hw_irq.h --- linux-2.6.13-rc2/include/asm-arm/hw_irq.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.13-rc2-armirq/include/asm-arm/hw_irq.h 2005-07-04 15:47:49.000000000 +0200 @@ -0,0 +1,9 @@ +/* + * Nothing to see here yet + */ +#ifndef _ARCH_ARM_HW_IRQ_H +#define _ARCH_ARM_HW_IRQ_H + +#include + +#endif diff -urN --exclude='*~' linux-2.6.13-rc2/include/asm-arm/irq.h linux-2.6.13-rc2-armirq/include/asm-arm/irq.h --- linux-2.6.13-rc2/include/asm-arm/irq.h 2005-07-09 13:04:56.000000000 +0200 +++ linux-2.6.13-rc2-armirq/include/asm-arm/irq.h 2005-07-09 13:10:42.000000000 +0200 @@ -19,16 +19,10 @@ #define NO_IRQ ((unsigned int)(-1)) #endif -struct irqaction; - -extern void disable_irq_nosync(unsigned int); -extern void disable_irq(unsigned int); -extern void enable_irq(unsigned int); - -#define __IRQT_FALEDGE (1 << 0) -#define __IRQT_RISEDGE (1 << 1) -#define __IRQT_LOWLVL (1 << 2) -#define __IRQT_HIGHLVL (1 << 3) +#define __IRQT_FALEDGE IRQ_TYPE_EDGEL +#define __IRQT_RISEDGE IRQ_TYPE_EDGEH +#define __IRQT_LOWLVL IRQ_TYPE_LEVELL +#define __IRQT_HIGHLVL IRQ_TYPE_LEVELH #define IRQT_NOEDGE (0) #define IRQT_RISING (__IRQT_RISEDGE) @@ -36,16 +30,9 @@ #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 *); -struct irqaction; -struct pt_regs; -int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); +/* FIXME_TGLX */ +#define IRQT_PROBE (1 << 7) #endif diff -urN --exclude='*~' linux-2.6.13-rc2/include/asm-arm/mach/irq.h linux-2.6.13-rc2-armirq/include/asm-arm/mach/irq.h --- linux-2.6.13-rc2/include/asm-arm/mach/irq.h 2005-07-09 13:04:56.000000000 +0200 +++ linux-2.6.13-rc2-armirq/include/asm-arm/mach/irq.h 2005-07-09 13:10:42.000000000 +0200 @@ -10,86 +10,9 @@ #ifndef __ASM_ARM_MACH_IRQ_H #define __ASM_ARM_MACH_IRQ_H -struct irqdesc; -struct pt_regs; -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 (*type)(unsigned int, unsigned int); - /* - * Set wakeup-enable on the selected IRQ - */ - int (*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 *chipdata; - 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; - - struct proc_dir_entry *procdir; - -#ifdef CONFIG_SMP - cpumask_t affinity; - unsigned int cpu; -#endif +#include - /* - * IRQ lock detection - */ - unsigned int lck_cnt; - unsigned int lck_pc; - unsigned int lck_jif; -}; - -extern struct irqdesc irq_desc[]; +struct seq_file; /* * This is internal. Do not use it. @@ -97,31 +20,52 @@ 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); +void __set_irq_handler(unsigned int irq, struct irq_type *, int); /* * External stuff. */ #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].chipdata = d; } while (0) -#define get_irq_chipdata(irq) (irq_desc[irq].chipdata) -void set_irq_chip(unsigned int irq, struct irqchip *); + +#define set_irq_chipdata(irq,d) set_irq_chip_data(irq, d) +#define get_irq_chipdata(irq) get_irq_chip_data(irq) + void set_irq_flags(unsigned int irq, unsigned int flags); #define IRQF_VALID (1 << 0) #define IRQF_PROBE (1 << 1) #define IRQF_NOAUTOEN (1 << 2) +/* ARM uses the retrigger functions in desc->chip or software retrigger */ +static inline void hw_resend_irq(struct irq_type *t, unsigned int i) {} + /* - * Built-in IRQ handlers. + * Hack alert. 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 (&default_level_type) +#define do_edge_IRQ (&default_edge_type) +#define do_simple_IRQ (&default_simple_type) + +/* Hack to get around set_irq_chained_handler(nr,NULL) problem */ +#define irq_NULL_type no_irq_type +#define set_irq_chained_handler(irq,handler) \ + __set_irq_handler(irq,&irq_##handler##_type,1) + +#define DEFINE_IRQ_CHAINED_TYPE(function) \ +struct irq_type irq_##function##_type = { \ + .typename = #function"-chained_type", \ + .handle_irq = function, \ +} + +#define do_bad_IRQ(irq,desc,regs) \ +do { \ + spin_lock(&desc->lock); \ + handle_bad_irq(irq, desc, regs); \ + spin_unlock(&desc->lock); \ +} while(0) + +/* FIXME */ +#define ack_bad_irq(irq) do {} while (0) #endif diff -urN --exclude='*~' linux-2.6.13-rc2/include/asm-arm/vst.h linux-2.6.13-rc2-armirq/include/asm-arm/vst.h --- linux-2.6.13-rc2/include/asm-arm/vst.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.13-rc2-armirq/include/asm-arm/vst.h 2005-07-12 19:05:01.000000000 +0200 @@ -0,0 +1,6 @@ +#ifndef ASMARM_VST_H +#define ASMARM_VST_H + +#include + +#endif diff -urN --exclude='*~' linux-2.6.13-rc2/include/linux/irq.h linux-2.6.13-rc2-armirq/include/linux/irq.h --- linux-2.6.13-rc2/include/linux/irq.h 2005-07-09 13:08:34.000000000 +0200 +++ linux-2.6.13-rc2-armirq/include/linux/irq.h 2005-07-09 16:14:50.000000000 +0200 @@ -1,14 +1,6 @@ #ifndef __irq_h #define __irq_h -/* - * Please do not include this file in generic code. There is currently - * no requirement for any architecture to implement anything held - * within this file. - * - * Thanks. --rmk - */ - #include #if !defined(CONFIG_ARCH_S390) @@ -33,69 +25,217 @@ #define IRQ_LEVEL 64 /* IRQ level triggered */ #define IRQ_MASKED 128 /* IRQ masked - shouldn't be seen again */ #define IRQ_PER_CPU 256 /* IRQ is per CPU */ +#define IRQ_NOPROBE 512 /* IRQ is not valid for probing */ +#define IRQ_NOREQUEST 1024 /* IRQ cannot be requested */ /* - * Interrupt controller descriptor. This is all we need - * to describe about the low-level hardware. + * IRQ types */ -struct hw_interrupt_type { - const char * typename; - 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 (*end)(unsigned int irq); - void (*set_affinity)(unsigned int irq, cpumask_t dest); +#define IRQ_TYPE_NONE 0x0000 /* Default, unspecified type */ +#define IRQ_TYPE_EDGEL 0x0001 /* Edge low/falling type */ +#define IRQ_TYPE_EDGEH 0x0002 /* Edge high/rising type */ +#define IRQ_TYPE_EDGEB \ + (IRQ_TYPE_EDGEL | IRQ_TYPE_EDGEH) /* Edge low+high/both type */ +#define IRQ_TYPE_LEVELL 0x0004 /* Level low type */ +#define IRQ_TYPE_LEVELH 0x0008 /* Level high type */ +#define IRQ_TYPE_SIMPLE 0x0010 /* Simple type */ + +/* + * IRQ wakeup control modes + */ +#define IRQ_WAKE_NORESUME 0x0000 /* Do not resume on this irq */ +#define IRQ_WAKE_RESUME 0x0001 /* Enable resume on this irq */ + +/** + * struct irq_chip - Low level interrupt controller hardware descriptor + * + * @ack: acknowledge IRQ + * @mask: mask the IRQ + * @mask_ack: acknowledge and mask the IRQ + * @unmask: unmask the IRQ + * @retrigger: retrigger the IRQ in hardware, if possible. Return 0 on success. + * @set_type: set the IRQ type (level, edge[high,low,both]) + * @set_wake: Set the IRQ PM-wakeup function + * @options: option field to store type, wake information + * @lock: locking for SMP + * @chip_data: platform-specific private data for the chip + */ +struct irq_chip { + spinlock_t lock; + void (*ack)(unsigned int irq); + void (*mask)(unsigned int irq); + void (*mask_ack)(unsigned int irq); + void (*unmask)(unsigned int irq); + int (*retrigger)(unsigned int irq); + int (*set_type)(unsigned int irq, unsigned int hw_type); + int (*set_wake)(unsigned int irq, unsigned int mode); + unsigned long options; + void *chip_data; +}; + +struct irq_desc; +struct irq_type; + +/** + * struct irq_type - high level hardware interrupt type descriptor + * + * @typename: 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 new interrupt. (Note: This will be renamed to 'start') + * @hold: same interrupt while the handler is running + * @end: end of interrupt + * @set_affinity: set the CPU affinity on SMP machines + * @set_type: set the interrupt type (level, edge[high,low,both]), + * returns a pointer to the irq_type structure which can + * handle the requested type or NULL, if the type cannot + * be handled. + */ +struct irq_type { + const char *typename; + unsigned int (*startup)(unsigned int irq); + void (*shutdown)(unsigned int irq); + void (*enable)(unsigned int irq); + void (*disable)(unsigned int irq); + + void (*handle_irq)(unsigned int irq, struct irq_desc *desc, + struct pt_regs *regs); + + /* (*start) Will be renamed */ + void (*ack)(unsigned int irq); + void (*hold)(unsigned int irq); + void (*end)(unsigned int irq); + void (*set_affinity)(unsigned int irq, cpumask_t dest); + struct irq_type *(*set_type)(unsigned int irq, unsigned int type); /* Currently used only by UML, might disappear one day.*/ #ifdef CONFIG_IRQ_RELEASE_METHOD void (*release)(unsigned int irq, void *dev_id); #endif }; -typedef struct hw_interrupt_type hw_irq_controller; - -/* - * This is the "IRQ descriptor", which contains various information - * about the irq, including what kind of hardware handling it has, - * whether it is disabled etc etc. +/** + * struct irq_desc - interrupt descriptor + * + * @lock: locking for SMP + * @status: status information + * @handler: interrupt type dependent handler functions, + * (this will be renamed to 'type') + * @chip: low level hardware access functions - comes from type + * @action: the irq action chain + * @depth: disable-depth, for nested irq_disable() calls + * @irq_count: stats field to detect stalled irqs + * @irqs_unhandled: stats field for spurious unhandled interrupts + * @data: data for the type handlers * * Pad this out to 32 bytes for cache and indexing reasons. */ -typedef struct irq_desc { - hw_irq_controller *handler; - void *handler_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 interrupts */ - unsigned int irqs_unhandled; - spinlock_t lock; -} ____cacheline_aligned irq_desc_t; +struct irq_desc { + spinlock_t lock; + unsigned int status; + /* (*type) Will be renamed !*/ + struct irq_type *handler; + struct irq_chip *chip; + struct irqaction *action; + unsigned long depth; + unsigned long irq_count; + unsigned long irqs_unhandled; + void *data; +} ____cacheline_aligned; + +extern struct irq_desc irq_desc[NR_IRQS]; -extern irq_desc_t irq_desc [NR_IRQS]; +/* + * Migration helpers for obsolete names, they will go away: + */ +#define irqdesc irq_desc +#define irqchip irq_chip +#define hw_interrupt_type irq_type +#define set_irq_type set_hwirq_type +typedef struct irq_desc irq_desc_t; +typedef struct irq_type hw_irq_controller; #include /* the arch dependent stuff */ +/* Setup an interrupt. Used for static setups in early init */ extern int setup_irq(unsigned int irq, struct irqaction * new); #ifdef CONFIG_GENERIC_HARDIRQS -extern cpumask_t irq_affinity[NR_IRQS]; -extern int no_irq_affinity; -extern int noirqdebug_setup(char *str); +/* Handle irq action chains */ extern fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, - struct irqaction *action); + struct irqaction *action); + +/* + * 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); + +#define desc_lock_handle_irq(irq, desc, regs) \ +do { \ + spin_lock(&desc->lock); \ + desc->handler->handle_irq(irq, desc, regs); \ + spin_unlock(&desc->lock); \ +} while(0) + +/* Monolithic do_IRQ implementation */ extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); -extern void note_interrupt(unsigned int irq, irq_desc_t *desc, - int action_ret, struct pt_regs *regs); -extern int can_request_irq(unsigned int irq, unsigned long irqflags); +/* Handling of unhandled and spurious interrupts */ +extern void note_interrupt(unsigned int irq, irq_desc_t *desc, int action_ret, struct pt_regs *regs); + +/* Proc filesystem */ extern void init_irq_proc(void); -#endif -extern hw_irq_controller no_irq_type; /* needed in every arch ? */ +/* Enable/disable irq debugging output */ +extern int noirqdebug_setup(char *str); -#endif +/* Set/get irq type */ +extern int set_irq_type(unsigned int irq, unsigned int type); +extern int get_irq_type(unsigned int irq, unsigned int type); + +/* Irq wakeup (PM) control) */ +extern int set_irq_wake(unsigned int irq, unsigned int mode); +#define enable_irq_wake(irq) set_irq_wake(irq, IRQ_WAKE_RESUME) +#define disable_irq_wake(irq) set_irq_wake(irq, IRQ_WAKE_NORESUME) + +/* Checks whether the interrupt can be requested by request_irq() */ +extern int can_request_irq(unsigned int irq, unsigned long irqflags); + +/* Set type control/chip/data for an interrupt */ +extern int generic_set_irq_type(unsigned int irq, struct irq_type *type); +extern int set_irq_data(unsigned int irq, void *data); +extern int set_irq_chip(unsigned int irq, struct irq_chip *chip); +extern int set_irq_chip_data(unsigned int irq, void *data); + +/* Get chip/data for an interrupt */ +#define get_irq_chip(irq) (irq_desc[irq].chip) +#define get_irq_chip_data(irq) (irq_desc[irq].chip->chip_data) + +/* Interrupt type default implementations */ +extern struct irq_type no_irq_type; +extern struct irq_type default_edge_type; +extern struct irq_type default_level_type; +extern struct irq_type default_simple_type; +extern struct irq_type default_percpu_type; + +/* CPU-affinity (on SMP) related data and functions */ +extern cpumask_t irq_affinity[NR_IRQS]; +extern int no_irq_affinity; +extern int set_irq_affinity(unsigned int irq, cpumask_t affinity); +extern cpumask_t get_irq_affinity(unsigned int irq); + +extern void check_irq_resend(irq_desc_t *desc, unsigned int irq); + +#endif /* GENERIC_HARDIRQS */ + +#endif /* !S390 */ #endif /* __irq_h */ diff -urN --exclude='*~' linux-2.6.13-rc2/kernel/irq/Makefile linux-2.6.13-rc2-armirq/kernel/irq/Makefile --- linux-2.6.13-rc2/kernel/irq/Makefile 2005-07-09 13:03:50.000000000 +0200 +++ linux-2.6.13-rc2-armirq/kernel/irq/Makefile 2005-07-09 13:10:42.000000000 +0200 @@ -1,5 +1,5 @@ -obj-y := handle.o manage.o spurious.o +obj-y := handle.o manage.o spurious.o resend.o obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o obj-$(CONFIG_PROC_FS) += proc.o diff -urN --exclude='*~' linux-2.6.13-rc2/kernel/irq/handle.c linux-2.6.13-rc2-armirq/kernel/irq/handle.c --- linux-2.6.13-rc2/kernel/irq/handle.c 2005-07-09 13:08:35.000000000 +0200 +++ linux-2.6.13-rc2-armirq/kernel/irq/handle.c 2005-07-18 21:46:27.000000000 +0200 @@ -1,9 +1,13 @@ /* * linux/kernel/irq/handle.c * - * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar + * Copyright (C) 1992, 1998-2005 Linus Torvalds, Ingo Molnar + * Copyright (C) 2005, Thomas Gleixner, Russell King * * This file contains the core interrupt handling code. + * + * Detailed information is available in Documentation/DocBook/genericirq + * */ #include @@ -11,58 +15,56 @@ #include #include #include - +#if defined(CONFIG_NO_IDLE_HZ) +#include +#endif #include "internals.h" /* - * Linux has a controller-independent interrupt architecture. - * Every controller has a 'controller-template', that is used - * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the apropriate - * controller. Thus drivers need not be aware of the - * interrupt-controller. - * - * The code is designed to be easily extended with new/different - * interrupt controllers, without having to do assembly magic or - * having to touch the generic code. - * - * Controller mappings for all interrupt sources: + * Default initialization for all interrupt sources */ irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { [0 ... NR_IRQS-1] = { .status = IRQ_DISABLED, .handler = &no_irq_type, + .depth = 1, .lock = SPIN_LOCK_UNLOCKED } }; /* - * Generic 'no controller' code + * What should we do if we get a hw irq event on an illegal vector? + * Each architecture has to answer this themself. */ -static void end_none(unsigned int irq) { } -static void enable_none(unsigned int irq) { } -static void disable_none(unsigned int irq) { } -static void shutdown_none(unsigned int irq) { } -static unsigned int startup_none(unsigned int irq) { return 0; } - -static void ack_none(unsigned int irq) +static void ack_bad(unsigned int irq) { - /* - * 'what should we do if we get a hw irq event on an illegal vector'. - * each architecture has to answer this themself. - */ ack_bad_irq(irq); } -struct hw_interrupt_type no_irq_type = { +/* + * NOP functions + */ +static void noop(unsigned int irq) +{ +} + +static unsigned int noop_ret(unsigned int irq) +{ + return 0; +} + +/* + * Generic no controller implementation + */ +struct irq_type no_irq_type = { .typename = "none", - .startup = startup_none, - .shutdown = shutdown_none, - .enable = enable_none, - .disable = disable_none, - .ack = ack_none, - .end = end_none, - .set_affinity = NULL + .startup = noop_ret, + .shutdown = noop, + .enable = noop, + .disable = noop, + .ack = ack_bad, + .end = noop, + .handle_irq = handle_bad_irq, }; /* @@ -74,7 +76,147 @@ } /* - * Have got an event to handle: + * default ack function + */ +static void default_ack(unsigned int irq) +{ + irq_desc[irq].chip->ack(irq); +} + +/* + * default mask ack function + */ +static void default_mask_ack(unsigned int irq) +{ + irq_desc_t *desc = irq_desc + irq; + + if (desc->chip->mask_ack) { + desc->chip->mask_ack(irq); + } else { + desc->chip->mask(irq); + desc->chip->ack(irq); + } +} + +/* + * default enable function + */ +static void default_enable(unsigned int irq) +{ + irq_desc_t *desc = irq_desc + irq; + + desc->chip->unmask(irq); + desc->status &= ~IRQ_MASKED; +} + +/* + * default end function + */ +static void default_end(unsigned int irq) +{ + irq_desc_t *desc = irq_desc + irq; + + if (!desc->depth) + desc->chip->unmask(irq); +} + +/* + * default disable function + */ +static void default_disable(unsigned int irq) +{ + irq_desc[irq].chip->mask(irq); +} + +/* + * Default set type function + */ +static struct irq_type *default_set_type(unsigned int irq, unsigned int type) +{ + irq_desc_t *desc = irq_desc + irq; + + if (desc->chip->set_type) + if (desc->chip->set_type(irq, type)) + return NULL; + + switch (type) { + case IRQ_TYPE_NONE: + return &no_irq_type; + + case IRQ_TYPE_EDGEL: + case IRQ_TYPE_EDGEH: + case IRQ_TYPE_EDGEB: + return &default_edge_type; + case IRQ_TYPE_LEVELL: + case IRQ_TYPE_LEVELH: + return &default_level_type; + case IRQ_TYPE_SIMPLE: + return &default_simple_type; + } + return NULL; +} + +/* + * Generic edge type interrupt + * + */ +struct irq_type default_edge_type = { + .typename = "default_edge", + .enable = default_enable, + .disable = default_disable, + .ack = default_ack, + .hold = default_mask_ack, + .end = noop, + .handle_irq = handle_edge_irq, + .set_type = default_set_type, +}; + +/* + * Generic level type interrupt + */ +struct irq_type default_level_type = { + .typename = "default_level", + .enable = default_enable, + .disable = default_disable, + .ack = default_mask_ack, + .end = default_end, + .handle_irq = handle_level_irq, + .set_type = default_set_type, +}; + +/* + * Generic simple type interrupt + * + * No hardware handling necessary + */ +struct irq_type default_simple_type = { + .typename = "default_simple", + .enable = noop, + .disable = noop, + .handle_irq = handle_simple_irq, +}; + +#ifdef CONFIG_SMP +/* + * Generic per cpu type interrupt + */ +struct irq_type default_percpu_type = { + .typename = "default_percpu", + .enable = default_enable, + .disable = default_disable, + .ack = default_ack, + .end = default_end, + .handle_irq = handle_percpu_irq, +}; +#endif + +/** + * handle_IRQ_event - irq action chain handler + * @irq: the interrupt number + * @regs: pointer to a register structure + * @action: the interrupt action chain for this irq + * + * Handles the action chain of an irq event */ fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, struct irqaction *action) @@ -84,6 +226,15 @@ if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); +#if defined(CONFIG_NO_IDLE_HZ) + if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) { + write_seqlock(&xtime_lock); + if (system_timer->dyn_tick->state & DYN_TICK_ENABLED) + system_timer->dyn_tick->handler(irq, 0, regs); + write_sequnlock(&xtime_lock); + } +#endif + do { ret = action->handler(irq, action->dev_id, regs); if (ret == IRQ_HANDLED) @@ -99,10 +250,208 @@ return retval; } -/* - * do_IRQ handles all normal device IRQ's (the special +/** + * 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, irq_desc_t *desc, struct pt_regs *regs) +{ +} + +/** + * handle_simple_irq - Simple and software-decoded IRQs. + * @irq: the interrupt number + * @desc: the interrupt description structure for this irq + * @regs: pointer to a register structure + * + * Simple interrupts are either sent from a demultiplexing interrupt + * handler or come from hardware, where no interrupt hardware control + * is necessary. + * + * Note: The caller is expected to handle the ack, clear, mask and + * unmask issues if necessary. + * + * Must be called with the irq_desc->lock held + */ +void handle_simple_irq(unsigned int irq, irq_desc_t *desc, struct pt_regs *regs) +{ + struct irqaction *action; + irqreturn_t action_ret; + const unsigned int cpu = smp_processor_id(); + + kstat_cpu(cpu).irqs[irq]++; + + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); + + action = desc->action; + if (unlikely(!action || desc->depth)) + return; + + desc->status |= IRQ_INPROGRESS; + spin_unlock(&desc->lock); + action_ret = handle_IRQ_event(irq, regs, action); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret, regs); + spin_lock(&desc->lock); + desc->status &= ~IRQ_INPROGRESS; +} + +/** + * handle_level_irq - Level type irq handler + * @irq: the interrupt number + * @desc: the interrupt description structure for this irq + * @regs: pointer to a register structure + * + * Level type interrupts are active as long as the hardware line has + * the active level. This may require to mask the interrupt and unmask it + * after the associated handler has acknowledged the device, so the + * interrupt line is back to inactive. + * + * Must be called with the irq_desc->lock held + */ +void handle_level_irq(unsigned int irq, irq_desc_t *desc, struct pt_regs *regs) +{ + struct irqaction *action; + irqreturn_t action_ret; + const unsigned int cpu = smp_processor_id(); + + kstat_cpu(cpu).irqs[irq]++; + + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); + + desc->handler->ack(irq); + + /* + * If its disabled or no action available + * keep it masked and get out of here + */ + action = desc->action; + if (unlikely(!action || desc->depth)) + goto out; + + desc->status |= IRQ_INPROGRESS; + spin_unlock(&desc->lock); + action_ret = handle_IRQ_event(irq, regs, action); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret, regs); + spin_lock(&desc->lock); + + desc->status &= ~IRQ_INPROGRESS; +out: + desc->handler->end(irq); +} + +/** + * handle_edge_irq - edge type IRQ handler + * @irq: the interrupt number + * @desc: the interrupt description structure for this irq + * @regs: pointer to a register structure + * + * Interrupt occures on the falling and/or rising edge of a hardware + * signal. The occurence is latched into the irq controller hardware + * and must be acked in order to be reenabled. After the ack another + * interrupt can happen on the same source even before the first one + * is handled by the assosiacted event handler. If this happens it + * might be necessary to disable (mask) the interrupt depending on the + * controller hardware. This requires to reenable the interrupt inside + * of the loop which handles the interrupts which have arrived while + * the handler was running. If all pending interrupts are handled, the + * loop is left and depending on the hardware controller some final + * ack might be necessary. + * + * Must be called with the irq_desc->lock held + */ +void handle_edge_irq(unsigned int irq, irq_desc_t *desc, struct pt_regs *regs) +{ + const unsigned int cpu = smp_processor_id(); + + kstat_cpu(cpu).irqs[irq]++; + + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); + + /* + * If we're currently running this IRQ, or its disabled, + * we shouldn't process the IRQ. Mark it pending, handle + * the necessary masking and go out + */ + if (unlikely((desc->status & IRQ_INPROGRESS) || desc->depth || + !desc->action)) { + desc->status |= (IRQ_PENDING | IRQ_MASKED); + desc->handler->hold(irq); + return; + } + + /* Start handling the irq */ + desc->handler->ack(irq); + + /* Mark the IRQ currently in progress.*/ + desc->status |= IRQ_INPROGRESS; + + do { + struct irqaction *action = desc->action; + irqreturn_t action_ret; + + if (unlikely(!action)) { + desc->handler->disable(irq); + return; + } + + /* + * When another irq arrived while we were handling + * one, we could have masked the irq. + * Renable it, if it was not disabled in meantime. + */ + if (unlikely(((desc->status & (IRQ_PENDING | IRQ_MASKED)) == + (IRQ_PENDING | IRQ_MASKED)) && !desc->depth)) + desc->handler->enable(irq); + + desc->status &= ~IRQ_PENDING; + spin_unlock(&desc->lock); + action_ret = handle_IRQ_event(irq, regs, action); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret, regs); + spin_lock(&desc->lock); + + } while ((desc->status & IRQ_PENDING) && !desc->depth); + + desc->status &= ~IRQ_INPROGRESS; + desc->handler->end(irq); +} + +#ifdef CONFIG_SMP +/** + * handle_percpu_IRQ - Per CPU local irq handler + * @irq: the interrupt number + * @desc: the interrupt description structure for this irq + * @regs: pointer to a register structure + * + * Per CPU interrupts on SMP machines without locking requirements + */ +void handle_percpu_irq(unsigned int irq, irq_desc_t *desc, struct pt_regs *regs) +{ + irqreturn_t action_ret; + + kstat_this_cpu.irqs[irq]++; + desc->handler->ack(irq); + action_ret = handle_IRQ_event(irq, regs, desc->action); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret, regs); + desc->handler->end(irq); +} +#endif /* CONFIG_SMP */ + +/** + * __do_IRQ - original all in one handler + * @irq: the interrupt number + * @regs: pointer to a register structure + * + * __do_IRQ handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific - * handlers). + * handlers). * This is the original x86 implementation which is used for every + * type of interrupt. + * */ fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs) { diff -urN --exclude='*~' linux-2.6.13-rc2/kernel/irq/manage.c linux-2.6.13-rc2-armirq/kernel/irq/manage.c --- linux-2.6.13-rc2/kernel/irq/manage.c 2005-07-09 13:08:35.000000000 +0200 +++ linux-2.6.13-rc2-armirq/kernel/irq/manage.c 2005-07-11 15:17:31.000000000 +0200 @@ -1,7 +1,8 @@ /* * linux/kernel/irq/manage.c * - * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar + * Copyright (C) 1992, 1998-2005 Linus Torvalds, Ingo Molnar + * Copyright (C) 2005, Thomas Gleixner * * This file contains driver APIs to the irq subsystem. */ @@ -20,6 +21,7 @@ /** * synchronize_irq - wait for pending IRQ handlers (on other CPUs) + * @irq: Interrupt to synchronize * * This function waits for any pending IRQ handlers for this interrupt * to complete before returning. If you use this function while @@ -110,12 +112,10 @@ break; case 1: { unsigned int status = desc->status & ~IRQ_DISABLED; - - desc->status = status; - if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { - desc->status = status | IRQ_REPLAY; - hw_resend_irq(desc->handler,irq); - } + + /* Prevent probing on this irq */ + desc->status = status | IRQ_NOPROBE; + check_irq_resend(desc, irq); desc->handler->enable(irq); /* fall-through */ } @@ -127,6 +127,28 @@ EXPORT_SYMBOL(enable_irq); +/** + * set_irq_wake - control irq power management wakeup + * @irq: Interrupt to control + * @mode: power management wakeup mode + * + * Enable/disable power management wakeup mode + */ +int set_irq_wake(unsigned int irq, unsigned int mode) +{ + irq_desc_t *desc = irq_desc + irq; + unsigned long flags; + int ret = -ENXIO; + + spin_lock_irqsave(&desc->lock, flags); + if (desc->chip && desc->chip->set_wake) + ret = desc->chip->set_wake(irq, mode); + spin_unlock_irqrestore(&desc->lock, flags); + return ret; +} + +EXPORT_SYMBOL(set_irq_wake); + /* * Internal function that tells the architecture code whether a * particular irq has been exclusively allocated or is available @@ -136,7 +158,7 @@ { struct irqaction *action; - if (irq >= NR_IRQS) + if (irq >= NR_IRQS || irq_desc[irq].status & IRQ_NOREQUEST) return 0; action = irq_desc[irq].action; @@ -180,12 +202,12 @@ /* * The following block of code has to be executed atomically */ - spin_lock_irqsave(&desc->lock,flags); + spin_lock_irqsave(&desc->lock, flags); p = &desc->action; if ((old = *p) != NULL) { /* Can't share interrupts unless both agree to */ if (!(old->flags & new->flags & SA_SHIRQ)) { - spin_unlock_irqrestore(&desc->lock,flags); + spin_unlock_irqrestore(&desc->lock, flags); return -EBUSY; } @@ -208,7 +230,7 @@ else desc->handler->enable(irq); } - spin_unlock_irqrestore(&desc->lock,flags); + spin_unlock_irqrestore(&desc->lock, flags); new->irq = irq; register_irq_proc(irq); @@ -242,7 +264,7 @@ return; desc = irq_desc + irq; - spin_lock_irqsave(&desc->lock,flags); + spin_lock_irqsave(&desc->lock, flags); p = &desc->action; for (;;) { struct irqaction * action = *p; @@ -270,7 +292,7 @@ else desc->handler->disable(irq); } - spin_unlock_irqrestore(&desc->lock,flags); + spin_unlock_irqrestore(&desc->lock, flags); unregister_handler_proc(irq, action); /* Make sure it's not being used on another CPU */ @@ -278,8 +300,8 @@ kfree(action); return; } - printk(KERN_ERR "Trying to free free IRQ%d\n",irq); - spin_unlock_irqrestore(&desc->lock,flags); + printk(KERN_ERR "Trying to free free IRQ%d\n", irq); + spin_unlock_irqrestore(&desc->lock, flags); return; } } @@ -332,6 +354,8 @@ return -EINVAL; if (irq >= NR_IRQS) return -EINVAL; + if (irq_desc[irq].status & IRQ_NOREQUEST) + return -EINVAL; if (!handler) return -EINVAL; @@ -355,3 +379,145 @@ EXPORT_SYMBOL(request_irq); +/** + * generic_set_irq_type - set the hardware irq type structure for an irq + * @irq: Interrupt number + * @type: Pointer to irq_type structure + */ +int generic_set_irq_type(unsigned int irq, struct irq_type *type) +{ + irq_desc_t *desc; + unsigned long flags; + + if (irq >= NR_IRQS) { + printk(KERN_ERR "Trying to install type for IRQ%d\n", irq); + return -EINVAL; + } + + if (!type) + type = &no_irq_type; + + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock, flags); + desc->handler = type; + spin_unlock_irqrestore(&desc->lock, flags); + + return 0; +} + +EXPORT_SYMBOL(generic_set_irq_type); + +/** + * set_irq_data - set irq type data for an irq + * @irq: Interrupt number + * @data: Pointer to interrupt specific data + * + * Set the hardware irq controller data for an irq + */ +int set_irq_data(unsigned int irq, void *data) +{ + irq_desc_t *desc; + unsigned long flags; + + if (irq >= NR_IRQS) { + printk(KERN_ERR "Trying to install controller data for IRQ%d\n", irq); + return -EINVAL; + } + + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock, flags); + desc->data = data; + spin_unlock_irqrestore(&desc->lock, flags); + return 0; +} + +EXPORT_SYMBOL(set_irq_data); + +/** + * set_irq_chip - set irq chip for an IRQ + * @irq: Interrupt number + * @chip: Pointer to irq_chip structure + * + * Set the hardware chip structure for an IRQ + */ +int set_irq_chip(unsigned int irq, struct irq_chip *chip) +{ + irq_desc_t *desc; + unsigned long flags; + + if (irq >= NR_IRQS) { + printk(KERN_ERR "Trying to install chip for IRQ%d\n", irq); + return -EINVAL; + } + + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock, flags); + desc->chip = chip; + spin_unlock_irqrestore(&desc->lock, flags); + return 0; +} + +EXPORT_SYMBOL(set_irq_chip); + +/** + * set_irq_chip_data - set irq chip data for an irq + * @irq: Interrupt number + * @data: Pointer to chip specific data + * + * Set the hardware irq chip data for an irq + */ +int set_irq_chip_data(unsigned int irq, void *data) +{ + irq_desc_t *desc = irq_desc + irq; + unsigned long flags; + + if (irq >= NR_IRQS || !desc->handler || !desc->chip) { + printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq); + return -EINVAL; + } + + spin_lock_irqsave(&desc->lock, flags); + desc->chip->chip_data = data; + spin_unlock_irqrestore(&desc->lock, flags); + + return 0; +} + +EXPORT_SYMBOL(set_irq_chip_data); + +/* + * set_hwirq_type - Set the irq type (level/edge/simple/percpu) + * @irq: Interrupt number + * @hw_type: interrupt type (see constants in include/linux/irq.h) + * + * Called from device drivers to configure GPIO interrupts + * according to their requirements. The set_type function of the + * handler returns a pointer to an irq_type structure which is + * able to handle this interrupt type. The handler in the irq + * descriptor structure is set to the new handler type. + * + */ +int set_hwirq_type(unsigned int irq, unsigned int hw_type) +{ + struct irq_type *type = NULL; + unsigned long flags; + irq_desc_t *desc; + + if (irq >= NR_IRQS) { + printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq); + return -ENODEV; + } + + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock, flags); + if (desc->handler->set_type) { + type = desc->handler->set_type(irq, hw_type); + if (type) + desc->handler = type; + } + spin_unlock_irqrestore(&desc->lock, flags); + return type ? -ENXIO : 0; +} + +EXPORT_SYMBOL(set_hwirq_type); + diff -urN --exclude='*~' linux-2.6.13-rc2/kernel/irq/resend.c linux-2.6.13-rc2-armirq/kernel/irq/resend.c --- linux-2.6.13-rc2/kernel/irq/resend.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.13-rc2-armirq/kernel/irq/resend.c 2005-07-09 13:10:42.000000000 +0200 @@ -0,0 +1,82 @@ +/* + * linux/kernel/irq/resend.c + * + * Copyright (C) 1992, 1998-2005 Linus Torvalds, Ingo Molnar + * Copyright (C) 2005, Thomas Gleixner + * + * This file contains the tasklet-based IRQ-resend code + */ + +#include +#include +#include +#include + +#include "internals.h" + +/* Bitmap to handle software resend of interrupts: */ +static DECLARE_BITMAP(irqs_resend, NR_IRQS); + +/* + * Run software resends of IRQ's + */ +static void resend_irqs(unsigned long arg) +{ + unsigned long flags; + int irq; + + for (;;) { + if (bitmap_empty(irqs_resend, NR_IRQS)) + break; + irq = find_first_bit(irqs_resend, NR_IRQS); + clear_bit(irq, irqs_resend); + local_irq_save(flags); + desc_lock_handle_irq(irq, (irq_desc + irq), NULL); + local_irq_restore(flags); + } +} + +/* Tasklet to handle resend: */ +static DECLARE_TASKLET(resend_tasklet, resend_irqs, 0); + +/* + * Handle irq resend + * + * If the interrupt is waiting to be processed, try to re-run it. We + * can't directly run it from here since the caller might be in an + * interrupt-protected region. Not all irq controller chips can + * retrigger interrupts at hardware level. For edge type interrupts it + * is necessary to resend them by software. At the moment the pending + * list is handled at the end of asm_do_IRQ. That means the next + * interrupt (on any irq line) will invoke the do_pending function. It + * could also be done by a thread which is woken up by the + * check_irq_resend function. + * + * Is called with interrupts disabled and desc->lock held + */ +void check_irq_resend(irq_desc_t *desc, unsigned int irq) +{ + + /* Chipless implementation. This should vanish in the long run */ + if (!desc->chip) { + unsigned int status = desc->status; + if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { + desc->status = status | IRQ_REPLAY; + hw_resend_irq(desc->handler, irq); + } + return; + } + + /* Chip based implementation */ + if ((desc->status & IRQ_PENDING) && !test_bit(irq, irqs_resend)) { + desc->status &= ~IRQ_PENDING; + /* Try to retrigger it in hardware */ + if (!desc->chip || !desc->chip->retrigger || + desc->chip->retrigger(irq)) { + /* Mark it pending */ + set_bit(irq, irqs_resend); + tasklet_schedule(&resend_tasklet); + } + } +} + diff -urN --exclude='*~' linux-2.6.13-rc2/Makefile linux-2.6.13-rc2-armirq/Makefile --- linux-2.6.13-rc2/Makefile 2005-07-09 13:08:04.000000000 +0200 +++ linux-2.6.13-rc2-armirq/Makefile 2005-07-12 19:43:44.000000000 +0200 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 13 -EXTRAVERSION =-rc2 +EXTRAVERSION =-rc2-armirq-B5 NAME=Woozy Numbat # *DOCUMENTATION*