ia64/xen-unstable

changeset 9715:9a273aabb839

New IO-APIC ACK method seems to cause problems on some systems
(e.g., Dell 1850). Disable it by default for now, but allow the
new mwethod to be tested by passing boot parameter 'new_ack'
to Xen.

You can tell which ACK method you are using because Xen prints
out "Using old ACK method" or "Using new ACK method" during boot.

This workaround can be removed if/when the problems with the new
ACK method are flushed out.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Apr 14 14:14:24 2006 +0100 (2006-04-14)
parents bb0dc0ae23bb
children 3a9d0c29ed72
files xen/arch/x86/io_apic.c
line diff
     1.1 --- a/xen/arch/x86/io_apic.c	Fri Apr 14 12:01:15 2006 +0100
     1.2 +++ b/xen/arch/x86/io_apic.c	Fri Apr 14 14:14:24 2006 +0100
     1.3 @@ -190,6 +190,18 @@ static void __unmask_IO_APIC_irq (unsign
     1.4      __modify_IO_APIC_irq(irq, 0, 0x00010000);
     1.5  }
     1.6  
     1.7 +/* trigger = 0 */
     1.8 +static void __edge_IO_APIC_irq (unsigned int irq)
     1.9 +{
    1.10 +    __modify_IO_APIC_irq(irq, 0, 0x00008000);
    1.11 +}
    1.12 +
    1.13 +/* trigger = 1 */
    1.14 +static void __level_IO_APIC_irq (unsigned int irq)
    1.15 +{
    1.16 +    __modify_IO_APIC_irq(irq, 0x00008000, 0);
    1.17 +}
    1.18 +
    1.19  /* mask = 1, trigger = 0 */
    1.20  static void __mask_and_edge_IO_APIC_irq (unsigned int irq)
    1.21  {
    1.22 @@ -1321,8 +1333,50 @@ static unsigned int startup_level_ioapic
    1.23      return 0; /* don't check for pending */
    1.24  }
    1.25  
    1.26 +static int new_ack;
    1.27 +boolean_param("new_ack", new_ack);
    1.28 +
    1.29  static void mask_and_ack_level_ioapic_irq (unsigned int irq)
    1.30  {
    1.31 +    unsigned long v;
    1.32 +    int i;
    1.33 +
    1.34 +    if ( new_ack )
    1.35 +        return;
    1.36 +
    1.37 +    mask_IO_APIC_irq(irq);
    1.38 +/*
    1.39 + * It appears there is an erratum which affects at least version 0x11
    1.40 + * of I/O APIC (that's the 82093AA and cores integrated into various
    1.41 + * chipsets).  Under certain conditions a level-triggered interrupt is
    1.42 + * erroneously delivered as edge-triggered one but the respective IRR
    1.43 + * bit gets set nevertheless.  As a result the I/O unit expects an EOI
    1.44 + * message but it will never arrive and further interrupts are blocked
    1.45 + * from the source.  The exact reason is so far unknown, but the
    1.46 + * phenomenon was observed when two consecutive interrupt requests
    1.47 + * from a given source get delivered to the same CPU and the source is
    1.48 + * temporarily disabled in between.
    1.49 + *
    1.50 + * A workaround is to simulate an EOI message manually.  We achieve it
    1.51 + * by setting the trigger mode to edge and then to level when the edge
    1.52 + * trigger mode gets detected in the TMR of a local APIC for a
    1.53 + * level-triggered interrupt.  We mask the source for the time of the
    1.54 + * operation to prevent an edge-triggered interrupt escaping meanwhile.
    1.55 + * The idea is from Manfred Spraul.  --macro
    1.56 + */
    1.57 +    i = IO_APIC_VECTOR(irq);
    1.58 +
    1.59 +    v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
    1.60 +
    1.61 +    ack_APIC_irq();
    1.62 +
    1.63 +    if (!(v & (1 << (i & 0x1f)))) {
    1.64 +        atomic_inc(&irq_mis_count);
    1.65 +        spin_lock(&ioapic_lock);
    1.66 +        __edge_IO_APIC_irq(irq);
    1.67 +        __level_IO_APIC_irq(irq);
    1.68 +        spin_unlock(&ioapic_lock);
    1.69 +    }
    1.70  }
    1.71  
    1.72  static void end_level_ioapic_irq (unsigned int irq)
    1.73 @@ -1330,6 +1384,12 @@ static void end_level_ioapic_irq (unsign
    1.74      unsigned long v;
    1.75      int i;
    1.76  
    1.77 +    if ( !new_ack )
    1.78 +    {
    1.79 +        unmask_IO_APIC_irq(irq);
    1.80 +        return;
    1.81 +    }
    1.82 +
    1.83  /*
    1.84   * It appears there is an erratum which affects at least version 0x11
    1.85   * of I/O APIC (that's the 82093AA and cores integrated into various
    1.86 @@ -1693,6 +1753,7 @@ void __init setup_IO_APIC(void)
    1.87          io_apic_irqs = ~PIC_IRQS;
    1.88  
    1.89      printk("ENABLING IO-APIC IRQs\n");
    1.90 +    printk(" -> Using %s ACK method\n", new_ack ? "new" : "old");
    1.91  
    1.92      /*
    1.93       * Set up IO-APIC IRQ routing.