Merge branch 'topic/asoc' into for-linus
[safe/jmp/linux-2.6] / drivers / pci / setup-bus.c
index b19a56b..19b1113 100644 (file)
@@ -101,9 +101,17 @@ static void __assign_resources_sorted(struct resource_list *head,
        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;
@@ -354,8 +362,11 @@ static void pci_bridge_check_ranges(struct pci_bus *bus)
        }
        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 */
@@ -384,8 +395,7 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon
        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)
@@ -800,11 +810,10 @@ static void __ref pci_bus_release_bridge_resources(struct pci_bus *bus,
 
 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;
 
@@ -829,109 +838,70 @@ static void pci_bus_dump_resources(struct pci_bus *bus)
        }
 }
 
-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 */
@@ -949,27 +919,5 @@ again:
        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);