Loading arch/sparc64/kernel/devices.c +86 −12 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <asm/timer.h> #include <asm/cpudata.h> #include <asm/vdev.h> #include <asm/irq.h> /* Used to synchronize acceses to NatSemi SUPER I/O chip configure * operations in asm/ns87303.h Loading @@ -33,14 +34,28 @@ extern void central_probe(void); u32 sun4v_vdev_devhandle; int sun4v_vdev_root; struct linux_prom_pci_intmap *sun4v_vdev_intmap; int sun4v_vdev_num_intmap; struct linux_prom_pci_intmap sun4v_vdev_intmask; struct vdev_intmap { unsigned int phys; unsigned int irq; unsigned int cnode; unsigned int cinterrupt; }; struct vdev_intmask { unsigned int phys; unsigned int interrupt; unsigned int __unused; }; static struct vdev_intmap *vdev_intmap; static int vdev_num_intmap; static struct vdev_intmask vdev_intmask; static void __init sun4v_virtual_device_probe(void) { struct linux_prom64_registers regs; struct linux_prom_pci_intmap *ip; struct vdev_intmap *ip; int node, sz, err; if (tlb_type != hypervisor) Loading @@ -58,10 +73,21 @@ static void __init sun4v_virtual_device_probe(void) prom_getproperty(node, "reg", (char *)®s, sizeof(regs)); sun4v_vdev_devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff; sz = sizeof(*ip) * 64; sun4v_vdev_intmap = ip = alloc_bootmem_low_pages(sz); if (!sun4v_vdev_intmap) { prom_printf("SUN4V: Error, cannot allocate vdev intmap.\n"); 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(); } Loading @@ -70,22 +96,70 @@ static void __init sun4v_virtual_device_probe(void) 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(); } sun4v_vdev_num_intmap = err / sizeof(*ip); vdev_num_intmap = err / sizeof(*ip); err = prom_getproperty(node, "interrupt-map-mask", (char *) &sun4v_vdev_intmask, sizeof(sun4v_vdev_intmask)); if (err == -1) { (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("SUN4V: virtual-devices devhandle[%x]\n", sun4v_vdev_devhandle); } unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node) { unsigned int irq, reg; int err, i; err = prom_getproperty(dev_node, "interrupts", (char *) &irq, sizeof(irq)); if (err <= 0) { printk("VDEV: Cannot get \"interrupts\" " "property for OBP node %x\n", dev_node); return 0; } err = prom_getproperty(dev_node, "reg", (char *) ®, sizeof(reg)); if (err <= 0) { printk("VDEV: Cannot get \"reg\" " "property for OBP node %x\n", dev_node); return 0; } 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)) { irq = vdev_intmap[i].cinterrupt; break; } } if (i == vdev_num_intmap) { printk("VDEV: No matching interrupt map entry " "for OBP node %x\n", dev_node); return 0; } return sun4v_build_irq(sun4v_vdev_devhandle, irq, 4, 0); } static const char *cpu_mid_prop(void) { if (tlb_type == spitfire) Loading drivers/serial/sunhv.c +4 −10 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <asm/hypervisor.h> #include <asm/spitfire.h> #include <asm/vdev.h> #include <asm/oplib.h> #include <asm/irq.h> #if defined(CONFIG_MAGIC_SYSRQ) Loading Loading @@ -427,7 +428,6 @@ static unsigned int __init get_interrupt(void) const char *cons_str = "console"; const char *compat_str = "compatible"; int node = prom_getchild(sun4v_vdev_root); unsigned int irq; char buf[64]; int err, len; Loading @@ -449,12 +449,7 @@ static unsigned int __init get_interrupt(void) /* Ok, the this is the OBP node for the sun4v hypervisor * console device. Decode the interrupt. */ err = prom_getproperty(node, "interrupts", (char *) &irq, sizeof(irq)); if (err == -1) return 0; return sun4v_build_irq(sun4v_vdev_devhandle, irq, 4, 0); return sun4v_vdev_device_interrupt(node); } static u32 sunhv_irq; Loading Loading @@ -487,8 +482,8 @@ static int __init sunhv_init(void) return -ENODEV; } printk("SUNHV: SUN4V virtual console, IRQ[%08x]\n", sunhv_irq); printk("SUNHV: SUN4V virtual console, IRQ %s\n", __irq_itoa(sunhv_irq)); sunhv_reg.minor = sunserial_current_minor; sunhv_reg.nr = 1; Loading Loading @@ -520,7 +515,6 @@ static void __exit sunhv_exit(void) uart_remove_one_port(&sunhv_reg, port); free_irq(sunhv_irq, port); sunserial_current_minor -= 1; uart_unregister_driver(&sunhv_reg); Loading include/asm-sparc64/vdev.h +2 −4 Original line number Diff line number Diff line Loading @@ -7,12 +7,10 @@ #define _SPARC64_VDEV_H #include <linux/types.h> #include <asm/oplib.h> extern u32 sun4v_vdev_devhandle; extern int sun4v_vdev_root; extern struct linux_prom_pci_intmap *sun4v_vdev_intmap; extern int sun4v_vdev_num_intmap; extern struct linux_prom_pci_intmap sun4v_vdev_intmask; extern unsigned int sun4v_vdev_device_interrupt(unsigned int); #endif /* !(_SPARC64_VDEV_H) */ Loading
arch/sparc64/kernel/devices.c +86 −12 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <asm/timer.h> #include <asm/cpudata.h> #include <asm/vdev.h> #include <asm/irq.h> /* Used to synchronize acceses to NatSemi SUPER I/O chip configure * operations in asm/ns87303.h Loading @@ -33,14 +34,28 @@ extern void central_probe(void); u32 sun4v_vdev_devhandle; int sun4v_vdev_root; struct linux_prom_pci_intmap *sun4v_vdev_intmap; int sun4v_vdev_num_intmap; struct linux_prom_pci_intmap sun4v_vdev_intmask; struct vdev_intmap { unsigned int phys; unsigned int irq; unsigned int cnode; unsigned int cinterrupt; }; struct vdev_intmask { unsigned int phys; unsigned int interrupt; unsigned int __unused; }; static struct vdev_intmap *vdev_intmap; static int vdev_num_intmap; static struct vdev_intmask vdev_intmask; static void __init sun4v_virtual_device_probe(void) { struct linux_prom64_registers regs; struct linux_prom_pci_intmap *ip; struct vdev_intmap *ip; int node, sz, err; if (tlb_type != hypervisor) Loading @@ -58,10 +73,21 @@ static void __init sun4v_virtual_device_probe(void) prom_getproperty(node, "reg", (char *)®s, sizeof(regs)); sun4v_vdev_devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff; sz = sizeof(*ip) * 64; sun4v_vdev_intmap = ip = alloc_bootmem_low_pages(sz); if (!sun4v_vdev_intmap) { prom_printf("SUN4V: Error, cannot allocate vdev intmap.\n"); 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(); } Loading @@ -70,22 +96,70 @@ static void __init sun4v_virtual_device_probe(void) 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(); } sun4v_vdev_num_intmap = err / sizeof(*ip); vdev_num_intmap = err / sizeof(*ip); err = prom_getproperty(node, "interrupt-map-mask", (char *) &sun4v_vdev_intmask, sizeof(sun4v_vdev_intmask)); if (err == -1) { (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("SUN4V: virtual-devices devhandle[%x]\n", sun4v_vdev_devhandle); } unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node) { unsigned int irq, reg; int err, i; err = prom_getproperty(dev_node, "interrupts", (char *) &irq, sizeof(irq)); if (err <= 0) { printk("VDEV: Cannot get \"interrupts\" " "property for OBP node %x\n", dev_node); return 0; } err = prom_getproperty(dev_node, "reg", (char *) ®, sizeof(reg)); if (err <= 0) { printk("VDEV: Cannot get \"reg\" " "property for OBP node %x\n", dev_node); return 0; } 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)) { irq = vdev_intmap[i].cinterrupt; break; } } if (i == vdev_num_intmap) { printk("VDEV: No matching interrupt map entry " "for OBP node %x\n", dev_node); return 0; } return sun4v_build_irq(sun4v_vdev_devhandle, irq, 4, 0); } static const char *cpu_mid_prop(void) { if (tlb_type == spitfire) Loading
drivers/serial/sunhv.c +4 −10 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <asm/hypervisor.h> #include <asm/spitfire.h> #include <asm/vdev.h> #include <asm/oplib.h> #include <asm/irq.h> #if defined(CONFIG_MAGIC_SYSRQ) Loading Loading @@ -427,7 +428,6 @@ static unsigned int __init get_interrupt(void) const char *cons_str = "console"; const char *compat_str = "compatible"; int node = prom_getchild(sun4v_vdev_root); unsigned int irq; char buf[64]; int err, len; Loading @@ -449,12 +449,7 @@ static unsigned int __init get_interrupt(void) /* Ok, the this is the OBP node for the sun4v hypervisor * console device. Decode the interrupt. */ err = prom_getproperty(node, "interrupts", (char *) &irq, sizeof(irq)); if (err == -1) return 0; return sun4v_build_irq(sun4v_vdev_devhandle, irq, 4, 0); return sun4v_vdev_device_interrupt(node); } static u32 sunhv_irq; Loading Loading @@ -487,8 +482,8 @@ static int __init sunhv_init(void) return -ENODEV; } printk("SUNHV: SUN4V virtual console, IRQ[%08x]\n", sunhv_irq); printk("SUNHV: SUN4V virtual console, IRQ %s\n", __irq_itoa(sunhv_irq)); sunhv_reg.minor = sunserial_current_minor; sunhv_reg.nr = 1; Loading Loading @@ -520,7 +515,6 @@ static void __exit sunhv_exit(void) uart_remove_one_port(&sunhv_reg, port); free_irq(sunhv_irq, port); sunserial_current_minor -= 1; uart_unregister_driver(&sunhv_reg); Loading
include/asm-sparc64/vdev.h +2 −4 Original line number Diff line number Diff line Loading @@ -7,12 +7,10 @@ #define _SPARC64_VDEV_H #include <linux/types.h> #include <asm/oplib.h> extern u32 sun4v_vdev_devhandle; extern int sun4v_vdev_root; extern struct linux_prom_pci_intmap *sun4v_vdev_intmap; extern int sun4v_vdev_num_intmap; extern struct linux_prom_pci_intmap sun4v_vdev_intmask; extern unsigned int sun4v_vdev_device_interrupt(unsigned int); #endif /* !(_SPARC64_VDEV_H) */