diff options
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r-- | drivers/pci/setup-bus.c | 321 |
1 files changed, 239 insertions, 82 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 66cb8f4cc5f4..89d0a6a88df7 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -33,11 +33,32 @@ struct resource_list_x { | |||
33 | struct pci_dev *dev; | 33 | struct pci_dev *dev; |
34 | resource_size_t start; | 34 | resource_size_t start; |
35 | resource_size_t end; | 35 | resource_size_t end; |
36 | resource_size_t add_size; | ||
36 | unsigned long flags; | 37 | unsigned long flags; |
37 | }; | 38 | }; |
38 | 39 | ||
39 | static void add_to_failed_list(struct resource_list_x *head, | 40 | #define free_list(type, head) do { \ |
40 | struct pci_dev *dev, struct resource *res) | 41 | struct type *list, *tmp; \ |
42 | for (list = (head)->next; list;) { \ | ||
43 | tmp = list; \ | ||
44 | list = list->next; \ | ||
45 | kfree(tmp); \ | ||
46 | } \ | ||
47 | (head)->next = NULL; \ | ||
48 | } while (0) | ||
49 | |||
50 | /** | ||
51 | * add_to_list() - add a new resource tracker to the list | ||
52 | * @head: Head of the list | ||
53 | * @dev: device corresponding to which the resource | ||
54 | * belongs | ||
55 | * @res: The resource to be tracked | ||
56 | * @add_size: additional size to be optionally added | ||
57 | * to the resource | ||
58 | */ | ||
59 | static void add_to_list(struct resource_list_x *head, | ||
60 | struct pci_dev *dev, struct resource *res, | ||
61 | resource_size_t add_size) | ||
41 | { | 62 | { |
42 | struct resource_list_x *list = head; | 63 | struct resource_list_x *list = head; |
43 | struct resource_list_x *ln = list->next; | 64 | struct resource_list_x *ln = list->next; |
@@ -45,7 +66,7 @@ static void add_to_failed_list(struct resource_list_x *head, | |||
45 | 66 | ||
46 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); | 67 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); |
47 | if (!tmp) { | 68 | if (!tmp) { |
48 | pr_warning("add_to_failed_list: kmalloc() failed!\n"); | 69 | pr_warning("add_to_list: kmalloc() failed!\n"); |
49 | return; | 70 | return; |
50 | } | 71 | } |
51 | 72 | ||
@@ -55,20 +76,14 @@ static void add_to_failed_list(struct resource_list_x *head, | |||
55 | tmp->start = res->start; | 76 | tmp->start = res->start; |
56 | tmp->end = res->end; | 77 | tmp->end = res->end; |
57 | tmp->flags = res->flags; | 78 | tmp->flags = res->flags; |
79 | tmp->add_size = add_size; | ||
58 | list->next = tmp; | 80 | list->next = tmp; |
59 | } | 81 | } |
60 | 82 | ||
61 | static void free_failed_list(struct resource_list_x *head) | 83 | static void add_to_failed_list(struct resource_list_x *head, |
84 | struct pci_dev *dev, struct resource *res) | ||
62 | { | 85 | { |
63 | struct resource_list_x *list, *tmp; | 86 | add_to_list(head, dev, res, 0); |
64 | |||
65 | for (list = head->next; list;) { | ||
66 | tmp = list; | ||
67 | list = list->next; | ||
68 | kfree(tmp); | ||
69 | } | ||
70 | |||
71 | head->next = NULL; | ||
72 | } | 87 | } |
73 | 88 | ||
74 | static void __dev_sort_resources(struct pci_dev *dev, | 89 | static void __dev_sort_resources(struct pci_dev *dev, |
@@ -91,18 +106,88 @@ static void __dev_sort_resources(struct pci_dev *dev, | |||
91 | pdev_sort_resources(dev, head); | 106 | pdev_sort_resources(dev, head); |
92 | } | 107 | } |
93 | 108 | ||
94 | static void __assign_resources_sorted(struct resource_list *head, | 109 | static inline void reset_resource(struct resource *res) |
95 | struct resource_list_x *fail_head) | 110 | { |
111 | res->start = 0; | ||
112 | res->end = 0; | ||
113 | res->flags = 0; | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * adjust_resources_sorted() - satisfy any additional resource requests | ||
118 | * | ||
119 | * @add_head : head of the list tracking requests requiring additional | ||
120 | * resources | ||
121 | * @head : head of the list tracking requests with allocated | ||
122 | * resources | ||
123 | * | ||
124 | * Walk through each element of the add_head and try to procure | ||
125 | * additional resources for the element, provided the element | ||
126 | * is in the head list. | ||
127 | */ | ||
128 | static void adjust_resources_sorted(struct resource_list_x *add_head, | ||
129 | struct resource_list *head) | ||
96 | { | 130 | { |
97 | struct resource *res; | 131 | struct resource *res; |
98 | struct resource_list *list, *tmp; | 132 | struct resource_list_x *list, *tmp, *prev; |
133 | struct resource_list *hlist; | ||
134 | resource_size_t add_size; | ||
99 | int idx; | 135 | int idx; |
100 | 136 | ||
101 | for (list = head->next; list;) { | 137 | prev = add_head; |
138 | for (list = add_head->next; list;) { | ||
102 | res = list->res; | 139 | res = list->res; |
140 | /* skip resource that has been reset */ | ||
141 | if (!res->flags) | ||
142 | goto out; | ||
143 | |||
144 | /* skip this resource if not found in head list */ | ||
145 | for (hlist = head->next; hlist && hlist->res != res; | ||
146 | hlist = hlist->next); | ||
147 | if (!hlist) { /* just skip */ | ||
148 | prev = list; | ||
149 | list = list->next; | ||
150 | continue; | ||
151 | } | ||
152 | |||
103 | idx = res - &list->dev->resource[0]; | 153 | idx = res - &list->dev->resource[0]; |
154 | add_size=list->add_size; | ||
155 | if (!resource_size(res) && add_size) { | ||
156 | res->end = res->start + add_size - 1; | ||
157 | if(pci_assign_resource(list->dev, idx)) | ||
158 | reset_resource(res); | ||
159 | } else if (add_size) { | ||
160 | adjust_resource(res, res->start, | ||
161 | resource_size(res) + add_size); | ||
162 | } | ||
163 | out: | ||
164 | tmp = list; | ||
165 | prev->next = list = list->next; | ||
166 | kfree(tmp); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | /** | ||
171 | * assign_requested_resources_sorted() - satisfy resource requests | ||
172 | * | ||
173 | * @head : head of the list tracking requests for resources | ||
174 | * @failed_list : head of the list tracking requests that could | ||
175 | * not be allocated | ||
176 | * | ||
177 | * Satisfy resource requests of each element in the list. Add | ||
178 | * requests that could not satisfied to the failed_list. | ||
179 | */ | ||
180 | static void assign_requested_resources_sorted(struct resource_list *head, | ||
181 | struct resource_list_x *fail_head) | ||
182 | { | ||
183 | struct resource *res; | ||
184 | struct resource_list *list; | ||
185 | int idx; | ||
104 | 186 | ||
105 | if (pci_assign_resource(list->dev, idx)) { | 187 | for (list = head->next; list; list = list->next) { |
188 | res = list->res; | ||
189 | idx = res - &list->dev->resource[0]; | ||
190 | if (resource_size(res) && pci_assign_resource(list->dev, idx)) { | ||
106 | if (fail_head && !pci_is_root_bus(list->dev->bus)) { | 191 | if (fail_head && !pci_is_root_bus(list->dev->bus)) { |
107 | /* | 192 | /* |
108 | * if the failed res is for ROM BAR, and it will | 193 | * if the failed res is for ROM BAR, and it will |
@@ -112,16 +197,25 @@ static void __assign_resources_sorted(struct resource_list *head, | |||
112 | (!(res->flags & IORESOURCE_ROM_ENABLE)))) | 197 | (!(res->flags & IORESOURCE_ROM_ENABLE)))) |
113 | add_to_failed_list(fail_head, list->dev, res); | 198 | add_to_failed_list(fail_head, list->dev, res); |
114 | } | 199 | } |
115 | res->start = 0; | 200 | reset_resource(res); |
116 | res->end = 0; | ||
117 | res->flags = 0; | ||
118 | } | 201 | } |
119 | tmp = list; | ||
120 | list = list->next; | ||
121 | kfree(tmp); | ||
122 | } | 202 | } |
123 | } | 203 | } |
124 | 204 | ||
205 | static void __assign_resources_sorted(struct resource_list *head, | ||
206 | struct resource_list_x *add_head, | ||
207 | struct resource_list_x *fail_head) | ||
208 | { | ||
209 | /* Satisfy the must-have resource requests */ | ||
210 | assign_requested_resources_sorted(head, fail_head); | ||
211 | |||
212 | /* Try to satisfy any additional nice-to-have resource | ||
213 | requests */ | ||
214 | if (add_head) | ||
215 | adjust_resources_sorted(add_head, head); | ||
216 | free_list(resource_list, head); | ||
217 | } | ||
218 | |||
125 | static void pdev_assign_resources_sorted(struct pci_dev *dev, | 219 | static void pdev_assign_resources_sorted(struct pci_dev *dev, |
126 | struct resource_list_x *fail_head) | 220 | struct resource_list_x *fail_head) |
127 | { | 221 | { |
@@ -129,11 +223,12 @@ static void pdev_assign_resources_sorted(struct pci_dev *dev, | |||
129 | 223 | ||
130 | head.next = NULL; | 224 | head.next = NULL; |
131 | __dev_sort_resources(dev, &head); | 225 | __dev_sort_resources(dev, &head); |
132 | __assign_resources_sorted(&head, fail_head); | 226 | __assign_resources_sorted(&head, NULL, fail_head); |
133 | 227 | ||
134 | } | 228 | } |
135 | 229 | ||
136 | static void pbus_assign_resources_sorted(const struct pci_bus *bus, | 230 | static void pbus_assign_resources_sorted(const struct pci_bus *bus, |
231 | struct resource_list_x *add_head, | ||
137 | struct resource_list_x *fail_head) | 232 | struct resource_list_x *fail_head) |
138 | { | 233 | { |
139 | struct pci_dev *dev; | 234 | struct pci_dev *dev; |
@@ -143,7 +238,7 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus, | |||
143 | list_for_each_entry(dev, &bus->devices, bus_list) | 238 | list_for_each_entry(dev, &bus->devices, bus_list) |
144 | __dev_sort_resources(dev, &head); | 239 | __dev_sort_resources(dev, &head); |
145 | 240 | ||
146 | __assign_resources_sorted(&head, fail_head); | 241 | __assign_resources_sorted(&head, add_head, fail_head); |
147 | } | 242 | } |
148 | 243 | ||
149 | void pci_setup_cardbus(struct pci_bus *bus) | 244 | void pci_setup_cardbus(struct pci_bus *bus) |
@@ -404,15 +499,62 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon | |||
404 | return NULL; | 499 | return NULL; |
405 | } | 500 | } |
406 | 501 | ||
407 | /* Sizing the IO windows of the PCI-PCI bridge is trivial, | 502 | static resource_size_t calculate_iosize(resource_size_t size, |
408 | since these windows have 4K granularity and the IO ranges | 503 | resource_size_t min_size, |
409 | of non-bridge PCI devices are limited to 256 bytes. | 504 | resource_size_t size1, |
410 | We must be careful with the ISA aliasing though. */ | 505 | resource_size_t old_size, |
411 | static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | 506 | resource_size_t align) |
507 | { | ||
508 | if (size < min_size) | ||
509 | size = min_size; | ||
510 | if (old_size == 1 ) | ||
511 | old_size = 0; | ||
512 | /* To be fixed in 2.5: we should have sort of HAVE_ISA | ||
513 | flag in the struct pci_bus. */ | ||
514 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) | ||
515 | size = (size & 0xff) + ((size & ~0xffUL) << 2); | ||
516 | #endif | ||
517 | size = ALIGN(size + size1, align); | ||
518 | if (size < old_size) | ||
519 | size = old_size; | ||
520 | return size; | ||
521 | } | ||
522 | |||
523 | static resource_size_t calculate_memsize(resource_size_t size, | ||
524 | resource_size_t min_size, | ||
525 | resource_size_t size1, | ||
526 | resource_size_t old_size, | ||
527 | resource_size_t align) | ||
528 | { | ||
529 | if (size < min_size) | ||
530 | size = min_size; | ||
531 | if (old_size == 1 ) | ||
532 | old_size = 0; | ||
533 | if (size < old_size) | ||
534 | size = old_size; | ||
535 | size = ALIGN(size + size1, align); | ||
536 | return size; | ||
537 | } | ||
538 | |||
539 | /** | ||
540 | * pbus_size_io() - size the io window of a given bus | ||
541 | * | ||
542 | * @bus : the bus | ||
543 | * @min_size : the minimum io window that must to be allocated | ||
544 | * @add_size : additional optional io window | ||
545 | * @add_head : track the additional io window on this list | ||
546 | * | ||
547 | * Sizing the IO windows of the PCI-PCI bridge is trivial, | ||
548 | * since these windows have 4K granularity and the IO ranges | ||
549 | * of non-bridge PCI devices are limited to 256 bytes. | ||
550 | * We must be careful with the ISA aliasing though. | ||
551 | */ | ||
552 | static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, | ||
553 | resource_size_t add_size, struct resource_list_x *add_head) | ||
412 | { | 554 | { |
413 | struct pci_dev *dev; | 555 | struct pci_dev *dev; |
414 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); | 556 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); |
415 | unsigned long size = 0, size1 = 0, old_size; | 557 | unsigned long size = 0, size0 = 0, size1 = 0; |
416 | 558 | ||
417 | if (!b_res) | 559 | if (!b_res) |
418 | return; | 560 | return; |
@@ -435,20 +577,12 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | |||
435 | size1 += r_size; | 577 | size1 += r_size; |
436 | } | 578 | } |
437 | } | 579 | } |
438 | if (size < min_size) | 580 | size0 = calculate_iosize(size, min_size, size1, |
439 | size = min_size; | 581 | resource_size(b_res), 4096); |
440 | old_size = resource_size(b_res); | 582 | size1 = !add_size? size0: |
441 | if (old_size == 1) | 583 | calculate_iosize(size, min_size+add_size, size1, |
442 | old_size = 0; | 584 | resource_size(b_res), 4096); |
443 | /* To be fixed in 2.5: we should have sort of HAVE_ISA | 585 | if (!size0 && !size1) { |
444 | flag in the struct pci_bus. */ | ||
445 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) | ||
446 | size = (size & 0xff) + ((size & ~0xffUL) << 2); | ||
447 | #endif | ||
448 | size = ALIGN(size + size1, 4096); | ||
449 | if (size < old_size) | ||
450 | size = old_size; | ||
451 | if (!size) { | ||
452 | if (b_res->start || b_res->end) | 586 | if (b_res->start || b_res->end) |
453 | dev_info(&bus->self->dev, "disabling bridge window " | 587 | dev_info(&bus->self->dev, "disabling bridge window " |
454 | "%pR to [bus %02x-%02x] (unused)\n", b_res, | 588 | "%pR to [bus %02x-%02x] (unused)\n", b_res, |
@@ -458,17 +592,30 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | |||
458 | } | 592 | } |
459 | /* Alignment of the IO window is always 4K */ | 593 | /* Alignment of the IO window is always 4K */ |
460 | b_res->start = 4096; | 594 | b_res->start = 4096; |
461 | b_res->end = b_res->start + size - 1; | 595 | b_res->end = b_res->start + size0 - 1; |
462 | b_res->flags |= IORESOURCE_STARTALIGN; | 596 | b_res->flags |= IORESOURCE_STARTALIGN; |
597 | if (size1 > size0 && add_head) | ||
598 | add_to_list(add_head, bus->self, b_res, size1-size0); | ||
463 | } | 599 | } |
464 | 600 | ||
465 | /* Calculate the size of the bus and minimal alignment which | 601 | /** |
466 | guarantees that all child resources fit in this size. */ | 602 | * pbus_size_mem() - size the memory window of a given bus |
603 | * | ||
604 | * @bus : the bus | ||
605 | * @min_size : the minimum memory window that must to be allocated | ||
606 | * @add_size : additional optional memory window | ||
607 | * @add_head : track the additional memory window on this list | ||
608 | * | ||
609 | * Calculate the size of the bus and minimal alignment which | ||
610 | * guarantees that all child resources fit in this size. | ||
611 | */ | ||
467 | static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | 612 | static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, |
468 | unsigned long type, resource_size_t min_size) | 613 | unsigned long type, resource_size_t min_size, |
614 | resource_size_t add_size, | ||
615 | struct resource_list_x *add_head) | ||
469 | { | 616 | { |
470 | struct pci_dev *dev; | 617 | struct pci_dev *dev; |
471 | resource_size_t min_align, align, size, old_size; | 618 | resource_size_t min_align, align, size, size0, size1; |
472 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ | 619 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ |
473 | int order, max_order; | 620 | int order, max_order; |
474 | struct resource *b_res = find_free_bus_resource(bus, type); | 621 | struct resource *b_res = find_free_bus_resource(bus, type); |
@@ -516,14 +663,6 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
516 | mem64_mask &= r->flags & IORESOURCE_MEM_64; | 663 | mem64_mask &= r->flags & IORESOURCE_MEM_64; |
517 | } | 664 | } |
518 | } | 665 | } |
519 | if (size < min_size) | ||
520 | size = min_size; | ||
521 | old_size = resource_size(b_res); | ||
522 | if (old_size == 1) | ||
523 | old_size = 0; | ||
524 | if (size < old_size) | ||
525 | size = old_size; | ||
526 | |||
527 | align = 0; | 666 | align = 0; |
528 | min_align = 0; | 667 | min_align = 0; |
529 | for (order = 0; order <= max_order; order++) { | 668 | for (order = 0; order <= max_order; order++) { |
@@ -537,8 +676,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
537 | min_align = align1 >> 1; | 676 | min_align = align1 >> 1; |
538 | align += aligns[order]; | 677 | align += aligns[order]; |
539 | } | 678 | } |
540 | size = ALIGN(size, min_align); | 679 | size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), align); |
541 | if (!size) { | 680 | size1 = !add_size ? size : |
681 | calculate_memsize(size, min_size+add_size, 0, | ||
682 | resource_size(b_res), align); | ||
683 | if (!size0 && !size1) { | ||
542 | if (b_res->start || b_res->end) | 684 | if (b_res->start || b_res->end) |
543 | dev_info(&bus->self->dev, "disabling bridge window " | 685 | dev_info(&bus->self->dev, "disabling bridge window " |
544 | "%pR to [bus %02x-%02x] (unused)\n", b_res, | 686 | "%pR to [bus %02x-%02x] (unused)\n", b_res, |
@@ -547,9 +689,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
547 | return 1; | 689 | return 1; |
548 | } | 690 | } |
549 | b_res->start = min_align; | 691 | b_res->start = min_align; |
550 | b_res->end = size + min_align - 1; | 692 | b_res->end = size0 + min_align - 1; |
551 | b_res->flags |= IORESOURCE_STARTALIGN; | 693 | b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask; |
552 | b_res->flags |= mem64_mask; | 694 | if (size1 > size0 && add_head) |
695 | add_to_list(add_head, bus->self, b_res, size1-size0); | ||
553 | return 1; | 696 | return 1; |
554 | } | 697 | } |
555 | 698 | ||
@@ -602,11 +745,12 @@ static void pci_bus_size_cardbus(struct pci_bus *bus) | |||
602 | } | 745 | } |
603 | } | 746 | } |
604 | 747 | ||
605 | void __ref pci_bus_size_bridges(struct pci_bus *bus) | 748 | void __ref __pci_bus_size_bridges(struct pci_bus *bus, |
749 | struct resource_list_x *add_head) | ||
606 | { | 750 | { |
607 | struct pci_dev *dev; | 751 | struct pci_dev *dev; |
608 | unsigned long mask, prefmask; | 752 | unsigned long mask, prefmask; |
609 | resource_size_t min_mem_size = 0, min_io_size = 0; | 753 | resource_size_t additional_mem_size = 0, additional_io_size = 0; |
610 | 754 | ||
611 | list_for_each_entry(dev, &bus->devices, bus_list) { | 755 | list_for_each_entry(dev, &bus->devices, bus_list) { |
612 | struct pci_bus *b = dev->subordinate; | 756 | struct pci_bus *b = dev->subordinate; |
@@ -620,7 +764,7 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) | |||
620 | 764 | ||
621 | case PCI_CLASS_BRIDGE_PCI: | 765 | case PCI_CLASS_BRIDGE_PCI: |
622 | default: | 766 | default: |
623 | pci_bus_size_bridges(b); | 767 | __pci_bus_size_bridges(b, add_head); |
624 | break; | 768 | break; |
625 | } | 769 | } |
626 | } | 770 | } |
@@ -637,11 +781,14 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) | |||
637 | case PCI_CLASS_BRIDGE_PCI: | 781 | case PCI_CLASS_BRIDGE_PCI: |
638 | pci_bridge_check_ranges(bus); | 782 | pci_bridge_check_ranges(bus); |
639 | if (bus->self->is_hotplug_bridge) { | 783 | if (bus->self->is_hotplug_bridge) { |
640 | min_io_size = pci_hotplug_io_size; | 784 | additional_io_size = pci_hotplug_io_size; |
641 | min_mem_size = pci_hotplug_mem_size; | 785 | additional_mem_size = pci_hotplug_mem_size; |
642 | } | 786 | } |
787 | /* | ||
788 | * Follow thru | ||
789 | */ | ||
643 | default: | 790 | default: |
644 | pbus_size_io(bus, min_io_size); | 791 | pbus_size_io(bus, 0, additional_io_size, add_head); |
645 | /* If the bridge supports prefetchable range, size it | 792 | /* If the bridge supports prefetchable range, size it |
646 | separately. If it doesn't, or its prefetchable window | 793 | separately. If it doesn't, or its prefetchable window |
647 | has already been allocated by arch code, try | 794 | has already been allocated by arch code, try |
@@ -649,30 +796,36 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) | |||
649 | resources. */ | 796 | resources. */ |
650 | mask = IORESOURCE_MEM; | 797 | mask = IORESOURCE_MEM; |
651 | prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; | 798 | prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; |
652 | if (pbus_size_mem(bus, prefmask, prefmask, min_mem_size)) | 799 | if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, add_head)) |
653 | mask = prefmask; /* Success, size non-prefetch only. */ | 800 | mask = prefmask; /* Success, size non-prefetch only. */ |
654 | else | 801 | else |
655 | min_mem_size += min_mem_size; | 802 | additional_mem_size += additional_mem_size; |
656 | pbus_size_mem(bus, mask, IORESOURCE_MEM, min_mem_size); | 803 | pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, add_head); |
657 | break; | 804 | break; |
658 | } | 805 | } |
659 | } | 806 | } |
807 | |||
808 | void __ref pci_bus_size_bridges(struct pci_bus *bus) | ||
809 | { | ||
810 | __pci_bus_size_bridges(bus, NULL); | ||
811 | } | ||
660 | EXPORT_SYMBOL(pci_bus_size_bridges); | 812 | EXPORT_SYMBOL(pci_bus_size_bridges); |
661 | 813 | ||
662 | static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, | 814 | static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, |
815 | struct resource_list_x *add_head, | ||
663 | struct resource_list_x *fail_head) | 816 | struct resource_list_x *fail_head) |
664 | { | 817 | { |
665 | struct pci_bus *b; | 818 | struct pci_bus *b; |
666 | struct pci_dev *dev; | 819 | struct pci_dev *dev; |
667 | 820 | ||
668 | pbus_assign_resources_sorted(bus, fail_head); | 821 | pbus_assign_resources_sorted(bus, add_head, fail_head); |
669 | 822 | ||
670 | list_for_each_entry(dev, &bus->devices, bus_list) { | 823 | list_for_each_entry(dev, &bus->devices, bus_list) { |
671 | b = dev->subordinate; | 824 | b = dev->subordinate; |
672 | if (!b) | 825 | if (!b) |
673 | continue; | 826 | continue; |
674 | 827 | ||
675 | __pci_bus_assign_resources(b, fail_head); | 828 | __pci_bus_assign_resources(b, add_head, fail_head); |
676 | 829 | ||
677 | switch (dev->class >> 8) { | 830 | switch (dev->class >> 8) { |
678 | case PCI_CLASS_BRIDGE_PCI: | 831 | case PCI_CLASS_BRIDGE_PCI: |
@@ -694,7 +847,7 @@ static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, | |||
694 | 847 | ||
695 | void __ref pci_bus_assign_resources(const struct pci_bus *bus) | 848 | void __ref pci_bus_assign_resources(const struct pci_bus *bus) |
696 | { | 849 | { |
697 | __pci_bus_assign_resources(bus, NULL); | 850 | __pci_bus_assign_resources(bus, NULL, NULL); |
698 | } | 851 | } |
699 | EXPORT_SYMBOL(pci_bus_assign_resources); | 852 | EXPORT_SYMBOL(pci_bus_assign_resources); |
700 | 853 | ||
@@ -709,7 +862,7 @@ static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge, | |||
709 | if (!b) | 862 | if (!b) |
710 | return; | 863 | return; |
711 | 864 | ||
712 | __pci_bus_assign_resources(b, fail_head); | 865 | __pci_bus_assign_resources(b, NULL, fail_head); |
713 | 866 | ||
714 | switch (bridge->class >> 8) { | 867 | switch (bridge->class >> 8) { |
715 | case PCI_CLASS_BRIDGE_PCI: | 868 | case PCI_CLASS_BRIDGE_PCI: |
@@ -842,17 +995,21 @@ void __init | |||
842 | pci_assign_unassigned_resources(void) | 995 | pci_assign_unassigned_resources(void) |
843 | { | 996 | { |
844 | struct pci_bus *bus; | 997 | struct pci_bus *bus; |
845 | 998 | struct resource_list_x add_list; /* list of resources that | |
999 | want additional resources */ | ||
1000 | add_list.next = NULL; | ||
846 | /* Depth first, calculate sizes and alignments of all | 1001 | /* Depth first, calculate sizes and alignments of all |
847 | subordinate buses. */ | 1002 | subordinate buses. */ |
848 | list_for_each_entry(bus, &pci_root_buses, node) { | 1003 | list_for_each_entry(bus, &pci_root_buses, node) { |
849 | pci_bus_size_bridges(bus); | 1004 | __pci_bus_size_bridges(bus, &add_list); |
850 | } | 1005 | } |
1006 | |||
851 | /* Depth last, allocate resources and update the hardware. */ | 1007 | /* Depth last, allocate resources and update the hardware. */ |
852 | list_for_each_entry(bus, &pci_root_buses, node) { | 1008 | list_for_each_entry(bus, &pci_root_buses, node) { |
853 | pci_bus_assign_resources(bus); | 1009 | __pci_bus_assign_resources(bus, &add_list, NULL); |
854 | pci_enable_bridges(bus); | 1010 | pci_enable_bridges(bus); |
855 | } | 1011 | } |
1012 | BUG_ON(add_list.next); | ||
856 | 1013 | ||
857 | /* dump the resource on buses */ | 1014 | /* dump the resource on buses */ |
858 | list_for_each_entry(bus, &pci_root_buses, node) { | 1015 | list_for_each_entry(bus, &pci_root_buses, node) { |
@@ -882,7 +1039,7 @@ again: | |||
882 | 1039 | ||
883 | if (tried_times >= 2) { | 1040 | if (tried_times >= 2) { |
884 | /* still fail, don't need to try more */ | 1041 | /* still fail, don't need to try more */ |
885 | free_failed_list(&head); | 1042 | free_list(resource_list_x, &head); |
886 | goto enable_all; | 1043 | goto enable_all; |
887 | } | 1044 | } |
888 | 1045 | ||
@@ -913,7 +1070,7 @@ again: | |||
913 | 1070 | ||
914 | list = list->next; | 1071 | list = list->next; |
915 | } | 1072 | } |
916 | free_failed_list(&head); | 1073 | free_list(resource_list_x, &head); |
917 | 1074 | ||
918 | goto again; | 1075 | goto again; |
919 | 1076 | ||