All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] VT-d: Fix PCI-X device assignment
@ 2008-12-19  2:35 Han, Weidong
  2008-12-19 12:55 ` Espen Skoglund
  0 siblings, 1 reply; 4+ messages in thread
From: Han, Weidong @ 2008-12-19  2:35 UTC (permalink / raw)
  To: xen-devel; +Cc: Kay, Allen M

[-- Attachment #1: Type: text/plain, Size: 511 bytes --]

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>

[-- Attachment #2: pcix.patch --]
[-- Type: application/octet-stream, Size: 5868 bytes --]

diff -r 22e3666ee483 xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c	Wed Dec 17 11:36:22 2008 +0000
+++ b/xen/drivers/passthrough/vtd/iommu.c	Thu Dec 18 16:48:13 2008 +0800
@@ -1129,8 +1129,8 @@ static int domain_context_mapping_one(
 
 enum {
     DEV_TYPE_PCIe_ENDPOINT,
-    DEV_TYPE_PCIe_BRIDGE,
-    DEV_TYPE_PCI_BRIDGE,
+    DEV_TYPE_PCIe_BRIDGE,    // PCIe root port, switch
+    DEV_TYPE_PCI_BRIDGE,     // PCIe-to-PCI/PCIx bridge, PCI-to-PCI bridge
     DEV_TYPE_PCI,
 };
 
@@ -1144,7 +1144,8 @@ int pdev_type(u8 bus, u8 devfn)
     class_device = pci_conf_read16(bus, d, f, PCI_CLASS_DEVICE);
     if ( class_device == PCI_CLASS_BRIDGE_PCI )
     {
-        pos = pci_find_next_cap(bus, devfn, PCI_CAPABILITY_LIST, PCI_CAP_ID_EXP);
+        pos = pci_find_next_cap(bus, devfn,
+                                PCI_CAPABILITY_LIST, PCI_CAP_ID_EXP);
         if ( !pos )
             return DEV_TYPE_PCI_BRIDGE;
         creg = pci_conf_read16(bus, d, f, pos + PCI_EXP_FLAGS);
@@ -1206,7 +1207,7 @@ static int domain_context_mapping(struct
 {
     struct acpi_drhd_unit *drhd;
     int ret = 0;
-    u16 sec_bus, sub_bus, ob, odf;
+    u16 sec_bus, sub_bus;
     u32 type;
     u8 secbus;
 
@@ -1220,15 +1221,13 @@ static int domain_context_mapping(struct
     switch ( type )
     {
     case DEV_TYPE_PCIe_BRIDGE:
+        break;
+
     case DEV_TYPE_PCI_BRIDGE:
         sec_bus = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
                                  PCI_SECONDARY_BUS);
         sub_bus = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
                                  PCI_SUBORDINATE_BUS);
-        /*dmar_scope_add_buses(&drhd->scope, sec_bus, sub_bus);*/
-
-        if ( type == DEV_TYPE_PCIe_BRIDGE )
-            break;
 
         spin_lock(&bus2bridge_lock);
         for ( sub_bus &= 0xff; sec_bus <= sub_bus; sec_bus++ )
@@ -1249,25 +1248,25 @@ static int domain_context_mapping(struct
 
     case DEV_TYPE_PCI:
         gdprintk(XENLOG_INFO VTDPREFIX,
-                 "domain_context_mapping:PCI:  bdf = %x:%x.%x\n",
+                 "domain_context_mapping:PCI: bdf = %x:%x.%x\n",
                  bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
 
-        ob = bus; odf = devfn;
-        if ( !find_pcie_endpoint(&bus, &devfn, &secbus) )
+        ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
+        if ( ret )
+           break;
+
+        secbus = bus;
+        /* dependent devices mapping */
+        while ( bus2bridge[bus].map )
         {
-            gdprintk(XENLOG_WARNING VTDPREFIX,
-                     "domain_context_mapping:invalid\n");
-            break;
+            secbus = bus;
+            devfn = bus2bridge[bus].devfn;
+            bus = bus2bridge[bus].bus;
+            ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
+            if ( ret )
+                return ret;
         }
 
-        if ( ob != bus || odf != devfn )
-            gdprintk(XENLOG_INFO VTDPREFIX,
-                     "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
@@ -1276,7 +1275,7 @@ static int domain_context_mapping(struct
              * these scanarios is not particularly well documented
              * anywhere.
              */
-            domain_context_mapping_one(domain, drhd->iommu, secbus, 0);
+            ret = domain_context_mapping_one(domain, drhd->iommu, secbus, 0);
         break;
 
     default:
@@ -1332,7 +1331,6 @@ static int domain_context_unmap(struct d
 static int domain_context_unmap(struct domain *domain, u8 bus, u8 devfn)
 {
     struct acpi_drhd_unit *drhd;
-    u16 sec_bus, sub_bus;
     int ret = 0;
     u32 type;
     u8 secbus;
@@ -1346,24 +1344,37 @@ static int domain_context_unmap(struct d
     {
     case DEV_TYPE_PCIe_BRIDGE:
     case DEV_TYPE_PCI_BRIDGE:
-        sec_bus = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
-                                 PCI_SECONDARY_BUS);
-        sub_bus = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
-                                 PCI_SUBORDINATE_BUS);
-        /*dmar_scope_remove_buses(&drhd->scope, sec_bus, sub_bus);*/
-        if ( DEV_TYPE_PCI_BRIDGE )
-            ret = domain_context_unmap_one(domain, drhd->iommu, bus, devfn);
         break;
 
     case DEV_TYPE_PCIe_ENDPOINT:
+        gdprintk(XENLOG_INFO VTDPREFIX,
+                 "domain_context_unmap:PCIe: bdf = %x:%x.%x\n",
+                 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
         ret = domain_context_unmap_one(domain, drhd->iommu, bus, devfn);
         break;
 
     case DEV_TYPE_PCI:
-        if ( find_pcie_endpoint(&bus, &devfn, &secbus) )
+        gdprintk(XENLOG_INFO VTDPREFIX,
+                 "domain_context_unmap:PCI: bdf = %x:%x.%x\n",
+                 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+        ret = domain_context_unmap_one(domain, drhd->iommu, bus, devfn);
+        if ( ret )
+            break;
+
+        secbus = bus;
+        /* dependent devices unmapping */
+        while ( bus2bridge[bus].map )
+        {
+            secbus = bus;
+            devfn = bus2bridge[bus].devfn;
+            bus = bus2bridge[bus].bus;
             ret = domain_context_unmap_one(domain, drhd->iommu, bus, devfn);
+            if ( ret )
+                return ret;
+        }
+
         if ( bus != secbus )
-            domain_context_unmap_one(domain, drhd->iommu, secbus, 0);
+            ret = domain_context_unmap_one(domain, drhd->iommu, secbus, 0);
         break;
 
     default:

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] VT-d: Fix PCI-X device assignment
  2008-12-19  2:35 [PATCH] VT-d: Fix PCI-X device assignment Han, Weidong
@ 2008-12-19 12:55 ` Espen Skoglund
  2008-12-19 13:18   ` Han, Weidong
  0 siblings, 1 reply; 4+ messages in thread
From: Espen Skoglund @ 2008-12-19 12:55 UTC (permalink / raw)
  To: Han, Weidong; +Cc: xen-devel, Kay, Allen M

Hmm... so the bridge does not take ownership of the request coming
from PCI-X devices?  As far as I remember, this was not my experience
when I tried mapping a PCI-X device (or does my memory serve me
wrong?)  I guess different chipsets behaves differently then.  Do you
know if there is a way to detect how the bridge behaves?  If the
bridge does not take ownership of the requests then we don't want to
also map devfn 0 of the bus.

	eSk


[Weidong Han]
> 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>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [PATCH] VT-d: Fix PCI-X device assignment
  2008-12-19 12:55 ` Espen Skoglund
