+ bridge->flags |= IORESOURCE_ASSIGNED;
+
+ printk(BIOS_SPEW, "%s %s_%s: next_base: %llx size: %llx align: %d "
+ "gran: %d done\n", dev_path(bus->dev), __func__,
+ (type & IORESOURCE_IO) ? "io" : (type & IORESOURCE_PREFETCH) ?
+ "prefmem" : "mem", base, bridge->size, bridge->align,
+ bridge->gran);
+
+ /* For each child which is a bridge, allocate_resources. */
+ for (dev = bus->children; dev; dev = dev->sibling) {
+ struct resource *child_bridge;
+
+ if (!dev->link_list)
+ continue;
+
+ /* Find the resources with matching type flags. */
+ for (child_bridge = dev->resource_list; child_bridge;
+ child_bridge = child_bridge->next) {
+ struct bus* link;
+
+ if (!(child_bridge->flags & IORESOURCE_BRIDGE) ||
+ (child_bridge->flags & type_mask) != type)
+ continue;
+
+ /*
+ * Split prefetchable memory if combined. Many domains
+ * use the same address space for prefetchable memory
+ * and non-prefetchable memory. Bridges below them need
+ * it separated. Add the PREFETCH flag to the type_mask
+ * and type.
+ */
+ link = dev->link_list;
+ while (link && link->link_num !=
+ IOINDEX_LINK(child_bridge->index))
+ link = link->next;
+ if (link == NULL)
+ printk(BIOS_ERR, "link %ld not found on %s\n",
+ IOINDEX_LINK(child_bridge->index),
+ dev_path(dev));
+
+ allocate_resources(link, child_bridge,
+ type_mask | IORESOURCE_PREFETCH,
+ type | (child_bridge->flags &
+ IORESOURCE_PREFETCH));
+ }
+ }
+}
+
+#if CONFIG_PCI_64BIT_PREF_MEM == 1
+#define MEM_MASK (IORESOURCE_PREFETCH | IORESOURCE_MEM)
+#else
+#define MEM_MASK (IORESOURCE_MEM)
+#endif
+
+#define IO_MASK (IORESOURCE_IO)
+#define PREF_TYPE (IORESOURCE_PREFETCH | IORESOURCE_MEM)
+#define MEM_TYPE (IORESOURCE_MEM)
+#define IO_TYPE (IORESOURCE_IO)
+
+struct constraints {
+ struct resource pref, io, mem;
+};
+
+static void constrain_resources(struct device *dev, struct constraints* limits)
+{
+ struct device *child;
+ struct resource *res;
+ struct resource *lim;
+ struct bus *link;
+
+ printk(BIOS_SPEW, "%s: %s\n", __func__, dev_path(dev));
+
+ /* Constrain limits based on the fixed resources of this device. */
+ for (res = dev->resource_list; res; res = res->next) {
+ if (!(res->flags & IORESOURCE_FIXED))
+ continue;
+ if (!res->size) {
+ /* It makes no sense to have 0-sized, fixed resources.*/
+ printk(BIOS_ERR, "skipping %s@%lx fixed resource, "
+ "size=0!\n", dev_path(dev), res->index);
+ continue;
+ }
+
+ /* PREFETCH, MEM, or I/O - skip any others. */
+ if ((res->flags & MEM_MASK) == PREF_TYPE)
+ lim = &limits->pref;
+ else if ((res->flags & MEM_MASK) == MEM_TYPE)
+ lim = &limits->mem;
+ else if ((res->flags & IO_MASK) == IO_TYPE)
+ lim = &limits->io;
+ else
+ continue;
+
+ /*
+ * Is it a fixed resource outside the current known region?
+ * If so, we don't have to consider it - it will be handled
+ * correctly and doesn't affect current region's limits.
+ */
+ if (((res->base + res->size -1) < lim->base)
+ || (res->base > lim->limit))
+ continue;
+
+ /*
+ * Choose to be above or below fixed resources. This check is
+ * signed so that "negative" amounts of space are handled
+ * correctly.
+ */
+ if ((signed long long)(lim->limit - (res->base + res->size -1))
+ > (signed long long)(res->base - lim->base))
+ lim->base = res->base + res->size;
+ else
+ lim->limit = res->base -1;
+ }
+
+ /* Descend into every enabled child and look for fixed resources. */
+ for (link = dev->link_list; link; link = link->next) {
+ for (child = link->children; child; child = child->sibling) {
+ if (child->enabled)
+ constrain_resources(child, limits);
+ }
+ }
+}
+
+static void avoid_fixed_resources(struct device *dev)
+{
+ struct constraints limits;
+ struct resource *res;
+
+ printk(BIOS_SPEW, "%s: %s\n", __func__, dev_path(dev));
+
+ /* Initialize constraints to maximum size. */
+ limits.pref.base = 0;
+ limits.pref.limit = 0xffffffffffffffffULL;
+ limits.io.base = 0;
+ limits.io.limit = 0xffffffffffffffffULL;
+ limits.mem.base = 0;
+ limits.mem.limit = 0xffffffffffffffffULL;
+
+ /* Constrain the limits to dev's initial resources. */
+ for (res = dev->resource_list; res; res = res->next) {
+ if ((res->flags & IORESOURCE_FIXED))
+ continue;
+ printk(BIOS_SPEW, "%s:@%s %02lx limit %08llx\n", __func__,
+ dev_path(dev), res->index, res->limit);
+ if ((res->flags & MEM_MASK) == PREF_TYPE &&
+ (res->limit < limits.pref.limit))
+ limits.pref.limit = res->limit;
+ if ((res->flags & MEM_MASK) == MEM_TYPE &&
+ (res->limit < limits.mem.limit))
+ limits.mem.limit = res->limit;
+ if ((res->flags & IO_MASK) == IO_TYPE &&
+ (res->limit < limits.io.limit))
+ limits.io.limit = res->limit;
+ }
+
+ /* Look through the tree for fixed resources and update the limits. */
+ constrain_resources(dev, &limits);
+
+ /* Update dev's resources with new limits. */
+ for (res = dev->resource_list; res; res = res->next) {
+ struct resource *lim;