ia64/xen-unstable
changeset 19707:07cf79dfb59c
vtd: Fix apic pin to interrupt remapping table index
Originally, it calls xmalloc to set index in
ioapic_rte_to_remap_entry(). When make with debug=y, it may trigger
spinlock BUG_ON because allocate memory with interrupt disabled.
Signed-off-by: Weidong Han <weidong.han@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Originally, it calls xmalloc to set index in
ioapic_rte_to_remap_entry(). When make with debug=y, it may trigger
spinlock BUG_ON because allocate memory with interrupt disabled.
Signed-off-by: Weidong Han <weidong.han@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Wed Jun 03 12:59:44 2009 +0100 (2009-06-03) |
parents | 49e8816db57a |
children | c4b048ce6a4b |
files | xen/drivers/passthrough/vtd/intremap.c |
line diff
1.1 --- a/xen/drivers/passthrough/vtd/intremap.c Wed Jun 03 12:35:25 2009 +0100 1.2 +++ b/xen/drivers/passthrough/vtd/intremap.c Wed Jun 03 12:59:44 2009 +0100 1.3 @@ -31,71 +31,40 @@ 1.4 #include "vtd.h" 1.5 #include "extern.h" 1.6 1.7 -#ifndef dest_SMI 1.8 +#ifdef __ia64__ 1.9 #define dest_SMI -1 1.10 #endif 1.11 1.12 -/* The max number of IOAPIC (or IOSAPIC) pin. The typical values can be 24 or 1.13 - * 48 on x86 and Itanium platforms. Here we use a biger number 256. This 1.14 - * should be big enough. Actually now IREMAP_ENTRY_NR is also 256. 1.15 - */ 1.16 -#define MAX_IOAPIC_PIN_NUM 256 1.17 - 1.18 -struct ioapicid_pin_intremap_index { 1.19 - struct list_head list; 1.20 - unsigned int ioapic_id; 1.21 - unsigned int pin; 1.22 - int intremap_index; 1.23 -}; 1.24 - 1.25 -static struct list_head ioapic_pin_to_intremap_index[MAX_IOAPIC_PIN_NUM]; 1.26 - 1.27 -static int init_ioapic_pin_intremap_index(void) 1.28 -{ 1.29 - static int initialized = 0; 1.30 - int i; 1.31 +/* apic_pin_2_ir_idx[apicid][pin] = interrupt remapping table index */ 1.32 +static unsigned int **apic_pin_2_ir_idx; 1.33 1.34 - if ( initialized == 1 ) 1.35 - return 0; 1.36 - 1.37 - for ( i = 0; i < MAX_IOAPIC_PIN_NUM; i++ ) 1.38 - INIT_LIST_HEAD(&ioapic_pin_to_intremap_index[i]); 1.39 - 1.40 - initialized = 1; 1.41 - return 0; 1.42 -} 1.43 +static int init_apic_pin_2_ir_idx(void) 1.44 +{ 1.45 + unsigned int *_apic_pin_2_ir_idx; 1.46 + unsigned int nr_pins, i; 1.47 1.48 -static int get_ioapic_pin_intremap_index(unsigned int ioapic_id, 1.49 - unsigned int pin) 1.50 -{ 1.51 - struct ioapicid_pin_intremap_index *entry; 1.52 - struct list_head *pos, *tmp; 1.53 + nr_pins = 0; 1.54 + for ( i = 0; i < nr_ioapics; i++ ) 1.55 + nr_pins += nr_ioapic_registers[i]; 1.56 1.57 - list_for_each_safe ( pos, tmp, &ioapic_pin_to_intremap_index[pin] ) 1.58 + _apic_pin_2_ir_idx = xmalloc_array(unsigned int, nr_pins); 1.59 + apic_pin_2_ir_idx = xmalloc_array(unsigned int *, nr_ioapics); 1.60 + if ( (_apic_pin_2_ir_idx == NULL) || (apic_pin_2_ir_idx == NULL) ) 1.61 { 1.62 - entry = list_entry(pos, struct ioapicid_pin_intremap_index, list); 1.63 - if ( entry->ioapic_id == ioapic_id ) 1.64 - return entry->intremap_index; 1.65 + xfree(_apic_pin_2_ir_idx); 1.66 + xfree(apic_pin_2_ir_idx); 1.67 + return -ENOMEM; 1.68 } 1.69 1.70 - return -1; 1.71 -} 1.72 - 1.73 -static int set_ioapic_pin_intremap_index(unsigned int ioapic_id, 1.74 - unsigned int pin, 1.75 - int index) 1.76 -{ 1.77 - struct ioapicid_pin_intremap_index *entry; 1.78 + for ( i = 0; i < nr_pins; i++ ) 1.79 + _apic_pin_2_ir_idx[i] = -1; 1.80 1.81 - entry = xmalloc(struct ioapicid_pin_intremap_index); 1.82 - if ( !entry ) 1.83 - return -ENOMEM; 1.84 - 1.85 - entry->ioapic_id = ioapic_id; 1.86 - entry->pin = pin; 1.87 - entry->intremap_index = index; 1.88 - 1.89 - list_add_tail(&entry->list, &ioapic_pin_to_intremap_index[pin]); 1.90 + nr_pins = 0; 1.91 + for ( i = 0; i < nr_ioapics; i++ ) 1.92 + { 1.93 + apic_pin_2_ir_idx[i] = &_apic_pin_2_ir_idx[nr_pins]; 1.94 + nr_pins += nr_ioapic_registers[i]; 1.95 + } 1.96 1.97 return 0; 1.98 } 1.99 @@ -160,7 +129,7 @@ static int remap_entry_to_ioapic_rte( 1.100 } 1.101 1.102 static int ioapic_rte_to_remap_entry(struct iommu *iommu, 1.103 - int apic_id, unsigned int ioapic_pin, struct IO_xAPIC_route_entry *old_rte, 1.104 + int apic, unsigned int ioapic_pin, struct IO_xAPIC_route_entry *old_rte, 1.105 unsigned int rte_upper, unsigned int value) 1.106 { 1.107 struct iremap_entry *iremap_entry = NULL, *iremap_entries; 1.108 @@ -174,12 +143,12 @@ static int ioapic_rte_to_remap_entry(str 1.109 remap_rte = (struct IO_APIC_route_remap_entry *) old_rte; 1.110 spin_lock_irqsave(&ir_ctrl->iremap_lock, flags); 1.111 1.112 - index = get_ioapic_pin_intremap_index(apic_id, ioapic_pin); 1.113 + index = apic_pin_2_ir_idx[apic][ioapic_pin]; 1.114 if ( index < 0 ) 1.115 { 1.116 ir_ctrl->iremap_index++; 1.117 index = ir_ctrl->iremap_index; 1.118 - set_ioapic_pin_intremap_index(apic_id, ioapic_pin, index); 1.119 + apic_pin_2_ir_idx[apic][ioapic_pin] = index; 1.120 } 1.121 1.122 if ( index > IREMAP_ENTRY_NR - 1 ) 1.123 @@ -218,7 +187,7 @@ static int ioapic_rte_to_remap_entry(str 1.124 new_ire.lo.res_1 = 0; 1.125 new_ire.lo.vector = new_rte.vector; 1.126 new_ire.lo.res_2 = 0; 1.127 - new_ire.hi.sid = apicid_to_bdf(apic_id); 1.128 + new_ire.hi.sid = apicid_to_bdf(IO_APIC_ID(apic)); 1.129 1.130 new_ire.hi.sq = 0; /* comparing all 16-bit of SID */ 1.131 new_ire.hi.svt = 1; /* requestor ID verification SID/SQ */ 1.132 @@ -356,8 +325,7 @@ void io_apic_write_remap_rte( 1.133 *(IO_APIC_BASE(apic)+4) = *(((int *)&old_rte)+0); 1.134 remap_rte->mask = saved_mask; 1.135 1.136 - ASSERT(ioapic_pin < MAX_IOAPIC_PIN_NUM); 1.137 - if ( ioapic_rte_to_remap_entry(iommu, IO_APIC_ID(apic), ioapic_pin, 1.138 + if ( ioapic_rte_to_remap_entry(iommu, apic, ioapic_pin, 1.139 &old_rte, rte_upper, value) ) 1.140 { 1.141 *IO_APIC_BASE(apic) = rte_upper ? (reg + 1) : reg; 1.142 @@ -628,9 +596,7 @@ int enable_intremap(struct iommu *iommu) 1.143 /* After set SIRTP, we should do globally invalidate the IEC */ 1.144 iommu_flush_iec_global(iommu); 1.145 1.146 - init_ioapic_pin_intremap_index(); 1.147 - 1.148 - return 0; 1.149 + return init_apic_pin_2_ir_idx(); 1.150 } 1.151 1.152 void disable_intremap(struct iommu *iommu)