@ 2008-12-19 13:18   ` Han, Weidong
  2008-12-19 16:54     ` Jiang, Yunhong
  0 siblings, 1 reply; 4+ messages in thread
From: Han, Weidong @ 2008-12-19 13:18 UTC (permalink / raw)
  To: 'Espen Skoglund'
  Cc: 'xen-devel@lists.xensource.com', Kay, Allen M

For PCI-X device, the requester-id "may" come from PCI-X device or its bridge.  software must consider the possibility of requests arriving with the source-id in the original PCI-X transaction or the source-id provided by the bridge. You can refer to the 3.6.1.1 Devices Behind PCI Express to PCI/PCI-X Bridges in VT-d specification.

BTW, I met DMA page faults when I assigned PCI-X device without my patch.

Regards,
Weidong


Espen Skoglund wrote:
> Hmm... so the bridge does not take ownership of the request coming
> from PCI-X devices?  As far as I remember, this was not my experience
> when I tried mapping a PCI-X device (or does my memory serve me
> wrong?)  I guess different chipsets behaves differently then.  Do you
> know if there is a way to detect how the bridge behaves?  If the
> bridge does not take ownership of the requests then we don't want to
> also map devfn 0 of the bus.
> 
> 	eSk
> 
> 
> [Weidong Han]
>> 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>
>> _______________________________________________
>> Xen-devel mailing list
>> Xen-devel@lists.xensource.com
>> http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [PATCH] VT-d: Fix PCI-X device assignment
  2008-12-19 13:18   ` Han, Weidong
@ 2008-12-19 16:54     ` Jiang, Yunhong
  0 siblings, 0 replies; 4+ messages in thread
