aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/setup-bus.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2012-01-21 05:08:27 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2012-02-14 11:44:55 -0500
commitbdc4abecaeff30b3cc230b418a925999dda594c2 (patch)
tree560705372265c02af5c8e9738a0a2bcaae32bb02 /drivers/pci/setup-bus.c
parent2934a0de095f277a7bbc15a72ecf61af31a45163 (diff)
PCI: Replace resource_list with generic list
So we can use helper functions for generic list. This makes the resource re-allocation code much more readable. -v2: Use list_add_tail instead of adding list_insert_before, Pointed out by Linus. Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r--drivers/pci/setup-bus.c374
1 files changed, 182 insertions, 192 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index b067a4cdce43..4c5509e3c75a 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -27,14 +27,14 @@
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include "pci.h" 28#include "pci.h"
29 29
30struct resource_list { 30struct pci_dev_resource {
31 struct resource_list *next; 31 struct list_head list;
32 struct resource *res; 32 struct resource *res;
33 struct pci_dev *dev; 33 struct pci_dev *dev;
34}; 34};
35 35
36struct resource_list_x { 36struct pci_dev_resource_x {
37 struct resource_list_x *next; 37 struct list_head list;
38 struct resource *res; 38 struct resource *res;
39 struct pci_dev *dev; 39 struct pci_dev *dev;
40 resource_size_t start; 40 resource_size_t start;
@@ -44,14 +44,12 @@ struct resource_list_x {
44 unsigned long flags; 44 unsigned long flags;
45}; 45};
46 46
47#define free_list(type, head) do { \ 47#define free_list(type, head) do { \
48 struct type *list, *tmp; \ 48 struct type *dev_res, *tmp; \
49 for (list = (head)->next; list;) { \ 49 list_for_each_entry_safe(dev_res, tmp, head, list) { \
50 tmp = list; \ 50 list_del(&dev_res->list); \
51 list = list->next; \ 51 kfree(dev_res); \
52 kfree(tmp); \ 52 } \
53 } \
54 (head)->next = NULL; \
55} while (0) 53} while (0)
56 54
57int pci_realloc_enable = 0; 55int pci_realloc_enable = 0;
@@ -70,21 +68,18 @@ void pci_realloc(void)
70 * @add_size: additional size to be optionally added 68 * @add_size: additional size to be optionally added
71 * to the resource 69 * to the resource
72 */ 70 */
73static int add_to_list(struct resource_list_x *head, 71static int add_to_list(struct list_head *head,
74 struct pci_dev *dev, struct resource *res, 72 struct pci_dev *dev, struct resource *res,
75 resource_size_t add_size, resource_size_t min_align) 73 resource_size_t add_size, resource_size_t min_align)
76{ 74{
77 struct resource_list_x *list = head; 75 struct pci_dev_resource_x *tmp;
78 struct resource_list_x *ln = list->next;
79 struct resource_list_x *tmp;
80 76
81 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); 77 tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
82 if (!tmp) { 78 if (!tmp) {
83 pr_warning("add_to_list: kmalloc() failed!\n"); 79 pr_warning("add_to_list: kmalloc() failed!\n");
84 return -ENOMEM; 80 return -ENOMEM;
85 } 81 }
86 82
87 tmp->next = ln;
88 tmp->res = res; 83 tmp->res = res;
89 tmp->dev = dev; 84 tmp->dev = dev;
90 tmp->start = res->start; 85 tmp->start = res->start;
@@ -92,12 +87,13 @@ static int add_to_list(struct resource_list_x *head,
92 tmp->flags = res->flags; 87 tmp->flags = res->flags;
93 tmp->add_size = add_size; 88 tmp->add_size = add_size;
94 tmp->min_align = min_align; 89 tmp->min_align = min_align;
95 list->next = tmp; 90
91 list_add(&tmp->list, head);
96 92
97 return 0; 93 return 0;
98} 94}
99 95
100static void add_to_failed_list(struct resource_list_x *head, 96static void add_to_failed_list(struct list_head *head,
101 struct pci_dev *dev, struct resource *res) 97 struct pci_dev *dev, struct resource *res)
102{ 98{
103 add_to_list(head, dev, res, 99 add_to_list(head, dev, res,
@@ -105,53 +101,48 @@ static void add_to_failed_list(struct resource_list_x *head,
105 0 /* dont care */); 101 0 /* dont care */);
106} 102}
107 103
108static void remove_from_list(struct resource_list_x *realloc_head, 104static void remove_from_list(struct list_head *realloc_head,
109 struct resource *res) 105 struct resource *res)
110{ 106{
111 struct resource_list_x *prev, *tmp, *list; 107 struct pci_dev_resource_x *dev_res_x, *tmp;
112 108
113 prev = realloc_head; 109 list_for_each_entry_safe(dev_res_x, tmp, realloc_head, list) {
114 for (list = realloc_head->next; list;) { 110 if (dev_res_x->res == res) {
115 if (list->res != res) { 111 list_del(&dev_res_x->list);
116 prev = list; 112 kfree(dev_res_x);
117 list = list->next; 113 break;
118 continue;
119 } 114 }
120 tmp = list;
121 prev->next = list = list->next;
122 kfree(tmp);
123 } 115 }
124} 116}
125 117
126static resource_size_t get_res_add_size(struct resource_list_x *realloc_head, 118static resource_size_t get_res_add_size(struct list_head *realloc_head,
127 struct resource *res) 119 struct resource *res)
128{ 120{
129 struct resource_list_x *list; 121 struct pci_dev_resource_x *dev_res_x;
130 122
131 /* check if it is in realloc_head list */ 123 list_for_each_entry(dev_res_x, realloc_head, list) {
132 for (list = realloc_head->next; list && list->res != res; 124 if (dev_res_x->res == res) {
133 list = list->next) 125 dev_printk(KERN_DEBUG, &dev_res_x->dev->dev,
134 ; 126 "%pR get_res_add_size add_size %llx\n",
135 127 dev_res_x->res,
136 if (list) { 128 (unsigned long long)dev_res_x->add_size);
137 dev_printk(KERN_DEBUG, &list->dev->dev, 129 return dev_res_x->add_size;
138 "%pR get_res_add_size add_size %llx\n", 130 }
139 list->res, (unsigned long long)list->add_size);
140 return list->add_size;
141 } 131 }
142 132
143 return 0; 133 return 0;
144} 134}
145 135
146/* Sort resources by alignment */ 136/* Sort resources by alignment */
147static void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) 137static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
148{ 138{
149 int i; 139 int i;
150 140
151 for (i = 0; i < PCI_NUM_RESOURCES; i++) { 141 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
152 struct resource *r; 142 struct resource *r;
153 struct resource_list *list, *tmp; 143 struct pci_dev_resource *dev_res, *tmp;
154 resource_size_t r_align; 144 resource_size_t r_align;
145 struct list_head *n;
155 146
156 r = &dev->resource[i]; 147 r = &dev->resource[i];
157 148
@@ -167,30 +158,34 @@ static void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
167 i, r); 158 i, r);
168 continue; 159 continue;
169 } 160 }
170 for (list = head; ; list = list->next) {
171 resource_size_t align = 0;
172 struct resource_list *ln = list->next;
173 161
174 if (ln) 162 tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
175 align = pci_resource_alignment(ln->dev, ln->res); 163 if (!tmp)
164 panic("pdev_sort_resources(): "
165 "kmalloc() failed!\n");
166 tmp->res = r;
167 tmp->dev = dev;
168
169 /* fallback is smallest one or list is empty*/
170 n = head;
171 list_for_each_entry(dev_res, head, list) {
172 resource_size_t align;
173
174 align = pci_resource_alignment(dev_res->dev,
175 dev_res->res);
176 176
177 if (r_align > align) { 177 if (r_align > align) {
178 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); 178 n = &dev_res->list;
179 if (!tmp)
180 panic("pdev_sort_resources(): "
181 "kmalloc() failed!\n");
182 tmp->next = ln;
183 tmp->res = r;
184 tmp->dev = dev;
185 list->next = tmp;
186 break; 179 break;
187 } 180 }
188 } 181 }
182 /* Insert it just before n*/
183 list_add_tail(&tmp->list, n);
189 } 184 }
190} 185}
191 186
192static void __dev_sort_resources(struct pci_dev *dev, 187static void __dev_sort_resources(struct pci_dev *dev,
193 struct resource_list *head) 188 struct list_head *head)
194{ 189{
195 u16 class = dev->class >> 8; 190 u16 class = dev->class >> 8;
196 191
@@ -228,49 +223,53 @@ static inline void reset_resource(struct resource *res)
228 * additional resources for the element, provided the element 223 * additional resources for the element, provided the element
229 * is in the head list. 224 * is in the head list.
230 */ 225 */
231static void reassign_resources_sorted(struct resource_list_x *realloc_head, 226static void reassign_resources_sorted(struct list_head *realloc_head,
232 struct resource_list *head) 227 struct list_head *head)
233{ 228{
234 struct resource *res; 229 struct resource *res;
235 struct resource_list_x *list, *tmp, *prev; 230 struct pci_dev_resource_x *dev_res_x, *tmp;
236 struct resource_list *hlist; 231 struct pci_dev_resource *dev_res;
237 resource_size_t add_size; 232 resource_size_t add_size;
238 int idx; 233 int idx;
239 234
240 prev = realloc_head; 235 list_for_each_entry_safe(dev_res_x, tmp, realloc_head, list) {
241 for (list = realloc_head->next; list;) { 236 bool found_match = false;
242 res = list->res; 237
238 res = dev_res_x->res;
243 /* skip resource that has been reset */ 239 /* skip resource that has been reset */
244 if (!res->flags) 240 if (!res->flags)
245 goto out; 241 goto out;
246 242
247 /* skip this resource if not found in head list */ 243 /* skip this resource if not found in head list */
248 for (hlist = head->next; hlist && hlist->res != res; 244 list_for_each_entry(dev_res, head, list) {
249 hlist = hlist->next); 245 if (dev_res->res == res) {
250 if (!hlist) { /* just skip */ 246 found_match = true;
251 prev = list; 247 break;
252 list = list->next; 248 }
253 continue;
254 } 249 }
250 if (!found_match)/* just skip */
251 continue;
255 252
256 idx = res - &list->dev->resource[0]; 253 idx = res - &dev_res_x->dev->resource[0];
257 add_size=list->add_size; 254 add_size = dev_res_x->add_size;
258 if (!resource_size(res)) { 255 if (!resource_size(res)) {
259 res->start = list->start; 256 res->start = dev_res_x->start;
260 res->end = res->start + add_size - 1; 257 res->end = res->start + add_size - 1;
261 if(pci_assign_resource(list->dev, idx)) 258 if (pci_assign_resource(dev_res_x->dev, idx))
262 reset_resource(res); 259 reset_resource(res);
263 } else { 260 } else {
264 resource_size_t align = list->min_align; 261 resource_size_t align = dev_res_x->min_align;
265 res->flags |= list->flags & (IORESOURCE_STARTALIGN|IORESOURCE_SIZEALIGN); 262 res->flags |= dev_res_x->flags &
266 if (pci_reassign_resource(list->dev, idx, add_size, align)) 263 (IORESOURCE_STARTALIGN|IORESOURCE_SIZEALIGN);
267 dev_printk(KERN_DEBUG, &list->dev->dev, "failed to add optional resources res=%pR\n", 264 if (pci_reassign_resource(dev_res_x->dev, idx,
265 add_size, align))
266 dev_printk(KERN_DEBUG, &dev_res_x->dev->dev,
267 "failed to add optional resources res=%pR\n",
268 res); 268 res);
269 } 269 }
270out: 270out:
271 tmp = list; 271 list_del(&dev_res_x->list);
272 prev->next = list = list->next; 272 kfree(dev_res_x);
273 kfree(tmp);
274 } 273 }
275} 274}
276 275
@@ -284,34 +283,36 @@ out:
284 * Satisfy resource requests of each element in the list. Add 283 * Satisfy resource requests of each element in the list. Add
285 * requests that could not satisfied to the failed_list. 284 * requests that could not satisfied to the failed_list.
286 */ 285 */
287static void assign_requested_resources_sorted(struct resource_list *head, 286static void assign_requested_resources_sorted(struct list_head *head,
288 struct resource_list_x *fail_head) 287 struct list_head *fail_head)
289{ 288{
290 struct resource *res; 289 struct resource *res;
291 struct resource_list *list; 290 struct pci_dev_resource *dev_res;
292 int idx; 291 int idx;
293 292
294 for (list = head->next; list; list = list->next) { 293 list_for_each_entry(dev_res, head, list) {
295 res = list->res; 294 res = dev_res->res;
296 idx = res - &list->dev->resource[0]; 295 idx = res - &dev_res->dev->resource[0];
297 if (resource_size(res) && pci_assign_resource(list->dev, idx)) { 296 if (resource_size(res) &&
298 if (fail_head && !pci_is_root_bus(list->dev->bus)) { 297 pci_assign_resource(dev_res->dev, idx)) {
298 if (fail_head && !pci_is_root_bus(dev_res->dev->bus)) {
299 /* 299 /*
300 * if the failed res is for ROM BAR, and it will 300 * if the failed res is for ROM BAR, and it will
301 * be enabled later, don't add it to the list 301 * be enabled later, don't add it to the list
302 */ 302 */
303 if (!((idx == PCI_ROM_RESOURCE) && 303 if (!((idx == PCI_ROM_RESOURCE) &&
304 (!(res->flags & IORESOURCE_ROM_ENABLE)))) 304 (!(res->flags & IORESOURCE_ROM_ENABLE))))
305 add_to_failed_list(fail_head, list->dev, res); 305 add_to_failed_list(fail_head,
306 dev_res->dev, res);
306 } 307 }
307 reset_resource(res); 308 reset_resource(res);
308 } 309 }
309 } 310 }
310} 311}
311 312
312static void __assign_resources_sorted(struct resource_list *head, 313static void __assign_resources_sorted(struct list_head *head,
313 struct resource_list_x *realloc_head, 314 struct list_head *realloc_head,
314 struct resource_list_x *fail_head) 315 struct list_head *fail_head)
315{ 316{
316 /* 317 /*
317 * Should not assign requested resources at first. 318 * Should not assign requested resources at first.
@@ -322,53 +323,55 @@ static void __assign_resources_sorted(struct resource_list *head,
322 * if could not do that, we still try to assign requested at first, 323 * if could not do that, we still try to assign requested at first,
323 * then try to reassign add_size for some resources. 324 * then try to reassign add_size for some resources.
324 */ 325 */
325 struct resource_list_x save_head, local_fail_head, *list; 326 LIST_HEAD(save_head);
326 struct resource_list *l; 327 LIST_HEAD(local_fail_head);
328 struct pci_dev_resource_x *dev_res_x;
329 struct pci_dev_resource *dev_res;
327 330
328 /* Check if optional add_size is there */ 331 /* Check if optional add_size is there */
329 if (!realloc_head || !realloc_head->next) 332 if (!realloc_head || list_empty(realloc_head))
330 goto requested_and_reassign; 333 goto requested_and_reassign;
331 334
332 /* Save original start, end, flags etc at first */ 335 /* Save original start, end, flags etc at first */
333 save_head.next = NULL; 336 list_for_each_entry(dev_res, head, list) {
334 for (l = head->next; l; l = l->next) 337 if (add_to_list(&save_head, dev_res->dev, dev_res->res, 0, 0)) {
335 if (add_to_list(&save_head, l->dev, l->res, 0, 0)) { 338 free_list(pci_dev_resource_x, &save_head);
336 free_list(resource_list_x, &save_head);
337 goto requested_and_reassign; 339 goto requested_and_reassign;
338 } 340 }
341 }
339 342
340 /* Update res in head list with add_size in realloc_head list */ 343 /* Update res in head list with add_size in realloc_head list */
341 for (l = head->next; l; l = l->next) 344 list_for_each_entry(dev_res, head, list)
342 l->res->end += get_res_add_size(realloc_head, l->res); 345 dev_res->res->end += get_res_add_size(realloc_head,
346 dev_res->res);
343 347
344 /* Try updated head list with add_size added */ 348 /* Try updated head list with add_size added */
345 local_fail_head.next = NULL;
346 assign_requested_resources_sorted(head, &local_fail_head); 349 assign_requested_resources_sorted(head, &local_fail_head);
347 350
348 /* all assigned with add_size ? */ 351 /* all assigned with add_size ? */
349 if (!local_fail_head.next) { 352 if (list_empty(&local_fail_head)) {
350 /* Remove head list from realloc_head list */ 353 /* Remove head list from realloc_head list */
351 for (l = head->next; l; l = l->next) 354 list_for_each_entry(dev_res, head, list)
352 remove_from_list(realloc_head, l->res); 355 remove_from_list(realloc_head, dev_res->res);
353 free_list(resource_list_x, &save_head); 356 free_list(pci_dev_resource_x, &save_head);
354 free_list(resource_list, head); 357 free_list(pci_dev_resource, head);
355 return; 358 return;
356 } 359 }
357 360
358 free_list(resource_list_x, &local_fail_head); 361 free_list(pci_dev_resource_x, &local_fail_head);
359 /* Release assigned resource */ 362 /* Release assigned resource */
360 for (l = head->next; l; l = l->next) 363 list_for_each_entry(dev_res, head, list)
361 if (l->res->parent) 364 if (dev_res->res->parent)
362 release_resource(l->res); 365 release_resource(dev_res->res);
363 /* Restore start/end/flags from saved list */ 366 /* Restore start/end/flags from saved list */
364 for (list = save_head.next; list; list = list->next) { 367 list_for_each_entry(dev_res_x, &save_head, list) {
365 struct resource *res = list->res; 368 struct resource *res = dev_res_x->res;
366 369
367 res->start = list->start; 370 res->start = dev_res_x->start;
368 res->end = list->end; 371 res->end = dev_res_x->end;
369 res->flags = list->flags; 372 res->flags = dev_res_x->flags;
370 } 373 }
371 free_list(resource_list_x, &save_head); 374 free_list(pci_dev_resource_x, &save_head);
372 375
373requested_and_reassign: 376requested_and_reassign:
374 /* Satisfy the must-have resource requests */ 377 /* Satisfy the must-have resource requests */
@@ -378,29 +381,27 @@ requested_and_reassign:
378 requests */ 381 requests */
379 if (realloc_head) 382 if (realloc_head)
380 reassign_resources_sorted(realloc_head, head); 383 reassign_resources_sorted(realloc_head, head);
381 free_list(resource_list, head); 384 free_list(pci_dev_resource, head);
382} 385}
383 386
384static void pdev_assign_resources_sorted(struct pci_dev *dev, 387static void pdev_assign_resources_sorted(struct pci_dev *dev,
385 struct resource_list_x *add_head, 388 struct list_head *add_head,
386 struct resource_list_x *fail_head) 389 struct list_head *fail_head)
387{ 390{
388 struct resource_list head; 391 LIST_HEAD(head);
389 392
390 head.next = NULL;
391 __dev_sort_resources(dev, &head); 393 __dev_sort_resources(dev, &head);
392 __assign_resources_sorted(&head, add_head, fail_head); 394 __assign_resources_sorted(&head, add_head, fail_head);
393 395
394} 396}
395 397
396static void pbus_assign_resources_sorted(const struct pci_bus *bus, 398static void pbus_assign_resources_sorted(const struct pci_bus *bus,
397 struct resource_list_x *realloc_head, 399 struct list_head *realloc_head,
398 struct resource_list_x *fail_head) 400 struct list_head *fail_head)
399{ 401{
400 struct pci_dev *dev; 402 struct pci_dev *dev;
401 struct resource_list head; 403 LIST_HEAD(head);
402 404
403 head.next = NULL;
404 list_for_each_entry(dev, &bus->devices, bus_list) 405 list_for_each_entry(dev, &bus->devices, bus_list)
405 __dev_sort_resources(dev, &head); 406 __dev_sort_resources(dev, &head);
406 407
@@ -713,7 +714,7 @@ static resource_size_t calculate_memsize(resource_size_t size,
713 * We must be careful with the ISA aliasing though. 714 * We must be careful with the ISA aliasing though.
714 */ 715 */
715static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, 716static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
716 resource_size_t add_size, struct resource_list_x *realloc_head) 717 resource_size_t add_size, struct list_head *realloc_head)
717{ 718{
718 struct pci_dev *dev; 719 struct pci_dev *dev;
719 struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); 720 struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
@@ -781,7 +782,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
781static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, 782static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
782 unsigned long type, resource_size_t min_size, 783 unsigned long type, resource_size_t min_size,
783 resource_size_t add_size, 784 resource_size_t add_size,
784 struct resource_list_x *realloc_head) 785 struct list_head *realloc_head)
785{ 786{
786 struct pci_dev *dev; 787 struct pci_dev *dev;
787 resource_size_t min_align, align, size, size0, size1; 788 resource_size_t min_align, align, size, size0, size1;
@@ -891,7 +892,7 @@ unsigned long pci_cardbus_resource_alignment(struct resource *res)
891} 892}
892 893
893static void pci_bus_size_cardbus(struct pci_bus *bus, 894static void pci_bus_size_cardbus(struct pci_bus *bus,
894 struct resource_list_x *realloc_head) 895 struct list_head *realloc_head)
895{ 896{
896 struct pci_dev *bridge = bus->self; 897 struct pci_dev *bridge = bus->self;
897 struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES]; 898 struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
@@ -953,7 +954,7 @@ static void pci_bus_size_cardbus(struct pci_bus *bus,
953} 954}
954 955
955void __ref __pci_bus_size_bridges(struct pci_bus *bus, 956void __ref __pci_bus_size_bridges(struct pci_bus *bus,
956 struct resource_list_x *realloc_head) 957 struct list_head *realloc_head)
957{ 958{
958 struct pci_dev *dev; 959 struct pci_dev *dev;
959 unsigned long mask, prefmask; 960 unsigned long mask, prefmask;
@@ -1024,8 +1025,8 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
1024EXPORT_SYMBOL(pci_bus_size_bridges); 1025EXPORT_SYMBOL(pci_bus_size_bridges);
1025 1026
1026static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, 1027static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
1027 struct resource_list_x *realloc_head, 1028 struct list_head *realloc_head,
1028 struct resource_list_x *fail_head) 1029 struct list_head *fail_head)
1029{ 1030{
1030 struct pci_bus *b; 1031 struct pci_bus *b;
1031 struct pci_dev *dev; 1032 struct pci_dev *dev;
@@ -1064,8 +1065,8 @@ void __ref pci_bus_assign_resources(const struct pci_bus *bus)
1064EXPORT_SYMBOL(pci_bus_assign_resources); 1065EXPORT_SYMBOL(pci_bus_assign_resources);
1065 1066
1066static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge, 1067static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge,
1067 struct resource_list_x *add_head, 1068 struct list_head *add_head,
1068 struct resource_list_x *fail_head) 1069 struct list_head *fail_head)
1069{ 1070{
1070 struct pci_bus *b; 1071 struct pci_bus *b;
1071 1072
@@ -1249,20 +1250,18 @@ void __init
1249pci_assign_unassigned_resources(void) 1250pci_assign_unassigned_resources(void)
1250{ 1251{
1251 struct pci_bus *bus; 1252 struct pci_bus *bus;
1252 struct resource_list_x realloc_list; /* list of resources that 1253 LIST_HEAD(realloc_head); /* list of resources that
1253 want additional resources */ 1254 want additional resources */
1254 struct resource_list_x *add_list = NULL; 1255 struct list_head *add_list = NULL;
1255 int tried_times = 0; 1256 int tried_times = 0;
1256 enum release_type rel_type = leaf_only; 1257 enum release_type rel_type = leaf_only;
1257 struct resource_list_x head, *list; 1258 LIST_HEAD(fail_head);
1259 struct pci_dev_resource_x *dev_res_x;
1258 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | 1260 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
1259 IORESOURCE_PREFETCH; 1261 IORESOURCE_PREFETCH;
1260 unsigned long failed_type; 1262 unsigned long failed_type;
1261 int pci_try_num = 1; 1263 int pci_try_num = 1;
1262 1264
1263 head.next = NULL;
1264 realloc_list.next = NULL;
1265
1266 /* don't realloc if asked to do so */ 1265 /* don't realloc if asked to do so */
1267 if (pci_realloc_enabled()) { 1266 if (pci_realloc_enabled()) {
1268 int max_depth = pci_get_max_depth(); 1267 int max_depth = pci_get_max_depth();
@@ -1278,7 +1277,7 @@ again:
1278 * must have, so can realloc parent bridge resource 1277 * must have, so can realloc parent bridge resource
1279 */ 1278 */
1280 if (tried_times + 1 == pci_try_num) 1279 if (tried_times + 1 == pci_try_num)
1281 add_list = &realloc_list; 1280 add_list = &realloc_head;
1282 /* Depth first, calculate sizes and alignments of all 1281 /* Depth first, calculate sizes and alignments of all
1283 subordinate buses. */ 1282 subordinate buses. */
1284 list_for_each_entry(bus, &pci_root_buses, node) 1283 list_for_each_entry(bus, &pci_root_buses, node)
@@ -1286,27 +1285,26 @@ again:
1286 1285
1287 /* Depth last, allocate resources and update the hardware. */ 1286 /* Depth last, allocate resources and update the hardware. */
1288 list_for_each_entry(bus, &pci_root_buses, node) 1287 list_for_each_entry(bus, &pci_root_buses, node)
1289 __pci_bus_assign_resources(bus, add_list, &head); 1288 __pci_bus_assign_resources(bus, add_list, &fail_head);
1290 if (add_list) 1289 if (add_list)
1291 BUG_ON(add_list->next); 1290 BUG_ON(!list_empty(add_list));
1292 tried_times++; 1291 tried_times++;
1293 1292
1294 /* any device complain? */ 1293 /* any device complain? */
1295 if (!head.next) 1294 if (list_empty(&fail_head))
1296 goto enable_and_dump; 1295 goto enable_and_dump;
1297 1296
1298 failed_type = 0; 1297 failed_type = 0;
1299 for (list = head.next; list;) { 1298 list_for_each_entry(dev_res_x, &fail_head, list)
1300 failed_type |= list->flags; 1299 failed_type |= dev_res_x->flags;
1301 list = list->next; 1300
1302 }
1303 /* 1301 /*
1304 * io port are tight, don't try extra 1302 * io port are tight, don't try extra
1305 * or if reach the limit, don't want to try more 1303 * or if reach the limit, don't want to try more
1306 */ 1304 */
1307 failed_type &= type_mask; 1305 failed_type &= type_mask;
1308 if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) { 1306 if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) {
1309 free_list(resource_list_x, &head); 1307 free_list(pci_dev_resource_x, &fail_head);
1310 goto enable_and_dump; 1308 goto enable_and_dump;
1311 } 1309 }
1312 1310
@@ -1321,25 +1319,23 @@ again:
1321 * Try to release leaf bridge's resources that doesn't fit resource of 1319 * Try to release leaf bridge's resources that doesn't fit resource of
1322 * child device under that bridge 1320 * child device under that bridge
1323 */ 1321 */
1324 for (list = head.next; list;) { 1322 list_for_each_entry(dev_res_x, &fail_head, list) {
1325 bus = list->dev->bus; 1323 bus = dev_res_x->dev->bus;
1326 pci_bus_release_bridge_resources(bus, list->flags & type_mask, 1324 pci_bus_release_bridge_resources(bus,
1327 rel_type); 1325 dev_res_x->flags & type_mask,
1328 list = list->next; 1326 rel_type);
1329 } 1327 }
1330 /* restore size and flags */ 1328 /* restore size and flags */
1331 for (list = head.next; list;) { 1329 list_for_each_entry(dev_res_x, &fail_head, list) {
1332 struct resource *res = list->res; 1330 struct resource *res = dev_res_x->res;
1333 1331
1334 res->start = list->start; 1332 res->start = dev_res_x->start;
1335 res->end = list->end; 1333 res->end = dev_res_x->end;
1336 res->flags = list->flags; 1334 res->flags = dev_res_x->flags;
1337 if (list->dev->subordinate) 1335 if (dev_res_x->dev->subordinate)
1338 res->flags = 0; 1336 res->flags = 0;
1339
1340 list = list->next;
1341 } 1337 }
1342 free_list(resource_list_x, &head); 1338 free_list(pci_dev_resource_x, &fail_head);
1343 1339
1344 goto again; 1340 goto again;
1345 1341
@@ -1356,29 +1352,27 @@ enable_and_dump:
1356void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) 1352void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
1357{ 1353{
1358 struct pci_bus *parent = bridge->subordinate; 1354 struct pci_bus *parent = bridge->subordinate;
1359 struct resource_list_x add_list; /* list of resources that 1355 LIST_HEAD(add_list); /* list of resources that
1360 want additional resources */ 1356 want additional resources */
1361 int tried_times = 0; 1357 int tried_times = 0;
1362 struct resource_list_x head, *list; 1358 LIST_HEAD(fail_head);
1359 struct pci_dev_resource_x *dev_res_x;
1363 int retval; 1360 int retval;
1364 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | 1361 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
1365 IORESOURCE_PREFETCH; 1362 IORESOURCE_PREFETCH;
1366 1363
1367 head.next = NULL;
1368 add_list.next = NULL;
1369
1370again: 1364again:
1371 __pci_bus_size_bridges(parent, &add_list); 1365 __pci_bus_size_bridges(parent, &add_list);
1372 __pci_bridge_assign_resources(bridge, &add_list, &head); 1366 __pci_bridge_assign_resources(bridge, &add_list, &fail_head);
1373 BUG_ON(add_list.next); 1367 BUG_ON(!list_empty(&add_list));
1374 tried_times++; 1368 tried_times++;
1375 1369
1376 if (!head.next) 1370 if (list_empty(&fail_head))
1377 goto enable_all; 1371 goto enable_all;
1378 1372
1379 if (tried_times >= 2) { 1373 if (tried_times >= 2) {
1380 /* still fail, don't need to try more */ 1374 /* still fail, don't need to try more */
1381 free_list(resource_list_x, &head); 1375 free_list(pci_dev_resource_x, &fail_head);
1382 goto enable_all; 1376 goto enable_all;
1383 } 1377 }
1384 1378
@@ -1389,27 +1383,24 @@ again:
1389 * Try to release leaf bridge's resources that doesn't fit resource of 1383 * Try to release leaf bridge's resources that doesn't fit resource of
1390 * child device under that bridge 1384 * child device under that bridge
1391 */ 1385 */
1392 for (list = head.next; list;) { 1386 list_for_each_entry(dev_res_x, &fail_head, list) {
1393 struct pci_bus *bus = list->dev->bus; 1387 struct pci_bus *bus = dev_res_x->dev->bus;
1394 unsigned long flags = list->flags; 1388 unsigned long flags = dev_res_x->flags;
1395 1389
1396 pci_bus_release_bridge_resources(bus, flags & type_mask, 1390 pci_bus_release_bridge_resources(bus, flags & type_mask,
1397 whole_subtree); 1391 whole_subtree);
1398 list = list->next;
1399 } 1392 }
1400 /* restore size and flags */ 1393 /* restore size and flags */
1401 for (list = head.next; list;) { 1394 list_for_each_entry(dev_res_x, &fail_head, list) {
1402 struct resource *res = list->res; 1395 struct resource *res = dev_res_x->res;
1403 1396
1404 res->start = list->start; 1397 res->start = dev_res_x->start;
1405 res->end = list->end; 1398 res->end = dev_res_x->end;
1406 res->flags = list->flags; 1399 res->flags = dev_res_x->flags;
1407 if (list->dev->subordinate) 1400 if (dev_res_x->dev->subordinate)
1408 res->flags = 0; 1401 res->flags = 0;
1409
1410 list = list->next;
1411 } 1402 }
1412 free_list(resource_list_x, &head); 1403 free_list(pci_dev_resource_x, &fail_head);
1413 1404
1414 goto again; 1405 goto again;
1415 1406
@@ -1434,12 +1425,11 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
1434{ 1425{
1435 unsigned int max; 1426 unsigned int max;
1436 struct pci_dev *dev; 1427 struct pci_dev *dev;
1437 struct resource_list_x add_list; /* list of resources that 1428 LIST_HEAD(add_list); /* list of resources that
1438 want additional resources */ 1429 want additional resources */
1439 1430
1440 max = pci_scan_child_bus(bus); 1431 max = pci_scan_child_bus(bus);
1441 1432
1442 add_list.next = NULL;
1443 down_read(&pci_bus_sem); 1433 down_read(&pci_bus_sem);
1444 list_for_each_entry(dev, &bus->devices, bus_list) 1434 list_for_each_entry(dev, &bus->devices, bus_list)
1445 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || 1435 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
@@ -1449,7 +1439,7 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
1449 &add_list); 1439 &add_list);
1450 up_read(&pci_bus_sem); 1440 up_read(&pci_bus_sem);
1451 __pci_bus_assign_resources(bus, &add_list, NULL); 1441 __pci_bus_assign_resources(bus, &add_list, NULL);
1452 BUG_ON(add_list.next); 1442 BUG_ON(!list_empty(&add_list));
1453 1443
1454 pci_enable_bridges(bus); 1444 pci_enable_bridges(bus);
1455 pci_bus_add_devices(bus); 1445 pci_bus_add_devices(bus);