ia64/xen-unstable

changeset 18592:51a05fb4c601

x86: Free MSI vector when a pirq is unmapped.

Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Oct 08 11:51:39 2008 +0100 (2008-10-08)
parents ed398097c03e
children 26985a665ded
files xen/arch/x86/domain.c xen/arch/x86/i8259.c xen/arch/x86/io_apic.c xen/arch/x86/irq.c xen/arch/x86/physdev.c xen/include/asm-x86/io_apic.h xen/include/asm-x86/irq.h
line diff
     1.1 --- a/xen/arch/x86/domain.c	Wed Oct 08 10:48:48 2008 +0100
     1.2 +++ b/xen/arch/x86/domain.c	Wed Oct 08 11:51:39 2008 +0100
     1.3 @@ -459,6 +459,7 @@ void arch_domain_destroy(struct domain *
     1.4          hvm_domain_destroy(d);
     1.5  
     1.6      pci_release_devices(d);
     1.7 +    free_domain_pirqs(d);
     1.8      if ( !is_idle_domain(d) )
     1.9          iommu_domain_destroy(d);
    1.10  
     2.1 --- a/xen/arch/x86/i8259.c	Wed Oct 08 10:48:48 2008 +0100
     2.2 +++ b/xen/arch/x86/i8259.c	Wed Oct 08 11:51:39 2008 +0100
     2.3 @@ -408,6 +408,10 @@ void __init init_IRQ(void)
     2.4          irq_desc[LEGACY_VECTOR(i)].handler = &i8259A_irq_type;
     2.5      }
     2.6  
     2.7 +    /* Never allocate the hypercall vector or Linux/BSD fast-trap vector. */
     2.8 +    vector_irq[HYPERCALL_VECTOR] = NEVER_ASSIGN;
     2.9 +    vector_irq[0x80] = NEVER_ASSIGN;
    2.10 +
    2.11      apic_intr_init();
    2.12  
    2.13      /* Set the clock to HZ Hz */
     3.1 --- a/xen/arch/x86/io_apic.c	Wed Oct 08 10:48:48 2008 +0100
     3.2 +++ b/xen/arch/x86/io_apic.c	Wed Oct 08 11:51:39 2008 +0100
     3.3 @@ -87,7 +87,8 @@ static struct irq_pin_list {
     3.4  } irq_2_pin[PIN_MAP_SIZE];
     3.5  static int irq_2_pin_free_entry = NR_IRQS;
     3.6  
     3.7 -int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
     3.8 +int vector_irq[NR_VECTORS] __read_mostly = {
     3.9 +    [0 ... NR_VECTORS - 1] = FREE_TO_ASSIGN};
    3.10  
    3.11  /*
    3.12   * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
    3.13 @@ -666,40 +667,46 @@ static inline int IO_APIC_irq_trigger(in
    3.14  /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
    3.15  u8 irq_vector[NR_IRQ_VECTORS] __read_mostly;
    3.16  
    3.17 +int free_irq_vector(int vector)
    3.18 +{
    3.19 +    int irq;
    3.20 +
    3.21 +    BUG_ON((vector > LAST_DYNAMIC_VECTOR) || (vector < FIRST_DYNAMIC_VECTOR));
    3.22 +
    3.23 +    spin_lock(&vector_lock);
    3.24 +    if ((irq = vector_irq[vector]) == AUTO_ASSIGN)
    3.25 +        vector_irq[vector] = FREE_TO_ASSIGN;
    3.26 +    spin_unlock(&vector_lock);
    3.27 +
    3.28 +    return (irq == AUTO_ASSIGN) ? 0 : -EINVAL;
    3.29 +}
    3.30 +
    3.31  int assign_irq_vector(int irq)
    3.32  {
    3.33 -    static unsigned current_vector = FIRST_DYNAMIC_VECTOR, offset = 0;
    3.34 +    static unsigned current_vector = FIRST_DYNAMIC_VECTOR;
    3.35      unsigned vector;
    3.36  
    3.37      BUG_ON(irq >= NR_IRQ_VECTORS);
    3.38 +
    3.39      spin_lock(&vector_lock);
    3.40  
    3.41 -    if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
    3.42 +    if ((irq != AUTO_ASSIGN) && (IO_APIC_VECTOR(irq) > 0)) {
    3.43          spin_unlock(&vector_lock);
    3.44          return IO_APIC_VECTOR(irq);
    3.45      }
    3.46  
    3.47 -next:
    3.48 -    current_vector += 8;
    3.49 -
    3.50 -    /* Skip the hypercall vector. */
    3.51 -    if (current_vector == HYPERCALL_VECTOR)
    3.52 -        goto next;
    3.53 +    vector = current_vector;
    3.54 +    while (vector_irq[vector] != FREE_TO_ASSIGN) {
    3.55 +        if (++vector > LAST_DYNAMIC_VECTOR)
    3.56 +            vector = FIRST_DYNAMIC_VECTOR;
    3.57  
    3.58 -    /* Skip the Linux/BSD fast-trap vector. */
    3.59 -    if (current_vector == 0x80)
    3.60 -        goto next;
    3.61 -
    3.62 -    if (current_vector > LAST_DYNAMIC_VECTOR) {
    3.63 -        offset++;
    3.64 -        if (!(offset%8)) {
    3.65 +        if (vector == current_vector) {
    3.66              spin_unlock(&vector_lock);
    3.67              return -ENOSPC;
    3.68          }
    3.69 -        current_vector = FIRST_DYNAMIC_VECTOR + offset;
    3.70      }
    3.71  
    3.72 -    vector = current_vector;
    3.73 +    current_vector = vector;
    3.74      vector_irq[vector] = irq;
    3.75      if (irq != AUTO_ASSIGN)
    3.76          IO_APIC_VECTOR(irq) = vector;
     4.1 --- a/xen/arch/x86/irq.c	Wed Oct 08 10:48:48 2008 +0100
     4.2 +++ b/xen/arch/x86/irq.c	Wed Oct 08 11:51:39 2008 +0100
     4.3 @@ -861,7 +861,10 @@ int unmap_domain_pirq(struct domain *d, 
     4.4          pci_disable_msi(vector);
     4.5  
     4.6      if ( desc->handler == &pci_msi_type )
     4.7 +    {
     4.8          desc->handler = &no_irq_type;
     4.9 +        free_irq_vector(vector);
    4.10 +    }
    4.11  
    4.12      if ( !forced_unbind )
    4.13      {
    4.14 @@ -885,6 +888,21 @@ int unmap_domain_pirq(struct domain *d, 
    4.15      return ret;
    4.16  }
    4.17  
    4.18 +void free_domain_pirqs(struct domain *d)
    4.19 +{
    4.20 +    int i;
    4.21 +
    4.22 +    ASSERT(d->is_dying == DOMDYING_dying);
    4.23 +
    4.24 +    spin_lock(&d->evtchn_lock);
    4.25 +
    4.26 +    for ( i = 0; i < NR_PIRQS; i++ )
    4.27 +        if ( d->arch.pirq_vector[i] > 0 )
    4.28 +            unmap_domain_pirq(d, i);
    4.29 +
    4.30 +    spin_unlock(&d->evtchn_lock);
    4.31 +}
    4.32 +
    4.33  extern void dump_ioapic_irq_info(void);
    4.34  
    4.35  static void dump_irqs(unsigned char key)
     5.1 --- a/xen/arch/x86/physdev.c	Wed Oct 08 10:48:48 2008 +0100
     5.2 +++ b/xen/arch/x86/physdev.c	Wed Oct 08 11:51:39 2008 +0100
     5.3 @@ -79,7 +79,7 @@ static int physdev_map_pirq(struct physd
     5.4              if ( vector < 0 || vector >= NR_VECTORS )
     5.5              {
     5.6                  dprintk(XENLOG_G_ERR, "dom%d: map irq with wrong vector %d\n",
     5.7 -                        d->domain_id, map->index);
     5.8 +                        d->domain_id, vector);
     5.9                  ret = -EINVAL;
    5.10                  goto free_domain;
    5.11              }
    5.12 @@ -140,13 +140,14 @@ static int physdev_map_pirq(struct physd
    5.13              pirq = map->pirq;
    5.14      }
    5.15  
    5.16 -
    5.17      ret = map_domain_pirq(d, pirq, vector, map->type, map_data);
    5.18 -    if ( !ret )
    5.19 +    if ( ret == 0 )
    5.20          map->pirq = pirq;
    5.21  
    5.22  done:
    5.23      spin_unlock(&d->evtchn_lock);
    5.24 +    if ( (ret != 0) && (map->type == MAP_PIRQ_TYPE_MSI) && (map->index == -1) )
    5.25 +        free_irq_vector(vector);
    5.26  free_domain:
    5.27      rcu_unlock_domain(d);
    5.28      return ret;
     6.1 --- a/xen/include/asm-x86/io_apic.h	Wed Oct 08 10:48:48 2008 +0100
     6.2 +++ b/xen/include/asm-x86/io_apic.h	Wed Oct 08 11:51:39 2008 +0100
     6.3 @@ -190,5 +190,6 @@ static inline int ioapic_resume(void) {r
     6.4  #endif
     6.5  
     6.6  extern int assign_irq_vector(int irq);
     6.7 +extern int free_irq_vector(int vector);
     6.8  
     6.9  #endif
     7.1 --- a/xen/include/asm-x86/irq.h	Wed Oct 08 10:48:48 2008 +0100
     7.2 +++ b/xen/include/asm-x86/irq.h	Wed Oct 08 11:51:39 2008 +0100
     7.3 @@ -19,7 +19,9 @@
     7.4  
     7.5  extern int vector_irq[NR_VECTORS];
     7.6  extern u8 irq_vector[NR_IRQ_VECTORS];
     7.7 -#define AUTO_ASSIGN             -1
     7.8 +#define AUTO_ASSIGN    -1
     7.9 +#define NEVER_ASSIGN   -2
    7.10 +#define FREE_TO_ASSIGN -3
    7.11  
    7.12  #define platform_legacy_irq(irq)	((irq) < 16)
    7.13  
    7.14 @@ -56,6 +58,7 @@ int map_domain_pirq(struct domain *d, in
    7.15                             void *data);
    7.16  int unmap_domain_pirq(struct domain *d, int pirq);
    7.17  int get_free_pirq(struct domain *d, int type, int index);
    7.18 +void free_domain_pirqs(struct domain *d);
    7.19  
    7.20  #define domain_irq_to_vector(d, irq) ((d)->arch.pirq_vector[(irq)])
    7.21  #define domain_vector_to_irq(d, vec) ((d)->arch.vector_pirq[(vec)])