diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2007-12-19 22:54:51 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-12-20 00:18:09 -0500 |
commit | bf5e2ba28f24f82a64524ef4772c9ebe12e2cd2a (patch) | |
tree | f35c139d124a9276b71260c13c8bddf0aa02b4d7 /arch/powerpc/kernel/pci_64.c | |
parent | fe2d338cdcc628e0abdb4f70570a7fa864c617db (diff) |
[POWERPC] Merge PCI resource fixups
The PCI code in 32 and 64 bits fixes up resources differently.
32 bits uses a header quirk plus handles bridges in pcibios_fixup_bus()
while 64 bits does things in various places depending on whether you
are using OF probing, using PCI hotplug, etc...
This merges those by basically using the 32 bits approach for both,
with various tweaks to make 64 bits work with the new approach.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/pci_64.c')
-rw-r--r-- | arch/powerpc/kernel/pci_64.c | 104 |
1 files changed, 17 insertions, 87 deletions
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 6d1c28fc5e23..b9619b9e5e02 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -41,9 +41,6 @@ | |||
41 | 41 | ||
42 | unsigned long pci_probe_only = 1; | 42 | unsigned long pci_probe_only = 1; |
43 | 43 | ||
44 | static void fixup_resource(struct resource *res, struct pci_dev *dev); | ||
45 | static void do_bus_setup(struct pci_bus *bus); | ||
46 | |||
47 | /* pci_io_base -- the base address from which io bars are offsets. | 44 | /* pci_io_base -- the base address from which io bars are offsets. |
48 | * This is the lowest I/O base address (so bar values are always positive), | 45 | * This is the lowest I/O base address (so bar values are always positive), |
49 | * and it *must* be the start of ISA space if an ISA bus exists because | 46 | * and it *must* be the start of ISA space if an ISA bus exists because |
@@ -239,7 +236,6 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) | |||
239 | res->end = base + size - 1; | 236 | res->end = base + size - 1; |
240 | res->flags = flags; | 237 | res->flags = flags; |
241 | res->name = pci_name(dev); | 238 | res->name = pci_name(dev); |
242 | fixup_resource(res, dev); | ||
243 | } | 239 | } |
244 | } | 240 | } |
245 | 241 | ||
@@ -308,7 +304,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
308 | EXPORT_SYMBOL(of_create_pci_dev); | 304 | EXPORT_SYMBOL(of_create_pci_dev); |
309 | 305 | ||
310 | void __devinit of_scan_bus(struct device_node *node, | 306 | void __devinit of_scan_bus(struct device_node *node, |
311 | struct pci_bus *bus) | 307 | struct pci_bus *bus) |
312 | { | 308 | { |
313 | struct device_node *child = NULL; | 309 | struct device_node *child = NULL; |
314 | const u32 *reg; | 310 | const u32 *reg; |
@@ -317,6 +313,7 @@ void __devinit of_scan_bus(struct device_node *node, | |||
317 | 313 | ||
318 | DBG("of_scan_bus(%s) bus no %d... \n", node->full_name, bus->number); | 314 | DBG("of_scan_bus(%s) bus no %d... \n", node->full_name, bus->number); |
319 | 315 | ||
316 | /* Scan direct children */ | ||
320 | while ((child = of_get_next_child(node, child)) != NULL) { | 317 | while ((child = of_get_next_child(node, child)) != NULL) { |
321 | DBG(" * %s\n", child->full_name); | 318 | DBG(" * %s\n", child->full_name); |
322 | reg = of_get_property(child, "reg", ®len); | 319 | reg = of_get_property(child, "reg", ®len); |
@@ -328,19 +325,26 @@ void __devinit of_scan_bus(struct device_node *node, | |||
328 | dev = of_create_pci_dev(child, bus, devfn); | 325 | dev = of_create_pci_dev(child, bus, devfn); |
329 | if (!dev) | 326 | if (!dev) |
330 | continue; | 327 | continue; |
331 | DBG("dev header type: %x\n", dev->hdr_type); | 328 | DBG(" dev header type: %x\n", dev->hdr_type); |
329 | } | ||
330 | |||
331 | /* Ally all fixups */ | ||
332 | pcibios_fixup_of_probed_bus(bus); | ||
332 | 333 | ||
334 | /* Now scan child busses */ | ||
335 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
333 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | 336 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || |
334 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) | 337 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { |
335 | of_scan_pci_bridge(child, dev); | 338 | struct device_node *child = pci_device_to_OF_node(dev); |
339 | if (dev) | ||
340 | of_scan_pci_bridge(child, dev); | ||
341 | } | ||
336 | } | 342 | } |
337 | |||
338 | do_bus_setup(bus); | ||
339 | } | 343 | } |
340 | EXPORT_SYMBOL(of_scan_bus); | 344 | EXPORT_SYMBOL(of_scan_bus); |
341 | 345 | ||
342 | void __devinit of_scan_pci_bridge(struct device_node *node, | 346 | void __devinit of_scan_pci_bridge(struct device_node *node, |
343 | struct pci_dev *dev) | 347 | struct pci_dev *dev) |
344 | { | 348 | { |
345 | struct pci_bus *bus; | 349 | struct pci_bus *bus; |
346 | const u32 *busrange, *ranges; | 350 | const u32 *busrange, *ranges; |
@@ -410,7 +414,6 @@ void __devinit of_scan_pci_bridge(struct device_node *node, | |||
410 | res->start = of_read_number(&ranges[1], 2); | 414 | res->start = of_read_number(&ranges[1], 2); |
411 | res->end = res->start + size - 1; | 415 | res->end = res->start + size - 1; |
412 | res->flags = flags; | 416 | res->flags = flags; |
413 | fixup_resource(res, dev); | ||
414 | } | 417 | } |
415 | sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), | 418 | sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), |
416 | bus->number); | 419 | bus->number); |
@@ -659,51 +662,13 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus) | |||
659 | } | 662 | } |
660 | EXPORT_SYMBOL_GPL(pcibios_map_io_space); | 663 | EXPORT_SYMBOL_GPL(pcibios_map_io_space); |
661 | 664 | ||
662 | static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) | ||
663 | { | ||
664 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
665 | unsigned long offset; | ||
666 | |||
667 | if (res->flags & IORESOURCE_IO) { | ||
668 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
669 | res->start += offset; | ||
670 | res->end += offset; | ||
671 | } else if (res->flags & IORESOURCE_MEM) { | ||
672 | res->start += hose->pci_mem_offset; | ||
673 | res->end += hose->pci_mem_offset; | ||
674 | } | ||
675 | } | ||
676 | |||
677 | void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, | ||
678 | struct pci_bus *bus) | ||
679 | { | ||
680 | /* Update device resources. */ | ||
681 | int i; | ||
682 | |||
683 | DBG("%s: Fixup resources:\n", pci_name(dev)); | ||
684 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { | ||
685 | struct resource *res = &dev->resource[i]; | ||
686 | if (!res->flags) | ||
687 | continue; | ||
688 | |||
689 | DBG(" 0x%02x < %08lx:0x%016lx...0x%016lx\n", | ||
690 | i, res->flags, res->start, res->end); | ||
691 | |||
692 | fixup_resource(res, dev); | ||
693 | |||
694 | DBG(" > %08lx:0x%016lx...0x%016lx\n", | ||
695 | res->flags, res->start, res->end); | ||
696 | } | ||
697 | } | ||
698 | EXPORT_SYMBOL(pcibios_fixup_device_resources); | ||
699 | |||
700 | void __devinit pcibios_setup_new_device(struct pci_dev *dev) | 665 | void __devinit pcibios_setup_new_device(struct pci_dev *dev) |
701 | { | 666 | { |
702 | struct dev_archdata *sd = &dev->dev.archdata; | 667 | struct dev_archdata *sd = &dev->dev.archdata; |
703 | 668 | ||
704 | sd->of_node = pci_device_to_OF_node(dev); | 669 | sd->of_node = pci_device_to_OF_node(dev); |
705 | 670 | ||
706 | DBG("PCI device %s OF node: %s\n", pci_name(dev), | 671 | DBG("PCI: device %s OF node: %s\n", pci_name(dev), |
707 | sd->of_node ? sd->of_node->full_name : "<none>"); | 672 | sd->of_node ? sd->of_node->full_name : "<none>"); |
708 | 673 | ||
709 | sd->dma_ops = pci_dma_ops; | 674 | sd->dma_ops = pci_dma_ops; |
@@ -717,7 +682,7 @@ void __devinit pcibios_setup_new_device(struct pci_dev *dev) | |||
717 | } | 682 | } |
718 | EXPORT_SYMBOL(pcibios_setup_new_device); | 683 | EXPORT_SYMBOL(pcibios_setup_new_device); |
719 | 684 | ||
720 | static void __devinit do_bus_setup(struct pci_bus *bus) | 685 | void __devinit pcibios_do_bus_setup(struct pci_bus *bus) |
721 | { | 686 | { |
722 | struct pci_dev *dev; | 687 | struct pci_dev *dev; |
723 | 688 | ||
@@ -726,42 +691,7 @@ static void __devinit do_bus_setup(struct pci_bus *bus) | |||
726 | 691 | ||
727 | list_for_each_entry(dev, &bus->devices, bus_list) | 692 | list_for_each_entry(dev, &bus->devices, bus_list) |
728 | pcibios_setup_new_device(dev); | 693 | pcibios_setup_new_device(dev); |
729 | |||
730 | /* Read default IRQs and fixup if necessary */ | ||
731 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
732 | pci_read_irq_line(dev); | ||
733 | if (ppc_md.pci_irq_fixup) | ||
734 | ppc_md.pci_irq_fixup(dev); | ||
735 | } | ||
736 | } | ||
737 | |||
738 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) | ||
739 | { | ||
740 | struct pci_dev *dev = bus->self; | ||
741 | struct device_node *np; | ||
742 | |||
743 | np = pci_bus_to_OF_node(bus); | ||
744 | |||
745 | DBG("pcibios_fixup_bus(%s)\n", np ? np->full_name : "<???>"); | ||
746 | |||
747 | if (dev && pci_probe_only && | ||
748 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
749 | /* This is a subordinate bridge */ | ||
750 | |||
751 | pci_read_bridge_bases(bus); | ||
752 | pcibios_fixup_device_resources(dev, bus); | ||
753 | } | ||
754 | |||
755 | do_bus_setup(bus); | ||
756 | |||
757 | if (!pci_probe_only) | ||
758 | return; | ||
759 | |||
760 | list_for_each_entry(dev, &bus->devices, bus_list) | ||
761 | if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) | ||
762 | pcibios_fixup_device_resources(dev, bus); | ||
763 | } | 694 | } |
764 | EXPORT_SYMBOL(pcibios_fixup_bus); | ||
765 | 695 | ||
766 | unsigned long pci_address_to_pio(phys_addr_t address) | 696 | unsigned long pci_address_to_pio(phys_addr_t address) |
767 | { | 697 | { |