summaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/irq.c')
-rw-r--r--arch/i386/kernel/irq.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index bfb2a6841..fcc0a72f5 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -536,7 +536,7 @@ void enable_irq(unsigned int irq)
desc->depth--;
break;
case 0:
- printk("enable_irq() unbalanced from %p\n",
+ printk("enable_irq(%u) unbalanced from %p\n", irq,
__builtin_return_address(0));
}
spin_unlock_irqrestore(&desc->lock, flags);
@@ -775,6 +775,8 @@ void free_irq(unsigned int irq, void *dev_id)
* disabled.
*/
+static DECLARE_MUTEX(probe_sem);
+
/**
* probe_irq_on - begin an interrupt autodetect
*
@@ -790,6 +792,7 @@ unsigned long probe_irq_on(void)
unsigned long val;
unsigned long delay;
+ down(&probe_sem);
/*
* something may have generated an irq long ago and we want to
* flush such a longstanding irq before considering it as spurious.
@@ -868,15 +871,18 @@ unsigned long probe_irq_on(void)
* Scan the ISA bus interrupt lines and return a bitmap of
* active interrupts. The interrupt probe logic state is then
* returned to its previous value.
+ *
+ * Note: we need to scan all the irq's even though we will
+ * only return ISA irq numbers - just so that we reset them
+ * all to a known state.
*/
-
unsigned int probe_irq_mask(unsigned long val)
{
int i;
unsigned int mask;
mask = 0;
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < NR_IRQS; i++) {
irq_desc_t *desc = irq_desc + i;
unsigned int status;
@@ -884,7 +890,7 @@ unsigned int probe_irq_mask(unsigned long val)
status = desc->status;
if (status & IRQ_AUTODETECT) {
- if (!(status & IRQ_WAITING))
+ if (i < 16 && !(status & IRQ_WAITING))
mask |= 1 << i;
desc->status = status & ~IRQ_AUTODETECT;
@@ -892,6 +898,7 @@ unsigned int probe_irq_mask(unsigned long val)
}
spin_unlock_irq(&desc->lock);
}
+ up(&probe_sem);
return mask & val;
}
@@ -943,6 +950,7 @@ int probe_irq_off(unsigned long val)
}
spin_unlock_irq(&desc->lock);
}
+ up(&probe_sem);
if (nr_irqs > 1)
irq_found = -irq_found;
@@ -998,7 +1006,7 @@ int setup_irq(unsigned int irq, struct irqaction * new)
if (!shared) {
desc->depth = 0;
- desc->status &= ~IRQ_DISABLED;
+ desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
desc->handler->startup(irq);
}
spin_unlock_irqrestore(&desc->lock,flags);