lkml.org 
[lkml]   [2009]   [Apr]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 062/100] x86: fix broken irq migration logic while cleaning up multiple vectors
    -stable review patch.  If anyone has any objections, please let us know.
    ---------------------

    From: Suresh Siddha <suresh.b.siddha@intel.com>

    upstream commit: 68a8ca593fac82e336a792226272455901fa83df

    Impact: fix spurious IRQs

    During irq migration, we send a low priority interrupt to the previous
    irq destination. This happens in non interrupt-remapping case after interrupt
    starts arriving at new destination and in interrupt-remapping case after
    modifying and flushing the interrupt-remapping table entry caches.

    This low priority irq cleanup handler can cleanup multiple vectors, as
    multiple irq's can be migrated at almost the same time. While
    there will be multiple invocations of irq cleanup handler (one cleanup
    IPI for each irq migration), first invocation of the cleanup handler
    can potentially cleanup more than one vector (as the first invocation can
    see the requests for more than vector cleanup). When we cleanup multiple
    vectors during the first invocation of the smp_irq_move_cleanup_interrupt(),
    other vectors that are to be cleanedup can still be pending in the local
    cpu's IRR (as smp_irq_move_cleanup_interrupt() runs with interrupts disabled).

    When we are ready to unhook a vector corresponding to an irq, check if that
    vector is registered in the local cpu's IRR. If so skip that cleanup and
    do a self IPI with the cleanup vector, so that we give a chance to
    service the pending vector interrupt and then cleanup that vector
    allocation once we execute the lowest priority handler.

    This fixes spurious interrupts seen when migrating multiple vectors
    at the same time.

    [ This is apparently possible even on conventional xapic, although to
    the best of our knowledge it has never been seen. The stable
    maintainers may wish to consider this one for -stable. ]

    [suresh: backport to 2.6.29]
    Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
    Cc: Eric W. Biederman <ebiederm@xmission.com>
    Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
    Cc: stable@kernel.org
    Signed-off-by: Chris Wright <chrisw@sous-sol.org>
    ---

    ---
    arch/x86/kernel/io_apic.c | 13 +++++++++++++
    1 file changed, 13 insertions(+)

    --- a/arch/x86/kernel/io_apic.c
    +++ b/arch/x86/kernel/io_apic.c
    @@ -2475,6 +2475,7 @@ asmlinkage void smp_irq_move_cleanup_int
    me = smp_processor_id();
    for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
    unsigned int irq;
    + unsigned int irr;
    struct irq_desc *desc;
    struct irq_cfg *cfg;
    irq = __get_cpu_var(vector_irq)[vector];
    @@ -2494,6 +2495,18 @@ asmlinkage void smp_irq_move_cleanup_int
    if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
    goto unlock;

    + irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
    + /*
    + * Check if the vector that needs to be cleanedup is
    + * registered at the cpu's IRR. If so, then this is not
    + * the best time to clean it up. Lets clean it up in the
    + * next attempt by sending another IRQ_MOVE_CLEANUP_VECTOR
    + * to myself.
    + */
    + if (irr & (1 << (vector % 32))) {
    + send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR);
    + goto unlock;
    + }
    __get_cpu_var(vector_irq)[vector] = -1;
    cfg->move_cleanup_count--;
    unlock:


    \
     
     \ /
      Last update: 2009-04-23 09:51    [W:4.372 / U:0.192 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site