Espen Skoglund
2008-Jul-10 16:09 UTC
[Xen-devel] [PATCH] vt-d: Fixup when mapping devices on non-PCIe buses
vt-d: Fixup when mapping devices on non-PCIe buses The source-id for transactions on non-PCIe buses seem to originate from devfn=0 on the secondary bus behind the bridge. Map that ID as well when assigning the device. The ID to use in these scenarios is not particularly well documented anywhere. Signed-off-by: Espen Skoglund <espen.skoglund@netronome.com> diff -r 28f57cc13cd5 xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Thu Jul 10 15:06:24 2008 +0100 +++ b/xen/drivers/passthrough/vtd/iommu.c Thu Jul 10 17:10:33 2008 +0100 @@ -1186,9 +1186,10 @@ #define MAX_BUSES 256 static struct { u8 map, bus, devfn; } bus2bridge[MAX_BUSES]; -static int find_pcie_endpoint(u8 *bus, u8 *devfn) +static int find_pcie_endpoint(u8 *bus, u8 *devfn, u8 *secbus) { int cnt = 0; + *secbus = *bus; if ( *bus == 0 ) /* assume integrated PCI devices in RC have valid requester-id */ @@ -1199,6 +1200,7 @@ while ( bus2bridge[*bus].map ) { + *secbus = *bus; *devfn = bus2bridge[*bus].devfn; *bus = bus2bridge[*bus].bus; if ( cnt++ >= MAX_BUSES ) @@ -1214,6 +1216,7 @@ int ret = 0; u16 sec_bus, sub_bus, ob, odf; u32 type; + u8 secbus; drhd = acpi_find_matched_drhd_unit(bus, devfn); if ( !drhd ) @@ -1254,7 +1257,7 @@ bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); ob = bus; odf = devfn; - if ( !find_pcie_endpoint(&bus, &devfn) ) + if ( !find_pcie_endpoint(&bus, &devfn, &secbus) ) { gdprintk(XENLOG_WARNING VTDPREFIX, "domain_context_mapping:invalid"); break; @@ -1265,7 +1268,17 @@ "domain_context_mapping:map: bdf = %x:%x.%x -> %x:%x.%x\n", ob, PCI_SLOT(odf), PCI_FUNC(odf), bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn); + if ( secbus != bus ) + /* + * The source-id for transactions on non-PCIe buses seem + * to originate from devfn=0 on the secondary bus behind + * the bridge. Map that id as well. The id to use in + * these scanarios is not particularly well documented + * anywhere. + */ + domain_context_mapping_one(domain, drhd->iommu, secbus, 0); break; default: @@ -1313,6 +1326,7 @@ u16 sec_bus, sub_bus; int ret = 0; u32 type; + u8 secbus; drhd = acpi_find_matched_drhd_unit(bus, devfn); if ( !drhd ) @@ -1337,8 +1351,10 @@ break; case DEV_TYPE_PCI: - if ( find_pcie_endpoint(&bus, &devfn) ) + if ( find_pcie_endpoint(&bus, &devfn, &secbus) ) ret = domain_context_unmap_one(drhd->iommu, bus, devfn); + if ( bus != secbus ) + domain_context_unmap_one(drhd->iommu, secbus, 0); break; default: @@ -1776,7 +1792,8 @@ static int intel_iommu_group_id(u8 bus, u8 devfn) { - if ( !bus2bridge[bus].map || find_pcie_endpoint(&bus, &devfn) ) + u8 secbus; + if ( !bus2bridge[bus].map || find_pcie_endpoint(&bus, &devfn, &secbus) ) return PCI_BDF2(bus, devfn); else return -1; _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel