From 734925d27566aefe3b74e826cbb3422fa34cd65c Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sat, 24 Jun 2006 09:57:13 +0100 Subject: [PATCH] --- yaml --- r: 29597 b: refs/heads/master c: 3da4bd2bfc672a484d2a5df9f89b79f5e1e634dc h: refs/heads/master i: 29595: f3d3287c7254dea4d4c5dbbaca8c7fa1f713e6cc v: v3 --- [refs] | 2 +- trunk/Documentation/sparc/sbus_drivers.txt | 95 +-- trunk/arch/arm/kernel/iwmmxt.S | 2 +- trunk/arch/i386/kernel/vmlinux.lds.S | 7 - trunk/arch/sparc/kernel/Makefile | 2 +- trunk/arch/sparc/kernel/ebus.c | 185 +++--- trunk/arch/sparc/kernel/ioport.c | 131 +---- trunk/arch/sparc/kernel/of_device.c | 268 --------- trunk/arch/sparc/kernel/pcic.c | 3 +- trunk/arch/sparc/kernel/prom.c | 474 --------------- trunk/arch/sparc/mm/init.c | 2 - trunk/arch/sparc64/defconfig | 12 +- trunk/arch/sparc64/kernel/Makefile | 2 +- trunk/arch/sparc64/kernel/auxio.c | 109 ++-- trunk/arch/sparc64/kernel/central.c | 127 ++-- trunk/arch/sparc64/kernel/chmc.c | 69 ++- trunk/arch/sparc64/kernel/devices.c | 222 ++++--- trunk/arch/sparc64/kernel/ebus.c | 197 ++++--- trunk/arch/sparc64/kernel/irq.c | 19 +- trunk/arch/sparc64/kernel/isa.c | 183 +++--- trunk/arch/sparc64/kernel/of_device.c | 279 --------- trunk/arch/sparc64/kernel/pci.c | 59 +- trunk/arch/sparc64/kernel/pci_common.c | 227 ++++--- trunk/arch/sparc64/kernel/pci_impl.h | 3 +- trunk/arch/sparc64/kernel/pci_psycho.c | 106 ++-- trunk/arch/sparc64/kernel/pci_sabre.c | 195 ++++--- trunk/arch/sparc64/kernel/pci_schizo.c | 171 +++--- trunk/arch/sparc64/kernel/pci_sun4v.c | 160 ++--- trunk/arch/sparc64/kernel/power.c | 113 ++-- trunk/arch/sparc64/kernel/prom.c | 650 --------------------- trunk/arch/sparc64/kernel/sbus.c | 67 +-- trunk/arch/sparc64/kernel/setup.c | 4 +- trunk/arch/sparc64/kernel/smp.c | 41 +- trunk/arch/sparc64/kernel/time.c | 386 ++++++------ trunk/arch/sparc64/kernel/traps.c | 18 +- trunk/arch/sparc64/kernel/unaligned.c | 9 - trunk/arch/sparc64/mm/init.c | 52 +- trunk/arch/sparc64/solaris/misc.c | 34 +- trunk/drivers/base/power/Makefile | 1 - trunk/drivers/base/power/resume.c | 4 - trunk/drivers/base/power/trace.c | 228 -------- trunk/drivers/char/drm/i915_dma.c | 4 +- trunk/drivers/char/drm/i915_drm.h | 13 - trunk/drivers/char/drm/i915_drv.h | 6 +- trunk/drivers/char/drm/i915_irq.c | 69 +-- trunk/drivers/char/drm/radeon_cp.c | 6 +- trunk/drivers/char/drm/radeon_drm.h | 7 +- trunk/drivers/char/drm/radeon_drv.h | 10 +- trunk/drivers/char/drm/radeon_state.c | 39 +- trunk/drivers/char/rtc.c | 4 +- trunk/drivers/input/misc/Kconfig | 2 +- trunk/drivers/input/misc/sparcspkr.c | 218 +++---- trunk/drivers/input/serio/i8042-sparcio.h | 10 +- trunk/drivers/net/myri_sbus.c | 116 ++-- trunk/drivers/net/myri_sbus.h | 1 + trunk/drivers/net/sunbmac.c | 127 ++-- trunk/drivers/net/sunbmac.h | 1 + trunk/drivers/net/sungem.c | 19 +- trunk/drivers/net/sunhme.c | 417 +++++++------ trunk/drivers/net/sunhme.h | 1 + trunk/drivers/net/sunlance.c | 173 +++--- trunk/drivers/net/sunqe.c | 468 ++++++++------- trunk/drivers/net/tg3.c | 10 +- trunk/drivers/net/tulip/tulip_core.c | 12 +- trunk/drivers/parport/parport_sunbpp.c | 134 ++--- trunk/drivers/sbus/char/bbc_envctrl.c | 4 +- trunk/drivers/sbus/char/bbc_i2c.c | 4 +- trunk/drivers/sbus/char/display7seg.c | 2 +- trunk/drivers/sbus/char/envctrl.c | 71 +-- trunk/drivers/sbus/char/flash.c | 16 +- trunk/drivers/sbus/char/openprom.c | 4 +- trunk/drivers/sbus/sbus.c | 582 +++++++++++++----- trunk/drivers/scsi/esp.c | 315 +++++----- trunk/drivers/scsi/esp.h | 4 + trunk/drivers/scsi/qlogicpti.c | 361 ++++++------ trunk/drivers/serial/sunhv.c | 35 +- trunk/drivers/serial/sunsab.c | 12 +- trunk/drivers/serial/sunsu.c | 4 +- trunk/drivers/serial/sunzilog.c | 2 +- trunk/drivers/usb/core/devio.c | 8 +- trunk/drivers/video/aty/atyfb_base.c | 2 +- trunk/drivers/video/intelfb/intelfb.h | 2 +- trunk/drivers/video/intelfb/intelfbdrv.c | 18 +- trunk/drivers/video/intelfb/intelfbhw.c | 24 +- trunk/include/asm-generic/rtc.h | 7 +- trunk/include/asm-sparc/ebus.h | 17 +- trunk/include/asm-sparc/of_device.h | 63 -- trunk/include/asm-sparc/pbm.h | 3 +- trunk/include/asm-sparc/prom.h | 98 ---- trunk/include/asm-sparc/sbus.h | 28 +- trunk/include/asm-sparc64/ebus.h | 20 +- trunk/include/asm-sparc64/fhc.h | 7 +- trunk/include/asm-sparc64/floppy.h | 27 +- trunk/include/asm-sparc64/isa.h | 21 +- trunk/include/asm-sparc64/of_device.h | 64 -- trunk/include/asm-sparc64/oplib.h | 5 +- trunk/include/asm-sparc64/parport.h | 25 +- trunk/include/asm-sparc64/pbm.h | 15 +- trunk/include/asm-sparc64/pgtable.h | 2 - trunk/include/asm-sparc64/prom.h | 98 ---- trunk/include/asm-sparc64/sbus.h | 29 +- trunk/include/asm-sparc64/vdev.h | 5 +- trunk/include/linux/resume-trace.h | 30 - trunk/kernel/power/Kconfig | 9 - trunk/sound/sparc/amd7930.c | 138 ++--- trunk/sound/sparc/cs4231.c | 13 +- 106 files changed, 3271 insertions(+), 5708 deletions(-) delete mode 100644 trunk/arch/sparc/kernel/of_device.c delete mode 100644 trunk/arch/sparc/kernel/prom.c delete mode 100644 trunk/arch/sparc64/kernel/of_device.c delete mode 100644 trunk/arch/sparc64/kernel/prom.c delete mode 100644 trunk/drivers/base/power/trace.c delete mode 100644 trunk/include/asm-sparc/of_device.h delete mode 100644 trunk/include/asm-sparc/prom.h delete mode 100644 trunk/include/asm-sparc64/of_device.h delete mode 100644 trunk/include/asm-sparc64/prom.h delete mode 100644 trunk/include/linux/resume-trace.h diff --git a/[refs] b/[refs] index 52fc15675078..0d319ad0afd8 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 83626b01275d0228516b4d97da008328fc37c934 +refs/heads/master: 3da4bd2bfc672a484d2a5df9f89b79f5e1e634dc diff --git a/trunk/Documentation/sparc/sbus_drivers.txt b/trunk/Documentation/sparc/sbus_drivers.txt index 4b9351624f13..876195dc2aef 100644 --- a/trunk/Documentation/sparc/sbus_drivers.txt +++ b/trunk/Documentation/sparc/sbus_drivers.txt @@ -25,84 +25,42 @@ the bits necessary to run your device. The most commonly used members of this structure, and their typical usage, will be detailed below. - Here is a piece of skeleton code for perofming a device -probe in an SBUS driverunder Linux: + Here is how probing is performed by an SBUS driver +under Linux: - static int __devinit mydevice_probe_one(struct sbus_dev *sdev) + static void init_one_mydevice(struct sbus_dev *sdev) { - struct mysdevice *mp = kzalloc(sizeof(*mp), GFP_KERNEL); - - if (!mp) - return -ENODEV; - - ... - dev_set_drvdata(&sdev->ofdev.dev, mp); - return 0; ... } - static int __devinit mydevice_probe(struct of_device *dev, - const struct of_device_id *match) + static int mydevice_match(struct sbus_dev *sdev) { - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - - return mydevice_probe_one(sdev); + if (some_criteria(sdev)) + return 1; + return 0; } - static int __devexit mydevice_remove(struct of_device *dev) + static void mydevice_probe(void) { - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - struct mydevice *mp = dev_get_drvdata(&dev->dev); - - return mydevice_remove_one(sdev, mp); - } - - static struct of_device_id mydevice_match[] = { - { - .name = "mydevice", - }, - {}, - }; - - MODULE_DEVICE_TABLE(of, mydevice_match); - - static struct of_platform_driver mydevice_driver = { - .name = "mydevice", - .match_table = mydevice_match, - .probe = mydevice_probe, - .remove = __devexit_p(mydevice_remove), - }; - - static int __init mydevice_init(void) - { - return of_register_driver(&mydevice_driver, &sbus_bus_type); - } + struct sbus_bus *sbus; + struct sbus_dev *sdev; - static void __exit mydevice_exit(void) - { - of_unregister_driver(&mydevice_driver); + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { + if (mydevice_match(sdev)) + init_one_mydevice(sdev); + } + } } - module_init(mydevice_init); - module_exit(mydevice_exit); - - The mydevice_match table is a series of entries which -describes what SBUS devices your driver is meant for. In the -simplest case you specify a string for the 'name' field. Every -SBUS device with a 'name' property matching your string will -be passed one-by-one to your .probe method. - - You should store away your device private state structure -pointer in the drvdata area so that you can retrieve it later on -in your .remove method. + All this does is walk through all SBUS devices in the +system, checks each to see if it is of the type which +your driver is written for, and if so it calls the init +routine to attach the device and prepare to drive it. - Any memory allocated, registers mapped, IRQs registered, -etc. must be undone by your .remove method so that all resources -of your device are relased by the time it returns. - - You should _NOT_ use the for_each_sbus(), for_each_sbusdev(), -and for_all_sbusdev() interfaces. They are deprecated, will be -removed, and no new driver should reference them ever. + "init_one_mydevice" might do things like allocate software +state structures, map in I/O registers, place the hardware +into an initialized state, etc. Mapping and Accessing I/O Registers @@ -305,3 +263,10 @@ discussed above and plus it handles both PCI and SBUS boards. Lance driver abuses consistent mappings for data transfer. It is a nifty trick which we do not particularly recommend... Just check it out and know that it's legal. + + Bad examples, do NOT use + + drivers/video/cgsix.c + This one uses result of sbus_ioremap as if it is an address. +This does NOT work on sparc64 and therefore is broken. We will +convert it at a later date. diff --git a/trunk/arch/arm/kernel/iwmmxt.S b/trunk/arch/arm/kernel/iwmmxt.S index af9e0ae952d5..a3bae95e536c 100644 --- a/trunk/arch/arm/kernel/iwmmxt.S +++ b/trunk/arch/arm/kernel/iwmmxt.S @@ -273,7 +273,7 @@ ENTRY(iwmmxt_task_restore) * * r0 = previous task_struct pointer (must be preserved) * r1 = previous thread_info pointer - * r2 = next thread_info.cpu_domain pointer (must be preserved) + * r2 = next thread_info pointer (must be preserved) * * Called only from __switch_to with task preemption disabled. * No need to care about preserving r4 and above. diff --git a/trunk/arch/i386/kernel/vmlinux.lds.S b/trunk/arch/i386/kernel/vmlinux.lds.S index 7512f39c9f25..8831303a473f 100644 --- a/trunk/arch/i386/kernel/vmlinux.lds.S +++ b/trunk/arch/i386/kernel/vmlinux.lds.S @@ -37,13 +37,6 @@ SECTIONS RODATA - . = ALIGN(4); - __tracedata_start = .; - .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { - *(.tracedata) - } - __tracedata_end = .; - /* writeable */ .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */ *(.data) diff --git a/trunk/arch/sparc/kernel/Makefile b/trunk/arch/sparc/kernel/Makefile index 6616ee05c313..1b83e21841b5 100644 --- a/trunk/arch/sparc/kernel/Makefile +++ b/trunk/arch/sparc/kernel/Makefile @@ -12,7 +12,7 @@ obj-y := entry.o wof.o wuf.o etrap.o rtrap.o traps.o $(IRQ_OBJS) \ sys_sparc.o sunos_asm.o systbls.o \ time.o windows.o cpu.o devices.o sclow.o \ tadpole.o tick14.o ptrace.o sys_solaris.o \ - unaligned.o muldiv.o semaphore.o prom.o of_device.o + unaligned.o muldiv.o semaphore.o obj-$(CONFIG_PCI) += pcic.o obj-$(CONFIG_SUN4) += sun4setup.o diff --git a/trunk/arch/sparc/kernel/ebus.c b/trunk/arch/sparc/kernel/ebus.c index a7a4892956c8..5c3529ceb5d6 100644 --- a/trunk/arch/sparc/kernel/ebus.c +++ b/trunk/arch/sparc/kernel/ebus.c @@ -20,7 +20,6 @@ #include #include #include -#include #include struct linux_ebus *ebus_chain = NULL; @@ -84,81 +83,79 @@ int __init ebus_blacklist_irq(char *name) return 0; } -void __init fill_ebus_child(struct device_node *dp, - struct linux_ebus_child *dev) +void __init fill_ebus_child(int node, struct linux_prom_registers *preg, + struct linux_ebus_child *dev) { - int *regs; - int *irqs; + int regs[PROMREG_MAX]; + int irqs[PROMREG_MAX]; + char lbuf[128]; int i, len; - dev->prom_node = dp; - regs = of_get_property(dp, "reg", &len); - if (!regs) - len = 0; + dev->prom_node = node; + prom_getstring(node, "name", lbuf, sizeof(lbuf)); + strcpy(dev->prom_name, lbuf); + + len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); + if (len == -1) len = 0; dev->num_addrs = len / sizeof(regs[0]); for (i = 0; i < dev->num_addrs; i++) { if (regs[i] >= dev->parent->num_addrs) { prom_printf("UGH: property for %s was %d, need < %d\n", - dev->prom_node->name, len, - dev->parent->num_addrs); + dev->prom_name, len, dev->parent->num_addrs); panic(__FUNCTION__); } - - /* XXX resource */ - dev->resource[i].start = - dev->parent->resource[regs[i]].start; + dev->resource[i].start = dev->parent->resource[regs[i]].start; /* XXX resource */ } for (i = 0; i < PROMINTR_MAX; i++) dev->irqs[i] = PCI_IRQ_NONE; - if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) { + if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) { dev->num_irqs = 1; + } else if ((len = prom_getproperty(node, "interrupts", + (char *)&irqs, sizeof(irqs))) == -1 || len == 0) { + dev->num_irqs = 0; + dev->irqs[0] = 0; + if (dev->parent->num_irqs != 0) { + dev->num_irqs = 1; + dev->irqs[0] = dev->parent->irqs[0]; +/* P3 */ /* printk("EBUS: dev %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */ + } } else { - irqs = of_get_property(dp, "interrupts", &len); - if (!irqs) { + dev->num_irqs = len / sizeof(irqs[0]); + if (irqs[0] == 0 || irqs[0] >= 8) { + /* + * XXX Zero is a valid pin number... + * This works as long as Ebus is not wired to INTA#. + */ + printk("EBUS: %s got bad irq %d from PROM\n", + dev->prom_name, irqs[0]); dev->num_irqs = 0; dev->irqs[0] = 0; - if (dev->parent->num_irqs != 0) { - dev->num_irqs = 1; - dev->irqs[0] = dev->parent->irqs[0]; - } } else { - dev->num_irqs = len / sizeof(irqs[0]); - if (irqs[0] == 0 || irqs[0] >= 8) { - /* - * XXX Zero is a valid pin number... - * This works as long as Ebus is not wired - * to INTA#. - */ - printk("EBUS: %s got bad irq %d from PROM\n", - dev->prom_node->name, irqs[0]); - dev->num_irqs = 0; - dev->irqs[0] = 0; - } else { - dev->irqs[0] = - pcic_pin_to_irq(irqs[0], - dev->prom_node->name); - } + dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name); } } } -void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) +void __init fill_ebus_device(int node, struct linux_ebus_device *dev) { - struct linux_prom_registers *regs; + struct linux_prom_registers regs[PROMREG_MAX]; struct linux_ebus_child *child; - int *irqs; + int irqs[PROMINTR_MAX]; + char lbuf[128]; int i, n, len; unsigned long baseaddr; - dev->prom_node = dp; + dev->prom_node = node; + prom_getstring(node, "name", lbuf, sizeof(lbuf)); + strcpy(dev->prom_name, lbuf); - regs = of_get_property(dp, "reg", &len); + len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); if (len % sizeof(struct linux_prom_registers)) { prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", - dev->prom_node->name, len, + dev->prom_name, len, (int)sizeof(struct linux_prom_registers)); panic(__FUNCTION__); } @@ -200,7 +197,7 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d if ((baseaddr = (unsigned long) ioremap(baseaddr, regs[i].reg_size)) == 0) { panic("ebus: unable to remap dev %s", - dev->prom_node->name); + dev->prom_name); } } dev->resource[i].start = baseaddr; /* XXX Unaligned */ @@ -209,43 +206,29 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d for (i = 0; i < PROMINTR_MAX; i++) dev->irqs[i] = PCI_IRQ_NONE; - if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) { + if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) { dev->num_irqs = 1; + } else if ((len = prom_getproperty(node, "interrupts", + (char *)&irqs, sizeof(irqs))) == -1 || len == 0) { + dev->num_irqs = 0; + if ((dev->irqs[0] = dev->bus->self->irq) != 0) { + dev->num_irqs = 1; +/* P3 */ /* printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */ + } } else { - irqs = of_get_property(dp, "interrupts", &len); - if (!irqs) { + dev->num_irqs = 1; /* dev->num_irqs = len / sizeof(irqs[0]); */ + if (irqs[0] == 0 || irqs[0] >= 8) { + /* See above for the parent. XXX */ + printk("EBUS: %s got bad irq %d from PROM\n", + dev->prom_name, irqs[0]); dev->num_irqs = 0; - if ((dev->irqs[0] = dev->bus->self->irq) != 0) { - dev->num_irqs = 1; -/* P3 */ /* printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */ - } + dev->irqs[0] = 0; } else { - dev->num_irqs = 1; /* dev->num_irqs = len / sizeof(irqs[0]); */ - if (irqs[0] == 0 || irqs[0] >= 8) { - /* See above for the parent. XXX */ - printk("EBUS: %s got bad irq %d from PROM\n", - dev->prom_node->name, irqs[0]); - dev->num_irqs = 0; - dev->irqs[0] = 0; - } else { - dev->irqs[0] = - pcic_pin_to_irq(irqs[0], - dev->prom_node->name); - } + dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name); } } - dev->ofdev.node = dp; - dev->ofdev.dev.parent = &dev->bus->ofdev.dev; - dev->ofdev.dev.bus = &ebus_bus_type; - strcpy(dev->ofdev.dev.bus_id, dp->path_component_name); - - /* Register with core */ - if (of_device_register(&dev->ofdev) != 0) - printk(KERN_DEBUG "ebus: device registration error for %s!\n", - dev->ofdev.dev.bus_id); - - if ((dp = dp->child) != NULL) { + if ((node = prom_getchild(node))) { dev->children = (struct linux_ebus_child *) ebus_alloc(sizeof(struct linux_ebus_child)); @@ -253,9 +236,9 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d child->next = NULL; child->parent = dev; child->bus = dev->bus; - fill_ebus_child(dp, child); + fill_ebus_child(node, ®s[0], child); - while ((dp = dp->sibling) != NULL) { + while ((node = prom_getsibling(node)) != 0) { child->next = (struct linux_ebus_child *) ebus_alloc(sizeof(struct linux_ebus_child)); @@ -263,49 +246,51 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d child->next = NULL; child->parent = dev; child->bus = dev->bus; - fill_ebus_child(dp, child); + fill_ebus_child(node, ®s[0], child); } } } void __init ebus_init(void) { - struct linux_prom_pci_registers *regs; + struct linux_prom_pci_registers regs[PROMREG_MAX]; struct linux_pbm_info *pbm; struct linux_ebus_device *dev; struct linux_ebus *ebus; struct ebus_system_entry *sp; struct pci_dev *pdev; struct pcidev_cookie *cookie; - struct device_node *dp; + char lbuf[128]; unsigned long addr, *base; unsigned short pci_command; - int len, reg, nreg; + int nd, len, ebusnd; + int reg, nreg; int num_ebus = 0; - dp = of_find_node_by_path("/"); + prom_getstring(prom_root_node, "name", lbuf, sizeof(lbuf)); for (sp = ebus_blacklist; sp->esname != NULL; sp++) { - if (strcmp(dp->name, sp->esname) == 0) { + if (strcmp(lbuf, sp->esname) == 0) { ebus_blackp = sp->ipt; break; } } pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, NULL); - if (!pdev) + if (!pdev) { return; - + } cookie = pdev->sysdata; - dp = cookie->prom_node; + ebusnd = cookie->prom_node; ebus_chain = ebus = (struct linux_ebus *) ebus_alloc(sizeof(struct linux_ebus)); ebus->next = NULL; - while (dp) { - struct device_node *nd; + while (ebusnd) { - ebus->prom_node = dp; + prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf)); + ebus->prom_node = ebusnd; + strcpy(ebus->prom_name, lbuf); ebus->self = pdev; ebus->parent = pbm = cookie->pbm; @@ -314,8 +299,9 @@ void __init ebus_init(void) pci_command |= PCI_COMMAND_MASTER; pci_write_config_word(pdev, PCI_COMMAND, pci_command); - regs = of_get_property(dp, "reg", &len); - if (!regs) { + len = prom_getproperty(ebusnd, "reg", (void *)regs, + sizeof(regs)); + if (len == 0 || len == -1) { prom_printf("%s: can't find reg property\n", __FUNCTION__); prom_halt(); @@ -331,18 +317,7 @@ void __init ebus_init(void) *base++ = addr; } - ebus->ofdev.node = dp; - ebus->ofdev.dev.parent = &pdev->dev; - ebus->ofdev.dev.bus = &ebus_bus_type; - strcpy(ebus->ofdev.dev.bus_id, dp->path_component_name); - - /* Register with core */ - if (of_device_register(&ebus->ofdev) != 0) - printk(KERN_DEBUG "ebus: device registration error for %s!\n", - ebus->ofdev.dev.bus_id); - - - nd = dp->child; + nd = prom_getchild(ebusnd); if (!nd) goto next_ebus; @@ -355,7 +330,7 @@ void __init ebus_init(void) dev->bus = ebus; fill_ebus_device(nd, dev); - while ((nd = nd->sibling) != NULL) { + while ((nd = prom_getsibling(nd)) != 0) { dev->next = (struct linux_ebus_device *) ebus_alloc(sizeof(struct linux_ebus_device)); @@ -373,7 +348,7 @@ void __init ebus_init(void) break; cookie = pdev->sysdata; - dp = cookie->prom_node; + ebusnd = cookie->prom_node; ebus->next = (struct linux_ebus *) ebus_alloc(sizeof(struct linux_ebus)); diff --git a/trunk/arch/sparc/kernel/ioport.c b/trunk/arch/sparc/kernel/ioport.c index ae4c667c906f..f9ff29734848 100644 --- a/trunk/arch/sparc/kernel/ioport.c +++ b/trunk/arch/sparc/kernel/ioport.c @@ -39,8 +39,6 @@ #include #include #include -#include -#include #include #include #include @@ -226,54 +224,10 @@ static void _sparc_free_io(struct resource *res) #ifdef CONFIG_SBUS -void sbus_set_sbus64(struct sbus_dev *sdev, int x) -{ +void sbus_set_sbus64(struct sbus_dev *sdev, int x) { printk("sbus_set_sbus64: unsupported\n"); } -extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq); -void __init sbus_fill_device_irq(struct sbus_dev *sdev) -{ - struct linux_prom_irqs irqs[PROMINTR_MAX]; - int len; - - len = prom_getproperty(sdev->prom_node, "intr", - (char *)irqs, sizeof(irqs)); - if (len != -1) { - sdev->num_irqs = len / 8; - if (sdev->num_irqs == 0) { - sdev->irqs[0] = 0; - } else if (sparc_cpu_model == sun4d) { - for (len = 0; len < sdev->num_irqs; len++) - sdev->irqs[len] = - sun4d_build_irq(sdev, irqs[len].pri); - } else { - for (len = 0; len < sdev->num_irqs; len++) - sdev->irqs[len] = irqs[len].pri; - } - } else { - int interrupts[PROMINTR_MAX]; - - /* No "intr" node found-- check for "interrupts" node. - * This node contains SBus interrupt levels, not IPLs - * as in "intr", and no vector values. We convert - * SBus interrupt levels to PILs (platform specific). - */ - len = prom_getproperty(sdev->prom_node, "interrupts", - (char *)interrupts, sizeof(interrupts)); - if (len == -1) { - sdev->irqs[0] = 0; - sdev->num_irqs = 0; - } else { - sdev->num_irqs = len / sizeof(int); - for (len = 0; len < sdev->num_irqs; len++) { - sdev->irqs[len] = - sbint_to_irq(sdev, interrupts[len]); - } - } - } -} - /* * Allocate a chunk of memory suitable for DMA. * Typically devices use them for control blocks. @@ -460,89 +414,6 @@ void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg, { printk("sbus_dma_sync_sg_for_device: not implemented yet\n"); } - -/* Support code for sbus_init(). */ -/* - * XXX This functions appears to be a distorted version of - * prom_sbus_ranges_init(), with all sun4d stuff cut away. - * Ask DaveM what is going on here, how is sun4d supposed to work... XXX - */ -/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */ -void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) -{ - int parent_node = pn->node; - - if (sparc_cpu_model == sun4d) { - struct linux_prom_ranges iounit_ranges[PROMREG_MAX]; - int num_iounit_ranges, len; - - len = prom_getproperty(parent_node, "ranges", - (char *) iounit_ranges, - sizeof (iounit_ranges)); - if (len != -1) { - num_iounit_ranges = - (len / sizeof(struct linux_prom_ranges)); - prom_adjust_ranges(sbus->sbus_ranges, - sbus->num_sbus_ranges, - iounit_ranges, num_iounit_ranges); - } - } -} - -void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) -{ - struct device_node *parent = dp->parent; - - if (sparc_cpu_model != sun4d && - parent != NULL && - !strcmp(parent->name, "iommu")) { - extern void iommu_init(int iommu_node, struct sbus_bus *sbus); - - iommu_init(parent->node, sbus); - } - - if (sparc_cpu_model == sun4d) { - extern void iounit_init(int sbi_node, int iounit_node, - struct sbus_bus *sbus); - - iounit_init(dp->node, parent->node, sbus); - } -} - -void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp) -{ - if (sparc_cpu_model == sun4d) { - struct device_node *parent = dp->parent; - - sbus->devid = of_getintprop_default(parent, "device-id", 0); - sbus->board = of_getintprop_default(parent, "board#", 0); - } -} - -int __init sbus_arch_preinit(void) -{ - extern void register_proc_sparc_ioport(void); - - register_proc_sparc_ioport(); - -#ifdef CONFIG_SUN4 - { - extern void sun4_dvma_init(void); - sun4_dvma_init(); - } - return 1; -#else - return 0; -#endif -} - -void __init sbus_arch_postinit(void) -{ - if (sparc_cpu_model == sun4d) { - extern void sun4d_init_sbi_irq(void); - sun4d_init_sbi_irq(); - } -} #endif /* CONFIG_SBUS */ #ifdef CONFIG_PCI diff --git a/trunk/arch/sparc/kernel/of_device.c b/trunk/arch/sparc/kernel/of_device.c deleted file mode 100644 index 001b8673b4bd..000000000000 --- a/trunk/arch/sparc/kernel/of_device.c +++ /dev/null @@ -1,268 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/** - * of_match_device - Tell if an of_device structure has a matching - * of_match structure - * @ids: array of of device match structures to search in - * @dev: the of device structure to match against - * - * Used by a driver to check whether an of_device present in the - * system is in its list of supported devices. - */ -const struct of_device_id *of_match_device(const struct of_device_id *matches, - const struct of_device *dev) -{ - if (!dev->node) - return NULL; - while (matches->name[0] || matches->type[0] || matches->compatible[0]) { - int match = 1; - if (matches->name[0]) - match &= dev->node->name - && !strcmp(matches->name, dev->node->name); - if (matches->type[0]) - match &= dev->node->type - && !strcmp(matches->type, dev->node->type); - if (matches->compatible[0]) - match &= of_device_is_compatible(dev->node, - matches->compatible); - if (match) - return matches; - matches++; - } - return NULL; -} - -static int of_platform_bus_match(struct device *dev, struct device_driver *drv) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * of_drv = to_of_platform_driver(drv); - const struct of_device_id * matches = of_drv->match_table; - - if (!matches) - return 0; - - return of_match_device(matches, of_dev) != NULL; -} - -struct of_device *of_dev_get(struct of_device *dev) -{ - struct device *tmp; - - if (!dev) - return NULL; - tmp = get_device(&dev->dev); - if (tmp) - return to_of_device(tmp); - else - return NULL; -} - -void of_dev_put(struct of_device *dev) -{ - if (dev) - put_device(&dev->dev); -} - - -static int of_device_probe(struct device *dev) -{ - int error = -ENODEV; - struct of_platform_driver *drv; - struct of_device *of_dev; - const struct of_device_id *match; - - drv = to_of_platform_driver(dev->driver); - of_dev = to_of_device(dev); - - if (!drv->probe) - return error; - - of_dev_get(of_dev); - - match = of_match_device(drv->match_table, of_dev); - if (match) - error = drv->probe(of_dev, match); - if (error) - of_dev_put(of_dev); - - return error; -} - -static int of_device_remove(struct device *dev) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - - if (dev->driver && drv->remove) - drv->remove(of_dev); - return 0; -} - -static int of_device_suspend(struct device *dev, pm_message_t state) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - int error = 0; - - if (dev->driver && drv->suspend) - error = drv->suspend(of_dev, state); - return error; -} - -static int of_device_resume(struct device * dev) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - int error = 0; - - if (dev->driver && drv->resume) - error = drv->resume(of_dev); - return error; -} - -#ifdef CONFIG_PCI -struct bus_type ebus_bus_type = { - .name = "ebus", - .match = of_platform_bus_match, - .probe = of_device_probe, - .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, -}; -#endif - -#ifdef CONFIG_SBUS -struct bus_type sbus_bus_type = { - .name = "sbus", - .match = of_platform_bus_match, - .probe = of_device_probe, - .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, -}; -#endif - -static int __init of_bus_driver_init(void) -{ - int err = 0; - -#ifdef CONFIG_PCI - if (!err) - err = bus_register(&ebus_bus_type); -#endif -#ifdef CONFIG_SBUS - if (!err) - err = bus_register(&sbus_bus_type); -#endif - return 0; -} - -postcore_initcall(of_bus_driver_init); - -int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) -{ - /* initialize common driver fields */ - drv->driver.name = drv->name; - drv->driver.bus = bus; - - /* register with core */ - return driver_register(&drv->driver); -} - -void of_unregister_driver(struct of_platform_driver *drv) -{ - driver_unregister(&drv->driver); -} - - -static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct of_device *ofdev; - - ofdev = to_of_device(dev); - return sprintf(buf, "%s", ofdev->node->full_name); -} - -static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); - -/** - * of_release_dev - free an of device structure when all users of it are finished. - * @dev: device that's been disconnected - * - * Will be called only by the device core when all users of this of device are - * done. - */ -void of_release_dev(struct device *dev) -{ - struct of_device *ofdev; - - ofdev = to_of_device(dev); - - kfree(ofdev); -} - -int of_device_register(struct of_device *ofdev) -{ - int rc; - - BUG_ON(ofdev->node == NULL); - - rc = device_register(&ofdev->dev); - if (rc) - return rc; - - device_create_file(&ofdev->dev, &dev_attr_devspec); - - return 0; -} - -void of_device_unregister(struct of_device *ofdev) -{ - device_remove_file(&ofdev->dev, &dev_attr_devspec); - device_unregister(&ofdev->dev); -} - -struct of_device* of_platform_device_create(struct device_node *np, - const char *bus_id, - struct device *parent, - struct bus_type *bus) -{ - struct of_device *dev; - - dev = kmalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return NULL; - memset(dev, 0, sizeof(*dev)); - - dev->dev.parent = parent; - dev->dev.bus = bus; - dev->dev.release = of_release_dev; - - strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); - - if (of_device_register(dev) != 0) { - kfree(dev); - return NULL; - } - - return dev; -} - -EXPORT_SYMBOL(of_match_device); -EXPORT_SYMBOL(of_register_driver); -EXPORT_SYMBOL(of_unregister_driver); -EXPORT_SYMBOL(of_device_register); -EXPORT_SYMBOL(of_device_unregister); -EXPORT_SYMBOL(of_dev_get); -EXPORT_SYMBOL(of_dev_put); -EXPORT_SYMBOL(of_platform_device_create); -EXPORT_SYMBOL(of_release_dev); diff --git a/trunk/arch/sparc/kernel/pcic.c b/trunk/arch/sparc/kernel/pcic.c index bcfdddd0418a..bcdf5ad0f035 100644 --- a/trunk/arch/sparc/kernel/pcic.c +++ b/trunk/arch/sparc/kernel/pcic.c @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -666,7 +665,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) /* cookies */ pcp = pci_devcookie_alloc(); pcp->pbm = &pcic->pbm; - pcp->prom_node = of_find_node_by_phandle(node); + pcp->prom_node = node; dev->sysdata = pcp; /* fixing I/O to look like memory */ diff --git a/trunk/arch/sparc/kernel/prom.c b/trunk/arch/sparc/kernel/prom.c deleted file mode 100644 index 63b2b9bd778e..000000000000 --- a/trunk/arch/sparc/kernel/prom.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Procedures for creating, accessing and interpreting the device tree. - * - * Paul Mackerras August 1996. - * Copyright (C) 1996-2005 Paul Mackerras. - * - * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. - * {engebret|bergner}@us.ibm.com - * - * Adapted for sparc32 by David S. Miller davem@davemloft.net - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -static struct device_node *allnodes; - -int of_device_is_compatible(struct device_node *device, const char *compat) -{ - const char* cp; - int cplen, l; - - cp = (char *) of_get_property(device, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - if (strncmp(cp, compat, strlen(compat)) == 0) - return 1; - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - - return 0; -} -EXPORT_SYMBOL(of_device_is_compatible); - -struct device_node *of_get_parent(const struct device_node *node) -{ - struct device_node *np; - - if (!node) - return NULL; - - np = node->parent; - - return np; -} -EXPORT_SYMBOL(of_get_parent); - -struct device_node *of_get_next_child(const struct device_node *node, - struct device_node *prev) -{ - struct device_node *next; - - next = prev ? prev->sibling : node->child; - for (; next != 0; next = next->sibling) { - break; - } - - return next; -} -EXPORT_SYMBOL(of_get_next_child); - -struct device_node *of_find_node_by_path(const char *path) -{ - struct device_node *np = allnodes; - - for (; np != 0; np = np->allnext) { - if (np->full_name != 0 && strcmp(np->full_name, path) == 0) - break; - } - - return np; -} -EXPORT_SYMBOL(of_find_node_by_path); - -struct device_node *of_find_node_by_phandle(phandle handle) -{ - struct device_node *np; - - for (np = allnodes; np != 0; np = np->allnext) - if (np->node == handle) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_phandle); - -struct device_node *of_find_node_by_name(struct device_node *from, - const char *name) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != NULL; np = np->allnext) - if (np->name != NULL && strcmp(np->name, name) == 0) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_name); - -struct device_node *of_find_node_by_type(struct device_node *from, - const char *type) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) - if (np->type != 0 && strcmp(np->type, type) == 0) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_type); - -struct device_node *of_find_compatible_node(struct device_node *from, - const char *type, const char *compatible) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) { - if (type != NULL - && !(np->type != 0 && strcmp(np->type, type) == 0)) - continue; - if (of_device_is_compatible(np, compatible)) - break; - } - - return np; -} -EXPORT_SYMBOL(of_find_compatible_node); - -struct property *of_find_property(struct device_node *np, const char *name, - int *lenp) -{ - struct property *pp; - - for (pp = np->properties; pp != 0; pp = pp->next) { - if (strcmp(pp->name, name) == 0) { - if (lenp != 0) - *lenp = pp->length; - break; - } - } - return pp; -} -EXPORT_SYMBOL(of_find_property); - -/* - * Find a property with a given name for a given node - * and return the value. - */ -void *of_get_property(struct device_node *np, const char *name, int *lenp) -{ - struct property *pp = of_find_property(np,name,lenp); - return pp ? pp->value : NULL; -} -EXPORT_SYMBOL(of_get_property); - -int of_getintprop_default(struct device_node *np, const char *name, int def) -{ - struct property *prop; - int len; - - prop = of_find_property(np, name, &len); - if (!prop || len != 4) - return def; - - return *(int *) prop->value; -} -EXPORT_SYMBOL(of_getintprop_default); - -static unsigned int prom_early_allocated; - -static void * __init prom_early_alloc(unsigned long size) -{ - void *ret; - - ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); - if (ret != NULL) - memset(ret, 0, size); - - prom_early_allocated += size; - - return ret; -} - -static int is_root_node(const struct device_node *dp) -{ - if (!dp) - return 0; - - return (dp->parent == NULL); -} - -/* The following routines deal with the black magic of fully naming a - * node. - * - * Certain well known named nodes are just the simple name string. - * - * Actual devices have an address specifier appended to the base name - * string, like this "foo@addr". The "addr" can be in any number of - * formats, and the platform plus the type of the node determine the - * format and how it is constructed. - * - * For children of the ROOT node, the naming convention is fixed and - * determined by whether this is a sun4u or sun4v system. - * - * For children of other nodes, it is bus type specific. So - * we walk up the tree until we discover a "device_type" property - * we recognize and we go from there. - */ -static void __init sparc32_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom_registers *regs; - struct property *rprop; - - rprop = of_find_property(dp, "reg", NULL); - if (!rprop) - return; - - regs = rprop->value; - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - regs->which_io, regs->phys_addr); -} - -/* "name@slot,offset" */ -static void __init sbus_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom_registers *regs; - struct property *prop; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - regs->which_io, - regs->phys_addr); -} - -/* "name@devnum[,func]" */ -static void __init pci_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom_pci_registers *regs; - struct property *prop; - unsigned int devfn; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - devfn = (regs->phys_hi >> 8) & 0xff; - if (devfn & 0x07) { - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - devfn >> 3, - devfn & 0x07); - } else { - sprintf(tmp_buf, "%s@%x", - dp->name, - devfn >> 3); - } -} - -/* "name@addrhi,addrlo" */ -static void __init ebus_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom_registers *regs; - struct property *prop; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - regs->which_io, regs->phys_addr); -} - -static void __init __build_path_component(struct device_node *dp, char *tmp_buf) -{ - struct device_node *parent = dp->parent; - - if (parent != NULL) { - if (!strcmp(parent->type, "pci") || - !strcmp(parent->type, "pciex")) - return pci_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "sbus")) - return sbus_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "ebus")) - return ebus_path_component(dp, tmp_buf); - - /* "isa" is handled with platform naming */ - } - - /* Use platform naming convention. */ - return sparc32_path_component(dp, tmp_buf); -} - -static char * __init build_path_component(struct device_node *dp) -{ - char tmp_buf[64], *n; - - tmp_buf[0] = '\0'; - __build_path_component(dp, tmp_buf); - if (tmp_buf[0] == '\0') - strcpy(tmp_buf, dp->name); - - n = prom_early_alloc(strlen(tmp_buf) + 1); - strcpy(n, tmp_buf); - - return n; -} - -static char * __init build_full_name(struct device_node *dp) -{ - int len, ourlen, plen; - char *n; - - plen = strlen(dp->parent->full_name); - ourlen = strlen(dp->path_component_name); - len = ourlen + plen + 2; - - n = prom_early_alloc(len); - strcpy(n, dp->parent->full_name); - if (!is_root_node(dp->parent)) { - strcpy(n + plen, "/"); - plen++; - } - strcpy(n + plen, dp->path_component_name); - - return n; -} - -static struct property * __init build_one_prop(phandle node, char *prev) -{ - static struct property *tmp = NULL; - struct property *p; - int len; - - if (tmp) { - p = tmp; - memset(p, 0, sizeof(*p) + 32); - tmp = NULL; - } else - p = prom_early_alloc(sizeof(struct property) + 32); - - p->name = (char *) (p + 1); - if (prev == NULL) { - prom_firstprop(node, p->name); - } else { - prom_nextprop(node, prev, p->name); - } - if (strlen(p->name) == 0) { - tmp = p; - return NULL; - } - p->length = prom_getproplen(node, p->name); - if (p->length <= 0) { - p->length = 0; - } else { - p->value = prom_early_alloc(p->length); - len = prom_getproperty(node, p->name, p->value, p->length); - } - return p; -} - -static struct property * __init build_prop_list(phandle node) -{ - struct property *head, *tail; - - head = tail = build_one_prop(node, NULL); - while(tail) { - tail->next = build_one_prop(node, tail->name); - tail = tail->next; - } - - return head; -} - -static char * __init get_one_property(phandle node, char *name) -{ - char *buf = ""; - int len; - - len = prom_getproplen(node, name); - if (len > 0) { - buf = prom_early_alloc(len); - len = prom_getproperty(node, name, buf, len); - } - - return buf; -} - -static struct device_node * __init create_node(phandle node) -{ - struct device_node *dp; - - if (!node) - return NULL; - - dp = prom_early_alloc(sizeof(*dp)); - - kref_init(&dp->kref); - - dp->name = get_one_property(node, "name"); - dp->type = get_one_property(node, "device_type"); - dp->node = node; - - /* Build interrupts later... */ - - dp->properties = build_prop_list(node); - - return dp; -} - -static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp) -{ - struct device_node *dp; - - dp = create_node(node); - if (dp) { - *(*nextp) = dp; - *nextp = &dp->allnext; - - dp->parent = parent; - dp->path_component_name = build_path_component(dp); - dp->full_name = build_full_name(dp); - - dp->child = build_tree(dp, prom_getchild(node), nextp); - - dp->sibling = build_tree(parent, prom_getsibling(node), nextp); - } - - return dp; -} - -void __init prom_build_devicetree(void) -{ - struct device_node **nextp; - - allnodes = create_node(prom_root_node); - allnodes->path_component_name = ""; - allnodes->full_name = "/"; - - nextp = &allnodes->allnext; - allnodes->child = build_tree(allnodes, - prom_getchild(allnodes->node), - &nextp); - printk("PROM: Built device tree with %u bytes of memory.\n", - prom_early_allocated); -} diff --git a/trunk/arch/sparc/mm/init.c b/trunk/arch/sparc/mm/init.c index cfa7d3456634..898669732466 100644 --- a/trunk/arch/sparc/mm/init.c +++ b/trunk/arch/sparc/mm/init.c @@ -31,7 +31,6 @@ #include #include /* bug in asm-generic/tlb.h: check_pgt_cache */ #include -#include DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -350,7 +349,6 @@ void __init paging_init(void) protection_map[14] = PAGE_SHARED; protection_map[15] = PAGE_SHARED; btfixup(); - prom_build_devicetree(); device_scan(); } diff --git a/trunk/arch/sparc64/defconfig b/trunk/arch/sparc64/defconfig index b2f41147d0e4..9da75f89fe2c 100644 --- a/trunk/arch/sparc64/defconfig +++ b/trunk/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.17 -# Fri Jun 23 23:17:09 2006 +# Tue Jun 20 01:26:43 2006 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -286,7 +286,6 @@ CONFIG_STANDALONE=y # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set -# CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker @@ -435,7 +434,6 @@ CONFIG_ISCSI_TCP=m # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set @@ -735,7 +733,6 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_NFORCE2 is not set -# CONFIG_I2C_OCORES is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set @@ -779,7 +776,6 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_HWMON=y # CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -808,12 +804,10 @@ CONFIG_HWMON=y # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_VT8231 is not set # CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83791D is not set # CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set @@ -1024,7 +1018,6 @@ CONFIG_USB_DEVICEFS=y CONFIG_USB_EHCI_HCD=m # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set -# CONFIG_USB_EHCI_TT_NEWSCHED is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set @@ -1104,12 +1097,10 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set -# CONFIG_USB_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TEST is not set @@ -1207,7 +1198,6 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set diff --git a/trunk/arch/sparc64/kernel/Makefile b/trunk/arch/sparc64/kernel/Makefile index 86c9fe3f3e4a..6f6816488b04 100644 --- a/trunk/arch/sparc64/kernel/Makefile +++ b/trunk/arch/sparc64/kernel/Makefile @@ -12,7 +12,7 @@ obj-y := process.o setup.o cpu.o idprom.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ unaligned.o central.o pci.o starfire.o semaphore.o \ power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \ - visemul.o prom.o of_device.o + visemul.o obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \ pci_psycho.o pci_sabre.o pci_schizo.o \ diff --git a/trunk/arch/sparc64/kernel/auxio.c b/trunk/arch/sparc64/kernel/auxio.c index 2c42894b188f..8852c20c8d99 100644 --- a/trunk/arch/sparc64/kernel/auxio.c +++ b/trunk/arch/sparc64/kernel/auxio.c @@ -110,82 +110,43 @@ void auxio_set_lte(int on) } } -static void __devinit auxio_report_dev(struct device_node *dp) +void __init auxio_probe(void) { - printk(KERN_INFO "AUXIO: Found device at %s\n", - dp->full_name); -} - -static struct of_device_id auxio_match[] = { - { - .name = "auxio", - }, - {}, -}; - -MODULE_DEVICE_TABLE(of, auxio_match); - -#ifdef CONFIG_SBUS -static int __devinit auxio_sbus_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - - auxio_devtype = AUXIO_TYPE_SBUS; - auxio_register = sbus_ioremap(&sdev->resource[0], 0, - sdev->reg_addrs[0].reg_size, - "auxiliaryIO"); - if (!auxio_register) - return -ENODEV; - - auxio_report_dev(dev->node); - return 0; -} - -static struct of_platform_driver auxio_sbus_driver = { - .name = "auxio", - .match_table = auxio_match, - .probe = auxio_sbus_probe, -}; -#endif - + struct sbus_bus *sbus; + struct sbus_dev *sdev = NULL; + + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { + if(!strcmp(sdev->prom_name, "auxio")) + goto found_sdev; + } + } + +found_sdev: + if (sdev) { + auxio_devtype = AUXIO_TYPE_SBUS; + auxio_register = sbus_ioremap(&sdev->resource[0], 0, + sdev->reg_addrs[0].reg_size, + "auxiliaryIO"); + } #ifdef CONFIG_PCI -static int __devinit auxio_ebus_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct linux_ebus_device *edev = to_ebus_device(&dev->dev); - - auxio_devtype = AUXIO_TYPE_EBUS; - auxio_register = ioremap(edev->resource[0].start, sizeof(u32)); - if (!auxio_register) - return -ENODEV; - - auxio_report_dev(dev->node); - + else { + struct linux_ebus *ebus; + struct linux_ebus_device *edev = NULL; + + for_each_ebus(ebus) { + for_each_ebusdev(edev, ebus) { + if (!strcmp(edev->prom_name, "auxio")) + goto ebus_done; + } + } + ebus_done: + if (edev) { + auxio_devtype = AUXIO_TYPE_EBUS; + auxio_register = + ioremap(edev->resource[0].start, sizeof(u32)); + } + } auxio_set_led(AUXIO_LED_ON); - - return 0; -} - -static struct of_platform_driver auxio_ebus_driver = { - .name = "auxio", - .match_table = auxio_match, - .probe = auxio_ebus_probe, -}; #endif - -static int __init auxio_probe(void) -{ -#ifdef CONFIG_SBUS - of_register_driver(&auxio_sbus_driver, &sbus_bus_type); -#endif -#ifdef CONFIG_PCI - of_register_driver(&auxio_ebus_driver, &ebus_bus_type); -#endif - - return 0; } - -/* Must be after subsys_initcall() so that busses are probed. Must - * be before device_initcall() because things like the floppy driver - * need to use the AUXIO register. - */ -fs_initcall(auxio_probe); diff --git a/trunk/arch/sparc64/kernel/central.c b/trunk/arch/sparc64/kernel/central.c index b66336db00ee..3d184a784968 100644 --- a/trunk/arch/sparc64/kernel/central.c +++ b/trunk/arch/sparc64/kernel/central.c @@ -29,34 +29,28 @@ static void central_probe_failure(int line) prom_halt(); } -static void central_ranges_init(struct linux_central *central) +static void central_ranges_init(int cnode, struct linux_central *central) { - struct device_node *dp = central->prom_node; - void *pval; - int len; + int success; central->num_central_ranges = 0; - pval = of_get_property(dp, "ranges", &len); - if (pval) { - memcpy(central->central_ranges, pval, len); - central->num_central_ranges = - (len / sizeof(struct linux_prom_ranges)); - } + success = prom_getproperty(central->prom_node, "ranges", + (char *) central->central_ranges, + sizeof (central->central_ranges)); + if (success != -1) + central->num_central_ranges = (success/sizeof(struct linux_prom_ranges)); } -static void fhc_ranges_init(struct linux_fhc *fhc) +static void fhc_ranges_init(int fnode, struct linux_fhc *fhc) { - struct device_node *dp = fhc->prom_node; - void *pval; - int len; + int success; fhc->num_fhc_ranges = 0; - pval = of_get_property(dp, "ranges", &len); - if (pval) { - memcpy(fhc->fhc_ranges, pval, len); - fhc->num_fhc_ranges = - (len / sizeof(struct linux_prom_ranges)); - } + success = prom_getproperty(fhc->prom_node, "ranges", + (char *) fhc->fhc_ranges, + sizeof (fhc->fhc_ranges)); + if (success != -1) + fhc->num_fhc_ranges = (success/sizeof(struct linux_prom_ranges)); } /* Range application routines are exported to various drivers, @@ -118,10 +112,15 @@ static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r) static void probe_other_fhcs(void) { - struct device_node *dp; - struct linux_prom64_registers *fpregs; + struct linux_prom64_registers fpregs[6]; + char namebuf[128]; + int node; - for_each_node_by_name(dp, "fhc") { + node = prom_getchild(prom_root_node); + node = prom_searchsiblings(node, "fhc"); + if (node == 0) + central_probe_failure(__LINE__); + while (node) { struct linux_fhc *fhc; int board; u32 tmp; @@ -138,12 +137,14 @@ static void probe_other_fhcs(void) /* Toplevel FHCs have no parent. */ fhc->parent = NULL; - fhc->prom_node = dp; - fhc_ranges_init(fhc); + fhc->prom_node = node; + prom_getstring(node, "name", namebuf, sizeof(namebuf)); + strcpy(fhc->prom_name, namebuf); + fhc_ranges_init(node, fhc); /* Non-central FHC's have 64-bit OBP format registers. */ - fpregs = of_get_property(dp, "reg", NULL); - if (!fpregs) + if (prom_getproperty(node, "reg", + (char *)&fpregs[0], sizeof(fpregs)) == -1) central_probe_failure(__LINE__); /* Only central FHC needs special ranges applied. */ @@ -154,7 +155,7 @@ static void probe_other_fhcs(void) fhc->fhc_regs.uregs = fpregs[4].phys_addr; fhc->fhc_regs.tregs = fpregs[5].phys_addr; - board = of_getintprop_default(dp, "board#", -1); + board = prom_getintdefault(node, "board#", -1); fhc->board = board; tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL); @@ -178,33 +179,33 @@ static void probe_other_fhcs(void) tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); tmp |= FHC_CONTROL_IXIST; upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); + + /* Look for the next FHC. */ + node = prom_getsibling(node); + if (node == 0) + break; + node = prom_searchsiblings(node, "fhc"); + if (node == 0) + break; } } static void probe_clock_board(struct linux_central *central, struct linux_fhc *fhc, - struct device_node *fp) + int cnode, int fnode) { - struct device_node *dp; - struct linux_prom_registers cregs[3], *pr; - int nslots, tmp, nregs; + struct linux_prom_registers cregs[3]; + int clknode, nslots, tmp, nregs; - dp = fp->child; - while (dp) { - if (!strcmp(dp->name, "clock-board")) - break; - dp = dp->sibling; - } - if (!dp) + clknode = prom_searchsiblings(prom_getchild(fnode), "clock-board"); + if (clknode == 0 || clknode == -1) central_probe_failure(__LINE__); - pr = of_get_property(dp, "reg", &nregs); - if (!pr) + nregs = prom_getproperty(clknode, "reg", (char *)&cregs[0], sizeof(cregs)); + if (nregs == -1) central_probe_failure(__LINE__); - memcpy(cregs, pr, nregs); nregs /= sizeof(struct linux_prom_registers); - apply_fhc_ranges(fhc, &cregs[0], nregs); apply_central_ranges(central, &cregs[0], nregs); central->cfreg = prom_reg_to_paddr(&cregs[0]); @@ -295,13 +296,13 @@ static void init_all_fhc_hw(void) void central_probe(void) { - struct linux_prom_registers fpregs[6], *pr; + struct linux_prom_registers fpregs[6]; struct linux_fhc *fhc; - struct device_node *dp, *fp; - int err; + char namebuf[128]; + int cnode, fnode, err; - dp = of_find_node_by_name(NULL, "central"); - if (!dp) { + cnode = prom_finddevice("/central"); + if (cnode == 0 || cnode == -1) { if (this_is_starfire) starfire_cpu_setup(); return; @@ -320,31 +321,31 @@ void central_probe(void) /* First init central. */ central_bus->child = fhc; - central_bus->prom_node = dp; - central_ranges_init(central_bus); + central_bus->prom_node = cnode; + + prom_getstring(cnode, "name", namebuf, sizeof(namebuf)); + strcpy(central_bus->prom_name, namebuf); + + central_ranges_init(cnode, central_bus); /* And then central's FHC. */ fhc->next = fhc_list; fhc_list = fhc; fhc->parent = central_bus; - fp = dp->child; - while (fp) { - if (!strcmp(fp->name, "fhc")) - break; - fp = fp->sibling; - } - if (!fp) + fnode = prom_searchsiblings(prom_getchild(cnode), "fhc"); + if (fnode == 0 || fnode == -1) central_probe_failure(__LINE__); - fhc->prom_node = fp; - fhc_ranges_init(fhc); + fhc->prom_node = fnode; + prom_getstring(fnode, "name", namebuf, sizeof(namebuf)); + strcpy(fhc->prom_name, namebuf); + + fhc_ranges_init(fnode, fhc); /* Now, map in FHC register set. */ - pr = of_get_property(fp, "reg", NULL); - if (!pr) + if (prom_getproperty(fnode, "reg", (char *)&fpregs[0], sizeof(fpregs)) == -1) central_probe_failure(__LINE__); - memcpy(fpregs, pr, sizeof(fpregs)); apply_central_ranges(central_bus, &fpregs[0], 6); @@ -365,7 +366,7 @@ void central_probe(void) fhc->jtag_master = 0; /* Attach the clock board registers for CENTRAL. */ - probe_clock_board(central_bus, fhc, fp); + probe_clock_board(central_bus, fhc, cnode, fnode); err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n", diff --git a/trunk/arch/sparc64/kernel/chmc.c b/trunk/arch/sparc64/kernel/chmc.c index 259f37e516f5..97cf912f0853 100644 --- a/trunk/arch/sparc64/kernel/chmc.c +++ b/trunk/arch/sparc64/kernel/chmc.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #define CHMCTRL_NDGRPS 2 @@ -68,6 +67,7 @@ struct bank_info { struct mctrl_info { struct list_head list; int portid; + int index; struct obp_mem_layout layout_prop; int layout_size; @@ -339,13 +339,12 @@ static void fetch_decode_regs(struct mctrl_info *mp) read_mcreg(mp, CHMCTRL_DECODE4)); } -static int init_one_mctrl(struct device_node *dp) +static int init_one_mctrl(int node, int index) { struct mctrl_info *mp = kmalloc(sizeof(*mp), GFP_KERNEL); - int portid = of_getintprop_default(dp, "portid", -1); - struct linux_prom64_registers *regs; - void *pval; - int len; + int portid = prom_getintdefault(node, "portid", -1); + struct linux_prom64_registers p_reg_prop; + int t; if (!mp) return -1; @@ -354,21 +353,24 @@ static int init_one_mctrl(struct device_node *dp) goto fail; mp->portid = portid; - pval = of_get_property(dp, "memory-layout", &len); - mp->layout_size = len; - if (!pval) + mp->layout_size = prom_getproplen(node, "memory-layout"); + if (mp->layout_size < 0) mp->layout_size = 0; - else { - if (mp->layout_size > sizeof(mp->layout_prop)) - goto fail; - memcpy(&mp->layout_prop, pval, len); - } + if (mp->layout_size > sizeof(mp->layout_prop)) + goto fail; - regs = of_get_property(dp, "reg", NULL); - if (!regs || regs->reg_size != 0x48) + if (mp->layout_size > 0) + prom_getproperty(node, "memory-layout", + (char *) &mp->layout_prop, + mp->layout_size); + + t = prom_getproperty(node, "reg", + (char *) &p_reg_prop, + sizeof(p_reg_prop)); + if (t < 0 || p_reg_prop.reg_size != 0x48) goto fail; - mp->regs = ioremap(regs->phys_addr, regs->reg_size); + mp->regs = ioremap(p_reg_prop.phys_addr, p_reg_prop.reg_size); if (mp->regs == NULL) goto fail; @@ -382,11 +384,13 @@ static int init_one_mctrl(struct device_node *dp) fetch_decode_regs(mp); + mp->index = index; + list_add(&mp->list, &mctrl_list); /* Report the device. */ - printk(KERN_INFO "%s: US3 memory controller at %p [%s]\n", - dp->full_name, + printk(KERN_INFO "chmc%d: US3 memory controller at %p [%s]\n", + mp->index, mp->regs, (mp->layout_size ? "ACTIVE" : "INACTIVE")); return 0; @@ -400,19 +404,34 @@ static int init_one_mctrl(struct device_node *dp) return -1; } +static int __init probe_for_string(char *name, int index) +{ + int node = prom_getchild(prom_root_node); + + while ((node = prom_searchsiblings(node, name)) != 0) { + int ret = init_one_mctrl(node, index); + + if (!ret) + index++; + + node = prom_getsibling(node); + if (!node) + break; + } + + return index; +} + static int __init chmc_init(void) { - struct device_node *dp; + int index; /* This driver is only for cheetah platforms. */ if (tlb_type != cheetah && tlb_type != cheetah_plus) return -ENODEV; - for_each_node_by_name(dp, "memory-controller") - init_one_mctrl(dp); - - for_each_node_by_name(dp, "mc-us3") - init_one_mctrl(dp); + index = probe_for_string("memory-controller", 0); + index = probe_for_string("mc-us3", index); return 0; } diff --git a/trunk/arch/sparc64/kernel/devices.c b/trunk/arch/sparc64/kernel/devices.c index 389301c95cb2..0dd95ae50e12 100644 --- a/trunk/arch/sparc64/kernel/devices.c +++ b/trunk/arch/sparc64/kernel/devices.c @@ -33,7 +33,7 @@ extern void cpu_probe(void); extern void central_probe(void); u32 sun4v_vdev_devhandle; -struct device_node *sun4v_vdev_root; +int sun4v_vdev_root; struct vdev_intmap { unsigned int phys; @@ -50,68 +50,102 @@ struct vdev_intmask { static struct vdev_intmap *vdev_intmap; static int vdev_num_intmap; -static struct vdev_intmask *vdev_intmask; +static struct vdev_intmask vdev_intmask; static void __init sun4v_virtual_device_probe(void) { - struct linux_prom64_registers *regs; - struct property *prop; - struct device_node *dp; - int sz; + struct linux_prom64_registers regs; + struct vdev_intmap *ip; + int node, sz, err; if (tlb_type != hypervisor) return; - dp = of_find_node_by_name(NULL, "virtual-devices"); - if (!dp) { + node = prom_getchild(prom_root_node); + node = prom_searchsiblings(node, "virtual-devices"); + if (!node) { prom_printf("SUN4V: Fatal error, no virtual-devices node.\n"); prom_halt(); } - sun4v_vdev_root = dp; + sun4v_vdev_root = node; - prop = of_find_property(dp, "reg", NULL); - regs = prop->value; - sun4v_vdev_devhandle = (regs[0].phys_addr >> 32UL) & 0x0fffffff; + prom_getproperty(node, "reg", (char *)®s, sizeof(regs)); + sun4v_vdev_devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff; - prop = of_find_property(dp, "interrupt-map", &sz); - vdev_intmap = prop->value; - vdev_num_intmap = sz / sizeof(struct vdev_intmap); + sz = prom_getproplen(node, "interrupt-map"); + if (sz <= 0) { + prom_printf("SUN4V: Error, no vdev interrupt-map.\n"); + prom_halt(); + } + + if ((sz % sizeof(*ip)) != 0) { + prom_printf("SUN4V: Bogus interrupt-map property size %d\n", + sz); + prom_halt(); + } + + vdev_intmap = ip = alloc_bootmem_low_pages(sz); + if (!vdev_intmap) { + prom_printf("SUN4V: Error, cannot allocate vdev_intmap.\n"); + prom_halt(); + } + + err = prom_getproperty(node, "interrupt-map", (char *) ip, sz); + if (err == -1) { + prom_printf("SUN4V: Fatal error, no vdev interrupt-map.\n"); + prom_halt(); + } + if (err != sz) { + prom_printf("SUN4V: Inconsistent interrupt-map size, " + "proplen(%d) vs getprop(%d).\n", sz,err); + prom_halt(); + } + + vdev_num_intmap = err / sizeof(*ip); - prop = of_find_property(dp, "interrupt-map-mask", NULL); - vdev_intmask = prop->value; + err = prom_getproperty(node, "interrupt-map-mask", + (char *) &vdev_intmask, + sizeof(vdev_intmask)); + if (err <= 0) { + prom_printf("SUN4V: Fatal error, no vdev " + "interrupt-map-mask.\n"); + prom_halt(); + } + if (err % sizeof(vdev_intmask)) { + prom_printf("SUN4V: Bogus interrupt-map-mask " + "property size %d\n", err); + prom_halt(); + } - printk("%s: Virtual Device Bus devhandle[%x]\n", - dp->full_name, sun4v_vdev_devhandle); + printk("SUN4V: virtual-devices devhandle[%x]\n", + sun4v_vdev_devhandle); } -unsigned int sun4v_vdev_device_interrupt(struct device_node *dev_node) +unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node) { - struct property *prop; unsigned int irq, reg; - int i; + int err, i; - prop = of_find_property(dev_node, "interrupts", NULL); - if (!prop) { + err = prom_getproperty(dev_node, "interrupts", + (char *) &irq, sizeof(irq)); + if (err <= 0) { printk("VDEV: Cannot get \"interrupts\" " - "property for OBP node %s\n", - dev_node->full_name); + "property for OBP node %x\n", dev_node); return 0; } - irq = *(unsigned int *) prop->value; - prop = of_find_property(dev_node, "reg", NULL); - if (!prop) { + err = prom_getproperty(dev_node, "reg", + (char *) ®, sizeof(reg)); + if (err <= 0) { printk("VDEV: Cannot get \"reg\" " - "property for OBP node %s\n", - dev_node->full_name); + "property for OBP node %x\n", dev_node); return 0; } - reg = *(unsigned int *) prop->value; for (i = 0; i < vdev_num_intmap; i++) { - if (vdev_intmap[i].phys == (reg & vdev_intmask->phys) && - vdev_intmap[i].irq == (irq & vdev_intmask->interrupt)) { + if (vdev_intmap[i].phys == (reg & vdev_intmask.phys) && + vdev_intmap[i].irq == (irq & vdev_intmask.interrupt)) { irq = vdev_intmap[i].cinterrupt; break; } @@ -119,7 +153,7 @@ unsigned int sun4v_vdev_device_interrupt(struct device_node *dev_node) if (i == vdev_num_intmap) { printk("VDEV: No matching interrupt map entry " - "for OBP node %s\n", dev_node->full_name); + "for OBP node %x\n", dev_node); return 0; } @@ -133,44 +167,38 @@ static const char *cpu_mid_prop(void) return "portid"; } -static int get_cpu_mid(struct device_node *dp) +static int get_cpu_mid(int prom_node) { - struct property *prop; - if (tlb_type == hypervisor) { - struct linux_prom64_registers *reg; - int len; + struct linux_prom64_registers reg; - prop = of_find_property(dp, "cpuid", &len); - if (prop && len == 4) - return *(int *) prop->value; + if (prom_getproplen(prom_node, "cpuid") == 4) + return prom_getintdefault(prom_node, "cpuid", 0); - prop = of_find_property(dp, "reg", NULL); - reg = prop->value; - return (reg[0].phys_addr >> 32) & 0x0fffffffUL; + prom_getproperty(prom_node, "reg", (char *) ®, sizeof(reg)); + return (reg.phys_addr >> 32) & 0x0fffffffUL; } else { const char *prop_name = cpu_mid_prop(); - prop = of_find_property(dp, prop_name, NULL); - if (prop) - return *(int *) prop->value; - return 0; + return prom_getintdefault(prom_node, prop_name, 0); } } -static int check_cpu_node(struct device_node *dp, int *cur_inst, - int (*compare)(struct device_node *, int, void *), - void *compare_arg, - struct device_node **dev_node, int *mid) +static int check_cpu_node(int nd, int *cur_inst, + int (*compare)(int, int, void *), void *compare_arg, + int *prom_node, int *mid) { - if (strcmp(dp->type, "cpu")) + char node_str[128]; + + prom_getstring(nd, "device_type", node_str, sizeof(node_str)); + if (strcmp(node_str, "cpu")) return -ENODEV; - if (!compare(dp, *cur_inst, compare_arg)) { - if (dev_node) - *dev_node = dp; + if (!compare(nd, *cur_inst, compare_arg)) { + if (prom_node) + *prom_node = nd; if (mid) - *mid = get_cpu_mid(dp); + *mid = get_cpu_mid(nd); return 0; } @@ -179,18 +207,25 @@ static int check_cpu_node(struct device_node *dp, int *cur_inst, return -ENODEV; } -static int __cpu_find_by(int (*compare)(struct device_node *, int, void *), - void *compare_arg, - struct device_node **dev_node, int *mid) +static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg, + int *prom_node, int *mid) { - struct device_node *dp; - int cur_inst; + int nd, cur_inst, err; + nd = prom_root_node; cur_inst = 0; - for_each_node_by_type(dp, "cpu") { - int err = check_cpu_node(dp, &cur_inst, - compare, compare_arg, - dev_node, mid); + + err = check_cpu_node(nd, &cur_inst, + compare, compare_arg, + prom_node, mid); + if (err == 0) + return 0; + + nd = prom_getchild(nd); + while ((nd = prom_getsibling(nd)) != 0) { + err = check_cpu_node(nd, &cur_inst, + compare, compare_arg, + prom_node, mid); if (err == 0) return 0; } @@ -198,7 +233,7 @@ static int __cpu_find_by(int (*compare)(struct device_node *, int, void *), return -ENODEV; } -static int cpu_instance_compare(struct device_node *dp, int instance, void *_arg) +static int cpu_instance_compare(int nd, int instance, void *_arg) { int desired_instance = (int) (long) _arg; @@ -207,27 +242,27 @@ static int cpu_instance_compare(struct device_node *dp, int instance, void *_arg return -ENODEV; } -int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid) +int cpu_find_by_instance(int instance, int *prom_node, int *mid) { return __cpu_find_by(cpu_instance_compare, (void *)(long)instance, - dev_node, mid); + prom_node, mid); } -static int cpu_mid_compare(struct device_node *dp, int instance, void *_arg) +static int cpu_mid_compare(int nd, int instance, void *_arg) { int desired_mid = (int) (long) _arg; int this_mid; - this_mid = get_cpu_mid(dp); + this_mid = get_cpu_mid(nd); if (this_mid == desired_mid) return 0; return -ENODEV; } -int cpu_find_by_mid(int mid, struct device_node **dev_node) +int cpu_find_by_mid(int mid, int *prom_node) { return __cpu_find_by(cpu_mid_compare, (void *)(long)mid, - dev_node, NULL); + prom_node, NULL); } void __init device_scan(void) @@ -239,47 +274,50 @@ void __init device_scan(void) #ifndef CONFIG_SMP { - struct device_node *dp; - int err, def; + int err, cpu_node, def; - err = cpu_find_by_instance(0, &dp, NULL); + err = cpu_find_by_instance(0, &cpu_node, NULL); if (err) { prom_printf("No cpu nodes, cannot continue\n"); prom_halt(); } - cpu_data(0).clock_tick = - of_getintprop_default(dp, "clock-frequency", 0); + cpu_data(0).clock_tick = prom_getintdefault(cpu_node, + "clock-frequency", + 0); def = ((tlb_type == hypervisor) ? (8 * 1024) : (16 * 1024)); - cpu_data(0).dcache_size = of_getintprop_default(dp, - "dcache-size", - def); + cpu_data(0).dcache_size = prom_getintdefault(cpu_node, + "dcache-size", + def); def = 32; cpu_data(0).dcache_line_size = - of_getintprop_default(dp, "dcache-line-size", def); + prom_getintdefault(cpu_node, "dcache-line-size", + def); def = 16 * 1024; - cpu_data(0).icache_size = of_getintprop_default(dp, - "icache-size", - def); + cpu_data(0).icache_size = prom_getintdefault(cpu_node, + "icache-size", + def); def = 32; cpu_data(0).icache_line_size = - of_getintprop_default(dp, "icache-line-size", def); + prom_getintdefault(cpu_node, "icache-line-size", + def); def = ((tlb_type == hypervisor) ? (3 * 1024 * 1024) : (4 * 1024 * 1024)); - cpu_data(0).ecache_size = of_getintprop_default(dp, - "ecache-size", - def); + cpu_data(0).ecache_size = prom_getintdefault(cpu_node, + "ecache-size", + def); def = 64; cpu_data(0).ecache_line_size = - of_getintprop_default(dp, "ecache-line-size", def); + prom_getintdefault(cpu_node, "ecache-line-size", + def); printk("CPU[0]: Caches " "D[sz(%d):line_sz(%d)] " "I[sz(%d):line_sz(%d)] " diff --git a/trunk/arch/sparc64/kernel/ebus.c b/trunk/arch/sparc64/kernel/ebus.c index 98e0a8cbeecd..c69504aa638f 100644 --- a/trunk/arch/sparc64/kernel/ebus.c +++ b/trunk/arch/sparc64/kernel/ebus.c @@ -269,6 +269,10 @@ EXPORT_SYMBOL(ebus_dma_enable); struct linux_ebus *ebus_chain = NULL; +#ifdef CONFIG_SUN_AUXIO +extern void auxio_probe(void); +#endif + static inline void *ebus_alloc(size_t size) { void *mem; @@ -279,55 +283,77 @@ static inline void *ebus_alloc(size_t size) return mem; } +static void __init ebus_ranges_init(struct linux_ebus *ebus) +{ + int success; + + ebus->num_ebus_ranges = 0; + success = prom_getproperty(ebus->prom_node, "ranges", + (char *)ebus->ebus_ranges, + sizeof(ebus->ebus_ranges)); + if (success != -1) + ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges)); +} + +static void __init ebus_intmap_init(struct linux_ebus *ebus) +{ + int success; + + ebus->num_ebus_intmap = 0; + success = prom_getproperty(ebus->prom_node, "interrupt-map", + (char *)ebus->ebus_intmap, + sizeof(ebus->ebus_intmap)); + if (success == -1) + return; + + ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap)); + + success = prom_getproperty(ebus->prom_node, "interrupt-map-mask", + (char *)&ebus->ebus_intmask, + sizeof(ebus->ebus_intmask)); + if (success == -1) { + prom_printf("%s: can't get interrupt-map-mask\n", __FUNCTION__); + prom_halt(); + } +} + int __init ebus_intmap_match(struct linux_ebus *ebus, struct linux_prom_registers *reg, int *interrupt) { - struct linux_prom_ebus_intmap *imap; - struct linux_prom_ebus_intmask *imask; unsigned int hi, lo, irq; - int i, len, n_imap; - - imap = of_get_property(ebus->prom_node, "interrupt-map", &len); - if (!imap) - return 0; - n_imap = len / sizeof(imap[0]); + int i; - imask = of_get_property(ebus->prom_node, "interrupt-map-mask", NULL); - if (!imask) + if (!ebus->num_ebus_intmap) return 0; - hi = reg->which_io & imask->phys_hi; - lo = reg->phys_addr & imask->phys_lo; - irq = *interrupt & imask->interrupt; - for (i = 0; i < n_imap; i++) { - if ((imap[i].phys_hi == hi) && - (imap[i].phys_lo == lo) && - (imap[i].interrupt == irq)) { - *interrupt = imap[i].cinterrupt; + hi = reg->which_io & ebus->ebus_intmask.phys_hi; + lo = reg->phys_addr & ebus->ebus_intmask.phys_lo; + irq = *interrupt & ebus->ebus_intmask.interrupt; + for (i = 0; i < ebus->num_ebus_intmap; i++) { + if ((ebus->ebus_intmap[i].phys_hi == hi) && + (ebus->ebus_intmap[i].phys_lo == lo) && + (ebus->ebus_intmap[i].interrupt == irq)) { + *interrupt = ebus->ebus_intmap[i].cinterrupt; return 0; } } return -1; } -void __init fill_ebus_child(struct device_node *dp, - struct linux_prom_registers *preg, - struct linux_ebus_child *dev, - int non_standard_regs) +void __init fill_ebus_child(int node, struct linux_prom_registers *preg, + struct linux_ebus_child *dev, int non_standard_regs) { - int *regs; - int *irqs; + int regs[PROMREG_MAX]; + int irqs[PROMREG_MAX]; int i, len; - dev->prom_node = dp; - printk(" (%s)", dp->name); + dev->prom_node = node; + prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name)); + printk(" (%s)", dev->prom_name); - regs = of_get_property(dp, "reg", &len); - if (!regs) - dev->num_addrs = 0; - else - dev->num_addrs = len / sizeof(regs[0]); + len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); + dev->num_addrs = len / sizeof(regs[0]); if (non_standard_regs) { /* This is to handle reg properties which are not @@ -344,21 +370,21 @@ void __init fill_ebus_child(struct device_node *dp, int rnum = regs[i]; if (rnum >= dev->parent->num_addrs) { prom_printf("UGH: property for %s was %d, need < %d\n", - dp->name, len, dev->parent->num_addrs); - prom_halt(); + dev->prom_name, len, dev->parent->num_addrs); + panic(__FUNCTION__); } dev->resource[i].start = dev->parent->resource[i].start; dev->resource[i].end = dev->parent->resource[i].end; dev->resource[i].flags = IORESOURCE_MEM; - dev->resource[i].name = dp->name; + dev->resource[i].name = dev->prom_name; } } for (i = 0; i < PROMINTR_MAX; i++) dev->irqs[i] = PCI_IRQ_NONE; - irqs = of_get_property(dp, "interrupts", &len); - if (!irqs) { + len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); + if ((len == -1) || (len == 0)) { dev->num_irqs = 0; /* * Oh, well, some PROMs don't export interrupts @@ -366,8 +392,8 @@ void __init fill_ebus_child(struct device_node *dp, * * Be smart about PS/2 keyboard and mouse. */ - if (!strcmp(dev->parent->prom_node->name, "8042")) { - if (!strcmp(dev->prom_node->name, "kb_ps2")) { + if (!strcmp(dev->parent->prom_name, "8042")) { + if (!strcmp(dev->prom_name, "kb_ps2")) { dev->num_irqs = 1; dev->irqs[0] = dev->parent->irqs[0]; } else { @@ -397,32 +423,32 @@ void __init fill_ebus_child(struct device_node *dp, static int __init child_regs_nonstandard(struct linux_ebus_device *dev) { - if (!strcmp(dev->prom_node->name, "i2c") || - !strcmp(dev->prom_node->name, "SUNW,lombus")) + if (!strcmp(dev->prom_name, "i2c") || + !strcmp(dev->prom_name, "SUNW,lombus")) return 1; return 0; } -void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) +void __init fill_ebus_device(int node, struct linux_ebus_device *dev) { - struct linux_prom_registers *regs; + struct linux_prom_registers regs[PROMREG_MAX]; struct linux_ebus_child *child; - int *irqs; + int irqs[PROMINTR_MAX]; int i, n, len; - dev->prom_node = dp; - - printk(" [%s", dp->name); + dev->prom_node = node; + prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name)); + printk(" [%s", dev->prom_name); - regs = of_get_property(dp, "reg", &len); - if (!regs) { + len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); + if (len == -1) { dev->num_addrs = 0; goto probe_interrupts; } if (len % sizeof(struct linux_prom_registers)) { prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", - dev->prom_node->name, len, + dev->prom_name, len, (int)sizeof(struct linux_prom_registers)); prom_halt(); } @@ -440,7 +466,7 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d dev->resource[i].end = (dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL); dev->resource[i].flags = IORESOURCE_MEM; - dev->resource[i].name = dev->prom_node->name; + dev->resource[i].name = dev->prom_name; request_resource(&dev->bus->self->resource[n], &dev->resource[i]); } @@ -449,8 +475,8 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d for (i = 0; i < PROMINTR_MAX; i++) dev->irqs[i] = PCI_IRQ_NONE; - irqs = of_get_property(dp, "interrupts", &len); - if (!irqs) { + len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); + if ((len == -1) || (len == 0)) { dev->num_irqs = 0; } else { dev->num_irqs = len / sizeof(irqs[0]); @@ -471,18 +497,7 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d } } - dev->ofdev.node = dp; - dev->ofdev.dev.parent = &dev->bus->ofdev.dev; - dev->ofdev.dev.bus = &ebus_bus_type; - strcpy(dev->ofdev.dev.bus_id, dp->path_component_name); - - /* Register with core */ - if (of_device_register(&dev->ofdev) != 0) - printk(KERN_DEBUG "ebus: device registration error for %s!\n", - dev->ofdev.dev.bus_id); - - dp = dp->child; - if (dp) { + if ((node = prom_getchild(node))) { printk(" ->"); dev->children = ebus_alloc(sizeof(struct linux_ebus_child)); @@ -490,18 +505,18 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d child->next = NULL; child->parent = dev; child->bus = dev->bus; - fill_ebus_child(dp, regs, child, - child_regs_nonstandard(dev)); + fill_ebus_child(node, ®s[0], + child, child_regs_nonstandard(dev)); - while ((dp = dp->sibling) != NULL) { + while ((node = prom_getsibling(node)) != 0) { child->next = ebus_alloc(sizeof(struct linux_ebus_child)); child = child->next; child->next = NULL; child->parent = dev; child->bus = dev->bus; - fill_ebus_child(dp, regs, child, - child_regs_nonstandard(dev)); + fill_ebus_child(node, ®s[0], + child, child_regs_nonstandard(dev)); } } printk("]"); @@ -528,8 +543,7 @@ void __init ebus_init(void) struct linux_ebus *ebus; struct pci_dev *pdev; struct pcidev_cookie *cookie; - struct device_node *dp; - int is_rio; + int nd, ebusnd, is_rio; int num_ebus = 0; pdev = find_next_ebus(NULL, &is_rio); @@ -539,22 +553,20 @@ void __init ebus_init(void) } cookie = pdev->sysdata; - dp = cookie->prom_node; + ebusnd = cookie->prom_node; ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); ebus->next = NULL; ebus->is_rio = is_rio; - while (dp) { - struct device_node *child; - + while (ebusnd) { /* SUNW,pci-qfe uses four empty ebuses on it. I think we should not consider them here, as they have half of the properties this code expects and once we do PCI hot-plug, we'd have to tweak with the ebus_chain in the runtime after initialization. -jj */ - if (!dp->child) { + if (!prom_getchild (ebusnd)) { pdev = find_next_ebus(pdev, &is_rio); if (!pdev) { if (ebus == ebus_chain) { @@ -566,29 +578,22 @@ void __init ebus_init(void) } ebus->is_rio = is_rio; cookie = pdev->sysdata; - dp = cookie->prom_node; + ebusnd = cookie->prom_node; continue; } printk("ebus%d:", num_ebus); + prom_getstring(ebusnd, "name", ebus->prom_name, sizeof(ebus->prom_name)); ebus->index = num_ebus; - ebus->prom_node = dp; + ebus->prom_node = ebusnd; ebus->self = pdev; ebus->parent = pbm = cookie->pbm; - ebus->ofdev.node = dp; - ebus->ofdev.dev.parent = &pdev->dev; - ebus->ofdev.dev.bus = &ebus_bus_type; - strcpy(ebus->ofdev.dev.bus_id, dp->path_component_name); + ebus_ranges_init(ebus); + ebus_intmap_init(ebus); - /* Register with core */ - if (of_device_register(&ebus->ofdev) != 0) - printk(KERN_DEBUG "ebus: device registration error for %s!\n", - ebus->ofdev.dev.bus_id); - - - child = dp->child; - if (!child) + nd = prom_getchild(ebusnd); + if (!nd) goto next_ebus; ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device)); @@ -597,16 +602,16 @@ void __init ebus_init(void) dev->next = NULL; dev->children = NULL; dev->bus = ebus; - fill_ebus_device(child, dev); + fill_ebus_device(nd, dev); - while ((child = child->sibling) != NULL) { + while ((nd = prom_getsibling(nd)) != 0) { dev->next = ebus_alloc(sizeof(struct linux_ebus_device)); dev = dev->next; dev->next = NULL; dev->children = NULL; dev->bus = ebus; - fill_ebus_device(child, dev); + fill_ebus_device(nd, dev); } next_ebus: @@ -617,7 +622,7 @@ void __init ebus_init(void) break; cookie = pdev->sysdata; - dp = cookie->prom_node; + ebusnd = cookie->prom_node; ebus->next = ebus_alloc(sizeof(struct linux_ebus)); ebus = ebus->next; @@ -626,4 +631,8 @@ void __init ebus_init(void) ++num_ebus; } pci_dev_put(pdev); /* XXX for the case, when ebusnd is 0, is it OK? */ + +#ifdef CONFIG_SUN_AUXIO + auxio_probe(); +#endif } diff --git a/trunk/arch/sparc64/kernel/irq.c b/trunk/arch/sparc64/kernel/irq.c index 31e0fbb0d82c..a8c9dc8d1958 100644 --- a/trunk/arch/sparc64/kernel/irq.c +++ b/trunk/arch/sparc64/kernel/irq.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -636,29 +635,23 @@ static u64 prom_limit0, prom_limit1; static void map_prom_timers(void) { - struct device_node *dp; - unsigned int *addr; + unsigned int addr[3]; + int tnode, err; /* PROM timer node hangs out in the top level of device siblings... */ - dp = of_find_node_by_path("/"); - dp = dp->child; - while (dp) { - if (!strcmp(dp->name, "counter-timer")) - break; - dp = dp->sibling; - } + tnode = prom_finddevice("/counter-timer"); /* Assume if node is not present, PROM uses different tick mechanism * which we should not care about. */ - if (!dp) { + if (tnode == 0 || tnode == -1) { prom_timers = (struct sun5_timer *) 0; return; } /* If PROM is really using this, it must be mapped by him. */ - addr = of_get_property(dp, "address", NULL); - if (!addr) { + err = prom_getproperty(tnode, "address", (char *)addr, sizeof(addr)); + if (err == -1) { prom_printf("PROM does not have timer mapped, trying to continue.\n"); prom_timers = (struct sun5_timer *) 0; return; diff --git a/trunk/arch/sparc64/kernel/isa.c b/trunk/arch/sparc64/kernel/isa.c index 6f16dee280a8..30862abee611 100644 --- a/trunk/arch/sparc64/kernel/isa.c +++ b/trunk/arch/sparc64/kernel/isa.c @@ -15,19 +15,23 @@ static void __init fatal_err(const char *reason) static void __init report_dev(struct sparc_isa_device *isa_dev, int child) { if (child) - printk(" (%s)", isa_dev->prom_node->name); + printk(" (%s)", isa_dev->prom_name); else - printk(" [%s", isa_dev->prom_node->name); + printk(" [%s", isa_dev->prom_name); } -static struct linux_prom_registers * __init -isa_dev_get_resource(struct sparc_isa_device *isa_dev) +static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev, + struct linux_prom_registers *pregs, + int pregs_size) { - struct linux_prom_registers *pregs; unsigned long base, len; int prop_len; - pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len); + prop_len = prom_getproperty(isa_dev->prom_node, "reg", + (char *) pregs, pregs_size); + + if (prop_len <= 0) + return; /* Only the first one is interesting. */ len = pregs[0].reg_size; @@ -38,12 +42,10 @@ isa_dev_get_resource(struct sparc_isa_device *isa_dev) isa_dev->resource.start = base; isa_dev->resource.end = (base + len - 1UL); isa_dev->resource.flags = IORESOURCE_IO; - isa_dev->resource.name = isa_dev->prom_node->name; + isa_dev->resource.name = isa_dev->prom_name; request_resource(&isa_dev->bus->parent->io_space, &isa_dev->resource); - - return pregs; } /* I can't believe they didn't put a real INO in the isa device @@ -72,30 +74,19 @@ static struct { static int __init isa_dev_get_irq_using_imap(struct sparc_isa_device *isa_dev, struct sparc_isa_bridge *isa_br, int *interrupt, - struct linux_prom_registers *reg) + struct linux_prom_registers *pregs) { - struct linux_prom_ebus_intmap *imap; - struct linux_prom_ebus_intmap *imask; unsigned int hi, lo, irq; - int i, len, n_imap; - - imap = of_get_property(isa_br->prom_node, "interrupt-map", &len); - if (!imap) - return 0; - n_imap = len / sizeof(imap[0]); - - imask = of_get_property(isa_br->prom_node, "interrupt-map-mask", NULL); - if (!imask) - return 0; - - hi = reg->which_io & imask->phys_hi; - lo = reg->phys_addr & imask->phys_lo; - irq = *interrupt & imask->interrupt; - for (i = 0; i < n_imap; i++) { - if ((imap[i].phys_hi == hi) && - (imap[i].phys_lo == lo) && - (imap[i].interrupt == irq)) { - *interrupt = imap[i].cinterrupt; + int i; + + hi = pregs->which_io & isa_br->isa_intmask.phys_hi; + lo = pregs->phys_addr & isa_br->isa_intmask.phys_lo; + irq = *interrupt & isa_br->isa_intmask.interrupt; + for (i = 0; i < isa_br->num_isa_intmap; i++) { + if ((isa_br->isa_intmap[i].phys_hi == hi) && + (isa_br->isa_intmap[i].phys_lo == lo) && + (isa_br->isa_intmap[i].interrupt == irq)) { + *interrupt = isa_br->isa_intmap[i].cinterrupt; return 0; } } @@ -107,8 +98,8 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev, { int irq_prop; - irq_prop = of_getintprop_default(isa_dev->prom_node, - "interrupts", -1); + irq_prop = prom_getintdefault(isa_dev->prom_node, + "interrupts", -1); if (irq_prop <= 0) { goto no_irq; } else { @@ -116,8 +107,7 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev, struct pci_pbm_info *pbm; int i; - if (of_find_property(isa_dev->bus->prom_node, - "interrupt-map", NULL)) { + if (isa_dev->bus->num_isa_intmap) { if (!isa_dev_get_irq_using_imap(isa_dev, isa_dev->bus, &irq_prop, @@ -151,15 +141,16 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev, static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) { - struct device_node *dp = parent_isa_dev->prom_node->child; + int node = prom_getchild(parent_isa_dev->prom_node); - if (!dp) + if (node == 0) return; printk(" ->"); - while (dp) { - struct linux_prom_registers *regs; + while (node != 0) { + struct linux_prom_registers regs[PROMREG_MAX]; struct sparc_isa_device *isa_dev; + int prop_len; isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); if (!isa_dev) { @@ -174,46 +165,49 @@ static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) parent_isa_dev->child = isa_dev; isa_dev->bus = parent_isa_dev->bus; - isa_dev->prom_node = dp; + isa_dev->prom_node = node; + prop_len = prom_getproperty(node, "name", + (char *) isa_dev->prom_name, + sizeof(isa_dev->prom_name)); + if (prop_len <= 0) { + fatal_err("cannot get child isa_dev OBP node name"); + prom_halt(); + } - regs = isa_dev_get_resource(isa_dev); + prop_len = prom_getproperty(node, "compatible", + (char *) isa_dev->compatible, + sizeof(isa_dev->compatible)); + + /* Not having this is OK. */ + if (prop_len <= 0) + isa_dev->compatible[0] = '\0'; + + isa_dev_get_resource(isa_dev, regs, sizeof(regs)); isa_dev_get_irq(isa_dev, regs); report_dev(isa_dev, 1); - dp = dp->sibling; + node = prom_getsibling(node); } } static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) { - struct device_node *dp = isa_br->prom_node->child; + int node = prom_getchild(isa_br->prom_node); - while (dp) { - struct linux_prom_registers *regs; + while (node != 0) { + struct linux_prom_registers regs[PROMREG_MAX]; struct sparc_isa_device *isa_dev; + int prop_len; isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); if (!isa_dev) { - printk(KERN_DEBUG "ISA: cannot allocate isa_dev"); - return; + fatal_err("cannot allocate isa_dev"); + prom_halt(); } memset(isa_dev, 0, sizeof(*isa_dev)); - isa_dev->ofdev.node = dp; - isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev; - isa_dev->ofdev.dev.bus = &isa_bus_type; - strcpy(isa_dev->ofdev.dev.bus_id, dp->path_component_name); - - /* Register with core */ - if (of_device_register(&isa_dev->ofdev) != 0) { - printk(KERN_DEBUG "isa: device registration error for %s!\n", - isa_dev->ofdev.dev.bus_id); - kfree(isa_dev); - goto next_sibling; - } - /* Link it in. */ isa_dev->next = NULL; if (isa_br->devices == NULL) { @@ -228,9 +222,24 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) } isa_dev->bus = isa_br; - isa_dev->prom_node = dp; + isa_dev->prom_node = node; + prop_len = prom_getproperty(node, "name", + (char *) isa_dev->prom_name, + sizeof(isa_dev->prom_name)); + if (prop_len <= 0) { + fatal_err("cannot get isa_dev OBP node name"); + prom_halt(); + } + + prop_len = prom_getproperty(node, "compatible", + (char *) isa_dev->compatible, + sizeof(isa_dev->compatible)); - regs = isa_dev_get_resource(isa_dev); + /* Not having this is OK. */ + if (prop_len <= 0) + isa_dev->compatible[0] = '\0'; + + isa_dev_get_resource(isa_dev, regs, sizeof(regs)); isa_dev_get_irq(isa_dev, regs); report_dev(isa_dev, 0); @@ -239,8 +248,7 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) printk("]"); - next_sibling: - dp = dp->sibling; + node = prom_getsibling(node); } } @@ -258,7 +266,7 @@ void __init isa_init(void) struct pcidev_cookie *pdev_cookie; struct pci_pbm_info *pbm; struct sparc_isa_bridge *isa_br; - struct device_node *dp; + int prop_len; pdev_cookie = pdev->sysdata; if (!pdev_cookie) { @@ -267,29 +275,15 @@ void __init isa_init(void) continue; } pbm = pdev_cookie->pbm; - dp = pdev_cookie->prom_node; isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL); if (!isa_br) { - printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge"); - return; + fatal_err("cannot allocate sparc_isa_bridge"); + prom_halt(); } memset(isa_br, 0, sizeof(*isa_br)); - isa_br->ofdev.node = dp; - isa_br->ofdev.dev.parent = &pdev->dev; - isa_br->ofdev.dev.bus = &isa_bus_type; - strcpy(isa_br->ofdev.dev.bus_id, dp->path_component_name); - - /* Register with core */ - if (of_device_register(&isa_br->ofdev) != 0) { - printk(KERN_DEBUG "isa: device registration error for %s!\n", - isa_br->ofdev.dev.bus_id); - kfree(isa_br); - return; - } - /* Link it in. */ isa_br->next = isa_chain; isa_chain = isa_br; @@ -298,6 +292,33 @@ void __init isa_init(void) isa_br->self = pdev; isa_br->index = index++; isa_br->prom_node = pdev_cookie->prom_node; + strncpy(isa_br->prom_name, pdev_cookie->prom_name, + sizeof(isa_br->prom_name)); + + prop_len = prom_getproperty(isa_br->prom_node, + "ranges", + (char *) isa_br->isa_ranges, + sizeof(isa_br->isa_ranges)); + if (prop_len <= 0) + isa_br->num_isa_ranges = 0; + else + isa_br->num_isa_ranges = + (prop_len / sizeof(struct linux_prom_isa_ranges)); + + prop_len = prom_getproperty(isa_br->prom_node, + "interrupt-map", + (char *) isa_br->isa_intmap, + sizeof(isa_br->isa_intmap)); + if (prop_len <= 0) + isa_br->num_isa_intmap = 0; + else + isa_br->num_isa_intmap = + (prop_len / sizeof(struct linux_prom_isa_intmap)); + + prop_len = prom_getproperty(isa_br->prom_node, + "interrupt-map-mask", + (char *) &(isa_br->isa_intmask), + sizeof(isa_br->isa_intmask)); printk("isa%d:", isa_br->index); diff --git a/trunk/arch/sparc64/kernel/of_device.c b/trunk/arch/sparc64/kernel/of_device.c deleted file mode 100644 index 566aa343aa62..000000000000 --- a/trunk/arch/sparc64/kernel/of_device.c +++ /dev/null @@ -1,279 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/** - * of_match_device - Tell if an of_device structure has a matching - * of_match structure - * @ids: array of of device match structures to search in - * @dev: the of device structure to match against - * - * Used by a driver to check whether an of_device present in the - * system is in its list of supported devices. - */ -const struct of_device_id *of_match_device(const struct of_device_id *matches, - const struct of_device *dev) -{ - if (!dev->node) - return NULL; - while (matches->name[0] || matches->type[0] || matches->compatible[0]) { - int match = 1; - if (matches->name[0]) - match &= dev->node->name - && !strcmp(matches->name, dev->node->name); - if (matches->type[0]) - match &= dev->node->type - && !strcmp(matches->type, dev->node->type); - if (matches->compatible[0]) - match &= of_device_is_compatible(dev->node, - matches->compatible); - if (match) - return matches; - matches++; - } - return NULL; -} - -static int of_platform_bus_match(struct device *dev, struct device_driver *drv) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * of_drv = to_of_platform_driver(drv); - const struct of_device_id * matches = of_drv->match_table; - - if (!matches) - return 0; - - return of_match_device(matches, of_dev) != NULL; -} - -struct of_device *of_dev_get(struct of_device *dev) -{ - struct device *tmp; - - if (!dev) - return NULL; - tmp = get_device(&dev->dev); - if (tmp) - return to_of_device(tmp); - else - return NULL; -} - -void of_dev_put(struct of_device *dev) -{ - if (dev) - put_device(&dev->dev); -} - - -static int of_device_probe(struct device *dev) -{ - int error = -ENODEV; - struct of_platform_driver *drv; - struct of_device *of_dev; - const struct of_device_id *match; - - drv = to_of_platform_driver(dev->driver); - of_dev = to_of_device(dev); - - if (!drv->probe) - return error; - - of_dev_get(of_dev); - - match = of_match_device(drv->match_table, of_dev); - if (match) - error = drv->probe(of_dev, match); - if (error) - of_dev_put(of_dev); - - return error; -} - -static int of_device_remove(struct device *dev) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - - if (dev->driver && drv->remove) - drv->remove(of_dev); - return 0; -} - -static int of_device_suspend(struct device *dev, pm_message_t state) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - int error = 0; - - if (dev->driver && drv->suspend) - error = drv->suspend(of_dev, state); - return error; -} - -static int of_device_resume(struct device * dev) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - int error = 0; - - if (dev->driver && drv->resume) - error = drv->resume(of_dev); - return error; -} - -#ifdef CONFIG_PCI -struct bus_type isa_bus_type = { - .name = "isa", - .match = of_platform_bus_match, - .probe = of_device_probe, - .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, -}; - -struct bus_type ebus_bus_type = { - .name = "ebus", - .match = of_platform_bus_match, - .probe = of_device_probe, - .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, -}; -#endif - -#ifdef CONFIG_SBUS -struct bus_type sbus_bus_type = { - .name = "sbus", - .match = of_platform_bus_match, - .probe = of_device_probe, - .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, -}; -#endif - -static int __init of_bus_driver_init(void) -{ - int err = 0; - -#ifdef CONFIG_PCI - if (!err) - err = bus_register(&isa_bus_type); - if (!err) - err = bus_register(&ebus_bus_type); -#endif -#ifdef CONFIG_SBUS - if (!err) - err = bus_register(&sbus_bus_type); -#endif - return 0; -} - -postcore_initcall(of_bus_driver_init); - -int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) -{ - /* initialize common driver fields */ - drv->driver.name = drv->name; - drv->driver.bus = bus; - - /* register with core */ - return driver_register(&drv->driver); -} - -void of_unregister_driver(struct of_platform_driver *drv) -{ - driver_unregister(&drv->driver); -} - - -static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct of_device *ofdev; - - ofdev = to_of_device(dev); - return sprintf(buf, "%s", ofdev->node->full_name); -} - -static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); - -/** - * of_release_dev - free an of device structure when all users of it are finished. - * @dev: device that's been disconnected - * - * Will be called only by the device core when all users of this of device are - * done. - */ -void of_release_dev(struct device *dev) -{ - struct of_device *ofdev; - - ofdev = to_of_device(dev); - - kfree(ofdev); -} - -int of_device_register(struct of_device *ofdev) -{ - int rc; - - BUG_ON(ofdev->node == NULL); - - rc = device_register(&ofdev->dev); - if (rc) - return rc; - - device_create_file(&ofdev->dev, &dev_attr_devspec); - - return 0; -} - -void of_device_unregister(struct of_device *ofdev) -{ - device_remove_file(&ofdev->dev, &dev_attr_devspec); - device_unregister(&ofdev->dev); -} - -struct of_device* of_platform_device_create(struct device_node *np, - const char *bus_id, - struct device *parent, - struct bus_type *bus) -{ - struct of_device *dev; - - dev = kmalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return NULL; - memset(dev, 0, sizeof(*dev)); - - dev->dev.parent = parent; - dev->dev.bus = bus; - dev->dev.release = of_release_dev; - - strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); - - if (of_device_register(dev) != 0) { - kfree(dev); - return NULL; - } - - return dev; -} - -EXPORT_SYMBOL(of_match_device); -EXPORT_SYMBOL(of_register_driver); -EXPORT_SYMBOL(of_unregister_driver); -EXPORT_SYMBOL(of_device_register); -EXPORT_SYMBOL(of_device_unregister); -EXPORT_SYMBOL(of_dev_get); -EXPORT_SYMBOL(of_dev_put); -EXPORT_SYMBOL(of_platform_device_create); -EXPORT_SYMBOL(of_release_dev); diff --git a/trunk/arch/sparc64/kernel/pci.c b/trunk/arch/sparc64/kernel/pci.c index 6c9e3e94abaa..9472580a4319 100644 --- a/trunk/arch/sparc64/kernel/pci.c +++ b/trunk/arch/sparc64/kernel/pci.c @@ -22,7 +22,6 @@ #include #include #include -#include unsigned long pci_memspace_mask = 0xffffffffUL; @@ -178,16 +177,16 @@ void pci_config_write32(u32 *addr, u32 val) } /* Probe for all PCI controllers in the system. */ -extern void sabre_init(struct device_node *, const char *); -extern void psycho_init(struct device_node *, const char *); -extern void schizo_init(struct device_node *, const char *); -extern void schizo_plus_init(struct device_node *, const char *); -extern void tomatillo_init(struct device_node *, const char *); -extern void sun4v_pci_init(struct device_node *, const char *); +extern void sabre_init(int, char *); +extern void psycho_init(int, char *); +extern void schizo_init(int, char *); +extern void schizo_plus_init(int, char *); +extern void tomatillo_init(int, char *); +extern void sun4v_pci_init(int, char *); static struct { char *model_name; - void (*init)(struct device_node *, const char *); + void (*init)(int, char *); } pci_controller_table[] __initdata = { { "SUNW,sabre", sabre_init }, { "pci108e,a000", sabre_init }, @@ -205,7 +204,7 @@ static struct { #define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \ sizeof(pci_controller_table[0])) -static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp) +static int __init pci_controller_init(char *model_name, int namelen, int node) { int i; @@ -213,15 +212,18 @@ static int __init pci_controller_init(const char *model_name, int namelen, struc if (!strncmp(model_name, pci_controller_table[i].model_name, namelen)) { - pci_controller_table[i].init(dp, model_name); + pci_controller_table[i].init(node, model_name); return 1; } } + printk("PCI: Warning unknown controller, model name [%s]\n", + model_name); + printk("PCI: Ignoring controller...\n"); return 0; } -static int __init pci_is_controller(const char *model_name, int namelen, struct device_node *dp) +static int __init pci_is_controller(char *model_name, int namelen, int node) { int i; @@ -235,35 +237,36 @@ static int __init pci_is_controller(const char *model_name, int namelen, struct return 0; } -static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *)) +static int __init pci_controller_scan(int (*handler)(char *, int, int)) { - struct device_node *dp; + char namebuf[64]; + int node; int count = 0; - for_each_node_by_name(dp, "pci") { - struct property *prop; + node = prom_getchild(prom_root_node); + while ((node = prom_searchsiblings(node, "pci")) != 0) { int len; - prop = of_find_property(dp, "model", &len); - if (!prop) - prop = of_find_property(dp, "compatible", &len); - - if (prop) { - const char *model = prop->value; + if ((len = prom_getproperty(node, "model", namebuf, sizeof(namebuf))) > 0 || + (len = prom_getproperty(node, "compatible", namebuf, sizeof(namebuf))) > 0) { int item_len = 0; /* Our value may be a multi-valued string in the * case of some compatible properties. For sanity, - * only try the first one. - */ - while (model[item_len] && len) { + * only try the first one. */ + + while (namebuf[item_len] && len) { len--; item_len++; } - if (handler(model, item_len, dp)) + if (handler(namebuf, item_len, node)) count++; } + + node = prom_getsibling(node); + if (!node) + break; } return count; @@ -406,14 +409,8 @@ void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res, } EXPORT_SYMBOL(pcibios_bus_to_resource); -extern int pci_irq_verbose; - char * __init pcibios_setup(char *str) { - if (!strcmp(str, "irq_verbose")) { - pci_irq_verbose = 1; - return NULL; - } return str; } diff --git a/trunk/arch/sparc64/kernel/pci_common.c b/trunk/arch/sparc64/kernel/pci_common.c index b06a2955bf5f..33dedb1aacd4 100644 --- a/trunk/arch/sparc64/kernel/pci_common.c +++ b/trunk/arch/sparc64/kernel/pci_common.c @@ -9,12 +9,6 @@ #include #include -#include - -#include "pci_impl.h" - -/* Pass "pci=irq_verbose" on the kernel command line to enable this. */ -int pci_irq_verbose; /* Fix self device of BUS and hook it into BUS->self. * The pci_scan_bus does not do this for the host bridge. @@ -34,14 +28,16 @@ void __init pci_fixup_host_bridge_self(struct pci_bus *pbus) 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) +/* Find the OBP PROM device tree node for a PCI device. + * Return zero if not found. + */ +static int __init find_device_prom_node(struct pci_pbm_info *pbm, + struct pci_dev *pdev, + int bus_prom_node, + struct linux_prom_pci_registers *pregs, + int *nregs) { - struct device_node *dp; + int node; *nregs = 0; @@ -58,30 +54,24 @@ find_device_prom_node(struct pci_pbm_info *pbm, struct pci_dev *pdev, 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) + return bus_prom_node; + + node = prom_getchild(bus_prom_node); + while (node != 0) { + int err = prom_getproperty(node, "reg", + (char *)pregs, + sizeof(*pregs) * PROMREG_MAX); + if (err == 0 || err == -1) 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; + if (((pregs[0].phys_hi >> 8) & 0xff) == pdev->devfn) { + *nregs = err / sizeof(*pregs); + return node; } do_next_sibling: - dp = dp->sibling; + node = prom_getsibling(node); } - - return NULL; + return 0; } /* Older versions of OBP on PCI systems encode 64-bit MEM @@ -138,17 +128,15 @@ static void __init fixup_obp_assignments(struct pci_dev *pdev, */ static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm, struct pci_dev *pdev, - struct device_node *bus_node) + int bus_prom_node) { - struct linux_prom_pci_registers *pregs = NULL; + struct linux_prom_pci_registers pregs[PROMREG_MAX]; struct pcidev_cookie *pcp; - struct device_node *dp; - struct property *prop; - int nregs, len; + int device_prom_node, nregs, err; - dp = find_device_prom_node(pbm, pdev, bus_node, - &pregs, &nregs); - if (!dp) { + device_prom_node = find_device_prom_node(pbm, pdev, bus_prom_node, + pregs, &nregs); + if (device_prom_node == 0) { /* If it is not in the OBP device tree then * there must be a damn good reason for it. * @@ -162,43 +150,45 @@ static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm, return; } - pcp = kzalloc(sizeof(*pcp), GFP_ATOMIC); + pcp = kmalloc(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; - memcpy(pcp->prom_regs, pregs, - nregs * sizeof(struct linux_prom_pci_registers)); + pcp->prom_node = device_prom_node; + memcpy(pcp->prom_regs, pregs, sizeof(pcp->prom_regs)); 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) { + err = prom_getproperty(device_prom_node, "name", + pcp->prom_name, sizeof(pcp->prom_name)); + if (err > 0) + pcp->prom_name[err] = 0; + else + pcp->prom_name[0] = 0; + + err = prom_getproperty(device_prom_node, + "assigned-addresses", + (char *)pcp->prom_assignments, + sizeof(pcp->prom_assignments)); + if (err == 0 || err == -1) pcp->num_prom_assignments = 0; - } else { - memcpy(pcp->prom_assignments, prop->value, len); + else pcp->num_prom_assignments = - (len / sizeof(pcp->prom_assignments[0])); - } + (err / sizeof(pcp->prom_assignments[0])); - if (strcmp(dp->name, "ebus") == 0) { - struct linux_prom_ebus_ranges *erng; + if (strcmp(pcp->prom_name, "ebus") == 0) { + struct linux_prom_ebus_ranges erng[PROM_PCIRNG_MAX]; int iter; /* EBUS is special... */ - prop = of_find_property(dp, "ranges", &len); - if (!prop) { + err = prom_getproperty(device_prom_node, "ranges", + (char *)&erng[0], sizeof(erng)); + if (err == 0 || err == -1) { 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++) { + err = (err / sizeof(erng[0])); + for(iter = 0; iter < err; iter++) { struct linux_prom_ebus_ranges *ep = &erng[iter]; struct linux_prom_pci_registers *ap; @@ -210,7 +200,7 @@ static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm, ap->size_hi = 0; ap->size_lo = ep->size; } - pcp->num_prom_assignments = len; + pcp->num_prom_assignments = err; } fixup_obp_assignments(pdev, pcp); @@ -220,7 +210,7 @@ static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm, void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus, struct pci_pbm_info *pbm, - struct device_node *dp) + int prom_node) { struct pci_dev *pdev, *pdev_next; struct pci_bus *this_pbus, *pbus_next; @@ -228,7 +218,7 @@ void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus, /* 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); + pdev_cookie_fillin(pbm, pdev, prom_node); list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) { struct pcidev_cookie *pcp = this_pbus->self->sysdata; @@ -251,6 +241,7 @@ static void __init bad_assignment(struct pci_dev *pdev, if (res) prom_printf("PCI: RES[%016lx-->%016lx:(%lx)]\n", res->start, res->end, res->flags); + prom_printf("Please email this information to davem@redhat.com\n"); if (do_prom_halt) prom_halt(); } @@ -282,7 +273,8 @@ __init get_root_resource(struct linux_prom_pci_registers *ap, return &pbm->mem_space; default: - printk("PCI: What is resource space %x?\n", space); + printk("PCI: What is resource space %x? " + "Tell davem@redhat.com about it!\n", space); return NULL; }; } @@ -564,10 +556,9 @@ static inline unsigned int pci_slot_swivel(struct pci_pbm_info *pbm, ret = ((interrupt - 1 + (PCI_SLOT(pdev->devfn) & 3)) & 3) + 1; - if (pci_irq_verbose) - printk("%s: %s IRQ Swivel %s [%x:%x] -> [%x]\n", - pbm->name, pci_name(toplevel_pdev), pci_name(pdev), - interrupt, PCI_SLOT(pdev->devfn), ret); + printk("%s: %s IRQ Swivel %s [%x:%x] -> [%x]\n", + pbm->name, pci_name(toplevel_pdev), pci_name(pdev), + interrupt, PCI_SLOT(pdev->devfn), ret); return ret; } @@ -577,60 +568,58 @@ static inline unsigned int pci_apply_intmap(struct pci_pbm_info *pbm, struct pci_dev *pbus, struct pci_dev *pdev, unsigned int interrupt, - struct device_node **cnode) + unsigned int *cnode) { - struct linux_prom_pci_intmap *imap; - struct linux_prom_pci_intmask *imask; + struct linux_prom_pci_intmap imap[PROM_PCIIMAP_MAX]; + struct linux_prom_pci_intmask imask; struct pcidev_cookie *pbus_pcp = pbus->sysdata; struct pcidev_cookie *pdev_pcp = pdev->sysdata; struct linux_prom_pci_registers *pregs = pdev_pcp->prom_regs; - struct property *prop; int plen, num_imap, i; unsigned int hi, mid, lo, irq, orig_interrupt; *cnode = pbus_pcp->prom_node; - prop = of_find_property(pbus_pcp->prom_node, "interrupt-map", &plen); - if (!prop || + plen = prom_getproperty(pbus_pcp->prom_node, "interrupt-map", + (char *) &imap[0], sizeof(imap)); + if (plen <= 0 || (plen % sizeof(struct linux_prom_pci_intmap)) != 0) { printk("%s: Device %s interrupt-map has bad len %d\n", pbm->name, pci_name(pbus), plen); goto no_intmap; } - imap = prop->value; num_imap = plen / sizeof(struct linux_prom_pci_intmap); - prop = of_find_property(pbus_pcp->prom_node, "interrupt-map-mask", &plen); - if (!prop || + plen = prom_getproperty(pbus_pcp->prom_node, "interrupt-map-mask", + (char *) &imask, sizeof(imask)); + if (plen <= 0 || (plen % sizeof(struct linux_prom_pci_intmask)) != 0) { printk("%s: Device %s interrupt-map-mask has bad len %d\n", pbm->name, pci_name(pbus), plen); goto no_intmap; } - imask = prop->value; orig_interrupt = interrupt; - hi = pregs->phys_hi & imask->phys_hi; - mid = pregs->phys_mid & imask->phys_mid; - lo = pregs->phys_lo & imask->phys_lo; - irq = interrupt & imask->interrupt; + hi = pregs->phys_hi & imask.phys_hi; + mid = pregs->phys_mid & imask.phys_mid; + lo = pregs->phys_lo & imask.phys_lo; + irq = interrupt & imask.interrupt; for (i = 0; i < num_imap; i++) { if (imap[i].phys_hi == hi && imap[i].phys_mid == mid && imap[i].phys_lo == lo && imap[i].interrupt == irq) { - *cnode = of_find_node_by_phandle(imap[i].cnode); + *cnode = imap[i].cnode; interrupt = imap[i].cinterrupt; } } - if (pci_irq_verbose) - printk("%s: %s MAP BUS %s DEV %s [%x] -> [%x]\n", - pbm->name, pci_name(toplevel_pdev), - pci_name(pbus), pci_name(pdev), - orig_interrupt, interrupt); + printk("%s: %s MAP BUS %s DEV %s [%x] -> [%x]\n", + pbm->name, pci_name(toplevel_pdev), + pci_name(pbus), pci_name(pdev), + orig_interrupt, interrupt); no_intmap: return interrupt; @@ -644,22 +633,21 @@ static inline unsigned int pci_apply_intmap(struct pci_pbm_info *pbm, * all interrupt translations are complete, else we should use that node's * "reg" property to apply the PBM's "interrupt-{map,mask}" to the interrupt. */ -static struct device_node * __init -pci_intmap_match_to_root(struct pci_pbm_info *pbm, - struct pci_dev *pdev, - unsigned int *interrupt) +static unsigned int __init pci_intmap_match_to_root(struct pci_pbm_info *pbm, + struct pci_dev *pdev, + unsigned int *interrupt) { struct pci_dev *toplevel_pdev = pdev; struct pcidev_cookie *toplevel_pcp = toplevel_pdev->sysdata; - struct device_node *cnode = toplevel_pcp->prom_node; + unsigned int cnode = toplevel_pcp->prom_node; while (pdev->bus->number != pbm->pci_first_busno) { struct pci_dev *pbus = pdev->bus->self; struct pcidev_cookie *pcp = pbus->sysdata; - struct property *prop; + int plen; - prop = of_find_property(pcp->prom_node, "interrupt-map", NULL); - if (!prop) { + plen = prom_getproplen(pcp->prom_node, "interrupt-map"); + if (plen <= 0) { *interrupt = pci_slot_swivel(pbm, toplevel_pdev, pdev, *interrupt); cnode = pcp->prom_node; @@ -687,29 +675,26 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt { struct pcidev_cookie *dev_pcp = pdev->sysdata; struct pci_pbm_info *pbm = dev_pcp->pbm; - struct linux_prom_pci_registers *reg; - struct device_node *cnode; - struct property *prop; + struct linux_prom_pci_registers reg[PROMREG_MAX]; unsigned int hi, mid, lo, irq; - int i, plen; + int i, cnode, plen; cnode = pci_intmap_match_to_root(pbm, pdev, interrupt); if (cnode == pbm->prom_node) goto success; - prop = of_find_property(cnode, "reg", &plen); - if (!prop || + plen = prom_getproperty(cnode, "reg", (char *) reg, sizeof(reg)); + if (plen <= 0 || (plen % sizeof(struct linux_prom_pci_registers)) != 0) { - printk("%s: OBP node %s reg property has bad len %d\n", - pbm->name, cnode->full_name, plen); + printk("%s: OBP node %x reg property has bad len %d\n", + pbm->name, cnode, plen); goto fail; } - reg = prop->value; - hi = reg[0].phys_hi & pbm->pbm_intmask->phys_hi; - mid = reg[0].phys_mid & pbm->pbm_intmask->phys_mid; - lo = reg[0].phys_lo & pbm->pbm_intmask->phys_lo; - irq = *interrupt & pbm->pbm_intmask->interrupt; + hi = reg[0].phys_hi & pbm->pbm_intmask.phys_hi; + mid = reg[0].phys_mid & pbm->pbm_intmask.phys_mid; + lo = reg[0].phys_lo & pbm->pbm_intmask.phys_lo; + irq = *interrupt & pbm->pbm_intmask.interrupt; for (i = 0; i < pbm->num_pbm_intmap; i++) { struct linux_prom_pci_intmap *intmap; @@ -729,11 +714,9 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt return 0; success: - if (pci_irq_verbose) - printk("%s: Routing bus[%2x] slot[%2x] to INO[%02x]\n", - pbm->name, - pdev->bus->number, PCI_SLOT(pdev->devfn), - *interrupt); + printk("PCI-IRQ: Routing bus[%2x] slot[%2x] to INO[%02x]\n", + pdev->bus->number, PCI_SLOT(pdev->devfn), + *interrupt); return 1; } @@ -744,8 +727,8 @@ static void __init pdev_fixup_irq(struct pci_dev *pdev) struct pci_controller_info *p = pbm->parent; unsigned int portid = pbm->portid; unsigned int prom_irq; - struct device_node *dp = pcp->prom_node; - struct property *prop; + int prom_node = pcp->prom_node; + int err; /* If this is an empty EBUS device, sometimes OBP fails to * give it a valid fully specified interrupts property. @@ -756,17 +739,17 @@ static void __init pdev_fixup_irq(struct pci_dev *pdev) */ if (pdev->vendor == PCI_VENDOR_ID_SUN && pdev->device == PCI_DEVICE_ID_SUN_EBUS && - !dp->child) { + !prom_getchild(prom_node)) { pdev->irq = 0; return; } - prop = of_find_property(dp, "interrupts", NULL); - if (!prop) { + err = prom_getproperty(prom_node, "interrupts", + (char *)&prom_irq, sizeof(prom_irq)); + if (err == 0 || err == -1) { pdev->irq = 0; return; } - prom_irq = *(unsigned int *) prop->value; if (tlb_type != hypervisor) { /* Fully specified already? */ diff --git a/trunk/arch/sparc64/kernel/pci_impl.h b/trunk/arch/sparc64/kernel/pci_impl.h index 971e2bea30b4..6c3205962544 100644 --- a/trunk/arch/sparc64/kernel/pci_impl.h +++ b/trunk/arch/sparc64/kernel/pci_impl.h @@ -10,7 +10,6 @@ #include #include #include -#include extern struct pci_controller_info *pci_controller_root; @@ -20,7 +19,7 @@ extern int pci_num_controllers; 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); + int 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, diff --git a/trunk/arch/sparc64/kernel/pci_psycho.c b/trunk/arch/sparc64/kernel/pci_psycho.c index 5b2261ebda6f..24db22aa9728 100644 --- a/trunk/arch/sparc64/kernel/pci_psycho.c +++ b/trunk/arch/sparc64/kernel/pci_psycho.c @@ -17,7 +17,6 @@ #include #include #include -#include #include "pci_impl.h" #include "iommu_common.h" @@ -1292,12 +1291,11 @@ static void psycho_pbm_strbuf_init(struct pci_controller_info *p, #define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL static void psycho_pbm_init(struct pci_controller_info *p, - struct device_node *dp, int is_pbm_a) + int prom_node, int is_pbm_a) { - unsigned int *busrange; - struct property *prop; + unsigned int busrange[2]; struct pci_pbm_info *pbm; - int len; + int err; if (is_pbm_a) { pbm = &p->pbm_A; @@ -1312,14 +1310,10 @@ static void psycho_pbm_init(struct pci_controller_info *p, } pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; - pbm->chip_version = 0; - prop = of_find_property(dp, "version#", NULL); - if (prop) - pbm->chip_version = *(int *) prop->value; - pbm->chip_revision = 0; - prop = of_find_property(dp, "module-revision#", NULL); - if (prop) - pbm->chip_revision = *(int *) prop->value; + pbm->chip_version = + prom_getintdefault(prom_node, "version#", 0); + pbm->chip_revision = + prom_getintdefault(prom_node, "module-revision#", 0); pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE; pbm->io_space.flags = IORESOURCE_IO; @@ -1328,36 +1322,45 @@ static void psycho_pbm_init(struct pci_controller_info *p, pbm_register_toplevel_resources(p, pbm); pbm->parent = p; - pbm->prom_node = dp; - pbm->name = dp->full_name; - - printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n", - pbm->name, - pbm->chip_version, pbm->chip_revision); - - prop = of_find_property(dp, "ranges", &len); - if (prop) { - pbm->pbm_ranges = prop->value; + pbm->prom_node = prom_node; + prom_getstring(prom_node, "name", + pbm->prom_name, + sizeof(pbm->prom_name)); + + err = prom_getproperty(prom_node, "ranges", + (char *)pbm->pbm_ranges, + sizeof(pbm->pbm_ranges)); + if (err != -1) pbm->num_pbm_ranges = - (len / sizeof(struct linux_prom_pci_ranges)); - } else { + (err / 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; + err = prom_getproperty(prom_node, "interrupt-map", + (char *)pbm->pbm_intmap, + sizeof(pbm->pbm_intmap)); + if (err != -1) { + pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); + err = prom_getproperty(prom_node, "interrupt-map-mask", + (char *)&pbm->pbm_intmask, + sizeof(pbm->pbm_intmask)); + if (err == -1) { + prom_printf("PSYCHO-PBM: Fatal error, no " + "interrupt-map-mask.\n"); + prom_halt(); + } } else { pbm->num_pbm_intmap = 0; + memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask)); } - prop = of_find_property(dp, "bus-range", NULL); - busrange = prop->value; + err = prom_getproperty(prom_node, "bus-range", + (char *)&busrange[0], + sizeof(busrange)); + if (err == 0 || err == -1) { + prom_printf("PSYCHO-PBM: Fatal error, no bus-range.\n"); + prom_halt(); + } pbm->pci_first_busno = busrange[0]; pbm->pci_last_busno = busrange[1]; @@ -1366,24 +1369,20 @@ static void psycho_pbm_init(struct pci_controller_info *p, #define PSYCHO_CONFIGSPACE 0x001000000UL -void psycho_init(struct device_node *dp, char *model_name) +void psycho_init(int node, char *model_name) { - struct linux_prom64_registers *pr_regs; + struct linux_prom64_registers pr_regs[3]; struct pci_controller_info *p; struct pci_iommu *iommu; - struct property *prop; u32 upa_portid; - int is_pbm_a; + int is_pbm_a, err; - upa_portid = 0xff; - prop = of_find_property(dp, "upa-portid", NULL); - if (prop) - upa_portid = *(u32 *) prop->value; + upa_portid = prom_getintdefault(node, "upa-portid", 0xff); for(p = pci_controller_root; p; p = p->next) { if (p->pbm_A.portid == upa_portid) { - is_pbm_a = (p->pbm_A.prom_node == NULL); - psycho_pbm_init(p, dp, is_pbm_a); + is_pbm_a = (p->pbm_A.prom_node == 0); + psycho_pbm_init(p, node, is_pbm_a); return; } } @@ -1413,14 +1412,23 @@ void psycho_init(struct device_node *dp, char *model_name) p->resource_adjust = psycho_resource_adjust; p->pci_ops = &psycho_ops; - prop = of_find_property(dp, "reg", NULL); - pr_regs = prop->value; + err = prom_getproperty(node, "reg", + (char *)&pr_regs[0], + sizeof(pr_regs)); + if (err == 0 || err == -1) { + prom_printf("PSYCHO: Fatal error, no reg property.\n"); + prom_halt(); + } p->pbm_A.controller_regs = pr_regs[2].phys_addr; p->pbm_B.controller_regs = pr_regs[2].phys_addr; + printk("PCI: Found PSYCHO, control regs at %016lx\n", + p->pbm_A.controller_regs); p->pbm_A.config_space = p->pbm_B.config_space = (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); + printk("PSYCHO: Shared PCI config space at %016lx\n", + p->pbm_A.config_space); /* * Psycho's PCI MEM space is mapped to a 2GB aligned area, so @@ -1433,5 +1441,5 @@ void psycho_init(struct device_node *dp, char *model_name) psycho_iommu_init(p); is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); - psycho_pbm_init(p, dp, is_pbm_a); + psycho_pbm_init(p, node, is_pbm_a); } diff --git a/trunk/arch/sparc64/kernel/pci_sabre.c b/trunk/arch/sparc64/kernel/pci_sabre.c index 26f194ce4400..b7d997b55f0a 100644 --- a/trunk/arch/sparc64/kernel/pci_sabre.c +++ b/trunk/arch/sparc64/kernel/pci_sabre.c @@ -19,7 +19,6 @@ #include #include #include -#include #include "pci_impl.h" #include "iommu_common.h" @@ -1307,36 +1306,34 @@ static void pbm_register_toplevel_resources(struct pci_controller_info *p, &pbm->mem_space); } -static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_begin) +static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dma_begin) { struct pci_pbm_info *pbm; - struct device_node *node; - struct property *prop; - u32 *busrange; - int len, simbas_found; + char namebuf[128]; + u32 busrange[2]; + int node, simbas_found; simbas_found = 0; - node = dp->child; - while (node != NULL) { - if (strcmp(node->name, "pci")) - goto next_pci; + node = prom_getchild(sabre_node); + while ((node = prom_searchsiblings(node, "pci")) != 0) { + int err; - prop = of_find_property(node, "model", NULL); - if (!prop || strncmp(prop->value, "SUNW,simba", prop->length)) + err = prom_getproperty(node, "model", namebuf, sizeof(namebuf)); + if ((err <= 0) || strncmp(namebuf, "SUNW,simba", err)) goto next_pci; - simbas_found++; + err = prom_getproperty(node, "bus-range", + (char *)&busrange[0], sizeof(busrange)); + if (err == 0 || err == -1) { + prom_printf("APB: Error, cannot get PCI bus-range.\n"); + prom_halt(); + } - prop = of_find_property(node, "bus-range", NULL); - busrange = prop->value; + simbas_found++; 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; @@ -1344,68 +1341,83 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp 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; + prom_getstring(node, "name", pbm->prom_name, sizeof(pbm->prom_name)); + err = prom_getproperty(node, "ranges", + (char *)pbm->pbm_ranges, + sizeof(pbm->pbm_ranges)); + if (err != -1) pbm->num_pbm_ranges = - (len / sizeof(struct linux_prom_pci_ranges)); - } else { + (err / 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; + err = prom_getproperty(node, "interrupt-map", + (char *)pbm->pbm_intmap, + sizeof(pbm->pbm_intmap)); + if (err != -1) { + pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); + err = prom_getproperty(node, "interrupt-map-mask", + (char *)&pbm->pbm_intmask, + sizeof(pbm->pbm_intmask)); + if (err == -1) { + prom_printf("APB: Fatal error, no interrupt-map-mask.\n"); + prom_halt(); + } } else { pbm->num_pbm_intmap = 0; + memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask)); } pbm_register_toplevel_resources(p, pbm); next_pci: - node = node->sibling; + node = prom_getsibling(node); + if (!node) + break; } if (simbas_found == 0) { + int err; + /* No APBs underneath, probably this is a hummingbird * system. */ pbm = &p->pbm_A; pbm->parent = p; - pbm->prom_node = dp; + pbm->prom_node = sabre_node; 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; + prom_getstring(sabre_node, "name", pbm->prom_name, sizeof(pbm->prom_name)); + err = prom_getproperty(sabre_node, "ranges", + (char *) pbm->pbm_ranges, + sizeof(pbm->pbm_ranges)); + if (err != -1) pbm->num_pbm_ranges = - (len / sizeof(struct linux_prom_pci_ranges)); - } else { + (err / 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; + err = prom_getproperty(sabre_node, "interrupt-map", + (char *) pbm->pbm_intmap, + sizeof(pbm->pbm_intmap)); + + if (err != -1) { + pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); + err = prom_getproperty(sabre_node, "interrupt-map-mask", + (char *)&pbm->pbm_intmask, + sizeof(pbm->pbm_intmask)); + if (err == -1) { + prom_printf("Hummingbird: Fatal error, no interrupt-map-mask.\n"); + prom_halt(); + } } else { pbm->num_pbm_intmap = 0; + memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask)); } - pbm->name = dp->full_name; - printk("%s: SABRE PCI Bus Module\n", pbm->name); + sprintf(pbm->name, "SABRE%d PBM%c", p->index, + (pbm == &p->pbm_A ? 'A' : 'B')); pbm->io_space.name = pbm->mem_space.name = pbm->name; /* Hack up top-level resources. */ @@ -1431,15 +1443,14 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp } } -void sabre_init(struct device_node *dp, char *model_name) +void sabre_init(int pnode, char *model_name) { - struct linux_prom64_registers *pr_regs; + struct linux_prom64_registers pr_regs[2]; struct pci_controller_info *p; struct pci_iommu *iommu; - struct property *prop; - int tsbsize; - u32 *busrange; - u32 *vdma; + int tsbsize, err; + u32 busrange[2]; + u32 vdma[2]; u32 upa_portid, dma_mask; u64 clear_irq; @@ -1447,21 +1458,22 @@ 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; + char compat[64]; - if (!strcmp(compat, "pci108e,a001")) - hummingbird_p = 1; - } - if (!hummingbird_p) { - struct device_node *dp; + if (prom_getproperty(pnode, "compatible", + compat, sizeof(compat)) > 0 && + !strcmp(compat, "pci108e,a001")) { + hummingbird_p = 1; + } else { + int cpu_node; /* Of course, Sun has to encode things a thousand * different ways, inconsistently. */ - cpu_find_by_instance(0, &dp, NULL); - if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe")) + cpu_find_by_instance(0, &cpu_node, NULL); + if (prom_getproperty(cpu_node, "name", + compat, sizeof(compat)) > 0 && + !strcmp(compat, "SUNW,UltraSPARC-IIe")) hummingbird_p = 1; } } @@ -1479,10 +1491,7 @@ void sabre_init(struct device_node *dp, char *model_name) } p->pbm_A.iommu = p->pbm_B.iommu = iommu; - upa_portid = 0xff; - prop = of_find_property(dp, "upa-portid", NULL); - if (prop) - upa_portid = *(u32 *) prop->value; + upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff); p->next = pci_controller_root; pci_controller_root = p; @@ -1500,9 +1509,13 @@ 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; + err = prom_getproperty(pnode, "reg", + (char *)&pr_regs[0], sizeof(pr_regs)); + if(err == 0 || err == -1) { + prom_printf("SABRE: Error, cannot get U2P registers " + "from PROM.\n"); + prom_halt(); + } /* * First REG in property is base of entire SABRE register space. @@ -1510,6 +1523,9 @@ void sabre_init(struct device_node *dp, char *model_name) p->pbm_A.controller_regs = pr_regs[0].phys_addr; p->pbm_B.controller_regs = pr_regs[0].phys_addr; + printk("PCI: Found SABRE, main regs at %016lx\n", + p->pbm_A.controller_regs); + /* Clear interrupts */ /* PCI first */ @@ -1528,9 +1544,16 @@ void sabre_init(struct device_node *dp, char *model_name) /* Now map in PCI config space for entire SABRE. */ p->pbm_A.config_space = p->pbm_B.config_space = (p->pbm_A.controller_regs + SABRE_CONFIGSPACE); - - prop = of_find_property(dp, "virtual-dma", NULL); - vdma = prop->value; + printk("SABRE: Shared PCI config space at %016lx\n", + p->pbm_A.config_space); + + err = prom_getproperty(pnode, "virtual-dma", + (char *)&vdma[0], sizeof(vdma)); + if(err == 0 || err == -1) { + prom_printf("SABRE: Error, cannot get virtual-dma property " + "from PROM.\n"); + prom_halt(); + } dma_mask = vdma[0]; switch(vdma[1]) { @@ -1554,13 +1577,21 @@ 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; + printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]); + + err = prom_getproperty(pnode, "bus-range", + (char *)&busrange[0], sizeof(busrange)); + if(err == 0 || err == -1) { + prom_printf("SABRE: Error, cannot get PCI bus-range " + " from PROM.\n"); + prom_halt(); + } + p->pci_first_busno = busrange[0]; p->pci_last_busno = busrange[1]; /* * Look for APB underneath. */ - sabre_pbm_init(p, dp, vdma[0]); + sabre_pbm_init(p, pnode, vdma[0]); } diff --git a/trunk/arch/sparc64/kernel/pci_schizo.c b/trunk/arch/sparc64/kernel/pci_schizo.c index f16449ccd7bc..cc662e915d32 100644 --- a/trunk/arch/sparc64/kernel/pci_schizo.c +++ b/trunk/arch/sparc64/kernel/pci_schizo.c @@ -16,7 +16,6 @@ #include #include #include -#include #include "pci_impl.h" #include "iommu_common.h" @@ -1457,12 +1456,10 @@ static void __schizo_scan_bus(struct pci_controller_info *p, pbm_config_busmastering(&p->pbm_B); p->pbm_B.is_66mhz_capable = - (of_find_property(p->pbm_B.prom_node, "66mhz-capable", NULL) - != NULL); + prom_getbool(p->pbm_B.prom_node, "66mhz-capable"); pbm_config_busmastering(&p->pbm_A); p->pbm_A.is_66mhz_capable = - (of_find_property(p->pbm_A.prom_node, "66mhz-capable", NULL) - != NULL); + prom_getbool(p->pbm_A.prom_node, "66mhz-capable"); pbm_scan_bus(p, &p->pbm_B); pbm_scan_bus(p, &p->pbm_A); @@ -1664,18 +1661,13 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) { struct pci_iommu *iommu = pbm->iommu; unsigned long i, tagbase, database; - struct property *prop; u32 vdma[2], dma_mask; u64 control; - int tsbsize; + int err, tsbsize; - prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); - if (prop) { - u32 *val = prop->value; - - vdma[0] = val[0]; - vdma[1] = val[1]; - } else { + err = prom_getproperty(pbm->prom_node, "virtual-dma", + (char *)&vdma[0], sizeof(vdma)); + if (err == 0 || err == -1) { /* No property, use default values. */ vdma[0] = 0xc0000000; vdma[1] = 0x40000000; @@ -1786,7 +1778,6 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) { - struct property *prop; u64 tmp; schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5); @@ -1800,8 +1791,7 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) pbm->chip_version >= 0x2) tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; - prop = of_find_property(pbm->prom_node, "no-bus-parking", NULL); - if (!prop) + if (!prom_getbool(pbm->prom_node, "no-bus-parking")) tmp |= SCHIZO_PCICTRL_PARK; else tmp &= ~SCHIZO_PCICTRL_PARK; @@ -1841,17 +1831,16 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) } static void schizo_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 portid, + int prom_node, u32 portid, int chip_type) { - struct linux_prom64_registers *regs; - struct property *prop; - unsigned int *busrange; + struct linux_prom64_registers pr_regs[4]; + unsigned int busrange[2]; struct pci_pbm_info *pbm; const char *chipset_name; - u32 *ino_bitmap; + u32 ino_bitmap[2]; int is_pbm_a; - int len; + int err; switch (chip_type) { case PBM_CHIP_TYPE_TOMATILLO: @@ -1879,10 +1868,16 @@ static void schizo_pbm_init(struct pci_controller_info *p, * 3) PBM PCI config space * 4) Ichip regs */ - prop = of_find_property(dp, "reg", NULL); - regs = prop->value; + err = prom_getproperty(prom_node, "reg", + (char *)&pr_regs[0], + sizeof(pr_regs)); + if (err == 0 || err == -1) { + prom_printf("%s: Fatal error, no reg property.\n", + chipset_name); + prom_halt(); + } - is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); + is_pbm_a = ((pr_regs[0].phys_addr & 0x00700000) == 0x00600000); if (is_pbm_a) pbm = &p->pbm_A; @@ -1891,62 +1886,92 @@ static void schizo_pbm_init(struct pci_controller_info *p, pbm->portid = portid; pbm->parent = p; - pbm->prom_node = dp; + pbm->prom_node = prom_node; pbm->pci_first_slot = 1; pbm->chip_type = chip_type; - pbm->chip_version = 0; - prop = of_find_property(dp, "version#", NULL); - if (prop) - pbm->chip_version = *(int *) prop->value; - pbm->chip_revision = 0; - prop = of_find_property(dp, "module-revision#", NULL); - if (prop) - pbm->chip_revision = *(int *) prop->value; - - pbm->pbm_regs = regs[0].phys_addr; - pbm->controller_regs = regs[1].phys_addr - 0x10000UL; + pbm->chip_version = + prom_getintdefault(prom_node, "version#", 0); + pbm->chip_revision = + prom_getintdefault(prom_node, "module-revision#", 0); + + pbm->pbm_regs = pr_regs[0].phys_addr; + pbm->controller_regs = pr_regs[1].phys_addr - 0x10000UL; if (chip_type == PBM_CHIP_TYPE_TOMATILLO) - pbm->sync_reg = regs[3].phys_addr + 0x1a18UL; + pbm->sync_reg = pr_regs[3].phys_addr + 0x1a18UL; - pbm->name = dp->full_name; + sprintf(pbm->name, + (chip_type == PBM_CHIP_TYPE_TOMATILLO ? + "TOMATILLO%d PBM%c" : + "SCHIZO%d PBM%c"), + p->index, + (pbm == &p->pbm_A ? 'A' : 'B')); - printk("%s: %s PCI Bus Module ver[%x:%x]\n", + printk("%s: ver[%x:%x], portid %x, " + "cregs[%lx] pregs[%lx]\n", pbm->name, - (chip_type == PBM_CHIP_TYPE_TOMATILLO ? - "TOMATILLO" : "SCHIZO"), - pbm->chip_version, pbm->chip_revision); + pbm->chip_version, pbm->chip_revision, + pbm->portid, + pbm->controller_regs, + pbm->pbm_regs); schizo_pbm_hw_init(pbm); - prop = of_find_property(dp, "ranges", &len); - pbm->pbm_ranges = prop->value; + prom_getstring(prom_node, "name", + pbm->prom_name, + sizeof(pbm->prom_name)); + + err = prom_getproperty(prom_node, "ranges", + (char *) pbm->pbm_ranges, + sizeof(pbm->pbm_ranges)); + if (err == 0 || err == -1) { + prom_printf("%s: Fatal error, no ranges property.\n", + pbm->name); + prom_halt(); + } + pbm->num_pbm_ranges = - (len / sizeof(struct linux_prom_pci_ranges)); + (err / sizeof(struct linux_prom_pci_ranges)); schizo_determine_mem_io_space(pbm); pbm_register_toplevel_resources(p, pbm); - 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; + err = prom_getproperty(prom_node, "interrupt-map", + (char *)pbm->pbm_intmap, + sizeof(pbm->pbm_intmap)); + if (err != -1) { + pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); + err = prom_getproperty(prom_node, "interrupt-map-mask", + (char *)&pbm->pbm_intmask, + sizeof(pbm->pbm_intmask)); + if (err == -1) { + prom_printf("%s: Fatal error, no " + "interrupt-map-mask.\n", pbm->name); + prom_halt(); + } } else { pbm->num_pbm_intmap = 0; + memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask)); } - prop = of_find_property(dp, "ino-bitmap", NULL); - ino_bitmap = prop->value; + err = prom_getproperty(prom_node, "ino-bitmap", + (char *) &ino_bitmap[0], + sizeof(ino_bitmap)); + if (err == 0 || err == -1) { + prom_printf("%s: Fatal error, no ino-bitmap.\n", pbm->name); + prom_halt(); + } pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) | ((u64)ino_bitmap[0] << 0UL)); - prop = of_find_property(dp, "bus-range", NULL); - busrange = prop->value; + err = prom_getproperty(prom_node, "bus-range", + (char *)&busrange[0], + sizeof(busrange)); + if (err == 0 || err == -1) { + prom_printf("%s: Fatal error, no bus-range.\n", pbm->name); + prom_halt(); + } pbm->pci_first_busno = busrange[0]; pbm->pci_last_busno = busrange[1]; @@ -1964,20 +1989,16 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) return (x == y); } -static void __schizo_init(struct device_node *dp, char *model_name, int chip_type) +static void __schizo_init(int node, char *model_name, int chip_type) { struct pci_controller_info *p; struct pci_iommu *iommu; - struct property *prop; int is_pbm_a; u32 portid; - portid = 0xff; - prop = of_find_property(dp, "portid", NULL); - if (prop) - portid = *(u32 *) prop->value; + portid = prom_getintdefault(node, "portid", 0xff); - for (p = pci_controller_root; p; p = p->next) { + for(p = pci_controller_root; p; p = p->next) { struct pci_pbm_info *pbm; if (p->pbm_A.prom_node && p->pbm_B.prom_node) @@ -1988,8 +2009,8 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ &p->pbm_B); if (portid_compare(pbm->portid, portid, chip_type)) { - is_pbm_a = (p->pbm_A.prom_node == NULL); - schizo_pbm_init(p, dp, portid, chip_type); + is_pbm_a = (p->pbm_A.prom_node == 0); + schizo_pbm_init(p, node, portid, chip_type); return; } } @@ -2030,20 +2051,20 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ /* Like PSYCHO we have a 2GB aligned area for memory space. */ pci_memspace_mask = 0x7fffffffUL; - schizo_pbm_init(p, dp, portid, chip_type); + schizo_pbm_init(p, node, portid, chip_type); } -void schizo_init(struct device_node *dp, char *model_name) +void schizo_init(int node, char *model_name) { - __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO); + __schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO); } -void schizo_plus_init(struct device_node *dp, char *model_name) +void schizo_plus_init(int node, char *model_name) { - __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS); + __schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS); } -void tomatillo_init(struct device_node *dp, char *model_name) +void tomatillo_init(int node, char *model_name) { - __schizo_init(dp, model_name, PBM_CHIP_TYPE_TOMATILLO); + __schizo_init(node, model_name, PBM_CHIP_TYPE_TOMATILLO); } diff --git a/trunk/arch/sparc64/kernel/pci_sun4v.c b/trunk/arch/sparc64/kernel/pci_sun4v.c index b69e2270a721..5419480edf41 100644 --- a/trunk/arch/sparc64/kernel/pci_sun4v.c +++ b/trunk/arch/sparc64/kernel/pci_sun4v.c @@ -18,7 +18,6 @@ #include #include #include -#include #include "pci_impl.h" #include "iommu_common.h" @@ -647,37 +646,35 @@ static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, u /* 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) +static int obp_find(struct linux_prom_pci_registers *pregs, int toplevel_node, unsigned int bus, unsigned int devfn) { - toplevel_node = toplevel_node->child; + toplevel_node = prom_getchild(toplevel_node); - while (toplevel_node != NULL) { - struct linux_prom_pci_registers *regs; - struct property *prop; - int ret; + while (toplevel_node != 0) { + int ret = obp_find(pregs, toplevel_node, bus, devfn); - ret = obp_find(toplevel_node, bus, devfn); if (ret != 0) return ret; - prop = of_find_property(toplevel_node, "reg", NULL); - if (!prop) + ret = prom_getproperty(toplevel_node, "reg", (char *) pregs, + sizeof(*pregs) * PROMREG_MAX); + if (ret == 0 || ret == -1) goto next_sibling; - regs = prop->value; - if (((regs->phys_hi >> 16) & 0xff) == bus && - ((regs->phys_hi >> 8) & 0xff) == devfn) + if (((pregs[0].phys_hi >> 16) & 0xff) == bus && + ((pregs[0].phys_hi >> 8) & 0xff) == devfn) break; next_sibling: - toplevel_node = toplevel_node->sibling; + toplevel_node = prom_getsibling(toplevel_node); } - return toplevel_node != NULL; + return toplevel_node; } static int pdev_htab_populate(struct pci_pbm_info *pbm) { + struct linux_prom_pci_registers pr[PROMREG_MAX]; u32 devhandle = pbm->devhandle; unsigned int bus; @@ -688,7 +685,7 @@ static int pdev_htab_populate(struct pci_pbm_info *pbm) unsigned int device = PCI_SLOT(devfn); unsigned int func = PCI_FUNC(devfn); - if (obp_find(pbm->prom_node, bus, devfn)) { + if (obp_find(pr, pbm->prom_node, bus, devfn)) { int err = pdev_htab_add(devhandle, bus, device, func); if (err) @@ -814,7 +811,8 @@ static void pbm_scan_bus(struct pci_controller_info *p, 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_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); @@ -824,18 +822,15 @@ static void pbm_scan_bus(struct pci_controller_info *p, static void pci_sun4v_scan_bus(struct pci_controller_info *p) { - struct property *prop; - struct device_node *dp; - - if ((dp = p->pbm_A.prom_node) != NULL) { - prop = of_find_property(dp, "66mhz-capable", NULL); - p->pbm_A.is_66mhz_capable = (prop != NULL); + if (p->pbm_A.prom_node) { + p->pbm_A.is_66mhz_capable = + prom_getbool(p->pbm_A.prom_node, "66mhz-capable"); pbm_scan_bus(p, &p->pbm_A); } - if ((dp = p->pbm_B.prom_node) != NULL) { - prop = of_find_property(dp, "66mhz-capable", NULL); - p->pbm_B.is_66mhz_capable = (prop != NULL); + if (p->pbm_B.prom_node) { + p->pbm_B.is_66mhz_capable = + prom_getbool(p->pbm_B.prom_node, "66mhz-capable"); pbm_scan_bus(p, &p->pbm_B); } @@ -987,13 +982,8 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm, HV_PCI_TSBID(0, i), &io_attrs, &ra); if (ret == HV_EOK) { - if (page_in_phys_avail(ra)) { - pci_sun4v_iommu_demap(devhandle, - HV_PCI_TSBID(0, i), 1); - } else { - cnt++; - __set_bit(i, arena->map); - } + cnt++; + __set_bit(i, arena->map); } } @@ -1003,18 +993,13 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm, static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) { struct pci_iommu *iommu = pbm->iommu; - struct property *prop; unsigned long num_tsb_entries, sz; u32 vdma[2], dma_mask, dma_offset; - int tsbsize; - - prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); - if (prop) { - u32 *val = prop->value; + int err, tsbsize; - vdma[0] = val[0]; - vdma[1] = val[1]; - } else { + err = prom_getproperty(pbm->prom_node, "virtual-dma", + (char *)&vdma[0], sizeof(vdma)); + if (err == 0 || err == -1) { /* No property, use default values. */ vdma[0] = 0x80000000; vdma[1] = 0x80000000; @@ -1066,30 +1051,34 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) iommu->arena.limit = num_tsb_entries; sz = probe_existing_entries(pbm, iommu); - if (sz) - printk("%s: Imported %lu TSB entries from OBP\n", - pbm->name, sz); + + printk("%s: TSB entries [%lu], existing mapings [%lu]\n", + pbm->name, num_tsb_entries, sz); } static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm) { - struct property *prop; - unsigned int *busrange; - - prop = of_find_property(pbm->prom_node, "bus-range", NULL); - - busrange = prop->value; + unsigned int busrange[2]; + int prom_node = pbm->prom_node; + int err; + + err = prom_getproperty(prom_node, "bus-range", + (char *)&busrange[0], + sizeof(busrange)); + if (err == 0 || err == -1) { + prom_printf("%s: Fatal error, no bus-range.\n", pbm->name); + prom_halt(); + } pbm->pci_first_busno = busrange[0]; pbm->pci_last_busno = busrange[1]; } -static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle) +static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 devhandle) { struct pci_pbm_info *pbm; - struct property *prop; - int len, i; + int err, i; if (devhandle & 0x40) pbm = &p->pbm_B; @@ -1097,19 +1086,32 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node pbm = &p->pbm_A; pbm->parent = p; - pbm->prom_node = dp; + pbm->prom_node = prom_node; pbm->pci_first_slot = 1; pbm->devhandle = devhandle; - pbm->name = dp->full_name; + sprintf(pbm->name, "SUN4V-PCI%d PBM%c", + p->index, (pbm == &p->pbm_A ? 'A' : 'B')); - printk("%s: SUN4V PCI Bus Module\n", pbm->name); + printk("%s: devhandle[%x] prom_node[%x:%x]\n", + pbm->name, pbm->devhandle, + pbm->prom_node, prom_getchild(pbm->prom_node)); + + prom_getstring(prom_node, "name", + pbm->prom_name, sizeof(pbm->prom_name)); + + err = prom_getproperty(prom_node, "ranges", + (char *) pbm->pbm_ranges, + sizeof(pbm->pbm_ranges)); + if (err == 0 || err == -1) { + prom_printf("%s: Fatal error, no ranges property.\n", + pbm->name); + prom_halt(); + } - prop = of_find_property(dp, "ranges", &len); - pbm->pbm_ranges = prop->value; pbm->num_pbm_ranges = - (len / sizeof(struct linux_prom_pci_ranges)); + (err / sizeof(struct linux_prom_pci_ranges)); /* Mask out the top 8 bits of the ranges, leaving the real * physical address. @@ -1120,13 +1122,24 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node pci_sun4v_determine_mem_io_space(pbm); pbm_register_toplevel_resources(p, pbm); - prop = of_find_property(dp, "interrupt-map", &len); - pbm->pbm_intmap = prop->value; - pbm->num_pbm_intmap = - (len / sizeof(struct linux_prom_pci_intmap)); + err = prom_getproperty(prom_node, "interrupt-map", + (char *)pbm->pbm_intmap, + sizeof(pbm->pbm_intmap)); + if (err == 0 || err == -1) { + prom_printf("%s: Fatal error, no interrupt-map property.\n", + pbm->name); + prom_halt(); + } - prop = of_find_property(dp, "interrupt-map-mask", NULL); - pbm->pbm_intmask = prop->value; + pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); + err = prom_getproperty(prom_node, "interrupt-map-mask", + (char *)&pbm->pbm_intmask, + sizeof(pbm->pbm_intmask)); + if (err == 0 || err == -1) { + prom_printf("%s: Fatal error, no interrupt-map-mask.\n", + pbm->name); + prom_halt(); + } pci_sun4v_get_bus_range(pbm); pci_sun4v_iommu_init(pbm); @@ -1134,19 +1147,16 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node pdev_htab_populate(pbm); } -void sun4v_pci_init(struct device_node *dp, char *model_name) +void sun4v_pci_init(int node, char *model_name) { struct pci_controller_info *p; struct pci_iommu *iommu; - struct property *prop; - struct linux_prom64_registers *regs; + struct linux_prom64_registers regs; u32 devhandle; int i; - prop = of_find_property(dp, "reg", NULL); - regs = prop->value; - - devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; + prom_getproperty(node, "reg", (char *)®s, sizeof(regs)); + devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff; for (p = pci_controller_root; p; p = p->next) { struct pci_pbm_info *pbm; @@ -1159,7 +1169,7 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) &p->pbm_B); if (pbm->devhandle == (devhandle ^ 0x40)) { - pci_sun4v_pbm_init(p, dp, devhandle); + pci_sun4v_pbm_init(p, node, devhandle); return; } } @@ -1210,7 +1220,7 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) */ pci_memspace_mask = 0x7fffffffUL; - pci_sun4v_pbm_init(p, dp, devhandle); + pci_sun4v_pbm_init(p, node, devhandle); return; fatal_memory_error: diff --git a/trunk/arch/sparc64/kernel/power.c b/trunk/arch/sparc64/kernel/power.c index 9496c7734014..30bcaf58e3ab 100644 --- a/trunk/arch/sparc64/kernel/power.c +++ b/trunk/arch/sparc64/kernel/power.c @@ -105,25 +105,76 @@ static int powerd(void *__unused) return 0; } -static int __init has_button_interrupt(unsigned int irq, struct device_node *dp) +static int __init has_button_interrupt(unsigned int irq, int prom_node) { if (irq == PCI_IRQ_NONE) return 0; - if (!of_find_property(dp, "button", NULL)) + if (!prom_node_has_property(prom_node, "button")) return 0; return 1; } -static void __devinit power_probe_common(struct of_device *dev, struct resource *res, unsigned int irq) +static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, int *prom_node_p) { - power_reg = ioremap(res->start, 0x4); + struct linux_ebus *ebus; + struct linux_ebus_device *edev; + + for_each_ebus(ebus) { + for_each_ebusdev(edev, ebus) { + if (!strcmp(edev->prom_name, "power")) { + *resp = &edev->resource[0]; + *irq_p = edev->irqs[0]; + *prom_node_p = edev->prom_node; + return 0; + } + } + } + return -ENODEV; +} - printk("power: Control reg at %p ... ", power_reg); +static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, int *prom_node_p) +{ + struct sparc_isa_bridge *isa_bus; + struct sparc_isa_device *isa_dev; + + for_each_isa(isa_bus) { + for_each_isadev(isa_dev, isa_bus) { + if (!strcmp(isa_dev->prom_name, "power")) { + *resp = &isa_dev->resource; + *irq_p = isa_dev->irq; + *prom_node_p = isa_dev->prom_node; + return 0; + } + } + } + return -ENODEV; +} - poweroff_method = machine_halt; /* able to use the standard halt */ +void __init power_init(void) +{ + struct resource *res = NULL; + unsigned int irq; + int prom_node; + static int invoked; + + if (invoked) + return; + invoked = 1; + + if (!power_probe_ebus(&res, &irq, &prom_node)) + goto found; - if (has_button_interrupt(irq, dev->node)) { + if (!power_probe_isa(&res, &irq, &prom_node)) + goto found; + + return; + +found: + power_reg = ioremap(res->start, 0x4); + printk("power: Control reg at %p ... ", power_reg); + poweroff_method = machine_halt; /* able to use the standard halt */ + if (has_button_interrupt(irq, prom_node)) { if (kernel_thread(powerd, NULL, CLONE_FS) < 0) { printk("Failed to start power daemon.\n"); return; @@ -137,52 +188,4 @@ static void __devinit power_probe_common(struct of_device *dev, struct resource printk("not using powerd.\n"); } } - -static struct of_device_id power_match[] = { - { - .name = "power", - }, - {}, -}; - -static int __devinit ebus_power_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct linux_ebus_device *edev = to_ebus_device(&dev->dev); - struct resource *res = &edev->resource[0]; - unsigned int irq = edev->irqs[0]; - - power_probe_common(dev, res,irq); - - return 0; -} - -static struct of_platform_driver ebus_power_driver = { - .name = "power", - .match_table = power_match, - .probe = ebus_power_probe, -}; - -static int __devinit isa_power_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct sparc_isa_device *idev = to_isa_device(&dev->dev); - struct resource *res = &idev->resource; - unsigned int irq = idev->irq; - - power_probe_common(dev, res,irq); - - return 0; -} - -static struct of_platform_driver isa_power_driver = { - .name = "power", - .match_table = power_match, - .probe = isa_power_probe, -}; - -void __init power_init(void) -{ - of_register_driver(&ebus_power_driver, &ebus_bus_type); - of_register_driver(&isa_power_driver, &isa_bus_type); - return; -} #endif /* CONFIG_PCI */ diff --git a/trunk/arch/sparc64/kernel/prom.c b/trunk/arch/sparc64/kernel/prom.c deleted file mode 100644 index e9d703eea806..000000000000 --- a/trunk/arch/sparc64/kernel/prom.c +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Procedures for creating, accessing and interpreting the device tree. - * - * Paul Mackerras August 1996. - * Copyright (C) 1996-2005 Paul Mackerras. - * - * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. - * {engebret|bergner}@us.ibm.com - * - * Adapted for sparc64 by David S. Miller davem@davemloft.net - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -static struct device_node *allnodes; - -int of_device_is_compatible(struct device_node *device, const char *compat) -{ - const char* cp; - int cplen, l; - - cp = (char *) of_get_property(device, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - if (strncmp(cp, compat, strlen(compat)) == 0) - return 1; - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - - return 0; -} -EXPORT_SYMBOL(of_device_is_compatible); - -struct device_node *of_get_parent(const struct device_node *node) -{ - struct device_node *np; - - if (!node) - return NULL; - - np = node->parent; - - return np; -} -EXPORT_SYMBOL(of_get_parent); - -struct device_node *of_get_next_child(const struct device_node *node, - struct device_node *prev) -{ - struct device_node *next; - - next = prev ? prev->sibling : node->child; - for (; next != 0; next = next->sibling) { - break; - } - - return next; -} -EXPORT_SYMBOL(of_get_next_child); - -struct device_node *of_find_node_by_path(const char *path) -{ - struct device_node *np = allnodes; - - for (; np != 0; np = np->allnext) { - if (np->full_name != 0 && strcmp(np->full_name, path) == 0) - break; - } - - return np; -} -EXPORT_SYMBOL(of_find_node_by_path); - -struct device_node *of_find_node_by_phandle(phandle handle) -{ - struct device_node *np; - - for (np = allnodes; np != 0; np = np->allnext) - if (np->node == handle) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_phandle); - -struct device_node *of_find_node_by_name(struct device_node *from, - const char *name) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != NULL; np = np->allnext) - if (np->name != NULL && strcmp(np->name, name) == 0) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_name); - -struct device_node *of_find_node_by_type(struct device_node *from, - const char *type) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) - if (np->type != 0 && strcmp(np->type, type) == 0) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_type); - -struct device_node *of_find_compatible_node(struct device_node *from, - const char *type, const char *compatible) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) { - if (type != NULL - && !(np->type != 0 && strcmp(np->type, type) == 0)) - continue; - if (of_device_is_compatible(np, compatible)) - break; - } - - return np; -} -EXPORT_SYMBOL(of_find_compatible_node); - -struct property *of_find_property(struct device_node *np, const char *name, - int *lenp) -{ - struct property *pp; - - for (pp = np->properties; pp != 0; pp = pp->next) { - if (strcmp(pp->name, name) == 0) { - if (lenp != 0) - *lenp = pp->length; - break; - } - } - return pp; -} -EXPORT_SYMBOL(of_find_property); - -/* - * Find a property with a given name for a given node - * and return the value. - */ -void *of_get_property(struct device_node *np, const char *name, int *lenp) -{ - struct property *pp = of_find_property(np,name,lenp); - return pp ? pp->value : NULL; -} -EXPORT_SYMBOL(of_get_property); - -int of_getintprop_default(struct device_node *np, const char *name, int def) -{ - struct property *prop; - int len; - - prop = of_find_property(np, name, &len); - if (!prop || len != 4) - return def; - - return *(int *) prop->value; -} -EXPORT_SYMBOL(of_getintprop_default); - -static unsigned int prom_early_allocated; - -static void * __init prom_early_alloc(unsigned long size) -{ - void *ret; - - ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); - if (ret != NULL) - memset(ret, 0, size); - - prom_early_allocated += size; - - return ret; -} - -static int is_root_node(const struct device_node *dp) -{ - if (!dp) - return 0; - - return (dp->parent == NULL); -} - -/* The following routines deal with the black magic of fully naming a - * node. - * - * Certain well known named nodes are just the simple name string. - * - * Actual devices have an address specifier appended to the base name - * string, like this "foo@addr". The "addr" can be in any number of - * formats, and the platform plus the type of the node determine the - * format and how it is constructed. - * - * For children of the ROOT node, the naming convention is fixed and - * determined by whether this is a sun4u or sun4v system. - * - * For children of other nodes, it is bus type specific. So - * we walk up the tree until we discover a "device_type" property - * we recognize and we go from there. - * - * As an example, the boot device on my workstation has a full path: - * - * /pci@1e,600000/ide@d/disk@0,0:c - */ -static void __init sun4v_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom64_registers *regs; - struct property *rprop; - u32 high_bits, low_bits, type; - - rprop = of_find_property(dp, "reg", NULL); - if (!rprop) - return; - - regs = rprop->value; - if (!is_root_node(dp->parent)) { - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - (unsigned int) (regs->phys_addr >> 32UL), - (unsigned int) (regs->phys_addr & 0xffffffffUL)); - return; - } - - type = regs->phys_addr >> 60UL; - high_bits = (regs->phys_addr >> 32UL) & 0x0fffffffUL; - low_bits = (regs->phys_addr & 0xffffffffUL); - - if (type == 0 || type == 8) { - const char *prefix = (type == 0) ? "m" : "i"; - - if (low_bits) - sprintf(tmp_buf, "%s@%s%x,%x", - dp->name, prefix, - high_bits, low_bits); - else - sprintf(tmp_buf, "%s@%s%x", - dp->name, - prefix, - high_bits); - } else if (type == 12) { - sprintf(tmp_buf, "%s@%x", - dp->name, high_bits); - } -} - -static void __init sun4u_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom64_registers *regs; - struct property *prop; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - if (!is_root_node(dp->parent)) { - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - (unsigned int) (regs->phys_addr >> 32UL), - (unsigned int) (regs->phys_addr & 0xffffffffUL)); - return; - } - - prop = of_find_property(dp, "upa-portid", NULL); - if (!prop) - prop = of_find_property(dp, "portid", NULL); - if (prop) { - unsigned long mask = 0xffffffffUL; - - if (tlb_type >= cheetah) - mask = 0x7fffff; - - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - *(u32 *)prop->value, - (unsigned int) (regs->phys_addr & mask)); - } -} - -/* "name@slot,offset" */ -static void __init sbus_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom_registers *regs; - struct property *prop; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - regs->which_io, - regs->phys_addr); -} - -/* "name@devnum[,func]" */ -static void __init pci_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom_pci_registers *regs; - struct property *prop; - unsigned int devfn; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - devfn = (regs->phys_hi >> 8) & 0xff; - if (devfn & 0x07) { - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - devfn >> 3, - devfn & 0x07); - } else { - sprintf(tmp_buf, "%s@%x", - dp->name, - devfn >> 3); - } -} - -/* "name@UPA_PORTID,offset" */ -static void __init upa_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom64_registers *regs; - struct property *prop; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - - prop = of_find_property(dp, "upa-portid", NULL); - if (!prop) - return; - - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - *(u32 *) prop->value, - (unsigned int) (regs->phys_addr & 0xffffffffUL)); -} - -/* "name@reg" */ -static void __init vdev_path_component(struct device_node *dp, char *tmp_buf) -{ - struct property *prop; - u32 *regs; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - - sprintf(tmp_buf, "%s@%x", dp->name, *regs); -} - -/* "name@addrhi,addrlo" */ -static void __init ebus_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom64_registers *regs; - struct property *prop; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - (unsigned int) (regs->phys_addr >> 32UL), - (unsigned int) (regs->phys_addr & 0xffffffffUL)); -} - -/* "name@bus,addr" */ -static void __init i2c_path_component(struct device_node *dp, char *tmp_buf) -{ - struct property *prop; - u32 *regs; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - - /* This actually isn't right... should look at the #address-cells - * property of the i2c bus node etc. etc. - */ - sprintf(tmp_buf, "%s@%x,%x", - dp->name, regs[0], regs[1]); -} - -/* "name@reg0[,reg1]" */ -static void __init usb_path_component(struct device_node *dp, char *tmp_buf) -{ - struct property *prop; - u32 *regs; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - - if (prop->length == sizeof(u32) || regs[1] == 1) { - sprintf(tmp_buf, "%s@%x", - dp->name, regs[0]); - } else { - sprintf(tmp_buf, "%s@%x,%x", - dp->name, regs[0], regs[1]); - } -} - -/* "name@reg0reg1[,reg2reg3]" */ -static void __init ieee1394_path_component(struct device_node *dp, char *tmp_buf) -{ - struct property *prop; - u32 *regs; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - - if (regs[2] || regs[3]) { - sprintf(tmp_buf, "%s@%08x%08x,%04x%08x", - dp->name, regs[0], regs[1], regs[2], regs[3]); - } else { - sprintf(tmp_buf, "%s@%08x%08x", - dp->name, regs[0], regs[1]); - } -} - -static void __init __build_path_component(struct device_node *dp, char *tmp_buf) -{ - struct device_node *parent = dp->parent; - - if (parent != NULL) { - if (!strcmp(parent->type, "pci") || - !strcmp(parent->type, "pciex")) - return pci_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "sbus")) - return sbus_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "upa")) - return upa_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "ebus")) - return ebus_path_component(dp, tmp_buf); - if (!strcmp(parent->name, "usb") || - !strcmp(parent->name, "hub")) - return usb_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "i2c")) - return i2c_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "firewire")) - return ieee1394_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "virtual-devices")) - return vdev_path_component(dp, tmp_buf); - - /* "isa" is handled with platform naming */ - } - - /* Use platform naming convention. */ - if (tlb_type == hypervisor) - return sun4v_path_component(dp, tmp_buf); - else - return sun4u_path_component(dp, tmp_buf); -} - -static char * __init build_path_component(struct device_node *dp) -{ - char tmp_buf[64], *n; - - tmp_buf[0] = '\0'; - __build_path_component(dp, tmp_buf); - if (tmp_buf[0] == '\0') - strcpy(tmp_buf, dp->name); - - n = prom_early_alloc(strlen(tmp_buf) + 1); - strcpy(n, tmp_buf); - - return n; -} - -static char * __init build_full_name(struct device_node *dp) -{ - int len, ourlen, plen; - char *n; - - plen = strlen(dp->parent->full_name); - ourlen = strlen(dp->path_component_name); - len = ourlen + plen + 2; - - n = prom_early_alloc(len); - strcpy(n, dp->parent->full_name); - if (!is_root_node(dp->parent)) { - strcpy(n + plen, "/"); - plen++; - } - strcpy(n + plen, dp->path_component_name); - - return n; -} - -static struct property * __init build_one_prop(phandle node, char *prev) -{ - static struct property *tmp = NULL; - struct property *p; - - if (tmp) { - p = tmp; - memset(p, 0, sizeof(*p) + 32); - tmp = NULL; - } else - p = prom_early_alloc(sizeof(struct property) + 32); - - p->name = (char *) (p + 1); - if (prev == NULL) { - prom_firstprop(node, p->name); - } else { - prom_nextprop(node, prev, p->name); - } - if (strlen(p->name) == 0) { - tmp = p; - return NULL; - } - p->length = prom_getproplen(node, p->name); - if (p->length <= 0) { - p->length = 0; - } else { - p->value = prom_early_alloc(p->length); - prom_getproperty(node, p->name, p->value, p->length); - } - return p; -} - -static struct property * __init build_prop_list(phandle node) -{ - struct property *head, *tail; - - head = tail = build_one_prop(node, NULL); - while(tail) { - tail->next = build_one_prop(node, tail->name); - tail = tail->next; - } - - return head; -} - -static char * __init get_one_property(phandle node, const char *name) -{ - char *buf = ""; - int len; - - len = prom_getproplen(node, name); - if (len > 0) { - buf = prom_early_alloc(len); - prom_getproperty(node, name, buf, len); - } - - return buf; -} - -static struct device_node * __init create_node(phandle node) -{ - struct device_node *dp; - - if (!node) - return NULL; - - dp = prom_early_alloc(sizeof(*dp)); - - kref_init(&dp->kref); - - dp->name = get_one_property(node, "name"); - dp->type = get_one_property(node, "device_type"); - dp->node = node; - - /* Build interrupts later... */ - - dp->properties = build_prop_list(node); - - return dp; -} - -static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp) -{ - struct device_node *dp; - - dp = create_node(node); - if (dp) { - *(*nextp) = dp; - *nextp = &dp->allnext; - - dp->parent = parent; - dp->path_component_name = build_path_component(dp); - dp->full_name = build_full_name(dp); - - dp->child = build_tree(dp, prom_getchild(node), nextp); - - dp->sibling = build_tree(parent, prom_getsibling(node), nextp); - } - - return dp; -} - -void __init prom_build_devicetree(void) -{ - struct device_node **nextp; - - allnodes = create_node(prom_root_node); - allnodes->path_component_name = ""; - allnodes->full_name = "/"; - - nextp = &allnodes->allnext; - allnodes->child = build_tree(allnodes, - prom_getchild(allnodes->node), - &nextp); - printk("PROM: Built device tree with %u bytes of memory.\n", - prom_early_allocated); -} diff --git a/trunk/arch/sparc64/kernel/sbus.c b/trunk/arch/sparc64/kernel/sbus.c index ac05e0f692ef..8812417247d4 100644 --- a/trunk/arch/sparc64/kernel/sbus.c +++ b/trunk/arch/sparc64/kernel/sbus.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include "iommu_common.h" @@ -1099,25 +1098,24 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus) } /* Boot time initialization. */ -static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) +void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus) { - struct linux_prom64_registers *pr; - struct device_node *dp; + struct linux_prom64_registers rprop; struct sbus_iommu *iommu; unsigned long regs, tsb_base; u64 control; - int i; - - dp = of_find_node_by_phandle(__node); + int err, i; - sbus->portid = of_getintprop_default(dp, "upa-portid", -1); + sbus->portid = prom_getintdefault(sbus->prom_node, + "upa-portid", -1); - pr = of_get_property(dp, "reg", NULL); - if (!pr) { + err = prom_getproperty(prom_node, "reg", + (char *)&rprop, sizeof(rprop)); + if (err < 0) { prom_printf("sbus_iommu_init: Cannot map SYSIO control registers.\n"); prom_halt(); } - regs = pr->phys_addr; + regs = rprop.phys_addr; iommu = kmalloc(sizeof(*iommu) + SMP_CACHE_BYTES, GFP_ATOMIC); if (iommu == NULL) { @@ -1227,50 +1225,3 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) sysio_register_error_handlers(sbus); } - -void sbus_fill_device_irq(struct sbus_dev *sdev) -{ - struct device_node *dp = of_find_node_by_phandle(sdev->prom_node); - struct linux_prom_irqs *irqs; - - irqs = of_get_property(dp, "interrupts", NULL); - if (!irqs) { - sdev->irqs[0] = 0; - sdev->num_irqs = 0; - } else { - unsigned int pri = irqs[0].pri; - - sdev->num_irqs = 1; - if (pri < 0x20) - pri += sdev->slot * 8; - - sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); - } -} - -void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) -{ -} - -void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) -{ - sbus_iommu_init(dp->node, sbus); -} - -void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp) -{ -} - -int __init sbus_arch_preinit(void) -{ - return 0; -} - -void __init sbus_arch_postinit(void) -{ - extern void firetruck_init(void); - extern void clock_probe(void); - - firetruck_init(); - clock_probe(); -} diff --git a/trunk/arch/sparc64/kernel/setup.c b/trunk/arch/sparc64/kernel/setup.c index a6a7d8168346..9cf1c88cd774 100644 --- a/trunk/arch/sparc64/kernel/setup.c +++ b/trunk/arch/sparc64/kernel/setup.c @@ -376,12 +376,12 @@ void __init setup_arch(char **cmdline_p) } #endif + smp_setup_cpu_possible_map(); + /* Get boot processor trap_block[] setup. */ init_cur_cpu_trap(current_thread_info()); paging_init(); - - smp_setup_cpu_possible_map(); } static int __init set_preferred_console(void) diff --git a/trunk/arch/sparc64/kernel/smp.c b/trunk/arch/sparc64/kernel/smp.c index f62bf3a2de1a..f03d52d0b88d 100644 --- a/trunk/arch/sparc64/kernel/smp.c +++ b/trunk/arch/sparc64/kernel/smp.c @@ -39,7 +39,6 @@ #include #include #include -#include extern void calibrate_delay(void); @@ -77,42 +76,41 @@ void smp_bogo(struct seq_file *m) void __init smp_store_cpu_info(int id) { - struct device_node *dp; - int def; + int cpu_node, def; /* multiplier and counter set by smp_setup_percpu_timer() */ cpu_data(id).udelay_val = loops_per_jiffy; - cpu_find_by_mid(id, &dp); - cpu_data(id).clock_tick = - of_getintprop_default(dp, "clock-frequency", 0); + cpu_find_by_mid(id, &cpu_node); + cpu_data(id).clock_tick = prom_getintdefault(cpu_node, + "clock-frequency", 0); def = ((tlb_type == hypervisor) ? (8 * 1024) : (16 * 1024)); - cpu_data(id).dcache_size = - of_getintprop_default(dp, "dcache-size", def); + cpu_data(id).dcache_size = prom_getintdefault(cpu_node, "dcache-size", + def); def = 32; cpu_data(id).dcache_line_size = - of_getintprop_default(dp, "dcache-line-size", def); + prom_getintdefault(cpu_node, "dcache-line-size", def); def = 16 * 1024; - cpu_data(id).icache_size = - of_getintprop_default(dp, "icache-size", def); + cpu_data(id).icache_size = prom_getintdefault(cpu_node, "icache-size", + def); def = 32; cpu_data(id).icache_line_size = - of_getintprop_default(dp, "icache-line-size", def); + prom_getintdefault(cpu_node, "icache-line-size", def); def = ((tlb_type == hypervisor) ? (3 * 1024 * 1024) : (4 * 1024 * 1024)); - cpu_data(id).ecache_size = - of_getintprop_default(dp, "ecache-size", def); + cpu_data(id).ecache_size = prom_getintdefault(cpu_node, "ecache-size", + def); def = 64; cpu_data(id).ecache_line_size = - of_getintprop_default(dp, "ecache-line-size", def); + prom_getintdefault(cpu_node, "ecache-line-size", def); printk("CPU[%d]: Caches " "D[sz(%d):line_sz(%d)] " @@ -344,10 +342,10 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu) prom_startcpu_cpuid(cpu, entry, cookie); } else { - struct device_node *dp; + int cpu_node; - cpu_find_by_mid(cpu, &dp); - prom_startcpu(dp->node, entry, cookie); + cpu_find_by_mid(cpu, &cpu_node); + prom_startcpu(cpu_node, entry, cookie); } for (timeout = 0; timeout < 5000000; timeout++) { @@ -1291,8 +1289,7 @@ int setup_profiling_timer(unsigned int multiplier) static void __init smp_tune_scheduling(void) { - struct device_node *dp; - int instance; + int instance, node; unsigned int def, smallest = ~0U; def = ((tlb_type == hypervisor) ? @@ -1300,10 +1297,10 @@ static void __init smp_tune_scheduling(void) (4 * 1024 * 1024)); instance = 0; - while (!cpu_find_by_instance(instance, &dp, NULL)) { + while (!cpu_find_by_instance(instance, &node, NULL)) { unsigned int val; - val = of_getintprop_default(dp, "ecache-size", def); + val = prom_getintdefault(node, "ecache-size", def); if (val < smallest) smallest = val; diff --git a/trunk/arch/sparc64/kernel/time.c b/trunk/arch/sparc64/kernel/time.c index 348b82035561..0f00a99927e9 100644 --- a/trunk/arch/sparc64/kernel/time.c +++ b/trunk/arch/sparc64/kernel/time.c @@ -48,7 +48,6 @@ #include #include #include -#include DEFINE_SPINLOCK(mostek_lock); DEFINE_SPINLOCK(rtc_lock); @@ -756,200 +755,24 @@ static int hypervisor_set_time(u32 secs) return -EOPNOTSUPP; } -static int __init clock_model_matches(char *model) -{ - if (strcmp(model, "mk48t02") && - strcmp(model, "mk48t08") && - strcmp(model, "mk48t59") && - strcmp(model, "m5819") && - strcmp(model, "m5819p") && - strcmp(model, "m5823") && - strcmp(model, "ds1287")) - return 0; - - return 1; -} - -static void __init __clock_assign_common(void __iomem *addr, char *model) -{ - if (model[5] == '0' && model[6] == '2') { - mstk48t02_regs = addr; - } else if(model[5] == '0' && model[6] == '8') { - mstk48t08_regs = addr; - mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; - } else { - mstk48t59_regs = addr; - mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; - } -} - -static void __init clock_assign_clk_reg(struct linux_prom_registers *clk_reg, - char *model) -{ - unsigned long addr; - - addr = ((unsigned long) clk_reg[0].phys_addr | - (((unsigned long) clk_reg[0].which_io) << 32UL)); - - __clock_assign_common((void __iomem *) addr, model); -} - -static int __init clock_probe_central(void) +void __init clock_probe(void) { - struct linux_prom_registers clk_reg[2], *pr; - struct device_node *dp; - char *model; - - if (!central_bus) - return 0; - - /* Get Central FHC's prom node. */ - dp = central_bus->child->prom_node; - - /* Then get the first child device below it. */ - dp = dp->child; - - while (dp) { - model = of_get_property(dp, "model", NULL); - if (!model || !clock_model_matches(model)) - goto next_sibling; - - pr = of_get_property(dp, "reg", NULL); - memcpy(clk_reg, pr, sizeof(clk_reg)); - - apply_fhc_ranges(central_bus->child, clk_reg, 1); - apply_central_ranges(central_bus, clk_reg, 1); - - clock_assign_clk_reg(clk_reg, model); - return 1; - - next_sibling: - dp = dp->sibling; - } - - return 0; -} - + struct linux_prom_registers clk_reg[2]; + char model[128]; + int node, busnd = -1, err; + unsigned long flags; + struct linux_central *cbus; #ifdef CONFIG_PCI -static void __init clock_isa_ebus_assign_regs(struct resource *res, char *model) -{ - if (!strcmp(model, "ds1287") || - !strcmp(model, "m5819") || - !strcmp(model, "m5819p") || - !strcmp(model, "m5823")) { - ds1287_regs = res->start; - } else { - mstk48t59_regs = (void __iomem *) res->start; - mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; - } -} - -static int __init clock_probe_one_ebus_dev(struct linux_ebus_device *edev) -{ - struct device_node *dp = edev->prom_node; - char *model; - - model = of_get_property(dp, "model", NULL); - if (!clock_model_matches(model)) - return 0; - - clock_isa_ebus_assign_regs(&edev->resource[0], model); - - return 1; -} - -static int __init clock_probe_ebus(void) -{ - struct linux_ebus *ebus; - - for_each_ebus(ebus) { - struct linux_ebus_device *edev; - - for_each_ebusdev(edev, ebus) { - if (clock_probe_one_ebus_dev(edev)) - return 1; - } - } - - return 0; -} - -static int __init clock_probe_one_isa_dev(struct sparc_isa_device *idev) -{ - struct device_node *dp = idev->prom_node; - char *model; - - model = of_get_property(dp, "model", NULL); - if (!clock_model_matches(model)) - return 0; - - clock_isa_ebus_assign_regs(&idev->resource, model); - - return 1; -} - -static int __init clock_probe_isa(void) -{ - struct sparc_isa_bridge *isa_br; - - for_each_isa(isa_br) { - struct sparc_isa_device *isa_dev; - - for_each_isadev(isa_dev, isa_br) { - if (clock_probe_one_isa_dev(isa_dev)) - return 1; - } - } - - return 0; -} -#endif /* CONFIG_PCI */ - -#ifdef CONFIG_SBUS -static int __init clock_probe_one_sbus_dev(struct sbus_bus *sbus, struct sbus_dev *sdev) -{ - struct resource *res; - char model[64]; - void __iomem *addr; - - prom_getstring(sdev->prom_node, "model", model, sizeof(model)); - if (!clock_model_matches(model)) - return 0; - - res = &sdev->resource[0]; - addr = sbus_ioremap(res, 0, 0x800UL, "eeprom"); - - __clock_assign_common(addr, model); - - return 1; -} - -static int __init clock_probe_sbus(void) -{ - struct sbus_bus *sbus; - - for_each_sbus(sbus) { - struct sbus_dev *sdev; - - for_each_sbusdev(sdev, sbus) { - if (clock_probe_one_sbus_dev(sbus, sdev)) - return 1; - } - } - - return 0; -} + struct linux_ebus *ebus = NULL; + struct sparc_isa_bridge *isa_br = NULL; #endif - -void __init clock_probe(void) -{ static int invoked; - unsigned long flags; if (invoked) return; invoked = 1; + if (this_is_starfire) { xtime.tv_sec = starfire_get_time(); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); @@ -965,26 +788,182 @@ void __init clock_probe(void) return; } + local_irq_save(flags); + + cbus = central_bus; + if (cbus != NULL) + busnd = central_bus->child->prom_node; + /* Check FHC Central then EBUSs then ISA bridges then SBUSs. * That way we handle the presence of multiple properly. * * As a special case, machines with Central must provide the * timer chip there. */ - if (!clock_probe_central() && #ifdef CONFIG_PCI - !clock_probe_ebus() && - !clock_probe_isa() && -#endif -#ifdef CONFIG_SBUS - !clock_probe_sbus() + if (ebus_chain != NULL) { + ebus = ebus_chain; + if (busnd == -1) + busnd = ebus->prom_node; + } + if (isa_chain != NULL) { + isa_br = isa_chain; + if (busnd == -1) + busnd = isa_br->prom_node; + } #endif - ) { - printk(KERN_WARNING "No clock chip found.\n"); - return; + if (sbus_root != NULL && busnd == -1) + busnd = sbus_root->prom_node; + + if (busnd == -1) { + prom_printf("clock_probe: problem, cannot find bus to search.\n"); + prom_halt(); } - local_irq_save(flags); + node = prom_getchild(busnd); + + while (1) { + if (!node) + model[0] = 0; + else + prom_getstring(node, "model", model, sizeof(model)); + if (strcmp(model, "mk48t02") && + strcmp(model, "mk48t08") && + strcmp(model, "mk48t59") && + strcmp(model, "m5819") && + strcmp(model, "m5819p") && + strcmp(model, "m5823") && + strcmp(model, "ds1287")) { + if (cbus != NULL) { + prom_printf("clock_probe: Central bus lacks timer chip.\n"); + prom_halt(); + } + + if (node != 0) + node = prom_getsibling(node); +#ifdef CONFIG_PCI + while ((node == 0) && ebus != NULL) { + ebus = ebus->next; + if (ebus != NULL) { + busnd = ebus->prom_node; + node = prom_getchild(busnd); + } + } + while ((node == 0) && isa_br != NULL) { + isa_br = isa_br->next; + if (isa_br != NULL) { + busnd = isa_br->prom_node; + node = prom_getchild(busnd); + } + } +#endif + if (node == 0) { + prom_printf("clock_probe: Cannot find timer chip\n"); + prom_halt(); + } + continue; + } + + err = prom_getproperty(node, "reg", (char *)clk_reg, + sizeof(clk_reg)); + if(err == -1) { + prom_printf("clock_probe: Cannot get Mostek reg property\n"); + prom_halt(); + } + + if (cbus != NULL) { + apply_fhc_ranges(central_bus->child, clk_reg, 1); + apply_central_ranges(central_bus, clk_reg, 1); + } +#ifdef CONFIG_PCI + else if (ebus != NULL) { + struct linux_ebus_device *edev; + + for_each_ebusdev(edev, ebus) + if (edev->prom_node == node) + break; + if (edev == NULL) { + if (isa_chain != NULL) + goto try_isa_clock; + prom_printf("%s: Mostek not probed by EBUS\n", + __FUNCTION__); + prom_halt(); + } + + if (!strcmp(model, "ds1287") || + !strcmp(model, "m5819") || + !strcmp(model, "m5819p") || + !strcmp(model, "m5823")) { + ds1287_regs = edev->resource[0].start; + } else { + mstk48t59_regs = (void __iomem *) + edev->resource[0].start; + mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; + } + break; + } + else if (isa_br != NULL) { + struct sparc_isa_device *isadev; + +try_isa_clock: + for_each_isadev(isadev, isa_br) + if (isadev->prom_node == node) + break; + if (isadev == NULL) { + prom_printf("%s: Mostek not probed by ISA\n"); + prom_halt(); + } + if (!strcmp(model, "ds1287") || + !strcmp(model, "m5819") || + !strcmp(model, "m5819p") || + !strcmp(model, "m5823")) { + ds1287_regs = isadev->resource.start; + } else { + mstk48t59_regs = (void __iomem *) + isadev->resource.start; + mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; + } + break; + } +#endif + else { + if (sbus_root->num_sbus_ranges) { + int nranges = sbus_root->num_sbus_ranges; + int rngc; + + for (rngc = 0; rngc < nranges; rngc++) + if (clk_reg[0].which_io == + sbus_root->sbus_ranges[rngc].ot_child_space) + break; + if (rngc == nranges) { + prom_printf("clock_probe: Cannot find ranges for " + "clock regs.\n"); + prom_halt(); + } + clk_reg[0].which_io = + sbus_root->sbus_ranges[rngc].ot_parent_space; + clk_reg[0].phys_addr += + sbus_root->sbus_ranges[rngc].ot_parent_base; + } + } + + if(model[5] == '0' && model[6] == '2') { + mstk48t02_regs = (void __iomem *) + (((u64)clk_reg[0].phys_addr) | + (((u64)clk_reg[0].which_io)<<32UL)); + } else if(model[5] == '0' && model[6] == '8') { + mstk48t08_regs = (void __iomem *) + (((u64)clk_reg[0].phys_addr) | + (((u64)clk_reg[0].which_io)<<32UL)); + mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; + } else { + mstk48t59_regs = (void __iomem *) + (((u64)clk_reg[0].phys_addr) | + (((u64)clk_reg[0].which_io)<<32UL)); + mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; + } + break; + } if (mstk48t02_regs != NULL) { /* Report a low battery voltage condition. */ @@ -1004,14 +983,12 @@ void __init clock_probe(void) /* This is gets the master TICK_INT timer going. */ static unsigned long sparc64_init_timers(void) { - struct device_node *dp; - struct property *prop; unsigned long clock; + int node; #ifdef CONFIG_SMP extern void smp_tick_init(void); #endif - dp = of_find_node_by_path("/"); if (tlb_type == spitfire) { unsigned long ver, manuf, impl; @@ -1022,17 +999,18 @@ static unsigned long sparc64_init_timers(void) if (manuf == 0x17 && impl == 0x13) { /* Hummingbird, aka Ultra-IIe */ tick_ops = &hbtick_operations; - prop = of_find_property(dp, "stick-frequency", NULL); + node = prom_root_node; + clock = prom_getint(node, "stick-frequency"); } else { tick_ops = &tick_operations; - cpu_find_by_instance(0, &dp, NULL); - prop = of_find_property(dp, "clock-frequency", NULL); + cpu_find_by_instance(0, &node, NULL); + clock = prom_getint(node, "clock-frequency"); } } else { tick_ops = &stick_operations; - prop = of_find_property(dp, "stick-frequency", NULL); + node = prom_root_node; + clock = prom_getint(node, "stick-frequency"); } - clock = *(unsigned int *) prop->value; timer_tick_offset = clock / HZ; #ifdef CONFIG_SMP diff --git a/trunk/arch/sparc64/kernel/traps.c b/trunk/arch/sparc64/kernel/traps.c index 1ff34b019f3f..5059cbd4feee 100644 --- a/trunk/arch/sparc64/kernel/traps.c +++ b/trunk/arch/sparc64/kernel/traps.c @@ -42,7 +42,6 @@ #ifdef CONFIG_KMOD #include #endif -#include ATOMIC_NOTIFIER_HEAD(sparc64die_chain); @@ -808,8 +807,7 @@ extern unsigned int cheetah_deferred_trap_vector[], cheetah_deferred_trap_vector void __init cheetah_ecache_flush_init(void) { unsigned long largest_size, smallest_linesize, order, ver; - struct device_node *dp; - int i, instance, sz; + int node, i, instance; /* Scan all cpu device tree nodes, note two values: * 1) largest E-cache size @@ -819,14 +817,14 @@ void __init cheetah_ecache_flush_init(void) smallest_linesize = ~0UL; instance = 0; - while (!cpu_find_by_instance(instance, &dp, NULL)) { + while (!cpu_find_by_instance(instance, &node, NULL)) { unsigned long val; - val = of_getintprop_default(dp, "ecache-size", - (2 * 1024 * 1024)); + val = prom_getintdefault(node, "ecache-size", + (2 * 1024 * 1024)); if (val > largest_size) largest_size = val; - val = of_getintprop_default(dp, "ecache-line-size", 64); + val = prom_getintdefault(node, "ecache-line-size", 64); if (val < smallest_linesize) smallest_linesize = val; instance++; @@ -851,16 +849,16 @@ void __init cheetah_ecache_flush_init(void) } /* Now allocate error trap reporting scoreboard. */ - sz = NR_CPUS * (2 * sizeof(struct cheetah_err_info)); + node = NR_CPUS * (2 * sizeof(struct cheetah_err_info)); for (order = 0; order < MAX_ORDER; order++) { - if ((PAGE_SIZE << order) >= sz) + if ((PAGE_SIZE << order) >= node) break; } cheetah_error_log = (struct cheetah_err_info *) __get_free_pages(GFP_KERNEL, order); if (!cheetah_error_log) { prom_printf("cheetah_ecache_flush_init: Failed to allocate " - "error logging scoreboard (%d bytes).\n", sz); + "error logging scoreboard (%d bytes).\n", node); prom_halt(); } memset(cheetah_error_log, 0, PAGE_SIZE << order); diff --git a/trunk/arch/sparc64/kernel/unaligned.c b/trunk/arch/sparc64/kernel/unaligned.c index bb2d68577855..001e8518331f 100644 --- a/trunk/arch/sparc64/kernel/unaligned.c +++ b/trunk/arch/sparc64/kernel/unaligned.c @@ -279,21 +279,12 @@ static void kernel_mna_trap_fault(void) asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) { - static unsigned long count, last_time; enum direction dir = decode_direction(insn); int size = decode_access_size(insn); current_thread_info()->kern_una_regs = regs; current_thread_info()->kern_una_insn = insn; - if (jiffies - last_time > 5 * HZ) - count = 0; - if (count < 5) { - last_time = jiffies; - count++; - printk("Kernel unaligned access at TPC[%lx]\n", regs->tpc); - } - if (!ok_for_kernel(insn) || dir == both) { printk("Unsupported unaligned load/store trap for kernel " "at <%016lx>.\n", regs->tpc); diff --git a/trunk/arch/sparc64/mm/init.c b/trunk/arch/sparc64/mm/init.c index 513993414747..1539a8362b6f 100644 --- a/trunk/arch/sparc64/mm/init.c +++ b/trunk/arch/sparc64/mm/init.c @@ -42,7 +42,6 @@ #include #include #include -#include extern void device_scan(void); @@ -102,6 +101,8 @@ static void __init read_obp_memory(const char *property, prom_halt(); } + *num_ents = ents; + /* Sanitize what we got from the firmware, by page aligning * everything. */ @@ -123,25 +124,6 @@ static void __init read_obp_memory(const char *property, regs[i].phys_addr = base; regs[i].reg_size = size; } - - for (i = 0; i < ents; i++) { - if (regs[i].reg_size == 0UL) { - int j; - - for (j = i; j < ents - 1; j++) { - regs[j].phys_addr = - regs[j+1].phys_addr; - regs[j].reg_size = - regs[j+1].reg_size; - } - - ents--; - i--; - } - } - - *num_ents = ents; - sort(regs, ents, sizeof(struct linux_prom64_registers), cmp_p64, NULL); } @@ -1357,8 +1339,6 @@ void __init paging_init(void) kernel_physical_mapping_init(); - prom_build_devicetree(); - { unsigned long zones_size[MAX_NR_ZONES]; unsigned long zholes_size[MAX_NR_ZONES]; @@ -1396,7 +1376,7 @@ static void __init taint_real_pages(void) while (old_start < old_end) { int n; - for (n = 0; n < pavail_rescan_ents; n++) { + for (n = 0; pavail_rescan_ents; n++) { unsigned long new_start, new_end; new_start = pavail_rescan[n].phys_addr; @@ -1418,32 +1398,6 @@ static void __init taint_real_pages(void) } } -int __init page_in_phys_avail(unsigned long paddr) -{ - int i; - - paddr &= PAGE_MASK; - - for (i = 0; i < pavail_rescan_ents; i++) { - unsigned long start, end; - - start = pavail_rescan[i].phys_addr; - end = start + pavail_rescan[i].reg_size; - - if (paddr >= start && paddr < end) - return 1; - } - if (paddr >= kern_base && paddr < (kern_base + kern_size)) - return 1; -#ifdef CONFIG_BLK_DEV_INITRD - if (paddr >= __pa(initrd_start) && - paddr < __pa(PAGE_ALIGN(initrd_end))) - return 1; -#endif - - return 0; -} - void __init mem_init(void) { unsigned long codepages, datapages, initpages; diff --git a/trunk/arch/sparc64/solaris/misc.c b/trunk/arch/sparc64/solaris/misc.c index 719c90905a1e..5284996780a7 100644 --- a/trunk/arch/sparc64/solaris/misc.c +++ b/trunk/arch/sparc64/solaris/misc.c @@ -23,7 +23,6 @@ #include #include #include -#include #include "conv.h" @@ -195,17 +194,14 @@ static char *machine(void) } } -static char *platform(char *buffer, int sz) +static char *platform(char *buffer) { - struct device_node *dp = of_find_node_by_path("/"); int len; *buffer = 0; - len = strlen(dp->name); - if (len > sz) - len = sz; - memcpy(buffer, dp->name, len); - buffer[len] = 0; + len = prom_getproperty(prom_root_node, "name", buffer, 256); + if(len > 0) + buffer[len] = 0; if (*buffer) { char *p; @@ -217,22 +213,16 @@ static char *platform(char *buffer, int sz) return "sun4u"; } -static char *serial(char *buffer, int sz) +static char *serial(char *buffer) { - struct device_node *dp = of_find_node_by_path("/options"); + int node = prom_getchild(prom_root_node); int len; + node = prom_searchsiblings(node, "options"); *buffer = 0; - if (dp) { - char *val = of_get_property(dp, "system-board-serial#", &len); - - if (val && len > 0) { - if (len > sz) - len = sz; - memcpy(buffer, val, len); - buffer[len] = 0; - } - } + len = prom_getproperty(node, "system-board-serial#", buffer, 256); + if(len > 0) + buffer[len] = 0; if (!*buffer) return "4512348717234"; else @@ -315,8 +305,8 @@ asmlinkage int solaris_sysinfo(int cmd, u32 buf, s32 count) case SI_MACHINE: r = machine(); break; case SI_ARCHITECTURE: r = "sparc"; break; case SI_HW_PROVIDER: r = "Sun_Microsystems"; break; - case SI_HW_SERIAL: r = serial(buffer, sizeof(buffer)); break; - case SI_PLATFORM: r = platform(buffer, sizeof(buffer)); break; + case SI_HW_SERIAL: r = serial(buffer); break; + case SI_PLATFORM: r = platform(buffer); break; case SI_SRPC_DOMAIN: r = ""; break; case SI_VERSION: r = "Generic"; break; default: return -EINVAL; diff --git a/trunk/drivers/base/power/Makefile b/trunk/drivers/base/power/Makefile index 91f230939c1e..ceeeba2c56c7 100644 --- a/trunk/drivers/base/power/Makefile +++ b/trunk/drivers/base/power/Makefile @@ -1,6 +1,5 @@ obj-y := shutdown.o obj-$(CONFIG_PM) += main.o suspend.o resume.o runtime.o sysfs.o -obj-$(CONFIG_PM_TRACE) += trace.o ifeq ($(CONFIG_DEBUG_DRIVER),y) EXTRA_CFLAGS += -DDEBUG diff --git a/trunk/drivers/base/power/resume.c b/trunk/drivers/base/power/resume.c index 520679ce53a8..317edbf0feca 100644 --- a/trunk/drivers/base/power/resume.c +++ b/trunk/drivers/base/power/resume.c @@ -9,7 +9,6 @@ */ #include -#include #include "../base.h" #include "power.h" @@ -24,8 +23,6 @@ int resume_device(struct device * dev) { int error = 0; - TRACE_DEVICE(dev); - TRACE_RESUME(0); down(&dev->sem); if (dev->power.pm_parent && dev->power.pm_parent->power.power_state.event) { @@ -39,7 +36,6 @@ int resume_device(struct device * dev) error = dev->bus->resume(dev); } up(&dev->sem); - TRACE_RESUME(error); return error; } diff --git a/trunk/drivers/base/power/trace.c b/trunk/drivers/base/power/trace.c deleted file mode 100644 index a9ab30fefffc..000000000000 --- a/trunk/drivers/base/power/trace.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * drivers/base/power/trace.c - * - * Copyright (C) 2006 Linus Torvalds - * - * Trace facility for suspend/resume problems, when none of the - * devices may be working. - */ - -#include -#include - -#include - -#include "power.h" - -/* - * Horrid, horrid, horrid. - * - * It turns out that the _only_ piece of hardware that actually - * keeps its value across a hard boot (and, more importantly, the - * POST init sequence) is literally the realtime clock. - * - * Never mind that an RTC chip has 114 bytes (and often a whole - * other bank of an additional 128 bytes) of nice SRAM that is - * _designed_ to keep data - the POST will clear it. So we literally - * can just use the few bytes of actual time data, which means that - * we're really limited. - * - * It means, for example, that we can't use the seconds at all - * (since the time between the hang and the boot might be more - * than a minute), and we'd better not depend on the low bits of - * the minutes either. - * - * There are the wday fields etc, but I wouldn't guarantee those - * are dependable either. And if the date isn't valid, either the - * hw or POST will do strange things. - * - * So we're left with: - * - year: 0-99 - * - month: 0-11 - * - day-of-month: 1-28 - * - hour: 0-23 - * - min: (0-30)*2 - * - * Giving us a total range of 0-16128000 (0xf61800), ie less - * than 24 bits of actual data we can save across reboots. - * - * And if your box can't boot in less than three minutes, - * you're screwed. - * - * Now, almost 24 bits of data is pitifully small, so we need - * to be pretty dense if we want to use it for anything nice. - * What we do is that instead of saving off nice readable info, - * we save off _hashes_ of information that we can hopefully - * regenerate after the reboot. - * - * In particular, this means that we might be unlucky, and hit - * a case where we have a hash collision, and we end up not - * being able to tell for certain exactly which case happened. - * But that's hopefully unlikely. - * - * What we do is to take the bits we can fit, and split them - * into three parts (16*997*1009 = 16095568), and use the values - * for: - * - 0-15: user-settable - * - 0-996: file + line number - * - 0-1008: device - */ -#define USERHASH (16) -#define FILEHASH (997) -#define DEVHASH (1009) - -#define DEVSEED (7919) - -static unsigned int dev_hash_value; - -static int set_magic_time(unsigned int user, unsigned int file, unsigned int device) -{ - unsigned int n = user + USERHASH*(file + FILEHASH*device); - - // June 7th, 2006 - static struct rtc_time time = { - .tm_sec = 0, - .tm_min = 0, - .tm_hour = 0, - .tm_mday = 7, - .tm_mon = 5, // June - counting from zero - .tm_year = 106, - .tm_wday = 3, - .tm_yday = 160, - .tm_isdst = 1 - }; - - time.tm_year = (n % 100); - n /= 100; - time.tm_mon = (n % 12); - n /= 12; - time.tm_mday = (n % 28) + 1; - n /= 28; - time.tm_hour = (n % 24); - n /= 24; - time.tm_min = (n % 20) * 3; - n /= 20; - set_rtc_time(&time); - return n ? -1 : 0; -} - -static unsigned int read_magic_time(void) -{ - struct rtc_time time; - unsigned int val; - - get_rtc_time(&time); - printk("Time: %2d:%02d:%02d Date: %02d/%02d/%02d\n", - time.tm_hour, time.tm_min, time.tm_sec, - time.tm_mon, time.tm_mday, time.tm_year); - val = time.tm_year; /* 100 years */ - if (val > 100) - val -= 100; - val += time.tm_mon * 100; /* 12 months */ - val += (time.tm_mday-1) * 100 * 12; /* 28 month-days */ - val += time.tm_hour * 100 * 12 * 28; /* 24 hours */ - val += (time.tm_min / 3) * 100 * 12 * 28 * 24; /* 20 3-minute intervals */ - return val; -} - -/* - * This is just the sdbm hash function with a user-supplied - * seed and final size parameter. - */ -static unsigned int hash_string(unsigned int seed, const char *data, unsigned int mod) -{ - unsigned char c; - while ((c = *data++) != 0) { - seed = (seed << 16) + (seed << 6) - seed + c; - } - return seed % mod; -} - -void set_trace_device(struct device *dev) -{ - dev_hash_value = hash_string(DEVSEED, dev->bus_id, DEVHASH); -} - -/* - * We could just take the "tracedata" index into the .tracedata - * section instead. Generating a hash of the data gives us a - * chance to work across kernel versions, and perhaps more - * importantly it also gives us valid/invalid check (ie we will - * likely not give totally bogus reports - if the hash matches, - * it's not any guarantee, but it's a high _likelihood_ that - * the match is valid). - */ -void generate_resume_trace(void *tracedata, unsigned int user) -{ - unsigned short lineno = *(unsigned short *)tracedata; - const char *file = *(const char **)(tracedata + 2); - unsigned int user_hash_value, file_hash_value; - - user_hash_value = user % USERHASH; - file_hash_value = hash_string(lineno, file, FILEHASH); - set_magic_time(user_hash_value, file_hash_value, dev_hash_value); -} - -extern char __tracedata_start, __tracedata_end; -static int show_file_hash(unsigned int value) -{ - int match; - char *tracedata; - - match = 0; - for (tracedata = &__tracedata_start ; tracedata < &__tracedata_end ; tracedata += 6) { - unsigned short lineno = *(unsigned short *)tracedata; - const char *file = *(const char **)(tracedata + 2); - unsigned int hash = hash_string(lineno, file, FILEHASH); - if (hash != value) - continue; - printk(" hash matches %s:%u\n", file, lineno); - match++; - } - return match; -} - -static int show_dev_hash(unsigned int value) -{ - int match = 0; - struct list_head * entry = dpm_active.prev; - - while (entry != &dpm_active) { - struct device * dev = to_device(entry); - unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH); - if (hash == value) { - printk(" hash matches device %s\n", dev->bus_id); - match++; - } - entry = entry->prev; - } - return match; -} - -static unsigned int hash_value_early_read; - -static int early_resume_init(void) -{ - hash_value_early_read = read_magic_time(); - return 0; -} - -static int late_resume_init(void) -{ - unsigned int val = hash_value_early_read; - unsigned int user, file, dev; - - user = val % USERHASH; - val = val / USERHASH; - file = val % FILEHASH; - val = val / FILEHASH; - dev = val /* % DEVHASH */; - - printk(" Magic number: %d:%d:%d\n", user, file, dev); - show_file_hash(file); - show_dev_hash(dev); - return 0; -} - -core_initcall(early_resume_init); -late_initcall(late_resume_init); diff --git a/trunk/drivers/char/drm/i915_dma.c b/trunk/drivers/char/drm/i915_dma.c index a94233bdbc0e..9f4b8ce4c05e 100644 --- a/trunk/drivers/char/drm/i915_dma.c +++ b/trunk/drivers/char/drm/i915_dma.c @@ -758,9 +758,7 @@ drm_ioctl_desc_t i915_ioctls[] = { [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH}, [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, - [DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, - [DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH }, + [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY } }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/trunk/drivers/char/drm/i915_drm.h b/trunk/drivers/char/drm/i915_drm.h index 5aa3e0e3bb45..4cb3da578330 100644 --- a/trunk/drivers/char/drm/i915_drm.h +++ b/trunk/drivers/char/drm/i915_drm.h @@ -124,8 +124,6 @@ typedef struct _drm_i915_sarea { #define DRM_I915_INIT_HEAP 0x0a #define DRM_I915_CMDBUFFER 0x0b #define DRM_I915_DESTROY_HEAP 0x0c -#define DRM_I915_SET_VBLANK_PIPE 0x0d -#define DRM_I915_GET_VBLANK_PIPE 0x0e #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -140,8 +138,6 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t) #define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t) #define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) -#define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) -#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -228,13 +224,4 @@ typedef struct drm_i915_mem_destroy_heap { int region; } drm_i915_mem_destroy_heap_t; -/* Allow X server to configure which pipes to monitor for vblank signals - */ -#define DRM_I915_VBLANK_PIPE_A 1 -#define DRM_I915_VBLANK_PIPE_B 2 - -typedef struct drm_i915_vblank_pipe { - int pipe; -} drm_i915_vblank_pipe_t; - #endif /* _I915_DRM_H_ */ diff --git a/trunk/drivers/char/drm/i915_drv.h b/trunk/drivers/char/drm/i915_drv.h index 2d565031c002..7a65666899e4 100644 --- a/trunk/drivers/char/drm/i915_drv.h +++ b/trunk/drivers/char/drm/i915_drv.h @@ -45,10 +45,9 @@ * 1.2: Add Power Management * 1.3: Add vblank support * 1.4: Fix cmdbuffer path, add heap destroy - * 1.5: Add vblank pipe configuration */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 5 +#define DRIVER_MINOR 4 #define DRIVER_PATCHLEVEL 0 typedef struct _drm_i915_ring_buffer { @@ -97,7 +96,6 @@ typedef struct drm_i915_private { int allow_batchbuffer; struct mem_block *agp_heap; unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; - int vblank_pipe; } drm_i915_private_t; extern drm_ioctl_desc_t i915_ioctls[]; @@ -121,8 +119,6 @@ extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); extern void i915_driver_irq_preinstall(drm_device_t * dev); extern void i915_driver_irq_postinstall(drm_device_t * dev); extern void i915_driver_irq_uninstall(drm_device_t * dev); -extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS); -extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS); /* i915_mem.c */ extern int i915_mem_alloc(DRM_IOCTL_ARGS); diff --git a/trunk/drivers/char/drm/i915_irq.c b/trunk/drivers/char/drm/i915_irq.c index cd96cfa430db..a752afd86ab8 100644 --- a/trunk/drivers/char/drm/i915_irq.c +++ b/trunk/drivers/char/drm/i915_irq.c @@ -44,8 +44,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) u16 temp; temp = I915_READ16(I915REG_INT_IDENTITY_R); - - temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG); + temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG); DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); @@ -59,7 +58,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) if (temp & USER_INT_FLAG) DRM_WAKEUP(&dev_priv->irq_queue); - if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { + if (temp & VSYNC_PIPEA_FLAG) { atomic_inc(&dev->vbl_received); DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); @@ -183,68 +182,6 @@ int i915_irq_wait(DRM_IOCTL_ARGS) return i915_wait_irq(dev, irqwait.irq_seq); } -static int i915_enable_interrupt (drm_device_t *dev) -{ - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u16 flag; - - flag = 0; - if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A) - flag |= VSYNC_PIPEA_FLAG; - if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) - flag |= VSYNC_PIPEB_FLAG; - if (dev_priv->vblank_pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { - DRM_ERROR("%s called with invalid pipe 0x%x\n", - __FUNCTION__, dev_priv->vblank_pipe); - return DRM_ERR(EINVAL); - } - I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag); - return 0; -} - -/* Set the vblank monitor pipe - */ -int i915_vblank_pipe_set(DRM_IOCTL_ARGS) -{ - DRM_DEVICE; - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_vblank_pipe_t pipe; - - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - - DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data, - sizeof(pipe)); - - dev_priv->vblank_pipe = pipe.pipe; - return i915_enable_interrupt (dev); -} - -int i915_vblank_pipe_get(DRM_IOCTL_ARGS) -{ - DRM_DEVICE; - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_vblank_pipe_t pipe; - u16 flag; - - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - - flag = I915_READ(I915REG_INT_ENABLE_R); - pipe.pipe = 0; - if (flag & VSYNC_PIPEA_FLAG) - pipe.pipe |= DRM_I915_VBLANK_PIPE_A; - if (flag & VSYNC_PIPEB_FLAG) - pipe.pipe |= DRM_I915_VBLANK_PIPE_B; - DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_pipe_t __user *) data, pipe, - sizeof(pipe)); - return 0; -} - /* drm_dma.h hooks */ void i915_driver_irq_preinstall(drm_device_t * dev) @@ -260,7 +197,7 @@ void i915_driver_irq_postinstall(drm_device_t * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - i915_enable_interrupt(dev); + I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | VSYNC_PIPEA_FLAG); DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); } diff --git a/trunk/drivers/char/drm/radeon_cp.c b/trunk/drivers/char/drm/radeon_cp.c index 5ad43ba7b5aa..7f949c9c9691 100644 --- a/trunk/drivers/char/drm/radeon_cp.c +++ b/trunk/drivers/char/drm/radeon_cp.c @@ -39,7 +39,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev); /* CP microcode (from ATI) */ -static const u32 R200_cp_microcode[][2] = { +static u32 R200_cp_microcode[][2] = { {0x21007000, 0000000000}, {0x20007000, 0000000000}, {0x000000ab, 0x00000004}, @@ -298,7 +298,7 @@ static const u32 R200_cp_microcode[][2] = { {0000000000, 0000000000}, }; -static const u32 radeon_cp_microcode[][2] = { +static u32 radeon_cp_microcode[][2] = { {0x21007000, 0000000000}, {0x20007000, 0000000000}, {0x000000b4, 0x00000004}, @@ -557,7 +557,7 @@ static const u32 radeon_cp_microcode[][2] = { {0000000000, 0000000000}, }; -static const u32 R300_cp_microcode[][2] = { +static u32 R300_cp_microcode[][2] = { {0x4200e000, 0000000000}, {0x4000e000, 0000000000}, {0x000000af, 0x00000008}, diff --git a/trunk/drivers/char/drm/radeon_drm.h b/trunk/drivers/char/drm/radeon_drm.h index 8d6350dd5360..c8e279e89c2e 100644 --- a/trunk/drivers/char/drm/radeon_drm.h +++ b/trunk/drivers/char/drm/radeon_drm.h @@ -161,8 +161,7 @@ #define R200_EMIT_PP_TXCTLALL_3 91 #define R200_EMIT_PP_TXCTLALL_4 92 #define R200_EMIT_PP_TXCTLALL_5 93 -#define R200_EMIT_VAP_PVS_CNTL 94 -#define RADEON_MAX_STATE_PACKETS 95 +#define RADEON_MAX_STATE_PACKETS 94 /* Commands understood by cmd_buffer ioctl. More can be added but * obviously these can't be removed or changed: @@ -177,7 +176,6 @@ #define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note: * doesn't make the cpu wait, just * the graphics hardware */ -#define RADEON_CMD_VECLINEAR 9 /* another r200 stopgap */ typedef union { int i; @@ -193,9 +191,6 @@ typedef union { struct { unsigned char cmd_type, offset, stride, count; } vectors; - struct { - unsigned char cmd_type, addr_lo, addr_hi, count; - } veclinear; struct { unsigned char cmd_type, buf_idx, pad0, pad1; } dma; diff --git a/trunk/drivers/char/drm/radeon_drv.h b/trunk/drivers/char/drm/radeon_drv.h index e5a256f5429c..78345cee8f8e 100644 --- a/trunk/drivers/char/drm/radeon_drv.h +++ b/trunk/drivers/char/drm/radeon_drv.h @@ -38,7 +38,7 @@ #define DRIVER_NAME "radeon" #define DRIVER_DESC "ATI Radeon" -#define DRIVER_DATE "20060524" +#define DRIVER_DATE "20060225" /* Interface history: * @@ -93,11 +93,9 @@ * 1.22- Add support for texture cache flushes (R300_TX_CNTL) * 1.23- Add new radeon memory map work from benh * 1.24- Add general-purpose packet for manipulating scratch registers (r300) - * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL, - * new packet type) */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 25 +#define DRIVER_MINOR 24 #define DRIVER_PATCHLEVEL 0 /* @@ -886,8 +884,6 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp, #define RADEON_PP_CUBIC_OFFSET_T1_0 0x1e00 #define RADEON_PP_CUBIC_OFFSET_T2_0 0x1e14 -#define RADEON_SE_TCL_STATE_FLUSH 0x2284 - #define SE_VAP_CNTL__TCL_ENA_MASK 0x00000001 #define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK 0x00010000 #define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT 0x00000012 @@ -909,8 +905,6 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp, #define R200_PP_AFS_0 0x2f80 #define R200_PP_AFS_1 0x2f00 /* same as txcblend_0 */ -#define R200_VAP_PVS_CNTL_1 0x22D0 - /* Constants */ #define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ diff --git a/trunk/drivers/char/drm/radeon_state.c b/trunk/drivers/char/drm/radeon_state.c index 5bb2234a9094..c5b8f774a599 100644 --- a/trunk/drivers/char/drm/radeon_state.c +++ b/trunk/drivers/char/drm/radeon_state.c @@ -249,7 +249,6 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * case R200_EMIT_PP_TXCTLALL_3: case R200_EMIT_PP_TXCTLALL_4: case R200_EMIT_PP_TXCTLALL_5: - case R200_EMIT_VAP_PVS_CNTL: /* These packets don't contain memory offsets */ break; @@ -627,7 +626,6 @@ static struct { {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"}, {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"}, {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"}, - {R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"}, }; /* ================================================================ @@ -2597,8 +2595,7 @@ static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv, int stride = header.vectors.stride; RING_LOCALS; - BEGIN_RING(5 + sz); - OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); + BEGIN_RING(3 + sz); OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0)); OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); @@ -2610,32 +2607,6 @@ static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv, return 0; } -static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv, - drm_radeon_cmd_header_t header, - drm_radeon_kcmd_buffer_t *cmdbuf) -{ - int sz = header.veclinear.count * 4; - int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8); - RING_LOCALS; - - if (!sz) - return 0; - if (sz * 4 > cmdbuf->bufsz) - return DRM_ERR(EINVAL); - - BEGIN_RING(5 + sz); - OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); - OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0)); - OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); - OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); - OUT_RING_TABLE(cmdbuf->buf, sz); - ADVANCE_RING(); - - cmdbuf->buf += sz * sizeof(int); - cmdbuf->bufsz -= sz * sizeof(int); - return 0; -} - static int radeon_emit_packet3(drm_device_t * dev, drm_file_t * filp_priv, drm_radeon_kcmd_buffer_t *cmdbuf) @@ -2894,14 +2865,6 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) goto err; } break; - case RADEON_CMD_VECLINEAR: - DRM_DEBUG("RADEON_CMD_VECLINEAR\n"); - if (radeon_emit_veclinear(dev_priv, header, &cmdbuf)) { - DRM_ERROR("radeon_emit_veclinear failed\n"); - goto err; - } - break; - default: DRM_ERROR("bad cmd_type %d at %p\n", header.header.cmd_type, diff --git a/trunk/drivers/char/rtc.c b/trunk/drivers/char/rtc.c index 0897b0c8d528..f6686fcce809 100644 --- a/trunk/drivers/char/rtc.c +++ b/trunk/drivers/char/rtc.c @@ -928,7 +928,7 @@ static int __init rtc_init(void) #ifdef __sparc__ for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if(strcmp(edev->prom_node->name, "rtc") == 0) { + if(strcmp(edev->prom_name, "rtc") == 0) { rtc_port = edev->resource[0].start; rtc_irq = edev->irqs[0]; goto found; @@ -938,7 +938,7 @@ static int __init rtc_init(void) #ifdef __sparc_v9__ for_each_isa(isa_br) { for_each_isadev(isa_dev, isa_br) { - if (strcmp(isa_dev->prom_node->name, "rtc") == 0) { + if (strcmp(isa_dev->prom_name, "rtc") == 0) { rtc_port = isa_dev->resource.start; rtc_irq = isa_dev->irq; goto found; diff --git a/trunk/drivers/input/misc/Kconfig b/trunk/drivers/input/misc/Kconfig index a6dfc7455733..4bad588d0e5d 100644 --- a/trunk/drivers/input/misc/Kconfig +++ b/trunk/drivers/input/misc/Kconfig @@ -26,7 +26,7 @@ config INPUT_PCSPKR config INPUT_SPARCSPKR tristate "SPARC Speaker support" - depends on PCI && SPARC64 + depends on PCI && SPARC help Say Y here if you want the standard Speaker on Sparc PCI systems to be used for bells and whistles. diff --git a/trunk/drivers/input/misc/sparcspkr.c b/trunk/drivers/input/misc/sparcspkr.c index 42c11fbf3c79..f0fd2c4740f1 100644 --- a/trunk/drivers/input/misc/sparcspkr.c +++ b/trunk/drivers/input/misc/sparcspkr.c @@ -2,7 +2,7 @@ * Driver for PC-speaker like devices found on various Sparc systems. * * Copyright (c) 2002 Vojtech Pavlik - * Copyright (c) 2002, 2006 David S. Miller (davem@davemloft.net) + * Copyright (c) 2002 David S. Miller (davem@redhat.com) */ #include #include @@ -13,23 +13,21 @@ #include #include +#ifdef CONFIG_SPARC64 #include +#endif -MODULE_AUTHOR("David S. Miller "); +MODULE_AUTHOR("David S. Miller "); MODULE_DESCRIPTION("Sparc Speaker beeper driver"); MODULE_LICENSE("GPL"); -struct sparcspkr_state { - const char *name; - unsigned long iobase; - int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value); - spinlock_t lock; - struct input_dev *input_dev; -}; +const char *beep_name; +static unsigned long beep_iobase; +static int (*beep_event)(struct input_dev *dev, unsigned int type, unsigned int code, int value); +static DEFINE_SPINLOCK(beep_lock); static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev); unsigned int count = 0; unsigned long flags; @@ -45,24 +43,24 @@ static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned in if (value > 20 && value < 32767) count = 1193182 / value; - spin_lock_irqsave(&state->lock, flags); + spin_lock_irqsave(&beep_lock, flags); /* EBUS speaker only has on/off state, the frequency does not * appear to be programmable. */ - if (state->iobase & 0x2UL) - outb(!!count, state->iobase); + if (beep_iobase & 0x2UL) + outb(!!count, beep_iobase); else - outl(!!count, state->iobase); + outl(!!count, beep_iobase); - spin_unlock_irqrestore(&state->lock, flags); + spin_unlock_irqrestore(&beep_lock, flags); return 0; } +#ifdef CONFIG_SPARC64 static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev); unsigned int count = 0; unsigned long flags; @@ -78,29 +76,29 @@ static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int if (value > 20 && value < 32767) count = 1193182 / value; - spin_lock_irqsave(&state->lock, flags); + spin_lock_irqsave(&beep_lock, flags); if (count) { /* enable counter 2 */ - outb(inb(state->iobase + 0x61) | 3, state->iobase + 0x61); + outb(inb(beep_iobase + 0x61) | 3, beep_iobase + 0x61); /* set command for counter 2, 2 byte write */ - outb(0xB6, state->iobase + 0x43); + outb(0xB6, beep_iobase + 0x43); /* select desired HZ */ - outb(count & 0xff, state->iobase + 0x42); - outb((count >> 8) & 0xff, state->iobase + 0x42); + outb(count & 0xff, beep_iobase + 0x42); + outb((count >> 8) & 0xff, beep_iobase + 0x42); } else { /* disable counter 2 */ - outb(inb_p(state->iobase + 0x61) & 0xFC, state->iobase + 0x61); + outb(inb_p(beep_iobase + 0x61) & 0xFC, beep_iobase + 0x61); } - spin_unlock_irqrestore(&state->lock, flags); + spin_unlock_irqrestore(&beep_lock, flags); return 0; } +#endif -static int __devinit sparcspkr_probe(struct device *dev) +static int __devinit sparcspkr_probe(struct platform_device *dev) { - struct sparcspkr_state *state = dev_get_drvdata(dev); struct input_dev *input_dev; int error; @@ -108,18 +106,18 @@ static int __devinit sparcspkr_probe(struct device *dev) if (!input_dev) return -ENOMEM; - input_dev->name = state->name; + input_dev->name = beep_name; input_dev->phys = "sparc/input0"; input_dev->id.bustype = BUS_ISA; input_dev->id.vendor = 0x001f; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = dev; + input_dev->cdev.dev = &dev->dev; input_dev->evbit[0] = BIT(EV_SND); input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); - input_dev->event = state->event; + input_dev->event = beep_event; error = input_register_device(input_dev); if (error) { @@ -127,137 +125,111 @@ static int __devinit sparcspkr_probe(struct device *dev) return error; } - state->input_dev = input_dev; + platform_set_drvdata(dev, input_dev); return 0; } -static int __devexit sparcspkr_remove(struct of_device *dev) +static int __devexit sparcspkr_remove(struct platform_device *dev) { - struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); - struct input_dev *input_dev = state->input_dev; - - /* turn off the speaker */ - state->event(input_dev, EV_SND, SND_BELL, 0); + struct input_dev *input_dev = platform_get_drvdata(dev); input_unregister_device(input_dev); - - dev_set_drvdata(&dev->dev, NULL); - kfree(state); - - return 0; -} - -static int sparcspkr_shutdown(struct of_device *dev) -{ - struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); - struct input_dev *input_dev = state->input_dev; - + platform_set_drvdata(dev, NULL); /* turn off the speaker */ - state->event(input_dev, EV_SND, SND_BELL, 0); + beep_event(NULL, EV_SND, SND_BELL, 0); return 0; } -static int __devinit ebus_beep_probe(struct of_device *dev, const struct of_device_id *match) +static void sparcspkr_shutdown(struct platform_device *dev) { - struct linux_ebus_device *edev = to_ebus_device(&dev->dev); - struct sparcspkr_state *state; - int err; - - state = kzalloc(sizeof(*state), GFP_KERNEL); - if (!state) - return -ENOMEM; - - state->name = "Sparc EBUS Speaker"; - state->iobase = edev->resource[0].start; - state->event = ebus_spkr_event; - spin_lock_init(&state->lock); - - dev_set_drvdata(&dev->dev, state); - - err = sparcspkr_probe(&dev->dev); - if (err) { - dev_set_drvdata(&dev->dev, NULL); - kfree(state); - } - - return 0; + /* turn off the speaker */ + beep_event(NULL, EV_SND, SND_BELL, 0); } -static struct of_device_id ebus_beep_match[] = { - { - .name = "beep", +static struct platform_driver sparcspkr_platform_driver = { + .driver = { + .name = "sparcspkr", + .owner = THIS_MODULE, }, - {}, -}; - -static struct of_platform_driver ebus_beep_driver = { - .name = "beep", - .match_table = ebus_beep_match, - .probe = ebus_beep_probe, - .remove = sparcspkr_remove, + .probe = sparcspkr_probe, + .remove = __devexit_p(sparcspkr_remove), .shutdown = sparcspkr_shutdown, }; -static int __devinit isa_beep_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct sparc_isa_device *idev = to_isa_device(&dev->dev); - struct sparcspkr_state *state; - int err; +static struct platform_device *sparcspkr_platform_device; - state = kzalloc(sizeof(*state), GFP_KERNEL); - if (!state) - return -ENOMEM; - - state->name = "Sparc ISA Speaker"; - state->iobase = idev->resource.start; - state->event = isa_spkr_event; - spin_lock_init(&state->lock); +static int __init sparcspkr_drv_init(void) +{ + int error; - dev_set_drvdata(&dev->dev, state); + error = platform_driver_register(&sparcspkr_platform_driver); + if (error) + return error; - err = sparcspkr_probe(&dev->dev); - if (err) { - dev_set_drvdata(&dev->dev, NULL); - kfree(state); + sparcspkr_platform_device = platform_device_alloc("sparcspkr", -1); + if (!sparcspkr_platform_device) { + error = -ENOMEM; + goto err_unregister_driver; } + error = platform_device_add(sparcspkr_platform_device); + if (error) + goto err_free_device; + return 0; -} -static struct of_device_id isa_beep_match[] = { - { - .name = "dma", - }, - {}, -}; + err_free_device: + platform_device_put(sparcspkr_platform_device); + err_unregister_driver: + platform_driver_unregister(&sparcspkr_platform_driver); -static struct of_platform_driver isa_beep_driver = { - .name = "beep", - .match_table = isa_beep_match, - .probe = isa_beep_probe, - .remove = sparcspkr_remove, - .shutdown = sparcspkr_shutdown, -}; + return error; +} static int __init sparcspkr_init(void) { - int err = of_register_driver(&ebus_beep_driver, &ebus_bus_type); - - if (!err) { - err = of_register_driver(&isa_beep_driver, &isa_bus_type); - if (err) - of_unregister_driver(&ebus_beep_driver); + struct linux_ebus *ebus; + struct linux_ebus_device *edev; +#ifdef CONFIG_SPARC64 + struct sparc_isa_bridge *isa_br; + struct sparc_isa_device *isa_dev; +#endif + + for_each_ebus(ebus) { + for_each_ebusdev(edev, ebus) { + if (!strcmp(edev->prom_name, "beep")) { + beep_name = "Sparc EBUS Speaker"; + beep_event = ebus_spkr_event; + beep_iobase = edev->resource[0].start; + return sparcspkr_drv_init(); + } + } + } +#ifdef CONFIG_SPARC64 + for_each_isa(isa_br) { + for_each_isadev(isa_dev, isa_br) { + /* A hack, the beep device's base lives in + * the DMA isa node. + */ + if (!strcmp(isa_dev->prom_name, "dma")) { + beep_name = "Sparc ISA Speaker"; + beep_event = isa_spkr_event, + beep_iobase = isa_dev->resource.start; + return sparcspkr_drv_init(); + } + } } +#endif - return err; + return -ENODEV; } static void __exit sparcspkr_exit(void) { - of_unregister_driver(&ebus_beep_driver); - of_unregister_driver(&isa_beep_driver); + platform_device_unregister(sparcspkr_platform_device); + platform_driver_unregister(&sparcspkr_platform_driver); } module_init(sparcspkr_init); diff --git a/trunk/drivers/input/serio/i8042-sparcio.h b/trunk/drivers/input/serio/i8042-sparcio.h index 6d66351805a2..ed9446f6d7e3 100644 --- a/trunk/drivers/input/serio/i8042-sparcio.h +++ b/trunk/drivers/input/serio/i8042-sparcio.h @@ -74,7 +74,7 @@ static int __init i8042_platform_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "8042")) + if (!strcmp(edev->prom_name, "8042")) goto edev_found; } } @@ -82,14 +82,14 @@ static int __init i8042_platform_init(void) edev_found: for_each_edevchild(edev, child) { - if (!strcmp(child->prom_node->name, OBP_PS2KBD_NAME1) || - !strcmp(child->prom_node->name, OBP_PS2KBD_NAME2)) { + if (!strcmp(child->prom_name, OBP_PS2KBD_NAME1) || + !strcmp(child->prom_name, OBP_PS2KBD_NAME2)) { i8042_kbd_irq = child->irqs[0]; kbd_iobase = ioremap(child->resource[0].start, 8); } - if (!strcmp(child->prom_node->name, OBP_PS2MS_NAME1) || - !strcmp(child->prom_node->name, OBP_PS2MS_NAME2)) + if (!strcmp(child->prom_name, OBP_PS2MS_NAME1) || + !strcmp(child->prom_name, OBP_PS2MS_NAME2)) i8042_aux_irq = child->irqs[0]; } if (i8042_kbd_irq == -1 || diff --git a/trunk/drivers/net/myri_sbus.c b/trunk/drivers/net/myri_sbus.c index d9f616fea3d9..6c86dca62e2a 100644 --- a/trunk/drivers/net/myri_sbus.c +++ b/trunk/drivers/net/myri_sbus.c @@ -1,10 +1,10 @@ -/* myri_sbus.c: MyriCOM MyriNET SBUS card driver. +/* myri_sbus.h: MyriCOM MyriNET SBUS card driver. * - * Copyright (C) 1996, 1999, 2006 David S. Miller (davem@davemloft.net) + * Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com) */ static char version[] = - "myri_sbus.c:v2.0 June 23, 2006 David S. Miller (davem@davemloft.net)\n"; + "myri_sbus.c:v1.9 12/Sep/99 David S. Miller (davem@redhat.com)\n"; #include #include @@ -81,6 +81,10 @@ static char version[] = #define DHDR(x) #endif +#ifdef MODULE +static struct myri_eth *root_myri_dev; +#endif + static void myri_reset_off(void __iomem *lp, void __iomem *cregs) { /* Clear IRQ mask. */ @@ -892,9 +896,8 @@ static void dump_eeprom(struct myri_eth *mp) } #endif -static int __init myri_ether_init(struct sbus_dev *sdev) +static int __init myri_ether_init(struct sbus_dev *sdev, int num) { - static int num; static unsigned version_printed; struct net_device *dev; struct myri_eth *mp; @@ -910,9 +913,6 @@ static int __init myri_ether_init(struct sbus_dev *sdev) if (version_printed++ == 0) printk(version); - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &sdev->ofdev.dev); - mp = (struct myri_eth *) dev->priv; spin_lock_init(&mp->irq_lock); mp->myri_sdev = sdev; @@ -1092,9 +1092,10 @@ static int __init myri_ether_init(struct sbus_dev *sdev) goto err_free_irq; } - dev_set_drvdata(&sdev->ofdev.dev, mp); - - num++; +#ifdef MODULE + mp->next_module = root_myri_dev; + root_myri_dev = mp; +#endif printk("%s: MyriCOM MyriNET Ethernet ", dev->name); @@ -1113,68 +1114,61 @@ static int __init myri_ether_init(struct sbus_dev *sdev) return -ENODEV; } - -static int __devinit myri_sbus_probe(struct of_device *dev, const struct of_device_id *match) +static int __init myri_sbus_match(struct sbus_dev *sdev) { - struct sbus_dev *sdev = to_sbus_device(&dev->dev); + char *name = sdev->prom_name; + + if (!strcmp(name, "MYRICOM,mlanai") || + !strcmp(name, "myri")) + return 1; - return myri_ether_init(sdev); + return 0; } -static int __devexit myri_sbus_remove(struct of_device *dev) +static int __init myri_sbus_probe(void) { - struct myri_eth *mp = dev_get_drvdata(&dev->dev); - struct net_device *net_dev = mp->dev; + struct sbus_bus *bus; + struct sbus_dev *sdev = NULL; + static int called; + int cards = 0, v; - unregister_netdevice(net_dev); - - free_irq(net_dev->irq, net_dev); +#ifdef MODULE + root_myri_dev = NULL; +#endif - if (mp->eeprom.cpuvers < CPUVERS_4_0) { - sbus_iounmap(mp->regs, mp->reg_size); - } else { - sbus_iounmap(mp->cregs, PAGE_SIZE); - sbus_iounmap(mp->lregs, (256 * 1024)); - sbus_iounmap(mp->lanai, (512 * 1024)); + if (called) + return -ENODEV; + called++; + + for_each_sbus(bus) { + for_each_sbusdev(sdev, bus) { + if (myri_sbus_match(sdev)) { + cards++; + DET(("Found myricom myrinet as %s\n", sdev->prom_name)); + if ((v = myri_ether_init(sdev, (cards - 1)))) + return v; + } + } } - - free_netdev(net_dev); - - dev_set_drvdata(&dev->dev, NULL); - + if (!cards) + return -ENODEV; return 0; } -static struct of_device_id myri_sbus_match[] = { - { - .name = "MYRICOM,mlanai", - }, - { - .name = "myri", - }, - {}, -}; - -MODULE_DEVICE_TABLE(of, myri_sbus_match); - -static struct of_platform_driver myri_sbus_driver = { - .name = "myri", - .match_table = myri_sbus_match, - .probe = myri_sbus_probe, - .remove = __devexit_p(myri_sbus_remove), -}; - -static int __init myri_sbus_init(void) -{ - return of_register_driver(&myri_sbus_driver, &sbus_bus_type); -} - -static void __exit myri_sbus_exit(void) +static void __exit myri_sbus_cleanup(void) { - of_unregister_driver(&myri_sbus_driver); +#ifdef MODULE + while (root_myri_dev) { + struct myri_eth *next = root_myri_dev->next_module; + + unregister_netdev(root_myri_dev->dev); + /* this will also free the co-allocated 'root_myri_dev' */ + free_netdev(root_myri_dev->dev); + root_myri_dev = next; + } +#endif /* MODULE */ } -module_init(myri_sbus_init); -module_exit(myri_sbus_exit); - +module_init(myri_sbus_probe); +module_exit(myri_sbus_cleanup); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/net/myri_sbus.h b/trunk/drivers/net/myri_sbus.h index 2f69ef7cdccb..47722f708a41 100644 --- a/trunk/drivers/net/myri_sbus.h +++ b/trunk/drivers/net/myri_sbus.h @@ -290,6 +290,7 @@ struct myri_eth { unsigned int reg_size; /* Size of register space. */ unsigned int shmem_base; /* Offset to shared ram. */ struct sbus_dev *myri_sdev; /* Our SBUS device struct. */ + struct myri_eth *next_module; /* Next in adapter chain. */ }; /* We use this to acquire receive skb's that we can DMA directly into. */ diff --git a/trunk/drivers/net/sunbmac.c b/trunk/drivers/net/sunbmac.c index 7127f0f36f0e..cfaf47c63c58 100644 --- a/trunk/drivers/net/sunbmac.c +++ b/trunk/drivers/net/sunbmac.c @@ -72,6 +72,8 @@ MODULE_LICENSE("GPL"); #define DIRQ(x) #endif +static struct bigmac *root_bigmac_dev; + #define DEFAULT_JAMSIZE 4 /* Toe jam */ #define QEC_RESET_TRIES 200 @@ -489,7 +491,7 @@ static void bigmac_tcvr_init(struct bigmac *bp) } } -static int bigmac_init_hw(struct bigmac *, int); +static int bigmac_init(struct bigmac *, int); static int try_next_permutation(struct bigmac *bp, void __iomem *tregs) { @@ -549,7 +551,7 @@ static void bigmac_timer(unsigned long data) if (ret == -1) { printk(KERN_ERR "%s: Link down, cable problem?\n", bp->dev->name); - ret = bigmac_init_hw(bp, 0); + ret = bigmac_init(bp, 0); if (ret) { printk(KERN_ERR "%s: Error, cannot re-init the " "BigMAC.\n", bp->dev->name); @@ -619,7 +621,7 @@ static void bigmac_begin_auto_negotiation(struct bigmac *bp) add_timer(&bp->bigmac_timer); } -static int bigmac_init_hw(struct bigmac *bp, int from_irq) +static int bigmac_init(struct bigmac *bp, int from_irq) { void __iomem *gregs = bp->gregs; void __iomem *cregs = bp->creg; @@ -750,7 +752,7 @@ static void bigmac_is_medium_rare(struct bigmac *bp, u32 qec_status, u32 bmac_st } printk(" RESET\n"); - bigmac_init_hw(bp, 1); + bigmac_init(bp, 1); } /* BigMAC transmit complete service routines. */ @@ -924,7 +926,7 @@ static int bigmac_open(struct net_device *dev) return ret; } init_timer(&bp->bigmac_timer); - ret = bigmac_init_hw(bp, 0); + ret = bigmac_init(bp, 0); if (ret) free_irq(dev->irq, bp); return ret; @@ -948,7 +950,7 @@ static void bigmac_tx_timeout(struct net_device *dev) { struct bigmac *bp = (struct bigmac *) dev->priv; - bigmac_init_hw(bp, 0); + bigmac_init(bp, 0); netif_wake_queue(dev); } @@ -1102,8 +1104,6 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev) bp->qec_sdev = qec_sdev; bp->bigmac_sdev = qec_sdev->child; - SET_NETDEV_DEV(dev, &bp->bigmac_sdev->ofdev.dev); - spin_lock_init(&bp->lock); /* Verify the registers we expect, are actually there. */ @@ -1226,7 +1226,11 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev) goto fail_and_cleanup; } - dev_set_drvdata(&bp->bigmac_sdev->ofdev.dev, bp); + /* Put us into the list of instances attached for later driver + * exit. + */ + bp->next_module = root_bigmac_dev; + root_bigmac_dev = bp; printk(KERN_INFO "%s: BigMAC 100baseT Ethernet ", dev->name); for (i = 0; i < 6; i++) @@ -1262,68 +1266,69 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev) /* QEC can be the parent of either QuadEthernet or * a BigMAC. We want the latter. */ -static int __devinit bigmac_sbus_probe(struct of_device *dev, const struct of_device_id *match) +static int __init bigmac_match(struct sbus_dev *sdev) { - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - struct device_node *dp = dev->node; - - if (!strcmp(dp->name, "be")) - sdev = sdev->parent; - - return bigmac_ether_init(sdev); -} - -static int __devexit bigmac_sbus_remove(struct of_device *dev) -{ - struct bigmac *bp = dev_get_drvdata(&dev->dev); - struct net_device *net_dev = bp->dev; - - unregister_netdevice(net_dev); + struct sbus_dev *child = sdev->child; - sbus_iounmap(bp->gregs, GLOB_REG_SIZE); - sbus_iounmap(bp->creg, CREG_REG_SIZE); - sbus_iounmap(bp->bregs, BMAC_REG_SIZE); - sbus_iounmap(bp->tregs, TCVR_REG_SIZE); - sbus_free_consistent(bp->bigmac_sdev, - PAGE_SIZE, - bp->bmac_block, - bp->bblock_dvma); + if (strcmp(sdev->prom_name, "qec") != 0) + return 0; - free_netdev(net_dev); + if (child == NULL) + return 0; - dev_set_drvdata(&dev->dev, NULL); + if (strcmp(child->prom_name, "be") != 0) + return 0; - return 0; + return 1; } -static struct of_device_id bigmac_sbus_match[] = { - { - .name = "qec", - }, - { - .name = "be", - }, - {}, -}; - -MODULE_DEVICE_TABLE(of, bigmac_sbus_match); - -static struct of_platform_driver bigmac_sbus_driver = { - .name = "sunbmac", - .match_table = bigmac_sbus_match, - .probe = bigmac_sbus_probe, - .remove = __devexit_p(bigmac_sbus_remove), -}; - -static int __init bigmac_init(void) +static int __init bigmac_probe(void) { - return of_register_driver(&bigmac_sbus_driver, &sbus_bus_type); + struct sbus_bus *sbus; + struct sbus_dev *sdev = NULL; + static int called; + int cards = 0, v; + + root_bigmac_dev = NULL; + + if (called) + return -ENODEV; + called++; + + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { + if (bigmac_match(sdev)) { + cards++; + if ((v = bigmac_ether_init(sdev))) + return v; + } + } + } + if (!cards) + return -ENODEV; + return 0; } -static void __exit bigmac_exit(void) +static void __exit bigmac_cleanup(void) { - of_unregister_driver(&bigmac_sbus_driver); + while (root_bigmac_dev) { + struct bigmac *bp = root_bigmac_dev; + struct bigmac *bp_nxt = root_bigmac_dev->next_module; + + sbus_iounmap(bp->gregs, GLOB_REG_SIZE); + sbus_iounmap(bp->creg, CREG_REG_SIZE); + sbus_iounmap(bp->bregs, BMAC_REG_SIZE); + sbus_iounmap(bp->tregs, TCVR_REG_SIZE); + sbus_free_consistent(bp->bigmac_sdev, + PAGE_SIZE, + bp->bmac_block, + bp->bblock_dvma); + + unregister_netdev(bp->dev); + free_netdev(bp->dev); + root_bigmac_dev = bp_nxt; + } } -module_init(bigmac_init); -module_exit(bigmac_exit); +module_init(bigmac_probe); +module_exit(bigmac_cleanup); diff --git a/trunk/drivers/net/sunbmac.h b/trunk/drivers/net/sunbmac.h index b563d3c2993e..b0dbc5187143 100644 --- a/trunk/drivers/net/sunbmac.h +++ b/trunk/drivers/net/sunbmac.h @@ -332,6 +332,7 @@ struct bigmac { struct sbus_dev *qec_sdev; struct sbus_dev *bigmac_sdev; struct net_device *dev; + struct bigmac *next_module; }; /* We use this to acquire receive skb's that we can DMA directly into. */ diff --git a/trunk/drivers/net/sungem.c b/trunk/drivers/net/sungem.c index 5248670d29f7..38cd30cb7c75 100644 --- a/trunk/drivers/net/sungem.c +++ b/trunk/drivers/net/sungem.c @@ -2880,20 +2880,17 @@ static int __devinit gem_get_device_address(struct gem *gp) #if defined(__sparc__) struct pci_dev *pdev = gp->pdev; struct pcidev_cookie *pcp = pdev->sysdata; - int use_idprom = 1; + int node = -1; if (pcp != NULL) { - unsigned char *addr; - int len; - - addr = of_get_property(pcp->prom_node, "local-mac-address", - &len); - if (addr && len == 6) { - use_idprom = 0; - memcpy(dev->dev_addr, addr, 6); - } + node = pcp->prom_node; + if (prom_getproplen(node, "local-mac-address") == 6) + prom_getproperty(node, "local-mac-address", + dev->dev_addr, 6); + else + node = -1; } - if (use_idprom) + if (node == -1) memcpy(dev->dev_addr, idprom->id_ethaddr, 6); #elif defined(CONFIG_PPC_PMAC) unsigned char *addr; diff --git a/trunk/drivers/net/sunhme.c b/trunk/drivers/net/sunhme.c index c33ead3470db..bd5d2668a362 100644 --- a/trunk/drivers/net/sunhme.c +++ b/trunk/drivers/net/sunhme.c @@ -1,9 +1,9 @@ -/* sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, +/* $Id: sunhme.c,v 1.124 2002/01/15 06:25:51 davem Exp $ + * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, * auto carrier detecting ethernet driver. Also known as the * "Happy Meal Ethernet" found on SunSwift SBUS cards. * - * Copyright (C) 1996, 1998, 1999, 2002, 2003, - 2006 David S. Miller (davem@davemloft.net) + * Copyright (C) 1996, 1998, 1999, 2002, 2003 David S. Miller (davem@redhat.com) * * Changes : * 2000/11/11 Willy Tarreau @@ -40,13 +40,15 @@ #include #include -#ifdef CONFIG_SPARC +#ifdef __sparc__ #include #include #include #include -#include #include +#ifndef __sparc_v9__ +#include +#endif #endif #include @@ -55,7 +57,7 @@ #ifdef CONFIG_PCI #include -#ifdef CONFIG_SPARC +#ifdef __sparc__ #include #endif #endif @@ -63,9 +65,9 @@ #include "sunhme.h" #define DRV_NAME "sunhme" -#define DRV_VERSION "3.00" -#define DRV_RELDATE "June 23, 2006" -#define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" +#define DRV_VERSION "2.02" +#define DRV_RELDATE "8/24/03" +#define DRV_AUTHOR "David S. Miller (davem@redhat.com)" static char version[] = DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; @@ -81,6 +83,8 @@ static int macaddr[6]; module_param_array(macaddr, int, NULL, 0); MODULE_PARM_DESC(macaddr, "Happy Meal MAC address to set"); +static struct happy_meal *root_happy_dev; + #ifdef CONFIG_SBUS static struct quattro *qfe_sbus_list; #endif @@ -177,6 +181,26 @@ static __inline__ void tx_dump_ring(struct happy_meal *hp) #define DEFAULT_IPG2 4 /* For all modes */ #define DEFAULT_JAMSIZE 4 /* Toe jam */ +#if defined(CONFIG_PCI) && defined(MODULE) +/* This happy_pci_ids is declared __initdata because it is only used + as an advisory to depmod. If this is ported to the new PCI interface + where it could be referenced at any time due to hot plugging, + the __initdata reference should be removed. */ + +static struct pci_device_id happymeal_pci_ids[] = { + { + .vendor = PCI_VENDOR_ID_SUN, + .device = PCI_DEVICE_ID_SUN_HAPPYMEAL, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(pci, happymeal_pci_ids); + +#endif + /* NOTE: In the descriptor writes one _must_ write the address * member _first_. The card must not be allowed to see * the updated descriptor flags until the address is @@ -1586,7 +1610,7 @@ static int happy_meal_init(struct happy_meal *hp) HMD(("happy_meal_init: old[%08x] bursts<", hme_read32(hp, gregs + GREG_CFG))); -#ifndef CONFIG_SPARC +#ifndef __sparc__ /* It is always PCI and can handle 64byte bursts. */ hme_write32(hp, gregs + GREG_CFG, GREG_CFG_BURST64); #else @@ -1623,7 +1647,7 @@ static int happy_meal_init(struct happy_meal *hp) HMD(("XXX>")); hme_write32(hp, gregs + GREG_CFG, 0); } -#endif /* CONFIG_SPARC */ +#endif /* __sparc__ */ /* Turn off interrupts we do not want to hear. */ HMD((", enable global interrupts, ")); @@ -2568,10 +2592,14 @@ static void __init quattro_apply_ranges(struct quattro *qp, struct happy_meal *h */ static struct quattro * __init quattro_sbus_find(struct sbus_dev *goal_sdev) { + struct sbus_bus *sbus; struct sbus_dev *sdev; struct quattro *qp; int i; + if (qfe_sbus_list == NULL) + goto found; + for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { for (i = 0, sdev = qp->quattro_dev; (sdev != NULL) && (i < 4); @@ -2580,7 +2608,17 @@ static struct quattro * __init quattro_sbus_find(struct sbus_dev *goal_sdev) return qp; } } + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { + if (sdev == goal_sdev) + goto found; + } + } + + /* Cannot find quattro parent, fail. */ + return NULL; +found: qp = kmalloc(sizeof(struct quattro), GFP_KERNEL); if (qp != NULL) { int i; @@ -2617,17 +2655,6 @@ static void __init quattro_sbus_register_irqs(void) } } } - -static void __devexit quattro_sbus_free_irqs(void) -{ - struct quattro *qp; - - for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { - struct sbus_dev *sdev = qp->quattro_dev; - - free_irq(sdev->irqs[0], qp); - } -} #endif /* CONFIG_SBUS */ #ifdef CONFIG_PCI @@ -2662,9 +2689,8 @@ static struct quattro * __init quattro_pci_find(struct pci_dev *pdev) #endif /* CONFIG_PCI */ #ifdef CONFIG_SBUS -static int __init happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) +static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) { - struct device_node *dp = sdev->ofdev.node; struct quattro *qp = NULL; struct happy_meal *hp; struct net_device *dev; @@ -2687,7 +2713,6 @@ static int __init happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) if (!dev) goto err_out; SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &sdev->ofdev.dev); if (hme_version_printed++ == 0) printk(KERN_INFO "%s", version); @@ -2703,16 +2728,13 @@ static int __init happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) for (i = 0; i < 6; i++) dev->dev_addr[i] = macaddr[i]; macaddr[5]++; + } else if (qfe_slot != -1 && + prom_getproplen(sdev->prom_node, + "local-mac-address") == 6) { + prom_getproperty(sdev->prom_node, "local-mac-address", + dev->dev_addr, 6); } else { - unsigned char *addr; - int len; - - addr = of_get_property(dp, "local-mac-address", &len); - - if (qfe_slot != -1 && addr && len == 6) - memcpy(dev->dev_addr, addr, 6); - else - memcpy(dev->dev_addr, idprom->id_ethaddr, 6); + memcpy(dev->dev_addr, idprom->id_ethaddr, 6); } hp = dev->priv; @@ -2723,8 +2745,9 @@ static int __init happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) err = -ENODEV; if (sdev->num_registers != 5) { - printk(KERN_ERR "happymeal: Device needs 5 regs, has %d.\n", + printk(KERN_ERR "happymeal: Device does not have 5 regs, it has %d.\n", sdev->num_registers); + printk(KERN_ERR "happymeal: Would you like that for here or to go?\n"); goto err_out_free_netdev; } @@ -2738,39 +2761,39 @@ static int __init happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) hp->gregs = sbus_ioremap(&sdev->resource[0], 0, GREG_REG_SIZE, "HME Global Regs"); if (!hp->gregs) { - printk(KERN_ERR "happymeal: Cannot map global registers.\n"); + printk(KERN_ERR "happymeal: Cannot map Happy Meal global registers.\n"); goto err_out_free_netdev; } hp->etxregs = sbus_ioremap(&sdev->resource[1], 0, ETX_REG_SIZE, "HME TX Regs"); if (!hp->etxregs) { - printk(KERN_ERR "happymeal: Cannot map MAC TX registers.\n"); + printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Transmit registers.\n"); goto err_out_iounmap; } hp->erxregs = sbus_ioremap(&sdev->resource[2], 0, ERX_REG_SIZE, "HME RX Regs"); if (!hp->erxregs) { - printk(KERN_ERR "happymeal: Cannot map MAC RX registers.\n"); + printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Receive registers.\n"); goto err_out_iounmap; } hp->bigmacregs = sbus_ioremap(&sdev->resource[3], 0, BMAC_REG_SIZE, "HME BIGMAC Regs"); if (!hp->bigmacregs) { - printk(KERN_ERR "happymeal: Cannot map BIGMAC registers.\n"); + printk(KERN_ERR "happymeal: Cannot map Happy Meal BIGMAC registers.\n"); goto err_out_iounmap; } hp->tcvregs = sbus_ioremap(&sdev->resource[4], 0, TCVR_REG_SIZE, "HME Tranceiver Regs"); if (!hp->tcvregs) { - printk(KERN_ERR "happymeal: Cannot map TCVR registers.\n"); + printk(KERN_ERR "happymeal: Cannot map Happy Meal Tranceiver registers.\n"); goto err_out_iounmap; } - hp->hm_revision = of_getintprop_default(dp, "hm-rev", 0xff); + hp->hm_revision = prom_getintdefault(sdev->prom_node, "hm-rev", 0xff); if (hp->hm_revision == 0xff) hp->hm_revision = 0xa0; @@ -2784,8 +2807,8 @@ static int __init happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) hp->happy_flags |= HFLAG_QUATTRO; /* Get the supported DVMA burst sizes from our Happy SBUS. */ - hp->happy_bursts = of_getintprop_default(sdev->bus->ofdev.node, - "burst-sizes", 0x00); + hp->happy_bursts = prom_getintdefault(sdev->bus->prom_node, + "burst-sizes", 0x00); hp->happy_block = sbus_alloc_consistent(hp->happy_dev, PAGE_SIZE, @@ -2848,8 +2871,6 @@ static int __init happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) goto err_out_free_consistent; } - dev_set_drvdata(&sdev->ofdev.dev, hp); - if (qfe_slot != -1) printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ", dev->name, qfe_slot); @@ -2862,6 +2883,12 @@ static int __init happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) dev->dev_addr[i], i == 5 ? ' ' : ':'); printk("\n"); + /* We are home free at this point, link us in to the happy + * device list. + */ + hp->next_module = root_happy_dev; + root_happy_dev = hp; + return 0; err_out_free_consistent: @@ -2891,7 +2918,7 @@ static int __init happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) #endif #ifdef CONFIG_PCI -#ifndef CONFIG_SPARC +#ifndef __sparc__ static int is_quattro_p(struct pci_dev *pdev) { struct pci_dev *busdev = pdev->bus->self; @@ -2979,14 +3006,14 @@ static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr) get_random_bytes(&dev_addr[3], 3); return; } -#endif /* !(CONFIG_SPARC) */ +#endif /* !(__sparc__) */ -static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __init happy_meal_pci_init(struct pci_dev *pdev) { struct quattro *qp = NULL; -#ifdef CONFIG_SPARC +#ifdef __sparc__ struct pcidev_cookie *pcp; + int node; #endif struct happy_meal *hp; struct net_device *dev; @@ -2997,14 +3024,15 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, int err; /* Now make sure pci_dev cookie is there. */ -#ifdef CONFIG_SPARC +#ifdef __sparc__ pcp = pdev->sysdata; - if (pcp == NULL) { + if (pcp == NULL || pcp->prom_node == -1) { printk(KERN_ERR "happymeal(PCI): Some PCI device info missing\n"); return -ENODEV; } + node = pcp->prom_node; - strcpy(prom_name, pcp->prom_node->name); + prom_getstring(node, "name", prom_name, sizeof(prom_name)); #else if (is_quattro_p(pdev)) strcpy(prom_name, "SUNW,qfe"); @@ -3075,15 +3103,11 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, dev->dev_addr[i] = macaddr[i]; macaddr[5]++; } else { -#ifdef CONFIG_SPARC - unsigned char *addr; - int len; - +#ifdef __sparc__ if (qfe_slot != -1 && - (addr = of_get_property(pcp->prom_node, - "local-mac-address", &len)) != NULL - && len == 6) { - memcpy(dev->dev_addr, addr, 6); + prom_getproplen(node, "local-mac-address") == 6) { + prom_getproperty(node, "local-mac-address", + dev->dev_addr, 6); } else { memcpy(dev->dev_addr, idprom->id_ethaddr, 6); } @@ -3099,8 +3123,8 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, hp->bigmacregs = (hpreg_base + 0x6000UL); hp->tcvregs = (hpreg_base + 0x7000UL); -#ifdef CONFIG_SPARC - hp->hm_revision = of_getintprop_default(pcp->prom_node, "hm-rev", 0xff); +#ifdef __sparc__ + hp->hm_revision = prom_getintdefault(node, "hm-rev", 0xff); if (hp->hm_revision == 0xff) { unsigned char prev; @@ -3124,7 +3148,7 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, /* And of course, indicate this is PCI. */ hp->happy_flags |= HFLAG_PCI; -#ifdef CONFIG_SPARC +#ifdef __sparc__ /* Assume PCI happy meals can handle all burst sizes. */ hp->happy_bursts = DMA_BURSTBITS; #endif @@ -3187,8 +3211,6 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, goto err_out_iounmap; } - dev_set_drvdata(&pdev->dev, hp); - if (!qfe_slot) { struct pci_dev *qpdev = qp->quattro_dev; @@ -3218,6 +3240,12 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, printk("\n"); + /* We are home free at this point, link us in to the happy + * device list. + */ + hp->next_module = root_happy_dev; + root_happy_dev = hp; + return 0; err_out_iounmap: @@ -3235,146 +3263,136 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, err_out: return err; } +#endif -static void __devexit happy_meal_pci_remove(struct pci_dev *pdev) -{ - struct happy_meal *hp = dev_get_drvdata(&pdev->dev); - struct net_device *net_dev = hp->dev; - - unregister_netdev(net_dev); - - pci_free_consistent(hp->happy_dev, - PAGE_SIZE, - hp->happy_block, - hp->hblock_dvma); - iounmap(hp->gregs); - pci_release_regions(hp->happy_dev); - - free_netdev(net_dev); - - dev_set_drvdata(&pdev->dev, NULL); -} - -static struct pci_device_id happymeal_pci_ids[] = { - { - .vendor = PCI_VENDOR_ID_SUN, - .device = PCI_DEVICE_ID_SUN_HAPPYMEAL, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(pci, happymeal_pci_ids); - -static struct pci_driver hme_pci_driver = { - .name = "hme", - .id_table = happymeal_pci_ids, - .probe = happy_meal_pci_probe, - .remove = __devexit_p(happy_meal_pci_remove), -}; - -static int __init happy_meal_pci_init(void) -{ - return pci_module_init(&hme_pci_driver); -} - -static void happy_meal_pci_exit(void) +#ifdef CONFIG_SBUS +static int __init happy_meal_sbus_probe(void) { - pci_unregister_driver(&hme_pci_driver); - - while (qfe_pci_list) { - struct quattro *qfe = qfe_pci_list; - struct quattro *next = qfe->next; - - kfree(qfe); - - qfe_pci_list = next; + struct sbus_bus *sbus; + struct sbus_dev *sdev; + int cards = 0; + char model[128]; + + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { + char *name = sdev->prom_name; + + if (!strcmp(name, "SUNW,hme")) { + cards++; + prom_getstring(sdev->prom_node, "model", + model, sizeof(model)); + if (!strcmp(model, "SUNW,sbus-qfe")) + happy_meal_sbus_init(sdev, 1); + else + happy_meal_sbus_init(sdev, 0); + } else if (!strcmp(name, "qfe") || + !strcmp(name, "SUNW,qfe")) { + cards++; + happy_meal_sbus_init(sdev, 1); + } + } } + if (cards != 0) + quattro_sbus_register_irqs(); + return cards; } - #endif -#ifdef CONFIG_SBUS -static int __devinit hme_sbus_probe(struct of_device *dev, const struct of_device_id *match) +#ifdef CONFIG_PCI +static int __init happy_meal_pci_probe(void) { - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - struct device_node *dp = dev->node; - char *model = of_get_property(dp, "model", NULL); - int is_qfe = (match->data != NULL); - - if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe")) - is_qfe = 1; + struct pci_dev *pdev = NULL; + int cards = 0; - return happy_meal_sbus_probe_one(sdev, is_qfe); + while ((pdev = pci_find_device(PCI_VENDOR_ID_SUN, + PCI_DEVICE_ID_SUN_HAPPYMEAL, pdev)) != NULL) { + if (pci_enable_device(pdev)) + continue; + pci_set_master(pdev); + cards++; + happy_meal_pci_init(pdev); + } + return cards; } +#endif -static int __devexit hme_sbus_remove(struct of_device *dev) +static int __init happy_meal_probe(void) { - struct happy_meal *hp = dev_get_drvdata(&dev->dev); - struct net_device *net_dev = hp->dev; - - unregister_netdevice(net_dev); - - /* XXX qfe parent interrupt... */ - - sbus_iounmap(hp->gregs, GREG_REG_SIZE); - sbus_iounmap(hp->etxregs, ETX_REG_SIZE); - sbus_iounmap(hp->erxregs, ERX_REG_SIZE); - sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); - sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); - sbus_free_consistent(hp->happy_dev, - PAGE_SIZE, - hp->happy_block, - hp->hblock_dvma); + static int called = 0; + int cards; - free_netdev(net_dev); + root_happy_dev = NULL; - dev_set_drvdata(&dev->dev, NULL); + if (called) + return -ENODEV; + called++; + cards = 0; +#ifdef CONFIG_SBUS + cards += happy_meal_sbus_probe(); +#endif +#ifdef CONFIG_PCI + cards += happy_meal_pci_probe(); +#endif + if (!cards) + return -ENODEV; return 0; } -static struct of_device_id hme_sbus_match[] = { - { - .name = "SUNW,hme", - }, - { - .name = "SUNW,qfe", - .data = (void *) 1, - }, - { - .name = "qfe", - .data = (void *) 1, - }, - {}, -}; -MODULE_DEVICE_TABLE(of, hme_sbus_match); +static void __exit happy_meal_cleanup_module(void) +{ +#ifdef CONFIG_SBUS + struct quattro *last_seen_qfe = NULL; +#endif -static struct of_platform_driver hme_sbus_driver = { - .name = "hme", - .match_table = hme_sbus_match, - .probe = hme_sbus_probe, - .remove = __devexit_p(hme_sbus_remove), -}; + while (root_happy_dev) { + struct happy_meal *hp = root_happy_dev; + struct happy_meal *next = root_happy_dev->next_module; + struct net_device *dev = hp->dev; -static int __init happy_meal_sbus_init(void) -{ - int err; + /* Unregister netdev before unmapping registers as this + * call can end up trying to access those registers. + */ + unregister_netdev(dev); - err = of_register_driver(&hme_sbus_driver, &sbus_bus_type); - if (!err) - quattro_sbus_register_irqs(); +#ifdef CONFIG_SBUS + if (!(hp->happy_flags & HFLAG_PCI)) { + if (hp->happy_flags & HFLAG_QUATTRO) { + if (hp->qfe_parent != last_seen_qfe) { + free_irq(dev->irq, hp->qfe_parent); + last_seen_qfe = hp->qfe_parent; + } + } - return err; -} + sbus_iounmap(hp->gregs, GREG_REG_SIZE); + sbus_iounmap(hp->etxregs, ETX_REG_SIZE); + sbus_iounmap(hp->erxregs, ERX_REG_SIZE); + sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); + sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); + sbus_free_consistent(hp->happy_dev, + PAGE_SIZE, + hp->happy_block, + hp->hblock_dvma); + } +#endif +#ifdef CONFIG_PCI + if ((hp->happy_flags & HFLAG_PCI)) { + pci_free_consistent(hp->happy_dev, + PAGE_SIZE, + hp->happy_block, + hp->hblock_dvma); + iounmap(hp->gregs); + pci_release_regions(hp->happy_dev); + } +#endif + free_netdev(dev); -static void happy_meal_sbus_exit(void) -{ - of_unregister_driver(&hme_sbus_driver); - quattro_sbus_free_irqs(); + root_happy_dev = next; + } + /* Now cleanup the quattro lists. */ +#ifdef CONFIG_SBUS while (qfe_sbus_list) { struct quattro *qfe = qfe_sbus_list; struct quattro *next = qfe->next; @@ -3383,39 +3401,18 @@ static void happy_meal_sbus_exit(void) qfe_sbus_list = next; } -} -#endif - -static int __init happy_meal_probe(void) -{ - int err = 0; - -#ifdef CONFIG_SBUS - err = happy_meal_sbus_init(); #endif #ifdef CONFIG_PCI - if (!err) { - err = happy_meal_pci_init(); -#ifdef CONFIG_SBUS - if (err) - happy_meal_sbus_exit(); -#endif - } -#endif - - return err; -} + while (qfe_pci_list) { + struct quattro *qfe = qfe_pci_list; + struct quattro *next = qfe->next; + kfree(qfe); -static void __exit happy_meal_exit(void) -{ -#ifdef CONFIG_SBUS - happy_meal_sbus_exit(); -#endif -#ifdef CONFIG_PCI - happy_meal_pci_exit(); + qfe_pci_list = next; + } #endif } module_init(happy_meal_probe); -module_exit(happy_meal_exit); +module_exit(happy_meal_cleanup_module); diff --git a/trunk/drivers/net/sunhme.h b/trunk/drivers/net/sunhme.h index 9b7ccaeeee89..34e9f953cea4 100644 --- a/trunk/drivers/net/sunhme.h +++ b/trunk/drivers/net/sunhme.h @@ -461,6 +461,7 @@ struct happy_meal { struct net_device *dev; /* Backpointer */ struct quattro *qfe_parent; /* For Quattro cards */ int qfe_ent; /* Which instance on quattro */ + struct happy_meal *next_module; }; /* Here are the happy flags. */ diff --git a/trunk/drivers/net/sunlance.c b/trunk/drivers/net/sunlance.c index 2c239ab63a80..6381243d8d00 100644 --- a/trunk/drivers/net/sunlance.c +++ b/trunk/drivers/net/sunlance.c @@ -266,6 +266,7 @@ struct lance_private { char *name; dma_addr_t init_block_dvma; struct net_device *dev; /* Backpointer */ + struct lance_private *next_module; struct sbus_dev *sdev; struct timer_list multicast_timer; }; @@ -297,6 +298,8 @@ int sparc_lance_debug = 2; #define LANCE_ADDR(x) ((long)(x) & ~0xff000000) +static struct lance_private *root_lance_dev; + /* Load the CSR registers */ static void load_csrs(struct lance_private *lp) { @@ -1324,9 +1327,9 @@ static struct ethtool_ops sparc_lance_ethtool_ops = { .get_link = sparc_lance_get_link, }; -static int __init sparc_lance_probe_one(struct sbus_dev *sdev, - struct sbus_dma *ledma, - struct sbus_dev *lebuffer) +static int __init sparc_lance_init(struct sbus_dev *sdev, + struct sbus_dma *ledma, + struct sbus_dev *lebuffer) { static unsigned version_printed; struct net_device *dev; @@ -1470,7 +1473,6 @@ static int __init sparc_lance_probe_one(struct sbus_dev *sdev, lp->dev = dev; SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &sdev->ofdev.dev); dev->open = &lance_open; dev->stop = &lance_close; dev->hard_start_xmit = &lance_start_xmit; @@ -1498,7 +1500,8 @@ static int __init sparc_lance_probe_one(struct sbus_dev *sdev, goto fail; } - dev_set_drvdata(&sdev->ofdev.dev, lp); + lp->next_module = root_lance_dev; + root_lance_dev = lp; printk(KERN_INFO "%s: LANCE ", dev->name); @@ -1533,112 +1536,88 @@ static inline struct sbus_dma *find_ledma(struct sbus_dev *sdev) #include /* Find all the lance cards on the system and initialize them */ -static struct sbus_dev sun4_sdev; -static int __init sparc_lance_init(void) +static int __init sparc_lance_probe(void) { + static struct sbus_dev sdev; + static int called; + + root_lance_dev = NULL; + + if (called) + return -ENODEV; + called++; + if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) || (idprom->id_machtype == (SM_SUN4|SM_4_470))) { - memset(&sun4_sdev, 0, sizeof(sdev)); - sun4_sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; - sun4_sdev.irqs[0] = 6; - return sparc_lance_probe_one(&sun4_sdev, NULL, NULL); + memset(&sdev, 0, sizeof(sdev)); + sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; + sdev.irqs[0] = 6; + return sparc_lance_init(&sdev, NULL, NULL); } return -ENODEV; } -static int __exit sunlance_sun4_remove(void) -{ - struct lance_private *lp = dev_get_drvdata(&sun4_sdev->dev); - struct net_device *net_dev = lp->dev; - - unregister_netdevice(net_dev); - - lance_free_hwresources(root_lance_dev); - - free_netdev(net_dev); - - dev_set_drvdata(&sun4_sdev->dev, NULL); - - return 0; -} - #else /* !CONFIG_SUN4 */ -static int __devinit sunlance_sbus_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - struct device_node *dp = dev->node; - int err; - - if (!strcmp(dp->name, "le")) { - err = sparc_lance_probe_one(sdev, NULL, NULL); - } else if (!strcmp(dp->name, "ledma")) { - struct sbus_dma *ledma = find_ledma(sdev); - - err = sparc_lance_probe_one(sdev->child, ledma, NULL); - } else { - BUG_ON(strcmp(dp->name, "lebuffer")); - - err = sparc_lance_probe_one(sdev->child, NULL, sdev); - } - - return err; -} - -static int __devexit sunlance_sbus_remove(struct of_device *dev) -{ - struct lance_private *lp = dev_get_drvdata(&dev->dev); - struct net_device *net_dev = lp->dev; - - unregister_netdevice(net_dev); - - lance_free_hwresources(lp); - - free_netdev(net_dev); - - dev_set_drvdata(&dev->dev, NULL); - - return 0; -} - -static struct of_device_id sunlance_sbus_match[] = { - { - .name = "le", - }, - { - .name = "ledma", - }, - { - .name = "lebuffer", - }, - {}, -}; - -MODULE_DEVICE_TABLE(of, sunlance_sbus_match); - -static struct of_platform_driver sunlance_sbus_driver = { - .name = "sunlance", - .match_table = sunlance_sbus_match, - .probe = sunlance_sbus_probe, - .remove = __devexit_p(sunlance_sbus_remove), -}; - - /* Find all the lance cards on the system and initialize them */ -static int __init sparc_lance_init(void) +static int __init sparc_lance_probe(void) { - return of_register_driver(&sunlance_sbus_driver, &sbus_bus_type); + struct sbus_bus *bus; + struct sbus_dev *sdev = NULL; + struct sbus_dma *ledma = NULL; + static int called; + int cards = 0, v; + + root_lance_dev = NULL; + + if (called) + return -ENODEV; + called++; + + for_each_sbus (bus) { + for_each_sbusdev (sdev, bus) { + if (strcmp(sdev->prom_name, "le") == 0) { + cards++; + if ((v = sparc_lance_init(sdev, NULL, NULL))) + return v; + continue; + } + if (strcmp(sdev->prom_name, "ledma") == 0) { + cards++; + ledma = find_ledma(sdev); + if ((v = sparc_lance_init(sdev->child, + ledma, NULL))) + return v; + continue; + } + if (strcmp(sdev->prom_name, "lebuffer") == 0){ + cards++; + if ((v = sparc_lance_init(sdev->child, + NULL, sdev))) + return v; + continue; + } + } /* for each sbusdev */ + } /* for each sbus */ + if (!cards) + return -ENODEV; + return 0; } #endif /* !CONFIG_SUN4 */ -static void __exit sparc_lance_exit(void) +static void __exit sparc_lance_cleanup(void) { -#ifdef CONFIG_SUN4 - sunlance_sun4_remove(); -#else - of_unregister_driver(&sunlance_sbus_driver); -#endif + struct lance_private *lp; + + while (root_lance_dev) { + lp = root_lance_dev->next_module; + + unregister_netdev(root_lance_dev->dev); + lance_free_hwresources(root_lance_dev); + free_netdev(root_lance_dev->dev); + root_lance_dev = lp; + } } -module_init(sparc_lance_init); -module_exit(sparc_lance_exit); +module_init(sparc_lance_probe); +module_exit(sparc_lance_cleanup); diff --git a/trunk/drivers/net/sunqe.c b/trunk/drivers/net/sunqe.c index 9da6d5b87173..1f2323be60d4 100644 --- a/trunk/drivers/net/sunqe.c +++ b/trunk/drivers/net/sunqe.c @@ -1,9 +1,10 @@ -/* sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver. +/* $Id: sunqe.c,v 1.55 2002/01/15 06:48:55 davem Exp $ + * sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver. * Once again I am out to prove that every ethernet * controller out there can be most efficiently programmed * if you make it look like a LANCE. * - * Copyright (C) 1996, 1999, 2003, 2006 David S. Miller (davem@davemloft.net) + * Copyright (C) 1996, 1999, 2003 David S. Miller (davem@redhat.com) */ #include @@ -40,9 +41,9 @@ #include "sunqe.h" #define DRV_NAME "sunqe" -#define DRV_VERSION "4.0" -#define DRV_RELDATE "June 23, 2006" -#define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" +#define DRV_VERSION "3.0" +#define DRV_RELDATE "8/24/03" +#define DRV_AUTHOR "David S. Miller (davem@redhat.com)" static char version[] = DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; @@ -754,269 +755,298 @@ static inline void qec_init_once(struct sunqec *qecp, struct sbus_dev *qsdev) qecp->gregs + GLOB_RSIZE); } -static u8 __init qec_get_burst(struct device_node *dp) +/* Four QE's per QEC card. */ +static int __init qec_ether_init(struct net_device *dev, struct sbus_dev *sdev) { + static unsigned version_printed; + struct net_device *qe_devs[4]; + struct sunqe *qeps[4]; + struct sbus_dev *qesdevs[4]; + struct sbus_dev *child; + struct sunqec *qecp = NULL; u8 bsizes, bsizes_more; + int i, j, res = -ENOMEM; - /* Find and set the burst sizes for the QEC, since it - * does the actual dma for all 4 channels. - */ - bsizes = of_getintprop_default(dp, "burst-sizes", 0xff); - bsizes &= 0xff; - bsizes_more = of_getintprop_default(dp->parent, "burst-sizes", 0xff); + for (i = 0; i < 4; i++) { + qe_devs[i] = alloc_etherdev(sizeof(struct sunqe)); + if (!qe_devs[i]) + goto out; + } - if (bsizes_more != 0xff) - bsizes &= bsizes_more; - if (bsizes == 0xff || (bsizes & DMA_BURST16) == 0 || - (bsizes & DMA_BURST32)==0) - bsizes = (DMA_BURST32 - 1); + if (version_printed++ == 0) + printk(KERN_INFO "%s", version); - return bsizes; -} + for (i = 0; i < 4; i++) { + qeps[i] = (struct sunqe *) qe_devs[i]->priv; + for (j = 0; j < 6; j++) + qe_devs[i]->dev_addr[j] = idprom->id_ethaddr[j]; + qeps[i]->channel = i; + spin_lock_init(&qeps[i]->lock); + } -static struct sunqec * __init get_qec(struct sbus_dev *child_sdev) -{ - struct sbus_dev *qec_sdev = child_sdev->parent; - struct sunqec *qecp; + qecp = kmalloc(sizeof(struct sunqec), GFP_KERNEL); + if (qecp == NULL) + goto out1; + qecp->qec_sdev = sdev; - for (qecp = root_qec_dev; qecp; qecp = qecp->next_module) { - if (qecp->qec_sdev == qec_sdev) - break; + for (i = 0; i < 4; i++) { + qecp->qes[i] = qeps[i]; + qeps[i]->dev = qe_devs[i]; + qeps[i]->parent = qecp; } - if (!qecp) { - qecp = kzalloc(sizeof(struct sunqec), GFP_KERNEL); - if (qecp) { - u32 ctrl; - - qecp->qec_sdev = qec_sdev; - qecp->gregs = sbus_ioremap(&qec_sdev->resource[0], 0, - GLOB_REG_SIZE, - "QEC Global Registers"); - if (!qecp->gregs) - goto fail; - - /* Make sure the QEC is in MACE mode. */ - ctrl = sbus_readl(qecp->gregs + GLOB_CTRL); - ctrl &= 0xf0000000; - if (ctrl != GLOB_CTRL_MMODE) { - printk(KERN_ERR "qec: Not in MACE mode!\n"); - goto fail; - } - if (qec_global_reset(qecp->gregs)) - goto fail; + res = -ENODEV; - qecp->qec_bursts = qec_get_burst(qec_sdev->ofdev.node); + for (i = 0, child = sdev->child; i < 4; i++, child = child->next) { + /* Link in channel */ + j = prom_getintdefault(child->prom_node, "channel#", -1); + if (j == -1) + goto out2; + qesdevs[j] = child; + } - qec_init_once(qecp, qec_sdev); + for (i = 0; i < 4; i++) + qeps[i]->qe_sdev = qesdevs[i]; - if (request_irq(qec_sdev->irqs[0], &qec_interrupt, - SA_SHIRQ, "qec", (void *) qecp)) { - printk(KERN_ERR "qec: Can't register irq.\n"); - goto fail; - } + /* Now map in the registers, QEC globals first. */ + qecp->gregs = sbus_ioremap(&sdev->resource[0], 0, + GLOB_REG_SIZE, "QEC Global Registers"); + if (!qecp->gregs) { + printk(KERN_ERR "QuadEther: Cannot map QEC global registers.\n"); + goto out2; + } - qecp->next_module = root_qec_dev; - root_qec_dev = qecp; - } + /* Make sure the QEC is in MACE mode. */ + if ((sbus_readl(qecp->gregs + GLOB_CTRL) & 0xf0000000) != GLOB_CTRL_MMODE) { + printk(KERN_ERR "QuadEther: AIEEE, QEC is not in MACE mode!\n"); + goto out3; } - return qecp; + /* Reset the QEC. */ + if (qec_global_reset(qecp->gregs)) + goto out3; -fail: - if (qecp->gregs) - sbus_iounmap(qecp->gregs, GLOB_REG_SIZE); - kfree(qecp); - return NULL; -} + /* Find and set the burst sizes for the QEC, since it does + * the actual dma for all 4 channels. + */ + bsizes = prom_getintdefault(sdev->prom_node, "burst-sizes", 0xff); + bsizes &= 0xff; + bsizes_more = prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff); -static int __init qec_ether_init(struct sbus_dev *sdev) -{ - static unsigned version_printed; - struct net_device *dev; - struct sunqe *qe; - struct sunqec *qecp; - int i, res; + if (bsizes_more != 0xff) + bsizes &= bsizes_more; + if (bsizes == 0xff || (bsizes & DMA_BURST16) == 0 || + (bsizes & DMA_BURST32)==0) + bsizes = (DMA_BURST32 - 1); - if (version_printed++ == 0) - printk(KERN_INFO "%s", version); + qecp->qec_bursts = bsizes; - dev = alloc_etherdev(sizeof(struct sunqe)); - if (!dev) - return -ENOMEM; + /* Perform one time QEC initialization, we never touch the QEC + * globals again after this. + */ + qec_init_once(qecp, sdev); + + for (i = 0; i < 4; i++) { + struct sunqe *qe = qeps[i]; + /* Map in QEC per-channel control registers. */ + qe->qcregs = sbus_ioremap(&qe->qe_sdev->resource[0], 0, + CREG_REG_SIZE, "QEC Channel Registers"); + if (!qe->qcregs) { + printk(KERN_ERR "QuadEther: Cannot map QE %d's channel registers.\n", i); + goto out4; + } - qe = netdev_priv(dev); + /* Map in per-channel AMD MACE registers. */ + qe->mregs = sbus_ioremap(&qe->qe_sdev->resource[1], 0, + MREGS_REG_SIZE, "QE MACE Registers"); + if (!qe->mregs) { + printk(KERN_ERR "QuadEther: Cannot map QE %d's MACE registers.\n", i); + goto out4; + } - i = of_getintprop_default(sdev->ofdev.node, "channel#", -1); - if (i == -1) { - struct sbus_dev *td = sdev->parent->child; - i = 0; - while (td != sdev) { - td = td->next; - i++; + qe->qe_block = sbus_alloc_consistent(qe->qe_sdev, + PAGE_SIZE, + &qe->qblock_dvma); + qe->buffers = sbus_alloc_consistent(qe->qe_sdev, + sizeof(struct sunqe_buffers), + &qe->buffers_dvma); + if (qe->qe_block == NULL || qe->qblock_dvma == 0 || + qe->buffers == NULL || qe->buffers_dvma == 0) { + goto out4; } + + /* Stop this QE. */ + qe_stop(qe); } - qe->channel = i; - spin_lock_init(&qe->lock); - - res = -ENODEV; - qecp = get_qec(sdev); - if (!qecp) - goto fail; - qecp->qes[qe->channel] = qe; - qe->dev = dev; - qe->parent = qecp; - qe->qe_sdev = sdev; + for (i = 0; i < 4; i++) { + SET_MODULE_OWNER(qe_devs[i]); + qe_devs[i]->open = qe_open; + qe_devs[i]->stop = qe_close; + qe_devs[i]->hard_start_xmit = qe_start_xmit; + qe_devs[i]->get_stats = qe_get_stats; + qe_devs[i]->set_multicast_list = qe_set_multicast; + qe_devs[i]->tx_timeout = qe_tx_timeout; + qe_devs[i]->watchdog_timeo = 5*HZ; + qe_devs[i]->irq = sdev->irqs[0]; + qe_devs[i]->dma = 0; + qe_devs[i]->ethtool_ops = &qe_ethtool_ops; + } - res = -ENOMEM; - qe->qcregs = sbus_ioremap(&qe->qe_sdev->resource[0], 0, - CREG_REG_SIZE, "QEC Channel Registers"); - if (!qe->qcregs) { - printk(KERN_ERR "qe: Cannot map channel registers.\n"); - goto fail; + /* QEC receives interrupts from each QE, then it sends the actual + * IRQ to the cpu itself. Since QEC is the single point of + * interrupt for all QE channels we register the IRQ handler + * for it now. + */ + if (request_irq(sdev->irqs[0], &qec_interrupt, + SA_SHIRQ, "QuadEther", (void *) qecp)) { + printk(KERN_ERR "QuadEther: Can't register QEC master irq handler.\n"); + res = -EAGAIN; + goto out4; } - qe->mregs = sbus_ioremap(&qe->qe_sdev->resource[1], 0, - MREGS_REG_SIZE, "QE MACE Registers"); - if (!qe->mregs) { - printk(KERN_ERR "qe: Cannot map MACE registers.\n"); - goto fail; + for (i = 0; i < 4; i++) { + if (register_netdev(qe_devs[i]) != 0) + goto out5; } - qe->qe_block = sbus_alloc_consistent(qe->qe_sdev, - PAGE_SIZE, - &qe->qblock_dvma); - qe->buffers = sbus_alloc_consistent(qe->qe_sdev, - sizeof(struct sunqe_buffers), - &qe->buffers_dvma); - if (qe->qe_block == NULL || qe->qblock_dvma == 0 || - qe->buffers == NULL || qe->buffers_dvma == 0) - goto fail; - - /* Stop this QE. */ - qe_stop(qe); - - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &sdev->ofdev.dev); - - dev->open = qe_open; - dev->stop = qe_close; - dev->hard_start_xmit = qe_start_xmit; - dev->get_stats = qe_get_stats; - dev->set_multicast_list = qe_set_multicast; - dev->tx_timeout = qe_tx_timeout; - dev->watchdog_timeo = 5*HZ; - dev->irq = sdev->irqs[0]; - dev->dma = 0; - dev->ethtool_ops = &qe_ethtool_ops; - - res = register_netdev(dev); - if (res) - goto fail; - - dev_set_drvdata(&sdev->ofdev.dev, qe); - - printk(KERN_INFO "%s: qe channel[%d] ", dev->name, qe->channel); - for (i = 0; i < 6; i++) - printk ("%2.2x%c", - dev->dev_addr[i], - i == 5 ? ' ': ':'); - printk("\n"); + /* Report the QE channels. */ + for (i = 0; i < 4; i++) { + printk(KERN_INFO "%s: QuadEthernet channel[%d] ", qe_devs[i]->name, i); + for (j = 0; j < 6; j++) + printk ("%2.2x%c", + qe_devs[i]->dev_addr[j], + j == 5 ? ' ': ':'); + printk("\n"); + } + /* We are home free at this point, link the qe's into + * the master list for later driver exit. + */ + qecp->next_module = root_qec_dev; + root_qec_dev = qecp; return 0; -fail: - if (qe->qcregs) - sbus_iounmap(qe->qcregs, CREG_REG_SIZE); - if (qe->mregs) - sbus_iounmap(qe->mregs, MREGS_REG_SIZE); - if (qe->qe_block) - sbus_free_consistent(qe->qe_sdev, - PAGE_SIZE, - qe->qe_block, - qe->qblock_dvma); - if (qe->buffers) - sbus_free_consistent(qe->qe_sdev, - sizeof(struct sunqe_buffers), - qe->buffers, - qe->buffers_dvma); - - free_netdev(dev); - +out5: + while (i--) + unregister_netdev(qe_devs[i]); + free_irq(sdev->irqs[0], (void *)qecp); +out4: + for (i = 0; i < 4; i++) { + struct sunqe *qe = (struct sunqe *)qe_devs[i]->priv; + + if (qe->qcregs) + sbus_iounmap(qe->qcregs, CREG_REG_SIZE); + if (qe->mregs) + sbus_iounmap(qe->mregs, MREGS_REG_SIZE); + if (qe->qe_block) + sbus_free_consistent(qe->qe_sdev, + PAGE_SIZE, + qe->qe_block, + qe->qblock_dvma); + if (qe->buffers) + sbus_free_consistent(qe->qe_sdev, + sizeof(struct sunqe_buffers), + qe->buffers, + qe->buffers_dvma); + } +out3: + sbus_iounmap(qecp->gregs, GLOB_REG_SIZE); +out2: + kfree(qecp); +out1: + i = 4; +out: + while (i--) + free_netdev(qe_devs[i]); return res; } -static int __devinit qec_sbus_probe(struct of_device *dev, const struct of_device_id *match) +static int __init qec_match(struct sbus_dev *sdev) { - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - - return qec_ether_init(sdev); -} - -static int __devexit qec_sbus_remove(struct of_device *dev) -{ - struct sunqe *qp = dev_get_drvdata(&dev->dev); - struct net_device *net_dev = qp->dev; - - unregister_netdevice(net_dev); - - sbus_iounmap(qp->qcregs, CREG_REG_SIZE); - sbus_iounmap(qp->mregs, MREGS_REG_SIZE); - sbus_free_consistent(qp->qe_sdev, - PAGE_SIZE, - qp->qe_block, - qp->qblock_dvma); - sbus_free_consistent(qp->qe_sdev, - sizeof(struct sunqe_buffers), - qp->buffers, - qp->buffers_dvma); - - free_netdev(net_dev); + struct sbus_dev *sibling; + int i; - dev_set_drvdata(&dev->dev, NULL); + if (strcmp(sdev->prom_name, "qec") != 0) + return 0; - return 0; + /* QEC can be parent of either QuadEthernet or BigMAC + * children. Do not confuse this with qfe/SUNW,qfe + * which is a quad-happymeal card and handled by + * a different driver. + */ + sibling = sdev->child; + for (i = 0; i < 4; i++) { + if (sibling == NULL) + return 0; + if (strcmp(sibling->prom_name, "qe") != 0) + return 0; + sibling = sibling->next; + } + return 1; } -static struct of_device_id qec_sbus_match[] = { - { - .name = "qe", - }, - {}, -}; - -MODULE_DEVICE_TABLE(of, qec_sbus_match); - -static struct of_platform_driver qec_sbus_driver = { - .name = "qec", - .match_table = qec_sbus_match, - .probe = qec_sbus_probe, - .remove = __devexit_p(qec_sbus_remove), -}; - -static int __init qec_init(void) +static int __init qec_probe(void) { - return of_register_driver(&qec_sbus_driver, &sbus_bus_type); + struct net_device *dev = NULL; + struct sbus_bus *bus; + struct sbus_dev *sdev = NULL; + static int called; + int cards = 0, v; + + root_qec_dev = NULL; + + if (called) + return -ENODEV; + called++; + + for_each_sbus(bus) { + for_each_sbusdev(sdev, bus) { + if (cards) + dev = NULL; + + if (qec_match(sdev)) { + cards++; + if ((v = qec_ether_init(dev, sdev))) + return v; + } + } + } + if (!cards) + return -ENODEV; + return 0; } -static void __exit qec_exit(void) +static void __exit qec_cleanup(void) { - of_unregister_driver(&qec_sbus_driver); + struct sunqec *next_qec; + int i; while (root_qec_dev) { - struct sunqec *next = root_qec_dev->next_module; - - free_irq(root_qec_dev->qec_sdev->irqs[0], - (void *) root_qec_dev); + next_qec = root_qec_dev->next_module; + + /* Release all four QE channels, then the QEC itself. */ + for (i = 0; i < 4; i++) { + unregister_netdev(root_qec_dev->qes[i]->dev); + sbus_iounmap(root_qec_dev->qes[i]->qcregs, CREG_REG_SIZE); + sbus_iounmap(root_qec_dev->qes[i]->mregs, MREGS_REG_SIZE); + sbus_free_consistent(root_qec_dev->qes[i]->qe_sdev, + PAGE_SIZE, + root_qec_dev->qes[i]->qe_block, + root_qec_dev->qes[i]->qblock_dvma); + sbus_free_consistent(root_qec_dev->qes[i]->qe_sdev, + sizeof(struct sunqe_buffers), + root_qec_dev->qes[i]->buffers, + root_qec_dev->qes[i]->buffers_dvma); + free_netdev(root_qec_dev->qes[i]->dev); + } + free_irq(root_qec_dev->qec_sdev->irqs[0], (void *)root_qec_dev); sbus_iounmap(root_qec_dev->gregs, GLOB_REG_SIZE); - kfree(root_qec_dev); - - root_qec_dev = next; + root_qec_dev = next_qec; } } -module_init(qec_init); -module_exit(qec_exit); +module_init(qec_probe); +module_exit(qec_cleanup); diff --git a/trunk/drivers/net/tg3.c b/trunk/drivers/net/tg3.c index 35f931638750..e3e380f90f86 100644 --- a/trunk/drivers/net/tg3.c +++ b/trunk/drivers/net/tg3.c @@ -10549,13 +10549,11 @@ static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp) struct pcidev_cookie *pcp = pdev->sysdata; if (pcp != NULL) { - unsigned char *addr; - int len; + int node = pcp->prom_node; - addr = of_get_property(pcp->prom_node, "local-mac-address", - &len); - if (addr && len == 6) { - memcpy(dev->dev_addr, addr, 6); + if (prom_getproplen(node, "local-mac-address") == 6) { + prom_getproperty(node, "local-mac-address", + dev->dev_addr, 6); memcpy(dev->perm_addr, dev->dev_addr, 6); return 0; } diff --git a/trunk/drivers/net/tulip/tulip_core.c b/trunk/drivers/net/tulip/tulip_core.c index e0de66739a42..cabdf894e21e 100644 --- a/trunk/drivers/net/tulip/tulip_core.c +++ b/trunk/drivers/net/tulip/tulip_core.c @@ -1550,14 +1550,10 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, dev->dev_addr[i] = last_phys_addr[i]; dev->dev_addr[i] = last_phys_addr[i] + 1; #if defined(__sparc__) - if (pcp) { - unsigned char *addr; - int len; - - addr = of_get_property(pcp->prom_node, - "local-mac-address", &len); - if (addr && len == 6) - memcpy(dev->dev_addr, addr, 6); + if ((pcp != NULL) && prom_getproplen(pcp->prom_node, + "local-mac-address") == 6) { + prom_getproperty(pcp->prom_node, "local-mac-address", + dev->dev_addr, 6); } #endif #if defined(__i386__) || defined(__x86_64__) /* Patch up x86 BIOS bug. */ diff --git a/trunk/drivers/parport/parport_sunbpp.c b/trunk/drivers/parport/parport_sunbpp.c index 69a4bbd4cbee..36a1556e64c7 100644 --- a/trunk/drivers/parport/parport_sunbpp.c +++ b/trunk/drivers/parport/parport_sunbpp.c @@ -1,4 +1,5 @@ -/* parport_sunbpp.c: Parallel-port routines for SBUS +/* $Id: parport_sunbpp.c,v 1.12 2001/05/26 03:01:42 davem Exp $ + * Parallel-port routines for Sun architecture * * Author: Derrick J. Brashear * @@ -13,9 +14,6 @@ * Gus Baldauf (gbaldauf@ix.netcom.com) * Peter Zaitcev * Tom Dyas - * - * Updated to new SBUS device framework: David S. Miller - * */ #include @@ -289,7 +287,14 @@ static struct parport_operations parport_sunbpp_ops = .owner = THIS_MODULE, }; -static int __devinit init_one_port(struct sbus_dev *sdev) +typedef struct { + struct list_head list; + struct parport *port; +} Node; +/* no locks, everything's serialized */ +static LIST_HEAD(port_list); + +static int __init init_one_port(struct sbus_dev *sdev) { struct parport *p; /* at least in theory there may be a "we don't dma" case */ @@ -298,120 +303,109 @@ static int __devinit init_one_port(struct sbus_dev *sdev) int irq, dma, err = 0, size; struct bpp_regs __iomem *regs; unsigned char value_tcr; + Node *node; + + dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev)); + node = kmalloc(sizeof(Node), GFP_KERNEL); + if (!node) + goto out0; irq = sdev->irqs[0]; base = sbus_ioremap(&sdev->resource[0], 0, sdev->reg_addrs[0].reg_size, "sunbpp"); if (!base) - return -ENODEV; + goto out1; size = sdev->reg_addrs[0].reg_size; dma = PARPORT_DMA_NONE; - ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); + dprintk(("alloc(ppops), ")); + ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); if (!ops) - goto out_unmap; + goto out2; memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); dprintk(("register_port\n")); if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) - goto out_free_ops; + goto out3; p->size = size; + dprintk((KERN_DEBUG "init_one_port: request_irq(%08x:%p:%x:%s:%p) ", + p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p)); if ((err = request_irq(p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p)) != 0) { - goto out_put_port; + dprintk(("ERROR %d\n", err)); + goto out4; } - + dprintk(("OK\n")); parport_sunbpp_enable_irq(p); regs = (struct bpp_regs __iomem *)p->base; - + dprintk((KERN_DEBUG "forward\n")); value_tcr = sbus_readb(®s->p_tcr); value_tcr &= ~P_TCR_DIR; sbus_writeb(value_tcr, ®s->p_tcr); printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); + node->port = p; + list_add(&node->list, &port_list); + parport_announce_port (p); - dev_set_drvdata(&sdev->ofdev.dev, p); - - parport_announce_port(p); - - return 0; + return 1; -out_put_port: +out4: parport_put_port(p); - -out_free_ops: +out3: kfree(ops); - -out_unmap: +out2: sbus_iounmap(base, size); - +out1: + kfree(node); +out0: return err; } -static int __devinit bpp_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - - return init_one_port(sdev); -} - -static int __devexit bpp_remove(struct of_device *dev) -{ - struct parport *p = dev_get_drvdata(&dev->dev); - struct parport_operations *ops = p->ops; - - parport_remove_port(p); - - if (p->irq != PARPORT_IRQ_NONE) { - parport_sunbpp_disable_irq(p); - free_irq(p->irq, p); - } - - sbus_iounmap((void __iomem *) p->base, p->size); - parport_put_port(p); - kfree(ops); - - dev_set_drvdata(&dev->dev, NULL); - - return 0; -} - -static struct of_device_id bpp_match[] = { - { - .name = "SUNW,bpp", - }, - {}, -}; - -MODULE_DEVICE_TABLE(of, qec_sbus_match); - -static struct of_platform_driver bpp_sbus_driver = { - .name = "bpp", - .match_table = bpp_match, - .probe = bpp_probe, - .remove = __devexit_p(bpp_remove), -}; - static int __init parport_sunbpp_init(void) { - return of_register_driver(&bpp_sbus_driver, &sbus_bus_type); + struct sbus_bus *sbus; + struct sbus_dev *sdev; + int count = 0; + + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { + if (!strcmp(sdev->prom_name, "SUNW,bpp")) + count += init_one_port(sdev); + } + } + return count ? 0 : -ENODEV; } static void __exit parport_sunbpp_exit(void) { - of_unregister_driver(&bpp_sbus_driver); + while (!list_empty(&port_list)) { + Node *node = list_entry(port_list.next, Node, list); + struct parport *p = node->port; + struct parport_operations *ops = p->ops; + parport_remove_port(p); + + if (p->irq != PARPORT_IRQ_NONE) { + parport_sunbpp_disable_irq(p); + free_irq(p->irq, p); + } + sbus_iounmap((void __iomem *)p->base, p->size); + parport_put_port(p); + kfree (ops); + list_del(&node->list); + kfree (node); + } } MODULE_AUTHOR("Derrick J Brashear"); MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port"); MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port"); -MODULE_VERSION("2.0"); MODULE_LICENSE("GPL"); module_init(parport_sunbpp_init) diff --git a/trunk/drivers/sbus/char/bbc_envctrl.c b/trunk/drivers/sbus/char/bbc_envctrl.c index 1cc706e11119..d89f83f769f5 100644 --- a/trunk/drivers/sbus/char/bbc_envctrl.c +++ b/trunk/drivers/sbus/char/bbc_envctrl.c @@ -575,9 +575,9 @@ int bbc_envctrl_init(void) int devidx = 0; while ((echild = bbc_i2c_getdev(devidx++)) != NULL) { - if (!strcmp(echild->prom_node->name, "temperature")) + if (!strcmp(echild->prom_name, "temperature")) attach_one_temp(echild, temp_index++); - if (!strcmp(echild->prom_node->name, "fan-control")) + if (!strcmp(echild->prom_name, "fan-control")) attach_one_fan(echild, fan_index++); } if (temp_index != 0 && fan_index != 0) { diff --git a/trunk/drivers/sbus/char/bbc_i2c.c b/trunk/drivers/sbus/char/bbc_i2c.c index 73634371393b..3e156e005f2e 100644 --- a/trunk/drivers/sbus/char/bbc_i2c.c +++ b/trunk/drivers/sbus/char/bbc_i2c.c @@ -423,7 +423,7 @@ static int __init bbc_present(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "bbc")) + if (!strcmp(edev->prom_name, "bbc")) return 1; } } @@ -446,7 +446,7 @@ static int __init bbc_i2c_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "i2c")) { + if (!strcmp(edev->prom_name, "i2c")) { if (!attach_one_i2c(edev, index)) index++; } diff --git a/trunk/drivers/sbus/char/display7seg.c b/trunk/drivers/sbus/char/display7seg.c index d92bc8827a9e..c3a51d1fae5d 100644 --- a/trunk/drivers/sbus/char/display7seg.c +++ b/trunk/drivers/sbus/char/display7seg.c @@ -184,7 +184,7 @@ static int __init d7s_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, D7S_OBPNAME)) + if (!strcmp(edev->prom_name, D7S_OBPNAME)) goto ebus_done; } } diff --git a/trunk/drivers/sbus/char/envctrl.c b/trunk/drivers/sbus/char/envctrl.c index cf97e9efe9b6..19e8eddf887a 100644 --- a/trunk/drivers/sbus/char/envctrl.c +++ b/trunk/drivers/sbus/char/envctrl.c @@ -768,14 +768,16 @@ static void envctrl_set_mon(struct i2c_child_t *pchild, * decoding tables, monitor type, optional properties. * Return: None. */ -static void envctrl_init_adc(struct i2c_child_t *pchild, struct device_node *dp) +static void envctrl_init_adc(struct i2c_child_t *pchild, int node) { + char chnls_desc[CHANNEL_DESC_SZ]; int i = 0, len; - char *pos; - unsigned int *pval; + char *pos = chnls_desc; /* Firmware describe channels into a stream separated by a '\0'. */ - pos = of_get_property(dp, "channels-description", &len); + len = prom_getproperty(node, "channels-description", chnls_desc, + CHANNEL_DESC_SZ); + chnls_desc[CHANNEL_DESC_SZ - 1] = '\0'; while (len > 0) { int l = strlen(pos) + 1; @@ -785,13 +787,10 @@ static void envctrl_init_adc(struct i2c_child_t *pchild, struct device_node *dp) } /* Get optional properties. */ - pval = of_get_property(dp, "warning-temp", NULL); - if (pval) - warning_temperature = *pval; - - pval = of_get_property(dp, "shutdown-temp", NULL); - if (pval) - shutdown_temperature = *pval; + len = prom_getproperty(node, "warning-temp", (char *)&warning_temperature, + sizeof(warning_temperature)); + len = prom_getproperty(node, "shutdown-temp", (char *)&shutdown_temperature, + sizeof(shutdown_temperature)); } /* Function Description: Initialize child device monitoring fan status. @@ -865,18 +864,21 @@ static void envctrl_init_voltage_status(struct i2c_child_t *pchild) static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, struct i2c_child_t *pchild) { - int len, i, tbls_size = 0; - struct device_node *dp = edev_child->prom_node; - void *pval; + int node, len, i, tbls_size = 0; + + node = edev_child->prom_node; /* Get device address. */ - pval = of_get_property(dp, "reg", &len); - memcpy(&pchild->addr, pval, len); + len = prom_getproperty(node, "reg", + (char *) &(pchild->addr), + sizeof(pchild->addr)); /* Get tables property. Read firmware temperature tables. */ - pval = of_get_property(dp, "translation", &len); - if (pval && len > 0) { - memcpy(pchild->tblprop_array, pval, len); + len = prom_getproperty(node, "translation", + (char *) pchild->tblprop_array, + (PCF8584_MAX_CHANNELS * + sizeof(struct pcf8584_tblprop))); + if (len > 0) { pchild->total_tbls = len / sizeof(struct pcf8584_tblprop); for (i = 0; i < pchild->total_tbls; i++) { if ((pchild->tblprop_array[i].size + pchild->tblprop_array[i].offset) > tbls_size) { @@ -889,12 +891,12 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, printk("envctrl: Failed to allocate table.\n"); return; } - pval = of_get_property(dp, "tables", &len); - if (!pval || len <= 0) { + len = prom_getproperty(node, "tables", + (char *) pchild->tables, tbls_size); + if (len <= 0) { printk("envctrl: Failed to get table.\n"); return; } - memcpy(pchild->tables, pval, len); } /* SPARCengine ASM Reference Manual (ref. SMI doc 805-7581-04) @@ -905,11 +907,12 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, * 'NULL' monitor type. */ if (ENVCTRL_CPCI_IGNORED_NODE == pchild->addr) { - struct device_node *root_node; int len; + char prop[56]; - root_node = of_find_node_by_path("/"); - if (!strcmp(root_node->name, "SUNW,UltraSPARC-IIi-cEngine")) { + len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop)); + if (0 < len && (0 == strncmp(prop, "SUNW,UltraSPARC-IIi-cEngine", len))) + { for (len = 0; len < PCF8584_MAX_CHANNELS; ++len) { pchild->mon_type[len] = ENVCTRL_NOMON; } @@ -918,14 +921,16 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, } /* Get the monitor channels. */ - pval = of_get_property(dp, "channels-in-use", &len); - memcpy(pchild->chnl_array, pval, len); + len = prom_getproperty(node, "channels-in-use", + (char *) pchild->chnl_array, + (PCF8584_MAX_CHANNELS * + sizeof(struct pcf8584_channel))); pchild->total_chnls = len / sizeof(struct pcf8584_channel); for (i = 0; i < pchild->total_chnls; i++) { switch (pchild->chnl_array[i].type) { case PCF8584_TEMP_TYPE: - envctrl_init_adc(pchild, dp); + envctrl_init_adc(pchild, node); break; case PCF8584_GLOBALADDR_TYPE: @@ -940,7 +945,7 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, case PCF8584_VOLTAGE_TYPE: if (pchild->i2ctype == I2C_ADC) { - envctrl_init_adc(pchild,dp); + envctrl_init_adc(pchild,node); } else { envctrl_init_voltage_status(pchild); } @@ -1041,7 +1046,7 @@ static int __init envctrl_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "bbc")) { + if (!strcmp(edev->prom_name, "bbc")) { /* If we find a boot-bus controller node, * then this envctrl driver is not for us. */ @@ -1055,14 +1060,14 @@ static int __init envctrl_init(void) */ for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "i2c")) { + if (!strcmp(edev->prom_name, "i2c")) { i2c = ioremap(edev->resource[0].start, 0x2); for_each_edevchild(edev, edev_child) { - if (!strcmp("gpio", edev_child->prom_node->name)) { + if (!strcmp("gpio", edev_child->prom_name)) { i2c_childlist[i].i2ctype = I2C_GPIO; envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++])); } - if (!strcmp("adc", edev_child->prom_node->name)) { + if (!strcmp("adc", edev_child->prom_name)) { i2c_childlist[i].i2ctype = I2C_ADC; envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++])); } diff --git a/trunk/drivers/sbus/char/flash.c b/trunk/drivers/sbus/char/flash.c index 5ae684c011f8..2beb3dded087 100644 --- a/trunk/drivers/sbus/char/flash.c +++ b/trunk/drivers/sbus/char/flash.c @@ -192,11 +192,9 @@ static int __init flash_init(void) } if (!sdev) { #ifdef CONFIG_PCI - struct linux_prom_registers *ebus_regs; - for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "flashprom")) + if (!strcmp(edev->prom_name, "flashprom")) goto ebus_done; } } @@ -204,23 +202,23 @@ static int __init flash_init(void) if (!edev) return -ENODEV; - ebus_regs = of_get_property(edev->prom_node, "reg", &len); - if (!ebus_regs || (len % sizeof(regs[0])) != 0) { + len = prom_getproperty(edev->prom_node, "reg", (void *)regs, sizeof(regs)); + if ((len % sizeof(regs[0])) != 0) { printk("flash: Strange reg property size %d\n", len); return -ENODEV; } - nregs = len / sizeof(ebus_regs[0]); + nregs = len / sizeof(regs[0]); flash.read_base = edev->resource[0].start; - flash.read_size = ebus_regs[0].reg_size; + flash.read_size = regs[0].reg_size; if (nregs == 1) { flash.write_base = edev->resource[0].start; - flash.write_size = ebus_regs[0].reg_size; + flash.write_size = regs[0].reg_size; } else if (nregs == 2) { flash.write_base = edev->resource[1].start; - flash.write_size = ebus_regs[1].reg_size; + flash.write_size = regs[1].reg_size; } else { printk("flash: Strange number of regs %d\n", nregs); return -ENODEV; diff --git a/trunk/drivers/sbus/char/openprom.c b/trunk/drivers/sbus/char/openprom.c index cf5b476b5496..239e108b8ed1 100644 --- a/trunk/drivers/sbus/char/openprom.c +++ b/trunk/drivers/sbus/char/openprom.c @@ -243,8 +243,8 @@ static int openprom_sunos_ioctl(struct inode * inode, struct file * file, ((int *) opp->oprom_array)[1]); pcp = pdev->sysdata; - if (pcp != NULL) { - node = pcp->prom_node->node; + if (pcp != NULL && pcp->prom_node != -1 && pcp->prom_node) { + node = pcp->prom_node; data->current_node = node; *((int *)opp->oprom_array) = node; opp->oprom_size = sizeof(int); diff --git a/trunk/drivers/sbus/sbus.c b/trunk/drivers/sbus/sbus.c index 387a6aa8c020..5d30a3ebfccd 100644 --- a/trunk/drivers/sbus/sbus.c +++ b/trunk/drivers/sbus/sbus.c @@ -1,6 +1,7 @@ -/* sbus.c: SBus support routines. +/* $Id: sbus.c,v 1.100 2002/01/24 15:36:24 davem Exp $ + * sbus.c: SBus support routines. * - * Copyright (C) 1995, 2006 David S. Miller (davem@davemloft.net) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ #include @@ -13,76 +14,237 @@ #include #include #include -#include -#include #include #include -struct sbus_bus *sbus_root; +struct sbus_bus *sbus_root = NULL; -static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev) -{ - unsigned long base; - void *pval; - int len; +static struct linux_prom_irqs irqs[PROMINTR_MAX] __initdata = { { 0 } }; +#ifdef CONFIG_SPARC32 +static int interrupts[PROMINTR_MAX] __initdata = { 0 }; +#endif - sdev->prom_node = dp->node; - strcpy(sdev->prom_name, dp->name); +#ifdef CONFIG_PCI +extern int pcic_present(void); +#endif - pval = of_get_property(dp, "reg", &len); - sdev->num_registers = 0; - if (pval) { - memcpy(sdev->reg_addrs, pval, len); +/* Perhaps when I figure out more about the iommu we'll put a + * device registration routine here that probe_sbus() calls to + * setup the iommu for each Sbus. + */ + +/* We call this for each SBus device, and fill the structure based + * upon the prom device tree. We return the start of memory after + * the things we have allocated. + */ - sdev->num_registers = - len / sizeof(struct linux_prom_registers); +/* #define DEBUG_FILL */ - base = (unsigned long) sdev->reg_addrs[0].phys_addr; +static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev) +{ + unsigned long address, base; + int len; - /* Compute the slot number. */ - if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) - sdev->slot = sbus_dev_slot(base); - else - sdev->slot = sdev->reg_addrs[0].which_io; + sdev->prom_node = prom_node; + prom_getstring(prom_node, "name", + sdev->prom_name, sizeof(sdev->prom_name)); + address = prom_getint(prom_node, "address"); + len = prom_getproperty(prom_node, "reg", + (char *) sdev->reg_addrs, + sizeof(sdev->reg_addrs)); + if (len == -1) { + sdev->num_registers = 0; + goto no_regs; } - pval = of_get_property(dp, "ranges", &len); - sdev->num_device_ranges = 0; - if (pval) { - memcpy(sdev->device_ranges, pval, len); - sdev->num_device_ranges = - len / sizeof(struct linux_prom_ranges); + if (len % sizeof(struct linux_prom_registers)) { + prom_printf("fill_sbus_device: proplen for regs of %s " + " was %d, need multiple of %d\n", + sdev->prom_name, len, + (int) sizeof(struct linux_prom_registers)); + prom_halt(); + } + if (len > (sizeof(struct linux_prom_registers) * PROMREG_MAX)) { + prom_printf("fill_sbus_device: Too many register properties " + "for device %s, len=%d\n", + sdev->prom_name, len); + prom_halt(); } + sdev->num_registers = len / sizeof(struct linux_prom_registers); + sdev->ranges_applied = 0; - sbus_fill_device_irq(sdev); + base = (unsigned long) sdev->reg_addrs[0].phys_addr; - sdev->ofdev.node = dp; - if (sdev->parent) - sdev->ofdev.dev.parent = &sdev->parent->ofdev.dev; - else - sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev; - sdev->ofdev.dev.bus = &sbus_bus_type; - strcpy(sdev->ofdev.dev.bus_id, dp->path_component_name); + /* Compute the slot number. */ + if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) { + sdev->slot = sbus_dev_slot(base); + } else { + sdev->slot = sdev->reg_addrs[0].which_io; + } - if (of_device_register(&sdev->ofdev) != 0) - printk(KERN_DEBUG "sbus: device registration error for %s!\n", - sdev->ofdev.dev.bus_id); +no_regs: + len = prom_getproperty(prom_node, "ranges", + (char *)sdev->device_ranges, + sizeof(sdev->device_ranges)); + if (len == -1) { + sdev->num_device_ranges = 0; + goto no_ranges; + } + if (len % sizeof(struct linux_prom_ranges)) { + prom_printf("fill_sbus_device: proplen for ranges of %s " + " was %d, need multiple of %d\n", + sdev->prom_name, len, + (int) sizeof(struct linux_prom_ranges)); + prom_halt(); + } + if (len > (sizeof(struct linux_prom_ranges) * PROMREG_MAX)) { + prom_printf("fill_sbus_device: Too many range properties " + "for device %s, len=%d\n", + sdev->prom_name, len); + prom_halt(); + } + sdev->num_device_ranges = + len / sizeof(struct linux_prom_ranges); + +no_ranges: + /* XXX Unfortunately, IRQ issues are very arch specific. + * XXX Pull this crud out into an arch specific area + * XXX at some point. -DaveM + */ +#ifdef CONFIG_SPARC64 + len = prom_getproperty(prom_node, "interrupts", + (char *) irqs, sizeof(irqs)); + if (len == -1 || len == 0) { + sdev->irqs[0] = 0; + sdev->num_irqs = 0; + } else { + unsigned int pri = irqs[0].pri; + + sdev->num_irqs = 1; + if (pri < 0x20) + pri += sdev->slot * 8; + + sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); + } +#endif /* CONFIG_SPARC64 */ + +#ifdef CONFIG_SPARC32 + len = prom_getproperty(prom_node, "intr", + (char *)irqs, sizeof(irqs)); + if (len != -1) { + sdev->num_irqs = len / 8; + if (sdev->num_irqs == 0) { + sdev->irqs[0] = 0; + } else if (sparc_cpu_model == sun4d) { + extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq); + + for (len = 0; len < sdev->num_irqs; len++) + sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri); + } else { + for (len = 0; len < sdev->num_irqs; len++) + sdev->irqs[len] = irqs[len].pri; + } + } else { + /* No "intr" node found-- check for "interrupts" node. + * This node contains SBus interrupt levels, not IPLs + * as in "intr", and no vector values. We convert + * SBus interrupt levels to PILs (platform specific). + */ + len = prom_getproperty(prom_node, "interrupts", + (char *)interrupts, sizeof(interrupts)); + if (len == -1) { + sdev->irqs[0] = 0; + sdev->num_irqs = 0; + } else { + sdev->num_irqs = len / sizeof(int); + for (len = 0; len < sdev->num_irqs; len++) { + sdev->irqs[len] = sbint_to_irq(sdev, interrupts[len]); + } + } + } +#endif /* CONFIG_SPARC32 */ } -static void __init sbus_bus_ranges_init(struct device_node *dp, struct sbus_bus *sbus) +/* This routine gets called from whoever needs the sbus first, to scan + * the SBus device tree. Currently it just prints out the devices + * found on the bus and builds trees of SBUS structs and attached + * devices. + */ + +extern void iommu_init(int iommu_node, struct sbus_bus *sbus); +extern void iounit_init(int sbi_node, int iounit_node, struct sbus_bus *sbus); +void sun4_init(void); +#ifdef CONFIG_SUN_AUXIO +extern void auxio_probe(void); +#endif + +static void __init sbus_do_child_siblings(int start_node, + struct sbus_dev *child, + struct sbus_dev *parent, + struct sbus_bus *sbus) { - void *pval; - int len; + struct sbus_dev *this_dev = child; + int this_node = start_node; + + /* Child already filled in, just need to traverse siblings. */ + child->child = NULL; + child->parent = parent; + while((this_node = prom_getsibling(this_node)) != 0) { + this_dev->next = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); + this_dev = this_dev->next; + this_dev->next = NULL; + this_dev->parent = parent; + + this_dev->bus = sbus; + fill_sbus_device(this_node, this_dev); + + if(prom_getchild(this_node)) { + this_dev->child = kmalloc(sizeof(struct sbus_dev), + GFP_ATOMIC); + this_dev->child->bus = sbus; + this_dev->child->next = NULL; + fill_sbus_device(prom_getchild(this_node), this_dev->child); + sbus_do_child_siblings(prom_getchild(this_node), + this_dev->child, this_dev, sbus); + } else { + this_dev->child = NULL; + } + } +} - pval = of_get_property(dp, "ranges", &len); - sbus->num_sbus_ranges = 0; - if (pval) { - memcpy(sbus->sbus_ranges, pval, len); - sbus->num_sbus_ranges = - len / sizeof(struct linux_prom_ranges); +/* + * XXX This functions appears to be a distorted version of + * prom_sbus_ranges_init(), with all sun4d stuff cut away. + * Ask DaveM what is going on here, how is sun4d supposed to work... XXX + */ +/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */ + +static void __init sbus_bus_ranges_init(int parent_node, struct sbus_bus *sbus) +{ + int len; - sbus_arch_bus_ranges_init(dp->parent, sbus); + len = prom_getproperty(sbus->prom_node, "ranges", + (char *) sbus->sbus_ranges, + sizeof(sbus->sbus_ranges)); + if (len == -1 || len == 0) { + sbus->num_sbus_ranges = 0; + return; } + sbus->num_sbus_ranges = len / sizeof(struct linux_prom_ranges); +#ifdef CONFIG_SPARC32 + if (sparc_cpu_model == sun4d) { + struct linux_prom_ranges iounit_ranges[PROMREG_MAX]; + int num_iounit_ranges; + + len = prom_getproperty(parent_node, "ranges", + (char *) iounit_ranges, + sizeof (iounit_ranges)); + if (len != -1) { + num_iounit_ranges = (len/sizeof(struct linux_prom_ranges)); + prom_adjust_ranges (sbus->sbus_ranges, sbus->num_sbus_ranges, iounit_ranges, num_iounit_ranges); + } + } +#endif } static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges, @@ -160,127 +322,241 @@ static void __init sbus_fixup_all_regs(struct sbus_dev *first_sdev) } } -/* We preserve the "probe order" of these bus and device lists to give - * the same ordering as the old code. - */ -static void __init sbus_insert(struct sbus_bus *sbus, struct sbus_bus **root) -{ - while (*root) - root = &(*root)->next; - *root = sbus; - sbus->next = NULL; -} +extern void register_proc_sparc_ioport(void); +extern void firetruck_init(void); -static void __init sdev_insert(struct sbus_dev *sdev, struct sbus_dev **root) -{ - while (*root) - root = &(*root)->next; - *root = sdev; - sdev->next = NULL; -} +#ifdef CONFIG_SUN4 +extern void sun4_dvma_init(void); +#endif -static void __init walk_children(struct device_node *dp, struct sbus_dev *parent, struct sbus_bus *sbus) +static int __init sbus_init(void) { - dp = dp->child; - while (dp) { - struct sbus_dev *sdev; - - sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC); - if (sdev) { - sdev_insert(sdev, &parent->child); - - sdev->bus = sbus; - sdev->parent = parent; + int nd, this_sbus, sbus_devs, topnd, iommund; + unsigned int sbus_clock; + struct sbus_bus *sbus; + struct sbus_dev *this_dev; + int num_sbus = 0; /* How many did we find? */ - fill_sbus_device(dp, sdev); +#ifdef CONFIG_SPARC32 + register_proc_sparc_ioport(); +#endif - walk_children(dp, sdev, sbus); +#ifdef CONFIG_SUN4 + sun4_dvma_init(); + return 0; +#endif + + topnd = prom_getchild(prom_root_node); + + /* Finding the first sbus is a special case... */ + iommund = 0; + if(sparc_cpu_model == sun4u) { + nd = prom_searchsiblings(topnd, "sbus"); + if(nd == 0) { +#ifdef CONFIG_PCI + if (!pcic_present()) { + prom_printf("Neither SBUS nor PCI found.\n"); + prom_halt(); + } else { +#ifdef CONFIG_SPARC64 + firetruck_init(); +#endif + } + return 0; +#else + prom_printf("YEEE, UltraSparc sbus not found\n"); + prom_halt(); +#endif + } + } else if(sparc_cpu_model == sun4d) { + if((iommund = prom_searchsiblings(topnd, "io-unit")) == 0 || + (nd = prom_getchild(iommund)) == 0 || + (nd = prom_searchsiblings(nd, "sbi")) == 0) { + panic("sbi not found"); + } + } else if((nd = prom_searchsiblings(topnd, "sbus")) == 0) { + if((iommund = prom_searchsiblings(topnd, "iommu")) == 0 || + (nd = prom_getchild(iommund)) == 0 || + (nd = prom_searchsiblings(nd, "sbus")) == 0) { +#ifdef CONFIG_PCI + if (!pcic_present()) { + prom_printf("Neither SBUS nor PCI found.\n"); + prom_halt(); + } + return 0; +#else + /* No reason to run further - the data access trap will occur. */ + panic("sbus not found"); +#endif } - dp = dp->sibling; } -} - -static void __init build_one_sbus(struct device_node *dp, int num_sbus) -{ - struct sbus_bus *sbus; - unsigned int sbus_clock; - struct device_node *dev_dp; - - sbus = kzalloc(sizeof(struct sbus_bus), GFP_ATOMIC); - if (!sbus) - return; - - sbus_insert(sbus, &sbus_root); - sbus->prom_node = dp->node; - - sbus_setup_iommu(sbus, dp); - - printk("sbus%d: ", num_sbus); - - sbus_clock = of_getintprop_default(dp, "clock-frequency", - (25*1000*1000)); - sbus->clock_freq = sbus_clock; - - printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000), - (int) (((sbus_clock/1000)%1000 != 0) ? - (((sbus_clock/1000)%1000) + 1000) : 0)); - - strcpy(sbus->prom_name, dp->name); - - sbus_setup_arch_props(sbus, dp); - - sbus_bus_ranges_init(dp, sbus); - sbus->ofdev.node = dp; - sbus->ofdev.dev.parent = NULL; - sbus->ofdev.dev.bus = &sbus_bus_type; - strcpy(sbus->ofdev.dev.bus_id, dp->path_component_name); - - if (of_device_register(&sbus->ofdev) != 0) - printk(KERN_DEBUG "sbus: device registration error for %s!\n", - sbus->ofdev.dev.bus_id); - - dev_dp = dp->child; - while (dev_dp) { - struct sbus_dev *sdev; + /* Ok, we've found the first one, allocate first SBus struct + * and place in chain. + */ + sbus = sbus_root = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC); + sbus->next = NULL; + sbus->prom_node = nd; + this_sbus = nd; - sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC); - if (sdev) { - sdev_insert(sdev, &sbus->devices); + if(iommund && sparc_cpu_model != sun4u && sparc_cpu_model != sun4d) + iommu_init(iommund, sbus); - sdev->bus = sbus; - sdev->parent = NULL; - fill_sbus_device(dev_dp, sdev); + /* Loop until we find no more SBUS's */ + while(this_sbus) { +#ifdef CONFIG_SPARC64 + /* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */ + if(sparc_cpu_model == sun4u) { + extern void sbus_iommu_init(int prom_node, struct sbus_bus *sbus); - walk_children(dev_dp, sdev, sbus); + sbus_iommu_init(this_sbus, sbus); + } +#endif /* CONFIG_SPARC64 */ + +#ifdef CONFIG_SPARC32 + if (sparc_cpu_model == sun4d) + iounit_init(this_sbus, iommund, sbus); +#endif /* CONFIG_SPARC32 */ + printk("sbus%d: ", num_sbus); + sbus_clock = prom_getint(this_sbus, "clock-frequency"); + if(sbus_clock == -1) + sbus_clock = (25*1000*1000); + printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000), + (int) (((sbus_clock/1000)%1000 != 0) ? + (((sbus_clock/1000)%1000) + 1000) : 0)); + + prom_getstring(this_sbus, "name", + sbus->prom_name, sizeof(sbus->prom_name)); + sbus->clock_freq = sbus_clock; +#ifdef CONFIG_SPARC32 + if (sparc_cpu_model == sun4d) { + sbus->devid = prom_getint(iommund, "device-id"); + sbus->board = prom_getint(iommund, "board#"); + } +#endif + + sbus_bus_ranges_init(iommund, sbus); + + sbus_devs = prom_getchild(this_sbus); + if (!sbus_devs) { + sbus->devices = NULL; + goto next_bus; } - dev_dp = dev_dp->sibling; - } - - sbus_fixup_all_regs(sbus->devices); - - dvma_init(sbus); -} -static int __init sbus_init(void) -{ - struct device_node *dp; - const char *sbus_name = "sbus"; - int num_sbus = 0; + sbus->devices = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); + + this_dev = sbus->devices; + this_dev->next = NULL; + + this_dev->bus = sbus; + this_dev->parent = NULL; + fill_sbus_device(sbus_devs, this_dev); + + /* Should we traverse for children? */ + if(prom_getchild(sbus_devs)) { + /* Allocate device node */ + this_dev->child = kmalloc(sizeof(struct sbus_dev), + GFP_ATOMIC); + /* Fill it */ + this_dev->child->bus = sbus; + this_dev->child->next = NULL; + fill_sbus_device(prom_getchild(sbus_devs), + this_dev->child); + sbus_do_child_siblings(prom_getchild(sbus_devs), + this_dev->child, + this_dev, + sbus); + } else { + this_dev->child = NULL; + } - if (sbus_arch_preinit()) - return 0; + while((sbus_devs = prom_getsibling(sbus_devs)) != 0) { + /* Allocate device node */ + this_dev->next = kmalloc(sizeof(struct sbus_dev), + GFP_ATOMIC); + this_dev = this_dev->next; + this_dev->next = NULL; + + /* Fill it */ + this_dev->bus = sbus; + this_dev->parent = NULL; + fill_sbus_device(sbus_devs, this_dev); + + /* Is there a child node hanging off of us? */ + if(prom_getchild(sbus_devs)) { + /* Get new device struct */ + this_dev->child = kmalloc(sizeof(struct sbus_dev), + GFP_ATOMIC); + /* Fill it */ + this_dev->child->bus = sbus; + this_dev->child->next = NULL; + fill_sbus_device(prom_getchild(sbus_devs), + this_dev->child); + sbus_do_child_siblings(prom_getchild(sbus_devs), + this_dev->child, + this_dev, + sbus); + } else { + this_dev->child = NULL; + } + } - if (sparc_cpu_model == sun4d) - sbus_name = "sbi"; + /* Walk all devices and apply parent ranges. */ + sbus_fixup_all_regs(sbus->devices); - for_each_node_by_name(dp, sbus_name) { - build_one_sbus(dp, num_sbus); + dvma_init(sbus); + next_bus: num_sbus++; + if(sparc_cpu_model == sun4u) { + this_sbus = prom_getsibling(this_sbus); + if(!this_sbus) + break; + this_sbus = prom_searchsiblings(this_sbus, "sbus"); + } else if(sparc_cpu_model == sun4d) { + iommund = prom_getsibling(iommund); + if(!iommund) + break; + iommund = prom_searchsiblings(iommund, "io-unit"); + if(!iommund) + break; + this_sbus = prom_searchsiblings(prom_getchild(iommund), "sbi"); + } else { + this_sbus = prom_getsibling(this_sbus); + if(!this_sbus) + break; + this_sbus = prom_searchsiblings(this_sbus, "sbus"); + } + if(this_sbus) { + sbus->next = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC); + sbus = sbus->next; + sbus->next = NULL; + sbus->prom_node = this_sbus; + } else { + break; + } + } /* while(this_sbus) */ + if (sparc_cpu_model == sun4d) { + extern void sun4d_init_sbi_irq(void); + sun4d_init_sbi_irq(); } - - sbus_arch_postinit(); + +#ifdef CONFIG_SPARC64 + if (sparc_cpu_model == sun4u) { + firetruck_init(); + } +#endif +#ifdef CONFIG_SUN_AUXIO + if (sparc_cpu_model == sun4u) + auxio_probe (); +#endif +#ifdef CONFIG_SPARC64 + if (sparc_cpu_model == sun4u) { + extern void clock_probe(void); + + clock_probe(); + } +#endif return 0; } diff --git a/trunk/drivers/scsi/esp.c b/trunk/drivers/scsi/esp.c index ddb512463b45..0a3e45d7a972 100644 --- a/trunk/drivers/scsi/esp.c +++ b/trunk/drivers/scsi/esp.c @@ -1,6 +1,7 @@ -/* esp.c: ESP Sun SCSI driver. +/* $Id: esp.c,v 1.101 2002/01/15 06:48:55 davem Exp $ + * esp.c: EnhancedScsiProcessor Sun SCSI driver code. * - * Copyright (C) 1995, 1998, 2006 David S. Miller (davem@davemloft.net) + * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu) */ /* TODO: @@ -184,6 +185,11 @@ enum { /*5*/ do_intr_end }; +/* The master ring of all esp hosts we are managing in this driver. */ +static struct esp *espchain; +static DEFINE_SPINLOCK(espchain_lock); +static int esps_running = 0; + /* Forward declarations. */ static irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs); @@ -688,6 +694,36 @@ static void __init esp_bootup_reset(struct esp *esp) sbus_readb(esp->eregs + ESP_INTRPT); } +static void esp_chain_add(struct esp *esp) +{ + spin_lock_irq(&espchain_lock); + if (espchain) { + struct esp *elink = espchain; + while (elink->next) + elink = elink->next; + elink->next = esp; + } else { + espchain = esp; + } + esp->next = NULL; + spin_unlock_irq(&espchain_lock); +} + +static void esp_chain_del(struct esp *esp) +{ + spin_lock_irq(&espchain_lock); + if (espchain == esp) { + espchain = esp->next; + } else { + struct esp *elink = espchain; + while (elink->next != esp) + elink = elink->next; + elink->next = esp->next; + } + esp->next = NULL; + spin_unlock_irq(&espchain_lock); +} + static int __init esp_find_dvma(struct esp *esp, struct sbus_dev *dma_sdev) { struct sbus_dev *sdev = esp->sdev; @@ -794,20 +830,19 @@ static int __init esp_register_irq(struct esp *esp) static void __init esp_get_scsi_id(struct esp *esp) { struct sbus_dev *sdev = esp->sdev; - struct device_node *dp = sdev->ofdev.node; - esp->scsi_id = of_getintprop_default(dp, - "initiator-id", - -1); + esp->scsi_id = prom_getintdefault(esp->prom_node, + "initiator-id", + -1); if (esp->scsi_id == -1) - esp->scsi_id = of_getintprop_default(dp, - "scsi-initiator-id", - -1); + esp->scsi_id = prom_getintdefault(esp->prom_node, + "scsi-initiator-id", + -1); if (esp->scsi_id == -1) esp->scsi_id = (sdev->bus == NULL) ? 7 : - of_getintprop_default(sdev->bus->ofdev.node, - "scsi-initiator-id", - 7); + prom_getintdefault(sdev->bus->prom_node, + "scsi-initiator-id", + 7); esp->ehost->this_id = esp->scsi_id; esp->scsi_id_mask = (1 << esp->scsi_id); @@ -1032,30 +1067,28 @@ static void __init esp_init_swstate(struct esp *esp) esp->prev_hme_dmacsr = 0xffffffff; } -static int __init detect_one_esp(struct scsi_host_template *tpnt, - struct device *dev, - struct sbus_dev *esp_dev, - struct sbus_dev *espdma, - struct sbus_bus *sbus, - int hme) +static int __init detect_one_esp(struct scsi_host_template *tpnt, struct sbus_dev *esp_dev, + struct sbus_dev *espdma, struct sbus_bus *sbus, + int id, int hme) { - static int instance; - struct Scsi_Host *esp_host = scsi_host_alloc(tpnt, sizeof(struct esp)); + struct Scsi_Host *esp_host = scsi_register(tpnt, sizeof(struct esp)); struct esp *esp; - if (!esp_host) - return -ENOMEM; - + if (!esp_host) { + printk("ESP: Cannot register SCSI host\n"); + return -1; + } if (hme) esp_host->max_id = 16; esp = (struct esp *) esp_host->hostdata; esp->ehost = esp_host; esp->sdev = esp_dev; - esp->esp_id = instance; + esp->esp_id = id; esp->prom_node = esp_dev->prom_node; prom_getstring(esp->prom_node, "name", esp->prom_name, sizeof(esp->prom_name)); + esp_chain_add(esp); if (esp_find_dvma(esp, espdma) < 0) goto fail_unlink; if (esp_map_regs(esp, hme) < 0) { @@ -1082,19 +1115,8 @@ static int __init detect_one_esp(struct scsi_host_template *tpnt, esp_bootup_reset(esp); - if (scsi_add_host(esp_host, dev)) - goto fail_free_irq; - - dev_set_drvdata(&esp_dev->ofdev.dev, esp); - - scsi_scan_host(esp_host); - instance++; - return 0; -fail_free_irq: - free_irq(esp->ehost->irq, esp); - fail_unmap_cmdarea: sbus_free_consistent(esp->sdev, 16, (void *) esp->esp_command, @@ -1107,98 +1129,119 @@ static int __init detect_one_esp(struct scsi_host_template *tpnt, esp->dma->allocated = 0; fail_unlink: - scsi_host_put(esp_host); + esp_chain_del(esp); + scsi_unregister(esp_host); return -1; } /* Detecting ESP chips on the machine. This is the simple and easy * version. */ -static int __devexit esp_remove_common(struct esp *esp) -{ - unsigned int irq = esp->ehost->irq; - - scsi_remove_host(esp->ehost); - - ESP_INTSOFF(esp->dregs); -#if 0 - esp_reset_dma(esp); - esp_reset_esp(esp); -#endif - - free_irq(irq, esp); - sbus_free_consistent(esp->sdev, 16, - (void *) esp->esp_command, esp->esp_command_dvma); - sbus_iounmap(esp->eregs, ESP_REG_SIZE); - esp->dma->allocated = 0; - - scsi_host_put(esp->ehost); - - return 0; -} - #ifdef CONFIG_SUN4 #include -static struct sbus_dev sun4_esp_dev; - -static int __init esp_sun4_probe(struct scsi_host_template *tpnt) +static int __init esp_detect(struct scsi_host_template *tpnt) { + static struct sbus_dev esp_dev; + int esps_in_use = 0; + + espchain = NULL; + if (sun4_esp_physaddr) { - memset(&sun4_esp_dev, 0, sizeof(esp_dev)); - sun4_esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr; - sun4_esp_dev.irqs[0] = 4; - sun4_esp_dev.resource[0].start = sun4_esp_physaddr; - sun4_esp_dev.resource[0].end = - sun4_esp_physaddr + ESP_REG_SIZE - 1; - sun4_esp_dev.resource[0].flags = IORESOURCE_IO; - - return detect_one_esp(tpnt, NULL, - &sun4_esp_dev, NULL, NULL, 0); + memset (&esp_dev, 0, sizeof(esp_dev)); + esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr; + esp_dev.irqs[0] = 4; + esp_dev.resource[0].start = sun4_esp_physaddr; + esp_dev.resource[0].end = sun4_esp_physaddr + ESP_REG_SIZE - 1; + esp_dev.resource[0].flags = IORESOURCE_IO; + + if (!detect_one_esp(tpnt, &esp_dev, NULL, NULL, 0, 0)) + esps_in_use++; + printk("ESP: Total of 1 ESP hosts found, %d actually in use.\n", esps_in_use); + esps_running = esps_in_use; } - return 0; + return esps_in_use; } -static int __devexit esp_sun4_remove(void) +#else /* !CONFIG_SUN4 */ + +static int __init esp_detect(struct scsi_host_template *tpnt) { - struct esp *esp = dev_get_drvdata(&dev->dev); + struct sbus_bus *sbus; + struct sbus_dev *esp_dev, *sbdev_iter; + int nesps = 0, esps_in_use = 0; - return esp_remove_common(esp); + espchain = 0; + if (!sbus_root) { +#ifdef CONFIG_PCI + return 0; +#else + panic("No SBUS in esp_detect()"); +#endif + } + for_each_sbus(sbus) { + for_each_sbusdev(sbdev_iter, sbus) { + struct sbus_dev *espdma = NULL; + int hme = 0; + + /* Is it an esp sbus device? */ + esp_dev = sbdev_iter; + if (strcmp(esp_dev->prom_name, "esp") && + strcmp(esp_dev->prom_name, "SUNW,esp")) { + if (!strcmp(esp_dev->prom_name, "SUNW,fas")) { + hme = 1; + espdma = esp_dev; + } else { + if (!esp_dev->child || + (strcmp(esp_dev->prom_name, "espdma") && + strcmp(esp_dev->prom_name, "dma"))) + continue; /* nope... */ + espdma = esp_dev; + esp_dev = esp_dev->child; + if (strcmp(esp_dev->prom_name, "esp") && + strcmp(esp_dev->prom_name, "SUNW,esp")) + continue; /* how can this happen? */ + } + } + + if (detect_one_esp(tpnt, esp_dev, espdma, sbus, nesps++, hme) < 0) + continue; + + esps_in_use++; + } /* for each sbusdev */ + } /* for each sbus */ + printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, + esps_in_use); + esps_running = esps_in_use; + return esps_in_use; } -#else /* !CONFIG_SUN4 */ +#endif /* !CONFIG_SUN4 */ -static int __devinit esp_sbus_probe(struct of_device *dev, const struct of_device_id *match) +/* + */ +static int esp_release(struct Scsi_Host *host) { - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - struct device_node *dp = dev->node; - struct sbus_dev *dma_sdev = NULL; - int hme = 0; - - if (dp->parent && - (!strcmp(dp->parent->name, "espdma") || - !strcmp(dp->parent->name, "dma"))) - dma_sdev = sdev->parent; - else if (!strcmp(dp->name, "SUNW,fas")) { - dma_sdev = sdev; - hme = 1; - } + struct esp *esp = (struct esp *) host->hostdata; - return detect_one_esp(match->data, &dev->dev, - sdev, dma_sdev, sdev->bus, hme); -} + ESP_INTSOFF(esp->dregs); +#if 0 + esp_reset_dma(esp); + esp_reset_esp(esp); +#endif -static int __devexit esp_sbus_remove(struct of_device *dev) -{ - struct esp *esp = dev_get_drvdata(&dev->dev); + free_irq(esp->ehost->irq, esp); + sbus_free_consistent(esp->sdev, 16, + (void *) esp->esp_command, esp->esp_command_dvma); + sbus_iounmap(esp->eregs, ESP_REG_SIZE); + esp->dma->allocated = 0; + esp_chain_del(esp); - return esp_remove_common(esp); + return 0; } -#endif /* !CONFIG_SUN4 */ - /* The info function will return whatever useful * information the developer sees fit. If not provided, then * the name field will be used instead. @@ -1372,11 +1415,18 @@ static int esp_host_info(struct esp *esp, char *ptr, off_t offset, int len) static int esp_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout) { - struct esp *esp = (struct esp *) host->hostdata; + struct esp *esp; if (inout) return -EINVAL; /* not yet */ + for_each_esp(esp) { + if (esp->ehost == host) + break; + } + if (!esp) + return -EINVAL; + if (start) *start = buffer; @@ -4327,12 +4377,15 @@ static void esp_slave_destroy(struct scsi_device *SDptr) SDptr->hostdata = NULL; } -static struct scsi_host_template esp_template = { - .module = THIS_MODULE, - .name = "esp", - .info = esp_info, +static struct scsi_host_template driver_template = { + .proc_name = "esp", + .proc_info = esp_proc_info, + .name = "Sun ESP 100/100a/200", + .detect = esp_detect, .slave_alloc = esp_slave_alloc, .slave_destroy = esp_slave_destroy, + .release = esp_release, + .info = esp_info, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, .eh_bus_reset_handler = esp_reset, @@ -4341,58 +4394,12 @@ static struct scsi_host_template esp_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, - .proc_name = "esp", - .proc_info = esp_proc_info, -}; - -#ifndef CONFIG_SUN4 -static struct of_device_id esp_match[] = { - { - .name = "SUNW,esp", - .data = &esp_template, - }, - { - .name = "SUNW,fas", - .data = &esp_template, - }, - { - .name = "esp", - .data = &esp_template, - }, - {}, -}; -MODULE_DEVICE_TABLE(of, esp_match); - -static struct of_platform_driver esp_sbus_driver = { - .name = "esp", - .match_table = esp_match, - .probe = esp_sbus_probe, - .remove = __devexit_p(esp_sbus_remove), }; -#endif - -static int __init esp_init(void) -{ -#ifdef CONFIG_SUN4 - return esp_sun4_probe(&esp_template); -#else - return of_register_driver(&esp_sbus_driver, &sbus_bus_type); -#endif -} -static void __exit esp_exit(void) -{ -#ifdef CONFIG_SUN4 - esp_sun4_remove(); -#else - of_unregister_driver(&esp_sbus_driver); -#endif -} +#include "scsi_module.c" -MODULE_DESCRIPTION("ESP Sun SCSI driver"); -MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); +MODULE_DESCRIPTION("EnhancedScsiProcessor Sun SCSI driver"); +MODULE_AUTHOR("David S. Miller (davem@redhat.com)"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -module_init(esp_init); -module_exit(esp_exit); diff --git a/trunk/drivers/scsi/esp.h b/trunk/drivers/scsi/esp.h index a98cda9121fc..73f7d6968ab6 100644 --- a/trunk/drivers/scsi/esp.h +++ b/trunk/drivers/scsi/esp.h @@ -403,4 +403,8 @@ struct esp { #define ESP_MHZ_TO_CYCLE(mhertz) ((1000000000) / ((mhertz) / 1000)) #define ESP_TICK(ccf, cycle) ((7682 * (ccf) * (cycle) / 1000)) +/* For our interrupt engine. */ +#define for_each_esp(esp) \ + for((esp) = espchain; (esp); (esp) = (esp)->next) + #endif /* !(_SPARC_ESP_H) */ diff --git a/trunk/drivers/scsi/qlogicpti.c b/trunk/drivers/scsi/qlogicpti.c index 329ead263714..2203103adced 100644 --- a/trunk/drivers/scsi/qlogicpti.c +++ b/trunk/drivers/scsi/qlogicpti.c @@ -1,6 +1,6 @@ /* qlogicpti.c: Performance Technologies QlogicISP sbus card driver. * - * Copyright (C) 1996, 2006 David S. Miller (davem@davemloft.net) + * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu) * * A lot of this driver was directly stolen from Erik H. Moe's PCI * Qlogic ISP driver. Mucho kudos to him for this code. @@ -46,6 +46,8 @@ #include #include + + #define MAX_TARGETS 16 #define MAX_LUNS 8 /* 32 for 1.31 F/W */ @@ -55,6 +57,7 @@ static struct qlogicpti *qptichain = NULL; static DEFINE_SPINLOCK(qptichain_lock); +static int qptis_running = 0; #define PACKB(a, b) (((a)<<4)|(b)) @@ -812,6 +815,173 @@ static int __init qpti_map_queues(struct qlogicpti *qpti) return 0; } +/* Detect all PTI Qlogic ISP's in the machine. */ +static int __init qlogicpti_detect(struct scsi_host_template *tpnt) +{ + struct qlogicpti *qpti; + struct Scsi_Host *qpti_host; + struct sbus_bus *sbus; + struct sbus_dev *sdev; + int nqptis = 0, nqptis_in_use = 0; + + tpnt->proc_name = "qlogicpti"; + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { + /* Is this a red snapper? */ + if (strcmp(sdev->prom_name, "ptisp") && + strcmp(sdev->prom_name, "PTI,ptisp") && + strcmp(sdev->prom_name, "QLGC,isp") && + strcmp(sdev->prom_name, "SUNW,isp")) + continue; + + /* Sometimes Antares cards come up not completely + * setup, and we get a report of a zero IRQ. + * Skip over them in such cases so we survive. + */ + if (sdev->irqs[0] == 0) { + printk("qpti%d: Adapter reports no interrupt, " + "skipping over this card.", nqptis); + continue; + } + + /* Yep, register and allocate software state. */ + qpti_host = scsi_register(tpnt, sizeof(struct qlogicpti)); + if (!qpti_host) { + printk("QPTI: Cannot register PTI Qlogic ISP SCSI host"); + continue; + } + qpti = (struct qlogicpti *) qpti_host->hostdata; + + /* We are wide capable, 16 targets. */ + qpti_host->max_id = MAX_TARGETS; + + /* Setup back pointers and misc. state. */ + qpti->qhost = qpti_host; + qpti->sdev = sdev; + qpti->qpti_id = nqptis++; + qpti->prom_node = sdev->prom_node; + prom_getstring(qpti->prom_node, "name", + qpti->prom_name, + sizeof(qpti->prom_name)); + + /* This is not correct, actually. There's a switch + * on the PTI cards that put them into "emulation" + * mode- i.e., report themselves as QLGC,isp + * instead of PTI,ptisp. The only real substantive + * difference between non-pti and pti cards is + * the tmon register. Which is possibly even + * there for Qlogic cards, but non-functional. + */ + qpti->is_pti = (strcmp (qpti->prom_name, "QLGC,isp") != 0); + + qpti_chain_add(qpti); + if (qpti_map_regs(qpti) < 0) + goto fail_unlink; + + if (qpti_register_irq(qpti) < 0) + goto fail_unmap_regs; + + qpti_get_scsi_id(qpti); + qpti_get_bursts(qpti); + qpti_get_clock(qpti); + + /* Clear out scsi_cmnd array. */ + memset(qpti->cmd_slots, 0, sizeof(qpti->cmd_slots)); + + if (qpti_map_queues(qpti) < 0) + goto fail_free_irq; + + /* Load the firmware. */ + if (qlogicpti_load_firmware(qpti)) + goto fail_unmap_queues; + if (qpti->is_pti) { + /* Check the PTI status reg. */ + if (qlogicpti_verify_tmon(qpti)) + goto fail_unmap_queues; + } + + /* Reset the ISP and init res/req queues. */ + if (qlogicpti_reset_hardware(qpti_host)) + goto fail_unmap_queues; + + printk("(Firmware v%d.%d.%d)", qpti->fware_majrev, + qpti->fware_minrev, qpti->fware_micrev); + { + char buffer[60]; + + prom_getstring (qpti->prom_node, + "isp-fcode", buffer, 60); + if (buffer[0]) + printk("(Firmware %s)", buffer); + if (prom_getbool(qpti->prom_node, "differential")) + qpti->differential = 1; + } + + printk (" [%s Wide, using %s interface]\n", + (qpti->ultra ? "Ultra" : "Fast"), + (qpti->differential ? "differential" : "single ended")); + + nqptis_in_use++; + continue; + + fail_unmap_queues: +#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) + sbus_free_consistent(qpti->sdev, + QSIZE(RES_QUEUE_LEN), + qpti->res_cpu, qpti->res_dvma); + sbus_free_consistent(qpti->sdev, + QSIZE(QLOGICPTI_REQ_QUEUE_LEN), + qpti->req_cpu, qpti->req_dvma); +#undef QSIZE + fail_free_irq: + free_irq(qpti->irq, qpti); + + fail_unmap_regs: + sbus_iounmap(qpti->qregs, + qpti->sdev->reg_addrs[0].reg_size); + if (qpti->is_pti) + sbus_iounmap(qpti->sreg, sizeof(unsigned char)); + fail_unlink: + qpti_chain_del(qpti); + scsi_unregister(qpti->qhost); + } + } + if (nqptis) + printk("QPTI: Total of %d PTI Qlogic/ISP hosts found, %d actually in use.\n", + nqptis, nqptis_in_use); + qptis_running = nqptis_in_use; + return nqptis; +} + +static int qlogicpti_release(struct Scsi_Host *host) +{ + struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; + + /* Remove visibility from IRQ handlers. */ + qpti_chain_del(qpti); + + /* Shut up the card. */ + sbus_writew(0, qpti->qregs + SBUS_CTRL); + + /* Free IRQ handler and unmap Qlogic,ISP and PTI status regs. */ + free_irq(qpti->irq, qpti); + +#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) + sbus_free_consistent(qpti->sdev, + QSIZE(RES_QUEUE_LEN), + qpti->res_cpu, qpti->res_dvma); + sbus_free_consistent(qpti->sdev, + QSIZE(QLOGICPTI_REQ_QUEUE_LEN), + qpti->req_cpu, qpti->req_dvma); +#undef QSIZE + + sbus_iounmap(qpti->qregs, qpti->sdev->reg_addrs[0].reg_size); + if (qpti->is_pti) + sbus_iounmap(qpti->sreg, sizeof(unsigned char)); + + return 0; +} + const char *qlogicpti_info(struct Scsi_Host *host) { static char buf[80]; @@ -1381,9 +1551,9 @@ static int qlogicpti_reset(struct scsi_cmnd *Cmnd) return return_status; } -static struct scsi_host_template qpti_template = { - .module = THIS_MODULE, - .name = "qlogicpti", +static struct scsi_host_template driver_template = { + .detect = qlogicpti_detect, + .release = qlogicpti_release, .info = qlogicpti_info, .queuecommand = qlogicpti_queuecommand_slow, .eh_abort_handler = qlogicpti_abort, @@ -1395,189 +1565,8 @@ static struct scsi_host_template qpti_template = { .use_clustering = ENABLE_CLUSTERING, }; -static int __devinit qpti_sbus_probe(struct of_device *dev, const struct of_device_id *match) -{ - static int nqptis; - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - struct device_node *dp = dev->node; - struct scsi_host_template *tpnt = match->data; - struct Scsi_Host *host; - struct qlogicpti *qpti; - char *fcode; - - /* Sometimes Antares cards come up not completely - * setup, and we get a report of a zero IRQ. - */ - if (sdev->irqs[0] == 0) - return -ENODEV; - - host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti)); - if (!host) - return -ENOMEM; - - qpti = (struct qlogicpti *) host->hostdata; - - host->max_id = MAX_TARGETS; - qpti->qhost = host; - qpti->sdev = sdev; - qpti->qpti_id = nqptis; - qpti->prom_node = sdev->prom_node; - strcpy(qpti->prom_name, sdev->ofdev.node->name); - qpti->is_pti = strcmp(qpti->prom_name, "QLGC,isp"); - - if (qpti_map_regs(qpti) < 0) - goto fail_unlink; - - if (qpti_register_irq(qpti) < 0) - goto fail_unmap_regs; - - qpti_get_scsi_id(qpti); - qpti_get_bursts(qpti); - qpti_get_clock(qpti); - - /* Clear out scsi_cmnd array. */ - memset(qpti->cmd_slots, 0, sizeof(qpti->cmd_slots)); - - if (qpti_map_queues(qpti) < 0) - goto fail_free_irq; - - /* Load the firmware. */ - if (qlogicpti_load_firmware(qpti)) - goto fail_unmap_queues; - if (qpti->is_pti) { - /* Check the PTI status reg. */ - if (qlogicpti_verify_tmon(qpti)) - goto fail_unmap_queues; - } - - /* Reset the ISP and init res/req queues. */ - if (qlogicpti_reset_hardware(host)) - goto fail_unmap_queues; - - if (scsi_add_host(host, &dev->dev)) - goto fail_unmap_queues; - - printk("(Firmware v%d.%d.%d)", qpti->fware_majrev, - qpti->fware_minrev, qpti->fware_micrev); - - fcode = of_get_property(dp, "isp-fcode", NULL); - if (fcode && fcode[0]) - printk("(Firmware %s)", fcode); - if (of_find_property(dp, "differential", NULL) != NULL) - qpti->differential = 1; - - printk (" [%s Wide, using %s interface]\n", - (qpti->ultra ? "Ultra" : "Fast"), - (qpti->differential ? "differential" : "single ended")); - - dev_set_drvdata(&sdev->ofdev.dev, qpti); - - qpti_chain_add(qpti); - - scsi_scan_host(host); - nqptis++; - - return 0; - -fail_unmap_queues: -#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) - sbus_free_consistent(qpti->sdev, - QSIZE(RES_QUEUE_LEN), - qpti->res_cpu, qpti->res_dvma); - sbus_free_consistent(qpti->sdev, - QSIZE(QLOGICPTI_REQ_QUEUE_LEN), - qpti->req_cpu, qpti->req_dvma); -#undef QSIZE - -fail_unmap_regs: - sbus_iounmap(qpti->qregs, - qpti->sdev->reg_addrs[0].reg_size); - if (qpti->is_pti) - sbus_iounmap(qpti->sreg, sizeof(unsigned char)); - -fail_free_irq: - free_irq(qpti->irq, qpti); - -fail_unlink: - scsi_host_put(host); - - return -ENODEV; -} - -static int __devexit qpti_sbus_remove(struct of_device *dev) -{ - struct qlogicpti *qpti = dev_get_drvdata(&dev->dev); - - qpti_chain_del(qpti); - - scsi_remove_host(qpti->qhost); - - /* Shut up the card. */ - sbus_writew(0, qpti->qregs + SBUS_CTRL); - - /* Free IRQ handler and unmap Qlogic,ISP and PTI status regs. */ - free_irq(qpti->irq, qpti); - -#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) - sbus_free_consistent(qpti->sdev, - QSIZE(RES_QUEUE_LEN), - qpti->res_cpu, qpti->res_dvma); - sbus_free_consistent(qpti->sdev, - QSIZE(QLOGICPTI_REQ_QUEUE_LEN), - qpti->req_cpu, qpti->req_dvma); -#undef QSIZE - - sbus_iounmap(qpti->qregs, qpti->sdev->reg_addrs[0].reg_size); - if (qpti->is_pti) - sbus_iounmap(qpti->sreg, sizeof(unsigned char)); - - scsi_host_put(qpti->qhost); - - return 0; -} - -static struct of_device_id qpti_match[] = { - { - .name = "ptisp", - .data = &qpti_template, - }, - { - .name = "PTI,ptisp", - .data = &qpti_template, - }, - { - .name = "QLGC,isp", - .data = &qpti_template, - }, - { - .name = "SUNW,isp", - .data = &qpti_template, - }, - {}, -}; -MODULE_DEVICE_TABLE(of, qpti_match); - -static struct of_platform_driver qpti_sbus_driver = { - .name = "qpti", - .match_table = qpti_match, - .probe = qpti_sbus_probe, - .remove = __devexit_p(qpti_sbus_remove), -}; -static int __init qpti_init(void) -{ - return of_register_driver(&qpti_sbus_driver, &sbus_bus_type); -} - -static void __exit qpti_exit(void) -{ - of_unregister_driver(&qpti_sbus_driver); -} +#include "scsi_module.c" -MODULE_DESCRIPTION("QlogicISP SBUS driver"); -MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); MODULE_LICENSE("GPL"); -MODULE_VERSION("2.0"); -module_init(qpti_init); -module_exit(qpti_exit); diff --git a/trunk/drivers/serial/sunhv.c b/trunk/drivers/serial/sunhv.c index ba22e256c6f7..f137804b3133 100644 --- a/trunk/drivers/serial/sunhv.c +++ b/trunk/drivers/serial/sunhv.c @@ -427,32 +427,31 @@ static int __init hv_console_compatible(char *buf, int len) static unsigned int __init get_interrupt(void) { - struct device_node *dev_node; - - dev_node = sun4v_vdev_root->child; - while (dev_node != NULL) { - struct property *prop; - - if (strcmp(dev_node->name, "console")) - goto next_sibling; + const char *cons_str = "console"; + const char *compat_str = "compatible"; + int node = prom_getchild(sun4v_vdev_root); + char buf[64]; + int err, len; + + node = prom_searchsiblings(node, cons_str); + if (!node) + return 0; - prop = of_find_property(dev_node, "compatible", NULL); - if (!prop) - goto next_sibling; + len = prom_getproplen(node, compat_str); + if (len == 0 || len == -1) + return 0; - if (hv_console_compatible(prop->value, prop->length)) - break; + err = prom_getproperty(node, compat_str, buf, 64); + if (err == -1) + return 0; - next_sibling: - dev_node = dev_node->sibling; - } - if (!dev_node) + if (!hv_console_compatible(buf, len)) return 0; /* Ok, the this is the OBP node for the sun4v hypervisor * console device. Decode the interrupt. */ - return sun4v_vdev_device_interrupt(dev_node); + return sun4v_vdev_device_interrupt(node); } static int __init sunhv_init(void) diff --git a/trunk/drivers/serial/sunsab.c b/trunk/drivers/serial/sunsab.c index e4c0fd2d6a9d..bfbe9dc90cca 100644 --- a/trunk/drivers/serial/sunsab.c +++ b/trunk/drivers/serial/sunsab.c @@ -984,19 +984,19 @@ static void __init for_each_sab_edev(void (*callback)(struct linux_ebus_device * for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "se")) { + if (!strcmp(edev->prom_name, "se")) { callback(edev, arg); continue; - } else if (!strcmp(edev->prom_node->name, "serial")) { - char *compat; + } else if (!strcmp(edev->prom_name, "serial")) { + char compat[32]; int clen; /* On RIO this can be an SE, check it. We could * just check ebus->is_rio, but this is more portable. */ - compat = of_get_property(edev->prom_node, - "compatible", &clen); - if (compat && clen > 0) { + clen = prom_getproperty(edev->prom_node, "compatible", + compat, sizeof(compat)); + if (clen > 0) { if (strncmp(compat, "sab82532", 8) == 0) { callback(edev, arg); continue; diff --git a/trunk/drivers/serial/sunsu.c b/trunk/drivers/serial/sunsu.c index 0268b307c01e..4cdb610cdd37 100644 --- a/trunk/drivers/serial/sunsu.c +++ b/trunk/drivers/serial/sunsu.c @@ -1053,7 +1053,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) */ for_each_ebus(ebus) { for_each_ebusdev(dev, ebus) { - if (dev->prom_node->node == up->port_node) { + if (dev->prom_node == up->port_node) { /* * The EBus is broken on sparc; it delivers * virtual addresses in resources. Oh well... @@ -1073,7 +1073,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) #ifdef CONFIG_SPARC64 for_each_isa(isa_br) { for_each_isadev(isa_dev, isa_br) { - if (isa_dev->prom_node->node == up->port_node) { + if (isa_dev->prom_node == up->port_node) { /* Same on sparc64. Cool architecure... */ up->port.membase = (char *) isa_dev->resource.start; up->port.mapbase = isa_dev->resource.start; diff --git a/trunk/drivers/serial/sunzilog.c b/trunk/drivers/serial/sunzilog.c index 76c9bac9271f..5b6569728a9c 100644 --- a/trunk/drivers/serial/sunzilog.c +++ b/trunk/drivers/serial/sunzilog.c @@ -1106,7 +1106,7 @@ static struct zilog_layout __iomem * __init get_zs_sun4u(int chip, int zsnode) + FHC_UREGS_ICLR; imap = central_bus->child->fhc_regs.uregs + FHC_UREGS_IMAP; - zilog_irq = build_irq(0, iclr, imap); + zilog_irq = build_irq(12, 0, iclr, imap); } else { err = prom_getproperty(zsnode, "interrupts", (char *) &sun4u_ino, diff --git a/trunk/drivers/usb/core/devio.c b/trunk/drivers/usb/core/devio.c index bcbeaf7101d1..3f8e06279c92 100644 --- a/trunk/drivers/usb/core/devio.c +++ b/trunk/drivers/usb/core/devio.c @@ -1078,7 +1078,9 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg) if (copy_from_user(&uurb, arg, sizeof(uurb))) return -EFAULT; - return proc_do_submiturb(ps, &uurb, (((struct usbdevfs_urb __user *)arg)->iso_frame_desc), arg); + return proc_do_submiturb(ps, &uurb, + (struct usbdevfs_iso_packet_desc __user *)uurb.iso_frame_desc, + arg); } static int proc_unlinkurb(struct dev_state *ps, void __user *arg) @@ -1203,7 +1205,9 @@ static int proc_submiturb_compat(struct dev_state *ps, void __user *arg) if (get_urb32(&uurb,(struct usbdevfs_urb32 *)arg)) return -EFAULT; - return proc_do_submiturb(ps, &uurb, ((struct usbdevfs_urb32 __user *)arg)->iso_frame_desc, arg); + return proc_do_submiturb(ps, &uurb, + (struct usbdevfs_iso_packet_desc __user *)uurb.iso_frame_desc, + arg); } static int processcompl_compat(struct async *as, void __user * __user *arg) diff --git a/trunk/drivers/video/aty/atyfb_base.c b/trunk/drivers/video/aty/atyfb_base.c index c054bb28b1c4..eb6aa42be60e 100644 --- a/trunk/drivers/video/aty/atyfb_base.c +++ b/trunk/drivers/video/aty/atyfb_base.c @@ -2966,7 +2966,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, } pcp = pdev->sysdata; - if (node == pcp->prom_node->node) { + if (node == pcp->prom_node) { struct fb_var_screeninfo *var = &default_var; unsigned int N, P, Q, M, T, R; u32 v_total, h_total; diff --git a/trunk/drivers/video/intelfb/intelfb.h b/trunk/drivers/video/intelfb/intelfb.h index e290d7460e1b..469b06c29180 100644 --- a/trunk/drivers/video/intelfb/intelfb.h +++ b/trunk/drivers/video/intelfb/intelfb.h @@ -237,7 +237,7 @@ struct intelfb_info { u32 fb_start; /* ring buffer */ - u32 ring_head; + u8 __iomem *ring_head; u32 ring_tail; u32 ring_tail_mask; u32 ring_space; diff --git a/trunk/drivers/video/intelfb/intelfbdrv.c b/trunk/drivers/video/intelfb/intelfbdrv.c index 0a0a8b199ecc..076fa56be192 100644 --- a/trunk/drivers/video/intelfb/intelfbdrv.c +++ b/trunk/drivers/video/intelfb/intelfbdrv.c @@ -707,7 +707,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) + (dinfo->ring.offset << 12); dinfo->ring.virtual = dinfo->aperture.virtual + (dinfo->ring.offset << 12); - dinfo->ring_head = 0; + dinfo->ring_head = dinfo->ring.virtual; } if (dinfo->hwcursor) { agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY @@ -766,18 +766,18 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) if (mtrr) set_mtrr(dinfo); - DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%p)\n", + DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%x)\n", dinfo->fb.physical, dinfo->fb.offset, dinfo->fb.size, - dinfo->fb.virtual); - DBG_MSG("MMIO: 0x%x/0x%x (0x%p)\n", + (u32 __iomem ) dinfo->fb.virtual); + DBG_MSG("MMIO: 0x%x/0x%x (0x%x)\n", dinfo->mmio_base_phys, INTEL_REG_SIZE, - dinfo->mmio_base); - DBG_MSG("ring buffer: 0x%x/0x%x (0x%p)\n", + (u32 __iomem) dinfo->mmio_base); + DBG_MSG("ring buffer: 0x%x/0x%x (0x%x)\n", dinfo->ring.physical, dinfo->ring.size, - dinfo->ring.virtual); - DBG_MSG("HW cursor: 0x%x/0x%x (0x%p) (offset 0x%x) (phys 0x%x)\n", + (u32 __iomem ) dinfo->ring.virtual); + DBG_MSG("HW cursor: 0x%x/0x%x (0x%x) (offset 0x%x) (phys 0x%x)\n", dinfo->cursor.physical, dinfo->cursor.size, - dinfo->cursor.virtual, dinfo->cursor.offset, + (u32 __iomem ) dinfo->cursor.virtual, dinfo->cursor.offset, dinfo->cursor.physical); DBG_MSG("options: vram = %d, accel = %d, hwcursor = %d, fixed = %d, " diff --git a/trunk/drivers/video/intelfb/intelfbhw.c b/trunk/drivers/video/intelfb/intelfbhw.c index 7533b3dd08ac..426b7430b125 100644 --- a/trunk/drivers/video/intelfb/intelfbhw.c +++ b/trunk/drivers/video/intelfb/intelfbhw.c @@ -1423,17 +1423,19 @@ wait_ring(struct intelfb_info *dinfo, int n) end = jiffies + (HZ * 3); while (dinfo->ring_space < n) { - dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK; - if (dinfo->ring_tail + RING_MIN_FREE < dinfo->ring_head) - dinfo->ring_space = dinfo->ring_head + dinfo->ring_head = (u8 __iomem *)(INREG(PRI_RING_HEAD) & + RING_HEAD_MASK); + if (dinfo->ring_tail + RING_MIN_FREE < + (u32 __iomem) dinfo->ring_head) + dinfo->ring_space = (u32 __iomem) dinfo->ring_head - (dinfo->ring_tail + RING_MIN_FREE); else dinfo->ring_space = (dinfo->ring.size + - dinfo->ring_head) + (u32 __iomem) dinfo->ring_head) - (dinfo->ring_tail + RING_MIN_FREE); - if (dinfo->ring_head != last_head) { + if ((u32 __iomem) dinfo->ring_head != last_head) { end = jiffies + (HZ * 3); - last_head = dinfo->ring_head; + last_head = (u32 __iomem) dinfo->ring_head; } i++; if (time_before(end, jiffies)) { @@ -1493,13 +1495,15 @@ refresh_ring(struct intelfb_info *dinfo) DBG_MSG("refresh_ring\n"); #endif - dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK; + dinfo->ring_head = (u8 __iomem *) (INREG(PRI_RING_HEAD) & + RING_HEAD_MASK); dinfo->ring_tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK; - if (dinfo->ring_tail + RING_MIN_FREE < dinfo->ring_head) - dinfo->ring_space = dinfo->ring_head + if (dinfo->ring_tail + RING_MIN_FREE < (u32 __iomem)dinfo->ring_head) + dinfo->ring_space = (u32 __iomem) dinfo->ring_head - (dinfo->ring_tail + RING_MIN_FREE); else - dinfo->ring_space = (dinfo->ring.size + dinfo->ring_head) + dinfo->ring_space = (dinfo->ring.size + + (u32 __iomem) dinfo->ring_head) - (dinfo->ring_tail + RING_MIN_FREE); } diff --git a/trunk/include/asm-generic/rtc.h b/trunk/include/asm-generic/rtc.h index 4087037a4225..cef08db34ada 100644 --- a/trunk/include/asm-generic/rtc.h +++ b/trunk/include/asm-generic/rtc.h @@ -114,7 +114,6 @@ static inline unsigned int get_rtc_time(struct rtc_time *time) /* Set the current date and time in the real time clock. */ static inline int set_rtc_time(struct rtc_time *time) { - unsigned long flags; unsigned char mon, day, hrs, min, sec; unsigned char save_control, save_freq_select; unsigned int yrs; @@ -132,7 +131,7 @@ static inline int set_rtc_time(struct rtc_time *time) if (yrs > 255) /* They are unsigned */ return -EINVAL; - spin_lock_irqsave(&rtc_lock, flags); + spin_lock_irq(&rtc_lock); #ifdef CONFIG_MACH_DECSTATION real_yrs = yrs; leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) || @@ -153,7 +152,7 @@ static inline int set_rtc_time(struct rtc_time *time) * whether the chip is in binary mode or not. */ if (yrs > 169) { - spin_unlock_irqrestore(&rtc_lock, flags); + spin_unlock_irq(&rtc_lock); return -EINVAL; } @@ -188,7 +187,7 @@ static inline int set_rtc_time(struct rtc_time *time) CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - spin_unlock_irqrestore(&rtc_lock, flags); + spin_unlock_irq(&rtc_lock); return 0; } diff --git a/trunk/include/asm-sparc/ebus.h b/trunk/include/asm-sparc/ebus.h index 54652887c127..2d6a997c5b0c 100644 --- a/trunk/include/asm-sparc/ebus.h +++ b/trunk/include/asm-sparc/ebus.h @@ -13,14 +13,13 @@ #include #endif #include -#include -#include struct linux_ebus_child { struct linux_ebus_child *next; struct linux_ebus_device *parent; struct linux_ebus *bus; - struct device_node *prom_node; + int prom_node; + char prom_name[64]; struct resource resource[PROMREG_MAX]; int num_addrs; unsigned int irqs[PROMINTR_MAX]; @@ -28,27 +27,27 @@ struct linux_ebus_child { }; struct linux_ebus_device { - struct of_device ofdev; struct linux_ebus_device *next; struct linux_ebus_child *children; struct linux_ebus *bus; - struct device_node *prom_node; + int prom_node; + char prom_name[64]; struct resource resource[PROMREG_MAX]; int num_addrs; unsigned int irqs[PROMINTR_MAX]; int num_irqs; }; -#define to_ebus_device(d) container_of(d, struct linux_ebus_device, ofdev.dev) struct linux_ebus { - struct of_device ofdev; struct linux_ebus *next; struct linux_ebus_device *devices; struct linux_pbm_info *parent; struct pci_dev *self; - struct device_node *prom_node; + int prom_node; + char prom_name[64]; + struct linux_prom_ebus_ranges ebus_ranges[PROMREG_MAX]; + int num_ebus_ranges; }; -#define to_ebus(d) container_of(d, struct linux_ebus, ofdev.dev) struct linux_ebus_dma { unsigned int dcsr; diff --git a/trunk/include/asm-sparc/of_device.h b/trunk/include/asm-sparc/of_device.h deleted file mode 100644 index 4816d102f918..000000000000 --- a/trunk/include/asm-sparc/of_device.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef _ASM_SPARC_OF_DEVICE_H -#define _ASM_SPARC_OF_DEVICE_H -#ifdef __KERNEL__ - -#include -#include -#include - -extern struct bus_type ebus_bus_type; -extern struct bus_type sbus_bus_type; - -/* - * The of_device is a kind of "base class" that is a superset of - * struct device for use by devices attached to an OF node and - * probed using OF properties. - */ -struct of_device -{ - struct device_node *node; /* OF device node */ - struct device dev; /* Generic device interface */ -}; -#define to_of_device(d) container_of(d, struct of_device, dev) - -extern const struct of_device_id *of_match_device( - const struct of_device_id *matches, const struct of_device *dev); - -extern struct of_device *of_dev_get(struct of_device *dev); -extern void of_dev_put(struct of_device *dev); - -/* - * An of_platform_driver driver is attached to a basic of_device on - * the ISA, EBUS, and SBUS busses on sparc64. - */ -struct of_platform_driver -{ - char *name; - struct of_device_id *match_table; - struct module *owner; - - int (*probe)(struct of_device* dev, const struct of_device_id *match); - int (*remove)(struct of_device* dev); - - int (*suspend)(struct of_device* dev, pm_message_t state); - int (*resume)(struct of_device* dev); - int (*shutdown)(struct of_device* dev); - - struct device_driver driver; -}; -#define to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver) - -extern int of_register_driver(struct of_platform_driver *drv, - struct bus_type *bus); -extern void of_unregister_driver(struct of_platform_driver *drv); -extern int of_device_register(struct of_device *ofdev); -extern void of_device_unregister(struct of_device *ofdev); -extern struct of_device *of_platform_device_create(struct device_node *np, - const char *bus_id, - struct device *parent, - struct bus_type *bus); -extern void of_release_dev(struct device *dev); - -#endif /* __KERNEL__ */ -#endif /* _ASM_SPARC_OF_DEVICE_H */ diff --git a/trunk/include/asm-sparc/pbm.h b/trunk/include/asm-sparc/pbm.h index fedd9c6e875c..0aba3a82c2eb 100644 --- a/trunk/include/asm-sparc/pbm.h +++ b/trunk/include/asm-sparc/pbm.h @@ -22,7 +22,6 @@ #include #include -#include struct linux_pbm_info { int prom_node; @@ -41,7 +40,7 @@ struct linux_pbm_info { */ struct pcidev_cookie { struct linux_pbm_info *pbm; - struct device_node *prom_node; + int prom_node; }; #endif /* !(__SPARC_PBM_H) */ diff --git a/trunk/include/asm-sparc/prom.h b/trunk/include/asm-sparc/prom.h deleted file mode 100644 index c5e3d26eabd3..000000000000 --- a/trunk/include/asm-sparc/prom.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef _SPARC_PROM_H -#define _SPARC_PROM_H -#ifdef __KERNEL__ - - -/* - * Definitions for talking to the Open Firmware PROM on - * Power Macintosh computers. - * - * Copyright (C) 1996-2005 Paul Mackerras. - * - * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp. - * Updates for SPARC32 by David S. Miller - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include - -typedef u32 phandle; -typedef u32 ihandle; - -struct interrupt_info { - int line; - int sense; /* +ve/-ve logic, edge or level, etc. */ -}; - -struct property { - char *name; - int length; - void *value; - struct property *next; -}; - -struct device_node { - char *name; - char *type; - phandle node; - phandle linux_phandle; - int n_intrs; - struct interrupt_info *intrs; - char *path_component_name; - char *full_name; - - struct property *properties; - struct property *deadprops; /* removed properties */ - struct device_node *parent; - struct device_node *child; - struct device_node *sibling; - struct device_node *next; /* next device of same type */ - struct device_node *allnext; /* next in list of all nodes */ - struct proc_dir_entry *pde; /* this node's proc directory */ - struct kref kref; - unsigned long _flags; - void *data; -}; - -static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) -{ - dn->pde = de; -} - -extern struct device_node *of_find_node_by_name(struct device_node *from, - const char *name); -#define for_each_node_by_name(dn, name) \ - for (dn = of_find_node_by_name(NULL, name); dn; \ - dn = of_find_node_by_name(dn, name)) -extern struct device_node *of_find_node_by_type(struct device_node *from, - const char *type); -#define for_each_node_by_type(dn, type) \ - for (dn = of_find_node_by_type(NULL, type); dn; \ - dn = of_find_node_by_type(dn, type)) -extern struct device_node *of_find_compatible_node(struct device_node *from, - const char *type, const char *compat); -extern struct device_node *of_find_node_by_path(const char *path); -extern struct device_node *of_find_node_by_phandle(phandle handle); -extern struct device_node *of_get_parent(const struct device_node *node); -extern struct device_node *of_get_next_child(const struct device_node *node, - struct device_node *prev); -extern struct property *of_find_property(struct device_node *np, - const char *name, - int *lenp); -extern int of_device_is_compatible(struct device_node *device, const char *); -extern void *of_get_property(struct device_node *node, const char *name, - int *lenp); -extern int of_getintprop_default(struct device_node *np, - const char *name, - int def); - -extern void prom_build_devicetree(void); - -#endif /* __KERNEL__ */ -#endif /* _SPARC_PROM_H */ diff --git a/trunk/include/asm-sparc/sbus.h b/trunk/include/asm-sparc/sbus.h index d036e4419d79..a13cddcecec5 100644 --- a/trunk/include/asm-sparc/sbus.h +++ b/trunk/include/asm-sparc/sbus.h @@ -11,8 +11,7 @@ #include #include -#include -#include +/* #include */ /* Unused since we use opaque iommu (|io-unit) */ #include /* We scan which devices are on the SBus using the PROM node device @@ -43,19 +42,18 @@ struct sbus_bus; /* Linux SBUS device tables */ struct sbus_dev { - struct of_device ofdev; - struct sbus_bus *bus; - struct sbus_dev *next; - struct sbus_dev *child; - struct sbus_dev *parent; - int prom_node; - char prom_name[64]; + struct sbus_bus *bus; /* Back ptr to sbus */ + struct sbus_dev *next; /* next device on this SBus or null */ + struct sbus_dev *child; /* For ledma and espdma on sun4m */ + struct sbus_dev *parent; /* Parent device if not toplevel */ + int prom_node; /* PROM device tree node for this device */ + char prom_name[64]; /* PROM device name */ int slot; struct resource resource[PROMREG_MAX]; struct linux_prom_registers reg_addrs[PROMREG_MAX]; - int num_registers; + int num_registers, ranges_applied; struct linux_prom_ranges device_ranges[PROMREG_MAX]; int num_device_ranges; @@ -63,11 +61,9 @@ struct sbus_dev { unsigned int irqs[4]; int num_irqs; }; -#define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev) /* This struct describes the SBus(s) found on this machine. */ struct sbus_bus { - struct of_device ofdev; void *iommu; /* Opaque IOMMU cookie */ struct sbus_dev *devices; /* Link to devices on this SBus */ struct sbus_bus *next; /* next SBus, if more than one SBus */ @@ -81,7 +77,6 @@ struct sbus_bus { int devid; int board; }; -#define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) extern struct sbus_bus *sbus_root; @@ -107,7 +102,6 @@ sbus_is_slave(struct sbus_dev *dev) #define sbus_can_dma_64bit(sdev) (0) /* actually, sparc_cpu_model==sun4d */ #define sbus_can_burst64(sdev) (0) /* actually, sparc_cpu_model==sun4d */ extern void sbus_set_sbus64(struct sbus_dev *, int); -extern void sbus_fill_device_irq(struct sbus_dev *); /* These yield IOMMU mappings in consistent mode. */ extern void *sbus_alloc_consistent(struct sbus_dev *, long, u32 *dma_addrp); @@ -145,10 +139,4 @@ extern void sbus_dma_sync_sg_for_device(struct sbus_dev *, struct scatterlist *, BTFIXUPDEF_CALL(unsigned int, sbint_to_irq, struct sbus_dev *sdev, unsigned int) #define sbint_to_irq(sdev, sbint) BTFIXUP_CALL(sbint_to_irq)(sdev, sbint) -extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *); -extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); -extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *); -extern int sbus_arch_preinit(void); -extern void sbus_arch_postinit(void); - #endif /* !(_SPARC_SBUS_H) */ diff --git a/trunk/include/asm-sparc64/ebus.h b/trunk/include/asm-sparc64/ebus.h index a4afe9d5703a..7a408a030f52 100644 --- a/trunk/include/asm-sparc64/ebus.h +++ b/trunk/include/asm-sparc64/ebus.h @@ -10,14 +10,13 @@ #include #include -#include -#include struct linux_ebus_child { struct linux_ebus_child *next; struct linux_ebus_device *parent; struct linux_ebus *bus; - struct device_node *prom_node; + int prom_node; + char prom_name[64]; struct resource resource[PROMREG_MAX]; int num_addrs; unsigned int irqs[PROMINTR_MAX]; @@ -25,29 +24,32 @@ struct linux_ebus_child { }; struct linux_ebus_device { - struct of_device ofdev; struct linux_ebus_device *next; struct linux_ebus_child *children; struct linux_ebus *bus; - struct device_node *prom_node; + int prom_node; + char prom_name[64]; struct resource resource[PROMREG_MAX]; int num_addrs; unsigned int irqs[PROMINTR_MAX]; int num_irqs; }; -#define to_ebus_device(d) container_of(d, struct linux_ebus_device, ofdev.dev) struct linux_ebus { - struct of_device ofdev; struct linux_ebus *next; struct linux_ebus_device *devices; struct pci_pbm_info *parent; struct pci_dev *self; int index; int is_rio; - struct device_node *prom_node; + int prom_node; + char prom_name[64]; + struct linux_prom_ebus_ranges ebus_ranges[PROMREG_MAX]; + int num_ebus_ranges; + struct linux_prom_ebus_intmap ebus_intmap[PROMREG_MAX]; + int num_ebus_intmap; + struct linux_prom_ebus_intmask ebus_intmask; }; -#define to_ebus(d) container_of(d, struct linux_ebus, ofdev.dev) struct ebus_dma_info { spinlock_t lock; diff --git a/trunk/include/asm-sparc64/fhc.h b/trunk/include/asm-sparc64/fhc.h index 9e7f1b0d78b9..f29eaa254055 100644 --- a/trunk/include/asm-sparc64/fhc.h +++ b/trunk/include/asm-sparc64/fhc.h @@ -10,7 +10,6 @@ #include #include -#include #include struct linux_fhc; @@ -35,7 +34,8 @@ struct linux_central { unsigned long clkregs; unsigned long clkver; int slots; - struct device_node *prom_node; + int prom_node; + char prom_name[64]; struct linux_prom_ranges central_ranges[PROMREG_MAX]; int num_central_ranges; @@ -112,7 +112,8 @@ struct linux_fhc { struct fhc_regs fhc_regs; int board; int jtag_master; - struct device_node *prom_node; + int prom_node; + char prom_name[64]; struct linux_prom_ranges fhc_ranges[PROMREG_MAX]; int num_fhc_ranges; diff --git a/trunk/include/asm-sparc64/floppy.h b/trunk/include/asm-sparc64/floppy.h index f8d57bb5570c..07ccd6f04b52 100644 --- a/trunk/include/asm-sparc64/floppy.h +++ b/trunk/include/asm-sparc64/floppy.h @@ -498,14 +498,15 @@ static int sun_pci_fd_test_drive(unsigned long port, int drive) #ifdef CONFIG_PCI static int __init ebus_fdthree_p(struct linux_ebus_device *edev) { - if (!strcmp(edev->prom_node->name, "fdthree")) + if (!strcmp(edev->prom_name, "fdthree")) return 1; - if (!strcmp(edev->prom_node->name, "floppy")) { - char *compat; - - compat = of_get_property(edev->prom_node, - "compatible", NULL); - if (compat && !strcmp(compat, "fdthree")) + if (!strcmp(edev->prom_name, "floppy")) { + char compat[16]; + prom_getstring(edev->prom_node, + "compatible", + compat, sizeof(compat)); + compat[15] = '\0'; + if (!strcmp(compat, "fdthree")) return 1; } return 0; @@ -523,12 +524,12 @@ static unsigned long __init isa_floppy_init(void) for_each_isa(isa_br) { for_each_isadev(isa_dev, isa_br) { - if (!strcmp(isa_dev->prom_node->name, "dma")) { + if (!strcmp(isa_dev->prom_name, "dma")) { struct sparc_isa_device *child = isa_dev->child; while (child) { - if (!strcmp(child->prom_node->name, + if (!strcmp(child->prom_name, "floppy")) { isa_dev = child; goto isa_done; @@ -613,7 +614,6 @@ static unsigned long __init sun_floppy_init(void) struct linux_ebus_device *edev = NULL; unsigned long config = 0; void __iomem *auxio_reg; - char *state_prop; for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { @@ -630,8 +630,9 @@ static unsigned long __init sun_floppy_init(void) #endif } - state_prop = of_get_property(edev->prom_node, "status", NULL); - if (state_prop && !strncmp(state_prop, "disabled", 8)) + prom_getproperty(edev->prom_node, "status", + state, sizeof(state)); + if (!strncmp(state, "disabled", 8)) return 0; FLOPPY_IRQ = edev->irqs[0]; @@ -702,7 +703,7 @@ static unsigned long __init sun_floppy_init(void) */ for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "ecpp")) { + if (!strcmp(edev->prom_name, "ecpp")) { config = edev->resource[1].start; goto config_done; } diff --git a/trunk/include/asm-sparc64/isa.h b/trunk/include/asm-sparc64/isa.h index d9728b9031fc..4601bbfc3e7b 100644 --- a/trunk/include/asm-sparc64/isa.h +++ b/trunk/include/asm-sparc64/isa.h @@ -9,32 +9,37 @@ #include #include -#include -#include struct sparc_isa_bridge; struct sparc_isa_device { - struct of_device ofdev; struct sparc_isa_device *next; struct sparc_isa_device *child; struct sparc_isa_bridge *bus; - struct device_node *prom_node; + int prom_node; + char prom_name[64]; + char compatible[64]; struct resource resource; unsigned int irq; }; -#define to_isa_device(d) container_of(d, struct sparc_isa_device, ofdev.dev) struct sparc_isa_bridge { - struct of_device ofdev; struct sparc_isa_bridge *next; struct sparc_isa_device *devices; struct pci_pbm_info *parent; struct pci_dev *self; int index; - struct device_node *prom_node; + int prom_node; + char prom_name[64]; +#define linux_prom_isa_ranges linux_prom_ebus_ranges + struct linux_prom_isa_ranges isa_ranges[PROMREG_MAX]; + int num_isa_ranges; +#define linux_prom_isa_intmap linux_prom_ebus_intmap + struct linux_prom_isa_intmap isa_intmap[PROMREG_MAX]; + int num_isa_intmap; +#define linux_prom_isa_intmask linux_prom_ebus_intmask + struct linux_prom_isa_intmap isa_intmask; }; -#define to_isa_bridge(d) container_of(d, struct sparc_isa_bridge, ofdev.dev) extern struct sparc_isa_bridge *isa_chain; diff --git a/trunk/include/asm-sparc64/of_device.h b/trunk/include/asm-sparc64/of_device.h deleted file mode 100644 index 024088ef9d27..000000000000 --- a/trunk/include/asm-sparc64/of_device.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _ASM_SPARC64_OF_DEVICE_H -#define _ASM_SPARC64_OF_DEVICE_H -#ifdef __KERNEL__ - -#include -#include -#include - -extern struct bus_type isa_bus_type; -extern struct bus_type ebus_bus_type; -extern struct bus_type sbus_bus_type; - -/* - * The of_device is a kind of "base class" that is a superset of - * struct device for use by devices attached to an OF node and - * probed using OF properties. - */ -struct of_device -{ - struct device_node *node; /* OF device node */ - struct device dev; /* Generic device interface */ -}; -#define to_of_device(d) container_of(d, struct of_device, dev) - -extern const struct of_device_id *of_match_device( - const struct of_device_id *matches, const struct of_device *dev); - -extern struct of_device *of_dev_get(struct of_device *dev); -extern void of_dev_put(struct of_device *dev); - -/* - * An of_platform_driver driver is attached to a basic of_device on - * the ISA, EBUS, and SBUS busses on sparc64. - */ -struct of_platform_driver -{ - char *name; - struct of_device_id *match_table; - struct module *owner; - - int (*probe)(struct of_device* dev, const struct of_device_id *match); - int (*remove)(struct of_device* dev); - - int (*suspend)(struct of_device* dev, pm_message_t state); - int (*resume)(struct of_device* dev); - int (*shutdown)(struct of_device* dev); - - struct device_driver driver; -}; -#define to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver) - -extern int of_register_driver(struct of_platform_driver *drv, - struct bus_type *bus); -extern void of_unregister_driver(struct of_platform_driver *drv); -extern int of_device_register(struct of_device *ofdev); -extern void of_device_unregister(struct of_device *ofdev); -extern struct of_device *of_platform_device_create(struct device_node *np, - const char *bus_id, - struct device *parent, - struct bus_type *bus); -extern void of_release_dev(struct device *dev); - -#endif /* __KERNEL__ */ -#endif /* _ASM_SPARC64_OF_DEVICE_H */ diff --git a/trunk/include/asm-sparc64/oplib.h b/trunk/include/asm-sparc64/oplib.h index a68b0bb05958..dea3e73f0955 100644 --- a/trunk/include/asm-sparc64/oplib.h +++ b/trunk/include/asm-sparc64/oplib.h @@ -323,9 +323,8 @@ extern int prom_pathtoinode(const char *path); extern int prom_inst2pkg(int); /* CPU probing helpers. */ -struct device_node; -int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid); -int cpu_find_by_mid(int mid, struct device_node **prom_node); +int cpu_find_by_instance(int instance, int *prom_node, int *mid); +int cpu_find_by_mid(int mid, int *prom_node); /* Client interface level routines. */ extern void prom_set_trap_table(unsigned long tba); diff --git a/trunk/include/asm-sparc64/parport.h b/trunk/include/asm-sparc64/parport.h index d3895873e4c7..56b5197d7898 100644 --- a/trunk/include/asm-sparc64/parport.h +++ b/trunk/include/asm-sparc64/parport.h @@ -67,17 +67,18 @@ static __inline__ unsigned int get_dma_residue(unsigned int dmanr) static int ebus_ecpp_p(struct linux_ebus_device *edev) { - if (!strcmp(edev->prom_node->name, "ecpp")) + if (!strcmp(edev->prom_name, "ecpp")) return 1; - if (!strcmp(edev->prom_node->name, "parallel")) { - char *compat; - - compat = of_get_property(edev->prom_node, - "compatible", NULL); - if (compat && - (!strcmp(compat, "ecpp") || - !strcmp(compat, "ns87317-ecpp") || - !strcmp(compat + 13, "ecpp"))) + if (!strcmp(edev->prom_name, "parallel")) { + char compat[19]; + prom_getstring(edev->prom_node, + "compatible", + compat, sizeof(compat)); + compat[18] = '\0'; + if (!strcmp(compat, "ecpp")) + return 1; + if (!strcmp(compat, "ns87317-ecpp") && + !strcmp(compat + 13, "ecpp")) return 1; } return 0; @@ -93,12 +94,12 @@ static int parport_isa_probe(int count) struct sparc_isa_device *child; unsigned long base; - if (strcmp(isa_dev->prom_node->name, "dma")) + if (strcmp(isa_dev->prom_name, "dma")) continue; child = isa_dev->child; while (child) { - if (!strcmp(child->prom_node->name, "parallel")) + if (!strcmp(child->prom_name, "parallel")) break; child = child->next; } diff --git a/trunk/include/asm-sparc64/pbm.h b/trunk/include/asm-sparc64/pbm.h index cebe80b1da6c..1396f110939a 100644 --- a/trunk/include/asm-sparc64/pbm.h +++ b/trunk/include/asm-sparc64/pbm.h @@ -15,7 +15,6 @@ #include #include #include -#include #include /* The abstraction used here is that there are PCI controllers, @@ -154,15 +153,16 @@ struct pci_pbm_info { int chip_revision; /* Name used for top-level resources. */ - char *name; + char name[64]; /* OBP specific information. */ - struct device_node *prom_node; - struct linux_prom_pci_ranges *pbm_ranges; + int prom_node; + char prom_name[64]; + struct linux_prom_pci_ranges pbm_ranges[PROM_PCIRNG_MAX]; int num_pbm_ranges; - struct linux_prom_pci_intmap *pbm_intmap; + struct linux_prom_pci_intmap pbm_intmap[PROM_PCIIMAP_MAX]; int num_pbm_intmap; - struct linux_prom_pci_intmask *pbm_intmask; + struct linux_prom_pci_intmask pbm_intmask; u64 ino_bitmap; /* PBM I/O and Memory space resources. */ @@ -227,7 +227,8 @@ struct pci_controller_info { */ struct pcidev_cookie { struct pci_pbm_info *pbm; - struct device_node *prom_node; + char prom_name[64]; + int prom_node; struct linux_prom_pci_registers prom_regs[PROMREG_MAX]; int num_prom_regs; struct linux_prom_pci_registers prom_assignments[PROMREG_MAX]; diff --git a/trunk/include/asm-sparc64/pgtable.h b/trunk/include/asm-sparc64/pgtable.h index 03f5bc9b6bec..4e218814bb3c 100644 --- a/trunk/include/asm-sparc64/pgtable.h +++ b/trunk/include/asm-sparc64/pgtable.h @@ -756,8 +756,6 @@ extern unsigned long *sparc64_valid_addr_bitmap; #define kern_addr_valid(addr) \ (test_bit(__pa((unsigned long)(addr))>>22, sparc64_valid_addr_bitmap)) -extern int page_in_phys_avail(unsigned long paddr); - extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot); diff --git a/trunk/include/asm-sparc64/prom.h b/trunk/include/asm-sparc64/prom.h deleted file mode 100644 index 6d1556c0c263..000000000000 --- a/trunk/include/asm-sparc64/prom.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef _SPARC64_PROM_H -#define _SPARC64_PROM_H -#ifdef __KERNEL__ - - -/* - * Definitions for talking to the Open Firmware PROM on - * Power Macintosh computers. - * - * Copyright (C) 1996-2005 Paul Mackerras. - * - * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp. - * Updates for SPARC64 by David S. Miller - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include - -typedef u32 phandle; -typedef u32 ihandle; - -struct interrupt_info { - int line; - int sense; /* +ve/-ve logic, edge or level, etc. */ -}; - -struct property { - char *name; - int length; - void *value; - struct property *next; -}; - -struct device_node { - char *name; - char *type; - phandle node; - phandle linux_phandle; - int n_intrs; - struct interrupt_info *intrs; - char *path_component_name; - char *full_name; - - struct property *properties; - struct property *deadprops; /* removed properties */ - struct device_node *parent; - struct device_node *child; - struct device_node *sibling; - struct device_node *next; /* next device of same type */ - struct device_node *allnext; /* next in list of all nodes */ - struct proc_dir_entry *pde; /* this node's proc directory */ - struct kref kref; - unsigned long _flags; - void *data; -}; - -static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) -{ - dn->pde = de; -} - -extern struct device_node *of_find_node_by_name(struct device_node *from, - const char *name); -#define for_each_node_by_name(dn, name) \ - for (dn = of_find_node_by_name(NULL, name); dn; \ - dn = of_find_node_by_name(dn, name)) -extern struct device_node *of_find_node_by_type(struct device_node *from, - const char *type); -#define for_each_node_by_type(dn, type) \ - for (dn = of_find_node_by_type(NULL, type); dn; \ - dn = of_find_node_by_type(dn, type)) -extern struct device_node *of_find_compatible_node(struct device_node *from, - const char *type, const char *compat); -extern struct device_node *of_find_node_by_path(const char *path); -extern struct device_node *of_find_node_by_phandle(phandle handle); -extern struct device_node *of_get_parent(const struct device_node *node); -extern struct device_node *of_get_next_child(const struct device_node *node, - struct device_node *prev); -extern struct property *of_find_property(struct device_node *np, - const char *name, - int *lenp); -extern int of_device_is_compatible(struct device_node *device, const char *); -extern void *of_get_property(struct device_node *node, const char *name, - int *lenp); -extern int of_getintprop_default(struct device_node *np, - const char *name, - int def); - -extern void prom_build_devicetree(void); - -#endif /* __KERNEL__ */ -#endif /* _SPARC64_PROM_H */ diff --git a/trunk/include/asm-sparc64/sbus.h b/trunk/include/asm-sparc64/sbus.h index 56ee985e4605..48279e10f385 100644 --- a/trunk/include/asm-sparc64/sbus.h +++ b/trunk/include/asm-sparc64/sbus.h @@ -11,8 +11,6 @@ #include #include -#include -#include #include #include @@ -44,19 +42,18 @@ struct sbus_bus; /* Linux SBUS device tables */ struct sbus_dev { - struct of_device ofdev; - struct sbus_bus *bus; - struct sbus_dev *next; - struct sbus_dev *child; - struct sbus_dev *parent; - int prom_node; - char prom_name[64]; - int slot; + struct sbus_bus *bus; /* Our toplevel parent SBUS */ + struct sbus_dev *next; /* Chain of siblings */ + struct sbus_dev *child; /* Chain of children */ + struct sbus_dev *parent;/* Parent device if not toplevel*/ + int prom_node; /* OBP node of this device */ + char prom_name[64]; /* OBP device name property */ + int slot; /* SBUS slot number */ struct resource resource[PROMREG_MAX]; struct linux_prom_registers reg_addrs[PROMREG_MAX]; - int num_registers; + int num_registers, ranges_applied; struct linux_prom_ranges device_ranges[PROMREG_MAX]; int num_device_ranges; @@ -64,11 +61,9 @@ struct sbus_dev { unsigned int irqs[4]; int num_irqs; }; -#define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev) /* This struct describes the SBus(s) found on this machine. */ struct sbus_bus { - struct of_device ofdev; void *iommu; /* Opaque IOMMU cookie */ struct sbus_dev *devices; /* Tree of SBUS devices */ struct sbus_bus *next; /* Next SBUS in system */ @@ -82,7 +77,6 @@ struct sbus_bus { int portid; void *starfire_cookie; }; -#define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) extern struct sbus_bus *sbus_root; @@ -101,7 +95,6 @@ extern struct sbus_bus *sbus_root; #define sbus_can_dma_64bit(sdev) (1) #define sbus_can_burst64(sdev) (1) extern void sbus_set_sbus64(struct sbus_dev *, int); -extern void sbus_fill_device_irq(struct sbus_dev *); /* These yield IOMMU mappings in consistent mode. */ extern void *sbus_alloc_consistent(struct sbus_dev *, size_t, dma_addr_t *dma_addrp); @@ -126,10 +119,4 @@ extern void sbus_dma_sync_sg_for_cpu(struct sbus_dev *, struct scatterlist *, in #define sbus_dma_sync_sg sbus_dma_sync_sg_for_cpu extern void sbus_dma_sync_sg_for_device(struct sbus_dev *, struct scatterlist *, int, int); -extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *); -extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); -extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *); -extern int sbus_arch_preinit(void); -extern void sbus_arch_postinit(void); - #endif /* !(_SPARC64_SBUS_H) */ diff --git a/trunk/include/asm-sparc64/vdev.h b/trunk/include/asm-sparc64/vdev.h index 25637c57675d..996e6be7b976 100644 --- a/trunk/include/asm-sparc64/vdev.h +++ b/trunk/include/asm-sparc64/vdev.h @@ -7,11 +7,10 @@ #define _SPARC64_VDEV_H #include -#include extern u32 sun4v_vdev_devhandle; -extern struct device_node *sun4v_vdev_root; +extern int sun4v_vdev_root; -extern unsigned int sun4v_vdev_device_interrupt(struct device_node *dev_node); +extern unsigned int sun4v_vdev_device_interrupt(unsigned int); #endif /* !(_SPARC64_VDEV_H) */ diff --git a/trunk/include/linux/resume-trace.h b/trunk/include/linux/resume-trace.h deleted file mode 100644 index a376bd4ade39..000000000000 --- a/trunk/include/linux/resume-trace.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef RESUME_TRACE_H -#define RESUME_TRACE_H - -#ifdef CONFIG_PM_TRACE - -struct device; -extern void set_trace_device(struct device *); -extern void generate_resume_trace(void *tracedata, unsigned int user); - -#define TRACE_DEVICE(dev) set_trace_device(dev) -#define TRACE_RESUME(user) do { \ - void *tracedata; \ - asm volatile("movl $1f,%0\n" \ - ".section .tracedata,\"a\"\n" \ - "1:\t.word %c1\n" \ - "\t.long %c2\n" \ - ".previous" \ - :"=r" (tracedata) \ - : "i" (__LINE__), "i" (__FILE__)); \ - generate_resume_trace(tracedata, user); \ -} while (0) - -#else - -#define TRACE_DEVICE(dev) do { } while (0) -#define TRACE_RESUME(dev) do { } while (0) - -#endif - -#endif diff --git a/trunk/kernel/power/Kconfig b/trunk/kernel/power/Kconfig index cdf315e794ff..ce0dfb8f4a4e 100644 --- a/trunk/kernel/power/Kconfig +++ b/trunk/kernel/power/Kconfig @@ -36,15 +36,6 @@ config PM_DEBUG code. This is helpful when debugging and reporting various PM bugs, like suspend support. -config PM_TRACE - bool "Suspend/resume event tracing" - depends on PM && PM_DEBUG && X86 - default y - ---help--- - This enables some cheesy code to save the last PM event point in the - RTC across reboots, so that you can debug a machine that just hangs - during suspend (or more commonly, during resume). - config SOFTWARE_SUSPEND bool "Software Suspend" depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP) diff --git a/trunk/sound/sparc/amd7930.c b/trunk/sound/sparc/amd7930.c index ba1b2a3443d3..dfe9bac7fa32 100644 --- a/trunk/sound/sparc/amd7930.c +++ b/trunk/sound/sparc/amd7930.c @@ -46,7 +46,6 @@ #include #include #include -#include static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ @@ -336,6 +335,7 @@ struct snd_amd7930 { int pgain; int mgain; + struct sbus_dev *sdev; unsigned int irq; unsigned int regs_size; struct snd_amd7930 *next; @@ -946,9 +946,11 @@ static struct snd_device_ops snd_amd7930_dev_ops = { }; static int __init snd_amd7930_create(struct snd_card *card, + struct sbus_dev *sdev, struct resource *rp, unsigned int reg_size, - int irq, int dev, + struct linux_prom_irqs *irq_prop, + int dev, struct snd_amd7930 **ramd) { unsigned long flags; @@ -962,6 +964,7 @@ static int __init snd_amd7930_create(struct snd_card *card, spin_lock_init(&amd->lock); amd->card = card; + amd->sdev = sdev; amd->regs_size = reg_size; amd->regs = sbus_ioremap(rp, 0, amd->regs_size, "amd7930"); @@ -972,14 +975,15 @@ static int __init snd_amd7930_create(struct snd_card *card, amd7930_idle(amd); - if (request_irq(irq, snd_amd7930_interrupt, + if (request_irq(irq_prop->pri, snd_amd7930_interrupt, SA_INTERRUPT | SA_SHIRQ, "amd7930", amd)) { snd_printk("amd7930-%d: Unable to grab IRQ %d\n", - dev, irq); + dev, + irq_prop->pri); snd_amd7930_free(amd); return -EBUSY; } - amd->irq = irq; + amd->irq = irq_prop->pri; amd7930_enable_ints(amd); @@ -1013,21 +1017,47 @@ static int __init snd_amd7930_create(struct snd_card *card, return 0; } -static int __init amd7930_attach_common(struct resource *rp, int irq) +static int __init amd7930_attach(int prom_node, struct sbus_dev *sdev) { - static int dev_num; + static int dev; + struct linux_prom_registers reg_prop; + struct linux_prom_irqs irq_prop; + struct resource res, *rp; struct snd_card *card; struct snd_amd7930 *amd; int err; - if (dev_num >= SNDRV_CARDS) + if (dev >= SNDRV_CARDS) return -ENODEV; - if (!enable[dev_num]) { - dev_num++; + if (!enable[dev]) { + dev++; return -ENOENT; } - card = snd_card_new(index[dev_num], id[dev_num], THIS_MODULE, 0); + err = prom_getproperty(prom_node, "intr", + (char *) &irq_prop, sizeof(irq_prop)); + if (err < 0) { + snd_printk("amd7930-%d: Firmware node lacks IRQ property.\n", dev); + return -ENODEV; + } + + err = prom_getproperty(prom_node, "reg", + (char *) ®_prop, sizeof(reg_prop)); + if (err < 0) { + snd_printk("amd7930-%d: Firmware node lacks register property.\n", dev); + return -ENODEV; + } + + if (sdev) { + rp = &sdev->resource[0]; + } else { + rp = &res; + rp->start = reg_prop.phys_addr; + rp->end = rp->start + reg_prop.reg_size - 1; + rp->flags = IORESOURCE_IO | (reg_prop.which_io & 0xff); + } + + card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); if (card == NULL) return -ENOMEM; @@ -1037,11 +1067,10 @@ static int __init amd7930_attach_common(struct resource *rp, int irq) card->shortname, rp->flags & 0xffL, rp->start, - irq); + irq_prop.pri); - if ((err = snd_amd7930_create(card, rp, - (rp->end - rp->start) + 1, - irq, dev_num, &amd)) < 0) + if ((err = snd_amd7930_create(card, sdev, rp, reg_prop.reg_size, + &irq_prop, dev, &amd)) < 0) goto out_err; if ((err = snd_amd7930_pcm(amd)) < 0) @@ -1056,8 +1085,7 @@ static int __init amd7930_attach_common(struct resource *rp, int irq) amd->next = amd7930_list; amd7930_list = amd; - dev_num++; - + dev++; return 0; out_err: @@ -1065,71 +1093,29 @@ static int __init amd7930_attach_common(struct resource *rp, int irq) return err; } -static int __init amd7930_obio_attach(struct device_node *dp) -{ - struct linux_prom_registers *regs; - struct linux_prom_irqs *irqp; - struct resource res, *rp; - int len; - - irqp = of_get_property(dp, "intr", &len); - if (!irqp) { - snd_printk("%s: Firmware node lacks IRQ property.\n", - dp->full_name); - return -ENODEV; - } - - regs = of_get_property(dp, "reg", &len); - if (!regs) { - snd_printk("%s: Firmware node lacks register property.\n", - dp->full_name); - return -ENODEV; - } - - rp = &res; - rp->start = regs->phys_addr; - rp->end = rp->start + regs->reg_size - 1; - rp->flags = IORESOURCE_IO | (regs->which_io & 0xff); - - return amd7930_attach_common(rp, irqp->pri); -} - -static int __devinit amd7930_sbus_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - - return amd7930_attach_common(&sdev->resource[0], sdev->irqs[0]); -} - -static struct of_device_id amd7930_match[] = { - { - .name = "audio", - }, - {}, -}; - -static struct of_platform_driver amd7930_sbus_driver = { - .name = "audio", - .match_table = amd7930_match, - .probe = amd7930_sbus_probe, -}; - static int __init amd7930_init(void) { - struct device_node *dp; + struct sbus_bus *sbus; + struct sbus_dev *sdev; + int node, found; + + found = 0; /* Try to find the sun4c "audio" node first. */ - dp = of_find_node_by_path("/"); - dp = dp->child; - while (dp) { - if (!strcmp(dp->name, "audio")) - amd7930_obio_attach(dp); + node = prom_getchild(prom_root_node); + node = prom_searchsiblings(node, "audio"); + if (node && amd7930_attach(node, NULL) == 0) + found++; - dp = dp->sibling; + /* Probe each SBUS for amd7930 chips. */ + for_all_sbusdev(sdev, sbus) { + if (!strcmp(sdev->prom_name, "audio")) { + if (amd7930_attach(sdev->prom_node, sdev) == 0) + found++; + } } - /* Probe each SBUS for amd7930 chips. */ - return of_register_driver(&amd7930_sbus_driver, &sbus_bus_type); + return (found > 0) ? 0 : -EIO; } static void __exit amd7930_exit(void) @@ -1145,8 +1131,6 @@ static void __exit amd7930_exit(void) } amd7930_list = NULL; - - of_unregister_driver(&amd7930_sbus_driver); } module_init(amd7930_init); diff --git a/trunk/sound/sparc/cs4231.c b/trunk/sound/sparc/cs4231.c index da54d04a3e3a..b3efc9aa2916 100644 --- a/trunk/sound/sparc/cs4231.c +++ b/trunk/sound/sparc/cs4231.c @@ -2284,14 +2284,15 @@ static int __init cs4231_init(void) for_each_ebusdev(edev, ebus) { int match = 0; - if (!strcmp(edev->prom_node->name, "SUNW,CS4231")) { + if (!strcmp(edev->prom_name, "SUNW,CS4231")) { match = 1; - } else if (!strcmp(edev->prom_node->name, "audio")) { - char *compat; + } else if (!strcmp(edev->prom_name, "audio")) { + char compat[16]; - compat = of_get_property(edev->prom_node, - "compatible", NULL); - if (compat && !strcmp(compat, "SUNW,CS4231")) + prom_getstring(edev->prom_node, "compatible", + compat, sizeof(compat)); + compat[15] = '\0'; + if (!strcmp(compat, "SUNW,CS4231")) match = 1; }