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

[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
Loading
Loading
Loading
Loading
+47 −24
Original line number Diff line number Diff line
@@ -152,7 +152,10 @@ void enable_irq(unsigned int irq)
	preempt_disable();

	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 {
		if (tlb_type == cheetah || tlb_type == cheetah_plus) {
			unsigned long ver;
@@ -210,6 +213,9 @@ void disable_irq(unsigned int irq)

	imap = bucket->imap;
	if (imap != 0UL) {
		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
@@ -222,6 +228,7 @@ void disable_irq(unsigned int irq)
			upa_writel(tmp, imap);
		}
	}
}

/* The timer is the one "weird" interrupt which is generated by
 * the CPU %tick register and not by some normal vectored interrupt
@@ -257,6 +264,8 @@ unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long
		return __irq(&pil0_dummy_bucket);
	}

	BUG_ON(tlb_type == hypervisor);

	/* RULE: Both must be specified in all other cases. */
	if (iclr == 0UL || imap == 0UL) {
		prom_printf("Invalid build_irq %d %d %016lx %016lx\n",
@@ -633,11 +642,17 @@ static void process_bucket(int irq, struct ino_bucket *bp, struct pt_regs *regs)
			break;
	}
	if (bp->pil != 0) {
		if (tlb_type == hypervisor) {
			unsigned int irq = __irq(bp);

			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:
	bp->flags &= ~IBF_INPROGRESS;
}
@@ -769,13 +784,20 @@ static int retarget_one_irq(struct irqaction *p, int goal_cpu)
{
	struct ino_bucket *bucket = get_ino_in_irqaction(p) + ivector_table;
	unsigned long imap = bucket->imap;
	unsigned int tid;

	while (!cpu_online(goal_cpu)) {
		if (++goal_cpu >= NR_CPUS)
			goal_cpu = 0;
	}

	if (tlb_type == hypervisor) {
		unsigned int irq = __irq(bucket);

		sun4v_intr_settarget(irq, goal_cpu);
		sun4v_intr_setenabled(irq, HV_INTR_ENABLED);
	} else {
		unsigned int tid;

		if (tlb_type == cheetah || tlb_type == cheetah_plus) {
			tid = goal_cpu << 26;
			tid &= IMAP_AID_SAFARI;
@@ -787,6 +809,7 @@ static int retarget_one_irq(struct irqaction *p, int goal_cpu)
			tid &= IMAP_TID_UPA;
		}
		upa_writel(tid | IMAP_VALID, imap);
	}

	do {
		if (++goal_cpu >= NR_CPUS)