{
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;
pci_write_config_dword(dev, pos + 4, 0);
region.start = 0;
region.end = sz64;
- pcibios_bus_to_resource(dev, res, ®ion);
bar_disabled = true;
} else {
region.start = l64;
region.end = l64 + sz64;
- pcibios_bus_to_resource(dev, res, ®ion);
}
} else {
sz = pci_size(l, sz, mask);
region.start = l;
region.end = l + sz;
- pcibios_bus_to_resource(dev, res, ®ion);
+ }
+
+ 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;
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
if (bar_too_big)
- dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos);
+ dev_err(&dev->dev, "reg 0x%x: can't handle 64-bit BAR\n", pos);
if (res->flags && !bar_disabled)
- dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
+ dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res);
return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
}
}
}
-static struct pci_bus * pci_alloc_bus(void)
+static struct pci_bus *pci_alloc_bus(void)
{
struct pci_bus *b;
b = kzalloc(sizeof(*b), GFP_KERNEL);
- if (b) {
- INIT_LIST_HEAD(&b->node);
- INIT_LIST_HEAD(&b->children);
- INIT_LIST_HEAD(&b->devices);
- INIT_LIST_HEAD(&b->slots);
- INIT_LIST_HEAD(&b->resources);
- b->max_bus_speed = PCI_SPEED_UNKNOWN;
- b->cur_bus_speed = PCI_SPEED_UNKNOWN;
- }
+ if (!b)
+ return NULL;
+
+ INIT_LIST_HEAD(&b->node);
+ INIT_LIST_HEAD(&b->children);
+ INIT_LIST_HEAD(&b->devices);
+ INIT_LIST_HEAD(&b->slots);
+ INIT_LIST_HEAD(&b->resources);
+ b->max_bus_speed = PCI_SPEED_UNKNOWN;
+ b->cur_bus_speed = PCI_SPEED_UNKNOWN;
return b;
}
struct pci_host_bridge *bridge;
bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
- if (bridge) {
- INIT_LIST_HEAD(&bridge->windows);
- bridge->bus = b;
- }
+ if (!bridge)
+ return NULL;
+ INIT_LIST_HEAD(&bridge->windows);
+ bridge->bus = b;
return bridge;
}
pci_dev = to_pci_dev(dev);
pci_release_capabilities(pci_dev);
pci_release_of_node(pci_dev);
+ pcibios_release_device(pci_dev);
pci_bus_put(pci_dev->bus);
kfree(pci_dev);
}