|
@@ -170,7 +170,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
|
|
{
|
|
|
u32 l, sz, mask;
|
|
|
u16 orig_cmd;
|
|
|
- struct pci_bus_region region;
|
|
|
+ struct pci_bus_region region, inverted_region;
|
|
|
bool bar_too_big = false, bar_disabled = false;
|
|
|
|
|
|
mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
|
|
@@ -266,6 +266,26 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
|
|
}
|
|
|
|
|
|
pcibios_bus_to_resource(dev, res, ®ion);
|
|
|
+ pcibios_resource_to_bus(dev, &inverted_region, res);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If "A" is a BAR value (a bus address), "bus_to_resource(A)" is
|
|
|
+ * the corresponding resource address (the physical address used by
|
|
|
+ * the CPU. Converting that resource address back to a bus address
|
|
|
+ * should yield the original BAR value:
|
|
|
+ *
|
|
|
+ * resource_to_bus(bus_to_resource(A)) == A
|
|
|
+ *
|
|
|
+ * If it doesn't, CPU accesses to "bus_to_resource(A)" will not
|
|
|
+ * be claimed by the device.
|
|
|
+ */
|
|
|
+ if (inverted_region.start != region.start) {
|
|
|
+ dev_info(&dev->dev, "reg 0x%x: initial BAR value %pa invalid; forcing reassignment\n",
|
|
|
+ pos, ®ion.start);
|
|
|
+ res->flags |= IORESOURCE_UNSET;
|
|
|
+ res->end -= res->start;
|
|
|
+ res->start = 0;
|
|
|
+ }
|
|
|
|
|
|
goto out;
|
|
|
|