]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | Subject: Fix DLPAR |
2 | From: Benjamin Herrenschmidt <benh@kernel.crashing.org> | |
3 | References: 439491 | |
4 | ||
5 | Signed-off-by: Olaf Hering <olh@suse.de> | |
6 | --- | |
7 | arch/powerpc/include/asm/pci.h | 2 | |
8 | arch/powerpc/kernel/pci-common.c | 110 ++++++++++++++--------------- | |
9 | arch/powerpc/platforms/pseries/pci_dlpar.c | 2 | |
10 | 3 files changed, 59 insertions(+), 55 deletions(-) | |
11 | ||
12 | --- a/arch/powerpc/include/asm/pci.h | |
13 | +++ b/arch/powerpc/include/asm/pci.h | |
14 | @@ -196,6 +196,8 @@ extern void pcibios_setup_new_device(str | |
15 | ||
16 | extern void pcibios_claim_one_bus(struct pci_bus *b); | |
17 | ||
18 | +extern void pcibios_allocate_bus_resources(struct pci_bus *bus); | |
19 | + | |
20 | extern void pcibios_resource_survey(void); | |
21 | ||
22 | extern struct pci_controller *init_phb_dynamic(struct device_node *dn); | |
23 | --- a/arch/powerpc/kernel/pci-common.c | |
24 | +++ b/arch/powerpc/kernel/pci-common.c | |
25 | @@ -986,69 +986,66 @@ static int __init reparent_resources(str | |
26 | * as well. | |
27 | */ | |
28 | ||
29 | -static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) | |
30 | +void pcibios_allocate_bus_resources(struct pci_bus *bus) | |
31 | { | |
32 | - struct pci_bus *bus; | |
33 | + struct pci_bus *b; | |
34 | int i; | |
35 | struct resource *res, *pr; | |
36 | ||
37 | - /* Depth-First Search on bus tree */ | |
38 | - list_for_each_entry(bus, bus_list, node) { | |
39 | - for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) { | |
40 | - if ((res = bus->resource[i]) == NULL || !res->flags | |
41 | - || res->start > res->end) | |
42 | - continue; | |
43 | - if (bus->parent == NULL) | |
44 | - pr = (res->flags & IORESOURCE_IO) ? | |
45 | - &ioport_resource : &iomem_resource; | |
46 | - else { | |
47 | - /* Don't bother with non-root busses when | |
48 | - * re-assigning all resources. We clear the | |
49 | - * resource flags as if they were colliding | |
50 | - * and as such ensure proper re-allocation | |
51 | - * later. | |
52 | + for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) { | |
53 | + if ((res = bus->resource[i]) == NULL || !res->flags | |
54 | + || res->start > res->end) | |
55 | + continue; | |
56 | + if (bus->parent == NULL) | |
57 | + pr = (res->flags & IORESOURCE_IO) ? | |
58 | + &ioport_resource : &iomem_resource; | |
59 | + else { | |
60 | + /* Don't bother with non-root busses when | |
61 | + * re-assigning all resources. We clear the | |
62 | + * resource flags as if they were colliding | |
63 | + * and as such ensure proper re-allocation | |
64 | + * later. | |
65 | + */ | |
66 | + if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC) | |
67 | + goto clear_resource; | |
68 | + pr = pci_find_parent_resource(bus->self, res); | |
69 | + if (pr == res) { | |
70 | + /* this happens when the generic PCI | |
71 | + * code (wrongly) decides that this | |
72 | + * bridge is transparent -- paulus | |
73 | */ | |
74 | - if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC) | |
75 | - goto clear_resource; | |
76 | - pr = pci_find_parent_resource(bus->self, res); | |
77 | - if (pr == res) { | |
78 | - /* this happens when the generic PCI | |
79 | - * code (wrongly) decides that this | |
80 | - * bridge is transparent -- paulus | |
81 | - */ | |
82 | - continue; | |
83 | - } | |
84 | + continue; | |
85 | } | |
86 | + } | |
87 | ||
88 | - DBG("PCI: %s (bus %d) bridge rsrc %d: %016llx-%016llx " | |
89 | - "[0x%x], parent %p (%s)\n", | |
90 | - bus->self ? pci_name(bus->self) : "PHB", | |
91 | - bus->number, i, | |
92 | - (unsigned long long)res->start, | |
93 | - (unsigned long long)res->end, | |
94 | - (unsigned int)res->flags, | |
95 | - pr, (pr && pr->name) ? pr->name : "nil"); | |
96 | - | |
97 | - if (pr && !(pr->flags & IORESOURCE_UNSET)) { | |
98 | - if (request_resource(pr, res) == 0) | |
99 | - continue; | |
100 | - /* | |
101 | - * Must be a conflict with an existing entry. | |
102 | - * Move that entry (or entries) under the | |
103 | - * bridge resource and try again. | |
104 | - */ | |
105 | - if (reparent_resources(pr, res) == 0) | |
106 | - continue; | |
107 | - } | |
108 | - printk(KERN_WARNING | |
109 | - "PCI: Cannot allocate resource region " | |
110 | - "%d of PCI bridge %d, will remap\n", | |
111 | - i, bus->number); | |
112 | -clear_resource: | |
113 | - res->flags = 0; | |
114 | + DBG("PCI: %s (bus %d) bridge rsrc %d: %016llx-%016llx " | |
115 | + "[0x%x], parent %p (%s)\n", | |
116 | + bus->self ? pci_name(bus->self) : "PHB", | |
117 | + bus->number, i, | |
118 | + (unsigned long long)res->start, | |
119 | + (unsigned long long)res->end, | |
120 | + (unsigned int)res->flags, | |
121 | + pr, (pr && pr->name) ? pr->name : "nil"); | |
122 | + | |
123 | + if (pr && !(pr->flags & IORESOURCE_UNSET)) { | |
124 | + if (request_resource(pr, res) == 0) | |
125 | + continue; | |
126 | + /* | |
127 | + * Must be a conflict with an existing entry. | |
128 | + * Move that entry (or entries) under the | |
129 | + * bridge resource and try again. | |
130 | + */ | |
131 | + if (reparent_resources(pr, res) == 0) | |
132 | + continue; | |
133 | } | |
134 | - pcibios_allocate_bus_resources(&bus->children); | |
135 | + printk(KERN_WARNING "PCI: Cannot allocate resource region " | |
136 | + "%d of PCI bridge %d, will remap\n", i, bus->number); | |
137 | +clear_resource: | |
138 | + res->flags = 0; | |
139 | } | |
140 | + | |
141 | + list_for_each_entry(b, &bus->children, node) | |
142 | + pcibios_allocate_bus_resources(b); | |
143 | } | |
144 | ||
145 | static inline void __devinit alloc_resource(struct pci_dev *dev, int idx) | |
146 | @@ -1119,10 +1116,13 @@ static void __init pcibios_allocate_reso | |
147 | ||
148 | void __init pcibios_resource_survey(void) | |
149 | { | |
150 | + struct pci_bus *b; | |
151 | + | |
152 | /* Allocate and assign resources. If we re-assign everything, then | |
153 | * we skip the allocate phase | |
154 | */ | |
155 | - pcibios_allocate_bus_resources(&pci_root_buses); | |
156 | + list_for_each_entry(b, &pci_root_buses, node) | |
157 | + pcibios_allocate_bus_resources(b); | |
158 | ||
159 | if (!(ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)) { | |
160 | pcibios_allocate_resources(0); | |
161 | --- a/arch/powerpc/platforms/pseries/pci_dlpar.c | |
162 | +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c | |
163 | @@ -189,6 +189,7 @@ struct pci_controller * __devinit init_p | |
164 | { | |
165 | struct pci_controller *phb; | |
166 | int primary; | |
167 | + struct pci_bus *b; | |
168 | ||
169 | primary = list_empty(&hose_list); | |
170 | phb = pcibios_alloc_controller(dn); | |
171 | @@ -203,6 +204,7 @@ struct pci_controller * __devinit init_p | |
172 | eeh_add_device_tree_early(dn); | |
173 | ||
174 | scan_phb(phb); | |
175 | + pcibios_allocate_bus_resources(phb->bus); | |
176 | pcibios_fixup_new_pci_devices(phb->bus); | |
177 | pci_bus_add_devices(phb->bus); | |
178 | eeh_add_device_tree_late(phb->bus); |