[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] dom0 linux: Fix issue on reassigning resources to PCI-PCI bridge.



This patch fixes the issue on reassigning resources to PCI-PCI bridge,
which was found by Zhao, Yu.

Current "quirk_align_mem_resources" updates Base/Limit register of
PCI-PCI bridge, if IORESOURCE_MEM is set in "dev->resource[i].flags".
But, when "quirk_align_mem_resources" is called, dev->resource[i].flags
is not initialized, because "quirk_align_mem_resources" is called
before "pci_read_bridge_bases". As a result, current code does not
update Base/Limit register.

This patch sets All F to Base register and sets 0 to Limit register,
regardless of "dev->resource[i].flags". After that,
"pci_assign_unassigned_resources" calculates resource window size and
assigns resource to PCI-PCI bridge.

Thanks,
--
Yuji Shimada


Signed-off-by: Yuji Shimada <shimada-yxb@xxxxxxxxxxxxxxx>

diff -r 16c549b3ba59 drivers/pci/pci.h
--- a/drivers/pci/pci.h Tue Oct 14 14:58:08 2008 +0100
+++ b/drivers/pci/pci.h Thu Oct 16 09:16:56 2008 +0900
@@ -102,7 +102,7 @@ pci_match_one_device(const struct pci_de
 #ifdef CONFIG_PCI_REASSIGN
 extern int reassign_resources;
 extern int is_reassigndev(struct pci_dev *dev);
-extern void pci_update_bridge(struct pci_dev *dev, int resno);
+extern void pci_disable_bridge_window(struct pci_dev *dev);
 #else
 #define reassign_resources 0
 #define is_reassigndev(dev) 0
diff -r 16c549b3ba59 drivers/pci/quirks.c
--- a/drivers/pci/quirks.c      Tue Oct 14 14:58:08 2008 +0100
+++ b/drivers/pci/quirks.c      Thu Oct 16 09:13:58 2008 +0900
@@ -69,8 +69,7 @@ static void __devinit quirk_align_mem_re
 
                        for (i=0; i < PCI_NUM_RESOURCES; i++) {
                                r = &dev->resource[i];
-                               if ((r == NULL) || 
-                                  !(r->flags & IORESOURCE_MEM))
+                               if (!(r->flags & IORESOURCE_MEM))
                                        continue;
 
                                r->end = r->end - r->start;
@@ -78,14 +77,15 @@ static void __devinit quirk_align_mem_re
 
                                if (i < PCI_BRIDGE_RESOURCES) {
                                        pci_update_resource(dev, r, i);
-                               } else if (i == 8 || i == 9) {
-                                       /* need to update(clear) the Base/Limit
-                                        * register also, because PCI bridge is
-                                        * disabled and the resource is 
-                                        * released.
-                                        */
-                                       pci_update_bridge(dev, i);
                                }
+                       }
+                       /* need to disable bridge's resource window,
+                        * to make kernel enable to reassign new resource
+                        * window later on.
+                        */
+                       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
+                           (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+                               pci_disable_bridge_window(dev);
                        }
                }
                return;
diff -r 16c549b3ba59 drivers/pci/setup-res.c
--- a/drivers/pci/setup-res.c   Tue Oct 14 14:58:08 2008 +0100
+++ b/drivers/pci/setup-res.c   Thu Oct 16 09:21:01 2008 +0900
@@ -118,72 +118,17 @@ EXPORT_SYMBOL_GPL(pci_claim_resource);
 EXPORT_SYMBOL_GPL(pci_claim_resource);
 
 #ifdef CONFIG_PCI_REASSIGN
-void
-pci_update_bridge(struct pci_dev *dev, int resno)
-{
-       struct resource *res = &dev->resource[resno]; 
-       struct pci_bus_region region;
-       u32 l, dw, base_up32, limit_up32;
-
-       if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE ||
-           (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) {
-               return;
-       }
-
-       if (!res->flags)
-               return;
-
-       switch (resno) {
-       case 8 :        /* MMIO Base/Limit */
-               pcibios_resource_to_bus(dev, &region, res);
-               if (res->flags & IORESOURCE_MEM &&
-                   !(res->flags & IORESOURCE_PREFETCH)) {
-                       l = (region.start >> 16) & 0xfff0;
-                       l |= region.end & 0xfff00000;
-               } else {
-                       l = 0x0000fff0;
-               }
-               pci_write_config_dword(dev, PCI_MEMORY_BASE, l);
-
-               break;
-
-       case 9 :        /* Prefetchable MMIO Base/Limit */
-               /* Clear out the upper 32 bits of PREF limit.
-                * If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily
-                * disables PREF range, which is ok.
-                */
-               pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0);
-
-               /* Get PREF 32/64 bits Addressing mode */
-               pci_read_config_dword(dev, PCI_PREF_MEMORY_BASE, &dw);
-
-               pcibios_resource_to_bus(dev, &region, res);
-               if (res->flags & IORESOURCE_MEM &&
-                   res->flags & IORESOURCE_PREFETCH) {
-                       l = (region.start >> 16) & 0xfff0;
-                       l |= region.end & 0xfff00000;
-
-                       if (dw & PCI_PREF_RANGE_TYPE_64) {
-                               base_up32 = (region.start >> 32) & 0xffffffff;
-                               limit_up32 = (region.end >> 32) & 0xffffffff;
-                       } else {
-                               base_up32 = 0;
-                               limit_up32 = 0;
-                       }
-               } else {
-                       l = 0x0000fff0;
-                       base_up32 = 0xffffffff;
-                       limit_up32 = 0;
-               }
-               pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, l);
-               /* Set up the upper 32 bits of PREF base/limit. */
-               pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, base_up32);
-               pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, limit_up32);
-               break;
-       default :
-               BUG();
-               break;
-       }
+void pci_disable_bridge_window(struct pci_dev *dev)
+{
+       printk(KERN_DEBUG "PCI: Disable bridge window on %s\n", pci_name(dev));
+  
+       /* MMIO Base/Limit */
+       pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0);
+  
+       /* Prefetchable MMIO Base/Limit */
+       pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0);
+       pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0x0000fff0);
+       pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff);
 }
 #endif
 



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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.