aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2012-08-30 18:17:20 +0100
committerKeir Fraser <keir@xen.org>2012-08-30 18:17:20 +0100
commit4dd113fd79da66a2d95c381f38e94c990f7e268f (patch)
tree468dbfbd813c5164a4de7574dc4fe8d65d1490b7
parent132906348a14d4df9830b2794c6f06315e44238b (diff)
downloadxen-4dd113fd79da66a2d95c381f38e94c990f7e268f.tar.gz
xen-4dd113fd79da66a2d95c381f38e94c990f7e268f.tar.bz2
xen-4dd113fd79da66a2d95c381f38e94c990f7e268f.zip
x86/i8259: Clean up _mask_and_ack_8259A_irq().
Signed-off-by: Keir Fraser <keir@xen.org>
-rw-r--r--xen/arch/x86/i8259.c63
1 files changed, 24 insertions, 39 deletions
diff --git a/xen/arch/x86/i8259.c b/xen/arch/x86/i8259.c
index a43ce04fc0..9cfbca87ff 100644
--- a/xen/arch/x86/i8259.c
+++ b/xen/arch/x86/i8259.c
@@ -123,6 +123,8 @@ static struct hw_interrupt_type __read_mostly i8259A_irq_type = {
* 8259A PIC functions to handle ISA devices:
*/
+#define aeoi_mode (i8259A_irq_type.ack == disable_8259A_irq)
+
/*
* This contains the irq mask for both 8259A irq controllers,
*/
@@ -248,10 +250,10 @@ static bool_t _mask_and_ack_8259A_irq(unsigned int irq)
{
unsigned int irqmask = 1 << irq;
unsigned long flags;
- bool_t real_irq = 1; /* Assume real unless spurious */
- bool_t need_eoi = i8259A_irq_type.ack != disable_8259A_irq;
+ bool_t is_real_irq = 1; /* Assume real unless spurious */
spin_lock_irqsave(&i8259A_lock, flags);
+
/*
* Lightweight spurious IRQ detection. We do not want
* to overdo spurious IRQ handling - it's usually a sign
@@ -267,57 +269,40 @@ static bool_t _mask_and_ack_8259A_irq(unsigned int irq)
* but should be enough to warn the user that there
* is something bad going on ...
*/
- if (cached_irq_mask & irqmask)
- goto spurious_8259A_irq;
+ if ((cached_irq_mask & irqmask) && !i8259A_irq_real(irq)) {
+ static int spurious_irq_mask;
+ is_real_irq = 0;
+ /* Report spurious IRQ, once per IRQ line. */
+ if (!(spurious_irq_mask & irqmask)) {
+ printk("spurious 8259A interrupt: IRQ%d.\n", irq);
+ spurious_irq_mask |= irqmask;
+ }
+ /*
+ * Theoretically we do not have to handle this IRQ,
+ * but in Linux this does not cause problems and is
+ * simpler for us.
+ */
+ }
+
cached_irq_mask |= irqmask;
- handle_real_irq:
if (irq & 8) {
inb(0xA1); /* DUMMY - (do we need this?) */
outb(cached_A1,0xA1);
- if ( need_eoi )
- {
+ if (!aeoi_mode) {
outb(0x60 + (irq & 7), 0xA0);/* 'Specific EOI' to slave */
outb(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */
}
} else {
inb(0x21); /* DUMMY - (do we need this?) */
outb(cached_21,0x21);
- if ( need_eoi )
+ if (!aeoi_mode)
outb(0x60 + irq, 0x20);/* 'Specific EOI' to master */
}
- spin_unlock_irqrestore(&i8259A_lock, flags);
- return real_irq;
- spurious_8259A_irq:
- /*
- * this is the slow path - should happen rarely.
- */
- if (i8259A_irq_real(irq))
- /*
- * oops, the IRQ _is_ in service according to the
- * 8259A - not spurious, go handle it.
- */
- goto handle_real_irq;
+ spin_unlock_irqrestore(&i8259A_lock, flags);
- {
- static int spurious_irq_mask;
- real_irq = 0;
- /*
- * At this point we can be sure the IRQ is spurious,
- * lets ACK and report it. [once per IRQ]
- */
- if (!(spurious_irq_mask & irqmask)) {
- printk("spurious 8259A interrupt: IRQ%d.\n", irq);
- spurious_irq_mask |= irqmask;
- }
- /*
- * Theoretically we do not have to handle this IRQ,
- * but in Linux this does not cause problems and is
- * simpler for us.
- */
- goto handle_real_irq;
- }
+ return is_real_irq;
}
static char irq_trigger[2];
@@ -339,7 +324,7 @@ static void save_ELCR(char *trigger)
int i8259A_resume(void)
{
- init_8259A(i8259A_irq_type.ack == disable_8259A_irq);
+ init_8259A(aeoi_mode);
restore_ELCR(irq_trigger);
return 0;
}