[Xen-devel,PATCH-4.5,v2,08/10] xen/arm: avoid taking unconditionally the vgic.lock in gic_clear_lrs

Message ID 1392393098-7351-8-git-send-email-stefano.stabellini@eu.citrix.com
State New
Headers show

Commit Message

Stefano Stabellini Feb. 14, 2014, 3:51 p.m.
We don't actually need to call _gic_clear_lr with the vgic.lock taken,
only in case the GICH_LR has to be free'ed we need the lock.
Add a boolean vgic_locked parameter to _gic_clear_lr, so that we can
avoid taking the lock if it has been already taken, or take the lock
only in the necessary case if it hasn't.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
---
 xen/arch/arm/gic.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

Patch

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 6386ccb..54be9ca 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -689,7 +689,7 @@  void gic_set_guest_irq(struct vcpu *v, unsigned int irq,
     gic_add_to_lr_pending(v, irq, priority);
 }
 
-static void _gic_clear_lr(struct vcpu *v, int i)
+static void _gic_clear_lr(struct vcpu *v, int i, int vgic_locked)
 {
     int irq;
     uint32_t lr;
@@ -711,6 +711,7 @@  static void _gic_clear_lr(struct vcpu *v, int i)
         GICH[GICH_LR + i] = 0;
         clear_bit(i, &this_cpu(lr_mask));
 
+        if ( !vgic_locked ) spin_lock(&v->arch.vgic.lock);
         if ( p->desc != NULL )
             p->desc->status &= ~IRQ_INPROGRESS;
         clear_bit(GIC_IRQ_GUEST_VISIBLE, &p->status);
@@ -721,6 +722,7 @@  static void _gic_clear_lr(struct vcpu *v, int i)
             gic_add_to_lr_pending(v, irq, p->priority);
         } else
             list_del_init(&p->inflight);
+        if ( !vgic_locked ) spin_unlock(&v->arch.vgic.lock);
     }
 }
 
@@ -731,16 +733,14 @@  static void gic_clear_lrs(struct vcpu *v)
     while ((i = find_next_bit((const long unsigned int *) &this_cpu(lr_mask),
                               nr_lrs, i)) < nr_lrs) {
 
-        spin_lock(&v->arch.vgic.lock);
-        _gic_clear_lr(v, i);
-        spin_unlock(&v->arch.vgic.lock);
+        _gic_clear_lr(v, i, 0);
         i++;
     }
 }
 
 void gic_set_clear_lr(struct vcpu *v, struct pending_irq *p)
 {
-    _gic_clear_lr(v, p->lr);
+    _gic_clear_lr(v, p->lr, 1);
 }
 
 static void gic_restore_pending_irqs(struct vcpu *v)