aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/pci_32.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2007-12-19 22:54:43 -0500
committerPaul Mackerras <paulus@samba.org>2007-12-20 00:18:05 -0500
commit0ec6b5c1028f29aed07bc7c32945990c5cd48c14 (patch)
tree4daf8b00a24292c4cd6d79f888aeb252b2c496c5 /arch/powerpc/kernel/pci_32.c
parentb1258fd1029a47e99a624970b16ac11ad97ddb6a (diff)
[POWERPC] pci32: Use generic pci_assign_unassign_resources
This makes the 32 bits PowerPC PCI code use the generic code to assign resources to devices that had unassigned or conflicting resources. This allow us to remove the local implementation that was incomplete and could not assign for example a PCI<->PCI bridge from scratch, which is needed on various embedded platforms. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/pci_32.c')
-rw-r--r--arch/powerpc/kernel/pci_32.c191
1 files changed, 17 insertions, 174 deletions
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index c1f34d5381af..1020d04b0a5a 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -37,10 +37,6 @@ int pcibios_assign_bus_offset = 1;
37 37
38void pcibios_make_OF_bus_map(void); 38void pcibios_make_OF_bus_map(void);
39 39
40static int pci_relocate_bridge_resource(struct pci_bus *bus, int i);
41static int probe_resource(struct pci_bus *parent, struct resource *pr,
42 struct resource *res, struct resource **conflict);
43static void update_bridge_base(struct pci_bus *bus, int i);
44static void pcibios_fixup_resources(struct pci_dev* dev); 40static void pcibios_fixup_resources(struct pci_dev* dev);
45static void fixup_broken_pcnet32(struct pci_dev* dev); 41static void fixup_broken_pcnet32(struct pci_dev* dev);
46static int reparent_resources(struct resource *parent, struct resource *res); 42static int reparent_resources(struct resource *parent, struct resource *res);
@@ -134,7 +130,7 @@ pcibios_fixup_resources(struct pci_dev *dev)
134 if (offset != 0) { 130 if (offset != 0) {
135 res->start = (res->start + offset) & mask; 131 res->start = (res->start + offset) & mask;
136 res->end = (res->end + offset) & mask; 132 res->end = (res->end + offset) & mask;
137 DBG("Fixup res %d (%lx) of dev %s: %llx -> %llx\n", 133 DBG("PCI: Fixup res %d (0x%lx) of dev %s: %llx -> %llx\n",
138 i, res->flags, pci_name(dev), 134 i, res->flags, pci_name(dev),
139 (u64)res->start - offset, (u64)res->start); 135 (u64)res->start - offset, (u64)res->start);
140 } 136 }
@@ -267,9 +263,12 @@ pcibios_allocate_bus_resources(struct list_head *bus_list)
267 } 263 }
268 } 264 }
269 265
270 DBG("PCI: bridge rsrc %llx..%llx (%lx), parent %p\n", 266 DBG("PCI: dev %s (bus 0x%02x) bridge rsrc %d: %016llx..%016llx "
267 "(f:0x%08lx), parent %p\n",
268 bus->self ? pci_name(bus->self) : "PHB", bus->number, i,
271 (u64)res->start, (u64)res->end, res->flags, pr); 269 (u64)res->start, (u64)res->end, res->flags, pr);
272 if (pr) { 270
271 if (pr && !(pr->flags & IORESOURCE_UNSET)) {
273 if (request_resource(pr, res) == 0) 272 if (request_resource(pr, res) == 0)
274 continue; 273 continue;
275 /* 274 /*
@@ -280,10 +279,11 @@ pcibios_allocate_bus_resources(struct list_head *bus_list)
280 if (reparent_resources(pr, res) == 0) 279 if (reparent_resources(pr, res) == 0)
281 continue; 280 continue;
282 } 281 }
283 printk(KERN_ERR "PCI: Cannot allocate resource region " 282 printk(KERN_WARNING
284 "%d of PCI bridge %d\n", i, bus->number); 283 "PCI: Cannot allocate resource region "
285 if (pci_relocate_bridge_resource(bus, i)) 284 "%d of PCI bridge %d, will remap\n",
286 bus->resource[i] = NULL; 285 i, bus->number);
286 res->flags |= IORESOURCE_UNSET;
287 } 287 }
288 pcibios_allocate_bus_resources(&bus->children); 288 pcibios_allocate_bus_resources(&bus->children);
289 } 289 }
@@ -324,112 +324,6 @@ reparent_resources(struct resource *parent, struct resource *res)
324 return 0; 324 return 0;
325} 325}
326 326
327/*
328 * A bridge has been allocated a range which is outside the range
329 * of its parent bridge, so it needs to be moved.
330 */
331static int __init
332pci_relocate_bridge_resource(struct pci_bus *bus, int i)
333{
334 struct resource *res, *pr, *conflict;
335 resource_size_t try, size;
336 struct pci_bus *parent = bus->parent;
337 int j;
338
339 if (parent == NULL) {
340 /* shouldn't ever happen */
341 printk(KERN_ERR "PCI: can't move host bridge resource\n");
342 return -1;
343 }
344 res = bus->resource[i];
345 if (res == NULL)
346 return -1;
347 pr = NULL;
348 for (j = 0; j < 4; j++) {
349 struct resource *r = parent->resource[j];
350 if (!r)
351 continue;
352 if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
353 continue;
354 if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) {
355 pr = r;
356 break;
357 }
358 if (res->flags & IORESOURCE_PREFETCH)
359 pr = r;
360 }
361 if (pr == NULL)
362 return -1;
363 size = res->end - res->start;
364 if (pr->start > pr->end || size > pr->end - pr->start)
365 return -1;
366 try = pr->end;
367 for (;;) {
368 res->start = try - size;
369 res->end = try;
370 if (probe_resource(bus->parent, pr, res, &conflict) == 0)
371 break;
372 if (conflict->start <= pr->start + size)
373 return -1;
374 try = conflict->start - 1;
375 }
376 if (request_resource(pr, res)) {
377 DBG(KERN_ERR "PCI: huh? couldn't move to %llx..%llx\n",
378 (u64)res->start, (u64)res->end);
379 return -1; /* "can't happen" */
380 }
381 update_bridge_base(bus, i);
382 printk(KERN_INFO "PCI: bridge %d resource %d moved to %llx..%llx\n",
383 bus->number, i, (unsigned long long)res->start,
384 (unsigned long long)res->end);
385 return 0;
386}
387
388static int __init
389probe_resource(struct pci_bus *parent, struct resource *pr,
390 struct resource *res, struct resource **conflict)
391{
392 struct pci_bus *bus;
393 struct pci_dev *dev;
394 struct resource *r;
395 int i;
396
397 for (r = pr->child; r != NULL; r = r->sibling) {
398 if (r->end >= res->start && res->end >= r->start) {
399 *conflict = r;
400 return 1;
401 }
402 }
403 list_for_each_entry(bus, &parent->children, node) {
404 for (i = 0; i < 4; ++i) {
405 if ((r = bus->resource[i]) == NULL)
406 continue;
407 if (!r->flags || r->start > r->end || r == res)
408 continue;
409 if (pci_find_parent_resource(bus->self, r) != pr)
410 continue;
411 if (r->end >= res->start && res->end >= r->start) {
412 *conflict = r;
413 return 1;
414 }
415 }
416 }
417 list_for_each_entry(dev, &parent->devices, bus_list) {
418 for (i = 0; i < 6; ++i) {
419 r = &dev->resource[i];
420 if (!r->flags || (r->flags & IORESOURCE_UNSET))
421 continue;
422 if (pci_find_parent_resource(dev, r) != pr)
423 continue;
424 if (r->end >= res->start && res->end >= r->start) {
425 *conflict = r;
426 return 1;
427 }
428 }
429 }
430 return 0;
431}
432
433void __init 327void __init
434update_bridge_resource(struct pci_dev *dev, struct resource *res) 328update_bridge_resource(struct pci_dev *dev, struct resource *res)
435{ 329{
@@ -486,24 +380,16 @@ update_bridge_resource(struct pci_dev *dev, struct resource *res)
486 pci_write_config_word(dev, PCI_COMMAND, cmd); 380 pci_write_config_word(dev, PCI_COMMAND, cmd);
487} 381}
488 382
489static void __init
490update_bridge_base(struct pci_bus *bus, int i)
491{
492 struct resource *res = bus->resource[i];
493 struct pci_dev *dev = bus->self;
494 update_bridge_resource(dev, res);
495}
496
497static inline void alloc_resource(struct pci_dev *dev, int idx) 383static inline void alloc_resource(struct pci_dev *dev, int idx)
498{ 384{
499 struct resource *pr, *r = &dev->resource[idx]; 385 struct resource *pr, *r = &dev->resource[idx];
500 386
501 DBG("PCI:%s: Resource %d: %016llx-%016llx (f=%lx)\n", 387 DBG("PCI: Allocating %s: Resource %d: %016llx..%016llx (f=%lx)\n",
502 pci_name(dev), idx, (u64)r->start, (u64)r->end, r->flags); 388 pci_name(dev), idx, (u64)r->start, (u64)r->end, r->flags);
503 pr = pci_find_parent_resource(dev, r); 389 pr = pci_find_parent_resource(dev, r);
504 if (!pr || request_resource(pr, r) < 0) { 390 if (!pr || (pr->flags & IORESOURCE_UNSET) || request_resource(pr, r) < 0) {
505 printk(KERN_WARNING "PCI: Remapping resource region %d" 391 printk(KERN_WARNING "PCI: Cannot allocate resource region %d"
506 " of device %s\n", idx, pci_name(dev)); 392 " of device %s, will remap\n", idx, pci_name(dev));
507 if (pr) 393 if (pr)
508 DBG("PCI: parent is %p: %016llx-%016llx (f=%lx)\n", 394 DBG("PCI: parent is %p: %016llx-%016llx (f=%lx)\n",
509 pr, (u64)pr->start, (u64)pr->end, pr->flags); 395 pr, (u64)pr->start, (u64)pr->end, pr->flags);
@@ -552,50 +438,6 @@ pcibios_allocate_resources(int pass)
552 } 438 }
553} 439}
554 440
555static void __init
556pcibios_assign_resources(void)
557{
558 struct pci_dev *dev = NULL;
559 int idx;
560 struct resource *r;
561
562 for_each_pci_dev(dev) {
563 int class = dev->class >> 8;
564
565 /* Don't touch classless devices and host bridges */
566 if (!class || class == PCI_CLASS_BRIDGE_HOST)
567 continue;
568
569 for (idx = 0; idx < 6; idx++) {
570 r = &dev->resource[idx];
571
572 /*
573 * We shall assign a new address to this resource,
574 * either because the BIOS (sic) forgot to do so
575 * or because we have decided the old address was
576 * unusable for some reason.
577 */
578 if ((r->flags & IORESOURCE_UNSET) && r->end &&
579 (!ppc_md.pcibios_enable_device_hook ||
580 !ppc_md.pcibios_enable_device_hook(dev, 1))) {
581 int rc;
582
583 r->flags &= ~IORESOURCE_UNSET;
584 rc = pci_assign_resource(dev, idx);
585 BUG_ON(rc);
586 }
587 }
588
589#if 0 /* don't assign ROMs */
590 r = &dev->resource[PCI_ROM_RESOURCE];
591 r->end -= r->start;
592 r->start = 0;
593 if (r->end)
594 pci_assign_resource(dev, PCI_ROM_RESOURCE);
595#endif
596 }
597}
598
599#ifdef CONFIG_PPC_OF 441#ifdef CONFIG_PPC_OF
600/* 442/*
601 * Functions below are used on OpenFirmware machines. 443 * Functions below are used on OpenFirmware machines.
@@ -1122,7 +964,8 @@ pcibios_init(void)
1122#ifdef CONFIG_PPC_PMAC 964#ifdef CONFIG_PPC_PMAC
1123 pcibios_fixup_p2p_bridges(); 965 pcibios_fixup_p2p_bridges();
1124#endif /* CONFIG_PPC_PMAC */ 966#endif /* CONFIG_PPC_PMAC */
1125 pcibios_assign_resources(); 967 DBG("PCI: Assigning unassigned resouces...\n");
968 pci_assign_unassigned_resources();
1126 969
1127 /* Call machine dependent post-init code */ 970 /* Call machine dependent post-init code */
1128 if (ppc_md.pcibios_after_init) 971 if (ppc_md.pcibios_after_init)