aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/probe.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 70f10fa3c1b2..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;
@@ -250,12 +250,10 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
250 pci_write_config_dword(dev, pos + 4, 0); 250 pci_write_config_dword(dev, pos + 4, 0);
251 region.start = 0; 251 region.start = 0;
252 region.end = sz64; 252 region.end = sz64;
253 pcibios_bus_to_resource(dev, res, &region);
254 bar_disabled = true; 253 bar_disabled = true;
255 } else { 254 } else {
256 region.start = l64; 255 region.start = l64;
257 region.end = l64 + sz64; 256 region.end = l64 + sz64;
258 pcibios_bus_to_resource(dev, res, &region);
259 } 257 }
260 } else { 258 } else {
261 sz = pci_size(l, sz, mask); 259 sz = pci_size(l, sz, mask);
@@ -265,7 +263,28 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
265 263
266 region.start = l; 264 region.start = l;
267 region.end = l + sz; 265 region.end = l + sz;
268 pcibios_bus_to_resource(dev, res, &region); 266 }
267
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;
269 } 288 }
270 289
271 goto out; 290 goto out;
@@ -278,9 +297,9 @@ out:
278 pci_write_config_word(dev, PCI_COMMAND, orig_cmd); 297 pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
279 298
280 if (bar_too_big) 299 if (bar_too_big)
281 dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos); 300 dev_err(&dev->dev, "reg 0x%x: can't handle 64-bit BAR\n", pos);
282 if (res->flags && !bar_disabled) 301 if (res->flags && !bar_disabled)
283 dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res); 302 dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res);
284 303
285 return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; 304 return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
286} 305}