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

[Xen-changelog] [xen-unstable] x86: Free MSI vector when a pirq is unmapped.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1223463099 -3600
# Node ID 51a05fb4c6014059058de48b83a9431e7474a456
# Parent  ed398097c03e16dacb1f3af19fa8faddf2deae1f
x86: Free MSI vector when a pirq is unmapped.

Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/domain.c         |    1 
 xen/arch/x86/i8259.c          |    4 +++
 xen/arch/x86/io_apic.c        |   49 ++++++++++++++++++++++++------------------
 xen/arch/x86/irq.c            |   18 +++++++++++++++
 xen/arch/x86/physdev.c        |    7 +++---
 xen/include/asm-x86/io_apic.h |    1 
 xen/include/asm-x86/irq.h     |    5 +++-
 7 files changed, 60 insertions(+), 25 deletions(-)

diff -r ed398097c03e -r 51a05fb4c601 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Wed Oct 08 10:48:48 2008 +0100
+++ b/xen/arch/x86/domain.c     Wed Oct 08 11:51:39 2008 +0100
@@ -459,6 +459,7 @@ void arch_domain_destroy(struct domain *
         hvm_domain_destroy(d);
 
     pci_release_devices(d);
+    free_domain_pirqs(d);
     if ( !is_idle_domain(d) )
         iommu_domain_destroy(d);
 
diff -r ed398097c03e -r 51a05fb4c601 xen/arch/x86/i8259.c
--- a/xen/arch/x86/i8259.c      Wed Oct 08 10:48:48 2008 +0100
+++ b/xen/arch/x86/i8259.c      Wed Oct 08 11:51:39 2008 +0100
@@ -408,6 +408,10 @@ void __init init_IRQ(void)
         irq_desc[LEGACY_VECTOR(i)].handler = &i8259A_irq_type;
     }
 
+    /* Never allocate the hypercall vector or Linux/BSD fast-trap vector. */
+    vector_irq[HYPERCALL_VECTOR] = NEVER_ASSIGN;
+    vector_irq[0x80] = NEVER_ASSIGN;
+
     apic_intr_init();
 
     /* Set the clock to HZ Hz */
diff -r ed398097c03e -r 51a05fb4c601 xen/arch/x86/io_apic.c
--- a/xen/arch/x86/io_apic.c    Wed Oct 08 10:48:48 2008 +0100
+++ b/xen/arch/x86/io_apic.c    Wed Oct 08 11:51:39 2008 +0100
@@ -87,7 +87,8 @@ static struct irq_pin_list {
 } irq_2_pin[PIN_MAP_SIZE];
 static int irq_2_pin_free_entry = NR_IRQS;
 
