git://git.onelab.eu
/
linux-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git]
/
kernel
/
irq
/
manage.c
diff --git
a/kernel/irq/manage.c
b/kernel/irq/manage.c
index
5202e4c
..
1279e34
100644
(file)
--- a/
kernel/irq/manage.c
+++ b/
kernel/irq/manage.c
@@
-6,6
+6,7
@@
* This file contains driver APIs to the irq subsystem.
*/
* This file contains driver APIs to the irq subsystem.
*/
+#include <linux/config.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/random.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/random.h>
@@
-17,8
+18,13
@@
cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
+#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE)
+cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS];
+#endif
+
/**
* synchronize_irq - wait for pending IRQ handlers (on other CPUs)
/**
* synchronize_irq - wait for pending IRQ handlers (on other CPUs)
+ * @irq: interrupt number to wait for
*
* This function waits for any pending IRQ handlers for this interrupt
* to complete before returning. If you use this function while
*
* This function waits for any pending IRQ handlers for this interrupt
* to complete before returning. If you use this function while
@@
-30,6
+36,9
@@
void synchronize_irq(unsigned int irq)
{
struct irq_desc *desc = irq_desc + irq;
{
struct irq_desc *desc = irq_desc + irq;
+ if (irq >= NR_IRQS)
+ return;
+
while (desc->status & IRQ_INPROGRESS)
cpu_relax();
}
while (desc->status & IRQ_INPROGRESS)
cpu_relax();
}
@@
-54,6
+63,9
@@
void disable_irq_nosync(unsigned int irq)
irq_desc_t *desc = irq_desc + irq;
unsigned long flags;
irq_desc_t *desc = irq_desc + irq;
unsigned long flags;
+ if (irq >= NR_IRQS)
+ return;
+
spin_lock_irqsave(&desc->lock, flags);
if (!desc->depth++) {
desc->status |= IRQ_DISABLED;
spin_lock_irqsave(&desc->lock, flags);
if (!desc->depth++) {
desc->status |= IRQ_DISABLED;
@@
-80,6
+92,9
@@
void disable_irq(unsigned int irq)
{
irq_desc_t *desc = irq_desc + irq;
{
irq_desc_t *desc = irq_desc + irq;
+ if (irq >= NR_IRQS)
+ return;
+
disable_irq_nosync(irq);
if (desc->action)
synchronize_irq(irq);
disable_irq_nosync(irq);
if (desc->action)
synchronize_irq(irq);
@@
-102,6
+117,9
@@
void enable_irq(unsigned int irq)
irq_desc_t *desc = irq_desc + irq;
unsigned long flags;
irq_desc_t *desc = irq_desc + irq;
unsigned long flags;
+ if (irq >= NR_IRQS)
+ return;
+
spin_lock_irqsave(&desc->lock, flags);
switch (desc->depth) {
case 0:
spin_lock_irqsave(&desc->lock, flags);
switch (desc->depth) {
case 0:
@@
-157,6
+175,9
@@
int setup_irq(unsigned int irq, struct irqaction * new)
unsigned long flags;
int shared = 0;
unsigned long flags;
int shared = 0;
+ if (irq >= NR_IRQS)
+ return -EINVAL;
+
if (desc->handler == &no_irq_type)
return -ENOSYS;
/*
if (desc->handler == &no_irq_type)
return -ENOSYS;
/*
@@
-183,10
+204,14
@@
int setup_irq(unsigned int irq, struct irqaction * new)
p = &desc->action;
if ((old = *p) != NULL) {
/* Can't share interrupts unless both agree to */
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);
- return -EBUSY;
- }
+ if (!(old->flags & new->flags & SA_SHIRQ))
+ goto mismatch;
+
+#if defined(ARCH_HAS_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ)
+ /* All handlers must agree on per-cpuness */
+ if ((old->flags & IRQ_PER_CPU) != (new->flags & IRQ_PER_CPU))
+ goto mismatch;
+#endif
/* add new interrupt at end of irq queue */
do {
/* add new interrupt at end of irq queue */
do {
@@
-197,7
+222,10
@@
int setup_irq(unsigned int irq, struct irqaction * new)
}
*p = new;
}
*p = new;
-
+#if defined(ARCH_HAS_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ)
+ if (new->flags & SA_PERCPU_IRQ)
+ desc->status |= IRQ_PER_CPU;
+#endif
if (!shared) {
desc->depth = 0;
desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT |
if (!shared) {
desc->depth = 0;
desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT |
@@
-215,6
+243,14
@@
int setup_irq(unsigned int irq, struct irqaction * new)
register_handler_proc(irq, new);
return 0;
register_handler_proc(irq, new);
return 0;
+
+mismatch:
+ spin_unlock_irqrestore(&desc->lock, flags);
+ if (!(new->flags & SA_PROBEIRQ)) {
+ printk(KERN_ERR "%s: irq handler mismatch\n", __FUNCTION__);
+ dump_stack();
+ }
+ return -EBUSY;
}
/**
}
/**
@@
-237,6
+273,7
@@
void free_irq(unsigned int irq, void *dev_id)
struct irqaction **p;
unsigned long flags;
struct irqaction **p;
unsigned long flags;
+ WARN_ON(in_interrupt());
if (irq >= NR_IRQS)
return;
if (irq >= NR_IRQS)
return;
@@
-255,6
+292,13
@@
void free_irq(unsigned int irq, void *dev_id)
/* Found it - now remove it from the list of entries */
*pp = action->next;
/* Found it - now remove it from the list of entries */
*pp = action->next;
+
+ /* Currently used only by UML, might disappear one day.*/
+#ifdef CONFIG_IRQ_RELEASE_METHOD
+ if (desc->handler->release)
+ desc->handler->release(irq, dev_id);
+#endif
+
if (!desc->action) {
desc->status |= IRQ_DISABLED;
if (desc->handler->shutdown)
if (!desc->action) {
desc->status |= IRQ_DISABLED;
if (desc->handler->shutdown)
@@
-338,6
+382,8
@@
int request_irq(unsigned int irq,
action->next = NULL;
action->dev_id = dev_id;
action->next = NULL;
action->dev_id = dev_id;
+ select_smp_affinity(irq);
+
retval = setup_irq(irq, action);
if (retval)
kfree(action);
retval = setup_irq(irq, action);
if (retval)
kfree(action);