diff options
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r-- | drivers/pci/setup-bus.c | 506 |
1 files changed, 454 insertions, 52 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index c48cd377b3f5..bf32f07c4efb 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -27,37 +27,83 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include "pci.h" | 28 | #include "pci.h" |
29 | 29 | ||
30 | static void pbus_assign_resources_sorted(const struct pci_bus *bus) | 30 | struct resource_list_x { |
31 | { | 31 | struct resource_list_x *next; |
32 | struct pci_dev *dev; | ||
33 | struct resource *res; | 32 | struct resource *res; |
34 | struct resource_list head, *list, *tmp; | 33 | struct pci_dev *dev; |
35 | int idx; | 34 | resource_size_t start; |
35 | resource_size_t end; | ||
36 | unsigned long flags; | ||
37 | }; | ||
36 | 38 | ||
37 | head.next = NULL; | 39 | static void add_to_failed_list(struct resource_list_x *head, |
38 | list_for_each_entry(dev, &bus->devices, bus_list) { | 40 | struct pci_dev *dev, struct resource *res) |
39 | u16 class = dev->class >> 8; | 41 | { |
42 | struct resource_list_x *list = head; | ||
43 | struct resource_list_x *ln = list->next; | ||
44 | struct resource_list_x *tmp; | ||
40 | 45 | ||
41 | /* Don't touch classless devices or host bridges or ioapics. */ | 46 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); |
42 | if (class == PCI_CLASS_NOT_DEFINED || | 47 | if (!tmp) { |
43 | class == PCI_CLASS_BRIDGE_HOST) | 48 | pr_warning("add_to_failed_list: kmalloc() failed!\n"); |
44 | continue; | 49 | return; |
50 | } | ||
45 | 51 | ||
46 | /* Don't touch ioapic devices already enabled by firmware */ | 52 | tmp->next = ln; |
47 | if (class == PCI_CLASS_SYSTEM_PIC) { | 53 | tmp->res = res; |
48 | u16 command; | 54 | tmp->dev = dev; |
49 | pci_read_config_word(dev, PCI_COMMAND, &command); | 55 | tmp->start = res->start; |
50 | if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | 56 | tmp->end = res->end; |
51 | continue; | 57 | tmp->flags = res->flags; |
52 | } | 58 | list->next = tmp; |
59 | } | ||
60 | |||
61 | static void free_failed_list(struct resource_list_x *head) | ||
62 | { | ||
63 | struct resource_list_x *list, *tmp; | ||
53 | 64 | ||
54 | pdev_sort_resources(dev, &head); | 65 | for (list = head->next; list;) { |
66 | tmp = list; | ||
67 | list = list->next; | ||
68 | kfree(tmp); | ||
55 | } | 69 | } |
56 | 70 | ||
57 | for (list = head.next; list;) { | 71 | head->next = NULL; |
72 | } | ||
73 | |||
74 | static void __dev_sort_resources(struct pci_dev *dev, | ||
75 | struct resource_list *head) | ||
76 | { | ||
77 | u16 class = dev->class >> 8; | ||
78 | |||
79 | /* Don't touch classless devices or host bridges or ioapics. */ | ||
80 | if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST) | ||
81 | return; | ||
82 | |||
83 | /* Don't touch ioapic devices already enabled by firmware */ | ||
84 | if (class == PCI_CLASS_SYSTEM_PIC) { | ||
85 | u16 command; | ||
86 | pci_read_config_word(dev, PCI_COMMAND, &command); | ||
87 | if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | pdev_sort_resources(dev, head); | ||
92 | } | ||
93 | |||
94 | static void __assign_resources_sorted(struct resource_list *head, | ||
95 | struct resource_list_x *fail_head) | ||
96 | { | ||
97 | struct resource *res; | ||
98 | struct resource_list *list, *tmp; | ||
99 | int idx; | ||
100 | |||
101 | for (list = head->next; list;) { | ||
58 | res = list->res; | 102 | res = list->res; |
59 | idx = res - &list->dev->resource[0]; | 103 | idx = res - &list->dev->resource[0]; |
60 | if (pci_assign_resource(list->dev, idx)) { | 104 | if (pci_assign_resource(list->dev, idx)) { |
105 | if (fail_head && !pci_is_root_bus(list->dev->bus)) | ||
106 | add_to_failed_list(fail_head, list->dev, res); | ||
61 | res->start = 0; | 107 | res->start = 0; |
62 | res->end = 0; | 108 | res->end = 0; |
63 | res->flags = 0; | 109 | res->flags = 0; |
@@ -68,6 +114,30 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus) | |||
68 | } | 114 | } |
69 | } | 115 | } |
70 | 116 | ||
117 | static void pdev_assign_resources_sorted(struct pci_dev *dev, | ||
118 | struct resource_list_x *fail_head) | ||
119 | { | ||
120 | struct resource_list head; | ||
121 | |||
122 | head.next = NULL; | ||
123 | __dev_sort_resources(dev, &head); | ||
124 | __assign_resources_sorted(&head, fail_head); | ||
125 | |||
126 | } | ||
127 | |||
128 | static void pbus_assign_resources_sorted(const struct pci_bus *bus, | ||
129 | struct resource_list_x *fail_head) | ||
130 | { | ||
131 | struct pci_dev *dev; | ||
132 | struct resource_list head; | ||
133 | |||
134 | head.next = NULL; | ||
135 | list_for_each_entry(dev, &bus->devices, bus_list) | ||
136 | __dev_sort_resources(dev, &head); | ||
137 | |||
138 | __assign_resources_sorted(&head, fail_head); | ||
139 | } | ||
140 | |||
71 | void pci_setup_cardbus(struct pci_bus *bus) | 141 | void pci_setup_cardbus(struct pci_bus *bus) |
72 | { | 142 | { |
73 | struct pci_dev *bridge = bus->self; | 143 | struct pci_dev *bridge = bus->self; |
@@ -134,18 +204,12 @@ EXPORT_SYMBOL(pci_setup_cardbus); | |||
134 | config space writes, so it's quite possible that an I/O window of | 204 | config space writes, so it's quite possible that an I/O window of |
135 | the bridge will have some undesirable address (e.g. 0) after the | 205 | the bridge will have some undesirable address (e.g. 0) after the |
136 | first write. Ditto 64-bit prefetchable MMIO. */ | 206 | first write. Ditto 64-bit prefetchable MMIO. */ |
137 | static void pci_setup_bridge(struct pci_bus *bus) | 207 | static void pci_setup_bridge_io(struct pci_bus *bus) |
138 | { | 208 | { |
139 | struct pci_dev *bridge = bus->self; | 209 | struct pci_dev *bridge = bus->self; |
140 | struct resource *res; | 210 | struct resource *res; |
141 | struct pci_bus_region region; | 211 | struct pci_bus_region region; |
142 | u32 l, bu, lu, io_upper16; | 212 | u32 l, io_upper16; |
143 | |||
144 | if (pci_is_enabled(bridge)) | ||
145 | return; | ||
146 | |||
147 | dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n", | ||
148 | bus->secondary, bus->subordinate); | ||
149 | 213 | ||
150 | /* Set up the top and bottom of the PCI I/O segment for this bus. */ | 214 | /* Set up the top and bottom of the PCI I/O segment for this bus. */ |
151 | res = bus->resource[0]; | 215 | res = bus->resource[0]; |
@@ -158,8 +222,7 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
158 | /* Set up upper 16 bits of I/O base/limit. */ | 222 | /* Set up upper 16 bits of I/O base/limit. */ |
159 | io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); | 223 | io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); |
160 | dev_info(&bridge->dev, " bridge window %pR\n", res); | 224 | dev_info(&bridge->dev, " bridge window %pR\n", res); |
161 | } | 225 | } else { |
162 | else { | ||
163 | /* Clear upper 16 bits of I/O base/limit. */ | 226 | /* Clear upper 16 bits of I/O base/limit. */ |
164 | io_upper16 = 0; | 227 | io_upper16 = 0; |
165 | l = 0x00f0; | 228 | l = 0x00f0; |
@@ -171,21 +234,35 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
171 | pci_write_config_dword(bridge, PCI_IO_BASE, l); | 234 | pci_write_config_dword(bridge, PCI_IO_BASE, l); |
172 | /* Update upper 16 bits of I/O base/limit. */ | 235 | /* Update upper 16 bits of I/O base/limit. */ |
173 | pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16); | 236 | pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16); |
237 | } | ||
174 | 238 | ||
175 | /* Set up the top and bottom of the PCI Memory segment | 239 | static void pci_setup_bridge_mmio(struct pci_bus *bus) |
176 | for this bus. */ | 240 | { |
241 | struct pci_dev *bridge = bus->self; | ||
242 | struct resource *res; | ||
243 | struct pci_bus_region region; | ||
244 | u32 l; | ||
245 | |||
246 | /* Set up the top and bottom of the PCI Memory segment for this bus. */ | ||
177 | res = bus->resource[1]; | 247 | res = bus->resource[1]; |
178 | pcibios_resource_to_bus(bridge, ®ion, res); | 248 | pcibios_resource_to_bus(bridge, ®ion, res); |
179 | if (res->flags & IORESOURCE_MEM) { | 249 | if (res->flags & IORESOURCE_MEM) { |
180 | l = (region.start >> 16) & 0xfff0; | 250 | l = (region.start >> 16) & 0xfff0; |
181 | l |= region.end & 0xfff00000; | 251 | l |= region.end & 0xfff00000; |
182 | dev_info(&bridge->dev, " bridge window %pR\n", res); | 252 | dev_info(&bridge->dev, " bridge window %pR\n", res); |
183 | } | 253 | } else { |
184 | else { | ||
185 | l = 0x0000fff0; | 254 | l = 0x0000fff0; |
186 | dev_info(&bridge->dev, " bridge window [mem disabled]\n"); | 255 | dev_info(&bridge->dev, " bridge window [mem disabled]\n"); |
187 | } | 256 | } |
188 | pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); | 257 | pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); |
258 | } | ||
259 | |||
260 | static void pci_setup_bridge_mmio_pref(struct pci_bus *bus) | ||
261 | { | ||
262 | struct pci_dev *bridge = bus->self; | ||
263 | struct resource *res; | ||
264 | struct pci_bus_region region; | ||
265 | u32 l, bu, lu; | ||
189 | 266 | ||
190 | /* Clear out the upper 32 bits of PREF limit. | 267 | /* Clear out the upper 32 bits of PREF limit. |
191 | If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily | 268 | If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily |
@@ -204,8 +281,7 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
204 | lu = upper_32_bits(region.end); | 281 | lu = upper_32_bits(region.end); |
205 | } | 282 | } |
206 | dev_info(&bridge->dev, " bridge window %pR\n", res); | 283 | dev_info(&bridge->dev, " bridge window %pR\n", res); |
207 | } | 284 | } else { |
208 | else { | ||
209 | l = 0x0000fff0; | 285 | l = 0x0000fff0; |
210 | dev_info(&bridge->dev, " bridge window [mem pref disabled]\n"); | 286 | dev_info(&bridge->dev, " bridge window [mem pref disabled]\n"); |
211 | } | 287 | } |
@@ -214,10 +290,35 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
214 | /* Set the upper 32 bits of PREF base & limit. */ | 290 | /* Set the upper 32 bits of PREF base & limit. */ |
215 | pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); | 291 | pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); |
216 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); | 292 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); |
293 | } | ||
294 | |||
295 | static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type) | ||
296 | { | ||
297 | struct pci_dev *bridge = bus->self; | ||
298 | |||
299 | dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n", | ||
300 | bus->secondary, bus->subordinate); | ||
301 | |||
302 | if (type & IORESOURCE_IO) | ||
303 | pci_setup_bridge_io(bus); | ||
304 | |||
305 | if (type & IORESOURCE_MEM) | ||
306 | pci_setup_bridge_mmio(bus); | ||
307 | |||
308 | if (type & IORESOURCE_PREFETCH) | ||
309 | pci_setup_bridge_mmio_pref(bus); | ||
217 | 310 | ||
218 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); | 311 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); |
219 | } | 312 | } |
220 | 313 | ||
314 | static void pci_setup_bridge(struct pci_bus *bus) | ||
315 | { | ||
316 | unsigned long type = IORESOURCE_IO | IORESOURCE_MEM | | ||
317 | IORESOURCE_PREFETCH; | ||
318 | |||
319 | __pci_setup_bridge(bus, type); | ||
320 | } | ||
321 | |||
221 | /* Check whether the bridge supports optional I/O and | 322 | /* Check whether the bridge supports optional I/O and |
222 | prefetchable memory ranges. If not, the respective | 323 | prefetchable memory ranges. If not, the respective |
223 | base/limit registers must be read-only and read as 0. */ | 324 | base/limit registers must be read-only and read as 0. */ |
@@ -253,8 +354,11 @@ static void pci_bridge_check_ranges(struct pci_bus *bus) | |||
253 | } | 354 | } |
254 | if (pmem) { | 355 | if (pmem) { |
255 | b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; | 356 | b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; |
256 | if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) | 357 | if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == |
358 | PCI_PREF_RANGE_TYPE_64) { | ||
257 | b_res[2].flags |= IORESOURCE_MEM_64; | 359 | b_res[2].flags |= IORESOURCE_MEM_64; |
360 | b_res[2].flags |= PCI_PREF_RANGE_TYPE_64; | ||
361 | } | ||
258 | } | 362 | } |
259 | 363 | ||
260 | /* double check if bridge does support 64 bit pref */ | 364 | /* double check if bridge does support 64 bit pref */ |
@@ -283,8 +387,7 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon | |||
283 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | 387 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | |
284 | IORESOURCE_PREFETCH; | 388 | IORESOURCE_PREFETCH; |
285 | 389 | ||
286 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 390 | pci_bus_for_each_resource(bus, r, i) { |
287 | r = bus->resource[i]; | ||
288 | if (r == &ioport_resource || r == &iomem_resource) | 391 | if (r == &ioport_resource || r == &iomem_resource) |
289 | continue; | 392 | continue; |
290 | if (r && (r->flags & type_mask) == type && !r->parent) | 393 | if (r && (r->flags & type_mask) == type && !r->parent) |
@@ -301,7 +404,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | |||
301 | { | 404 | { |
302 | struct pci_dev *dev; | 405 | struct pci_dev *dev; |
303 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); | 406 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); |
304 | unsigned long size = 0, size1 = 0; | 407 | unsigned long size = 0, size1 = 0, old_size; |
305 | 408 | ||
306 | if (!b_res) | 409 | if (!b_res) |
307 | return; | 410 | return; |
@@ -326,12 +429,17 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | |||
326 | } | 429 | } |
327 | if (size < min_size) | 430 | if (size < min_size) |
328 | size = min_size; | 431 | size = min_size; |
432 | old_size = resource_size(b_res); | ||
433 | if (old_size == 1) | ||
434 | old_size = 0; | ||
329 | /* To be fixed in 2.5: we should have sort of HAVE_ISA | 435 | /* To be fixed in 2.5: we should have sort of HAVE_ISA |
330 | flag in the struct pci_bus. */ | 436 | flag in the struct pci_bus. */ |
331 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) | 437 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) |
332 | size = (size & 0xff) + ((size & ~0xffUL) << 2); | 438 | size = (size & 0xff) + ((size & ~0xffUL) << 2); |
333 | #endif | 439 | #endif |
334 | size = ALIGN(size + size1, 4096); | 440 | size = ALIGN(size + size1, 4096); |
441 | if (size < old_size) | ||
442 | size = old_size; | ||
335 | if (!size) { | 443 | if (!size) { |
336 | if (b_res->start || b_res->end) | 444 | if (b_res->start || b_res->end) |
337 | dev_info(&bus->self->dev, "disabling bridge window " | 445 | dev_info(&bus->self->dev, "disabling bridge window " |
@@ -352,7 +460,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
352 | unsigned long type, resource_size_t min_size) | 460 | unsigned long type, resource_size_t min_size) |
353 | { | 461 | { |
354 | struct pci_dev *dev; | 462 | struct pci_dev *dev; |
355 | resource_size_t min_align, align, size; | 463 | resource_size_t min_align, align, size, old_size; |
356 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ | 464 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ |
357 | int order, max_order; | 465 | int order, max_order; |
358 | struct resource *b_res = find_free_bus_resource(bus, type); | 466 | struct resource *b_res = find_free_bus_resource(bus, type); |
@@ -402,6 +510,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
402 | } | 510 | } |
403 | if (size < min_size) | 511 | if (size < min_size) |
404 | size = min_size; | 512 | size = min_size; |
513 | old_size = resource_size(b_res); | ||
514 | if (old_size == 1) | ||
515 | old_size = 0; | ||
516 | if (size < old_size) | ||
517 | size = old_size; | ||
405 | 518 | ||
406 | align = 0; | 519 | align = 0; |
407 | min_align = 0; | 520 | min_align = 0; |
@@ -538,23 +651,25 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) | |||
538 | } | 651 | } |
539 | EXPORT_SYMBOL(pci_bus_size_bridges); | 652 | EXPORT_SYMBOL(pci_bus_size_bridges); |
540 | 653 | ||
541 | void __ref pci_bus_assign_resources(const struct pci_bus *bus) | 654 | static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, |
655 | struct resource_list_x *fail_head) | ||
542 | { | 656 | { |
543 | struct pci_bus *b; | 657 | struct pci_bus *b; |
544 | struct pci_dev *dev; | 658 | struct pci_dev *dev; |
545 | 659 | ||
546 | pbus_assign_resources_sorted(bus); | 660 | pbus_assign_resources_sorted(bus, fail_head); |
547 | 661 | ||
548 | list_for_each_entry(dev, &bus->devices, bus_list) { | 662 | list_for_each_entry(dev, &bus->devices, bus_list) { |
549 | b = dev->subordinate; | 663 | b = dev->subordinate; |
550 | if (!b) | 664 | if (!b) |
551 | continue; | 665 | continue; |
552 | 666 | ||
553 | pci_bus_assign_resources(b); | 667 | __pci_bus_assign_resources(b, fail_head); |
554 | 668 | ||
555 | switch (dev->class >> 8) { | 669 | switch (dev->class >> 8) { |
556 | case PCI_CLASS_BRIDGE_PCI: | 670 | case PCI_CLASS_BRIDGE_PCI: |
557 | pci_setup_bridge(b); | 671 | if (!pci_is_enabled(dev)) |
672 | pci_setup_bridge(b); | ||
558 | break; | 673 | break; |
559 | 674 | ||
560 | case PCI_CLASS_BRIDGE_CARDBUS: | 675 | case PCI_CLASS_BRIDGE_CARDBUS: |
@@ -568,15 +683,130 @@ void __ref pci_bus_assign_resources(const struct pci_bus *bus) | |||
568 | } | 683 | } |
569 | } | 684 | } |
570 | } | 685 | } |
686 | |||
687 | void __ref pci_bus_assign_resources(const struct pci_bus *bus) | ||
688 | { | ||
689 | __pci_bus_assign_resources(bus, NULL); | ||
690 | } | ||
571 | EXPORT_SYMBOL(pci_bus_assign_resources); | 691 | EXPORT_SYMBOL(pci_bus_assign_resources); |
572 | 692 | ||
693 | static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge, | ||
694 | struct resource_list_x *fail_head) | ||
695 | { | ||
696 | struct pci_bus *b; | ||
697 | |||
698 | pdev_assign_resources_sorted((struct pci_dev *)bridge, fail_head); | ||
699 | |||
700 | b = bridge->subordinate; | ||
701 | if (!b) | ||
702 | return; | ||
703 | |||
704 | __pci_bus_assign_resources(b, fail_head); | ||
705 | |||
706 | switch (bridge->class >> 8) { | ||
707 | case PCI_CLASS_BRIDGE_PCI: | ||
708 | pci_setup_bridge(b); | ||
709 | break; | ||
710 | |||
711 | case PCI_CLASS_BRIDGE_CARDBUS: | ||
712 | pci_setup_cardbus(b); | ||
713 | break; | ||
714 | |||
715 | default: | ||
716 | dev_info(&bridge->dev, "not setting up bridge for bus " | ||
717 | "%04x:%02x\n", pci_domain_nr(b), b->number); | ||
718 | break; | ||
719 | } | ||
720 | } | ||
721 | static void pci_bridge_release_resources(struct pci_bus *bus, | ||
722 | unsigned long type) | ||
723 | { | ||
724 | int idx; | ||
725 | bool changed = false; | ||
726 | struct pci_dev *dev; | ||
727 | struct resource *r; | ||
728 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | ||
729 | IORESOURCE_PREFETCH; | ||
730 | |||
731 | dev = bus->self; | ||
732 | for (idx = PCI_BRIDGE_RESOURCES; idx <= PCI_BRIDGE_RESOURCE_END; | ||
733 | idx++) { | ||
734 | r = &dev->resource[idx]; | ||
735 | if ((r->flags & type_mask) != type) | ||
736 | continue; | ||
737 | if (!r->parent) | ||
738 | continue; | ||
739 | /* | ||
740 | * if there are children under that, we should release them | ||
741 | * all | ||
742 | */ | ||
743 | release_child_resources(r); | ||
744 | if (!release_resource(r)) { | ||
745 | dev_printk(KERN_DEBUG, &dev->dev, | ||
746 | "resource %d %pR released\n", idx, r); | ||
747 | /* keep the old size */ | ||
748 | r->end = resource_size(r) - 1; | ||
749 | r->start = 0; | ||
750 | r->flags = 0; | ||
751 | changed = true; | ||
752 | } | ||
753 | } | ||
754 | |||
755 | if (changed) { | ||
756 | /* avoiding touch the one without PREF */ | ||
757 | if (type & IORESOURCE_PREFETCH) | ||
758 | type = IORESOURCE_PREFETCH; | ||
759 | __pci_setup_bridge(bus, type); | ||
760 | } | ||
761 | } | ||
762 | |||
763 | enum release_type { | ||
764 | leaf_only, | ||
765 | whole_subtree, | ||
766 | }; | ||
767 | /* | ||
768 | * try to release pci bridge resources that is from leaf bridge, | ||
769 | * so we can allocate big new one later | ||
770 | */ | ||
771 | static void __ref pci_bus_release_bridge_resources(struct pci_bus *bus, | ||
772 | unsigned long type, | ||
773 | enum release_type rel_type) | ||
774 | { | ||
775 | struct pci_dev *dev; | ||
776 | bool is_leaf_bridge = true; | ||
777 | |||
778 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
779 | struct pci_bus *b = dev->subordinate; | ||
780 | if (!b) | ||
781 | continue; | ||
782 | |||
783 | is_leaf_bridge = false; | ||
784 | |||
785 | if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) | ||
786 | continue; | ||
787 | |||
788 | if (rel_type == whole_subtree) | ||
789 | pci_bus_release_bridge_resources(b, type, | ||
790 | whole_subtree); | ||
791 | } | ||
792 | |||
793 | if (pci_is_root_bus(bus)) | ||
794 | return; | ||
795 | |||
796 | if ((bus->self->class >> 8) != PCI_CLASS_BRIDGE_PCI) | ||
797 | return; | ||
798 | |||
799 | if ((rel_type == whole_subtree) || is_leaf_bridge) | ||
800 | pci_bridge_release_resources(bus, type); | ||
801 | } | ||
802 | |||
573 | static void pci_bus_dump_res(struct pci_bus *bus) | 803 | static void pci_bus_dump_res(struct pci_bus *bus) |
574 | { | 804 | { |
575 | int i; | 805 | struct resource *res; |
806 | int i; | ||
576 | 807 | ||
577 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 808 | pci_bus_for_each_resource(bus, res, i) { |
578 | struct resource *res = bus->resource[i]; | 809 | if (!res || !res->end || !res->flags) |
579 | if (!res || !res->end) | ||
580 | continue; | 810 | continue; |
581 | 811 | ||
582 | dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res); | 812 | dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res); |
@@ -600,11 +830,65 @@ static void pci_bus_dump_resources(struct pci_bus *bus) | |||
600 | } | 830 | } |
601 | } | 831 | } |
602 | 832 | ||
833 | static int __init pci_bus_get_depth(struct pci_bus *bus) | ||
834 | { | ||
835 | int depth = 0; | ||
836 | struct pci_dev *dev; | ||
837 | |||
838 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
839 | int ret; | ||
840 | struct pci_bus *b = dev->subordinate; | ||
841 | if (!b) | ||
842 | continue; | ||
843 | |||
844 | ret = pci_bus_get_depth(b); | ||
845 | if (ret + 1 > depth) | ||
846 | depth = ret + 1; | ||
847 | } | ||
848 | |||
849 | return depth; | ||
850 | } | ||
851 | static int __init pci_get_max_depth(void) | ||
852 | { | ||
853 | int depth = 0; | ||
854 | struct pci_bus *bus; | ||
855 | |||
856 | list_for_each_entry(bus, &pci_root_buses, node) { | ||
857 | int ret; | ||
858 | |||
859 | ret = pci_bus_get_depth(bus); | ||
860 | if (ret > depth) | ||
861 | depth = ret; | ||
862 | } | ||
863 | |||
864 | return depth; | ||
865 | } | ||
866 | |||
867 | /* | ||
868 | * first try will not touch pci bridge res | ||
869 | * second and later try will clear small leaf bridge res | ||
870 | * will stop till to the max deepth if can not find good one | ||
871 | */ | ||
603 | void __init | 872 | void __init |
604 | pci_assign_unassigned_resources(void) | 873 | pci_assign_unassigned_resources(void) |
605 | { | 874 | { |
606 | struct pci_bus *bus; | 875 | struct pci_bus *bus; |
876 | int tried_times = 0; | ||
877 | enum release_type rel_type = leaf_only; | ||
878 | struct resource_list_x head, *list; | ||
879 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | ||
880 | IORESOURCE_PREFETCH; | ||
881 | unsigned long failed_type; | ||
882 | int max_depth = pci_get_max_depth(); | ||
883 | int pci_try_num; | ||
607 | 884 | ||
885 | head.next = NULL; | ||
886 | |||
887 | pci_try_num = max_depth + 1; | ||
888 | printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n", | ||
889 | max_depth, pci_try_num); | ||
890 | |||
891 | again: | ||
608 | /* Depth first, calculate sizes and alignments of all | 892 | /* Depth first, calculate sizes and alignments of all |
609 | subordinate buses. */ | 893 | subordinate buses. */ |
610 | list_for_each_entry(bus, &pci_root_buses, node) { | 894 | list_for_each_entry(bus, &pci_root_buses, node) { |
@@ -612,12 +896,130 @@ pci_assign_unassigned_resources(void) | |||
612 | } | 896 | } |
613 | /* Depth last, allocate resources and update the hardware. */ | 897 | /* Depth last, allocate resources and update the hardware. */ |
614 | list_for_each_entry(bus, &pci_root_buses, node) { | 898 | list_for_each_entry(bus, &pci_root_buses, node) { |
615 | pci_bus_assign_resources(bus); | 899 | __pci_bus_assign_resources(bus, &head); |
616 | pci_enable_bridges(bus); | ||
617 | } | 900 | } |
901 | tried_times++; | ||
902 | |||
903 | /* any device complain? */ | ||
904 | if (!head.next) | ||
905 | goto enable_and_dump; | ||
906 | failed_type = 0; | ||
907 | for (list = head.next; list;) { | ||
908 | failed_type |= list->flags; | ||
909 | list = list->next; | ||
910 | } | ||
911 | /* | ||
912 | * io port are tight, don't try extra | ||
913 | * or if reach the limit, don't want to try more | ||
914 | */ | ||
915 | failed_type &= type_mask; | ||
916 | if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) { | ||
917 | free_failed_list(&head); | ||
918 | goto enable_and_dump; | ||
919 | } | ||
920 | |||
921 | printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", | ||
922 | tried_times + 1); | ||
923 | |||
924 | /* third times and later will not check if it is leaf */ | ||
925 | if ((tried_times + 1) > 2) | ||
926 | rel_type = whole_subtree; | ||
927 | |||
928 | /* | ||
929 | * Try to release leaf bridge's resources that doesn't fit resource of | ||
930 | * child device under that bridge | ||
931 | */ | ||
932 | for (list = head.next; list;) { | ||
933 | bus = list->dev->bus; | ||
934 | pci_bus_release_bridge_resources(bus, list->flags & type_mask, | ||
935 | rel_type); | ||
936 | list = list->next; | ||
937 | } | ||
938 | /* restore size and flags */ | ||
939 | for (list = head.next; list;) { | ||
940 | struct resource *res = list->res; | ||
941 | |||
942 | res->start = list->start; | ||
943 | res->end = list->end; | ||
944 | res->flags = list->flags; | ||
945 | if (list->dev->subordinate) | ||
946 | res->flags = 0; | ||
947 | |||
948 | list = list->next; | ||
949 | } | ||
950 | free_failed_list(&head); | ||
951 | |||
952 | goto again; | ||
953 | |||
954 | enable_and_dump: | ||
955 | /* Depth last, update the hardware. */ | ||
956 | list_for_each_entry(bus, &pci_root_buses, node) | ||
957 | pci_enable_bridges(bus); | ||
618 | 958 | ||
619 | /* dump the resource on buses */ | 959 | /* dump the resource on buses */ |
620 | list_for_each_entry(bus, &pci_root_buses, node) { | 960 | list_for_each_entry(bus, &pci_root_buses, node) { |
621 | pci_bus_dump_resources(bus); | 961 | pci_bus_dump_resources(bus); |
622 | } | 962 | } |
623 | } | 963 | } |
964 | |||
965 | void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) | ||
966 | { | ||
967 | struct pci_bus *parent = bridge->subordinate; | ||
968 | int tried_times = 0; | ||
969 | struct resource_list_x head, *list; | ||
970 | int retval; | ||
971 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | ||
972 | IORESOURCE_PREFETCH; | ||
973 | |||
974 | head.next = NULL; | ||
975 | |||
976 | again: | ||
977 | pci_bus_size_bridges(parent); | ||
978 | __pci_bridge_assign_resources(bridge, &head); | ||
979 | retval = pci_reenable_device(bridge); | ||
980 | pci_set_master(bridge); | ||
981 | pci_enable_bridges(parent); | ||
982 | |||
983 | tried_times++; | ||
984 | |||
985 | if (!head.next) | ||
986 | return; | ||
987 | |||
988 | if (tried_times >= 2) { | ||
989 | /* still fail, don't need to try more */ | ||
990 | free_failed_list(&head); | ||
991 | return; | ||
992 | } | ||
993 | |||
994 | printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", | ||
995 | tried_times + 1); | ||
996 | |||
997 | /* | ||
998 | * Try to release leaf bridge's resources that doesn't fit resource of | ||
999 | * child device under that bridge | ||
1000 | */ | ||
1001 | for (list = head.next; list;) { | ||
1002 | struct pci_bus *bus = list->dev->bus; | ||
1003 | unsigned long flags = list->flags; | ||
1004 | |||
1005 | pci_bus_release_bridge_resources(bus, flags & type_mask, | ||
1006 | whole_subtree); | ||
1007 | list = list->next; | ||
1008 | } | ||
1009 | /* restore size and flags */ | ||
1010 | for (list = head.next; list;) { | ||
1011 | struct resource *res = list->res; | ||
1012 | |||
1013 | res->start = list->start; | ||
1014 | res->end = list->end; | ||
1015 | res->flags = list->flags; | ||
1016 | if (list->dev->subordinate) | ||
1017 | res->flags = 0; | ||
1018 | |||
1019 | list = list->next; | ||
1020 | } | ||
1021 | free_failed_list(&head); | ||
1022 | |||
1023 | goto again; | ||
1024 | } | ||
1025 | EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); | ||