unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
{
- unsigned long sysino, hv_err;
- unsigned int virq;
+ struct irq_handler_data *data;
+ struct ino_bucket *bucket;
+ unsigned long hv_err, cookie;
+
+ bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);
+ if (unlikely(!bucket))
+ return 0;
+
+ bucket->virt_irq = virt_irq_alloc(__irq(bucket));
+ set_irq_chip(bucket->virt_irq, &sun4v_virq);
- BUG_ON(devhandle & devino);
+ data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
+ if (unlikely(!data))
+ return 0;
- sysino = devhandle | devino;
- BUG_ON(sysino & ~(IMAP_IGN | IMAP_INO));
+ set_irq_chip_data(bucket->virt_irq, data);
- hv_err = sun4v_vintr_set_cookie(devhandle, devino, sysino);
+ /* Catch accidental accesses to these things. IMAP/ICLR handling
+ * is done by hypervisor calls on sun4v platforms, not by direct
+ * register accesses.
+ */
+ data->imap = ~0UL;
+ data->iclr = ~0UL;
+
+ cookie = ~__pa(bucket);
+ hv_err = sun4v_vintr_set_cookie(devhandle, devino, cookie);
if (hv_err) {
prom_printf("IRQ: Fatal, cannot set cookie for [%x:%x] "
"err=%lu\n", devhandle, devino, hv_err);
prom_halt();
}
- virq = sun4v_build_common(sysino, &sun4v_virq);
-
- virt_to_real_irq_table[virq].dev_handle = devhandle;
- virt_to_real_irq_table[virq].dev_ino = devino;
+ virt_to_real_irq_table[bucket->virt_irq].dev_handle = devhandle;
+ virt_to_real_irq_table[bucket->virt_irq].dev_ino = devino;
- return virq;
+ return bucket->virt_irq;
}
void ack_bad_irq(unsigned int virt_irq)
TRAP_LOAD_IRQ_WORK_PA(%g1, %g4)
+ /* For VIRQs, cookie is encoded as ~bucket_phys_addr */
+ brlz,pt %g3, 1f
+ xnor %g3, %g0, %g4
+
/* Get __pa(&ivector_table[IVEC]) into %g4. */
sethi %hi(ivector_table_pa), %g4
ldx [%g4 + %lo(ivector_table_pa)], %g4
sllx %g3, 4, %g3
add %g4, %g3, %g4
- ldx [%g1], %g2
+1: ldx [%g1], %g2
stxa %g2, [%g4] ASI_PHYS_USE_EC
stx %g4, [%g1]