powerpc/pci: Change how re-assigning resouces work

When PCI_REASSIGN_ALL_RSRC is set, we used to clear all bus resources
at the beginning of survey and re-allocate them later.

This changes it so instead, during early fixup, we mark all resources
as IORESOURCE_UNSET and move them down to be 0-based.

Later, if bus resources are still unset at the beginning of the survey,
then we clear them.

This shouldn't impact the re-assignment case on 4xx, but will enable
us to have the platform do some custom resource assignment before the
survey, by clearing individual resources IORESOURCE_UNSET bit.

Also limits the clutter in the kernel log from fixup when re-assigning
since we don't care about the offset applied to the BAR values in this
case.
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 491b98c3
...@@ -921,18 +921,22 @@ static void __devinit pcibios_fixup_resources(struct pci_dev *dev) ...@@ -921,18 +921,22 @@ static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
struct resource *res = dev->resource + i; struct resource *res = dev->resource + i;
if (!res->flags) if (!res->flags)
continue; continue;
/* On platforms that have PCI_PROBE_ONLY set, we don't
* consider 0 as an unassigned BAR value. It's technically /* If we're going to re-assign everything, we mark all resources
* a valid value, but linux doesn't like it... so when we can * as unset (and 0-base them). In addition, we mark BARs starting
* re-assign things, we do so, but if we can't, we keep it * at 0 as unset as well, except if PCI_PROBE_ONLY is also set
* around and hope for the best... * since in that case, we don't want to re-assign anything
*/ */
if (res->start == 0 && !pci_has_flag(PCI_PROBE_ONLY)) { if (pci_has_flag(PCI_REASSIGN_ALL_RSRC) ||
pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] is unassigned\n", (res->start == 0 && !pci_has_flag(PCI_PROBE_ONLY))) {
pci_name(dev), i, /* Only print message if not re-assigning */
(unsigned long long)res->start, if (!pci_has_flag(PCI_REASSIGN_ALL_RSRC))
(unsigned long long)res->end, pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] "
(unsigned int)res->flags); "is unassigned\n",
pci_name(dev), i,
(unsigned long long)res->start,
(unsigned long long)res->end,
(unsigned int)res->flags);
res->end -= res->start; res->end -= res->start;
res->start = 0; res->start = 0;
res->flags |= IORESOURCE_UNSET; res->flags |= IORESOURCE_UNSET;
...@@ -1042,6 +1046,16 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus) ...@@ -1042,6 +1046,16 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus)
if (i >= 3 && bus->self->transparent) if (i >= 3 && bus->self->transparent)
continue; continue;
/* If we are going to re-assign everything, mark the resource
* as unset and move it down to 0
*/
if (pci_has_flag(PCI_REASSIGN_ALL_RSRC)) {
res->flags |= IORESOURCE_UNSET;
res->end -= res->start;
res->start = 0;
continue;
}
pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x] fixup...\n", pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x] fixup...\n",
pci_name(dev), i, pci_name(dev), i,
(unsigned long long)res->start,\ (unsigned long long)res->start,\
...@@ -1262,18 +1276,15 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus) ...@@ -1262,18 +1276,15 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
pci_bus_for_each_resource(bus, res, i) { pci_bus_for_each_resource(bus, res, i) {
if (!res || !res->flags || res->start > res->end || res->parent) if (!res || !res->flags || res->start > res->end || res->parent)
continue; continue;
/* If the resource was left unset at this point, we clear it */
if (res->flags & IORESOURCE_UNSET)
goto clear_resource;
if (bus->parent == NULL) if (bus->parent == NULL)
pr = (res->flags & IORESOURCE_IO) ? pr = (res->flags & IORESOURCE_IO) ?
&ioport_resource : &iomem_resource; &ioport_resource : &iomem_resource;
else { else {
/* Don't bother with non-root busses when
* re-assigning all resources. We clear the
* resource flags as if they were colliding
* and as such ensure proper re-allocation
* later.
*/
if (pci_has_flag(PCI_REASSIGN_ALL_RSRC))
goto clear_resource;
pr = pci_find_parent_resource(bus->self, res); pr = pci_find_parent_resource(bus->self, res);
if (pr == res) { if (pr == res) {
/* this happens when the generic PCI /* this happens when the generic PCI
...@@ -1304,9 +1315,9 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus) ...@@ -1304,9 +1315,9 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
if (reparent_resources(pr, res) == 0) if (reparent_resources(pr, res) == 0)
continue; continue;
} }
printk(KERN_WARNING "PCI: Cannot allocate resource region " pr_warning("PCI: Cannot allocate resource region "
"%d of PCI bridge %d, will remap\n", i, bus->number); "%d of PCI bridge %d, will remap\n", i, bus->number);
clear_resource: clear_resource:
res->start = res->end = 0; res->start = res->end = 0;
res->flags = 0; res->flags = 0;
} }
...@@ -1451,16 +1462,11 @@ void __init pcibios_resource_survey(void) ...@@ -1451,16 +1462,11 @@ void __init pcibios_resource_survey(void)
{ {
struct pci_bus *b; struct pci_bus *b;
/* Allocate and assign resources. If we re-assign everything, then /* Allocate and assign resources */
* we skip the allocate phase
*/
list_for_each_entry(b, &pci_root_buses, node) list_for_each_entry(b, &pci_root_buses, node)
pcibios_allocate_bus_resources(b); pcibios_allocate_bus_resources(b);
pcibios_allocate_resources(0);
if (!pci_has_flag(PCI_REASSIGN_ALL_RSRC)) { pcibios_allocate_resources(1);
pcibios_allocate_resources(0);
pcibios_allocate_resources(1);
}
/* Before we start assigning unassigned resource, we try to reserve /* Before we start assigning unassigned resource, we try to reserve
* the low IO area and the VGA memory area if they intersect the * the low IO area and the VGA memory area if they intersect the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment