]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/pci/setup-bus.c
PCI: Rename variables
[linux.git] / drivers / pci / setup-bus.c
index e7dbe21705ba5b0f9c906287656bd2c03f4ece5d..9d167d5b22352bdd926a4451bae1b1017b9ca1b8 100644 (file)
@@ -752,24 +752,32 @@ static void pci_bridge_check_ranges(struct pci_bus *bus)
 }
 
 /*
- * Helper function for sizing routines: find first available bus resource
- * of a given type.  Note: we intentionally skip the bus resources which
- * have already been assigned (that is, have non-NULL parent resource).
+ * Helper function for sizing routines.  Assigned resources have non-NULL
+ * parent resource.
+ *
+ * Return first unassigned resource of the correct type.  If there is none,
+ * return first assigned resource of the correct type.  If none of the
+ * above, return NULL.
+ *
+ * Returning an assigned resource of the correct type allows the caller to
+ * distinguish between already assigned and no resource of the correct type.
  */
-static struct resource *find_free_bus_resource(struct pci_bus *bus,
-                                              unsigned long type_mask,
-                                              unsigned long type)
+static struct resource *find_bus_resource_of_type(struct pci_bus *bus,
+                                                 unsigned long type_mask,
+                                                 unsigned long type)
 {
+       struct resource *r, *r_assigned = NULL;
        int i;
-       struct resource *r;
 
        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)
                        return r;
+               if (r && (r->flags & type_mask) == type && !r_assigned)
+                       r_assigned = r;
        }
-       return NULL;
+       return r_assigned;
 }
 
 static resource_size_t calculate_iosize(resource_size_t size,
@@ -866,8 +874,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
                         struct list_head *realloc_head)
 {
        struct pci_dev *dev;
-       struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO,
-                                                       IORESOURCE_IO);
+       struct resource *b_res = find_bus_resource_of_type(bus, IORESOURCE_IO,
+                                                          IORESOURCE_IO);
        resource_size_t size = 0, size0 = 0, size1 = 0;
        resource_size_t children_add_size = 0;
        resource_size_t min_align, align;
@@ -875,6 +883,10 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
        if (!b_res)
                return;
 
+       /* If resource is already assigned, nothing more to do */
+       if (b_res->parent)
+               return;
+
        min_align = window_alignment(bus, IORESOURCE_IO);
        list_for_each_entry(dev, &bus->devices, bus_list) {
                int i;
@@ -978,7 +990,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
        resource_size_t min_align, align, size, size0, size1;
        resource_size_t aligns[18]; /* Alignments from 1MB to 128GB */
        int order, max_order;
-       struct resource *b_res = find_free_bus_resource(bus,
+       struct resource *b_res = find_bus_resource_of_type(bus,
                                        mask | IORESOURCE_PREFETCH, type);
        resource_size_t children_add_size = 0;
        resource_size_t children_add_align = 0;
@@ -987,6 +999,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
        if (!b_res)
                return -ENOSPC;
 
+       /* If resource is already assigned, nothing more to do */
+       if (b_res->parent)
+               return 0;
+
        memset(aligns, 0, sizeof(aligns));
        max_order = 0;
        size = 0;
@@ -1178,7 +1194,8 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
 {
        struct pci_dev *dev;
        unsigned long mask, prefmask, type2 = 0, type3 = 0;
-       resource_size_t additional_mem_size = 0, additional_io_size = 0;
+       resource_size_t additional_io_size = 0, additional_mmio_size = 0,
+                       additional_mmio_pref_size = 0;
        struct resource *b_res;
        int ret;
 
@@ -1212,7 +1229,8 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
                pci_bridge_check_ranges(bus);
                if (bus->self->is_hotplug_bridge) {
                        additional_io_size  = pci_hotplug_io_size;
-                       additional_mem_size = pci_hotplug_mem_size;
+                       additional_mmio_size = pci_hotplug_mmio_size;
+                       additional_mmio_pref_size = pci_hotplug_mmio_pref_size;
                }
                /* Fall through */
        default:
@@ -1230,9 +1248,9 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
                if (b_res[2].flags & IORESOURCE_MEM_64) {
                        prefmask |= IORESOURCE_MEM_64;
                        ret = pbus_size_mem(bus, prefmask, prefmask,
-                                 prefmask, prefmask,
-                                 realloc_head ? 0 : additional_mem_size,
-                                 additional_mem_size, realloc_head);
+                               prefmask, prefmask,
+                               realloc_head ? 0 : additional_mmio_pref_size,
+                               additional_mmio_pref_size, realloc_head);
 
                        /*
                         * If successful, all non-prefetchable resources
@@ -1254,9 +1272,9 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
                if (!type2) {
                        prefmask &= ~IORESOURCE_MEM_64;
                        ret = pbus_size_mem(bus, prefmask, prefmask,
-                                        prefmask, prefmask,
-                                        realloc_head ? 0 : additional_mem_size,
-                                        additional_mem_size, realloc_head);
+                               prefmask, prefmask,
+                               realloc_head ? 0 : additional_mmio_pref_size,
+                               additional_mmio_pref_size, realloc_head);
 
                        /*
                         * If successful, only non-prefetchable resources
@@ -1265,7 +1283,7 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
                        if (ret == 0)
                                mask = prefmask;
                        else
-                               additional_mem_size += additional_mem_size;
+                               additional_mmio_size += additional_mmio_pref_size;
 
                        type2 = type3 = IORESOURCE_MEM;
                }
@@ -1285,8 +1303,8 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
                 * prefetchable resource in a 64-bit prefetchable window.
                 */
                pbus_size_mem(bus, mask, IORESOURCE_MEM, type2, type3,
-                               realloc_head ? 0 : additional_mem_size,
-                               additional_mem_size, realloc_head);
+                             realloc_head ? 0 : additional_mmio_size,
+                             additional_mmio_size, realloc_head);
                break;
        }
 }
@@ -1785,12 +1803,18 @@ void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
        /* Restore size and flags */
        list_for_each_entry(fail_res, &fail_head, list) {
                struct resource *res = fail_res->res;
+               int idx;
 
                res->start = fail_res->start;
                res->end = fail_res->end;
                res->flags = fail_res->flags;
-               if (fail_res->dev->subordinate)
-                       res->flags = 0;
+
+               if (pci_is_bridge(fail_res->dev)) {
+                       idx = res - &fail_res->dev->resource[0];
+                       if (idx >= PCI_BRIDGE_RESOURCES &&
+                           idx <= PCI_BRIDGE_RESOURCE_END)
+                               res->flags = 0;
+               }
        }
        free_list(&fail_head);
 
@@ -1849,6 +1873,7 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
        unsigned int normal_bridges = 0, hotplug_bridges = 0;
        struct resource *io_res, *mmio_res, *mmio_pref_res;
        struct pci_dev *dev, *bridge = bus->self;
+       resource_size_t io_per_hp, mmio_per_hp, mmio_pref_per_hp;
 
        io_res = &bridge->resource[PCI_BRIDGE_RESOURCES + 0];
        mmio_res = &bridge->resource[PCI_BRIDGE_RESOURCES + 1];
@@ -1884,11 +1909,10 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
         */
        if (hotplug_bridges + normal_bridges == 1) {
                dev = list_first_entry(&bus->devices, struct pci_dev, bus_list);
-               if (dev->subordinate) {
+               if (dev->subordinate)
                        pci_bus_distribute_available_resources(dev->subordinate,
                                add_list, available_io, available_mmio,
                                available_mmio_pref);
-               }
                return;
        }
 
@@ -1933,7 +1957,7 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
         * resource space between hotplug bridges.
         */
        for_each_pci_bridge(dev, bus) {
-               resource_size_t align, io, mmio, mmio_pref;
+               resource_size_t align;
                struct pci_bus *b;
 
                b = dev->subordinate;
@@ -1946,22 +1970,25 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
                 * account.
                 */
                align = pci_resource_alignment(bridge, io_res);
-               io = div64_ul(available_io, hotplug_bridges);
-               io = min(ALIGN(io, align), remaining_io);
-               remaining_io -= io;
+               io_per_hp = div64_ul(available_io, hotplug_bridges);
+               io_per_hp = min(ALIGN(io_per_hp, align), remaining_io);
+               remaining_io -= io_per_hp;
 
                align = pci_resource_alignment(bridge, mmio_res);
-               mmio = div64_ul(available_mmio, hotplug_bridges);
-               mmio = min(ALIGN(mmio, align), remaining_mmio);
-               remaining_mmio -= mmio;
+               mmio_per_hp = div64_ul(available_mmio, hotplug_bridges);
+               mmio_per_hp = min(ALIGN(mmio_per_hp, align), remaining_mmio);
+               remaining_mmio -= mmio_per_hp;
 
                align = pci_resource_alignment(bridge, mmio_pref_res);
-               mmio_pref = div64_ul(available_mmio_pref, hotplug_bridges);
-               mmio_pref = min(ALIGN(mmio_pref, align), remaining_mmio_pref);
-               remaining_mmio_pref -= mmio_pref;
+               mmio_pref_per_hp = div64_ul(available_mmio_pref,
+                                           hotplug_bridges);
+               mmio_pref_per_hp = min(ALIGN(mmio_pref_per_hp, align),
+                                      remaining_mmio_pref);
+               remaining_mmio_pref -= mmio_pref_per_hp;
 
-               pci_bus_distribute_available_resources(b, add_list, io, mmio,
-                                                      mmio_pref);
+               pci_bus_distribute_available_resources(b, add_list, io_per_hp,
+                                                      mmio_per_hp,
+                                                      mmio_pref_per_hp);
        }
 }
 
@@ -2037,12 +2064,18 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
        /* Restore size and flags */
        list_for_each_entry(fail_res, &fail_head, list) {
                struct resource *res = fail_res->res;
+               int idx;
 
                res->start = fail_res->start;
                res->end = fail_res->end;
                res->flags = fail_res->flags;
-               if (fail_res->dev->subordinate)
-                       res->flags = 0;
+
+               if (pci_is_bridge(fail_res->dev)) {
+                       idx = res - &fail_res->dev->resource[0];
+                       if (idx >= PCI_BRIDGE_RESOURCES &&
+                           idx <= PCI_BRIDGE_RESOURCE_END)
+                               res->flags = 0;
+               }
        }
        free_list(&fail_head);
 
@@ -2066,6 +2099,8 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
        unsigned int i;
        int ret;
 
+       down_read(&pci_bus_sem);
+
        /* Walk to the root hub, releasing bridge BARs when possible */
        next = bridge;
        do {
@@ -2100,8 +2135,10 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
                next = bridge->bus ? bridge->bus->self : NULL;
        } while (next);
 
-       if (list_empty(&saved))
+       if (list_empty(&saved)) {
+               up_read(&pci_bus_sem);
                return -ENOENT;
+       }
 
        __pci_bus_size_bridges(bridge->subordinate, &added);
        __pci_bridge_assign_resources(bridge, &added, &failed);
@@ -2122,6 +2159,7 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
        }
 
        free_list(&saved);
+       up_read(&pci_bus_sem);
        return 0;
 
 cleanup:
@@ -2150,6 +2188,7 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
                pci_setup_bridge(bridge->subordinate);
        }
        free_list(&saved);
+       up_read(&pci_bus_sem);
 
        return ret;
 }