-int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
+int vector_irq[NR_VECTORS] __read_mostly = {
+    [0 ... NR_VECTORS - 1] = FREE_TO_ASSIGN};
 
 /*
  * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
@@ -666,40 +667,46 @@ static inline int IO_APIC_irq_trigger(in
 /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
 u8 irq_vector[NR_IRQ_VECTORS] __read_mostly;
 
+int free_irq_vector(int vector)
+{
+    int irq;
+
+    BUG_ON((vector > LAST_DYNAMIC_VECTOR) || (vector < FIRST_DYNAMIC_VECTOR));
+
+    spin_lock(&vector_lock);
+    if ((irq = vector_irq[vector]) == AUTO_ASSIGN)
+        vector_irq[vector] = FREE_TO_ASSIGN;
+    spin_unlock(&vector_lock);
+
+    return (irq == AUTO_ASSIGN) ? 0 : -EINVAL;
+}
+
 int assign_irq_vector(int irq)
 {
-    static unsigned current_vector = FIRST_DYNAMIC_VECTOR, offset = 0;
+    static unsigned current_vector = FIRST_DYNAMIC_VECTOR;
     unsigned vector;
 
     BUG_ON(irq >= NR_IRQ_VECTORS);
+
     spin_lock(&vector_lock);
 
-    if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
+    if ((irq != AUTO_ASSIGN) && (IO_APIC_VECTOR(irq) > 0)) {
         spin_unlock(&vector_lock);
         return IO_APIC_VECTOR(irq);
     }
 
-next:
-    current_vector += 8;
-
-    /* Skip the hypercall vector. */
-    if (current_vector == HYPERCALL_VECTOR)
-        goto next;
-
-    /* Skip the Linux/BSD fast-trap vector. */
-    if (current_vector == 0x80)
-        goto next;
-
-    if (current_vector > LAST_DYNAMIC_VECTOR) {
-        offset++;
-        if (!(offset%8)) {
+    vector = current_vector;
+    while (vector_irq[vector] != FREE_TO_ASSIGN) {
+        if (++vector > LAST_DYNAMIC_VECTOR)
+            vector = FIRST_DYNAMIC_VECTOR;
+
+        if (vector == current_vector) {
             spin_unlock(&vector_lock);
             return -ENOSPC;
         }
-        current_vector = FIRST_DYNAMIC_VECTOR + offset;
-    }
-
-    vector = current_vector;
+    }
+
+    current_vector = vector;
     vector_irq[vector] = irq;
     if (irq != AUTO_ASSIGN)
         IO_APIC_VECTOR(irq) = vector;
diff -r ed398097c03e -r 51a05fb4c601 xen/arch/x86/irq.c
--- a/xen/arch/x86/irq.c        Wed Oct 08 10:48:48 2008 +0100
+++ b/xen/arch/x86/irq.c        Wed Oct 08 11:51:39 2008 +0100
@@ -861,7 +861,10 @@ int unmap_domain_pirq(struct domain *d, 
         pci_disable_msi(vector);
 
     if ( desc->handler == &pci_msi_type )
+    {
         desc->handler = &no_irq_type;
+        free_irq_vector(vector);
+    }
 
     if ( !forced_unbind )
     {
@@ -883,6 +886,21 @@ int unmap_domain_pirq(struct domain *d, 
 
  done:
     return ret;
+}
+
+void free_domain_pirqs(struct domain *d)
+{
+    int i;
+
+    ASSERT(d->is_dying == DOMDYING_dying);
+
+    spin_lock(&d->evtchn_lock);
+
+    for ( i = 0; i < NR_PIRQS; i++ )
+        if ( d->arch.pirq_vector[i] > 0 )
+            unmap_domain_pirq(d, i);
+
+    spin_unlock(&d->evtchn_lock);
 }
 
 extern void dump_ioapic_irq_info(void);
diff -r ed398097c03e -r 51a05fb4c601 xen/arch/x86/physdev.c
--- a/xen/arch/x86/physdev.c    Wed Oct 08 10:48:48 2008 +0100
+++ b/xen/arch/x86/physdev.c    Wed Oct 08 11:51:39 2008 +0100
@@ -79,7 +79,7 @@ static int physdev_map_pirq(struct physd
             if ( vector < 0 || vector >= NR_VECTORS )
             {
                 dprintk(XENLOG_G_ERR, "dom%d: map irq with wrong vector %d\n",
-                        d->domain_id, map->index);
+                        d->domain_id, vector);
                 ret = -EINVAL;
                 goto free_domain;
             }
@@ -140,13 +140,14 @@ static int physdev_map_pirq(struct physd
             pirq = map->pirq;
     }
 
-
     ret = map_domain_pirq(d, pirq, vector, map->type, map_data);
-    if ( !ret )
+    if ( ret == 0 )
         map->pirq = pirq;
 
 done:
     spin_unlock(&d->evtchn_lock);
+    if ( (ret != 0) && (map->type == MAP_PIRQ_TYPE_MSI) && (map->index == -1) )
+        free_irq_vector(vector);
 free_domain:
     rcu_unlock_domain(d);
     return ret;
diff -r ed398097c03e -r 51a05fb4c601 xen/include/asm-x86/io_apic.h
--- a/xen/include/asm-x86/io_apic.h     Wed Oct 08 10:48:48 2008 +0100
+++ b/xen/include/asm-x86/io_apic.h     Wed Oct 08 11:51:39 2008 +0100
@@ -190,5 +190,6 @@ static inline int ioapic_resume(void) {r
 #endif
 
 extern int assign_irq_vector(int irq);
+extern int free_irq_vector(int vector);
 
 #endif
diff -r ed398097c03e -r 51a05fb4c601 xen/include/asm-x86/irq.h
--- a/xen/include/asm-x86/irq.h Wed Oct 08 10:48:48 2008 +0100
+++ b/xen/include/asm-x86/irq.h Wed Oct 08 11:51:39 2008 +0100
@@ -19,7 +19,9 @@
 
 extern int vector_irq[NR_VECTORS];
 extern u8 irq_vector[NR_IRQ_VECTORS];
-#define AUTO_ASSIGN             -1
+#define AUTO_ASSIGN    -1
+#define NEVER_ASSIGN   -2
+#define FREE_TO_ASSIGN -3
 
 #define platform_legacy_irq(irq)       ((irq) < 16)
 
@@ -56,6 +58,7 @@ int map_domain_pirq(struct domain *d, in
                            void *data);
 int unmap_domain_pirq(struct domain *d, int pirq);
 int get_free_pirq(struct domain *d, int type, int index);
+void free_domain_pirqs(struct domain *d);
 
 #define domain_irq_to_vector(d, irq) ((d)->arch.pirq_vector[(irq)])
 #define domain_vector_to_irq(d, vec) ((d)->arch.vector_pirq[(vec)])

_______________________________________________
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®.