debuggers.hg
changeset 18972:d238101c1832
VT-d: Fix PCI-X device assignment
When assign PCI device, current code just map its bridge and its
secondary bus number and devfn 0. It doesn't work for PCI-x device
assignment, because the request may be the source-id in the original
PCI-X transaction or the source-id provided by the bridge. It needs to
map the device itself, and its upstream bridges till PCIe-to-PCI/PCI-x
bridge.
In addition, add description for DEV_TYPE_PCIe_BRIDGE and
DEV_TYPE_PCI_BRIDGE for understandability.
Signed-off-by: Weidong Han <weidong.han@intel.com>
When assign PCI device, current code just map its bridge and its
secondary bus number and devfn 0. It doesn't work for PCI-x device
assignment, because the request may be the source-id in the original
PCI-X transaction or the source-id provided by the bridge. It needs to
map the device itself, and its upstream bridges till PCIe-to-PCI/PCI-x
bridge.
In addition, add description for DEV_TYPE_PCIe_BRIDGE and
DEV_TYPE_PCI_BRIDGE for understandability.
Signed-off-by: Weidong Han <weidong.han@intel.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Fri Dec 19 13:42:04 2008 +0000 (2008-12-19) |
parents | 8c35da364ab3 |
children | 2312cc25232b |
files | xen/drivers/passthrough/vtd/iommu.c |
line diff
1.1 --- a/xen/drivers/passthrough/vtd/iommu.c Thu Dec 18 17:18:28 2008 +0000 1.2 +++ b/xen/drivers/passthrough/vtd/iommu.c Fri Dec 19 13:42:04 2008 +0000 1.3 @@ -1129,8 +1129,8 @@ static int domain_context_mapping_one( 1.4 1.5 enum { 1.6 DEV_TYPE_PCIe_ENDPOINT, 1.7 - DEV_TYPE_PCIe_BRIDGE, 1.8 - DEV_TYPE_PCI_BRIDGE, 1.9 + DEV_TYPE_PCIe_BRIDGE, // PCIe root port, switch 1.10 + DEV_TYPE_PCI_BRIDGE, // PCIe-to-PCI/PCIx bridge, PCI-to-PCI bridge 1.11 DEV_TYPE_PCI, 1.12 }; 1.13 1.14 @@ -1144,7 +1144,8 @@ int pdev_type(u8 bus, u8 devfn) 1.15 class_device = pci_conf_read16(bus, d, f, PCI_CLASS_DEVICE); 1.16 if ( class_device == PCI_CLASS_BRIDGE_PCI ) 1.17 { 1.18 - pos = pci_find_next_cap(bus, devfn, PCI_CAPABILITY_LIST, PCI_CAP_ID_EXP); 1.19 + pos = pci_find_next_cap(bus, devfn, 1.20 + PCI_CAPABILITY_LIST, PCI_CAP_ID_EXP); 1.21 if ( !pos ) 1.22 return DEV_TYPE_PCI_BRIDGE; 1.23 creg = pci_conf_read16(bus, d, f, pos + PCI_EXP_FLAGS); 1.24 @@ -1206,7 +1207,7 @@ static int domain_context_mapping(struct 1.25 { 1.26 struct acpi_drhd_unit *drhd; 1.27 int ret = 0; 1.28 - u16 sec_bus, sub_bus, ob, odf; 1.29 + u16 sec_bus, sub_bus; 1.30 u32 type; 1.31 u8 secbus; 1.32 1.33 @@ -1220,15 +1221,13 @@ static int domain_context_mapping(struct 1.34 switch ( type ) 1.35 { 1.36 case DEV_TYPE_PCIe_BRIDGE: 1.37 + break; 1.38 + 1.39 case DEV_TYPE_PCI_BRIDGE: 1.40 sec_bus = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), 1.41 PCI_SECONDARY_BUS); 1.42 sub_bus = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), 1.43 PCI_SUBORDINATE_BUS); 1.44 - /*dmar_scope_add_buses(&drhd->scope, sec_bus, sub_bus);*/ 1.45 - 1.46 - if ( type == DEV_TYPE_PCIe_BRIDGE ) 1.47 - break; 1.48 1.49 spin_lock(&bus2bridge_lock); 1.50 for ( sub_bus &= 0xff; sec_bus <= sub_bus; sec_bus++ ) 1.51 @@ -1249,25 +1248,25 @@ static int domain_context_mapping(struct 1.52 1.53 case DEV_TYPE_PCI: 1.54 gdprintk(XENLOG_INFO VTDPREFIX, 1.55 - "domain_context_mapping:PCI: bdf = %x:%x.%x\n", 1.56 + "domain_context_mapping:PCI: bdf = %x:%x.%x\n", 1.57 bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); 1.58 1.59 - ob = bus; odf = devfn; 1.60 - if ( !find_pcie_endpoint(&bus, &devfn, &secbus) ) 1.61 + ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn); 1.62 + if ( ret ) 1.63 + break; 1.64 + 1.65 + secbus = bus; 1.66 + /* dependent devices mapping */ 1.67 + while ( bus2bridge[bus].map ) 1.68 { 1.69 - gdprintk(XENLOG_WARNING VTDPREFIX, 1.70 - "domain_context_mapping:invalid\n"); 1.71 - break; 1.72 + secbus = bus; 1.73 + devfn = bus2bridge[bus].devfn; 1.74 + bus = bus2bridge[bus].bus; 1.75 + ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn); 1.76 + if ( ret ) 1.77 + return ret; 1.78 } 1.79 1.80 - if ( ob != bus || odf != devfn ) 1.81 - gdprintk(XENLOG_INFO VTDPREFIX, 1.82 - "domain_context_mapping:map: " 1.83 - "bdf = %x:%x.%x -> %x:%x.%x\n", 1.84 - ob, PCI_SLOT(odf), PCI_FUNC(odf), 1.85 - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); 1.86 - 1.87 - ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn); 1.88 if ( secbus != bus ) 1.89 /* 1.90 * The source-id for transactions on non-PCIe buses seem 1.91 @@ -1276,7 +1275,7 @@ static int domain_context_mapping(struct 1.92 * these scanarios is not particularly well documented 1.93 * anywhere. 1.94 */ 1.95 - domain_context_mapping_one(domain, drhd->iommu, secbus, 0); 1.96 + ret = domain_context_mapping_one(domain, drhd->iommu, secbus, 0); 1.97 break; 1.98 1.99 default: 1.100 @@ -1332,7 +1331,6 @@ static int domain_context_unmap_one( 1.101 static int domain_context_unmap(struct domain *domain, u8 bus, u8 devfn) 1.102 { 1.103 struct acpi_drhd_unit *drhd; 1.104 - u16 sec_bus, sub_bus; 1.105 int ret = 0; 1.106 u32 type; 1.107 u8 secbus; 1.108 @@ -1346,24 +1344,37 @@ static int domain_context_unmap(struct d 1.109 { 1.110 case DEV_TYPE_PCIe_BRIDGE: 1.111 case DEV_TYPE_PCI_BRIDGE: 1.112 - sec_bus = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), 1.113 - PCI_SECONDARY_BUS); 1.114 - sub_bus = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), 1.115 - PCI_SUBORDINATE_BUS); 1.116 - /*dmar_scope_remove_buses(&drhd->scope, sec_bus, sub_bus);*/ 1.117 - if ( DEV_TYPE_PCI_BRIDGE ) 1.118 - ret = domain_context_unmap_one(domain, drhd->iommu, bus, devfn); 1.119 break; 1.120 1.121 case DEV_TYPE_PCIe_ENDPOINT: 1.122 + gdprintk(XENLOG_INFO VTDPREFIX, 1.123 + "domain_context_unmap:PCIe: bdf = %x:%x.%x\n", 1.124 + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); 1.125 ret = domain_context_unmap_one(domain, drhd->iommu, bus, devfn); 1.126 break; 1.127 1.128 case DEV_TYPE_PCI: 1.129 - if ( find_pcie_endpoint(&bus, &devfn, &secbus) ) 1.130 + gdprintk(XENLOG_INFO VTDPREFIX, 1.131 + "domain_context_unmap:PCI: bdf = %x:%x.%x\n", 1.132 + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); 1.133 + ret = domain_context_unmap_one(domain, drhd->iommu, bus, devfn); 1.134 + if ( ret ) 1.135 + break; 1.136 + 1.137 + secbus = bus; 1.138 + /* dependent devices unmapping */ 1.139 + while ( bus2bridge[bus].map ) 1.140 + { 1.141 + secbus = bus; 1.142 + devfn = bus2bridge[bus].devfn; 1.143 + bus = bus2bridge[bus].bus; 1.144 ret = domain_context_unmap_one(domain, drhd->iommu, bus, devfn); 1.145 + if ( ret ) 1.146 + return ret; 1.147 + } 1.148 + 1.149 if ( bus != secbus ) 1.150 - domain_context_unmap_one(domain, drhd->iommu, secbus, 0); 1.151 + ret = domain_context_unmap_one(domain, drhd->iommu, secbus, 0); 1.152 break; 1.153 1.154 default: