diff options
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/pci_64.c | 68 | ||||
-rw-r--r-- | arch/powerpc/kernel/rtas_pci.c | 68 |
2 files changed, 70 insertions, 66 deletions
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index d7de3ec0bf83..5a5b24685081 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -187,7 +187,7 @@ static DEFINE_SPINLOCK(hose_spinlock); | |||
187 | /* | 187 | /* |
188 | * pci_controller(phb) initialized common variables. | 188 | * pci_controller(phb) initialized common variables. |
189 | */ | 189 | */ |
190 | void __devinit pci_setup_pci_controller(struct pci_controller *hose) | 190 | static void __devinit pci_setup_pci_controller(struct pci_controller *hose) |
191 | { | 191 | { |
192 | memset(hose, 0, sizeof(struct pci_controller)); | 192 | memset(hose, 0, sizeof(struct pci_controller)); |
193 | 193 | ||
@@ -197,6 +197,65 @@ void __devinit pci_setup_pci_controller(struct pci_controller *hose) | |||
197 | spin_unlock(&hose_spinlock); | 197 | spin_unlock(&hose_spinlock); |
198 | } | 198 | } |
199 | 199 | ||
200 | static void add_linux_pci_domain(struct device_node *dev, | ||
201 | struct pci_controller *phb) | ||
202 | { | ||
203 | struct property *of_prop; | ||
204 | unsigned int size; | ||
205 | |||
206 | of_prop = (struct property *) | ||
207 | get_property(dev, "linux,pci-domain", &size); | ||
208 | if (of_prop != NULL) | ||
209 | return; | ||
210 | WARN_ON(of_prop && size < sizeof(int)); | ||
211 | if (of_prop && size < sizeof(int)) | ||
212 | of_prop = NULL; | ||
213 | size = sizeof(struct property) + sizeof(int); | ||
214 | if (of_prop == NULL) { | ||
215 | if (mem_init_done) | ||
216 | of_prop = kmalloc(size, GFP_KERNEL); | ||
217 | else | ||
218 | of_prop = alloc_bootmem(size); | ||
219 | } | ||
220 | memset(of_prop, 0, sizeof(struct property)); | ||
221 | of_prop->name = "linux,pci-domain"; | ||
222 | of_prop->length = sizeof(int); | ||
223 | of_prop->value = (unsigned char *)&of_prop[1]; | ||
224 | *((int *)of_prop->value) = phb->global_number; | ||
225 | prom_add_property(dev, of_prop); | ||
226 | } | ||
227 | |||
228 | struct pci_controller * pcibios_alloc_controller(struct device_node *dev) | ||
229 | { | ||
230 | struct pci_controller *phb; | ||
231 | |||
232 | if (mem_init_done) | ||
233 | phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL); | ||
234 | else | ||
235 | phb = alloc_bootmem(sizeof (struct pci_controller)); | ||
236 | if (phb == NULL) | ||
237 | return NULL; | ||
238 | pci_setup_pci_controller(phb); | ||
239 | phb->arch_data = dev; | ||
240 | phb->is_dynamic = mem_init_done; | ||
241 | if (dev) | ||
242 | add_linux_pci_domain(dev, phb); | ||
243 | return phb; | ||
244 | } | ||
245 | |||
246 | void pcibios_free_controller(struct pci_controller *phb) | ||
247 | { | ||
248 | if (phb->arch_data) { | ||
249 | struct device_node *np = phb->arch_data; | ||
250 | int *domain = (int *)get_property(np, | ||
251 | "linux,pci-domain", NULL); | ||
252 | if (domain) | ||
253 | *domain = -1; | ||
254 | } | ||
255 | if (phb->is_dynamic) | ||
256 | kfree(phb); | ||
257 | } | ||
258 | |||
200 | static void __init pcibios_claim_one_bus(struct pci_bus *b) | 259 | static void __init pcibios_claim_one_bus(struct pci_bus *b) |
201 | { | 260 | { |
202 | struct pci_dev *dev; | 261 | struct pci_dev *dev; |
@@ -907,9 +966,10 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, | |||
907 | * (size depending on dev->n_addr_cells) | 966 | * (size depending on dev->n_addr_cells) |
908 | * cells 4+5 or 5+6: the size of the range | 967 | * cells 4+5 or 5+6: the size of the range |
909 | */ | 968 | */ |
910 | rlen = 0; | ||
911 | hose->io_base_phys = 0; | ||
912 | ranges = (unsigned int *) get_property(dev, "ranges", &rlen); | 969 | ranges = (unsigned int *) get_property(dev, "ranges", &rlen); |
970 | if (ranges == NULL) | ||
971 | return; | ||
972 | hose->io_base_phys = 0; | ||
913 | while ((rlen -= np * sizeof(unsigned int)) >= 0) { | 973 | while ((rlen -= np * sizeof(unsigned int)) >= 0) { |
914 | res = NULL; | 974 | res = NULL; |
915 | pci_space = ranges[0]; | 975 | pci_space = ranges[0]; |
@@ -1107,6 +1167,8 @@ int remap_bus_range(struct pci_bus *bus) | |||
1107 | 1167 | ||
1108 | if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) | 1168 | if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) |
1109 | return 1; | 1169 | return 1; |
1170 | if (start_phys == 0) | ||
1171 | return 1; | ||
1110 | printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); | 1172 | printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); |
1111 | if (__ioremap_explicit(start_phys, start_virt, size, | 1173 | if (__ioremap_explicit(start_phys, start_virt, size, |
1112 | _PAGE_NO_CACHE | _PAGE_GUARDED)) | 1174 | _PAGE_NO_CACHE | _PAGE_GUARDED)) |
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 0e5a8e116653..60dec2401c26 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c | |||
@@ -304,75 +304,18 @@ static int __devinit setup_phb(struct device_node *dev, | |||
304 | struct pci_controller *phb, | 304 | struct pci_controller *phb, |
305 | unsigned int addr_size_words) | 305 | unsigned int addr_size_words) |
306 | { | 306 | { |
307 | pci_setup_pci_controller(phb); | ||
308 | |||
309 | if (is_python(dev)) | 307 | if (is_python(dev)) |
310 | python_countermeasures(dev, addr_size_words); | 308 | python_countermeasures(dev, addr_size_words); |
311 | 309 | ||
312 | if (phb_set_bus_ranges(dev, phb)) | 310 | if (phb_set_bus_ranges(dev, phb)) |
313 | return 1; | 311 | return 1; |
314 | 312 | ||
315 | phb->arch_data = dev; | ||
316 | phb->ops = &rtas_pci_ops; | 313 | phb->ops = &rtas_pci_ops; |
317 | phb->buid = get_phb_buid(dev); | 314 | phb->buid = get_phb_buid(dev); |
318 | 315 | ||
319 | return 0; | 316 | return 0; |
320 | } | 317 | } |
321 | 318 | ||
322 | static void __devinit add_linux_pci_domain(struct device_node *dev, | ||
323 | struct pci_controller *phb, | ||
324 | struct property *of_prop) | ||
325 | { | ||
326 | memset(of_prop, 0, sizeof(struct property)); | ||
327 | of_prop->name = "linux,pci-domain"; | ||
328 | of_prop->length = sizeof(phb->global_number); | ||
329 | of_prop->value = (unsigned char *)&of_prop[1]; | ||
330 | memcpy(of_prop->value, &phb->global_number, sizeof(phb->global_number)); | ||
331 | prom_add_property(dev, of_prop); | ||
332 | } | ||
333 | |||
334 | static struct pci_controller * __init alloc_phb(struct device_node *dev, | ||
335 | unsigned int addr_size_words) | ||
336 | { | ||
337 | struct pci_controller *phb; | ||
338 | struct property *of_prop; | ||
339 | |||
340 | phb = alloc_bootmem(sizeof(struct pci_controller)); | ||
341 | if (phb == NULL) | ||
342 | return NULL; | ||
343 | |||
344 | of_prop = alloc_bootmem(sizeof(struct property) + | ||
345 | sizeof(phb->global_number)); | ||
346 | if (!of_prop) | ||
347 | return NULL; | ||
348 | |||
349 | if (setup_phb(dev, phb, addr_size_words)) | ||
350 | return NULL; | ||
351 | |||
352 | add_linux_pci_domain(dev, phb, of_prop); | ||
353 | |||
354 | return phb; | ||
355 | } | ||
356 | |||
357 | static struct pci_controller * __devinit alloc_phb_dynamic(struct device_node *dev, unsigned int addr_size_words) | ||
358 | { | ||
359 | struct pci_controller *phb; | ||
360 | |||
361 | phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), | ||
362 | GFP_KERNEL); | ||
363 | if (phb == NULL) | ||
364 | return NULL; | ||
365 | |||
366 | if (setup_phb(dev, phb, addr_size_words)) | ||
367 | return NULL; | ||
368 | |||
369 | phb->is_dynamic = 1; | ||
370 | |||
371 | /* TODO: linux,pci-domain? */ | ||
372 | |||
373 | return phb; | ||
374 | } | ||
375 | |||
376 | unsigned long __init find_and_init_phbs(void) | 319 | unsigned long __init find_and_init_phbs(void) |
377 | { | 320 | { |
378 | struct device_node *node; | 321 | struct device_node *node; |
@@ -397,10 +340,10 @@ unsigned long __init find_and_init_phbs(void) | |||
397 | if (node->type == NULL || strcmp(node->type, "pci") != 0) | 340 | if (node->type == NULL || strcmp(node->type, "pci") != 0) |
398 | continue; | 341 | continue; |
399 | 342 | ||
400 | phb = alloc_phb(node, root_size_cells); | 343 | phb = pcibios_alloc_controller(node); |
401 | if (!phb) | 344 | if (!phb) |
402 | continue; | 345 | continue; |
403 | 346 | setup_phb(node, phb, root_size_cells); | |
404 | pci_process_bridge_OF_ranges(phb, node, 0); | 347 | pci_process_bridge_OF_ranges(phb, node, 0); |
405 | pci_setup_phb_io(phb, index == 0); | 348 | pci_setup_phb_io(phb, index == 0); |
406 | #ifdef CONFIG_PPC_PSERIES | 349 | #ifdef CONFIG_PPC_PSERIES |
@@ -446,10 +389,10 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) | |||
446 | root_size_cells = prom_n_size_cells(root); | 389 | root_size_cells = prom_n_size_cells(root); |
447 | 390 | ||
448 | primary = list_empty(&hose_list); | 391 | primary = list_empty(&hose_list); |
449 | phb = alloc_phb_dynamic(dn, root_size_cells); | 392 | phb = pcibios_alloc_controller(dn); |
450 | if (!phb) | 393 | if (!phb) |
451 | return NULL; | 394 | return NULL; |
452 | 395 | setup_phb(dn, phb, root_size_cells); | |
453 | pci_process_bridge_OF_ranges(phb, dn, primary); | 396 | pci_process_bridge_OF_ranges(phb, dn, primary); |
454 | 397 | ||
455 | pci_setup_phb_io_dynamic(phb, primary); | 398 | pci_setup_phb_io_dynamic(phb, primary); |
@@ -505,8 +448,7 @@ int pcibios_remove_root_bus(struct pci_controller *phb) | |||
505 | } | 448 | } |
506 | 449 | ||
507 | list_del(&phb->list_node); | 450 | list_del(&phb->list_node); |
508 | if (phb->is_dynamic) | 451 | pcibios_free_controller(phb); |
509 | kfree(phb); | ||
510 | 452 | ||
511 | return 0; | 453 | return 0; |
512 | } | 454 | } |