[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |