Subject: [RFC PATCH] PCI: Set pref for mem64 resource of pcie device We still get "no compatible bridge window" warning on sparc T5-8 after we add support for 64bit resource for root bus. [ 286.647560] PCI: scan_bus[/pci@300/pci@1/pci@0/pci@6] bus no 8 [ 286.921232] PCI: Claiming 0000:00:01.0: Resource 15: 0000800100000000..00008004afffffff [220c] [ 287.229190] PCI: Claiming 0000:01:00.0: Resource 15: 0000800100000000..00008004afffffff [220c] [ 287.533428] PCI: Claiming 0000:02:04.0: Resource 15: 0000800100000000..000080012fffffff [220c] [ 288.149831] PCI: Claiming 0000:03:00.0: Resource 15: 0000800100000000..000080012fffffff [220c] [ 288.252466] PCI: Claiming 0000:04:06.0: Resource 14: 0000800100000000..000080010fffffff [220c] [ 288.867196] PCI: Claiming 0000:05:00.0: Resource 0: 0000800100000000..0000800100001fff [204] [ 288.968221] pci 0000:05:00.0: can't claim BAR 0 [mem 0x800100000000-0x800100001fff]: no compatible bridge window All the bridges have pref mem 64-bit resource, but the device resource does not have pref set, then we can not find parent for the device resource, as we can not put non-pref mem under pref mem. According to pcie spec errta https://www.pcisig.com/specifications/pciexpress/base2/PCIe_Base_r2.1_Errata_08Jun10.pdf page 13, in some case it is ok to mark some as pref. only set the bit when the mmio is above 4G by BIOS. Signed-off-by: Yinghai Lu --- drivers/pci/probe.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) Index: linux-2.6/drivers/pci/probe.c =================================================================== --- linux-2.6.orig/drivers/pci/probe.c +++ linux-2.6/drivers/pci/probe.c @@ -1508,6 +1508,43 @@ static void pci_init_capabilities(struct pci_enable_acs(dev); } +/* + * According to + * https://www.pcisig.com/specifications/pciexpress/base2/PCIe_Base_r2.1_Errata_08Jun10.pdf + * page 13, system firmware could put some 64bit non-pref under 64bit pref, + * on some cases. + * Let's set pref bit when pci bus address is above 4G. + */ +static void set_pcie_64bit_pref(struct pci_dev *dev) +{ + int i; + + if (!pci_is_pcie(dev)) + return; + + for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) { + struct resource *res = &dev->resource[i]; + struct pci_bus_region r; + enum pci_bar_type type; + int reg; + + if (!(res->flags & IORESOURCE_MEM_64)) + continue; + + if (res->flags & IORESOURCE_PREFETCH) + continue; + + pcibios_resource_to_bus(dev->bus, &r, res); + if (r.start < 0xffffffff) + continue; + + reg = pci_resource_bar(dev, i, &type); + dev_printk(KERN_DEBUG, &dev->dev, "reg %d %pR + pref\n", + reg, res); + res->flags |= IORESOURCE_PREFETCH; + } +} + void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) { int ret; @@ -1538,6 +1575,9 @@ void pci_device_add(struct pci_dev *dev, /* Initialize various capabilities */ pci_init_capabilities(dev); + /* After pcie_cap is assigned and sriov bar is probed */ + set_pcie_64bit_pref(dev); + /* * Add the device to our list of discovered devices * and the bus list for fixup functions, etc.