# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1224241316 -3600
# Node ID 8fbf8e2fd08770446fd5f852da83edf0e6b82430
# Parent 16c549b3ba59e21c36f03a1e499e7908417ecca1
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.
Signed-off-by: Yuji Shimada <shimada-yxb@xxxxxxxxxxxxxxx>
---
drivers/pci/pci.h | 2 -
drivers/pci/quirks.c | 18 +++++------
drivers/pci/setup-res.c | 77 ++++++------------------------------------------
3 files changed, 21 insertions(+), 76 deletions(-)
diff -r 16c549b3ba59 -r 8fbf8e2fd087 drivers/pci/pci.h
--- a/drivers/pci/pci.h Tue Oct 14 14:58:08 2008 +0100
+++ b/drivers/pci/pci.h Fri Oct 17 12:01:56 2008 +0100
@@ -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 -r 8fbf8e2fd087 drivers/pci/quirks.c
--- a/drivers/pci/quirks.c Tue Oct 14 14:58:08 2008 +0100
+++ b/drivers/pci/quirks.c Fri Oct 17 12:01:56 2008 +0100
@@ -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 -r 8fbf8e2fd087 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 Fri Oct 17 12:01:56 2008 +0100
@@ -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, ®ion, 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, ®ion, 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-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|