aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/bus.c')
-rw-r--r--drivers/pci/bus.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 73aef51a28f0..8fb16188cd82 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,
228} 228}
229EXPORT_SYMBOL(pci_bus_alloc_resource); 229EXPORT_SYMBOL(pci_bus_alloc_resource);
230 230
231/*
232 * The @idx resource of @dev should be a PCI-PCI bridge window. If this
233 * resource fits inside a window of an upstream bridge, do nothing. If it
234 * overlaps an upstream window but extends outside it, clip the resource so
235 * it fits completely inside.
236 */
237bool pci_bus_clip_resource(struct pci_dev *dev, int idx)
238{
239 struct pci_bus *bus = dev->bus;
240 struct resource *res = &dev->resource[idx];
241 struct resource orig_res = *res;
242 struct resource *r;
243 int i;
244
245 pci_bus_for_each_resource(bus, r, i) {
246 resource_size_t start, end;
247
248 if (!r)
249 continue;
250
251 if (resource_type(res) != resource_type(r))
252 continue;
253
254 start = max(r->start, res->start);
255 end = min(r->end, res->end);
256
257 if (start > end)
258 continue; /* no overlap */
259
260 if (res->start == start && res->end == end)
261 return false; /* no change */
262
263 res->start = start;
264 res->end = end;
265 dev_printk(KERN_DEBUG, &dev->dev, "%pR clipped to %pR\n",
266 &orig_res, res);
267
268 return true;
269 }
270
271 return false;
272}
273
231void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { } 274void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
232 275
233/** 276/**