Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 21462
b: refs/heads/master
c: 9d29a3f
h: refs/heads/master
v: v3
  • Loading branch information
David S. Miller committed Mar 20, 2006
1 parent 5679d8e commit 4a5defe
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 27 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7890f794e0e6f7dce2a5f4a03ba64b0b3fe306bd
refs/heads/master: 9d29a3fafd06534ad73427fee3c968c094d05b9b
98 changes: 86 additions & 12 deletions trunk/arch/sparc64/kernel/devices.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -58,10 +73,21 @@ static void __init sun4v_virtual_device_probe(void)
prom_getproperty(node, "reg", (char *)&regs, 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();
}

Expand All @@ -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 *) &reg, 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)
Expand Down
14 changes: 4 additions & 10 deletions trunk/drivers/serial/sunhv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 2 additions & 4 deletions trunk/include/asm-sparc64/vdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) */

0 comments on commit 4a5defe

Please sign in to comment.