Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

irqchip/mips-gic: Replace static map with dynamic

Commit 4cfffcfa5106 ("irqchip/mips-gic: Fix local interrupts") fixed
local interrupts by creating virq mappings for them all at startup.
Unfortunately this change broke legacy IRQ controllers in the same
system, such as the i8259 on the Malta platform, as it allocates virq
numbers that were expected to be available for the legacy controller.

Instead of creating the mappings statically when the GIC is probed,
re-introduce the irq domain .map function, removed by commit e875bd66dfb
("irqchip/mips-gic: Fix local interrupts") and use it to set up the irq
handler and chip. Since a good deal of the required functionality is
already implemented by gic_irq_domain_alloc, repurpose that function for
gic_irq_domain_map and add a new gic_irq_domain_alloc which wraps
gic_irq_domain_map with the necessary conversion.

This change fixes the legacy interrupt controller of the Malta platform
without breaking the perf interrupt fixed by commit e875bd66dfb
("irqchip/mips-gic: Fix local interrupts").


Signed-off-by: Matt Redfearn <matt.redfearn@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Link: http://lkml.kernel.org/r/1492679256-14513-4-git-send-email-matt.redfearn@imgtec.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

authored by

Matt Redfearn and committed by
Thomas Gleixner
8ada00a6 b87281e7

+18 -42
+18 -42
drivers/irqchip/irq-mips-gic.c
··· 700 700 return 0; 701 701 } 702 702 703 - static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq, 704 - unsigned int nr_irqs, void *arg) 703 + static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, 704 + irq_hw_number_t hwirq) 705 705 { 706 - struct irq_fwspec *fwspec = arg; 707 - irq_hw_number_t hwirq; 708 706 int err; 709 707 710 - if (fwspec->param[0] == GIC_SHARED) { 711 - hwirq = GIC_SHARED_TO_HWIRQ(fwspec->param[1]); 712 - 708 + if (hwirq >= GIC_SHARED_HWIRQ_BASE) { 713 709 /* verify that shared irqs don't conflict with an IPI irq */ 714 710 if (test_bit(GIC_HWIRQ_TO_SHARED(hwirq), ipi_resrv)) 715 711 return -EBUSY; ··· 718 722 719 723 return gic_shared_irq_domain_map(d, virq, hwirq, 0); 720 724 } 721 - 722 - hwirq = GIC_LOCAL_TO_HWIRQ(fwspec->param[1]); 723 725 724 726 switch (GIC_HWIRQ_TO_LOCAL(hwirq)) { 725 727 case GIC_LOCAL_INT_TIMER: ··· 752 758 return gic_local_irq_domain_map(d, virq, hwirq); 753 759 } 754 760 761 + static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq, 762 + unsigned int nr_irqs, void *arg) 763 + { 764 + struct irq_fwspec *fwspec = arg; 765 + irq_hw_number_t hwirq; 766 + 767 + if (fwspec->param[0] == GIC_SHARED) 768 + hwirq = GIC_SHARED_TO_HWIRQ(fwspec->param[1]); 769 + else 770 + hwirq = GIC_LOCAL_TO_HWIRQ(fwspec->param[1]); 771 + 772 + return gic_irq_domain_map(d, virq, hwirq); 773 + } 774 + 755 775 void gic_irq_domain_free(struct irq_domain *d, unsigned int virq, 756 776 unsigned int nr_irqs) 757 777 { ··· 775 767 .xlate = gic_irq_domain_xlate, 776 768 .alloc = gic_irq_domain_alloc, 777 769 .free = gic_irq_domain_free, 770 + .map = gic_irq_domain_map, 778 771 }; 779 772 780 773 static int gic_ipi_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, ··· 881 872 .match = gic_ipi_domain_match, 882 873 }; 883 874 884 - static void __init gic_map_single_int(struct device_node *node, 885 - unsigned int irq) 886 - { 887 - unsigned int linux_irq; 888 - struct irq_fwspec local_int_fwspec = { 889 - .fwnode = &node->fwnode, 890 - .param_count = 3, 891 - .param = { 892 - [0] = GIC_LOCAL, 893 - [1] = irq, 894 - [2] = IRQ_TYPE_NONE, 895 - }, 896 - }; 897 - 898 - if (!gic_local_irq_is_routable(irq)) 899 - return; 900 - 901 - linux_irq = irq_create_fwspec_mapping(&local_int_fwspec); 902 - WARN_ON(!linux_irq); 903 - } 904 - 905 - static void __init gic_map_interrupts(struct device_node *node) 906 - { 907 - gic_map_single_int(node, GIC_LOCAL_INT_WD); 908 - gic_map_single_int(node, GIC_LOCAL_INT_COMPARE); 909 - gic_map_single_int(node, GIC_LOCAL_INT_TIMER); 910 - gic_map_single_int(node, GIC_LOCAL_INT_PERFCTR); 911 - gic_map_single_int(node, GIC_LOCAL_INT_SWINT0); 912 - gic_map_single_int(node, GIC_LOCAL_INT_SWINT1); 913 - gic_map_single_int(node, GIC_LOCAL_INT_FDC); 914 - } 915 - 916 875 static void __init __gic_init(unsigned long gic_base_addr, 917 876 unsigned long gic_addrspace_size, 918 877 unsigned int cpu_vec, unsigned int irqbase, ··· 974 997 975 998 bitmap_copy(ipi_available, ipi_resrv, GIC_MAX_INTRS); 976 999 gic_basic_init(); 977 - gic_map_interrupts(node); 978 1000 } 979 1001 980 1002 void __init gic_init(unsigned long gic_base_addr,