From: Jiang, Yunhong @ 2008-12-19 16:54 UTC (permalink / raw)
  To: Han, Weidong, 'Espen Skoglund'
  Cc: 'xen-devel@lists.xensource.com', Kay, Allen M

Espen, I think you can also refer to PCIE to PCI/X bridge spec fore more information.
In sec 2.3. Assignment of Requester ID and Tag by the Bridge, it gives some items when will bridge take the ownership.

Thanks
Yunhong Jiang

xen-devel-bounces@lists.xensource.com <> wrote:
> For PCI-X device, the requester-id "may" come from PCI-X
> device or its bridge.  software must consider the possibility
> of requests arriving with the source-id in the original PCI-X
> transaction or the source-id provided by the bridge. You can
> refer to the 3.6.1.1 Devices Behind PCI Express to PCI/PCI-X
> Bridges in VT-d specification.
> 
> BTW, I met DMA page faults when I assigned PCI-X device without my patch.
> 
> Regards,
> Weidong
> 
> 
> Espen Skoglund wrote:
>> Hmm... so the bridge does not take ownership of the request coming
>> from PCI-X devices?  As far as I remember, this was not my experience
>> when I tried mapping a PCI-X device (or does my memory serve me
>> wrong?)  I guess different chipsets behaves differently then.  Do you
>> know if there is a way to detect how the bridge behaves?  If the
>> bridge does not take ownership of the requests then we don't want to also
>> map devfn 0 of the bus. 
>> 
>> 	eSk
>> 
>> 
>> [Weidong Han]
>>> 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>
>>> _______________________________________________
>>> Xen-devel mailing list
>>> Xen-devel@lists.xensource.com
>>> http://lists.xensource.com/xen-devel
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-12-19 16:54 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-12-19  2:35 [PATCH] VT-d: Fix PCI-X device assignment Han, Weidong
2008-12-19 12:55 ` Espen Skoglund
2008-12-19 13:18   ` Han, Weidong
2008-12-19 16:54     ` Jiang, Yunhong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.