Yuji Shimada
2008-Oct-17 00:14 UTC
[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@necst.nec.co.jp> 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, ®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-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel