forked from Minki/linux
[PATCH] PCI: pci_assign_unassigned_resources() on x86
- Add sanity check for io[port,mem]_resource in setup-bus.c. These resources look like "free" as they have no parents, but obviously we must not touch them. - In i386.c:pci_allocate_bus_resources(), if a bridge resource cannot be allocated for some reason, then clear its flags. This prevents any child allocations in this range, so the setup-bus code will work with a clean resource sub-tree. - i386.c:pcibios_enable_resources() doesn't enable bridges, as it checks only resources 0-5, which looks like a clear bug to me. I suspect it might break hotplug as well in some cases. From: Ivan Kokshaysky <ink@jurassic.park.msu.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
90b54929b6
commit
299de0343c
@ -165,6 +165,7 @@ static int __init pcibios_init(void)
|
|||||||
if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
|
if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
|
||||||
pcibios_sort();
|
pcibios_sort();
|
||||||
#endif
|
#endif
|
||||||
|
pci_assign_unassigned_resources();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,11 +106,16 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
|
|||||||
if ((dev = bus->self)) {
|
if ((dev = bus->self)) {
|
||||||
for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
|
for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
|
||||||
r = &dev->resource[idx];
|
r = &dev->resource[idx];
|
||||||
if (!r->start)
|
if (!r->flags)
|
||||||
continue;
|
continue;
|
||||||
pr = pci_find_parent_resource(dev, r);
|
pr = pci_find_parent_resource(dev, r);
|
||||||
if (!pr || request_resource(pr, r) < 0)
|
if (!r->start || !pr || request_resource(pr, r) < 0) {
|
||||||
printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, pci_name(dev));
|
printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, pci_name(dev));
|
||||||
|
/* Something is wrong with the region.
|
||||||
|
Invalidate the resource to prevent child
|
||||||
|
resource allocations in this range. */
|
||||||
|
r->flags = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pcibios_allocate_bus_resources(&bus->children);
|
pcibios_allocate_bus_resources(&bus->children);
|
||||||
@ -227,7 +232,7 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask)
|
|||||||
|
|
||||||
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
||||||
old_cmd = cmd;
|
old_cmd = cmd;
|
||||||
for(idx=0; idx<6; idx++) {
|
for(idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
|
||||||
/* Only set up the requested stuff */
|
/* Only set up the requested stuff */
|
||||||
if (!(mask & (1<<idx)))
|
if (!(mask & (1<<idx)))
|
||||||
continue;
|
continue;
|
||||||
|
@ -273,6 +273,8 @@ find_free_bus_resource(struct pci_bus *bus, unsigned long type)
|
|||||||
|
|
||||||
for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
|
for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
|
||||||
r = bus->resource[i];
|
r = bus->resource[i];
|
||||||
|
if (r == &ioport_resource || r == &iomem_resource)
|
||||||
|
continue;
|
||||||
if (r && (r->flags & type_mask) == type && !r->parent)
|
if (r && (r->flags & type_mask) == type && !r->parent)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user