]> xenbits.xensource.com Git - xen.git/commitdiff
Clear IRQ_GUEST in irq_desc->status when setting action to NULL.
authorIgor Mammedov <imammedo@redhat.com>
Mon, 3 Oct 2011 15:35:03 +0000 (16:35 +0100)
committerIgor Mammedov <imammedo@redhat.com>
Mon, 3 Oct 2011 15:35:03 +0000 (16:35 +0100)
Looking more closely at usage of action field with relation to
IRQ_GUEST flag. It appears that set IRQ_GUEST implies that action
is not NULL. As result it is not safe to set action to NULL and
leave IRQ_GUEST set.

Hence IRQ_GUEST should be cleared in dynamic_irq_cleanup where
action is set to NULL.

An addition remove BUGON at __pirq_guest_unbind that appears to be
bogus and not needed anymore.

Thanks Paolo Bonzini for NACKing previous patch, and pointing at the
correct solution.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reinstate the BUG_ON, but after the action==NULL check. Since we then
go and start interpreting action as an irq_guest_action_t, the BUG_ON
is relevant here.

More generally, the brute-force nature of dynamic_irq_cleanup() looks
a bit worrying. Possibly there should be more integratioin with
pirq_guest_unbind() logic, for cleaning up un-acked EOIs and the like.

Signed-off-by: Keir Fraser <keir@xen.org>
xen-unstable changeset:   23852:c944e82bb092
xen-unstable date:        Sun Sep 18 00:00:26 2011 +0100

xen/arch/x86/irq.c

index 60cb65d121ab8e31578834d5330b89eb6a78cc55..bf0bcf68de91bf7f0e868115af2a8d8738fd746b 100644 (file)
@@ -154,6 +154,7 @@ static void dynamic_irq_cleanup(unsigned int irq)
 
     spin_lock_irqsave(&desc->lock, flags);
     desc->status  |= IRQ_DISABLED;
+    desc->status  &= ~IRQ_GUEST;
     desc->handler->shutdown(irq);
     action = desc->action;
     desc->action  = NULL;
@@ -1277,8 +1278,6 @@ static irq_guest_action_t *__pirq_guest_unbind(
     cpumask_t           cpu_eoi_map;
     int                 i;
 
-    BUG_ON(!(desc->status & IRQ_GUEST));
-
     action = (irq_guest_action_t *)desc->action;
     irq = desc - irq_desc;
 
@@ -1289,6 +1288,8 @@ static irq_guest_action_t *__pirq_guest_unbind(
         return NULL;
     }
 
+    BUG_ON(!(desc->status & IRQ_GUEST));
+
     for ( i = 0; (i < action->nr_guests) && (action->guest[i] != d); i++ )
         continue;
     BUG_ON(i == action->nr_guests);