diff options
| -rw-r--r-- | drivers/pci/probe.c | 22 |
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, ®ion); | 268 | pcibios_bus_to_resource(dev, res, ®ion); |
| 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, ®ion.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 | ||
