@@ -269,6 +269,10 @@ static void pci_static_enum_set_bridge_memory(struct pci_dev *dev, struct pci_st
*setting)
{
u16 mem_base_lo, mem_limit_lo;
+ struct pci_dev *parent;
+ struct resource *res;
+ u16 parent_base_lo, parent_limit_lo;
+ unsigned long base, limit;
dev_info(&dev->dev, "Overriding memory base and limit to %pa-%pa\n",
&setting->bridgemem_start, &setting->bridgemem_end);
@@ -276,6 +280,39 @@ static void pci_static_enum_set_bridge_memory(struct pci_dev *dev, struct pci_st
mem_limit_lo = (setting->bridgemem_end >> 16) & ~0xf;
pci_write_config_word(dev, PCI_MEMORY_BASE, mem_base_lo);
pci_write_config_word(dev, PCI_MEMORY_LIMIT, mem_limit_lo);
+
+ /* update all upstream bridges' memory to encompass this
+ bridge memory */
+ parent = pci_upstream_bridge(dev);
+ while (parent) {
+ res = parent->bus->resource[1];
+ pci_read_config_word(parent, PCI_MEMORY_BASE, &parent_base_lo);
+ pci_read_config_word(parent, PCI_MEMORY_LIMIT,
+ &parent_limit_lo);
+ base =
+ ((unsigned long)parent_base_lo & PCI_MEMORY_RANGE_MASK) <<
+ 16;
+ limit =
+ (((unsigned long)parent_limit_lo & PCI_MEMORY_RANGE_MASK) <<
+ 16) | 0xfffff;
+ if (base > setting->bridgemem_start) {
+ dev_info(&parent->dev, "Updating memory base to %pa\n",
+ &setting->bridgemem_start);
+ if (res)
+ res->start = setting->bridgemem_start;
+ pci_write_config_word(parent, PCI_MEMORY_BASE,
+ mem_base_lo);
+ }
+ if (limit < setting->bridgemem_end) {
+ dev_info(&parent->dev, "Updating memory limit to %pa\n",
+ &setting->bridgemem_end);
+ if (res)
+ res->end = setting->bridgemem_end;
+ pci_write_config_word(parent, PCI_MEMORY_LIMIT,
+ mem_limit_lo);
+ }
+ parent = pci_upstream_bridge(parent);
+ }
}
/**
After overriding the memory behind a bridge, update all upstream bridges so that their memory bases and limits encompass the overridden values. Signed-off-by: Jason Tang <jason.tang2@ngc.com> --- drivers/pci/pci_static_enum.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)