IRQ: Introduce old_vector to irq_cfg
authorAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 5 Sep 2011 14:09:24 +0000 (15:09 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 5 Sep 2011 14:09:24 +0000 (15:09 +0100)
Introduce old_vector to irq_cfg with the same principle as
old_cpu_mask.  This removes a brute force loop from
__clear_irq_vector(), and paves the way to correct bitrotten logic
elsewhere in the irq code.

Signed-off-by Andrew Cooper <andrew.cooper3@citrix.com>

xen/arch/x86/io_apic.c
xen/arch/x86/irq.c
xen/include/asm-x86/irq.h

index 0fdcc7d6944adc5352fa2347aae5d6eb818e515c..bccd52be8ea428e0bb74a9947dffe37b5c09486c 100644 (file)
@@ -488,11 +488,16 @@ fastcall void smp_irq_move_cleanup_interrupt(struct cpu_user_regs *regs)
         __get_cpu_var(vector_irq)[vector] = -1;
         cfg->move_cleanup_count--;
 
-        if ( cfg->move_cleanup_count == 0 
-             &&  cfg->used_vectors )
+        if ( cfg->move_cleanup_count == 0 )
         {
-            ASSERT(test_bit(vector, cfg->used_vectors));
-            clear_bit(vector, cfg->used_vectors);
+            cfg->old_vector = IRQ_VECTOR_UNASSIGNED;
+            cpus_clear(cfg->old_cpu_mask);
+
+            if ( cfg->used_vectors )
+            {
+                ASSERT(test_bit(vector, cfg->used_vectors));
+                clear_bit(vector, cfg->used_vectors);
+            }
         }
 unlock:
         spin_unlock(&desc->lock);
index 4357389c5a57fae92623d38e8f0c8ed5e964dc11..71fea2d74f78cc5430c144204877feb2547d9a96 100644 (file)
@@ -43,8 +43,6 @@ vmask_t global_used_vector_map;
 u8 __read_mostly *irq_vector;
 struct irq_desc __read_mostly *irq_desc = NULL;
 
-#define IRQ_VECTOR_UNASSIGNED (0)
-
 static DECLARE_BITMAP(used_vectors, NR_VECTORS);
 
 struct irq_cfg __read_mostly *irq_cfg = NULL;
@@ -235,15 +233,9 @@ static void __clear_irq_vector(int irq)
 
     cpus_and(tmp_mask, cfg->old_cpu_mask, cpu_online_map);
     for_each_cpu_mask(cpu, tmp_mask) {
-        for (vector = FIRST_DYNAMIC_VECTOR; vector <= LAST_DYNAMIC_VECTOR;
-                                vector++) {
-            if (per_cpu(vector_irq, cpu)[vector] != irq)
-                continue;
-            TRACE_3D(TRC_HW_IRQ_MOVE_FINISH,
-                     irq, vector, cpu);
-            per_cpu(vector_irq, cpu)[vector] = -1;
-             break;
-        }
+        ASSERT( per_cpu(vector_irq, cpu)[cfg->old_vector] == irq );
+        TRACE_3D(TRC_HW_IRQ_MOVE_FINISH, irq, vector, cpu);
+        per_cpu(vector_irq, cpu)[cfg->old_vector] = -1;
      }
 
     if ( cfg->used_vectors )
@@ -253,6 +245,8 @@ static void __clear_irq_vector(int irq)
     }
 
     cfg->move_in_progress = 0;
+    cfg->old_vector = IRQ_VECTOR_UNASSIGNED;
+    cpus_clear(cfg->old_cpu_mask);
 }
 
 void clear_irq_vector(int irq)
@@ -303,6 +297,7 @@ static void __init init_one_irq_desc(struct irq_desc *desc)
 static void __init init_one_irq_cfg(struct irq_cfg *cfg)
 {
     cfg->vector = IRQ_VECTOR_UNASSIGNED;
+    cfg->old_vector = IRQ_VECTOR_UNASSIGNED;
     cpus_clear(cfg->cpu_mask);
     cpus_clear(cfg->old_cpu_mask);
     cfg->used_vectors = NULL;
@@ -491,6 +486,7 @@ next:
         if (old_vector) {
             cfg->move_in_progress = 1;
             cpus_copy(cfg->old_cpu_mask, cfg->cpu_mask);
+            cfg->old_vector = cfg->vector;
         }
         trace_irq_mask(TRC_HW_IRQ_ASSIGN_VECTOR, irq, vector, &tmp_mask);
         for_each_cpu_mask(new_cpu, tmp_mask)
index 4b59629731a7ffd15eb09a67145178f8b505f708..8b6c106aab3dd7853b1faf7955614e8ffd596a2b 100644 (file)
@@ -28,7 +28,8 @@ typedef struct {
 } vmask_t;
 
 struct irq_cfg {
-        int  vector;
+        s16 vector;                  /* vector itself is only 8 bits, */
+        s16 old_vector;              /* but we use -1 for unassigned  */
         cpumask_t cpu_mask;
         cpumask_t old_cpu_mask;
         unsigned move_cleanup_count;
@@ -41,6 +42,8 @@ struct irq_cfg {
 #define IRQ_UNUSED      (0)
 #define IRQ_USED        (1)
 
+#define IRQ_VECTOR_UNASSIGNED (-1)
+
 extern struct irq_cfg *irq_cfg;
 
 typedef int vector_irq_t[NR_VECTORS];