diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc64/kernel/irq.c | 37 | ||||
-rw-r--r-- | arch/sparc64/kernel/sun4v_ivec.S | 6 |
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 | ||
644 | unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | 644 | unsigned 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 | ||
669 | void ack_bad_irq(unsigned int virt_irq) | 684 | void 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 | 111 | 1: 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 | ||