aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64')
-rw-r--r--arch/sparc64/kernel/irq.c37
-rw-r--r--arch/sparc64/kernel/sun4v_ivec.S6
2 files changed, 31 insertions, 12 deletions
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 5a92851296c0..4e9537c96778 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -643,27 +643,42 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
643 643
644unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) 644unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
645{ 645{
646 unsigned long sysino, hv_err; 646 struct irq_handler_data *data;
647 unsigned int virq; 647 struct ino_bucket *bucket;
648 unsigned long hv_err, cookie;
649
650 bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);
651 if (unlikely(!bucket))
652 return 0;
653
654 bucket->virt_irq = virt_irq_alloc(__irq(bucket));
655 set_irq_chip(bucket->virt_irq, &sun4v_virq);
648 656
649 BUG_ON(devhandle & devino); 657 data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
658 if (unlikely(!data))
659 return 0;
650 660
651 sysino = devhandle | devino; 661 set_irq_chip_data(bucket->virt_irq, data);
652 BUG_ON(sysino & ~(IMAP_IGN | IMAP_INO));
653 662
654 hv_err = sun4v_vintr_set_cookie(devhandle, devino, sysino); 663 /* Catch accidental accesses to these things. IMAP/ICLR handling
664 * is done by hypervisor calls on sun4v platforms, not by direct
665 * register accesses.
666 */
667 data->imap = ~0UL;
668 data->iclr = ~0UL;
669
670 cookie = ~__pa(bucket);
671 hv_err = sun4v_vintr_set_cookie(devhandle, devino, cookie);
655 if (hv_err) { 672 if (hv_err) {
656 prom_printf("IRQ: Fatal, cannot set cookie for [%x:%x] " 673 prom_printf("IRQ: Fatal, cannot set cookie for [%x:%x] "
657 "err=%lu\n", devhandle, devino, hv_err); 674 "err=%lu\n", devhandle, devino, hv_err);
658 prom_halt(); 675 prom_halt();
659 } 676 }
660 677
661 virq = sun4v_build_common(sysino, &sun4v_virq); 678 virt_to_real_irq_table[bucket->virt_irq].dev_handle = devhandle;
662 679 virt_to_real_irq_table[bucket->virt_irq].dev_ino = devino;
663 virt_to_real_irq_table[virq].dev_handle = devhandle;
664 virt_to_real_irq_table[virq].dev_ino = devino;
665 680
666 return virq; 681 return bucket->virt_irq;
667} 682}
668 683
669void ack_bad_irq(unsigned int virt_irq) 684void ack_bad_irq(unsigned int virt_irq)
diff --git a/arch/sparc64/kernel/sun4v_ivec.S b/arch/sparc64/kernel/sun4v_ivec.S
index 16d306445912..e2f8e1b4882a 100644
--- a/arch/sparc64/kernel/sun4v_ivec.S
+++ b/arch/sparc64/kernel/sun4v_ivec.S
@@ -98,13 +98,17 @@ sun4v_dev_mondo:
98 98
99 TRAP_LOAD_IRQ_WORK_PA(%g1, %g4) 99 TRAP_LOAD_IRQ_WORK_PA(%g1, %g4)
100 100
101 /* For VIRQs, cookie is encoded as ~bucket_phys_addr */
102 brlz,pt %g3, 1f
103 xnor %g3, %g0, %g4
104
101 /* Get __pa(&ivector_table[IVEC]) into %g4. */ 105 /* Get __pa(&ivector_table[IVEC]) into %g4. */
102 sethi %hi(ivector_table_pa), %g4 106 sethi %hi(ivector_table_pa), %g4
103 ldx [%g4 + %lo(ivector_table_pa)], %g4 107 ldx [%g4 + %lo(ivector_table_pa)], %g4
104 sllx %g3, 4, %g3 108 sllx %g3, 4, %g3
105 add %g4, %g3, %g4 109 add %g4, %g3, %g4
106 110
107 ldx [%g1], %g2 1111: ldx [%g1], %g2
108 stxa %g2, [%g4] ASI_PHYS_USE_EC 112 stxa %g2, [%g4] ASI_PHYS_USE_EC
109 stx %g4, [%g1] 113 stx %g4, [%g1]
110 114