diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-20 11:54:53 -0800 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-20 11:54:53 -0800 |
commit | 4c971aa78314253cce914ed29e3d90df3326d646 (patch) | |
tree | a9dcf0b1fdc9e1aacff90afb5b3ab79983115dcc /drivers/pci/bus.c | |
parent | 4ba24fef3eb3b142197135223b90ced2f319cd53 (diff) | |
parent | 290b799c390d77d27effee3ce312203aaa32ee74 (diff) |
Merge branch 'next' into for-linus
Second round of updates for 3.20.
Diffstat (limited to 'drivers/pci/bus.c')
-rw-r--r-- | drivers/pci/bus.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 73aef51a28f..8fb16188cd8 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -228,6 +228,49 @@ int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, } EXPORT_SYMBOL(pci_bus_alloc_resource); +/* + * The @idx resource of @dev should be a PCI-PCI bridge window. If this + * resource fits inside a window of an upstream bridge, do nothing. If it + * overlaps an upstream window but extends outside it, clip the resource so + * it fits completely inside. + */ +bool pci_bus_clip_resource(struct pci_dev *dev, int idx) +{ + struct pci_bus *bus = dev->bus; + struct resource *res = &dev->resource[idx]; + struct resource orig_res = *res; + struct resource *r; + int i; + + pci_bus_for_each_resource(bus, r, i) { + resource_size_t start, end; + + if (!r) + continue; + + if (resource_type(res) != resource_type(r)) + continue; + + start = max(r->start, res->start); + end = min(r->end, res->end); + + if (start > end) + continue; /* no overlap */ + + if (res->start == start && res->end == end) + return false; /* no change */ + + res->start = start; + res->end = end; + dev_printk(KERN_DEBUG, &dev->dev, "%pR clipped to %pR\n", + &orig_res, res); + + return true; + } + + return false; +} + void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { } /** |