# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1215707603 -3600
# Node ID 27aaff984b3679375819075ae2bbec4e05dc9b50
# Parent 07c7aef164cf88f8dbe9e5d967f0099f31790918
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@xxxxxxxxxxxxx>
---
xen/drivers/passthrough/vtd/iommu.c | 25 +++++++++++++++++++++----
1 files changed, 21 insertions(+), 4 deletions(-)
diff -r 07c7aef164cf -r 27aaff984b36 xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c Thu Jul 10 17:29:06 2008 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c Thu Jul 10 17:33:23 2008 +0100
@@ -1186,9 +1186,10 @@ int pdev_type(u8 bus, u8 devfn)
#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 @@ static int find_pcie_endpoint(u8 *bus, u
while ( bus2bridge[*bus].map )
{
+ *secbus = *bus;
*devfn = bus2bridge[*bus].devfn;
*bus = bus2bridge[*bus].bus;
if ( cnt++ >= MAX_BUSES )
@@ -1214,6 +1216,7 @@ static int domain_context_mapping(struct
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 @@ static int domain_context_mapping(struct
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 @@ static int domain_context_mapping(struct
"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 @@ static int domain_context_unmap(u8 bus,
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 @@ static int domain_context_unmap(u8 bus,
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 @@ int intel_iommu_assign_device(struct dom
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-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|