diff options
| -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 a94ecc16120..89d0a6a88df 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) { |
