aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2010-12-16 12:38:20 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-12-17 13:00:38 -0500
commitac57cd5ee1935d1e60de86d75f13f377775f1c96 (patch)
tree2c53e07fc33f5cd2fc95f1dfdedb2a338758c2fe
parent49c2fa08a77a7eefa4cbc73601f64984aceacfa7 (diff)
Revert "PCI: fix pci_bus_alloc_resource() hang, prefer positive decode"
This reverts commit 82e3e767c21fef2b1b38868e20eb4e470a1e38e3. We're going back to considering bus resources in the order we found them (in _CRS order, when we're using _CRS), so we don't need to define any ordering. Acked-by: H. Peter Anvin <hpa@zytor.com> Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r--drivers/pci/bus.c70
1 files changed, 21 insertions, 49 deletions
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 003170ea2e39..5624db8c9ad0 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -64,57 +64,17 @@ void pci_bus_remove_resources(struct pci_bus *bus)
64 } 64 }
65} 65}
66 66
67static bool pci_bus_resource_better(struct resource *res1, bool pos1,
68 struct resource *res2, bool pos2)
69{
70 /* If exactly one is positive decode, always prefer that one */
71 if (pos1 != pos2)
72 return pos1 ? true : false;
73
74 /* Prefer the one that contains the highest address */
75 if (res1->end != res2->end)
76 return (res1->end > res2->end) ? true : false;
77
78 /* Otherwise, prefer the one with highest "center of gravity" */
79 if (res1->start != res2->start)
80 return (res1->start > res2->start) ? true : false;
81
82 /* Otherwise, choose one arbitrarily (but consistently) */
83 return (res1 > res2) ? true : false;
84}
85
86static bool pci_bus_resource_positive(struct pci_bus *bus, struct resource *res)
87{
88 struct pci_bus_resource *bus_res;
89
90 /*
91 * This relies on the fact that pci_bus.resource[] refers to P2P or
92 * CardBus bridge base/limit registers, which are always positively
93 * decoded. The pci_bus.resources list contains host bridge or
94 * subtractively decoded resources.
95 */
96 list_for_each_entry(bus_res, &bus->resources, list) {
97 if (bus_res->res == res)
98 return (bus_res->flags & PCI_SUBTRACTIVE_DECODE) ?
99 false : true;
100 }
101 return true;
102}
103
104/* 67/*
105 * Find the next-best bus resource after the cursor "res". If the cursor is 68 * Find the highest-address bus resource below the cursor "res". If the
106 * NULL, return the best resource. "Best" means that we prefer positive 69 * cursor is NULL, return the highest resource.
107 * decode regions over subtractive decode, then those at higher addresses.
108 */ 70 */
109static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus, 71static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus,
110 unsigned int type, 72 unsigned int type,
111 struct resource *res) 73 struct resource *res)
112{ 74{
113 bool res_pos, r_pos, prev_pos = false;
114 struct resource *r, *prev = NULL; 75 struct resource *r, *prev = NULL;
115 int i; 76 int i;
116 77
117 res_pos = pci_bus_resource_positive(bus, res);
118 pci_bus_for_each_resource(bus, r, i) { 78 pci_bus_for_each_resource(bus, r, i) {
119 if (!r) 79 if (!r)
120 continue; 80 continue;
@@ -122,14 +82,26 @@ static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus,
122 if ((r->flags & IORESOURCE_TYPE_BITS) != type) 82 if ((r->flags & IORESOURCE_TYPE_BITS) != type)
123 continue; 83 continue;
124 84
125 r_pos = pci_bus_resource_positive(bus, r); 85 /* If this resource is at or past the cursor, skip it */
126 if (!res || pci_bus_resource_better(res, res_pos, r, r_pos)) { 86 if (res) {
127 if (!prev || pci_bus_resource_better(r, r_pos, 87 if (r == res)
128 prev, prev_pos)) { 88 continue;
129 prev = r; 89 if (r->end > res->end)
130 prev_pos = r_pos; 90 continue;
131 } 91 if (r->end == res->end && r->start > res->start)
92 continue;
132 } 93 }
94
95 if (!prev)
96 prev = r;
97
98 /*
99 * A small resource is higher than a large one that ends at
100 * the same address.
101 */
102 if (r->end > prev->end ||
103 (r->end == prev->end && r->start > prev->start))
104 prev = r;
133 } 105 }
134 106
135 return prev; 107 return prev;