diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/setup-bus.c | 231 |
1 files changed, 184 insertions, 47 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index a94ecc161208..89d0a6a88df7 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -33,6 +33,7 @@ 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 | ||
@@ -46,8 +47,18 @@ struct resource_list_x { | |||
46 | (head)->next = NULL; \ | 47 | (head)->next = NULL; \ |
47 | } while (0) | 48 | } while (0) |
48 | 49 | ||
49 | static void add_to_failed_list(struct resource_list_x *head, | 50 | /** |
50 | struct pci_dev *dev, struct resource *res) | 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) | ||
51 | { | 62 | { |
52 | struct resource_list_x *list = head; | 63 | struct resource_list_x *list = head; |
53 | struct resource_list_x *ln = list->next; | 64 | struct resource_list_x *ln = list->next; |
@@ -55,7 +66,7 @@ static void add_to_failed_list(struct resource_list_x *head, | |||
55 | 66 | ||
56 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); | 67 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); |
57 | if (!tmp) { | 68 | if (!tmp) { |
58 | pr_warning("add_to_failed_list: kmalloc() failed!\n"); | 69 | pr_warning("add_to_list: kmalloc() failed!\n"); |
59 | return; | 70 | return; |
60 | } | 71 | } |
61 | 72 | ||
@@ -65,9 +76,16 @@ static void add_to_failed_list(struct resource_list_x *head, | |||
65 | tmp->start = res->start; | 76 | tmp->start = res->start; |
66 | tmp->end = res->end; | 77 | tmp->end = res->end; |
67 | tmp->flags = res->flags; | 78 | tmp->flags = res->flags; |
79 | tmp->add_size = add_size; | ||
68 | list->next = tmp; | 80 | list->next = tmp; |
69 | } | 81 | } |
70 | 82 | ||
83 | static void add_to_failed_list(struct resource_list_x *head, | ||
84 | struct pci_dev *dev, struct resource *res) | ||
85 | { | ||
86 | add_to_list(head, dev, res, 0); | ||
87 | } | ||
88 | |||
71 | static void __dev_sort_resources(struct pci_dev *dev, | 89 | static void __dev_sort_resources(struct pci_dev *dev, |
72 | struct resource_list *head) | 90 | struct resource_list *head) |
73 | { | 91 | { |
@@ -95,18 +113,81 @@ static inline void reset_resource(struct resource *res) | |||
95 | res->flags = 0; | 113 | res->flags = 0; |
96 | } | 114 | } |
97 | 115 | ||
98 | static void __assign_resources_sorted(struct resource_list *head, | 116 | /** |
99 | struct resource_list_x *fail_head) | 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) | ||
100 | { | 130 | { |
101 | struct resource *res; | 131 | struct resource *res; |
102 | struct resource_list *list, *tmp; | 132 | struct resource_list_x *list, *tmp, *prev; |
133 | struct resource_list *hlist; | ||
134 | resource_size_t add_size; | ||
103 | int idx; | 135 | int idx; |
104 | 136 | ||
105 | for (list = head->next; list;) { | 137 | prev = add_head; |
138 | for (list = add_head->next; list;) { | ||
106 | 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 | |||
107 | 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; | ||
108 | 186 | ||
109 | 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)) { | ||
110 | if (fail_head && !pci_is_root_bus(list->dev->bus)) { | 191 | if (fail_head && !pci_is_root_bus(list->dev->bus)) { |
111 | /* | 192 | /* |
112 | * if the failed res is for ROM BAR, and it will | 193 | * if the failed res is for ROM BAR, and it will |
@@ -118,12 +199,23 @@ static void __assign_resources_sorted(struct resource_list *head, | |||
118 | } | 199 | } |
119 | reset_resource(res); | 200 | reset_resource(res); |
120 | } | 201 | } |
121 | tmp = list; | ||
122 | list = list->next; | ||
123 | kfree(tmp); | ||
124 | } | 202 | } |
125 | } | 203 | } |
126 | 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 | |||
127 | static void pdev_assign_resources_sorted(struct pci_dev *dev, | 219 | static void pdev_assign_resources_sorted(struct pci_dev *dev, |
128 | struct resource_list_x *fail_head) | 220 | struct resource_list_x *fail_head) |
129 | { | 221 | { |
@@ -131,11 +223,12 @@ static void pdev_assign_resources_sorted(struct pci_dev *dev, | |||
131 | 223 | ||
132 | head.next = NULL; | 224 | head.next = NULL; |
133 | __dev_sort_resources(dev, &head); | 225 | __dev_sort_resources(dev, &head); |
134 | __assign_resources_sorted(&head, fail_head); | 226 | __assign_resources_sorted(&head, NULL, fail_head); |
135 | 227 | ||
136 | } | 228 | } |
137 | 229 | ||
138 | 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, | ||
139 | struct resource_list_x *fail_head) | 232 | struct resource_list_x *fail_head) |
140 | { | 233 | { |
141 | struct pci_dev *dev; | 234 | struct pci_dev *dev; |
@@ -145,7 +238,7 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus, | |||
145 | list_for_each_entry(dev, &bus->devices, bus_list) | 238 | list_for_each_entry(dev, &bus->devices, bus_list) |
146 | __dev_sort_resources(dev, &head); | 239 | __dev_sort_resources(dev, &head); |
147 | 240 | ||
148 | __assign_resources_sorted(&head, fail_head); | 241 | __assign_resources_sorted(&head, add_head, fail_head); |
149 | } | 242 | } |
150 | 243 | ||
151 | void pci_setup_cardbus(struct pci_bus *bus) | 244 | void pci_setup_cardbus(struct pci_bus *bus) |
@@ -443,15 +536,25 @@ static resource_size_t calculate_memsize(resource_size_t size, | |||
443 | return size; | 536 | return size; |
444 | } | 537 | } |
445 | 538 | ||
446 | /* Sizing the IO windows of the PCI-PCI bridge is trivial, | 539 | /** |
447 | since these windows have 4K granularity and the IO ranges | 540 | * pbus_size_io() - size the io window of a given bus |
448 | of non-bridge PCI devices are limited to 256 bytes. | 541 | * |
449 | We must be careful with the ISA aliasing though. */ | 542 | * @bus : the bus |
450 | static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | 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) | ||
451 | { | 554 | { |
452 | struct pci_dev *dev; | 555 | struct pci_dev *dev; |
453 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); | 556 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); |
454 | unsigned long size = 0, size1 = 0; | 557 | unsigned long size = 0, size0 = 0, size1 = 0; |
455 | 558 | ||
456 | if (!b_res) | 559 | if (!b_res) |
457 | return; | 560 | return; |
@@ -474,9 +577,12 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | |||
474 | size1 += r_size; | 577 | size1 += r_size; |
475 | } | 578 | } |
476 | } | 579 | } |
477 | size = calculate_iosize(size, min_size, size1, | 580 | size0 = calculate_iosize(size, min_size, size1, |
581 | resource_size(b_res), 4096); | ||
582 | size1 = !add_size? size0: | ||
583 | calculate_iosize(size, min_size+add_size, size1, | ||
478 | resource_size(b_res), 4096); | 584 | resource_size(b_res), 4096); |
479 | if (!size) { | 585 | if (!size0 && !size1) { |
480 | if (b_res->start || b_res->end) | 586 | if (b_res->start || b_res->end) |
481 | dev_info(&bus->self->dev, "disabling bridge window " | 587 | dev_info(&bus->self->dev, "disabling bridge window " |
482 | "%pR to [bus %02x-%02x] (unused)\n", b_res, | 588 | "%pR to [bus %02x-%02x] (unused)\n", b_res, |
@@ -486,17 +592,30 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | |||
486 | } | 592 | } |
487 | /* Alignment of the IO window is always 4K */ | 593 | /* Alignment of the IO window is always 4K */ |
488 | b_res->start = 4096; | 594 | b_res->start = 4096; |
489 | b_res->end = b_res->start + size - 1; | 595 | b_res->end = b_res->start + size0 - 1; |
490 | 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); | ||
491 | } | 599 | } |
492 | 600 | ||
493 | /* Calculate the size of the bus and minimal alignment which | 601 | /** |
494 | 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 | */ | ||
495 | 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, |
496 | 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) | ||
497 | { | 616 | { |
498 | struct pci_dev *dev; | 617 | struct pci_dev *dev; |
499 | resource_size_t min_align, align, size; | 618 | resource_size_t min_align, align, size, size0, size1; |
500 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ | 619 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ |
501 | int order, max_order; | 620 | int order, max_order; |
502 | struct resource *b_res = find_free_bus_resource(bus, type); | 621 | struct resource *b_res = find_free_bus_resource(bus, type); |
@@ -557,8 +676,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
557 | min_align = align1 >> 1; | 676 | min_align = align1 >> 1; |
558 | align += aligns[order]; | 677 | align += aligns[order]; |
559 | } | 678 | } |
560 | size = calculate_memsize(size, min_size, 0, resource_size(b_res), align); | 679 | size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), align); |
561 | 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) { | ||
562 | if (b_res->start || b_res->end) | 684 | if (b_res->start || b_res->end) |
563 | dev_info(&bus->self->dev, "disabling bridge window " | 685 | dev_info(&bus->self->dev, "disabling bridge window " |
564 | "%pR to [bus %02x-%02x] (unused)\n", b_res, | 686 | "%pR to [bus %02x-%02x] (unused)\n", b_res, |
@@ -567,9 +689,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
567 | return 1; | 689 | return 1; |
568 | } | 690 | } |
569 | b_res->start = min_align; | 691 | b_res->start = min_align; |
570 | b_res->end = size + min_align - 1; | 692 | b_res->end = size0 + min_align - 1; |
571 | b_res->flags |= IORESOURCE_STARTALIGN; | 693 | b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask; |
572 | b_res->flags |= mem64_mask; | 694 | if (size1 > size0 && add_head) |
695 | add_to_list(add_head, bus->self, b_res, size1-size0); | ||
573 | return 1; | 696 | return 1; |
574 | } | 697 | } |
575 | 698 | ||
@@ -622,11 +745,12 @@ static void pci_bus_size_cardbus(struct pci_bus *bus) | |||
622 | } | 745 | } |
623 | } | 746 | } |
624 | 747 | ||
625 | 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) | ||
626 | { | 750 | { |
627 | struct pci_dev *dev; | 751 | struct pci_dev *dev; |
628 | unsigned long mask, prefmask; | 752 | unsigned long mask, prefmask; |
629 | resource_size_t min_mem_size = 0, min_io_size = 0; | 753 | resource_size_t additional_mem_size = 0, additional_io_size = 0; |
630 | 754 | ||
631 | list_for_each_entry(dev, &bus->devices, bus_list) { | 755 | list_for_each_entry(dev, &bus->devices, bus_list) { |
632 | struct pci_bus *b = dev->subordinate; | 756 | struct pci_bus *b = dev->subordinate; |
@@ -640,7 +764,7 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) | |||
640 | 764 | ||
641 | case PCI_CLASS_BRIDGE_PCI: | 765 | case PCI_CLASS_BRIDGE_PCI: |
642 | default: | 766 | default: |
643 | pci_bus_size_bridges(b); | 767 | __pci_bus_size_bridges(b, add_head); |
644 | break; | 768 | break; |
645 | } | 769 | } |
646 | } | 770 | } |
@@ -657,11 +781,14 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) | |||
657 | case PCI_CLASS_BRIDGE_PCI: | 781 | case PCI_CLASS_BRIDGE_PCI: |
658 | pci_bridge_check_ranges(bus); | 782 | pci_bridge_check_ranges(bus); |
659 | if (bus->self->is_hotplug_bridge) { | 783 | if (bus->self->is_hotplug_bridge) { |
660 | min_io_size = pci_hotplug_io_size; | 784 | additional_io_size = pci_hotplug_io_size; |
661 | min_mem_size = pci_hotplug_mem_size; | 785 | additional_mem_size = pci_hotplug_mem_size; |
662 | } | 786 | } |
787 | /* | ||
788 | * Follow thru | ||
789 | */ | ||
663 | default: | 790 | default: |
664 | pbus_size_io(bus, min_io_size); | 791 | pbus_size_io(bus, 0, additional_io_size, add_head); |
665 | /* If the bridge supports prefetchable range, size it | 792 | /* If the bridge supports prefetchable range, size it |
666 | separately. If it doesn't, or its prefetchable window | 793 | separately. If it doesn't, or its prefetchable window |
667 | has already been allocated by arch code, try | 794 | has already been allocated by arch code, try |
@@ -669,30 +796,36 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) | |||
669 | resources. */ | 796 | resources. */ |
670 | mask = IORESOURCE_MEM; | 797 | mask = IORESOURCE_MEM; |
671 | prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; | 798 | prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; |
672 | if (pbus_size_mem(bus, prefmask, prefmask, min_mem_size)) | 799 | if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, add_head)) |
673 | mask = prefmask; /* Success, size non-prefetch only. */ | 800 | mask = prefmask; /* Success, size non-prefetch only. */ |
674 | else | 801 | else |
675 | min_mem_size += min_mem_size; | 802 | additional_mem_size += additional_mem_size; |
676 | pbus_size_mem(bus, mask, IORESOURCE_MEM, min_mem_size); | 803 | pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, add_head); |
677 | break; | 804 | break; |
678 | } | 805 | } |
679 | } | 806 | } |
807 | |||
808 | void __ref pci_bus_size_bridges(struct pci_bus *bus) | ||
809 | { | ||
810 | __pci_bus_size_bridges(bus, NULL); | ||
811 | } | ||
680 | EXPORT_SYMBOL(pci_bus_size_bridges); | 812 | EXPORT_SYMBOL(pci_bus_size_bridges); |
681 | 813 | ||
682 | 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, | ||
683 | struct resource_list_x *fail_head) | 816 | struct resource_list_x *fail_head) |
684 | { | 817 | { |
685 | struct pci_bus *b; | 818 | struct pci_bus *b; |
686 | struct pci_dev *dev; | 819 | struct pci_dev *dev; |
687 | 820 | ||
688 | pbus_assign_resources_sorted(bus, fail_head); | 821 | pbus_assign_resources_sorted(bus, add_head, fail_head); |
689 | 822 | ||
690 | list_for_each_entry(dev, &bus->devices, bus_list) { | 823 | list_for_each_entry(dev, &bus->devices, bus_list) { |
691 | b = dev->subordinate; | 824 | b = dev->subordinate; |
692 | if (!b) | 825 | if (!b) |
693 | continue; | 826 | continue; |
694 | 827 | ||
695 | __pci_bus_assign_resources(b, fail_head); | 828 | __pci_bus_assign_resources(b, add_head, fail_head); |
696 | 829 | ||
697 | switch (dev->class >> 8) { | 830 | switch (dev->class >> 8) { |
698 | case PCI_CLASS_BRIDGE_PCI: | 831 | case PCI_CLASS_BRIDGE_PCI: |
@@ -714,7 +847,7 @@ static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, | |||
714 | 847 | ||
715 | void __ref pci_bus_assign_resources(const struct pci_bus *bus) | 848 | void __ref pci_bus_assign_resources(const struct pci_bus *bus) |
716 | { | 849 | { |
717 | __pci_bus_assign_resources(bus, NULL); | 850 | __pci_bus_assign_resources(bus, NULL, NULL); |
718 | } | 851 | } |
719 | EXPORT_SYMBOL(pci_bus_assign_resources); | 852 | EXPORT_SYMBOL(pci_bus_assign_resources); |
720 | 853 | ||
@@ -729,7 +862,7 @@ static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge, | |||
729 | if (!b) | 862 | if (!b) |
730 | return; | 863 | return; |
731 | 864 | ||
732 | __pci_bus_assign_resources(b, fail_head); | 865 | __pci_bus_assign_resources(b, NULL, fail_head); |
733 | 866 | ||
734 | switch (bridge->class >> 8) { | 867 | switch (bridge->class >> 8) { |
735 | case PCI_CLASS_BRIDGE_PCI: | 868 | case PCI_CLASS_BRIDGE_PCI: |
@@ -862,17 +995,21 @@ void __init | |||
862 | pci_assign_unassigned_resources(void) | 995 | pci_assign_unassigned_resources(void) |
863 | { | 996 | { |
864 | struct pci_bus *bus; | 997 | struct pci_bus *bus; |
865 | 998 | struct resource_list_x add_list; /* list of resources that | |
999 | want additional resources */ | ||
1000 | add_list.next = NULL; | ||
866 | /* Depth first, calculate sizes and alignments of all | 1001 | /* Depth first, calculate sizes and alignments of all |
867 | subordinate buses. */ | 1002 | subordinate buses. */ |
868 | list_for_each_entry(bus, &pci_root_buses, node) { | 1003 | list_for_each_entry(bus, &pci_root_buses, node) { |
869 | pci_bus_size_bridges(bus); | 1004 | __pci_bus_size_bridges(bus, &add_list); |
870 | } | 1005 | } |
1006 | |||
871 | /* Depth last, allocate resources and update the hardware. */ | 1007 | /* Depth last, allocate resources and update the hardware. */ |
872 | list_for_each_entry(bus, &pci_root_buses, node) { | 1008 | list_for_each_entry(bus, &pci_root_buses, node) { |
873 | pci_bus_assign_resources(bus); | 1009 | __pci_bus_assign_resources(bus, &add_list, NULL); |
874 | pci_enable_bridges(bus); | 1010 | pci_enable_bridges(bus); |
875 | } | 1011 | } |
1012 | BUG_ON(add_list.next); | ||
876 | 1013 | ||
877 | /* dump the resource on buses */ | 1014 | /* dump the resource on buses */ |
878 | list_for_each_entry(bus, &pci_root_buses, node) { | 1015 | list_for_each_entry(bus, &pci_root_buses, node) { |