Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=48d8d7ee5dd17c64833e0343ab4ae8ef01cc2648
Commit:     48d8d7ee5dd17c64833e0343ab4ae8ef01cc2648
Parent:     c47e285dee9673087273fafcff06a44c58ed4efd
Author:     Siddha, Suresh B <[EMAIL PROTECTED]>
AuthorDate: Mon Jun 25 15:52:35 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Tue Jun 26 16:54:29 2007 -0700

    x86_64 irq: use mask/unmask and proper locking in fixup_irqs()
    
    Force irq migration path during cpu offline, is not using proper locks and
    irq_chip mask/unmask routines.  This will result in some races(especially
    the device generating the interrupt can see some inconsistent state,
    resulting in issues like stuck irq,..).
    
    Appended patch fixes the issue by taking proper lock and encapsulating
    irq_chip set_affinity() with a mask() before and an unmask() after.
    
    This fixes a MSI irq stuck issue reported by Darrick Wong.
    
    There are several more general bugs in this area(irq migration in the
    process context). For example,
    
     1. Possibility of missing edge triggered irq.
     2. Reliable method of migrating level triggered irq in the process context.
    
    We plan to look and close these in the near future.
    
    Eric says:
        In addition even with the fix from Suresh there is still at least one
        nasty hardware race in fixup_irqs().   However we exercise that code
        path rarely enough that we are unlikely to hit it in the real world,
        and that race seems to have existed since the code was merged.  And a
        fix for that is not coming soon as it is an open investigation area
        if we can fix irq migration to work outside of irq context or if
        we have to rework the requirements imposed by the generic cpu hotplug
        and layer on fixup_irqs().  So this may come up again.
    
    Signed-off-by: Suresh Siddha <[EMAIL PROTECTED]>
    Cc: Eric W. Biederman <[EMAIL PROTECTED]>
    Reported-and-tested-by: Darrick Wong <[EMAIL PROTECTED]>
    Cc: Andi Kleen <[EMAIL PROTECTED]>
    Acked-by: Rafael J. Wysocki <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 arch/x86_64/kernel/irq.c |   32 +++++++++++++++++++++++++++++---
 1 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index 3eaceac..39cb3fa 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -144,17 +144,43 @@ void fixup_irqs(cpumask_t map)
 
        for (irq = 0; irq < NR_IRQS; irq++) {
                cpumask_t mask;
+               int break_affinity = 0;
+               int set_affinity = 1;
+
                if (irq == 2)
                        continue;
 
+               /* interrupt's are disabled at this point */
+               spin_lock(&irq_desc[irq].lock);
+
+               if (!irq_has_action(irq) ||
+                   cpus_equal(irq_desc[irq].affinity, map)) {
+                       spin_unlock(&irq_desc[irq].lock);
+                       continue;
+               }
+
                cpus_and(mask, irq_desc[irq].affinity, map);
-               if (any_online_cpu(mask) == NR_CPUS) {
-                       printk("Breaking affinity for irq %i\n", irq);
+               if (cpus_empty(mask)) {
+                       break_affinity = 1;
                        mask = map;
                }
+
+               if (irq_desc[irq].chip->mask)
+                       irq_desc[irq].chip->mask(irq);
+
                if (irq_desc[irq].chip->set_affinity)
                        irq_desc[irq].chip->set_affinity(irq, mask);
-               else if (irq_desc[irq].action && !(warned++))
+               else if (!(warned++))
+                       set_affinity = 0;
+
+               if (irq_desc[irq].chip->unmask)
+                       irq_desc[irq].chip->unmask(irq);
+
+               spin_unlock(&irq_desc[irq].lock);
+
+               if (break_affinity && set_affinity)
+                       printk("Broke affinity for irq %i\n", irq);
+               else if (!set_affinity)
                        printk("Cannot set affinity for irq %i\n", irq);
        }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to