/*
* linux/kernel/irq/handle.c
*
- * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
- * Copyright (C) 2005-2006, Thomas Gleixner, Russell King
+ * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
*
* This file contains the core interrupt handling code.
- *
- * Detailed information is available in Documentation/DocBook/genericirq
- *
*/
#include <linux/irq.h>
#include "internals.h"
-/**
- * handle_bad_irq - handle spurious and unhandled irqs
- * @irq: the interrupt number
- * @desc: description of the interrupt
- * @regs: pointer to a register structure
- *
- * Handles spurious and unhandled IRQ's. It also prints a debugmessage.
- */
-void fastcall
-handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
-{
- print_irq_desc(irq, desc);
- kstat_this_cpu.irqs[irq]++;
- ack_bad_irq(irq);
-}
-
/*
* Linux has a controller-independent interrupt architecture.
* Every controller has a 'controller-template', that is used
* by the main code to do the right thing. Each driver-visible
- * interrupt source is transparently wired to the appropriate
+ * interrupt source is transparently wired to the apropriate
* controller. Thus drivers need not be aware of the
* interrupt-controller.
*
*
* Controller mappings for all interrupt sources:
*/
-struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned = {
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
[0 ... NR_IRQS-1] = {
.status = IRQ_DISABLED,
- .chip = &no_irq_chip,
- .handle_irq = handle_bad_irq,
- .depth = 1,
- .lock = SPIN_LOCK_UNLOCKED,
-#ifdef CONFIG_SMP
- .affinity = CPU_MASK_ALL
-#endif
+ .handler = &no_irq_type,
+ .lock = SPIN_LOCK_UNLOCKED
}
};
/*
- * What should we do if we get a hw irq event on an illegal vector?
- * Each architecture has to answer this themself.
- */
-static void ack_bad(unsigned int irq)
-{
- print_irq_desc(irq, irq_desc + irq);
- ack_bad_irq(irq);
-}
-
-/*
- * NOP functions
+ * Generic 'no controller' code
*/
-static void noop(unsigned int irq)
-{
-}
+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 unsigned int noop_ret(unsigned int irq)
+static void ack_none(unsigned int irq)
{
- return 0;
+ /*
+ * '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);
}
-/*
- * Generic no controller implementation
- */
-struct irq_chip no_irq_chip = {
- .name = "none",
- .startup = noop_ret,
- .shutdown = noop,
- .enable = noop,
- .disable = noop,
- .ack = ack_bad,
- .end = noop,
-};
-
-/*
- * Generic dummy implementation which can be used for
- * real dumb interrupt sources
- */
-struct irq_chip dummy_irq_chip = {
- .name = "dummy",
- .startup = noop_ret,
- .shutdown = noop,
- .enable = noop,
- .disable = noop,
- .ack = noop,
- .mask = noop,
- .unmask = noop,
- .end = noop,
+struct hw_interrupt_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
};
/*
return IRQ_NONE;
}
-/**
- * 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
+/*
+ * Have got an event to handle:
*/
-irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
- struct irqaction *action)
+fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
+ struct irqaction *action)
{
- irqreturn_t ret, retval = IRQ_NONE;
- unsigned int status = 0;
+ int ret, retval = 0, status = 0;
- handle_dynamic_tick(action);
-
- if (!(action->flags & IRQF_DISABLED))
- local_irq_enable_in_hardirq();
+ if (!(action->flags & SA_INTERRUPT))
+ local_irq_enable();
do {
ret = action->handler(irq, action->dev_id, regs);
action = action->next;
} while (action);
- if (status & IRQF_SAMPLE_RANDOM)
+ if (status & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
local_irq_disable();
return retval;
}
-/**
- * __do_IRQ - original all in one highlevel IRQ handler
- * @irq: the interrupt number
- * @regs: pointer to a register structure
- *
- * __do_IRQ handles all normal device IRQ's (the special
+/*
+ * do_IRQ handles all normal device IRQ's (the special
* SMP cross-CPU interrupts have their own specific
* handlers).
- *
- * This is the original x86 implementation which is used for every
- * interrupt type.
*/
fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
{
- struct irq_desc *desc = irq_desc + irq;
- struct irqaction *action;
+ irq_desc_t *desc = irq_desc + irq;
+ struct irqaction * action;
unsigned int status;
kstat_this_cpu.irqs[irq]++;
/*
* No locking required for CPU-local interrupts:
*/
- if (desc->chip->ack)
- desc->chip->ack(irq);
+ if (desc->handler->ack)
+ desc->handler->ack(irq);
action_ret = handle_IRQ_event(irq, regs, desc->action);
- desc->chip->end(irq);
+ desc->handler->end(irq);
return 1;
}
spin_lock(&desc->lock);
- if (desc->chip->ack)
- desc->chip->ack(irq);
+ if (desc->handler->ack)
+ desc->handler->ack(irq);
/*
* REPLAY is when Linux resends an IRQ that was dropped earlier
* WAITING is used by probe to mark irqs that are being tested
* The ->end() handler has to deal with interrupts which got
* disabled while the handler was running.
*/
- desc->chip->end(irq);
+ desc->handler->end(irq);
spin_unlock(&desc->lock);
return 1;
}
-#ifdef CONFIG_TRACE_IRQFLAGS
-
-/*
- * lockdep: we want to handle all irq_desc locks as a single lock-class:
- */
-static struct lock_class_key irq_desc_lock_class;
-
-void early_init_irq_lock_class(void)
-{
- int i;
-
- for (i = 0; i < NR_IRQS; i++)
- lockdep_set_class(&irq_desc[i].lock, &irq_desc_lock_class);
-}
-
-#endif