From cb993029094ed61f286793819d3aaa1deea5b252 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 7 Dec 2007 02:00:45 +1100 Subject: [POWERPC] iSeries: Call iSeries_pcibios_init from setup_arch Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 9f63bdcb0bd..69364f3dc5c 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -519,9 +519,6 @@ static int __init pcibios_init(void) */ ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot; - if (firmware_has_feature(FW_FEATURE_ISERIES)) - iSeries_pcibios_init(); - printk(KERN_DEBUG "PCI: Probing PCI hardware\n"); /* Scan all of the recorded PCI controllers. */ -- cgit v1.2.3 From c96bede657510cfb171c0fd86fc710582a1c5a5f Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 11 Dec 2007 11:03:48 +1100 Subject: [POWERPC] iSeries: hose->buid is always zero for iSeries so remove a firmware feature test. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 69364f3dc5c..7e74aa2bfba 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -581,12 +581,8 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) /* Decide whether to display the domain number in /proc */ int pci_proc_domain(struct pci_bus *bus) { - if (firmware_has_feature(FW_FEATURE_ISERIES)) - return 0; - else { - struct pci_controller *hose = pci_bus_to_host(bus); - return hose->buid != 0; - } + struct pci_controller *hose = pci_bus_to_host(bus); + return hose->buid != 0; } void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, -- cgit v1.2.3 From 9ccc4fd260397f0f8ac6078f4cd45fda2d320ead Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 7 Dec 2007 02:03:23 +1100 Subject: [POWERPC] Remove some iSeries platform checks from the PCI code Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 7e74aa2bfba..002cd4cac0f 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -31,7 +31,6 @@ #include #include #include -#include #ifdef DEBUG #include @@ -197,9 +196,6 @@ static void __init pcibios_claim_of_setup(void) { struct pci_bus *b; - if (firmware_has_feature(FW_FEATURE_ISERIES)) - return; - list_for_each_entry(b, &pci_root_buses, node) pcibios_claim_one_bus(b); } @@ -477,8 +473,7 @@ void __devinit scan_phb(struct pci_controller *hose) bus->secondary = hose->first_busno; hose->bus = bus; - if (!firmware_has_feature(FW_FEATURE_ISERIES)) - pcibios_map_io_space(bus); + pcibios_map_io_space(bus); bus->resource[0] = res = &hose->io_resource; if (res->flags && request_resource(&ioport_resource, res)) { @@ -527,15 +522,13 @@ static int __init pcibios_init(void) pci_bus_add_devices(hose->bus); } - if (!firmware_has_feature(FW_FEATURE_ISERIES)) { - if (pci_probe_only) - pcibios_claim_of_setup(); - else - /* FIXME: `else' will be removed when - pci_assign_unassigned_resources() is able to work - correctly with [partially] allocated PCI tree. */ - pci_assign_unassigned_resources(); - } + if (pci_probe_only) + pcibios_claim_of_setup(); + else + /* FIXME: `else' will be removed when + pci_assign_unassigned_resources() is able to work + correctly with [partially] allocated PCI tree. */ + pci_assign_unassigned_resources(); /* Call machine dependent final fixup */ if (ppc_md.pcibios_fixup) -- cgit v1.2.3 From 44ef339073f67d4abcc62ae52a5fbc069d7a4d29 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 10 Dec 2007 14:33:21 +1100 Subject: [POWERPC] pci_controller->arch_data really is a struct device_node * Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 002cd4cac0f..6b9a8564e73 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -458,7 +458,7 @@ EXPORT_SYMBOL(of_scan_pci_bridge); void __devinit scan_phb(struct pci_controller *hose) { struct pci_bus *bus; - struct device_node *node = hose->arch_data; + struct device_node *node = hose->dn; int i, mode; struct resource *res; @@ -705,8 +705,7 @@ int pcibios_unmap_io_space(struct pci_bus *bus) if (hose->io_base_alloc == 0) return 0; - DBG("IO unmapping for PHB %s\n", - ((struct device_node *)hose->arch_data)->full_name); + DBG("IO unmapping for PHB %s\n", hose->dn->full_name); DBG(" alloc=0x%p\n", hose->io_base_alloc); /* This is a PHB, we fully unmap the IO area */ @@ -765,8 +764,7 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus) hose->io_base_virt = (void __iomem *)(area->addr + hose->io_base_phys - phys_page); - DBG("IO mapping for PHB %s\n", - ((struct device_node *)hose->arch_data)->full_name); + DBG("IO mapping for PHB %s\n", hose->dn->full_name); DBG(" phys=0x%016lx, virt=0x%p (alloc=0x%p)\n", hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc); DBG(" size=0x%016lx (alloc=0x%016lx)\n", -- cgit v1.2.3 From 13dccb9e65dc0fa4de83e5bd5639f7a7f3f6fb9e Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 11 Dec 2007 14:48:18 +1100 Subject: [POWERPC] Merge pci_process_bridge_OF_ranges() This merges the 32-bit and 64-bit implementations of pci_process_bridge_OF_ranges(). The new function is cleaner than both the old ones, and supports 64 bits ranges on ppc32 which is necessary for the 4xx port. It also adds some better (hopefully) output to the kernel log which should help diagnose problems and makes better use of existing OF parsing helpers (avoiding a few bugs of both implementations along the way). There are still a few unfortunate ifdef's but there is no way around these for now at least not until some other bits of the PCI code are made common. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 93 -------------------------------------------- 1 file changed, 93 deletions(-) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 6b9a8564e73..bf06926f677 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -578,99 +578,6 @@ int pci_proc_domain(struct pci_bus *bus) return hose->buid != 0; } -void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, - struct device_node *dev, int prim) -{ - const unsigned int *ranges; - unsigned int pci_space; - unsigned long size; - int rlen = 0; - int memno = 0; - struct resource *res; - int np, na = of_n_addr_cells(dev); - unsigned long pci_addr, cpu_phys_addr; - - np = na + 5; - - /* From "PCI Binding to 1275" - * The ranges property is laid out as an array of elements, - * each of which comprises: - * cells 0 - 2: a PCI address - * cells 3 or 3+4: a CPU physical address - * (size depending on dev->n_addr_cells) - * cells 4+5 or 5+6: the size of the range - */ - ranges = of_get_property(dev, "ranges", &rlen); - if (ranges == NULL) - return; - hose->io_base_phys = 0; - while ((rlen -= np * sizeof(unsigned int)) >= 0) { - res = NULL; - pci_space = ranges[0]; - pci_addr = ((unsigned long)ranges[1] << 32) | ranges[2]; - cpu_phys_addr = of_translate_address(dev, &ranges[3]); - size = ((unsigned long)ranges[na+3] << 32) | ranges[na+4]; - ranges += np; - if (size == 0) - continue; - - /* Now consume following elements while they are contiguous */ - while (rlen >= np * sizeof(unsigned int)) { - unsigned long addr, phys; - - if (ranges[0] != pci_space) - break; - addr = ((unsigned long)ranges[1] << 32) | ranges[2]; - phys = ranges[3]; - if (na >= 2) - phys = (phys << 32) | ranges[4]; - if (addr != pci_addr + size || - phys != cpu_phys_addr + size) - break; - - size += ((unsigned long)ranges[na+3] << 32) - | ranges[na+4]; - ranges += np; - rlen -= np * sizeof(unsigned int); - } - - switch ((pci_space >> 24) & 0x3) { - case 1: /* I/O space */ - hose->io_base_phys = cpu_phys_addr - pci_addr; - /* handle from 0 to top of I/O window */ - hose->pci_io_size = pci_addr + size; - - res = &hose->io_resource; - res->flags = IORESOURCE_IO; - res->start = pci_addr; - DBG("phb%d: IO 0x%lx -> 0x%lx\n", hose->global_number, - res->start, res->start + size - 1); - break; - case 2: /* memory space */ - memno = 0; - while (memno < 3 && hose->mem_resources[memno].flags) - ++memno; - - if (memno == 0) - hose->pci_mem_offset = cpu_phys_addr - pci_addr; - if (memno < 3) { - res = &hose->mem_resources[memno]; - res->flags = IORESOURCE_MEM; - res->start = cpu_phys_addr; - DBG("phb%d: MEM 0x%lx -> 0x%lx\n", hose->global_number, - res->start, res->start + size - 1); - } - break; - } - if (res != NULL) { - res->name = dev->full_name; - res->end = res->start + size - 1; - res->parent = NULL; - res->sibling = NULL; - res->child = NULL; - } - } -} #ifdef CONFIG_HOTPLUG -- cgit v1.2.3 From 84631f37cc405dd6dcd566f9fa4e8a3ca2f03f76 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 17 Dec 2007 17:35:53 +1100 Subject: [POWERPC] Implement pci_set_dma_mask() in terms of the dma_ops PowerPC currently doesn't implement pci_set_dma_mask(), which means drivers calling it will get the generic version in drivers/pci/pci.c. The powerpc dma mapping ops include a dma_set_mask() hook, which luckily is not implemented by anyone - so there is no bug in the fact that the hook is currently never called. However in future we'll add implementation(s) of dma_set_mask(), and so we need pci_set_dma_mask() to call the hook. To save adding a hook to the dma mapping ops, pci-set_consistent_dma_mask() simply calls the dma_set_mask() hook and then copies the new mask into dev.coherenet_dma_mask. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index bf06926f677..f5c4628698b 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -69,6 +69,22 @@ struct dma_mapping_ops *get_pci_dma_ops(void) } EXPORT_SYMBOL(get_pci_dma_ops); + +int pci_set_dma_mask(struct pci_dev *dev, u64 mask) +{ + return dma_set_mask(&dev->dev, mask); +} + +int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) +{ + int rc; + + rc = dma_set_mask(&dev->dev, mask); + dev->dev.coherent_dma_mask = dev->dma_mask; + + return rc; +} + static void fixup_broken_pcnet32(struct pci_dev* dev) { if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { -- cgit v1.2.3 From fc3fb71c3e1850a6a1099dd1cb7bcd7e69ac7b73 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 20 Dec 2007 14:54:46 +1100 Subject: [POWERPC] pci32: Add flags modifying the PCI code behaviour This adds to the 32 bits PCI code some flags, replacing the old pci_assign_all_busses global, that allow us to control various aspects of the PCI probing, such as whether to re-assign all resources or not, or to not try to assign anything at all. This also adds the flag x86 already has to avoid ISA alignment on bridges that don't have ISA forwarding enabled (no legacy devices on the top level bus) and sets it for PowerMacs. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index f5c4628698b..3e7cf7af3bf 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -40,7 +40,6 @@ #endif unsigned long pci_probe_only = 1; -int pci_assign_all_buses = 0; static void fixup_resource(struct resource *res, struct pci_dev *dev); static void do_bus_setup(struct pci_bus *bus); -- cgit v1.2.3 From fa462f2d75e2437b5757069d3d7d27b1e50285cb Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 20 Dec 2007 14:54:49 +1100 Subject: [POWERPC] pci32: Add platform option to enable /proc PCI domains This adds flags the platforms can use to enable domain numbers in /proc/bus/pci. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 3e7cf7af3bf..e0f3731c3a1 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -586,14 +586,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) return 0; } -/* Decide whether to display the domain number in /proc */ -int pci_proc_domain(struct pci_bus *bus) -{ - struct pci_controller *hose = pci_bus_to_host(bus); - return hose->buid != 0; -} - - #ifdef CONFIG_HOTPLUG int pcibios_unmap_io_space(struct pci_bus *bus) -- cgit v1.2.3 From fe2d338cdcc628e0abdb4f70570a7fa864c617db Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 20 Dec 2007 14:54:50 +1100 Subject: [POWERPC] Merge pcibios_resource_to_bus/bus_to_resource This merges the PowerPC 32 and 64 bits version of pcibios_resource_to_bus and pcibios_bus_to_resource(). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 42 ------------------------------------------ 1 file changed, 42 deletions(-) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index e0f3731c3a1..6d1c28fc5e2 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -93,48 +93,6 @@ static void fixup_broken_pcnet32(struct pci_dev* dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32); -void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, - struct resource *res) -{ - unsigned long offset = 0; - struct pci_controller *hose = pci_bus_to_host(dev->bus); - - if (!hose) - return; - - if (res->flags & IORESOURCE_IO) - offset = (unsigned long)hose->io_base_virt - _IO_BASE; - - if (res->flags & IORESOURCE_MEM) - offset = hose->pci_mem_offset; - - region->start = res->start - offset; - region->end = res->end - offset; -} - -void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, - struct pci_bus_region *region) -{ - unsigned long offset = 0; - struct pci_controller *hose = pci_bus_to_host(dev->bus); - - if (!hose) - return; - - if (res->flags & IORESOURCE_IO) - offset = (unsigned long)hose->io_base_virt - _IO_BASE; - - if (res->flags & IORESOURCE_MEM) - offset = hose->pci_mem_offset; - - res->start = region->start + offset; - res->end = region->end + offset; -} - -#ifdef CONFIG_HOTPLUG -EXPORT_SYMBOL(pcibios_resource_to_bus); -EXPORT_SYMBOL(pcibios_bus_to_resource); -#endif /* * We need to avoid collisions with `mirrored' VGA ports -- cgit v1.2.3 From bf5e2ba28f24f82a64524ef4772c9ebe12e2cd2a Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 20 Dec 2007 14:54:51 +1100 Subject: [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 Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 104 +++++++------------------------------------ 1 file changed, 17 insertions(+), 87 deletions(-) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 6d1c28fc5e2..b9619b9e5e0 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -41,9 +41,6 @@ unsigned long pci_probe_only = 1; -static void fixup_resource(struct resource *res, struct pci_dev *dev); -static void do_bus_setup(struct pci_bus *bus); - /* pci_io_base -- the base address from which io bars are offsets. * This is the lowest I/O base address (so bar values are always positive), * 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) res->end = base + size - 1; res->flags = flags; res->name = pci_name(dev); - fixup_resource(res, dev); } } @@ -308,7 +304,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, EXPORT_SYMBOL(of_create_pci_dev); void __devinit of_scan_bus(struct device_node *node, - struct pci_bus *bus) + struct pci_bus *bus) { struct device_node *child = NULL; const u32 *reg; @@ -317,6 +313,7 @@ void __devinit of_scan_bus(struct device_node *node, DBG("of_scan_bus(%s) bus no %d... \n", node->full_name, bus->number); + /* Scan direct children */ while ((child = of_get_next_child(node, child)) != NULL) { DBG(" * %s\n", child->full_name); reg = of_get_property(child, "reg", ®len); @@ -328,19 +325,26 @@ void __devinit of_scan_bus(struct device_node *node, dev = of_create_pci_dev(child, bus, devfn); if (!dev) continue; - DBG("dev header type: %x\n", dev->hdr_type); + DBG(" dev header type: %x\n", dev->hdr_type); + } + + /* Ally all fixups */ + pcibios_fixup_of_probed_bus(bus); + /* Now scan child busses */ + list_for_each_entry(dev, &bus->devices, bus_list) { if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || - dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) - of_scan_pci_bridge(child, dev); + dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { + struct device_node *child = pci_device_to_OF_node(dev); + if (dev) + of_scan_pci_bridge(child, dev); + } } - - do_bus_setup(bus); } EXPORT_SYMBOL(of_scan_bus); void __devinit of_scan_pci_bridge(struct device_node *node, - struct pci_dev *dev) + struct pci_dev *dev) { struct pci_bus *bus; const u32 *busrange, *ranges; @@ -410,7 +414,6 @@ void __devinit of_scan_pci_bridge(struct device_node *node, res->start = of_read_number(&ranges[1], 2); res->end = res->start + size - 1; res->flags = flags; - fixup_resource(res, dev); } sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), bus->number); @@ -659,51 +662,13 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus) } EXPORT_SYMBOL_GPL(pcibios_map_io_space); -static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - unsigned long offset; - - if (res->flags & IORESOURCE_IO) { - offset = (unsigned long)hose->io_base_virt - _IO_BASE; - res->start += offset; - res->end += offset; - } else if (res->flags & IORESOURCE_MEM) { - res->start += hose->pci_mem_offset; - res->end += hose->pci_mem_offset; - } -} - -void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, - struct pci_bus *bus) -{ - /* Update device resources. */ - int i; - - DBG("%s: Fixup resources:\n", pci_name(dev)); - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *res = &dev->resource[i]; - if (!res->flags) - continue; - - DBG(" 0x%02x < %08lx:0x%016lx...0x%016lx\n", - i, res->flags, res->start, res->end); - - fixup_resource(res, dev); - - DBG(" > %08lx:0x%016lx...0x%016lx\n", - res->flags, res->start, res->end); - } -} -EXPORT_SYMBOL(pcibios_fixup_device_resources); - void __devinit pcibios_setup_new_device(struct pci_dev *dev) { struct dev_archdata *sd = &dev->dev.archdata; sd->of_node = pci_device_to_OF_node(dev); - DBG("PCI device %s OF node: %s\n", pci_name(dev), + DBG("PCI: device %s OF node: %s\n", pci_name(dev), sd->of_node ? sd->of_node->full_name : ""); sd->dma_ops = pci_dma_ops; @@ -717,7 +682,7 @@ void __devinit pcibios_setup_new_device(struct pci_dev *dev) } EXPORT_SYMBOL(pcibios_setup_new_device); -static void __devinit do_bus_setup(struct pci_bus *bus) +void __devinit pcibios_do_bus_setup(struct pci_bus *bus) { struct pci_dev *dev; @@ -726,42 +691,7 @@ static void __devinit do_bus_setup(struct pci_bus *bus) list_for_each_entry(dev, &bus->devices, bus_list) pcibios_setup_new_device(dev); - - /* Read default IRQs and fixup if necessary */ - list_for_each_entry(dev, &bus->devices, bus_list) { - pci_read_irq_line(dev); - if (ppc_md.pci_irq_fixup) - ppc_md.pci_irq_fixup(dev); - } -} - -void __devinit pcibios_fixup_bus(struct pci_bus *bus) -{ - struct pci_dev *dev = bus->self; - struct device_node *np; - - np = pci_bus_to_OF_node(bus); - - DBG("pcibios_fixup_bus(%s)\n", np ? np->full_name : ""); - - if (dev && pci_probe_only && - (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { - /* This is a subordinate bridge */ - - pci_read_bridge_bases(bus); - pcibios_fixup_device_resources(dev, bus); - } - - do_bus_setup(bus); - - if (!pci_probe_only) - return; - - list_for_each_entry(dev, &bus->devices, bus_list) - if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) - pcibios_fixup_device_resources(dev, bus); } -EXPORT_SYMBOL(pcibios_fixup_bus); unsigned long pci_address_to_pio(phys_addr_t address) { -- cgit v1.2.3 From 3fd94c6b1a1158d3e0e505b0a00c3a707b5fcd40 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 20 Dec 2007 14:54:53 +1100 Subject: [POWERPC] Merge PCI resource allocation & assignment The 32 bits PCI code now uses the generic code for assigning unassigned resources and an algorithm similar to x86 for claiming existing ones. This works far better than the 64 bits code which basically can only claim existing ones (pci_probe_only=1) or would fall apart completely. This merges them so that the new 32 bits implementation is used for both. 64 bits now gets the new PCI flags for controlling the behaviour, though the old pci_probe_only global is still there for now to be cleared if you want to. I kept a pcibios_claim_one_bus() function mostly based on the old 64 bits code for use by the DLPAR hotplug. This will have to be cleaned up, thought I hope it will work in the meantime. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 118 +++++-------------------------------------- 1 file changed, 12 insertions(+), 106 deletions(-) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index b9619b9e5e0..794359d8686 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -91,85 +91,6 @@ static void fixup_broken_pcnet32(struct pci_dev* dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32); -/* - * We need to avoid collisions with `mirrored' VGA ports - * and other strange ISA hardware, so we always want the - * addresses to be allocated in the 0x000-0x0ff region - * modulo 0x400. - * - * Why? Because some silly external IO cards only decode - * the low 10 bits of the IO address. The 0x00-0xff region - * is reserved for motherboard devices that decode all 16 - * bits, so it's ok to allocate at, say, 0x2800-0x28ff, - * but we want to try to avoid allocating at 0x2900-0x2bff - * which might have be mirrored at 0x0100-0x03ff.. - */ -void pcibios_align_resource(void *data, struct resource *res, - resource_size_t size, resource_size_t align) -{ - struct pci_dev *dev = data; - struct pci_controller *hose = pci_bus_to_host(dev->bus); - resource_size_t start = res->start; - unsigned long alignto; - - if (res->flags & IORESOURCE_IO) { - unsigned long offset = (unsigned long)hose->io_base_virt - - _IO_BASE; - /* Make sure we start at our min on all hoses */ - if (start - offset < PCIBIOS_MIN_IO) - start = PCIBIOS_MIN_IO + offset; - - /* - * Put everything into 0x00-0xff region modulo 0x400 - */ - if (start & 0x300) - start = (start + 0x3ff) & ~0x3ff; - - } else if (res->flags & IORESOURCE_MEM) { - /* Make sure we start at our min on all hoses */ - if (start - hose->pci_mem_offset < PCIBIOS_MIN_MEM) - start = PCIBIOS_MIN_MEM + hose->pci_mem_offset; - - /* Align to multiple of size of minimum base. */ - alignto = max(0x1000UL, align); - start = ALIGN(start, alignto); - } - - res->start = start; -} - -void __devinit pcibios_claim_one_bus(struct pci_bus *b) -{ - struct pci_dev *dev; - struct pci_bus *child_bus; - - list_for_each_entry(dev, &b->devices, bus_list) { - int i; - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *r = &dev->resource[i]; - - if (r->parent || !r->start || !r->flags) - continue; - pci_claim_resource(dev, i); - } - } - - list_for_each_entry(child_bus, &b->children, node) - pcibios_claim_one_bus(child_bus); -} -#ifdef CONFIG_HOTPLUG -EXPORT_SYMBOL_GPL(pcibios_claim_one_bus); -#endif - -static void __init pcibios_claim_of_setup(void) -{ - struct pci_bus *b; - - list_for_each_entry(b, &pci_root_buses, node) - pcibios_claim_one_bus(b); -} - static u32 get_int_prop(struct device_node *np, const char *name, u32 def) { const u32 *prop; @@ -440,6 +361,7 @@ void __devinit scan_phb(struct pci_controller *hose) DBG("Scanning PHB %s\n", node ? node->full_name : ""); + /* Create an empty bus for the toplevel */ bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, node); if (bus == NULL) { printk(KERN_ERR "Failed to create bus for PCI domain %04x\n", @@ -449,26 +371,16 @@ void __devinit scan_phb(struct pci_controller *hose) bus->secondary = hose->first_busno; hose->bus = bus; + /* Get some IO space for the new PHB */ pcibios_map_io_space(bus); + /* Wire up PHB bus resources */ bus->resource[0] = res = &hose->io_resource; - if (res->flags && request_resource(&ioport_resource, res)) { - printk(KERN_ERR "Failed to request PCI IO region " - "on PCI domain %04x\n", hose->global_number); - DBG("res->start = 0x%016lx, res->end = 0x%016lx\n", - res->start, res->end); - } - - for (i = 0; i < 3; ++i) { - res = &hose->mem_resources[i]; - bus->resource[i+1] = res; - if (res->flags && request_resource(&iomem_resource, res)) - printk(KERN_ERR "Failed to request PCI memory region " - "on PCI domain %04x\n", hose->global_number); - } + for (i = 0; i < 3; ++i) + bus->resource[i+1] = &hose->mem_resources[i]; + /* Get probe mode and perform scan */ mode = PCI_PROBE_NORMAL; - if (node && ppc_md.pci_probe_mode) mode = ppc_md.pci_probe_mode(bus); DBG(" probe mode: %d\n", mode); @@ -485,12 +397,15 @@ static int __init pcibios_init(void) { struct pci_controller *hose, *tmp; + printk(KERN_INFO "PCI: Probing PCI hardware\n"); + /* For now, override phys_mem_access_prot. If we need it, * later, we may move that initialization to each ppc_md */ ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot; - printk(KERN_DEBUG "PCI: Probing PCI hardware\n"); + if (pci_probe_only) + ppc_pci_flags |= PPC_PCI_PROBE_ONLY; /* Scan all of the recorded PCI controllers. */ list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { @@ -498,17 +413,8 @@ static int __init pcibios_init(void) pci_bus_add_devices(hose->bus); } - if (pci_probe_only) - pcibios_claim_of_setup(); - else - /* FIXME: `else' will be removed when - pci_assign_unassigned_resources() is able to work - correctly with [partially] allocated PCI tree. */ - pci_assign_unassigned_resources(); - - /* Call machine dependent final fixup */ - if (ppc_md.pcibios_fixup) - ppc_md.pcibios_fixup(); + /* Call common code to handle resource allocation */ + pcibios_resource_survey(); printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); -- cgit v1.2.3 From 50c9bc2fc86fddd39eea6a12ceb81585bc2aafaa Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 20 Dec 2007 14:54:55 +1100 Subject: [POWERPC] fix iSeries PCI resource management The way iSeries manages PCI IO and Memory resources is a bit strange and is based on overriding the content of those resources with home cooked ones afterward. This changes it a bit to better integrate with the new resource handling so that the "virtual" tokens that iSeries replaces resources with are done from the proper per-device fixup hook, and bridge resources are set to enclose that token space. This fixes various things such as the output of /proc/iomem & ioports, among others. This also fixes up various boot messages as well. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 794359d8686..2ec040b314d 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -359,7 +359,7 @@ void __devinit scan_phb(struct pci_controller *hose) int i, mode; struct resource *res; - DBG("Scanning PHB %s\n", node ? node->full_name : ""); + DBG("PCI: Scanning PHB %s\n", node ? node->full_name : ""); /* Create an empty bus for the toplevel */ bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, node); @@ -375,9 +375,22 @@ void __devinit scan_phb(struct pci_controller *hose) pcibios_map_io_space(bus); /* Wire up PHB bus resources */ - bus->resource[0] = res = &hose->io_resource; - for (i = 0; i < 3; ++i) + if (hose->io_resource.flags) { + DBG("PCI: PHB IO resource = %016lx-%016lx [%lx]\n", + hose->io_resource.start, hose->io_resource.end, + hose->io_resource.flags); + bus->resource[0] = res = &hose->io_resource; + } + for (i = 0; i < 3; ++i) { + DBG("PCI: PHB MEM resource %d = %016lx-%016lx [%lx]\n", i, + hose->mem_resources[i].start, + hose->mem_resources[i].end, + hose->mem_resources[i].flags); bus->resource[i+1] = &hose->mem_resources[i]; + } + DBG("PCI: PHB MEM offset = %016lx\n", hose->pci_mem_offset); + DBG("PCI: PHB IO offset = %08lx\n", + (unsigned long)hose->io_base_virt - _IO_BASE); /* Get probe mode and perform scan */ mode = PCI_PROBE_NORMAL; -- cgit v1.2.3 From 549beb9ba3b03345cbd8e1233825d5b197a3f9f7 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 20 Dec 2007 14:54:57 +1100 Subject: [POWERPC] Merge 32 and 64 bits pcibios_enable_device This merge the two implementations, based on the previously fixed up 32 bits one. The pcibios_enable_device_hook in ppc_md is now available for ppc64 use. Also remove the new unused "initial" parameter from it and fixup users. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 30 ------------------------------ 1 file changed, 30 deletions(-) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 2ec040b314d..5949bbabd7f 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -436,36 +436,6 @@ static int __init pcibios_init(void) subsys_initcall(pcibios_init); -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - u16 cmd, oldcmd; - int i; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - oldcmd = cmd; - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *res = &dev->resource[i]; - - /* Only set up the requested stuff */ - if (!(mask & (1<flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (res->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - - if (cmd != oldcmd) { - printk(KERN_DEBUG "PCI: Enabling device: (%s), cmd %x\n", - pci_name(dev), cmd); - /* Enable the appropriate bits in the PCI command register. */ - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - #ifdef CONFIG_HOTPLUG int pcibios_unmap_io_space(struct pci_bus *bus) -- cgit v1.2.3 From 85e99b9fffb62e101e38c74c935256fc589703c2 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 3 Jan 2008 15:13:37 +1100 Subject: [POWERPC] arch/powerpc/kernel: Use for_each_child_of_node Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 5949bbabd7f..1930f393d01 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -227,7 +227,7 @@ EXPORT_SYMBOL(of_create_pci_dev); void __devinit of_scan_bus(struct device_node *node, struct pci_bus *bus) { - struct device_node *child = NULL; + struct device_node *child; const u32 *reg; int reglen, devfn; struct pci_dev *dev; @@ -235,7 +235,7 @@ void __devinit of_scan_bus(struct device_node *node, DBG("of_scan_bus(%s) bus no %d... \n", node->full_name, bus->number); /* Scan direct children */ - while ((child = of_get_next_child(node, child)) != NULL) { + for_each_child_of_node(node, child) { DBG(" * %s\n", child->full_name); reg = of_get_property(child, "reg", ®len); if (reg == NULL || reglen < 20) -- cgit v1.2.3 From 9d5f49283b85d925f17fa07af5e4879465e179d6 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 21 Jan 2008 11:32:50 +1100 Subject: [POWERPC] Always hookup PHB IO resource even when empty We must always hookup the pci_bus resource 0 to the PHB io_resource even if the latter is empty (the bus has no IO support). Otherwise, some other code will end up hooking it up to something bogus and the resource tree will end up being broken. This fixes boot on QS20 Cell blades where the IDE driver failed to allocate the IO resources due to breakage of the resource tree. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'arch/powerpc/kernel/pci_64.c') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 1930f393d01..52750745edf 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -357,7 +357,6 @@ void __devinit scan_phb(struct pci_controller *hose) struct pci_bus *bus; struct device_node *node = hose->dn; int i, mode; - struct resource *res; DBG("PCI: Scanning PHB %s\n", node ? node->full_name : ""); @@ -375,12 +374,10 @@ void __devinit scan_phb(struct pci_controller *hose) pcibios_map_io_space(bus); /* Wire up PHB bus resources */ - if (hose->io_resource.flags) { - DBG("PCI: PHB IO resource = %016lx-%016lx [%lx]\n", - hose->io_resource.start, hose->io_resource.end, - hose->io_resource.flags); - bus->resource[0] = res = &hose->io_resource; - } + DBG("PCI: PHB IO resource = %016lx-%016lx [%lx]\n", + hose->io_resource.start, hose->io_resource.end, + hose->io_resource.flags); + bus->resource[0] = &hose->io_resource; for (i = 0; i < 3; ++i) { DBG("PCI: PHB MEM resource %d = %016lx-%016lx [%lx]\n", i, hose->mem_resources[i].start, -- cgit v1.2.3