preempt_disable();
if (tlb_type == hypervisor) {
- /* XXX SUN4V: implement me... XXX */
+ unsigned int ino = __irq_ino(irq);
+ int cpu = hard_smp_processor_id();
+ int err;
+
+ err = sun4v_intr_settarget(ino, cpu);
+ if (err != HV_EOK)
+ printk("sun4v_intr_settarget(%x,%d): err(%d)\n",
+ ino, cpu, err);
+ sun4v_intr_setenabled(ino, HV_INTR_ENABLED);
+ if (err != HV_EOK)
+ printk("sun4v_intr_setenabled(%x): err(%d)\n",
+ ino, err);
} else {
if (tlb_type == cheetah || tlb_type == cheetah_plus) {
unsigned long ver;
imap = bucket->imap;
if (imap != 0UL) {
- u32 tmp;
+ if (tlb_type == hypervisor) {
+ unsigned int ino = __irq_ino(irq);
+ int err;
+
+ err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED);
+ if (err != HV_EOK)
+ printk("sun4v_intr_setenabled(%x): "
+ "err(%d)\n", ino, err);
+ } else {
+ u32 tmp;
- /* NOTE: We do not want to futz with the IRQ clear registers
- * and move the state to IDLE, the SCSI code does call
- * disable_irq() to assure atomicity in the queue cmd
- * SCSI adapter driver code. Thus we'd lose interrupts.
- */
- tmp = upa_readl(imap);
- tmp &= ~IMAP_VALID;
- upa_writel(tmp, imap);
+ /* NOTE: We do not want to futz with the IRQ clear registers
+ * and move the state to IDLE, the SCSI code does call
+ * disable_irq() to assure atomicity in the queue cmd
+ * SCSI adapter driver code. Thus we'd lose interrupts.
+ */
+ tmp = upa_readl(imap);
+ tmp &= ~IMAP_VALID;
+ upa_writel(tmp, imap);
+ }
}
}
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",
return __irq(bucket);
}
+unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsigned char flags)
+{
+ struct ino_bucket *bucket;
+ unsigned long sysino;
+
+ sysino = sun4v_devino_to_sysino(devhandle, devino);
+
+ printk(KERN_INFO "sun4v_irq: Mapping (%x:%x) --> sysino[%lx]\n",
+ devhandle, devino, sysino);
+
+ bucket = &ivector_table[sysino];
+
+ /* Catch accidental accesses to these things. IMAP/ICLR handling
+ * is done by hypervisor calls on sun4v platforms, not by direct
+ * register accesses.
+ */
+ bucket->imap = ~0UL;
+ bucket->iclr = ~0UL;
+
+ bucket->pil = pil;
+ bucket->flags = flags;
+
+ bucket->irq_info = kmalloc(sizeof(struct irq_desc), GFP_ATOMIC);
+ if (!bucket->irq_info) {
+ prom_printf("IRQ: Error, kmalloc(irq_desc) failed.\n");
+ prom_halt();
+ }
+ memset(bucket->irq_info, 0, sizeof(struct irq_desc));
+
+ return __irq(bucket);
+}
+
static void atomic_bucket_insert(struct ino_bucket *bucket)
{
unsigned long pstate;
break;
}
if (bp->pil != 0) {
- upa_writel(ICLR_IDLE, bp->iclr);
- /* Test and add entropy */
- if (random & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
+ if (tlb_type == hypervisor) {
+ unsigned int ino = __irq_ino(bp);
+ int err;
+
+ err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE);
+ if (err != HV_EOK)
+ printk("sun4v_intr_setstate(%x): "
+ "err(%d)\n", ino, err);
+ } 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;
{
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 == 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;
+ if (tlb_type == hypervisor) {
+ unsigned int ino = __irq_ino(bucket);
+
+ sun4v_intr_settarget(ino, goal_cpu);
+ sun4v_intr_setenabled(ino, HV_INTR_ENABLED);
} else {
- tid = (starfire_translate(imap, goal_cpu) << 26);
- tid &= IMAP_TID_UPA;
+ unsigned int tid;
+
+ 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 {
if (++goal_cpu >= NR_CPUS)