for (list = head->next; list;) {
res = list->res;
idx = res - &list->dev->resource[0];
+
if (pci_assign_resource(list->dev, idx)) {
- if (fail_head && !pci_is_root_bus(list->dev->bus))
- add_to_failed_list(fail_head, list->dev, res);
+ if (fail_head && !pci_is_root_bus(list->dev->bus)) {
+ /*
+ * if the failed res is for ROM BAR, and it will
+ * be enabled later, don't add it to the list
+ */
+ if (!((idx == PCI_ROM_RESOURCE) &&
+ (!(res->flags & IORESOURCE_ROM_ENABLE))))
+ add_to_failed_list(fail_head, list->dev, res);
+ }
res->start = 0;
res->end = 0;
res->flags = 0;
}
if (pmem) {
b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
- if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64)
+ if ((pmem & PCI_PREF_RANGE_TYPE_MASK) ==
+ PCI_PREF_RANGE_TYPE_64) {
b_res[2].flags |= IORESOURCE_MEM_64;
+ b_res[2].flags |= PCI_PREF_RANGE_TYPE_64;
+ }
}
/* double check if bridge does support 64 bit pref */
unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
IORESOURCE_PREFETCH;
- for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
- r = bus->resource[i];
+ pci_bus_for_each_resource(bus, r, i) {
if (r == &ioport_resource || r == &iomem_resource)
continue;
if (r && (r->flags & type_mask) == type && !r->parent)
static void pci_bus_dump_res(struct pci_bus *bus)
{
- int i;
-
- for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
- struct resource *res = bus->resource[i];
+ struct resource *res;
+ int i;
+ pci_bus_for_each_resource(bus, res, i) {
if (!res || !res->end || !res->flags)
continue;
}
}
-static int __init pci_bus_get_depth(struct pci_bus *bus)
-{
- int depth = 0;
- struct pci_dev *dev;
-
- list_for_each_entry(dev, &bus->devices, bus_list) {
- int ret;
- struct pci_bus *b = dev->subordinate;
- if (!b)
- continue;
-
- ret = pci_bus_get_depth(b);
- if (ret + 1 > depth)
- depth = ret + 1;
- }
-
- return depth;
-}
-static int __init pci_get_max_depth(void)
+void __init
+pci_assign_unassigned_resources(void)
{
- int depth = 0;
struct pci_bus *bus;
+ /* Depth first, calculate sizes and alignments of all
+ subordinate buses. */
list_for_each_entry(bus, &pci_root_buses, node) {
- int ret;
-
- ret = pci_bus_get_depth(bus);
- if (ret > depth)
- depth = ret;
+ pci_bus_size_bridges(bus);
+ }
+ /* Depth last, allocate resources and update the hardware. */
+ list_for_each_entry(bus, &pci_root_buses, node) {
+ pci_bus_assign_resources(bus);
+ pci_enable_bridges(bus);
}
- return depth;
+ /* dump the resource on buses */
+ list_for_each_entry(bus, &pci_root_buses, node) {
+ pci_bus_dump_resources(bus);
+ }
}
-/*
- * first try will not touch pci bridge res
- * second and later try will clear small leaf bridge res
- * will stop till to the max deepth if can not find good one
- */
-void __init
-pci_assign_unassigned_resources(void)
+void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
{
- struct pci_bus *bus;
+ struct pci_bus *parent = bridge->subordinate;
int tried_times = 0;
- enum release_type rel_type = leaf_only;
struct resource_list_x head, *list;
+ int retval;
unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
IORESOURCE_PREFETCH;
- unsigned long failed_type;
- int max_depth = pci_get_max_depth();
- int pci_try_num;
head.next = NULL;
- pci_try_num = max_depth + 1;
- printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n",
- max_depth, pci_try_num);
-
again:
- /* Depth first, calculate sizes and alignments of all
- subordinate buses. */
- list_for_each_entry(bus, &pci_root_buses, node) {
- pci_bus_size_bridges(bus);
- }
- /* Depth last, allocate resources and update the hardware. */
- list_for_each_entry(bus, &pci_root_buses, node) {
- __pci_bus_assign_resources(bus, &head);
- }
+ pci_bus_size_bridges(parent);
+ __pci_bridge_assign_resources(bridge, &head);
+ retval = pci_reenable_device(bridge);
+ pci_set_master(bridge);
+ pci_enable_bridges(parent);
+
tried_times++;
- /* any device complain? */
if (!head.next)
- goto enable_and_dump;
- failed_type = 0;
- for (list = head.next; list;) {
- failed_type |= list->flags;
- list = list->next;
- }
- /*
- * io port are tight, don't try extra
- * or if reach the limit, don't want to try more
- */
- failed_type &= type_mask;
- if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) {
+ return;
+
+ if (tried_times >= 2) {
+ /* still fail, don't need to try more */
free_failed_list(&head);
- goto enable_and_dump;
+ return;
}
printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n",
tried_times + 1);
- /* third times and later will not check if it is leaf */
- if ((tried_times + 1) > 2)
- rel_type = whole_subtree;
-
/*
* Try to release leaf bridge's resources that doesn't fit resource of
* child device under that bridge
*/
for (list = head.next; list;) {
- bus = list->dev->bus;
- pci_bus_release_bridge_resources(bus, list->flags & type_mask,
- rel_type);
+ struct pci_bus *bus = list->dev->bus;
+ unsigned long flags = list->flags;
+
+ pci_bus_release_bridge_resources(bus, flags & type_mask,
+ whole_subtree);
list = list->next;
}
/* restore size and flags */
free_failed_list(&head);
goto again;
-
-enable_and_dump:
- /* Depth last, update the hardware. */
- list_for_each_entry(bus, &pci_root_buses, node)
- pci_enable_bridges(bus);
-
- /* dump the resource on buses */
- list_for_each_entry(bus, &pci_root_buses, node) {
- pci_bus_dump_resources(bus);
- }
-}
-
-void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
-{
- struct pci_bus *parent = bridge->subordinate;
- int retval;
-
- pci_bus_size_bridges(parent);
- __pci_bridge_assign_resources(bridge, NULL);
- retval = pci_reenable_device(bridge);
- pci_set_master(bridge);
- pci_enable_bridges(parent);
}
EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);