@@ -64,6 +64,24 @@ void pci_bus_remove_resources(struct pci_bus *bus)
}
}
+static int resource_compare(struct resource *res1, struct resource *res2)
+{
+ if (res1->end < res2->end)
+ return -1;
+
+ if (res1->end > res2->end)
+ return 1;
+
+ if (res1->start < res2->start)
+ return -1;
+
+ if (res1->start > res2->start)
+ return 1;
+
+ /* If start/end are identical, order them to avoid loops */
+ return res1 - res2;
+}
+
/*
* Find the highest-address bus resource below the cursor "res". If the
* cursor is NULL, return the highest resource.
@@ -82,26 +100,12 @@ static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus,
if ((r->flags & IORESOURCE_TYPE_BITS) != type)
continue;
- /* If this resource is at or past the cursor, skip it */
- if (res) {
- if (r == res)
- continue;
- if (r->end > res->end)
- continue;
- if (r->end == res->end && r->start > res->start)
- continue;
+ /* Only look at resources before the cursor */
+ if (!res || resource_compare(r, res) < 0) {
+ /* Keep the highest one we find */
+ if (!prev || resource_compare(r, prev) > 0)
+ prev = r;
}
-
- if (!prev)
- prev = r;
-
- /*
- * A small resource is higher than a large one that ends at
- * the same address.
- */
- if (r->end > prev->end ||
- (r->end == prev->end && r->start > prev->start))
- prev = r;
}
return prev;