[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] x86, irq: No synamic memory allocation with IRQs disabled.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1224594834 -3600
# Node ID de6af72f7b5cef2902063f2898d8238ab4697a1e
# Parent  3b99705155c156dca3e139c83830261cb7c07f6d
x86, irq: No synamic memory allocation with IRQs disabled.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/irq.c |   55 +++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 39 insertions(+), 16 deletions(-)

diff -r 3b99705155c1 -r de6af72f7b5c xen/arch/x86/irq.c
--- a/xen/arch/x86/irq.c        Tue Oct 21 11:44:39 2008 +0100
+++ b/xen/arch/x86/irq.c        Tue Oct 21 14:13:54 2008 +0100
@@ -510,7 +510,7 @@ int pirq_guest_bind(struct vcpu *v, int 
 {
     unsigned int        vector;
     irq_desc_t         *desc;
-    irq_guest_action_t *action;
+    irq_guest_action_t *action, *newaction = NULL;
     int                 rc = 0;
     cpumask_t           cpumask = CPU_MASK_NONE;
 
@@ -520,7 +520,10 @@ int pirq_guest_bind(struct vcpu *v, int 
  retry:
     desc = domain_spin_lock_irq_desc(v->domain, irq, NULL);
     if ( desc == NULL )
-        return -EINVAL;
+    {
+        rc = -EINVAL;
+        goto out;
+    }
 
     action = (irq_guest_action_t *)desc->action;
     vector = desc - irq_desc;
@@ -533,18 +536,24 @@ int pirq_guest_bind(struct vcpu *v, int 
                     "Cannot bind IRQ %d to guest. In use by '%s'.\n",
                     irq, desc->action->name);
             rc = -EBUSY;
-            goto out;
+            goto unlock_out;
         }
 
-        action = xmalloc(irq_guest_action_t);
-        if ( (desc->action = (struct irqaction *)action) == NULL )
+        if ( newaction == NULL )
         {
+            spin_unlock_irq(&desc->lock);
+            if ( (newaction = xmalloc(irq_guest_action_t)) != NULL )
+                goto retry;
             gdprintk(XENLOG_INFO,
-                    "Cannot bind IRQ %d to guest. Out of memory.\n",
-                    irq);
+                     "Cannot bind IRQ %d to guest. Out of memory.\n",
+                     irq);
             rc = -ENOMEM;
             goto out;
         }
+
+        action = newaction;
+        desc->action = (struct irqaction *)action;
+        newaction = NULL;
 
         action->nr_guests   = 0;
         action->in_flight   = 0;
@@ -568,7 +577,7 @@ int pirq_guest_bind(struct vcpu *v, int 
                "Will not share with others.\n",
                 irq);
         rc = -EBUSY;
-        goto out;
+        goto unlock_out;
     }
     else if ( action->nr_guests == 0 )
     {
@@ -588,17 +597,21 @@ int pirq_guest_bind(struct vcpu *v, int 
         gdprintk(XENLOG_INFO, "Cannot bind IRQ %d to guest. "
                "Already at max share.\n", irq);
         rc = -EBUSY;
-        goto out;
+        goto unlock_out;
     }
 
     action->guest[action->nr_guests++] = v->domain;
 
+ unlock_out:
+    spin_unlock_irq(&desc->lock);
  out:
-    spin_unlock_irq(&desc->lock);
+    if ( newaction != NULL )
+        xfree(newaction);
     return rc;
 }
 
-static void __pirq_guest_unbind(struct domain *d, int irq, irq_desc_t *desc)
+static irq_guest_action_t *__pirq_guest_unbind(
+    struct domain *d, int irq, irq_desc_t *desc)
 {
     unsigned int        vector;
     irq_guest_action_t *action;
@@ -644,7 +657,7 @@ static void __pirq_guest_unbind(struct d
     BUG_ON(test_bit(irq, d->pirq_mask));
 
     if ( action->nr_guests != 0 )
-        return;
+        return NULL;
 
     BUG_ON(action->in_flight != 0);
 
@@ -672,15 +685,18 @@ static void __pirq_guest_unbind(struct d
     BUG_ON(!cpus_empty(action->cpu_eoi_map));
 
     desc->action = NULL;
-    xfree(action);
     desc->status &= ~IRQ_GUEST;
     desc->status &= ~IRQ_INPROGRESS;
     kill_timer(&irq_guest_eoi_timer[vector]);
     desc->handler->shutdown(vector);
+
+    /* Caller frees the old guest descriptor block. */
+    return action;
 }
 
 void pirq_guest_unbind(struct domain *d, int irq)
 {
+    irq_guest_action_t *oldaction = NULL;
     irq_desc_t *desc;
     int vector;
 
@@ -699,16 +715,19 @@ void pirq_guest_unbind(struct domain *d,
     }
     else
     {
-        __pirq_guest_unbind(d, irq, desc);
+        oldaction = __pirq_guest_unbind(d, irq, desc);
     }
 
     spin_unlock_irq(&desc->lock);
+
+    if ( oldaction != NULL )
+        xfree(oldaction);
 }
 
 int pirq_guest_force_unbind(struct domain *d, int irq)
 {
     irq_desc_t *desc;
-    irq_guest_action_t *action;
+    irq_guest_action_t *action, *oldaction = NULL;
     int i, bound = 0;
 
     WARN_ON(!spin_is_locked(&d->event_lock));
@@ -727,10 +746,14 @@ int pirq_guest_force_unbind(struct domai
         goto out;
 
     bound = 1;
-    __pirq_guest_unbind(d, irq, desc);
+    oldaction = __pirq_guest_unbind(d, irq, desc);
 
  out:
     spin_unlock_irq(&desc->lock);
+
+    if ( oldaction != NULL )
+        xfree(oldaction);
+
     return bound;
 }
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.