x86,irq: Clean up __clear_irq_vector
authorKeir Fraser <keir@xen.org>
Fri, 30 Sep 2011 20:15:21 +0000 (21:15 +0100)
committerKeir Fraser <keir@xen.org>
Fri, 30 Sep 2011 20:15:21 +0000 (21:15 +0100)
Fix and clean up the logic to __clear_irq_vector().

We always need to clear the things related to cfg->vector.

If the IRQ is currently in motion, then we need to also clear
out things related to cfg->old_vector.

This patch reorganizes the function to make the parallels between
the two clean-ups more obvious.

The main functional change here is with cfg->used_vectors; make
sure to clear cfg->vector always (even if !cfg->move_in_progress);
if cfg->move_in_progress, clear cfg->old_vector as well.

Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
xen/arch/x86/irq.c

index e0b2d0137966ad9999b053e4557ad0899a95fa05..75041049bf4bfa3ba6f7acf717f52bd13c66ecb3 100644 (file)
@@ -211,43 +211,57 @@ static void dynamic_irq_cleanup(unsigned int irq)
 
 static void __clear_irq_vector(int irq)
 {
-    int cpu, vector;
+    int cpu, vector, old_vector;
     cpumask_t tmp_mask;
     struct irq_cfg *cfg = irq_cfg(irq);
 
     BUG_ON(!cfg->vector);
 
+    /* Always clear cfg->vector */
     vector = cfg->vector;
     cpus_and(tmp_mask, cfg->cpu_mask, cpu_online_map);
 
-    trace_irq_mask(TRC_HW_IRQ_CLEAR_VECTOR, irq, vector, &tmp_mask);
-
-    for_each_cpu_mask(cpu, tmp_mask)
+    for_each_cpu_mask(cpu, tmp_mask) {
+        ASSERT( per_cpu(vector_irq, cpu)[vector] == irq );
         per_cpu(vector_irq, cpu)[vector] = -1;
+    }
 
     cfg->vector = IRQ_VECTOR_UNASSIGNED;
     cpus_clear(cfg->cpu_mask);
+
+    if ( cfg->used_vectors )
+    {
+        ASSERT(test_bit(vector, cfg->used_vectors));
+        clear_bit(vector, cfg->used_vectors);
+    }
+
     cfg->used = IRQ_UNUSED;
 
+    trace_irq_mask(TRC_HW_IRQ_CLEAR_VECTOR, irq, vector, &tmp_mask);
+
     if (likely(!cfg->move_in_progress))
         return;
 
+    /* If we were in motion, also clear cfg->old_vector */
+    old_vector = cfg->old_vector;
     cpus_and(tmp_mask, cfg->old_cpu_mask, cpu_online_map);
+
     for_each_cpu_mask(cpu, tmp_mask) {
-        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;
+        ASSERT( per_cpu(vector_irq, cpu)[old_vector] == irq );
+        TRACE_3D(TRC_HW_IRQ_MOVE_FINISH, irq, old_vector, cpu);
+        per_cpu(vector_irq, cpu)[old_vector] = -1;
      }
 
+    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);
+        ASSERT(test_bit(old_vector, cfg->used_vectors));
+        clear_bit(old_vector, cfg->used_vectors);
     }
 
     cfg->move_in_progress = 0;
-    cfg->old_vector = IRQ_VECTOR_UNASSIGNED;
-    cpus_clear(cfg->old_cpu_mask);
 }
 
 void clear_irq_vector(int irq)