Commit 10951ee6 authored by David S. Miller's avatar David S. Miller

[SPARC64]: Program IRQ registers correctly on sun4v.

Need to use hypervisor calls instead of direct register
accesses.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e3999574
...@@ -152,7 +152,10 @@ void enable_irq(unsigned int irq) ...@@ -152,7 +152,10 @@ void enable_irq(unsigned int irq)
preempt_disable(); preempt_disable();
if (tlb_type == hypervisor) { if (tlb_type == hypervisor) {
/* XXX SUN4V: implement me... XXX */ int cpu = hard_smp_processor_id();
sun4v_intr_settarget(irq, cpu);
sun4v_intr_setenabled(irq, HV_INTR_ENABLED);
} else { } else {
if (tlb_type == cheetah || tlb_type == cheetah_plus) { if (tlb_type == cheetah || tlb_type == cheetah_plus) {
unsigned long ver; unsigned long ver;
...@@ -210,16 +213,20 @@ void disable_irq(unsigned int irq) ...@@ -210,16 +213,20 @@ void disable_irq(unsigned int irq)
imap = bucket->imap; imap = bucket->imap;
if (imap != 0UL) { if (imap != 0UL) {
u32 tmp; if (tlb_type == hypervisor) {
sun4v_intr_setenabled(irq, HV_INTR_DISABLED);
} else {
u32 tmp;
/* NOTE: We do not want to futz with the IRQ clear registers /* NOTE: We do not want to futz with the IRQ clear registers
* and move the state to IDLE, the SCSI code does call * and move the state to IDLE, the SCSI code does call
* disable_irq() to assure atomicity in the queue cmd * disable_irq() to assure atomicity in the queue cmd
* SCSI adapter driver code. Thus we'd lose interrupts. * SCSI adapter driver code. Thus we'd lose interrupts.
*/ */
tmp = upa_readl(imap); tmp = upa_readl(imap);
tmp &= ~IMAP_VALID; tmp &= ~IMAP_VALID;
upa_writel(tmp, imap); upa_writel(tmp, imap);
}
} }
} }
...@@ -257,6 +264,8 @@ unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long ...@@ -257,6 +264,8 @@ unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long
return __irq(&pil0_dummy_bucket); return __irq(&pil0_dummy_bucket);
} }
BUG_ON(tlb_type == hypervisor);
/* RULE: Both must be specified in all other cases. */ /* RULE: Both must be specified in all other cases. */
if (iclr == 0UL || imap == 0UL) { if (iclr == 0UL || imap == 0UL) {
prom_printf("Invalid build_irq %d %d %016lx %016lx\n", prom_printf("Invalid build_irq %d %d %016lx %016lx\n",
...@@ -633,10 +642,16 @@ static void process_bucket(int irq, struct ino_bucket *bp, struct pt_regs *regs) ...@@ -633,10 +642,16 @@ static void process_bucket(int irq, struct ino_bucket *bp, struct pt_regs *regs)
break; break;
} }
if (bp->pil != 0) { if (bp->pil != 0) {
upa_writel(ICLR_IDLE, bp->iclr); if (tlb_type == hypervisor) {
/* Test and add entropy */ unsigned int irq = __irq(bp);
if (random & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq); sun4v_intr_setstate(irq, HV_INTR_STATE_IDLE);
} else {
upa_writel(ICLR_IDLE, bp->iclr);
/* Test and add entropy */
if (random & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
}
} }
out: out:
bp->flags &= ~IBF_INPROGRESS; bp->flags &= ~IBF_INPROGRESS;
...@@ -769,24 +784,32 @@ static int retarget_one_irq(struct irqaction *p, int goal_cpu) ...@@ -769,24 +784,32 @@ static int retarget_one_irq(struct irqaction *p, int goal_cpu)
{ {
struct ino_bucket *bucket = get_ino_in_irqaction(p) + ivector_table; struct ino_bucket *bucket = get_ino_in_irqaction(p) + ivector_table;
unsigned long imap = bucket->imap; unsigned long imap = bucket->imap;
unsigned int tid;
while (!cpu_online(goal_cpu)) { while (!cpu_online(goal_cpu)) {
if (++goal_cpu >= NR_CPUS) if (++goal_cpu >= NR_CPUS)
goal_cpu = 0; goal_cpu = 0;
} }
if (tlb_type == cheetah || tlb_type == cheetah_plus) { if (tlb_type == hypervisor) {
tid = goal_cpu << 26; unsigned int irq = __irq(bucket);
tid &= IMAP_AID_SAFARI;
} else if (this_is_starfire == 0) { sun4v_intr_settarget(irq, goal_cpu);
tid = goal_cpu << 26; sun4v_intr_setenabled(irq, HV_INTR_ENABLED);
tid &= IMAP_TID_UPA;
} else { } else {
tid = (starfire_translate(imap, goal_cpu) << 26); unsigned int tid;
tid &= IMAP_TID_UPA;
if (tlb_type == cheetah || tlb_type == cheetah_plus) {
tid = goal_cpu << 26;
tid &= IMAP_AID_SAFARI;
} else if (this_is_starfire == 0) {
tid = goal_cpu << 26;
tid &= IMAP_TID_UPA;
} else {
tid = (starfire_translate(imap, goal_cpu) << 26);
tid &= IMAP_TID_UPA;
}
upa_writel(tid | IMAP_VALID, imap);
} }
upa_writel(tid | IMAP_VALID, imap);
do { do {
if (++goal_cpu >= NR_CPUS) if (++goal_cpu >= NR_CPUS)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment