diff options
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 46 |
1 files changed, 30 insertions, 16 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 505fbb670d6a..7325d43bf030 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -401,33 +401,40 @@ EXPORT_SYMBOL_GPL(pci_find_ht_capability); * @res: child resource record for which parent is sought * * For given resource region of given device, return the resource - * region of parent bus the given region is contained in or where - * it should be allocated from. + * region of parent bus the given region is contained in. */ struct resource * pci_find_parent_resource(const struct pci_dev *dev, struct resource *res) { const struct pci_bus *bus = dev->bus; + struct resource *r; int i; - struct resource *best = NULL, *r; pci_bus_for_each_resource(bus, r, i) { if (!r) continue; - if (res->start && !(res->start >= r->start && res->end <= r->end)) - continue; /* Not contained */ - if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM)) - continue; /* Wrong type */ - if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) - return r; /* Exact match */ - /* We can't insert a non-prefetch resource inside a prefetchable parent .. */ - if (r->flags & IORESOURCE_PREFETCH) - continue; - /* .. but we can put a prefetchable resource inside a non-prefetchable one */ - if (!best) - best = r; + if (res->start && resource_contains(r, res)) { + + /* + * If the window is prefetchable but the BAR is + * not, the allocator made a mistake. + */ + if (r->flags & IORESOURCE_PREFETCH && + !(res->flags & IORESOURCE_PREFETCH)) + return NULL; + + /* + * If we're below a transparent bridge, there may + * be both a positively-decoded aperture and a + * subtractively-decoded region that contain the BAR. + * We want the positively-decoded one, so this depends + * on pci_bus_for_each_resource() giving us those + * first. + */ + return r; + } } - return best; + return NULL; } /** @@ -1178,6 +1185,11 @@ int pci_load_and_free_saved_state(struct pci_dev *dev, } EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state); +int __weak pcibios_enable_device(struct pci_dev *dev, int bars) +{ + return pci_enable_resources(dev, bars); +} + static int do_pci_enable_device(struct pci_dev *dev, int bars) { int err; @@ -4262,6 +4274,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev) "Rounding up size of resource #%d to %#llx.\n", i, (unsigned long long)size); } + r->flags |= IORESOURCE_UNSET; r->end = size - 1; r->start = 0; } @@ -4275,6 +4288,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev) r = &dev->resource[i]; if (!(r->flags & IORESOURCE_MEM)) continue; + r->flags |= IORESOURCE_UNSET; r->end = resource_size(r) - 1; r->start = 0; } |