diff options
author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2010-12-16 12:38:20 -0500 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-12-17 13:00:38 -0500 |
commit | ac57cd5ee1935d1e60de86d75f13f377775f1c96 (patch) | |
tree | 2c53e07fc33f5cd2fc95f1dfdedb2a338758c2fe /drivers/pci/bus.c | |
parent | 49c2fa08a77a7eefa4cbc73601f64984aceacfa7 (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>
Diffstat (limited to 'drivers/pci/bus.c')
-rw-r--r-- | drivers/pci/bus.c | 70 |
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 | ||
67 | static 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 | |||
86 | static 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 | */ |
109 | static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus, | 71 | static 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; |