From abfd336cd79ea154dc71f09272f578a731b81d8c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 26 Feb 2007 09:40:34 -0800 Subject: [SPARC64]: Fix arch_teardown_msi_irq(). Need to use get_irq_msi() not get_irq_data(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/sparc64/kernel/pci.c') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 6b740eb6fe7e..6fedfb98f8b0 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -668,7 +668,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) void arch_teardown_msi_irq(unsigned int virt_irq) { - struct msi_desc *entry = get_irq_data(virt_irq); + struct msi_desc *entry = get_irq_msi(virt_irq); struct pci_dev *pdev = entry->dev; struct pcidev_cookie *pcp = pdev->sysdata; struct pci_pbm_info *pbm = pcp->pbm; -- cgit v1.2.3 From f6d0f9ea55277a49ef6c86a768acec021451b139 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 1 Mar 2007 18:09:18 -0800 Subject: [SPARC]: Provide pci_device_to_OF_node() just like powerpc. Signed-off-by: David S. Miller --- arch/sparc/kernel/pcic.c | 8 ++++++++ arch/sparc64/kernel/pci.c | 8 ++++++++ include/asm-sparc/pci.h | 3 +++ include/asm-sparc64/pci.h | 3 +++ 4 files changed, 22 insertions(+) (limited to 'arch/sparc64/kernel/pci.c') diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 207f1b6eef53..3fa5f95c4614 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -944,6 +944,14 @@ int pcibios_assign_resource(struct pci_dev *pdev, int resource) return -ENXIO; } +struct device_node *pci_device_to_OF_node(struct pci_dev *pdev) +{ + struct pcidev_cookie *pc = pdev->sysdata; + + return pc->prom_node; +} +EXPORT_SYMBOL(pci_device_to_OF_node); + /* * This probably belongs here rather than ioport.c because * we do not want this crud linked into SBus kernels. diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 6fedfb98f8b0..196b4b72482b 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -681,4 +681,12 @@ void arch_teardown_msi_irq(unsigned int virt_irq) } #endif /* !(CONFIG_PCI_MSI) */ +struct device_node *pci_device_to_OF_node(struct pci_dev *pdev) +{ + struct pcidev_cookie *pc = pdev->sysdata; + + return pc->op->node; +} +EXPORT_SYMBOL(pci_device_to_OF_node); + #endif /* !(CONFIG_PCI) */ diff --git a/include/asm-sparc/pci.h b/include/asm-sparc/pci.h index 38644742f011..a750c688408b 100644 --- a/include/asm-sparc/pci.h +++ b/include/asm-sparc/pci.h @@ -165,6 +165,9 @@ static inline int pci_dma_mapping_error(dma_addr_t dma_addr) return (dma_addr == PCI_DMA_ERROR_CODE); } +struct device_node; +extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev); + #endif /* __KERNEL__ */ /* generic pci stuff */ diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h index ca6560288ae8..b14a725b430d 100644 --- a/include/asm-sparc64/pci.h +++ b/include/asm-sparc64/pci.h @@ -312,6 +312,9 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) return PCI_IRQ_NONE; } +struct device_node; +extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev); + #endif /* __KERNEL__ */ #endif /* __SPARC64_PCI_H */ -- cgit v1.2.3 From f6b45da1299f1f2e92a1446cfa400be53fdc5c99 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Thu, 12 Apr 2007 13:47:37 -0700 Subject: [SPARC]: Fix section mismatch warnings in pci.c and pcic.c Fix section mismatch in arch/sparc/kernel/pcic.c and arch/sparc64/kernel/pci.c. Signed-off-by: Robert Reif Signed-off-by: David S. Miller --- arch/sparc/kernel/pcic.c | 4 ++-- arch/sparc64/kernel/pci.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/sparc64/kernel/pci.c') diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 3fa5f95c4614..1c927c538b8b 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -601,7 +601,7 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node) /* * Normally called from {do_}pci_scan_bus... */ -void __init pcibios_fixup_bus(struct pci_bus *bus) +void __devinit pcibios_fixup_bus(struct pci_bus *bus) { struct pci_dev *dev; int i, has_io, has_mem; @@ -842,7 +842,7 @@ static void watchdog_reset() { /* * Other archs parse arguments here. */ -char * __init pcibios_setup(char *str) +char * __devinit pcibios_setup(char *str) { return str; } diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 196b4b72482b..12109886bb1e 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -327,7 +327,7 @@ static int __init pcibios_init(void) subsys_initcall(pcibios_init); -void pcibios_fixup_bus(struct pci_bus *pbus) +void __devinit pcibios_fixup_bus(struct pci_bus *pbus) { struct pci_pbm_info *pbm = pbus->sysdata; @@ -405,7 +405,7 @@ void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res, } EXPORT_SYMBOL(pcibios_bus_to_resource); -char * __init pcibios_setup(char *str) +char * __devinit pcibios_setup(char *str) { return str; } -- cgit v1.2.3 From a2fb23af1c31ad6e0c281e56d385f803229d57fa Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 28 Feb 2007 23:35:04 -0800 Subject: [SPARC64]: Probe PCI bus using OF device tree. Almost entirely taken from the 64-bit PowerPC PCI code. This allowed to eliminate a ton of cruft from the sparc64 PCI layer. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 375 ++++++++++++++++++++- arch/sparc64/kernel/pci_common.c | 707 --------------------------------------- arch/sparc64/kernel/pci_impl.h | 15 +- arch/sparc64/kernel/pci_iommu.c | 47 +-- arch/sparc64/kernel/pci_psycho.c | 26 +- arch/sparc64/kernel/pci_sabre.c | 53 +-- arch/sparc64/kernel/pci_schizo.c | 26 +- arch/sparc64/kernel/pci_sun4v.c | 199 ++--------- include/asm-sparc64/device.h | 18 +- include/asm-sparc64/pbm.h | 23 -- 10 files changed, 426 insertions(+), 1063 deletions(-) (limited to 'arch/sparc64/kernel/pci.c') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 12109886bb1e..246b8009a2b4 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -1,9 +1,11 @@ -/* $Id: pci.c,v 1.39 2002/01/05 01:13:43 davem Exp $ - * pci.c: UltraSparc PCI controller support. +/* pci.c: UltraSparc PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com) * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) + * + * OF tree based PCI bus probing taken from the PowerPC port + * with minor modifications, see there for credits. */ #include @@ -300,6 +302,329 @@ static void __init pci_controller_probe(void) pci_controller_scan(pci_controller_init); } +static unsigned long pci_parse_of_flags(u32 addr0) +{ + unsigned long flags = 0; + + if (addr0 & 0x02000000) { + flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY; + flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64; + flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M; + if (addr0 & 0x40000000) + flags |= IORESOURCE_PREFETCH + | PCI_BASE_ADDRESS_MEM_PREFETCH; + } else if (addr0 & 0x01000000) + flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO; + return flags; +} + +/* The of_device layer has translated all of the assigned-address properties + * into physical address resources, we only have to figure out the register + * mapping. + */ +static void pci_parse_of_addrs(struct of_device *op, + struct device_node *node, + struct pci_dev *dev) +{ + struct resource *op_res; + const u32 *addrs; + int proplen; + + addrs = of_get_property(node, "assigned-addresses", &proplen); + if (!addrs) + return; + printk(" parse addresses (%d bytes) @ %p\n", proplen, addrs); + op_res = &op->resource[0]; + for (; proplen >= 20; proplen -= 20, addrs += 5, op_res++) { + struct resource *res; + unsigned long flags; + int i; + + flags = pci_parse_of_flags(addrs[0]); + if (!flags) + continue; + i = addrs[0] & 0xff; + printk(" start: %lx, end: %lx, i: %x\n", + op_res->start, op_res->end, i); + + if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) { + res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2]; + } else if (i == dev->rom_base_reg) { + res = &dev->resource[PCI_ROM_RESOURCE]; + flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE; + } else { + printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i); + continue; + } + res->start = op_res->start; + res->end = op_res->end; + res->flags = flags; + res->name = pci_name(dev); + } +} + +struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, + struct device_node *node, + struct pci_bus *bus, int devfn) +{ + struct dev_archdata *sd; + struct pci_dev *dev; + const char *type; + + dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); + if (!dev) + return NULL; + + sd = &dev->dev.archdata; + sd->iommu = pbm->iommu; + sd->stc = &pbm->stc; + sd->host_controller = pbm; + sd->prom_node = node; + sd->op = of_find_device_by_node(node); + sd->msi_num = 0xffffffff; + + type = of_get_property(node, "device_type", NULL); + if (type == NULL) + type = ""; + + printk(" create device, devfn: %x, type: %s\n", devfn, type); + + dev->bus = bus; + dev->sysdata = node; + dev->dev.parent = bus->bridge; + dev->dev.bus = &pci_bus_type; + dev->devfn = devfn; + dev->multifunction = 0; /* maybe a lie? */ + + dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff); + dev->device = of_getintprop_default(node, "device-id", 0xffff); + dev->subsystem_vendor = + of_getintprop_default(node, "subsystem-vendor-id", 0); + dev->subsystem_device = + of_getintprop_default(node, "subsystem-id", 0); + + dev->cfg_size = pci_cfg_space_size(dev); + + sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), + dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); + dev->class = of_getintprop_default(node, "class-code", 0); + + printk(" class: 0x%x\n", dev->class); + + dev->current_state = 4; /* unknown power state */ + dev->error_state = pci_channel_io_normal; + + if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { + /* a PCI-PCI bridge */ + dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; + dev->rom_base_reg = PCI_ROM_ADDRESS1; + } else if (!strcmp(type, "cardbus")) { + dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; + } else { + dev->hdr_type = PCI_HEADER_TYPE_NORMAL; + dev->rom_base_reg = PCI_ROM_ADDRESS; + + dev->irq = sd->op->irqs[0]; + if (dev->irq == 0xffffffff) + dev->irq = PCI_IRQ_NONE; + } + + pci_parse_of_addrs(sd->op, node, dev); + + printk(" adding to system ...\n"); + + pci_device_add(dev, bus); + + return dev; +} + +static void __init pci_of_scan_bus(struct pci_pbm_info *pbm, + struct device_node *node, + struct pci_bus *bus); + +#define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1]) + +void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, + struct device_node *node, + struct pci_dev *dev) +{ + struct pci_bus *bus; + const u32 *busrange, *ranges; + int len, i; + struct resource *res; + unsigned int flags; + u64 size; + + printk("of_scan_pci_bridge(%s)\n", node->full_name); + + /* parse bus-range property */ + busrange = of_get_property(node, "bus-range", &len); + if (busrange == NULL || len != 8) { + printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n", + node->full_name); + return; + } + ranges = of_get_property(node, "ranges", &len); + if (ranges == NULL) { + printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n", + node->full_name); + return; + } + + bus = pci_add_new_bus(dev->bus, dev, busrange[0]); + if (!bus) { + printk(KERN_ERR "Failed to create pci bus for %s\n", + node->full_name); + return; + } + + bus->primary = dev->bus->number; + bus->subordinate = busrange[1]; + bus->bridge_ctl = 0; + + /* parse ranges property */ + /* PCI #address-cells == 3 and #size-cells == 2 always */ + res = &dev->resource[PCI_BRIDGE_RESOURCES]; + for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) { + res->flags = 0; + bus->resource[i] = res; + ++res; + } + i = 1; + for (; len >= 32; len -= 32, ranges += 8) { + struct resource *root; + + flags = pci_parse_of_flags(ranges[0]); + size = GET_64BIT(ranges, 6); + if (flags == 0 || size == 0) + continue; + if (flags & IORESOURCE_IO) { + res = bus->resource[0]; + if (res->flags) { + printk(KERN_ERR "PCI: ignoring extra I/O range" + " for bridge %s\n", node->full_name); + continue; + } + root = &pbm->io_space; + } else { + if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) { + printk(KERN_ERR "PCI: too many memory ranges" + " for bridge %s\n", node->full_name); + continue; + } + res = bus->resource[i]; + ++i; + root = &pbm->mem_space; + } + + res->start = GET_64BIT(ranges, 1); + res->end = res->start + size - 1; + res->flags = flags; + + /* Another way to implement this would be to add an of_device + * layer routine that can calculate a resource for a given + * range property value in a PCI device. + */ + pbm->parent->resource_adjust(dev, res, root); + } + sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), + bus->number); + printk(" bus name: %s\n", bus->name); + + pci_of_scan_bus(pbm, node, bus); +} + +static void __init pci_of_scan_bus(struct pci_pbm_info *pbm, + struct device_node *node, + struct pci_bus *bus) +{ + struct device_node *child; + const u32 *reg; + int reglen, devfn; + struct pci_dev *dev; + + printk("PCI: scan_bus[%s] bus no %d\n", + node->full_name, bus->number); + + child = NULL; + while ((child = of_get_next_child(node, child)) != NULL) { + printk(" * %s\n", child->full_name); + reg = of_get_property(child, "reg", ®len); + if (reg == NULL || reglen < 20) + continue; + devfn = (reg[0] >> 8) & 0xff; + + /* create a new pci_dev for this device */ + dev = of_create_pci_dev(pbm, child, bus, devfn); + if (!dev) + continue; + printk("PCI: dev header type: %x\n", dev->hdr_type); + + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || + dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) + of_scan_pci_bridge(pbm, child, dev); + } +} + +static ssize_t +show_pciobppath_attr(struct device * dev, struct device_attribute * attr, char * buf) +{ + struct pci_dev *pdev; + struct device_node *dp; + + pdev = to_pci_dev(dev); + dp = pdev->dev.archdata.prom_node; + + return snprintf (buf, PAGE_SIZE, "%s\n", dp->full_name); +} + +static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, NULL); + +static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) +{ + struct pci_dev *dev; + int err; + + list_for_each_entry(dev, &bus->devices, bus_list) { + /* we don't really care if we can create this file or + * not, but we need to assign the result of the call + * or the world will fall under alien invasion and + * everybody will be frozen on a spaceship ready to be + * eaten on alpha centauri by some green and jelly + * humanoid. + */ + err = sysfs_create_file(&dev->dev.kobj, &dev_attr_obppath.attr); + } +} + +struct pci_bus * __init pci_scan_one_pbm(struct pci_pbm_info *pbm) +{ + struct pci_controller_info *p = pbm->parent; + struct device_node *node = pbm->prom_node; + struct pci_bus *bus; + + printk("PCI: Scanning PBM %s\n", node->full_name); + + /* XXX parent device? XXX */ + bus = pci_create_bus(NULL, pbm->pci_first_busno, p->pci_ops, pbm); + if (!bus) { + printk(KERN_ERR "Failed to create bus for %s\n", + node->full_name); + return NULL; + } + bus->secondary = pbm->pci_first_busno; + bus->subordinate = pbm->pci_last_busno; + + bus->resource[0] = &pbm->io_space; + bus->resource[1] = &pbm->mem_space; + + pci_of_scan_bus(pbm, node, bus); + pci_bus_add_devices(bus); + pci_bus_register_of_sysfs(bus); + + return bus; +} + static void __init pci_scan_each_controller_bus(void) { struct pci_controller_info *p; @@ -360,8 +685,33 @@ void pcibios_align_resource(void *data, struct resource *res, { } -int pcibios_enable_device(struct pci_dev *pdev, int mask) +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; } @@ -422,17 +772,10 @@ char * __devinit pcibios_setup(char *str) static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm; + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; struct pci_controller_info *p; unsigned long space_size, user_offset, user_size; - if (!pcp) - return -ENXIO; - pbm = pcp->pbm; - if (!pbm) - return -ENXIO; - p = pbm->parent; if (p->pbms_same_domain) { unsigned long lowest, highest; @@ -651,8 +994,7 @@ EXPORT_SYMBOL(pci_domain_nr); #ifdef CONFIG_PCI_MSI int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; struct pci_controller_info *p = pbm->parent; int virt_irq, err; @@ -670,8 +1012,7 @@ void arch_teardown_msi_irq(unsigned int virt_irq) { struct msi_desc *entry = get_irq_msi(virt_irq); struct pci_dev *pdev = entry->dev; - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; struct pci_controller_info *p = pbm->parent; if (!pbm->msi_num || !p->setup_msi_irq) @@ -683,9 +1024,7 @@ void arch_teardown_msi_irq(unsigned int virt_irq) struct device_node *pci_device_to_OF_node(struct pci_dev *pdev) { - struct pcidev_cookie *pc = pdev->sysdata; - - return pc->op->node; + return pdev->dev.archdata.prom_node; } EXPORT_SYMBOL(pci_device_to_OF_node); diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 5a92cb90ebe0..0d3c95df0d95 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -16,713 +16,6 @@ #include "pci_impl.h" -/* Fix self device of BUS and hook it into BUS->self. - * The pci_scan_bus does not do this for the host bridge. - */ -void __init pci_fixup_host_bridge_self(struct pci_bus *pbus) -{ - struct pci_dev *pdev; - - list_for_each_entry(pdev, &pbus->devices, bus_list) { - if (pdev->class >> 8 == PCI_CLASS_BRIDGE_HOST) { - pbus->self = pdev; - return; - } - } - - prom_printf("PCI: Critical error, cannot find host bridge PDEV.\n"); - prom_halt(); -} - -/* Find the OBP PROM device tree node for a PCI device. */ -static struct device_node * __init -find_device_prom_node(struct pci_pbm_info *pbm, struct pci_dev *pdev, - struct device_node *bus_node, - struct linux_prom_pci_registers **pregs, - int *nregs) -{ - struct device_node *dp; - - *nregs = 0; - - /* - * Return the PBM's PROM node in case we are it's PCI device, - * as the PBM's reg property is different to standard PCI reg - * properties. We would delete this device entry otherwise, - * which confuses XFree86's device probing... - */ - if ((pdev->bus->number == pbm->pci_bus->number) && (pdev->devfn == 0) && - (pdev->vendor == PCI_VENDOR_ID_SUN) && - (pdev->device == PCI_DEVICE_ID_SUN_PBM || - pdev->device == PCI_DEVICE_ID_SUN_SCHIZO || - pdev->device == PCI_DEVICE_ID_SUN_TOMATILLO || - pdev->device == PCI_DEVICE_ID_SUN_SABRE || - pdev->device == PCI_DEVICE_ID_SUN_HUMMINGBIRD)) - return bus_node; - - dp = bus_node->child; - while (dp) { - struct linux_prom_pci_registers *regs; - struct property *prop; - int len; - - prop = of_find_property(dp, "reg", &len); - if (!prop) - goto do_next_sibling; - - regs = prop->value; - if (((regs[0].phys_hi >> 8) & 0xff) == pdev->devfn) { - *pregs = regs; - *nregs = len / sizeof(struct linux_prom_pci_registers); - return dp; - } - - do_next_sibling: - dp = dp->sibling; - } - - return NULL; -} - -/* Older versions of OBP on PCI systems encode 64-bit MEM - * space assignments incorrectly, this fixes them up. We also - * take the opportunity here to hide other kinds of bogus - * assignments. - */ -static void __init fixup_obp_assignments(struct pci_dev *pdev, - struct pcidev_cookie *pcp) -{ - int i; - - if (pdev->vendor == PCI_VENDOR_ID_AL && - (pdev->device == PCI_DEVICE_ID_AL_M7101 || - pdev->device == PCI_DEVICE_ID_AL_M1533)) { - int i; - - /* Zap all of the normal resources, they are - * meaningless and generate bogus resource collision - * messages. This is OpenBoot's ill-fated attempt to - * represent the implicit resources that these devices - * have. - */ - pcp->num_prom_assignments = 0; - for (i = 0; i < 6; i++) { - pdev->resource[i].start = - pdev->resource[i].end = - pdev->resource[i].flags = 0; - } - pdev->resource[PCI_ROM_RESOURCE].start = - pdev->resource[PCI_ROM_RESOURCE].end = - pdev->resource[PCI_ROM_RESOURCE].flags = 0; - return; - } - - for (i = 0; i < pcp->num_prom_assignments; i++) { - struct linux_prom_pci_registers *ap; - int space; - - ap = &pcp->prom_assignments[i]; - space = ap->phys_hi >> 24; - if ((space & 0x3) == 2 && - (space & 0x4) != 0) { - ap->phys_hi &= ~(0x7 << 24); - ap->phys_hi |= 0x3 << 24; - } - } -} - -static ssize_t -show_pciobppath_attr(struct device * dev, struct device_attribute * attr, char * buf) -{ - struct pci_dev *pdev; - struct pcidev_cookie *sysdata; - - pdev = to_pci_dev(dev); - sysdata = pdev->sysdata; - - return snprintf (buf, PAGE_SIZE, "%s\n", sysdata->prom_node->full_name); -} - -static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, NULL); - -/* Fill in the PCI device cookie sysdata for the given - * PCI device. This cookie is the means by which one - * can get to OBP and PCI controller specific information - * for a PCI device. - */ -static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm, - struct pci_dev *pdev, - struct device_node *bus_node) -{ - struct linux_prom_pci_registers *pregs = NULL; - struct pcidev_cookie *pcp; - struct device_node *dp; - struct property *prop; - int nregs, len, err; - - dp = find_device_prom_node(pbm, pdev, bus_node, - &pregs, &nregs); - if (!dp) { - /* If it is not in the OBP device tree then - * there must be a damn good reason for it. - * - * So what we do is delete the device from the - * PCI device tree completely. This scenario - * is seen, for example, on CP1500 for the - * second EBUS/HappyMeal pair if the external - * connector for it is not present. - */ - pci_remove_bus_device(pdev); - return; - } - - pcp = kzalloc(sizeof(*pcp), GFP_ATOMIC); - if (pcp == NULL) { - prom_printf("PCI_COOKIE: Fatal malloc error, aborting...\n"); - prom_halt(); - } - pcp->pbm = pbm; - pcp->prom_node = dp; - pcp->op = of_find_device_by_node(dp); - memcpy(pcp->prom_regs, pregs, - nregs * sizeof(struct linux_prom_pci_registers)); - pcp->num_prom_regs = nregs; - - /* We can't have the pcidev_cookie assignments be just - * direct pointers into the property value, since they - * are potentially modified by the probing process. - */ - prop = of_find_property(dp, "assigned-addresses", &len); - if (!prop) { - pcp->num_prom_assignments = 0; - } else { - memcpy(pcp->prom_assignments, prop->value, len); - pcp->num_prom_assignments = - (len / sizeof(pcp->prom_assignments[0])); - } - - if (strcmp(dp->name, "ebus") == 0) { - struct linux_prom_ebus_ranges *erng; - int iter; - - /* EBUS is special... */ - prop = of_find_property(dp, "ranges", &len); - if (!prop) { - prom_printf("EBUS: Fatal error, no range property\n"); - prom_halt(); - } - erng = prop->value; - len = (len / sizeof(erng[0])); - for (iter = 0; iter < len; iter++) { - struct linux_prom_ebus_ranges *ep = &erng[iter]; - struct linux_prom_pci_registers *ap; - - ap = &pcp->prom_assignments[iter]; - - ap->phys_hi = ep->parent_phys_hi; - ap->phys_mid = ep->parent_phys_mid; - ap->phys_lo = ep->parent_phys_lo; - ap->size_hi = 0; - ap->size_lo = ep->size; - } - pcp->num_prom_assignments = len; - } - - fixup_obp_assignments(pdev, pcp); - - pdev->sysdata = pcp; - - /* we don't really care if we can create this file or not, - * but we need to assign the result of the call or the world will fall - * under alien invasion and everybody will be frozen on a spaceship - * ready to be eaten on alpha centauri by some green and jelly humanoid. - */ - err = sysfs_create_file(&pdev->dev.kobj, &dev_attr_obppath.attr); -} - -void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus, - struct pci_pbm_info *pbm, - struct device_node *dp) -{ - struct pci_dev *pdev, *pdev_next; - struct pci_bus *this_pbus, *pbus_next; - - /* This must be _safe because the cookie fillin - routine can delete devices from the tree. */ - list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list) - pdev_cookie_fillin(pbm, pdev, dp); - - list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) { - struct pcidev_cookie *pcp = this_pbus->self->sysdata; - - pci_fill_in_pbm_cookies(this_pbus, pbm, pcp->prom_node); - } -} - -static void __init bad_assignment(struct pci_dev *pdev, - struct linux_prom_pci_registers *ap, - struct resource *res, - int do_prom_halt) -{ - prom_printf("PCI: Bogus PROM assignment. BUS[%02x] DEVFN[%x]\n", - pdev->bus->number, pdev->devfn); - if (ap) - prom_printf("PCI: phys[%08x:%08x:%08x] size[%08x:%08x]\n", - ap->phys_hi, ap->phys_mid, ap->phys_lo, - ap->size_hi, ap->size_lo); - if (res) - prom_printf("PCI: RES[%016lx-->%016lx:(%lx)]\n", - res->start, res->end, res->flags); - if (do_prom_halt) - prom_halt(); -} - -static struct resource * -__init get_root_resource(struct linux_prom_pci_registers *ap, - struct pci_pbm_info *pbm) -{ - int space = (ap->phys_hi >> 24) & 3; - - switch (space) { - case 0: - /* Configuration space, silently ignore it. */ - return NULL; - - case 1: - /* 16-bit IO space */ - return &pbm->io_space; - - case 2: - /* 32-bit MEM space */ - return &pbm->mem_space; - - case 3: - /* 64-bit MEM space, these are allocated out of - * the 32-bit mem_space range for the PBM, ie. - * we just zero out the upper 32-bits. - */ - return &pbm->mem_space; - - default: - printk("PCI: What is resource space %x?\n", space); - return NULL; - }; -} - -static struct resource * -__init get_device_resource(struct linux_prom_pci_registers *ap, - struct pci_dev *pdev) -{ - struct resource *res; - int breg = (ap->phys_hi & 0xff); - - switch (breg) { - case PCI_ROM_ADDRESS: - /* Unfortunately I have seen several cases where - * buggy FCODE uses a space value of '1' (I/O space) - * in the register property for the ROM address - * so disable this sanity check for now. - */ -#if 0 - { - int space = (ap->phys_hi >> 24) & 3; - - /* It had better be MEM space. */ - if (space != 2) - bad_assignment(pdev, ap, NULL, 0); - } -#endif - res = &pdev->resource[PCI_ROM_RESOURCE]; - break; - - case PCI_BASE_ADDRESS_0: - case PCI_BASE_ADDRESS_1: - case PCI_BASE_ADDRESS_2: - case PCI_BASE_ADDRESS_3: - case PCI_BASE_ADDRESS_4: - case PCI_BASE_ADDRESS_5: - res = &pdev->resource[(breg - PCI_BASE_ADDRESS_0) / 4]; - break; - - default: - bad_assignment(pdev, ap, NULL, 0); - res = NULL; - break; - }; - - return res; -} - -static void __init pdev_record_assignments(struct pci_pbm_info *pbm, - struct pci_dev *pdev) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - int i; - - for (i = 0; i < pcp->num_prom_assignments; i++) { - struct linux_prom_pci_registers *ap; - struct resource *root, *res; - - /* The format of this property is specified in - * the PCI Bus Binding to IEEE1275-1994. - */ - ap = &pcp->prom_assignments[i]; - root = get_root_resource(ap, pbm); - res = get_device_resource(ap, pdev); - if (root == NULL || res == NULL || - res->flags == 0) - continue; - - /* Ok we know which resource this PROM assignment is - * for, sanity check it. - */ - if ((res->start & 0xffffffffUL) != ap->phys_lo) - bad_assignment(pdev, ap, res, 1); - - /* If it is a 64-bit MEM space assignment, verify that - * the resource is too and that the upper 32-bits match. - */ - if (((ap->phys_hi >> 24) & 3) == 3) { - if (((res->flags & IORESOURCE_MEM) == 0) || - ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) - != PCI_BASE_ADDRESS_MEM_TYPE_64)) - bad_assignment(pdev, ap, res, 1); - if ((res->start >> 32) != ap->phys_mid) - bad_assignment(pdev, ap, res, 1); - - /* PBM cannot generate cpu initiated PIOs - * to the full 64-bit space. Therefore the - * upper 32-bits better be zero. If it is - * not, just skip it and we will assign it - * properly ourselves. - */ - if ((res->start >> 32) != 0UL) { - printk(KERN_ERR "PCI: OBP assigns out of range MEM address " - "%016lx for region %ld on device %s\n", - res->start, (res - &pdev->resource[0]), pci_name(pdev)); - continue; - } - } - - /* Adjust the resource into the physical address space - * of this PBM. - */ - pbm->parent->resource_adjust(pdev, res, root); - - if (request_resource(root, res) < 0) { - int rnum; - - /* OK, there is some conflict. But this is fine - * since we'll reassign it in the fixup pass. - * - * Do not print the warning for ROM resources - * as such a conflict is quite common and - * harmless as the ROM bar is disabled. - */ - rnum = (res - &pdev->resource[0]); - if (rnum != PCI_ROM_RESOURCE) - printk(KERN_ERR "PCI: Resource collision, " - "region %d " - "[%016lx:%016lx] of device %s\n", - rnum, - res->start, res->end, - pci_name(pdev)); - } - } -} - -void __init pci_record_assignments(struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *dev; - struct pci_bus *bus; - - list_for_each_entry(dev, &pbus->devices, bus_list) - pdev_record_assignments(pbm, dev); - - list_for_each_entry(bus, &pbus->children, node) - pci_record_assignments(pbm, bus); -} - -/* Return non-zero if PDEV has implicit I/O resources even - * though it may not have an I/O base address register - * active. - */ -static int __init has_implicit_io(struct pci_dev *pdev) -{ - int class = pdev->class >> 8; - - if (class == PCI_CLASS_NOT_DEFINED || - class == PCI_CLASS_NOT_DEFINED_VGA || - class == PCI_CLASS_STORAGE_IDE || - (pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) - return 1; - - return 0; -} - -static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm, - struct pci_dev *pdev) -{ - u32 reg; - u16 cmd; - int i, io_seen, mem_seen; - - io_seen = mem_seen = 0; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *root, *res; - unsigned long size, min, max, align; - - res = &pdev->resource[i]; - - if (res->flags & IORESOURCE_IO) - io_seen++; - else if (res->flags & IORESOURCE_MEM) - mem_seen++; - - /* If it is already assigned or the resource does - * not exist, there is nothing to do. - */ - if (res->parent != NULL || res->flags == 0UL) - continue; - - /* Determine the root we allocate from. */ - if (res->flags & IORESOURCE_IO) { - root = &pbm->io_space; - min = root->start + 0x400UL; - max = root->end; - } else { - root = &pbm->mem_space; - min = root->start; - max = min + 0x80000000UL; - } - - size = res->end - res->start; - align = size + 1; - if (allocate_resource(root, res, size + 1, min, max, align, NULL, NULL) < 0) { - /* uh oh */ - prom_printf("PCI: Failed to allocate resource %d for %s\n", - i, pci_name(pdev)); - prom_halt(); - } - - /* Update PCI config space. */ - pbm->parent->base_address_update(pdev, i); - } - - /* Special case, disable the ROM. Several devices - * act funny (ie. do not respond to memory space writes) - * when it is left enabled. A good example are Qlogic,ISP - * adapters. - */ - pci_read_config_dword(pdev, PCI_ROM_ADDRESS, ®); - reg &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_dword(pdev, PCI_ROM_ADDRESS, reg); - - /* If we saw I/O or MEM resources, enable appropriate - * bits in PCI command register. - */ - if (io_seen || mem_seen) { - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - if (io_seen || has_implicit_io(pdev)) - cmd |= PCI_COMMAND_IO; - if (mem_seen) - cmd |= PCI_COMMAND_MEMORY; - pci_write_config_word(pdev, PCI_COMMAND, cmd); - } - - /* If this is a PCI bridge or an IDE controller, - * enable bus mastering. In the former case also - * set the cache line size correctly. - */ - if (((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI) || - (((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) && - ((pdev->class & 0x80) != 0))) { - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER; - pci_write_config_word(pdev, PCI_COMMAND, cmd); - - if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI) - pci_write_config_byte(pdev, - PCI_CACHE_LINE_SIZE, - (64 / sizeof(u32))); - } -} - -void __init pci_assign_unassigned(struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *dev; - struct pci_bus *bus; - - list_for_each_entry(dev, &pbus->devices, bus_list) - pdev_assign_unassigned(pbm, dev); - - list_for_each_entry(bus, &pbus->children, node) - pci_assign_unassigned(pbm, bus); -} - -static void __init pdev_fixup_irq(struct pci_dev *pdev) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - struct of_device *op = pcp->op; - - if (op->irqs[0] == 0xffffffff) { - pdev->irq = PCI_IRQ_NONE; - return; - } - - pdev->irq = op->irqs[0]; - - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, - pdev->irq & PCI_IRQ_INO); -} - -void __init pci_fixup_irq(struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *dev; - struct pci_bus *bus; - - list_for_each_entry(dev, &pbus->devices, bus_list) - pdev_fixup_irq(dev); - - list_for_each_entry(bus, &pbus->children, node) - pci_fixup_irq(pbm, bus); -} - -static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz) -{ - u16 cmd; - u8 hdr_type, min_gnt, ltimer; - - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER; - pci_write_config_word(pdev, PCI_COMMAND, cmd); - - /* Read it back, if the mastering bit did not - * get set, the device does not support bus - * mastering so we have nothing to do here. - */ - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - if ((cmd & PCI_COMMAND_MASTER) == 0) - return; - - /* Set correct cache line size, 64-byte on all - * Sparc64 PCI systems. Note that the value is - * measured in 32-bit words. - */ - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, - 64 / sizeof(u32)); - - pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr_type); - hdr_type &= ~0x80; - if (hdr_type != PCI_HEADER_TYPE_NORMAL) - return; - - /* If the latency timer is already programmed with a non-zero - * value, assume whoever set it (OBP or whoever) knows what - * they are doing. - */ - pci_read_config_byte(pdev, PCI_LATENCY_TIMER, <imer); - if (ltimer != 0) - return; - - /* XXX Since I'm tipping off the min grant value to - * XXX choose a suitable latency timer value, I also - * XXX considered making use of the max latency value - * XXX as well. Unfortunately I've seen too many bogusly - * XXX low settings for it to the point where it lacks - * XXX any usefulness. In one case, an ethernet card - * XXX claimed a min grant of 10 and a max latency of 5. - * XXX Now, if I had two such cards on the same bus I - * XXX could not set the desired burst period (calculated - * XXX from min grant) without violating the max latency - * XXX bound. Duh... - * XXX - * XXX I blame dumb PC bios implementors for stuff like - * XXX this, most of them don't even try to do something - * XXX sensible with latency timer values and just set some - * XXX default value (usually 32) into every device. - */ - - pci_read_config_byte(pdev, PCI_MIN_GNT, &min_gnt); - - if (min_gnt == 0) { - /* If no min_gnt setting then use a default - * value. - */ - if (is_66mhz) - ltimer = 16; - else - ltimer = 32; - } else { - int shift_factor; - - if (is_66mhz) - shift_factor = 2; - else - shift_factor = 3; - - /* Use a default value when the min_gnt value - * is erroneously high. - */ - if (((unsigned int) min_gnt << shift_factor) > 512 || - ((min_gnt << shift_factor) & 0xff) == 0) { - ltimer = 8 << shift_factor; - } else { - ltimer = min_gnt << shift_factor; - } - } - - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, ltimer); -} - -void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *pdev; - int all_are_66mhz; - u16 status; - - if (pbm->is_66mhz_capable == 0) { - all_are_66mhz = 0; - goto out; - } - - all_are_66mhz = 1; - list_for_each_entry(pdev, &pbus->devices, bus_list) { - pci_read_config_word(pdev, PCI_STATUS, &status); - if (!(status & PCI_STATUS_66MHZ)) { - all_are_66mhz = 0; - break; - } - } -out: - pbm->all_devs_66mhz = all_are_66mhz; - - printk("PCI%d(PBM%c): Bus running at %dMHz\n", - pbm->parent->index, - (pbm == &pbm->parent->pbm_A) ? 'A' : 'B', - (all_are_66mhz ? 66 : 33)); -} - -void pci_setup_busmastering(struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *dev; - struct pci_bus *bus; - int is_66mhz; - - is_66mhz = pbm->is_66mhz_capable && pbm->all_devs_66mhz; - - list_for_each_entry(dev, &pbus->devices, bus_list) - pdev_setup_busmastering(dev, is_66mhz); - - list_for_each_entry(bus, &pbus->children, node) - pci_setup_busmastering(pbm, bus); -} - void pci_register_legacy_regions(struct resource *io_res, struct resource *mem_res) { diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 971e2bea30b4..ea8a6bd146ae 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -17,20 +17,7 @@ extern struct pci_controller_info *pci_controller_root; extern int pci_num_controllers; /* PCI bus scanning and fixup support. */ -extern void pci_fixup_host_bridge_self(struct pci_bus *pbus); -extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus, - struct pci_pbm_info *pbm, - struct device_node *prom_node); -extern void pci_record_assignments(struct pci_pbm_info *pbm, - struct pci_bus *pbus); -extern void pci_assign_unassigned(struct pci_pbm_info *pbm, - struct pci_bus *pbus); -extern void pci_fixup_irq(struct pci_pbm_info *pbm, - struct pci_bus *pbus); -extern void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm, - struct pci_bus *pbus); -extern void pci_setup_busmastering(struct pci_pbm_info *pbm, - struct pci_bus *pbus); +extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm); extern void pci_register_legacy_regions(struct resource *io_res, struct resource *mem_res); diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 7aca0f33f885..554daabb381e 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -220,7 +220,6 @@ static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx) */ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp) { - struct pcidev_cookie *pcp; struct pci_iommu *iommu; iopte_t *iopte; unsigned long flags, order, first_page; @@ -237,8 +236,7 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr return NULL; memset((char *)first_page, 0, PAGE_SIZE << order); - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; + iommu = pdev->dev.archdata.iommu; spin_lock_irqsave(&iommu->lock, flags); iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT); @@ -268,14 +266,12 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr /* Free and unmap a consistent DMA translation. */ static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma) { - struct pcidev_cookie *pcp; struct pci_iommu *iommu; iopte_t *iopte; unsigned long flags, order, npages; npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; + iommu = pdev->dev.archdata.iommu; iopte = iommu->page_table + ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT); @@ -295,7 +291,6 @@ static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, */ static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction) { - struct pcidev_cookie *pcp; struct pci_iommu *iommu; struct pci_strbuf *strbuf; iopte_t *base; @@ -304,9 +299,8 @@ static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz, u32 bus_addr, ret; unsigned long iopte_protection; - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; + iommu = pdev->dev.archdata.iommu; + strbuf = pdev->dev.archdata.stc; if (unlikely(direction == PCI_DMA_NONE)) goto bad_no_ctx; @@ -416,7 +410,6 @@ do_flush_sync: /* Unmap a single streaming mode DMA translation. */ static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) { - struct pcidev_cookie *pcp; struct pci_iommu *iommu; struct pci_strbuf *strbuf; iopte_t *base; @@ -428,9 +421,8 @@ static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_ return; } - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; + iommu = pdev->dev.archdata.iommu; + strbuf = pdev->dev.archdata.stc; npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); npages >>= IO_PAGE_SHIFT; @@ -549,7 +541,6 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, */ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { - struct pcidev_cookie *pcp; struct pci_iommu *iommu; struct pci_strbuf *strbuf; unsigned long flags, ctx, npages, iopte_protection; @@ -570,9 +561,8 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n return 1; } - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; + iommu = pdev->dev.archdata.iommu; + strbuf = pdev->dev.archdata.stc; if (unlikely(direction == PCI_DMA_NONE)) goto bad_no_ctx; @@ -636,7 +626,6 @@ bad_no_ctx: /* Unmap a set of streaming mode DMA translations. */ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { - struct pcidev_cookie *pcp; struct pci_iommu *iommu; struct pci_strbuf *strbuf; iopte_t *base; @@ -648,9 +637,8 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in WARN_ON(1); } - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; + iommu = pdev->dev.archdata.iommu; + strbuf = pdev->dev.archdata.stc; bus_addr = sglist->dma_address & IO_PAGE_MASK; @@ -696,14 +684,12 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in */ static void pci_4u_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) { - struct pcidev_cookie *pcp; struct pci_iommu *iommu; struct pci_strbuf *strbuf; unsigned long flags, ctx, npages; - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; + iommu = pdev->dev.archdata.iommu; + strbuf = pdev->dev.archdata.stc; if (!strbuf->strbuf_enabled) return; @@ -736,15 +722,13 @@ static void pci_4u_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_ */ static void pci_4u_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { - struct pcidev_cookie *pcp; struct pci_iommu *iommu; struct pci_strbuf *strbuf; unsigned long flags, ctx, npages, i; u32 bus_addr; - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; + iommu = pdev->dev.archdata.iommu; + strbuf = pdev->dev.archdata.stc; if (!strbuf->strbuf_enabled) return; @@ -809,13 +793,12 @@ static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit) int pci_dma_supported(struct pci_dev *pdev, u64 device_mask) { - struct pcidev_cookie *pcp = pdev->sysdata; u64 dma_addr_mask; if (pdev == NULL) { dma_addr_mask = 0xffffffff; } else { - struct pci_iommu *iommu = pcp->pbm->iommu; + struct pci_iommu *iommu = pdev->dev.archdata.iommu; dma_addr_mask = iommu->dma_addr_mask; diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index fda5db223d96..12ea30d30b2f 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -905,8 +905,7 @@ static void psycho_resource_adjust(struct pci_dev *pdev, static void psycho_base_address_update(struct pci_dev *pdev, int resource) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; struct resource *res, *root; u32 reg; int where, size, is_64bit; @@ -968,28 +967,7 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) static void pbm_scan_bus(struct pci_controller_info *p, struct pci_pbm_info *pbm) { - struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL); - - if (!cookie) { - prom_printf("PSYCHO: Critical allocation failure.\n"); - prom_halt(); - } - - /* All we care about is the PBM. */ - cookie->pbm = pbm; - - pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, - p->pci_ops, - pbm); - pci_fixup_host_bridge_self(pbm->pci_bus); - pbm->pci_bus->self->sysdata = cookie; - - pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); - pci_record_assignments(pbm, pbm->pci_bus); - pci_assign_unassigned(pbm, pbm->pci_bus); - pci_fixup_irq(pbm, pbm->pci_bus); - pci_determine_66mhz_disposition(pbm, pbm->pci_bus); - pci_setup_busmastering(pbm, pbm->pci_bus); + pbm->pci_bus = pci_scan_one_pbm(pbm); } static void psycho_scan_bus(struct pci_controller_info *p) diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 94bb681f2323..bbf624517508 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -710,8 +710,8 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p) p->index); ret = IRQ_HANDLED; } - pci_read_config_word(sabre_root_bus->self, - PCI_STATUS, &stat); + pci_bus_read_config_word(sabre_root_bus, 0, + PCI_STATUS, &stat); if (stat & (PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | PCI_STATUS_REC_TARGET_ABORT | @@ -719,8 +719,8 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p) PCI_STATUS_SIG_SYSTEM_ERROR)) { printk("SABRE%d: PCI bus error, PCI_STATUS[%04x]\n", p->index, stat); - pci_write_config_word(sabre_root_bus->self, - PCI_STATUS, 0xffff); + pci_bus_write_config_word(sabre_root_bus, 0, + PCI_STATUS, 0xffff); ret = IRQ_HANDLED; } return ret; @@ -887,8 +887,7 @@ static void sabre_resource_adjust(struct pci_dev *pdev, static void sabre_base_address_update(struct pci_dev *pdev, int resource) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; struct resource *res; unsigned long base; u32 reg; @@ -978,27 +977,11 @@ static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) } } -static struct pcidev_cookie *alloc_bridge_cookie(struct pci_pbm_info *pbm) -{ - struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL); - - if (!cookie) { - prom_printf("SABRE: Critical allocation failure.\n"); - prom_halt(); - } - - /* All we care about is the PBM. */ - cookie->pbm = pbm; - - return cookie; -} - static void sabre_scan_bus(struct pci_controller_info *p) { static int once; struct pci_bus *sabre_bus, *pbus; struct pci_pbm_info *pbm; - struct pcidev_cookie *cookie; int sabres_scanned; /* The APB bridge speaks to the Sabre host PCI bridge @@ -1020,13 +1003,9 @@ static void sabre_scan_bus(struct pci_controller_info *p) } once++; - cookie = alloc_bridge_cookie(&p->pbm_A); - - sabre_bus = pci_scan_bus(p->pci_first_busno, - p->pci_ops, - &p->pbm_A); - pci_fixup_host_bridge_self(sabre_bus); - sabre_bus->self->sysdata = cookie; + sabre_bus = pci_scan_one_pbm(&p->pbm_A); + if (!sabre_bus) + return; sabre_root_bus = sabre_bus; @@ -1043,19 +1022,9 @@ static void sabre_scan_bus(struct pci_controller_info *p) } else continue; - cookie = alloc_bridge_cookie(pbm); - pbus->self->sysdata = cookie; - sabres_scanned++; - pbus->sysdata = pbm; pbm->pci_bus = pbus; - pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node); - pci_record_assignments(pbm, pbus); - pci_assign_unassigned(pbm, pbus); - pci_fixup_irq(pbm, pbus); - pci_determine_66mhz_disposition(pbm, pbus); - pci_setup_busmastering(pbm, pbus); } if (!sabres_scanned) { @@ -1063,12 +1032,6 @@ static void sabre_scan_bus(struct pci_controller_info *p) pbm = &p->pbm_A; sabre_bus->sysdata = pbm; pbm->pci_bus = sabre_bus; - pci_fill_in_pbm_cookies(sabre_bus, pbm, pbm->prom_node); - pci_record_assignments(pbm, sabre_bus); - pci_assign_unassigned(pbm, sabre_bus); - pci_fixup_irq(pbm, sabre_bus); - pci_determine_66mhz_disposition(pbm, sabre_bus); - pci_setup_busmastering(pbm, sabre_bus); } sabre_register_error_handlers(p); diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 66911b126aed..48dea52ac522 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1232,28 +1232,7 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) static void pbm_scan_bus(struct pci_controller_info *p, struct pci_pbm_info *pbm) { - struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL); - - if (!cookie) { - prom_printf("%s: Critical allocation failure.\n", pbm->name); - prom_halt(); - } - - /* All we care about is the PBM. */ - cookie->pbm = pbm; - - pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, - p->pci_ops, - pbm); - pci_fixup_host_bridge_self(pbm->pci_bus); - pbm->pci_bus->self->sysdata = cookie; - - pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); - pci_record_assignments(pbm, pbm->pci_bus); - pci_assign_unassigned(pbm, pbm->pci_bus); - pci_fixup_irq(pbm, pbm->pci_bus); - pci_determine_66mhz_disposition(pbm, pbm->pci_bus); - pci_setup_busmastering(pbm, pbm->pci_bus); + pbm->pci_bus = pci_scan_one_pbm(pbm); } static void __schizo_scan_bus(struct pci_controller_info *p, @@ -1297,8 +1276,7 @@ static void tomatillo_scan_bus(struct pci_controller_info *p) static void schizo_base_address_update(struct pci_dev *pdev, int resource) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; struct resource *res, *root; u32 reg; int where, size, is_64bit; diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index bd74c155519e..eec7def379dc 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -53,8 +53,8 @@ static inline void pci_iommu_batch_start(struct pci_dev *pdev, unsigned long pro /* Interrupts must be disabled. */ static long pci_iommu_batch_flush(struct pci_iommu_batch *p) { - struct pcidev_cookie *pcp = p->pdev->sysdata; - unsigned long devhandle = pcp->pbm->devhandle; + struct pci_pbm_info *pbm = p->pdev->dev.archdata.host_controller; + unsigned long devhandle = pbm->devhandle; unsigned long prot = p->prot; unsigned long entry = p->entry; u64 *pglist = p->pglist; @@ -159,7 +159,6 @@ static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, un static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp) { - struct pcidev_cookie *pcp; struct pci_iommu *iommu; unsigned long flags, order, first_page, npages, n; void *ret; @@ -178,8 +177,7 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr memset((char *)first_page, 0, PAGE_SIZE << order); - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; + iommu = pdev->dev.archdata.iommu; spin_lock_irqsave(&iommu->lock, flags); entry = pci_arena_alloc(&iommu->arena, npages); @@ -226,15 +224,15 @@ arena_alloc_fail: static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma) { - struct pcidev_cookie *pcp; + struct pci_pbm_info *pbm; struct pci_iommu *iommu; unsigned long flags, order, npages, entry; u32 devhandle; npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - devhandle = pcp->pbm->devhandle; + iommu = pdev->dev.archdata.iommu; + pbm = pdev->dev.archdata.host_controller; + devhandle = pbm->devhandle; entry = ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT); spin_lock_irqsave(&iommu->lock, flags); @@ -259,7 +257,6 @@ static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction) { - struct pcidev_cookie *pcp; struct pci_iommu *iommu; unsigned long flags, npages, oaddr; unsigned long i, base_paddr; @@ -267,8 +264,7 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz, unsigned long prot; long entry; - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; + iommu = pdev->dev.archdata.iommu; if (unlikely(direction == PCI_DMA_NONE)) goto bad; @@ -324,7 +320,7 @@ iommu_map_fail: static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) { - struct pcidev_cookie *pcp; + struct pci_pbm_info *pbm; struct pci_iommu *iommu; unsigned long flags, npages; long entry; @@ -336,9 +332,9 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_ return; } - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - devhandle = pcp->pbm->devhandle; + iommu = pdev->dev.archdata.iommu; + pbm = pdev->dev.archdata.host_controller; + devhandle = pbm->devhandle; npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); npages >>= IO_PAGE_SHIFT; @@ -460,7 +456,6 @@ iommu_map_failed: static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { - struct pcidev_cookie *pcp; struct pci_iommu *iommu; unsigned long flags, npages, prot; u32 dma_base; @@ -480,8 +475,7 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n return 1; } - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; + iommu = pdev->dev.archdata.iommu; if (unlikely(direction == PCI_DMA_NONE)) goto bad; @@ -537,7 +531,7 @@ iommu_map_failed: static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { - struct pcidev_cookie *pcp; + struct pci_pbm_info *pbm; struct pci_iommu *iommu; unsigned long flags, i, npages; long entry; @@ -548,9 +542,9 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in WARN_ON(1); } - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - devhandle = pcp->pbm->devhandle; + iommu = pdev->dev.archdata.iommu; + pbm = pdev->dev.archdata.host_controller; + devhandle = pbm->devhandle; bus_addr = sglist->dma_address & IO_PAGE_MASK; @@ -600,132 +594,12 @@ struct pci_iommu_ops pci_sun4v_iommu_ops = { .dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu, }; -/* SUN4V PCI configuration space accessors. */ - -struct pdev_entry { - struct pdev_entry *next; - u32 devhandle; - unsigned int bus; - unsigned int device; - unsigned int func; -}; - -#define PDEV_HTAB_SIZE 16 -#define PDEV_HTAB_MASK (PDEV_HTAB_SIZE - 1) -static struct pdev_entry *pdev_htab[PDEV_HTAB_SIZE]; - -static inline unsigned int pdev_hashfn(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func) -{ - unsigned int val; - - val = (devhandle ^ (devhandle >> 4)); - val ^= bus; - val ^= device; - val ^= func; - - return val & PDEV_HTAB_MASK; -} - -static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func) -{ - struct pdev_entry *p = kmalloc(sizeof(*p), GFP_KERNEL); - struct pdev_entry **slot; - - if (!p) - return -ENOMEM; - - slot = &pdev_htab[pdev_hashfn(devhandle, bus, device, func)]; - p->next = *slot; - *slot = p; - - p->devhandle = devhandle; - p->bus = bus; - p->device = device; - p->func = func; - - return 0; -} - -/* Recursively descend into the OBP device tree, rooted at toplevel_node, - * looking for a PCI device matching bus and devfn. - */ -static int obp_find(struct device_node *toplevel_node, unsigned int bus, unsigned int devfn) -{ - toplevel_node = toplevel_node->child; - - while (toplevel_node != NULL) { - struct linux_prom_pci_registers *regs; - struct property *prop; - int ret; - - ret = obp_find(toplevel_node, bus, devfn); - if (ret != 0) - return ret; - - prop = of_find_property(toplevel_node, "reg", NULL); - if (!prop) - goto next_sibling; - - regs = prop->value; - if (((regs->phys_hi >> 16) & 0xff) == bus && - ((regs->phys_hi >> 8) & 0xff) == devfn) - break; - - next_sibling: - toplevel_node = toplevel_node->sibling; - } - - return toplevel_node != NULL; -} - -static int pdev_htab_populate(struct pci_pbm_info *pbm) -{ - u32 devhandle = pbm->devhandle; - unsigned int bus; - - for (bus = pbm->pci_first_busno; bus <= pbm->pci_last_busno; bus++) { - unsigned int devfn; - - for (devfn = 0; devfn < 256; devfn++) { - unsigned int device = PCI_SLOT(devfn); - unsigned int func = PCI_FUNC(devfn); - - if (obp_find(pbm->prom_node, bus, devfn)) { - int err = pdev_htab_add(devhandle, bus, - device, func); - if (err) - return err; - } - } - } - - return 0; -} - -static struct pdev_entry *pdev_find(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func) -{ - struct pdev_entry *p; - - p = pdev_htab[pdev_hashfn(devhandle, bus, device, func)]; - while (p) { - if (p->devhandle == devhandle && - p->bus == bus && - p->device == device && - p->func == func) - break; - - p = p->next; - } - - return p; -} - static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func) { if (bus < pbm->pci_first_busno || bus > pbm->pci_last_busno) return 1; - return pdev_find(pbm->devhandle, bus, device, func) == NULL; + return 0; } static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, @@ -800,27 +674,7 @@ static struct pci_ops pci_sun4v_ops = { static void pbm_scan_bus(struct pci_controller_info *p, struct pci_pbm_info *pbm) { - struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL); - - if (!cookie) { - prom_printf("%s: Critical allocation failure.\n", pbm->name); - prom_halt(); - } - - /* All we care about is the PBM. */ - cookie->pbm = pbm; - - pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, p->pci_ops, pbm); -#if 0 - pci_fixup_host_bridge_self(pbm->pci_bus); - pbm->pci_bus->self->sysdata = cookie; -#endif - pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); - pci_record_assignments(pbm, pbm->pci_bus); - pci_assign_unassigned(pbm, pbm->pci_bus); - pci_fixup_irq(pbm, pbm->pci_bus); - pci_determine_66mhz_disposition(pbm, pbm->pci_bus); - pci_setup_busmastering(pbm, pbm->pci_bus); + pbm->pci_bus = pci_scan_one_pbm(pbm); } static void pci_sun4v_scan_bus(struct pci_controller_info *p) @@ -846,8 +700,7 @@ static void pci_sun4v_scan_bus(struct pci_controller_info *p) static void pci_sun4v_base_address_update(struct pci_dev *pdev, int resource) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; struct resource *res, *root; u32 reg; int where, size, is_64bit; @@ -1410,8 +1263,7 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p, struct pci_dev *pdev, struct msi_desc *entry) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; unsigned long devino, msiqid; struct msi_msg msg; int msi_num, err; @@ -1455,7 +1307,7 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p, if (pci_sun4v_msi_setvalid(pbm->devhandle, msi_num, HV_MSIVALID_VALID)) goto out_err; - pcp->msi_num = msi_num; + pdev->dev.archdata.msi_num = msi_num; if (entry->msi_attrib.is_64) { msg.address_hi = pbm->msi64_start >> 32; @@ -1484,12 +1336,11 @@ out_err: static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq, struct pci_dev *pdev) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; unsigned long msiqid, err; unsigned int msi_num; - msi_num = pcp->msi_num; + msi_num = pdev->dev.archdata.msi_num; err = pci_sun4v_msi_getmsiq(pbm->devhandle, msi_num, &msiqid); if (err) { printk(KERN_ERR "%s: getmsiq gives error %lu\n", @@ -1559,8 +1410,6 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node pci_sun4v_get_bus_range(pbm); pci_sun4v_iommu_init(pbm); pci_sun4v_msi_init(pbm); - - pdev_htab_populate(pbm); } void sun4v_pci_init(struct device_node *dp, char *model_name) diff --git a/include/asm-sparc64/device.h b/include/asm-sparc64/device.h index d8f9872b0e2d..d5a4559b9555 100644 --- a/include/asm-sparc64/device.h +++ b/include/asm-sparc64/device.h @@ -3,5 +3,21 @@ * * This file is released under the GPLv2 */ -#include +#ifndef _ASM_SPARC64_DEVICE_H +#define _ASM_SPARC64_DEVICE_H +struct device_node; +struct of_device; + +struct dev_archdata { + void *iommu; + void *stc; + void *host_controller; + + struct device_node *prom_node; + struct of_device *op; + + unsigned int msi_num; +}; + +#endif /* _ASM_SPARC64_DEVICE_H */ diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h index 7a246d8a1828..88974d685a3d 100644 --- a/include/asm-sparc64/pbm.h +++ b/include/asm-sparc64/pbm.h @@ -244,27 +244,4 @@ struct pci_controller_info { unsigned int pci_last_busno; }; -/* PCI devices which are not bridges have this placed in their pci_dev - * sysdata member. This makes OBP aware PCI device drivers easier to - * code. - */ -struct pcidev_cookie { - struct pci_pbm_info *pbm; - struct device_node *prom_node; - struct of_device *op; - struct linux_prom_pci_registers prom_regs[PROMREG_MAX]; - int num_prom_regs; - struct linux_prom_pci_registers prom_assignments[PROMREG_MAX]; - int num_prom_assignments; -#ifdef CONFIG_PCI_MSI - unsigned int msi_num; -#endif -}; - -/* Currently these are the same across all PCI controllers - * we support. Someday they may not be... - */ -#define PCI_IRQ_IGN 0x000007c0 /* Interrupt Group Number */ -#define PCI_IRQ_INO 0x0000003f /* Interrupt Number */ - #endif /* !(__SPARC64_PBM_H) */ -- cgit v1.2.3 From 1e8a8cc52daa95e702303ca3ce67955a4c051d7d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 28 Feb 2007 23:38:38 -0800 Subject: [SPARC64]: Internalize pci_memspace_mask. The only user was bus_dvma_to_mem() which is no longer used by any driver, so kill that, and the export of pci_memspace_mask. The only user now is the PCI mmap support code. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 2 ++ arch/sparc64/kernel/pci_impl.h | 1 + arch/sparc64/kernel/sparc64_ksyms.c | 1 - include/asm-sparc64/io.h | 8 -------- 4 files changed, 3 insertions(+), 9 deletions(-) (limited to 'arch/sparc64/kernel/pci.c') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 246b8009a2b4..ec0d12a48c2b 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -27,6 +27,8 @@ #include #include +#include "pci_impl.h" + unsigned long pci_memspace_mask = 0xffffffffUL; #ifndef CONFIG_PCI diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index ea8a6bd146ae..c4ba702e1fd9 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -13,6 +13,7 @@ #include extern struct pci_controller_info *pci_controller_root; +extern unsigned long pci_memspace_mask; extern int pci_num_controllers; diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index beffc82a1e85..d00f51a5683f 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -212,7 +212,6 @@ EXPORT_SYMBOL(insl); #ifdef CONFIG_PCI EXPORT_SYMBOL(ebus_chain); EXPORT_SYMBOL(isa_chain); -EXPORT_SYMBOL(pci_memspace_mask); EXPORT_SYMBOL(pci_alloc_consistent); EXPORT_SYMBOL(pci_free_consistent); EXPORT_SYMBOL(pci_map_single); diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h index 30b912d8e8bc..ad595b679842 100644 --- a/include/asm-sparc64/io.h +++ b/include/asm-sparc64/io.h @@ -24,14 +24,6 @@ extern unsigned long kern_base, kern_size; #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) #define BIO_VMERGE_BOUNDARY 8192 -/* Different PCI controllers we support have their PCI MEM space - * mapped to an either 2GB (Psycho) or 4GB (Sabre) aligned area, - * so need to chop off the top 33 or 32 bits. - */ -extern unsigned long pci_memspace_mask; - -#define bus_dvma_to_mem(__vaddr) ((__vaddr) & pci_memspace_mask) - static __inline__ u8 _inb(unsigned long addr) { u8 ret; -- cgit v1.2.3 From a378fd0ee8ea6af5dafd0ab3d634f22b926b5ac4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 1 Mar 2007 11:46:13 -0800 Subject: [SPARC64]: Fix obppath pci device sysfs creation. Need to traverse recursively down child busses else we only get the file created under devices at the top-level. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/sparc64/kernel/pci.c') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index ec0d12a48c2b..425e883e7e3b 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -585,6 +585,7 @@ static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, N static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) { struct pci_dev *dev; + struct pci_bus *child_bus; int err; list_for_each_entry(dev, &bus->devices, bus_list) { @@ -597,6 +598,8 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) */ err = sysfs_create_file(&dev->dev.kobj, &dev_attr_obppath.attr); } + list_for_each_entry(child_bus, &bus->children, node) + pci_bus_register_of_sysfs(child_bus); } struct pci_bus * __init pci_scan_one_pbm(struct pci_pbm_info *pbm) -- cgit v1.2.3 From 01f94c4a6ced476ce69b895426fc29bfc48c69bd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 4 Mar 2007 12:53:19 -0800 Subject: [SPARC64]: Fix sabre pci controllers with new probing scheme. The SIMBA APB bridge is strange, it is a PCI bridge but it lacks some standard OF properties, in particular it lacks a 'ranges' property. What you have to do is read the IO and MEM range registers in the APB bridge to determine the ranges handled by each bridge. So fill in the bus resources by doing that. Since we now handle this quirk in the generic PCI and OF device probing layers, we can flat out eliminate all of that code from the sabre pci controller driver. In fact we can thus eliminate completely another quirk of the sabre driver. It tried to make the two APB bridges look like PBMs but that makes zero sense now (and it's questionable whether it ever made sense). So now just use pbm_A and probe the whole PCI hierarchy using that as the root. This simplification allows many future cleanups to occur. Also, I've found yet another quirk that needs to be worked around while testing this. You can't use the 'class-code' OF firmware property, especially for IDE controllers. We have to read the value out of PCI config space or else we'll see the value the device was showing before it was programmed into native mode. I'm starting to think it might be wise to just read all of the values out of PCI config space instead of using the OF properties. :-/ Signed-off-by: David S. Miller --- arch/sparc64/kernel/of_device.c | 29 ++++ arch/sparc64/kernel/pci.c | 80 +++++++++- arch/sparc64/kernel/pci_sabre.c | 340 ++++++++-------------------------------- 3 files changed, 165 insertions(+), 284 deletions(-) (limited to 'arch/sparc64/kernel/pci.c') diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 6b8798141f2c..8964eacb0048 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -317,6 +317,11 @@ static unsigned int of_bus_default_get_flags(const u32 *addr) static int of_bus_pci_match(struct device_node *np) { if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { + char *model = of_get_property(np, "model", NULL); + + if (model && !strcmp(model, "SUNW,simba")) + return 0; + /* Do not do PCI specific frobbing if the * PCI bridge lacks a ranges property. We * want to pass it through up to the next @@ -332,6 +337,21 @@ static int of_bus_pci_match(struct device_node *np) return 0; } +static int of_bus_simba_match(struct device_node *np) +{ + char *model = of_get_property(np, "model", NULL); + + if (model && !strcmp(model, "SUNW,simba")) + return 1; + return 0; +} + +static int of_bus_simba_map(u32 *addr, const u32 *range, + int na, int ns, int pna) +{ + return 0; +} + static void of_bus_pci_count_cells(struct device_node *np, int *addrc, int *sizec) { @@ -436,6 +456,15 @@ static struct of_bus of_busses[] = { .map = of_bus_pci_map, .get_flags = of_bus_pci_get_flags, }, + /* SIMBA */ + { + .name = "simba", + .addr_prop_name = "assigned-addresses", + .match = of_bus_simba_match, + .count_cells = of_bus_pci_count_cells, + .map = of_bus_simba_map, + .get_flags = of_bus_pci_get_flags, + }, /* SBUS */ { .name = "sbus", diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 425e883e7e3b..b63341c2a334 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "pci_impl.h" @@ -372,6 +373,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, struct dev_archdata *sd; struct pci_dev *dev; const char *type; + u32 class; dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); if (!dev) @@ -409,7 +411,15 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); - dev->class = of_getintprop_default(node, "class-code", 0); + + /* dev->class = of_getintprop_default(node, "class-code", 0); */ + /* We can't actually use the firmware value, we have to read what + * is in the register right now. One reason is that in the case + * of IDE interfaces the firmware can sample the value before the + * the IDE interface is programmed into native mode. + */ + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); + dev->class = class >> 8; printk(" class: 0x%x\n", dev->class); @@ -440,6 +450,53 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, return dev; } +static void __init apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p) +{ + u32 idx, first, last; + + first = 8; + last = 0; + for (idx = 0; idx < 8; idx++) { + if ((map & (1 << idx)) != 0) { + if (first > idx) + first = idx; + if (last < idx) + last = idx; + } + } + + *first_p = first; + *last_p = last; +} + +/* Cook up fake bus resources for SUNW,simba PCI bridges which lack + * a proper 'ranges' property. + */ +static void __init apb_fake_ranges(struct pci_dev *dev, + struct pci_bus *bus, + struct pci_pbm_info *pbm) +{ + struct resource *res; + u32 first, last; + u8 map; + + pci_read_config_byte(dev, APB_IO_ADDRESS_MAP, &map); + apb_calc_first_last(map, &first, &last); + res = bus->resource[0]; + res->start = (first << 21); + res->end = (last << 21) + ((1 << 21) - 1); + res->flags = IORESOURCE_IO; + pbm->parent->resource_adjust(dev, res, &pbm->io_space); + + pci_read_config_byte(dev, APB_MEM_ADDRESS_MAP, &map); + apb_calc_first_last(map, &first, &last); + res = bus->resource[1]; + res->start = (first << 21); + res->end = (last << 21) + ((1 << 21) - 1); + res->flags = IORESOURCE_MEM; + pbm->parent->resource_adjust(dev, res, &pbm->mem_space); +} + static void __init pci_of_scan_bus(struct pci_pbm_info *pbm, struct device_node *node, struct pci_bus *bus); @@ -452,7 +509,7 @@ void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, { struct pci_bus *bus; const u32 *busrange, *ranges; - int len, i; + int len, i, simba; struct resource *res; unsigned int flags; u64 size; @@ -467,10 +524,16 @@ void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, return; } ranges = of_get_property(node, "ranges", &len); + simba = 0; if (ranges == NULL) { - printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n", - node->full_name); - return; + char *model = of_get_property(node, "model", NULL); + if (model && !strcmp(model, "SUNW,simba")) { + simba = 1; + } else { + printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n", + node->full_name); + return; + } } bus = pci_add_new_bus(dev->bus, dev, busrange[0]); @@ -484,7 +547,7 @@ void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, bus->subordinate = busrange[1]; bus->bridge_ctl = 0; - /* parse ranges property */ + /* parse ranges property, or cook one up by hand for Simba */ /* PCI #address-cells == 3 and #size-cells == 2 always */ res = &dev->resource[PCI_BRIDGE_RESOURCES]; for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) { @@ -492,6 +555,10 @@ void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, bus->resource[i] = res; ++res; } + if (simba) { + apb_fake_ranges(dev, bus, pbm); + goto simba_cont; + } i = 1; for (; len >= 32; len -= 32, ranges += 8) { struct resource *root; @@ -529,6 +596,7 @@ void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, */ pbm->parent->resource_adjust(dev, res, root); } +simba_cont: sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), bus->number); printk(" bus name: %s\n", bus->name); diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index bbf624517508..f4e346092a53 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -254,9 +254,6 @@ static int __sabre_out_of_range(struct pci_pbm_info *pbm, return 0; return ((pbm->parent == 0) || - ((pbm == &pbm->parent->pbm_B) && - (bus == pbm->pci_first_busno) && - PCI_SLOT(devfn) > 8) || ((pbm == &pbm->parent->pbm_A) && (bus == pbm->pci_first_busno) && PCI_SLOT(devfn) > 8)); @@ -800,12 +797,10 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) { sabre_check_iommu_error(p, afsr, afar); pci_scan_for_target_abort(p, &p->pbm_A, p->pbm_A.pci_bus); - pci_scan_for_target_abort(p, &p->pbm_B, p->pbm_B.pci_bus); } - if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) { + if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) pci_scan_for_master_abort(p, &p->pbm_A, p->pbm_A.pci_bus); - pci_scan_for_master_abort(p, &p->pbm_B, p->pbm_B.pci_bus); - } + /* For excessive retries, SABRE/PBM will abort the device * and there is no way to specifically check for excessive * retries in the config space status registers. So what @@ -813,10 +808,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) * abort events. */ - if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) { + if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) pci_scan_for_parity_error(p, &p->pbm_A, p->pbm_A.pci_bus); - pci_scan_for_parity_error(p, &p->pbm_B, p->pbm_B.pci_bus); - } return IRQ_HANDLED; } @@ -935,44 +928,33 @@ static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) struct pci_dev *pdev; list_for_each_entry(pdev, &sabre_bus->devices, bus_list) { - if (pdev->vendor == PCI_VENDOR_ID_SUN && pdev->device == PCI_DEVICE_ID_SUN_SIMBA) { - u32 word32; u16 word16; - sabre_read_pci_cfg(pdev->bus, pdev->devfn, - PCI_COMMAND, 2, &word32); - word16 = (u16) word32; + pci_read_config_word(pdev, PCI_COMMAND, &word16); word16 |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; - word32 = (u32) word16; - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_COMMAND, 2, word32); + pci_write_config_word(pdev, PCI_COMMAND, word16); /* Status register bits are "write 1 to clear". */ - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_STATUS, 2, 0xffff); - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_SEC_STATUS, 2, 0xffff); + pci_write_config_word(pdev, PCI_STATUS, 0xffff); + pci_write_config_word(pdev, PCI_SEC_STATUS, 0xffff); /* Use a primary/seconday latency timer value * of 64. */ - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_LATENCY_TIMER, 1, 64); - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_SEC_LATENCY_TIMER, 1, 64); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); + pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 64); /* Enable reporting/forwarding of master aborts, * parity, and SERR. */ - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_BRIDGE_CONTROL, 1, - (PCI_BRIDGE_CTL_PARITY | - PCI_BRIDGE_CTL_SERR | - PCI_BRIDGE_CTL_MASTER_ABORT)); + pci_write_config_byte(pdev, PCI_BRIDGE_CONTROL, + (PCI_BRIDGE_CTL_PARITY | + PCI_BRIDGE_CTL_SERR | + PCI_BRIDGE_CTL_MASTER_ABORT)); } } } @@ -980,16 +962,13 @@ static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) static void sabre_scan_bus(struct pci_controller_info *p) { static int once; - struct pci_bus *sabre_bus, *pbus; - struct pci_pbm_info *pbm; - int sabres_scanned; + struct pci_bus *pbus; /* The APB bridge speaks to the Sabre host PCI bridge * at 66Mhz, but the front side of APB runs at 33Mhz * for both segments. */ p->pbm_A.is_66mhz_capable = 0; - p->pbm_B.is_66mhz_capable = 0; /* This driver has not been verified to handle * multiple SABREs yet, so trap this. @@ -1003,36 +982,13 @@ static void sabre_scan_bus(struct pci_controller_info *p) } once++; - sabre_bus = pci_scan_one_pbm(&p->pbm_A); - if (!sabre_bus) + pbus = pci_scan_one_pbm(&p->pbm_A); + if (!pbus) return; - sabre_root_bus = sabre_bus; - - apb_init(p, sabre_bus); - - sabres_scanned = 0; + sabre_root_bus = pbus; - list_for_each_entry(pbus, &sabre_bus->children, node) { - - if (pbus->number == p->pbm_A.pci_first_busno) { - pbm = &p->pbm_A; - } else if (pbus->number == p->pbm_B.pci_first_busno) { - pbm = &p->pbm_B; - } else - continue; - - sabres_scanned++; - pbus->sysdata = pbm; - pbm->pci_bus = pbus; - } - - if (!sabres_scanned) { - /* Hummingbird, no APBs. */ - pbm = &p->pbm_A; - sabre_bus->sysdata = pbm; - pbm->pci_bus = sabre_bus; - } + apb_init(p, pbus); sabre_register_error_handlers(p); } @@ -1089,213 +1045,54 @@ static void sabre_iommu_init(struct pci_controller_info *p, sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); } -static void pbm_register_toplevel_resources(struct pci_controller_info *p, - struct pci_pbm_info *pbm) +static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_start, u32 dma_end) { - char *name = pbm->name; - unsigned long ibase = p->pbm_A.controller_regs + SABRE_IOSPACE; - unsigned long mbase = p->pbm_A.controller_regs + SABRE_MEMSPACE; - unsigned int devfn; - unsigned long first, last, i; - u8 *addr, map; - - sprintf(name, "SABRE%d PBM%c", - p->index, - (pbm == &p->pbm_A ? 'A' : 'B')); - pbm->io_space.name = pbm->mem_space.name = name; - - devfn = PCI_DEVFN(1, (pbm == &p->pbm_A) ? 0 : 1); - addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_IO_ADDRESS_MAP); - map = 0; - pci_config_read8(addr, &map); - - first = 8; - last = 0; - for (i = 0; i < 8; i++) { - if ((map & (1 << i)) != 0) { - if (first > i) - first = i; - if (last < i) - last = i; - } - } - pbm->io_space.start = ibase + (first << 21UL); - pbm->io_space.end = ibase + (last << 21UL) + ((1 << 21UL) - 1); + struct pci_pbm_info *pbm; + struct resource *rp; + + pbm = &p->pbm_A; + pbm->name = dp->full_name; + printk("%s: SABRE PCI Bus Module\n", pbm->name); + + pbm->chip_type = PBM_CHIP_TYPE_SABRE; + pbm->parent = p; + pbm->prom_node = dp; + pbm->pci_first_slot = 1; + pbm->pci_first_busno = p->pci_first_busno; + pbm->pci_last_busno = p->pci_last_busno; + + pbm->io_space.name = pbm->mem_space.name = pbm->name; + + pbm->io_space.start = p->pbm_A.controller_regs + SABRE_IOSPACE; + pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL; pbm->io_space.flags = IORESOURCE_IO; - addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_MEM_ADDRESS_MAP); - map = 0; - pci_config_read8(addr, &map); - - first = 8; - last = 0; - for (i = 0; i < 8; i++) { - if ((map & (1 << i)) != 0) { - if (first > i) - first = i; - if (last < i) - last = i; - } - } - pbm->mem_space.start = mbase + (first << 29UL); - pbm->mem_space.end = mbase + (last << 29UL) + ((1 << 29UL) - 1); + pbm->mem_space.start = (p->pbm_A.controller_regs + SABRE_MEMSPACE); + pbm->mem_space.end = (pbm->mem_space.start + ((1UL << 32UL) - 1UL)); pbm->mem_space.flags = IORESOURCE_MEM; if (request_resource(&ioport_resource, &pbm->io_space) < 0) { - prom_printf("Cannot register PBM-%c's IO space.\n", - (pbm == &p->pbm_A ? 'A' : 'B')); + prom_printf("Cannot register Sabre's IO space.\n"); prom_halt(); } if (request_resource(&iomem_resource, &pbm->mem_space) < 0) { - prom_printf("Cannot register PBM-%c's MEM space.\n", - (pbm == &p->pbm_A ? 'A' : 'B')); + prom_printf("Cannot register Sabre's MEM space.\n"); prom_halt(); } - /* Register legacy regions if this PBM covers that area. */ - if (pbm->io_space.start == ibase && - pbm->mem_space.start == mbase) - pci_register_legacy_regions(&pbm->io_space, - &pbm->mem_space); -} - -static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_start, u32 dma_end) -{ - struct pci_pbm_info *pbm; - struct device_node *node; - struct property *prop; - u32 *busrange; - int len, simbas_found; - - simbas_found = 0; - node = dp->child; - while (node != NULL) { - if (strcmp(node->name, "pci")) - goto next_pci; - - prop = of_find_property(node, "model", NULL); - if (!prop || strncmp(prop->value, "SUNW,simba", prop->length)) - goto next_pci; - - simbas_found++; - - prop = of_find_property(node, "bus-range", NULL); - busrange = prop->value; - if (busrange[0] == 1) - pbm = &p->pbm_B; - else - pbm = &p->pbm_A; - - pbm->name = node->full_name; - printk("%s: SABRE PCI Bus Module\n", pbm->name); - - pbm->chip_type = PBM_CHIP_TYPE_SABRE; - pbm->parent = p; - pbm->prom_node = node; - pbm->pci_first_slot = 1; - pbm->pci_first_busno = busrange[0]; - pbm->pci_last_busno = busrange[1]; - - prop = of_find_property(node, "ranges", &len); - if (prop) { - pbm->pbm_ranges = prop->value; - pbm->num_pbm_ranges = - (len / sizeof(struct linux_prom_pci_ranges)); - } else { - pbm->num_pbm_ranges = 0; - } - - prop = of_find_property(node, "interrupt-map", &len); - if (prop) { - pbm->pbm_intmap = prop->value; - pbm->num_pbm_intmap = - (len / sizeof(struct linux_prom_pci_intmap)); - - prop = of_find_property(node, "interrupt-map-mask", - NULL); - pbm->pbm_intmask = prop->value; - } else { - pbm->num_pbm_intmap = 0; - } - - pbm_register_toplevel_resources(p, pbm); - - next_pci: - node = node->sibling; - } - if (simbas_found == 0) { - struct resource *rp; - - /* No APBs underneath, probably this is a hummingbird - * system. - */ - pbm = &p->pbm_A; - pbm->parent = p; - pbm->prom_node = dp; - pbm->pci_first_busno = p->pci_first_busno; - pbm->pci_last_busno = p->pci_last_busno; - - prop = of_find_property(dp, "ranges", &len); - if (prop) { - pbm->pbm_ranges = prop->value; - pbm->num_pbm_ranges = - (len / sizeof(struct linux_prom_pci_ranges)); - } else { - pbm->num_pbm_ranges = 0; - } - - prop = of_find_property(dp, "interrupt-map", &len); - if (prop) { - pbm->pbm_intmap = prop->value; - pbm->num_pbm_intmap = - (len / sizeof(struct linux_prom_pci_intmap)); - - prop = of_find_property(dp, "interrupt-map-mask", - NULL); - pbm->pbm_intmask = prop->value; - } else { - pbm->num_pbm_intmap = 0; - } - - pbm->name = dp->full_name; - printk("%s: SABRE PCI Bus Module\n", pbm->name); - - pbm->io_space.name = pbm->mem_space.name = pbm->name; - - /* Hack up top-level resources. */ - pbm->io_space.start = p->pbm_A.controller_regs + SABRE_IOSPACE; - pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL; - pbm->io_space.flags = IORESOURCE_IO; - - pbm->mem_space.start = - (p->pbm_A.controller_regs + SABRE_MEMSPACE); - pbm->mem_space.end = - (pbm->mem_space.start + ((1UL << 32UL) - 1UL)); - pbm->mem_space.flags = IORESOURCE_MEM; - - if (request_resource(&ioport_resource, &pbm->io_space) < 0) { - prom_printf("Cannot register Hummingbird's IO space.\n"); - prom_halt(); - } - if (request_resource(&iomem_resource, &pbm->mem_space) < 0) { - prom_printf("Cannot register Hummingbird's MEM space.\n"); - prom_halt(); - } - - rp = kmalloc(sizeof(*rp), GFP_KERNEL); - if (!rp) { - prom_printf("Cannot allocate IOMMU resource.\n"); - prom_halt(); - } - rp->name = "IOMMU"; - rp->start = pbm->mem_space.start + (unsigned long) dma_start; - rp->end = pbm->mem_space.start + (unsigned long) dma_end - 1UL; - rp->flags = IORESOURCE_BUSY; - request_resource(&pbm->mem_space, rp); - - pci_register_legacy_regions(&pbm->io_space, - &pbm->mem_space); + rp = kmalloc(sizeof(*rp), GFP_KERNEL); + if (!rp) { + prom_printf("Cannot allocate IOMMU resource.\n"); + prom_halt(); } + rp->name = "IOMMU"; + rp->start = pbm->mem_space.start + (unsigned long) dma_start; + rp->end = pbm->mem_space.start + (unsigned long) dma_end - 1UL; + rp->flags = IORESOURCE_BUSY; + request_resource(&pbm->mem_space, rp); + + pci_register_legacy_regions(&pbm->io_space, + &pbm->mem_space); } void sabre_init(struct device_node *dp, char *model_name) @@ -1303,7 +1100,6 @@ void sabre_init(struct device_node *dp, char *model_name) struct linux_prom64_registers *pr_regs; struct pci_controller_info *p; struct pci_iommu *iommu; - struct property *prop; int tsbsize; u32 *busrange; u32 *vdma; @@ -1314,13 +1110,9 @@ void sabre_init(struct device_node *dp, char *model_name) if (!strcmp(model_name, "pci108e,a001")) hummingbird_p = 1; else if (!strcmp(model_name, "SUNW,sabre")) { - prop = of_find_property(dp, "compatible", NULL); - if (prop) { - const char *compat = prop->value; - - if (!strcmp(compat, "pci108e,a001")) - hummingbird_p = 1; - } + const char *compat = of_get_property(dp, "compatible", NULL); + if (compat && !strcmp(compat, "pci108e,a001")) + hummingbird_p = 1; if (!hummingbird_p) { struct device_node *dp; @@ -1344,18 +1136,14 @@ void sabre_init(struct device_node *dp, char *model_name) prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n"); prom_halt(); } - p->pbm_A.iommu = p->pbm_B.iommu = iommu; + p->pbm_A.iommu = iommu; - upa_portid = 0xff; - prop = of_find_property(dp, "upa-portid", NULL); - if (prop) - upa_portid = *(u32 *) prop->value; + upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); p->next = pci_controller_root; pci_controller_root = p; p->pbm_A.portid = upa_portid; - p->pbm_B.portid = upa_portid; p->index = pci_num_controllers++; p->pbms_same_domain = 1; p->scan_bus = sabre_scan_bus; @@ -1367,14 +1155,12 @@ void sabre_init(struct device_node *dp, char *model_name) * Map in SABRE register set and report the presence of this SABRE. */ - prop = of_find_property(dp, "reg", NULL); - pr_regs = prop->value; + pr_regs = of_get_property(dp, "reg", NULL); /* * First REG in property is base of entire SABRE register space. */ p->pbm_A.controller_regs = pr_regs[0].phys_addr; - p->pbm_B.controller_regs = pr_regs[0].phys_addr; /* Clear interrupts */ @@ -1392,11 +1178,10 @@ void sabre_init(struct device_node *dp, char *model_name) SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); /* Now map in PCI config space for entire SABRE. */ - p->pbm_A.config_space = p->pbm_B.config_space = + p->pbm_A.config_space = (p->pbm_A.controller_regs + SABRE_CONFIGSPACE); - prop = of_find_property(dp, "virtual-dma", NULL); - vdma = prop->value; + vdma = of_get_property(dp, "virtual-dma", NULL); dma_mask = vdma[0]; switch(vdma[1]) { @@ -1420,8 +1205,7 @@ void sabre_init(struct device_node *dp, char *model_name) sabre_iommu_init(p, tsbsize, vdma[0], dma_mask); - prop = of_find_property(dp, "bus-range", NULL); - busrange = prop->value; + busrange = of_get_property(dp, "bus-range", NULL); p->pci_first_busno = busrange[0]; p->pci_last_busno = busrange[1]; -- cgit v1.2.3 From 0bae5f81b6f8130f5197e59b0e2ad6820c766b2b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 8 Mar 2007 22:42:19 -0800 Subject: [SPARC64]: Kill pci_controller->resource_adjust() All the implementations can be identical and generic, so no need for controller specific methods. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 17 ++++++++++++----- arch/sparc64/kernel/pci_psycho.c | 9 --------- arch/sparc64/kernel/pci_sabre.c | 17 ----------------- arch/sparc64/kernel/pci_schizo.c | 9 --------- arch/sparc64/kernel/pci_sun4v.c | 9 --------- include/asm-sparc64/pbm.h | 1 - 6 files changed, 12 insertions(+), 50 deletions(-) (limited to 'arch/sparc64/kernel/pci.c') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index b63341c2a334..6b94d97e56ad 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -469,6 +469,13 @@ static void __init apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p) *last_p = last; } +static void __init pci_resource_adjust(struct resource *res, + struct resource *root) +{ + res->start += root->start; + res->end += root->start; +} + /* Cook up fake bus resources for SUNW,simba PCI bridges which lack * a proper 'ranges' property. */ @@ -486,7 +493,7 @@ static void __init apb_fake_ranges(struct pci_dev *dev, res->start = (first << 21); res->end = (last << 21) + ((1 << 21) - 1); res->flags = IORESOURCE_IO; - pbm->parent->resource_adjust(dev, res, &pbm->io_space); + pci_resource_adjust(res, &pbm->io_space); pci_read_config_byte(dev, APB_MEM_ADDRESS_MAP, &map); apb_calc_first_last(map, &first, &last); @@ -494,7 +501,7 @@ static void __init apb_fake_ranges(struct pci_dev *dev, res->start = (first << 21); res->end = (last << 21) + ((1 << 21) - 1); res->flags = IORESOURCE_MEM; - pbm->parent->resource_adjust(dev, res, &pbm->mem_space); + pci_resource_adjust(res, &pbm->mem_space); } static void __init pci_of_scan_bus(struct pci_pbm_info *pbm, @@ -594,7 +601,7 @@ void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, * layer routine that can calculate a resource for a given * range property value in a PCI device. */ - pbm->parent->resource_adjust(dev, res, root); + pci_resource_adjust(res, root); } simba_cont: sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), @@ -803,7 +810,7 @@ void pcibios_resource_to_bus(struct pci_dev *pdev, struct pci_bus_region *region else root = &pbm->mem_space; - pbm->parent->resource_adjust(pdev, &zero_res, root); + pci_resource_adjust(&zero_res, root); region->start = res->start - zero_res.start; region->end = res->end - zero_res.start; @@ -824,7 +831,7 @@ void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res, else root = &pbm->mem_space; - pbm->parent->resource_adjust(pdev, res, root); + pci_resource_adjust(res, root); } EXPORT_SYMBOL(pcibios_bus_to_resource); diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 1717df549488..c3f212725b04 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -894,14 +894,6 @@ static void psycho_register_error_handlers(struct pci_controller_info *p) } /* PSYCHO boot time probing and initialization. */ -static void psycho_resource_adjust(struct pci_dev *pdev, - struct resource *res, - struct resource *root) -{ - res->start += root->start; - res->end += root->start; -} - static void psycho_base_address_update(struct pci_dev *pdev, int resource) { struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; @@ -1218,7 +1210,6 @@ void psycho_init(struct device_node *dp, char *model_name) p->pbms_same_domain = 0; p->scan_bus = psycho_scan_bus; p->base_address_update = psycho_base_address_update; - p->resource_adjust = psycho_resource_adjust; p->pci_ops = &psycho_ops; prop = of_find_property(dp, "reg", NULL); diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 2dad171b54e2..64cdce81d86a 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -862,22 +862,6 @@ static void sabre_register_error_handlers(struct pci_controller_info *p) sabre_write(base + SABRE_PCICTRL, tmp); } -static void sabre_resource_adjust(struct pci_dev *pdev, - struct resource *res, - struct resource *root) -{ - struct pci_pbm_info *pbm = pdev->bus->sysdata; - unsigned long base; - - if (res->flags & IORESOURCE_IO) - base = pbm->controller_regs + SABRE_IOSPACE; - else - base = pbm->controller_regs + SABRE_MEMSPACE; - - res->start += base; - res->end += base; -} - static void sabre_base_address_update(struct pci_dev *pdev, int resource) { struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; @@ -1116,7 +1100,6 @@ void sabre_init(struct device_node *dp, char *model_name) p->pbms_same_domain = 1; p->scan_bus = sabre_scan_bus; p->base_address_update = sabre_base_address_update; - p->resource_adjust = sabre_resource_adjust; p->pci_ops = &sabre_ops; /* diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index dec8dc9499e0..ba9206eb9516 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1295,14 +1295,6 @@ static void schizo_base_address_update(struct pci_dev *pdev, int resource) pci_write_config_dword(pdev, where + 4, 0); } -static void schizo_resource_adjust(struct pci_dev *pdev, - struct resource *res, - struct resource *root) -{ - res->start += root->start; - res->end += root->start; -} - #define SCHIZO_STRBUF_CONTROL (0x02800UL) #define SCHIZO_STRBUF_FLUSH (0x02808UL) #define SCHIZO_STRBUF_FSYNC (0x02810UL) @@ -1670,7 +1662,6 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ p->index = pci_num_controllers++; p->scan_bus = schizo_scan_bus; p->base_address_update = schizo_base_address_update; - p->resource_adjust = schizo_resource_adjust; p->pci_ops = &schizo_ops; /* Like PSYCHO we have a 2GB aligned area for memory space. */ diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 9b57ba1cb947..ce0417e776a1 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -743,14 +743,6 @@ static void pci_sun4v_base_address_update(struct pci_dev *pdev, int resource) pci_write_config_dword(pdev, where + 4, 0); } -static void pci_sun4v_resource_adjust(struct pci_dev *pdev, - struct resource *res, - struct resource *root) -{ - res->start += root->start; - res->end += root->start; -} - static unsigned long probe_existing_entries(struct pci_pbm_info *pbm, struct pci_iommu *iommu) { @@ -1387,7 +1379,6 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) p->scan_bus = pci_sun4v_scan_bus; p->base_address_update = pci_sun4v_base_address_update; - p->resource_adjust = pci_sun4v_resource_adjust; #ifdef CONFIG_PCI_MSI p->setup_msi_irq = pci_sun4v_setup_msi_irq; p->teardown_msi_irq = pci_sun4v_teardown_msi_irq; diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h index 629290987429..1bd5b37c6d43 100644 --- a/include/asm-sparc64/pbm.h +++ b/include/asm-sparc64/pbm.h @@ -225,7 +225,6 @@ struct pci_controller_info { /* Operations which are controller specific. */ void (*scan_bus)(struct pci_controller_info *); void (*base_address_update)(struct pci_dev *, int); - void (*resource_adjust)(struct pci_dev *, struct resource *, struct resource *); #ifdef CONFIG_PCI_MSI int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev, -- cgit v1.2.3 From 3875c5c02d7112aa85f815d65d8add2e39ae9e34 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 8 Mar 2007 22:52:11 -0800 Subject: [SPARC64]: Kill pci_controller->pbms_same_domain We don't do the "Simba APB is a PBM" bogosity for Sabre controllers any longer, so this pbms_same_domain thing is no longer necessary. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 75 +++++++--------------------------------- arch/sparc64/kernel/pci_psycho.c | 1 - arch/sparc64/kernel/pci_sabre.c | 1 - arch/sparc64/kernel/pci_sun4v.c | 1 - include/asm-sparc64/pbm.h | 3 -- 5 files changed, 12 insertions(+), 69 deletions(-) (limited to 'arch/sparc64/kernel/pci.c') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 6b94d97e56ad..a7809a00324c 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -857,43 +857,12 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc unsigned long space_size, user_offset, user_size; p = pbm->parent; - if (p->pbms_same_domain) { - unsigned long lowest, highest; - - lowest = ~0UL; highest = 0UL; - if (mmap_state == pci_mmap_io) { - if (p->pbm_A.io_space.flags) { - lowest = p->pbm_A.io_space.start; - highest = p->pbm_A.io_space.end + 1; - } - if (p->pbm_B.io_space.flags) { - if (lowest > p->pbm_B.io_space.start) - lowest = p->pbm_B.io_space.start; - if (highest < p->pbm_B.io_space.end + 1) - highest = p->pbm_B.io_space.end + 1; - } - space_size = highest - lowest; - } else { - if (p->pbm_A.mem_space.flags) { - lowest = p->pbm_A.mem_space.start; - highest = p->pbm_A.mem_space.end + 1; - } - if (p->pbm_B.mem_space.flags) { - if (lowest > p->pbm_B.mem_space.start) - lowest = p->pbm_B.mem_space.start; - if (highest < p->pbm_B.mem_space.end + 1) - highest = p->pbm_B.mem_space.end + 1; - } - space_size = highest - lowest; - } + if (mmap_state == pci_mmap_io) { + space_size = (pbm->io_space.end - + pbm->io_space.start) + 1; } else { - if (mmap_state == pci_mmap_io) { - space_size = (pbm->io_space.end - - pbm->io_space.start) + 1; - } else { - space_size = (pbm->mem_space.end - - pbm->mem_space.start) + 1; - } + space_size = (pbm->mem_space.end - + pbm->mem_space.start) + 1; } /* Make sure the request is in range. */ @@ -904,31 +873,12 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc (user_offset + user_size) > space_size) return -EINVAL; - if (p->pbms_same_domain) { - unsigned long lowest = ~0UL; - - if (mmap_state == pci_mmap_io) { - if (p->pbm_A.io_space.flags) - lowest = p->pbm_A.io_space.start; - if (p->pbm_B.io_space.flags && - lowest > p->pbm_B.io_space.start) - lowest = p->pbm_B.io_space.start; - } else { - if (p->pbm_A.mem_space.flags) - lowest = p->pbm_A.mem_space.start; - if (p->pbm_B.mem_space.flags && - lowest > p->pbm_B.mem_space.start) - lowest = p->pbm_B.mem_space.start; - } - vma->vm_pgoff = (lowest + user_offset) >> PAGE_SHIFT; + if (mmap_state == pci_mmap_io) { + vma->vm_pgoff = (pbm->io_space.start + + user_offset) >> PAGE_SHIFT; } else { - if (mmap_state == pci_mmap_io) { - vma->vm_pgoff = (pbm->io_space.start + - user_offset) >> PAGE_SHIFT; - } else { - vma->vm_pgoff = (pbm->mem_space.start + - user_offset) >> PAGE_SHIFT; - } + vma->vm_pgoff = (pbm->mem_space.start + + user_offset) >> PAGE_SHIFT; } return 0; @@ -1062,9 +1012,8 @@ int pci_domain_nr(struct pci_bus *pbus) struct pci_controller_info *p = pbm->parent; ret = p->index; - if (p->pbms_same_domain == 0) - ret = ((ret << 1) + - ((pbm == &pbm->parent->pbm_B) ? 1 : 0)); + ret = ((ret << 1) + + ((pbm == &pbm->parent->pbm_B) ? 1 : 0)); } return ret; diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 64bd3579f1ca..0ab2aa0261ce 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1163,7 +1163,6 @@ void psycho_init(struct device_node *dp, char *model_name) p->pbm_A.portid = upa_portid; p->pbm_B.portid = upa_portid; p->index = pci_num_controllers++; - p->pbms_same_domain = 0; p->scan_bus = psycho_scan_bus; p->pci_ops = &psycho_ops; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index f3ec7bdacdc0..cef81c88548a 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1052,7 +1052,6 @@ void sabre_init(struct device_node *dp, char *model_name) p->pbm_A.portid = upa_portid; p->index = pci_num_controllers++; - p->pbms_same_domain = 1; p->scan_bus = sabre_scan_bus; p->pci_ops = &sabre_ops; diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index f9cd9f620d4e..b63ef26abf02 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -1330,7 +1330,6 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) pci_controller_root = p; p->index = pci_num_controllers++; - p->pbms_same_domain = 0; p->scan_bus = pci_sun4v_scan_bus; #ifdef CONFIG_PCI_MSI diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h index 07f58adb591a..43b07b9b42c5 100644 --- a/include/asm-sparc64/pbm.h +++ b/include/asm-sparc64/pbm.h @@ -215,9 +215,6 @@ struct pci_controller_info { */ int index; - /* Do the PBMs both exist in the same PCI domain? */ - int pbms_same_domain; - /* The PCI bus modules controlled by us. */ struct pci_pbm_info pbm_A; struct pci_pbm_info pbm_B; -- cgit v1.2.3 From c6e87566ea080bbbe926c0e429fed48e6f680d93 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 9 Mar 2007 16:58:43 -0800 Subject: [SPARC64]: Const'ify pci_iommu_ops. Based upon a similar patch for x86_64 written by Stephen Hemminger. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 4 ++-- arch/sparc64/kernel/pci_iommu.c | 2 +- arch/sparc64/kernel/pci_sun4v.c | 2 +- include/asm-sparc64/pci.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/sparc64/kernel/pci.c') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index a7809a00324c..914a216da339 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -282,10 +282,10 @@ int __init pcic_present(void) return pci_controller_scan(pci_is_controller); } -struct pci_iommu_ops *pci_iommu_ops; +const struct pci_iommu_ops *pci_iommu_ops; EXPORT_SYMBOL(pci_iommu_ops); -extern struct pci_iommu_ops pci_sun4u_iommu_ops, +extern const struct pci_iommu_ops pci_sun4u_iommu_ops, pci_sun4v_iommu_ops; /* Find each controller in the system, attach and initialize diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 554daabb381e..aefdcc51045b 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -759,7 +759,7 @@ static void pci_4u_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist spin_unlock_irqrestore(&iommu->lock, flags); } -struct pci_iommu_ops pci_sun4u_iommu_ops = { +const struct pci_iommu_ops pci_sun4u_iommu_ops = { .alloc_consistent = pci_4u_alloc_consistent, .free_consistent = pci_4u_free_consistent, .map_single = pci_4u_map_single, diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index c6feae6e9690..a8c12c1e8039 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -583,7 +583,7 @@ static void pci_4v_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist /* Nothing to do... */ } -struct pci_iommu_ops pci_sun4v_iommu_ops = { +const struct pci_iommu_ops pci_sun4v_iommu_ops = { .alloc_consistent = pci_4v_alloc_consistent, .free_consistent = pci_4v_free_consistent, .map_single = pci_4v_map_single, diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h index b14a725b430d..47cea16e1bad 100644 --- a/include/asm-sparc64/pci.h +++ b/include/asm-sparc64/pci.h @@ -54,7 +54,7 @@ struct pci_iommu_ops { void (*dma_sync_sg_for_cpu)(struct pci_dev *, struct scatterlist *, int, int); }; -extern struct pci_iommu_ops *pci_iommu_ops; +extern const struct pci_iommu_ops *pci_iommu_ops; /* Allocate and map kernel buffer using consistent mode DMA for a device. * hwdev should be valid struct pci_dev pointer for PCI devices. -- cgit v1.2.3 From 97b3cf050b467dda571943ceadff5452bed04549 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 11 Mar 2007 16:42:53 -0700 Subject: [SPARC64]: Add dummy host controller to root of all PCI domains. We fake up a dummy one in all cases because that is the simplest thing to do and it happens to be necessary for hypervisor systems. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 119 +++++++++++++++++++++++++++++---------- arch/sparc64/kernel/pci_impl.h | 9 +++ arch/sparc64/kernel/pci_psycho.c | 7 +++ arch/sparc64/kernel/pci_sabre.c | 12 ++++ arch/sparc64/kernel/pci_schizo.c | 6 ++ arch/sparc64/kernel/pci_sun4v.c | 6 ++ 6 files changed, 129 insertions(+), 30 deletions(-) (limited to 'arch/sparc64/kernel/pci.c') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 914a216da339..ec5f85b030ef 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -368,7 +368,8 @@ static void pci_parse_of_addrs(struct of_device *op, struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, struct device_node *node, - struct pci_bus *bus, int devfn) + struct pci_bus *bus, int devfn, + int host_controller) { struct dev_archdata *sd; struct pci_dev *dev; @@ -400,47 +401,62 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, dev->devfn = devfn; dev->multifunction = 0; /* maybe a lie? */ - dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff); - dev->device = of_getintprop_default(node, "device-id", 0xffff); - dev->subsystem_vendor = - of_getintprop_default(node, "subsystem-vendor-id", 0); - dev->subsystem_device = - of_getintprop_default(node, "subsystem-id", 0); - - dev->cfg_size = pci_cfg_space_size(dev); - + if (host_controller) { + dev->vendor = 0x108e; + dev->device = 0x8000; + dev->subsystem_vendor = 0x0000; + dev->subsystem_device = 0x0000; + dev->cfg_size = 256; + } else { + dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff); + dev->device = of_getintprop_default(node, "device-id", 0xffff); + dev->subsystem_vendor = + of_getintprop_default(node, "subsystem-vendor-id", 0); + dev->subsystem_device = + of_getintprop_default(node, "subsystem-id", 0); + + dev->cfg_size = pci_cfg_space_size(dev); + } sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); - /* dev->class = of_getintprop_default(node, "class-code", 0); */ - /* We can't actually use the firmware value, we have to read what - * is in the register right now. One reason is that in the case - * of IDE interfaces the firmware can sample the value before the - * the IDE interface is programmed into native mode. - */ - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); - dev->class = class >> 8; - + if (host_controller) { + dev->class = PCI_CLASS_BRIDGE_HOST << 8; + } else { + /* We can't actually use the firmware value, we have + * to read what is in the register right now. One + * reason is that in the case of IDE interfaces the + * firmware can sample the value before the the IDE + * interface is programmed into native mode. + */ + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); + dev->class = class >> 8; + } printk(" class: 0x%x\n", dev->class); dev->current_state = 4; /* unknown power state */ dev->error_state = pci_channel_io_normal; - if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { - /* a PCI-PCI bridge */ + if (host_controller) { dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; dev->rom_base_reg = PCI_ROM_ADDRESS1; - } else if (!strcmp(type, "cardbus")) { - dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; + dev->irq = PCI_IRQ_NONE; } else { - dev->hdr_type = PCI_HEADER_TYPE_NORMAL; - dev->rom_base_reg = PCI_ROM_ADDRESS; + if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { + /* a PCI-PCI bridge */ + dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; + dev->rom_base_reg = PCI_ROM_ADDRESS1; + } else if (!strcmp(type, "cardbus")) { + dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; + } else { + dev->hdr_type = PCI_HEADER_TYPE_NORMAL; + dev->rom_base_reg = PCI_ROM_ADDRESS; - dev->irq = sd->op->irqs[0]; - if (dev->irq == 0xffffffff) - dev->irq = PCI_IRQ_NONE; + dev->irq = sd->op->irqs[0]; + if (dev->irq == 0xffffffff) + dev->irq = PCI_IRQ_NONE; + } } - pci_parse_of_addrs(sd->op, node, dev); printk(" adding to system ...\n"); @@ -632,7 +648,7 @@ static void __init pci_of_scan_bus(struct pci_pbm_info *pbm, devfn = (reg[0] >> 8) & 0xff; /* create a new pci_dev for this device */ - dev = of_create_pci_dev(pbm, child, bus, devfn); + dev = of_create_pci_dev(pbm, child, bus, devfn, 0); if (!dev) continue; printk("PCI: dev header type: %x\n", dev->hdr_type); @@ -677,10 +693,49 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) pci_bus_register_of_sysfs(child_bus); } +int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev, + unsigned int devfn, + int where, int size, + u32 *value) +{ + static u8 fake_pci_config[] = { + 0x8e, 0x10, /* Vendor: 0x108e (Sun) */ + 0x00, 0x80, /* Device: 0x8000 (PBM) */ + 0x46, 0x01, /* Command: 0x0146 (SERR, PARITY, MASTER, MEM) */ + 0xa0, 0x22, /* Status: 0x02a0 (DEVSEL_MED, FB2B, 66MHZ) */ + 0x00, 0x00, 0x00, 0x06, /* Class: 0x06000000 host bridge */ + 0x00, /* Cacheline: 0x00 */ + 0x40, /* Latency: 0x40 */ + 0x00, /* Header-Type: 0x00 normal */ + }; + + *value = 0; + if (where >= 0 && where < sizeof(fake_pci_config) && + (where + size) >= 0 && + (where + size) < sizeof(fake_pci_config) && + size <= sizeof(u32)) { + while (size--) { + *value <<= 8; + *value |= fake_pci_config[where + size]; + } + } + + return PCIBIOS_SUCCESSFUL; +} + +int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev, + unsigned int devfn, + int where, int size, + u32 value) +{ + return PCIBIOS_SUCCESSFUL; +} + struct pci_bus * __init pci_scan_one_pbm(struct pci_pbm_info *pbm) { struct pci_controller_info *p = pbm->parent; struct device_node *node = pbm->prom_node; + struct pci_dev *host_pdev; struct pci_bus *bus; printk("PCI: Scanning PBM %s\n", node->full_name); @@ -698,6 +753,10 @@ struct pci_bus * __init pci_scan_one_pbm(struct pci_pbm_info *pbm) bus->resource[0] = &pbm->io_space; bus->resource[1] = &pbm->mem_space; + /* Create the dummy host bridge and link it in. */ + host_pdev = of_create_pci_dev(pbm, node, bus, 0x00, 1); + bus->self = host_pdev; + pci_of_scan_bus(pbm, node, bus); pci_bus_add_devices(bus); pci_bus_register_of_sysfs(bus); diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index c6714548d823..1208583fcb83 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -20,6 +20,15 @@ extern int pci_num_controllers; extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm); extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm); +extern int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev, + unsigned int devfn, + int where, int size, + u32 *value); +extern int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev, + unsigned int devfn, + int where, int size, + u32 value); + /* Error reporting support. */ extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); extern void pci_scan_for_master_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 2e5d40a26dbd..154c03290d5d 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -118,6 +118,10 @@ static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, u16 tmp16; u8 tmp8; + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, + size, value); + switch (size) { case 1: *value = 0xff; @@ -171,6 +175,9 @@ static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, unsigned char bus = bus_dev->number; u32 *addr; + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, + size, value); addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); if (!addr) return PCIBIOS_SUCCESSFUL; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 1bd7fc7c05e6..a2f129d29c20 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -319,6 +319,12 @@ static int __sabre_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) { + struct pci_pbm_info *pbm = bus->sysdata; + + if (bus == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus, devfn, where, + size, value); + if (!bus->number && sabre_out_of_range(devfn)) { switch (size) { case 1: @@ -435,6 +441,12 @@ static int __sabre_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { + struct pci_pbm_info *pbm = bus->sysdata; + + if (bus == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus, devfn, where, + size, value); + if (bus->number) return __sabre_write_pci_cfg(bus, devfn, where, size, value); diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index f1f105af8d3c..322cdbf50eff 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -125,6 +125,9 @@ static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, u16 tmp16; u8 tmp8; + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, + size, value); switch (size) { case 1: *value = 0xff; @@ -178,6 +181,9 @@ static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, unsigned char bus = bus_dev->number; u32 *addr; + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, + size, value); addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where); if (!addr) return PCIBIOS_SUCCESSFUL; diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index a8c12c1e8039..52bd4563492d 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -612,6 +612,9 @@ static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, unsigned int func = PCI_FUNC(devfn); unsigned long ret; + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, + size, value); if (pci_sun4v_out_of_range(pbm, bus, device, func)) { ret = ~0UL; } else { @@ -650,6 +653,9 @@ static int pci_sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, unsigned int func = PCI_FUNC(devfn); unsigned long ret; + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, + size, value); if (pci_sun4v_out_of_range(pbm, bus, device, func)) { /* Do nothing. */ } else { -- cgit v1.2.3 From 28f57e774d91ce01e03ff65caa2313bc8786b66f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 12 Mar 2007 19:40:26 -0700 Subject: [SPARC64]: Force dummy host controller onto bus zero. This helps deal with the invisible bridge that sits between the host controller and the top-most visisble PCI devices on hypervisor systems. For example, on T1000 the bus-range property says 2 --> 4 and so there is a PCI express bridge at bus 2, devfn 0, etc. So if we don't force the dummy host controller to bus zero, we'll try to create two devices with the same domain/bus/devfn triplet. Also, add some more log diagnostics to make debugging stuff like this easyer. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'arch/sparc64/kernel/pci.c') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index ec5f85b030ef..8a7c699bb109 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -392,7 +392,8 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, if (type == NULL) type = ""; - printk(" create device, devfn: %x, type: %s\n", devfn, type); + printk(" create device, devfn: %x, type: %s hostcontroller(%d)\n", + devfn, type, host_controller); dev->bus = bus; dev->sysdata = node; @@ -407,6 +408,9 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, dev->subsystem_vendor = 0x0000; dev->subsystem_device = 0x0000; dev->cfg_size = 256; + dev->class = PCI_CLASS_BRIDGE_HOST << 8; + sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), + 0x00, PCI_SLOT(devfn), PCI_FUNC(devfn)); } else { dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff); dev->device = of_getintprop_default(node, "device-id", 0xffff); @@ -416,13 +420,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, of_getintprop_default(node, "subsystem-id", 0); dev->cfg_size = pci_cfg_space_size(dev); - } - sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), - dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); - if (host_controller) { - dev->class = PCI_CLASS_BRIDGE_HOST << 8; - } else { /* We can't actually use the firmware value, we have * to read what is in the register right now. One * reason is that in the case of IDE interfaces the @@ -431,8 +429,12 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, */ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); dev->class = class >> 8; + + sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), + dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); } - printk(" class: 0x%x\n", dev->class); + printk(" class: 0x%x device name: %s\n", + dev->class, pci_name(dev)); dev->current_state = 4; /* unknown power state */ dev->error_state = pci_channel_io_normal; -- cgit v1.2.3 From a165b4205e0097c7544ec3c59522a3b20ec14eb1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 29 Mar 2007 01:50:16 -0700 Subject: [SPARC64]: Fix PCI rework to adhere to of_get_property() const return. Signed-off-by: David S. Miller --- arch/sparc64/kernel/of_device.c | 4 ++-- arch/sparc64/kernel/pci.c | 2 +- arch/sparc64/kernel/pci_common.c | 6 +++--- arch/sparc64/kernel/pci_sabre.c | 6 +++--- arch/sparc64/kernel/pci_schizo.c | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) (limited to 'arch/sparc64/kernel/pci.c') diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index f18eec6ad691..9ac9a307999a 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -317,7 +317,7 @@ static unsigned int of_bus_default_get_flags(const u32 *addr) static int of_bus_pci_match(struct device_node *np) { if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { - char *model = of_get_property(np, "model", NULL); + const char *model = of_get_property(np, "model", NULL); if (model && !strcmp(model, "SUNW,simba")) return 0; @@ -339,7 +339,7 @@ static int of_bus_pci_match(struct device_node *np) static int of_bus_simba_match(struct device_node *np) { - char *model = of_get_property(np, "model", NULL); + const char *model = of_get_property(np, "model", NULL); if (model && !strcmp(model, "SUNW,simba")) return 1; diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 8a7c699bb109..023af41ad68d 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -551,7 +551,7 @@ void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, ranges = of_get_property(node, "ranges", &len); simba = 0; if (ranges == NULL) { - char *model = of_get_property(node, "model", NULL); + const char *model = of_get_property(node, "model", NULL); if (model && !strcmp(model, "SUNW,simba")) { simba = 1; } else { diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 6b5c8e7a3eb0..1e6aeedf43c4 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -54,7 +54,7 @@ static void pci_register_legacy_regions(struct resource *io_res, static void pci_register_iommu_region(struct pci_pbm_info *pbm) { - u32 *vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); + const u32 *vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); if (vdma) { struct resource *rp = kmalloc(sizeof(*rp), GFP_KERNEL); @@ -73,7 +73,7 @@ static void pci_register_iommu_region(struct pci_pbm_info *pbm) void pci_determine_mem_io_space(struct pci_pbm_info *pbm) { - struct linux_prom_pci_ranges *pbm_ranges; + const struct linux_prom_pci_ranges *pbm_ranges; int i, saw_mem, saw_io; int num_pbm_ranges; @@ -82,7 +82,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) num_pbm_ranges = i / sizeof(*pbm_ranges); for (i = 0; i < num_pbm_ranges; i++) { - struct linux_prom_pci_ranges *pr = &pbm_ranges[i]; + const struct linux_prom_pci_ranges *pr = &pbm_ranges[i]; unsigned long a; u32 parent_phys_hi, parent_phys_lo; int type; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index a2f129d29c20..9a2ce0637c80 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1015,12 +1015,12 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp void sabre_init(struct device_node *dp, char *model_name) { - struct linux_prom64_registers *pr_regs; + const struct linux_prom64_registers *pr_regs; struct pci_controller_info *p; struct pci_iommu *iommu; int tsbsize; - u32 *busrange; - u32 *vdma; + const u32 *busrange; + const u32 *vdma; u32 upa_portid, dma_mask; u64 clear_irq; diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 322cdbf50eff..47a5aa94dcae 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1490,11 +1490,11 @@ static void schizo_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 portid, int chip_type) { - struct linux_prom64_registers *regs; - unsigned int *busrange; + const struct linux_prom64_registers *regs; + const unsigned int *busrange; struct pci_pbm_info *pbm; const char *chipset_name; - u32 *ino_bitmap; + const u32 *ino_bitmap; int is_pbm_a; switch (chip_type) { -- cgit v1.2.3