aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/probe.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index cd7b6de9376c..fe5b50bd7536 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -170,7 +170,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
170{ 170{
171 u32 l, sz, mask; 171 u32 l, sz, mask;
172 u16 orig_cmd; 172 u16 orig_cmd;
173 struct pci_bus_region region; 173 struct pci_bus_region region, inverted_region;
174 bool bar_too_big = false, bar_disabled = false; 174 bool bar_too_big = false, bar_disabled = false;
175 175
176 mask = type ? PCI_ROM_ADDRESS_MASK : ~0; 176 mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
@@ -266,6 +266,26 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
266 } 266 }
267 267
268 pcibios_bus_to_resource(dev, res, &region); 268 pcibios_bus_to_resource(dev, res, &region);
269 pcibios_resource_to_bus(dev, &inverted_region, res);
270
271 /*
272 * If "A" is a BAR value (a bus address), "bus_to_resource(A)" is
273 * the corresponding resource address (the physical address used by
274 * the CPU. Converting that resource address back to a bus address
275 * should yield the original BAR value:
276 *
277 * resource_to_bus(bus_to_resource(A)) == A
278 *
279 * If it doesn't, CPU accesses to "bus_to_resource(A)" will not
280 * be claimed by the device.
281 */
282 if (inverted_region.start != region.start) {
283 dev_info(&dev->dev, "reg 0x%x: initial BAR value %pa invalid; forcing reassignment\n",
284 pos, &region.start);
285 res->flags |= IORESOURCE_UNSET;
286 res->end -= res->start;
287 res->start = 0;
288 }
269 289
270 goto out; 290 goto out;
271 291