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

irqchip/mips-gic: Remove device IRQ domain

In commit c98c1822ee13 ("irqchip/mips-gic: Add device hierarchy domain")
Qais indicates that he felt having a separate device IRQ domain was
cleaner, but along with everyone else I'm aware of touching this driver
I disagree.

Remove the separate device IRQ domain so that we simply have the main
GIC IRQ domain used for devices, and an IPI IRQ domain as a child. The
logic for handling the device interrupts & IPIs is cleanly separated
into the appropriate domain ops, making it much easier to reason about
what the driver is doing than the previous approach where the 2 child
domains had to call up to their parent, which had to handle both types
of interrupt & had all sorts of weird & wonderful duplication or
outright clobbering of setup performed by multiple domains.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
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-3-git-send-email-matt.redfearn@imgtec.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

authored by

Paul Burton and committed by
Thomas Gleixner
b87281e7 f8dcd9e8

+93 -197
+93 -197
drivers/irqchip/irq-mips-gic.c
··· 29 29 DECLARE_BITMAP(pcpu_mask, GIC_MAX_INTRS); 30 30 }; 31 31 32 - struct gic_irq_spec { 33 - enum { 34 - GIC_DEVICE, 35 - GIC_IPI 36 - } type; 37 - 38 - union { 39 - struct cpumask *ipimask; 40 - unsigned int hwirq; 41 - }; 42 - }; 43 - 44 32 static unsigned long __gic_base_addr; 45 33 46 34 static void __iomem *gic_base; 47 35 static struct gic_pcpu_mask pcpu_masks[NR_CPUS]; 48 36 static DEFINE_SPINLOCK(gic_lock); 49 37 static struct irq_domain *gic_irq_domain; 50 - static struct irq_domain *gic_dev_domain; 51 38 static struct irq_domain *gic_ipi_domain; 52 39 static int gic_shared_intrs; 53 40 static int gic_vpes; ··· 681 694 return 0; 682 695 } 683 696 684 - static int gic_setup_dev_chip(struct irq_domain *d, unsigned int virq, 685 - unsigned int hwirq) 686 - { 687 - struct irq_chip *chip; 688 - int err; 689 - 690 - if (hwirq >= GIC_SHARED_HWIRQ_BASE) { 691 - err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, 692 - &gic_level_irq_controller, 693 - NULL); 694 - } else { 695 - switch (GIC_HWIRQ_TO_LOCAL(hwirq)) { 696 - case GIC_LOCAL_INT_TIMER: 697 - case GIC_LOCAL_INT_PERFCTR: 698 - case GIC_LOCAL_INT_FDC: 699 - /* 700 - * HACK: These are all really percpu interrupts, but 701 - * the rest of the MIPS kernel code does not use the 702 - * percpu IRQ API for them. 703 - */ 704 - chip = &gic_all_vpes_local_irq_controller; 705 - irq_set_handler(virq, handle_percpu_irq); 706 - break; 707 - 708 - default: 709 - chip = &gic_local_irq_controller; 710 - irq_set_handler(virq, handle_percpu_devid_irq); 711 - irq_set_percpu_devid(virq); 712 - break; 713 - } 714 - 715 - err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, 716 - chip, NULL); 717 - } 718 - 719 - return err; 720 - } 721 - 722 - static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq, 723 - unsigned int nr_irqs, void *arg) 724 - { 725 - struct gic_irq_spec *spec = arg; 726 - irq_hw_number_t hwirq, base_hwirq; 727 - int cpu, ret, i; 728 - 729 - if (spec->type == GIC_DEVICE) { 730 - /* verify that shared irqs don't conflict with an IPI irq */ 731 - if ((spec->hwirq >= GIC_SHARED_HWIRQ_BASE) && 732 - test_bit(GIC_HWIRQ_TO_SHARED(spec->hwirq), ipi_resrv)) 733 - return -EBUSY; 734 - 735 - return gic_setup_dev_chip(d, virq, spec->hwirq); 736 - } else { 737 - base_hwirq = find_first_bit(ipi_available, gic_shared_intrs); 738 - if (base_hwirq == gic_shared_intrs) { 739 - return -ENOMEM; 740 - } 741 - 742 - /* check that we have enough space */ 743 - for (i = base_hwirq; i < nr_irqs; i++) { 744 - if (!test_bit(i, ipi_available)) 745 - return -EBUSY; 746 - } 747 - bitmap_clear(ipi_available, base_hwirq, nr_irqs); 748 - 749 - /* map the hwirq for each cpu consecutively */ 750 - i = 0; 751 - for_each_cpu(cpu, spec->ipimask) { 752 - hwirq = GIC_SHARED_TO_HWIRQ(base_hwirq + i); 753 - 754 - ret = irq_domain_set_hwirq_and_chip(d, virq + i, hwirq, 755 - &gic_level_irq_controller, 756 - NULL); 757 - if (ret) 758 - goto error; 759 - 760 - irq_set_handler(virq + i, handle_level_irq); 761 - 762 - ret = gic_shared_irq_domain_map(d, virq + i, hwirq, cpu); 763 - if (ret) 764 - goto error; 765 - 766 - i++; 767 - } 768 - 769 - /* 770 - * tell the parent about the base hwirq we allocated so it can 771 - * set its own domain data 772 - */ 773 - spec->hwirq = base_hwirq; 774 - } 775 - 776 - return 0; 777 - error: 778 - bitmap_set(ipi_available, base_hwirq, nr_irqs); 779 - return ret; 780 - } 781 - 782 - void gic_irq_domain_free(struct irq_domain *d, unsigned int virq, 783 - unsigned int nr_irqs) 784 - { 785 - irq_hw_number_t base_hwirq; 786 - struct irq_data *data; 787 - 788 - data = irq_get_irq_data(virq); 789 - if (!data) 790 - return; 791 - 792 - base_hwirq = GIC_HWIRQ_TO_SHARED(irqd_to_hwirq(data)); 793 - bitmap_set(ipi_available, base_hwirq, nr_irqs); 794 - } 795 - 796 - int gic_irq_domain_match(struct irq_domain *d, struct device_node *node, 797 - enum irq_domain_bus_token bus_token) 798 - { 799 - /* this domain should'nt be accessed directly */ 800 - return 0; 801 - } 802 - 803 - static const struct irq_domain_ops gic_irq_domain_ops = { 804 - .alloc = gic_irq_domain_alloc, 805 - .free = gic_irq_domain_free, 806 - .match = gic_irq_domain_match, 807 - }; 808 - 809 - static int gic_dev_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, 697 + static int gic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, 810 698 const u32 *intspec, unsigned int intsize, 811 699 irq_hw_number_t *out_hwirq, 812 700 unsigned int *out_type) ··· 700 838 return 0; 701 839 } 702 840 703 - static int gic_dev_domain_alloc(struct irq_domain *d, unsigned int virq, 841 + static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq, 704 842 unsigned int nr_irqs, void *arg) 705 843 { 706 844 struct irq_fwspec *fwspec = arg; 707 - struct gic_irq_spec spec = { 708 - .type = GIC_DEVICE, 709 - }; 710 - int i, ret; 845 + irq_hw_number_t hwirq; 846 + int err; 711 847 712 - if (fwspec->param[0] == GIC_SHARED) 713 - spec.hwirq = GIC_SHARED_TO_HWIRQ(fwspec->param[1]); 714 - else 715 - spec.hwirq = GIC_LOCAL_TO_HWIRQ(fwspec->param[1]); 848 + if (fwspec->param[0] == GIC_SHARED) { 849 + hwirq = GIC_SHARED_TO_HWIRQ(fwspec->param[1]); 716 850 717 - ret = irq_domain_alloc_irqs_parent(d, virq, nr_irqs, &spec); 718 - if (ret) 719 - return ret; 851 + /* verify that shared irqs don't conflict with an IPI irq */ 852 + if (test_bit(GIC_HWIRQ_TO_SHARED(hwirq), ipi_resrv)) 853 + return -EBUSY; 720 854 721 - for (i = 0; i < nr_irqs; i++) { 722 - ret = gic_setup_dev_chip(d, virq + i, spec.hwirq + i); 723 - if (ret) 724 - goto error; 855 + err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, 856 + &gic_level_irq_controller, 857 + NULL); 858 + if (err) 859 + return err; 860 + 861 + return gic_shared_irq_domain_map(d, virq, hwirq, 0); 725 862 } 726 863 727 - return 0; 864 + hwirq = GIC_LOCAL_TO_HWIRQ(fwspec->param[1]); 728 865 729 - error: 730 - irq_domain_free_irqs_parent(d, virq, nr_irqs); 731 - return ret; 866 + switch (GIC_HWIRQ_TO_LOCAL(hwirq)) { 867 + case GIC_LOCAL_INT_TIMER: 868 + case GIC_LOCAL_INT_PERFCTR: 869 + case GIC_LOCAL_INT_FDC: 870 + /* 871 + * HACK: These are all really percpu interrupts, but 872 + * the rest of the MIPS kernel code does not use the 873 + * percpu IRQ API for them. 874 + */ 875 + err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, 876 + &gic_all_vpes_local_irq_controller, 877 + NULL); 878 + if (err) 879 + return err; 880 + 881 + irq_set_handler(virq, handle_percpu_irq); 882 + break; 883 + 884 + default: 885 + err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, 886 + &gic_local_irq_controller, 887 + NULL); 888 + if (err) 889 + return err; 890 + 891 + irq_set_handler(virq, handle_percpu_devid_irq); 892 + irq_set_percpu_devid(virq); 893 + break; 894 + } 895 + 896 + return gic_local_irq_domain_map(d, virq, hwirq); 732 897 } 733 898 734 - void gic_dev_domain_free(struct irq_domain *d, unsigned int virq, 899 + void gic_irq_domain_free(struct irq_domain *d, unsigned int virq, 735 900 unsigned int nr_irqs) 736 901 { 737 - /* no real allocation is done for dev irqs, so no need to free anything */ 738 - return; 739 902 } 740 903 741 - static void gic_dev_domain_activate(struct irq_domain *domain, 742 - struct irq_data *d) 743 - { 744 - if (GIC_HWIRQ_TO_LOCAL(d->hwirq) < GIC_NUM_LOCAL_INTRS) 745 - gic_local_irq_domain_map(domain, d->irq, d->hwirq); 746 - else 747 - gic_shared_irq_domain_map(domain, d->irq, d->hwirq, 0); 748 - } 749 - 750 - static struct irq_domain_ops gic_dev_domain_ops = { 751 - .xlate = gic_dev_domain_xlate, 752 - .alloc = gic_dev_domain_alloc, 753 - .free = gic_dev_domain_free, 754 - .activate = gic_dev_domain_activate, 904 + static const struct irq_domain_ops gic_irq_domain_ops = { 905 + .xlate = gic_irq_domain_xlate, 906 + .alloc = gic_irq_domain_alloc, 907 + .free = gic_irq_domain_free, 755 908 }; 756 909 757 910 static int gic_ipi_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, ··· 788 911 unsigned int nr_irqs, void *arg) 789 912 { 790 913 struct cpumask *ipimask = arg; 791 - struct gic_irq_spec spec = { 792 - .type = GIC_IPI, 793 - .ipimask = ipimask 794 - }; 795 - int ret, i; 914 + irq_hw_number_t hwirq, base_hwirq; 915 + int cpu, ret, i; 796 916 797 - ret = irq_domain_alloc_irqs_parent(d, virq, nr_irqs, &spec); 798 - if (ret) 799 - return ret; 917 + base_hwirq = find_first_bit(ipi_available, gic_shared_intrs); 918 + if (base_hwirq == gic_shared_intrs) 919 + return -ENOMEM; 800 920 801 - /* the parent should have set spec.hwirq to the base_hwirq it allocated */ 802 - for (i = 0; i < nr_irqs; i++) { 803 - ret = irq_domain_set_hwirq_and_chip(d, virq + i, 804 - GIC_SHARED_TO_HWIRQ(spec.hwirq + i), 921 + /* check that we have enough space */ 922 + for (i = base_hwirq; i < nr_irqs; i++) { 923 + if (!test_bit(i, ipi_available)) 924 + return -EBUSY; 925 + } 926 + bitmap_clear(ipi_available, base_hwirq, nr_irqs); 927 + 928 + /* map the hwirq for each cpu consecutively */ 929 + i = 0; 930 + for_each_cpu(cpu, ipimask) { 931 + hwirq = GIC_SHARED_TO_HWIRQ(base_hwirq + i); 932 + 933 + ret = irq_domain_set_hwirq_and_chip(d, virq + i, hwirq, 934 + &gic_edge_irq_controller, 935 + NULL); 936 + if (ret) 937 + goto error; 938 + 939 + ret = irq_domain_set_hwirq_and_chip(d->parent, virq + i, hwirq, 805 940 &gic_edge_irq_controller, 806 941 NULL); 807 942 if (ret) ··· 822 933 ret = irq_set_irq_type(virq + i, IRQ_TYPE_EDGE_RISING); 823 934 if (ret) 824 935 goto error; 936 + 937 + ret = gic_shared_irq_domain_map(d, virq + i, hwirq, cpu); 938 + if (ret) 939 + goto error; 940 + 941 + i++; 825 942 } 826 943 827 944 return 0; 828 945 error: 829 - irq_domain_free_irqs_parent(d, virq, nr_irqs); 946 + bitmap_set(ipi_available, base_hwirq, nr_irqs); 830 947 return ret; 831 948 } 832 949 833 950 void gic_ipi_domain_free(struct irq_domain *d, unsigned int virq, 834 951 unsigned int nr_irqs) 835 952 { 836 - irq_domain_free_irqs_parent(d, virq, nr_irqs); 953 + irq_hw_number_t base_hwirq; 954 + struct irq_data *data; 955 + 956 + data = irq_get_irq_data(virq); 957 + if (!data) 958 + return; 959 + 960 + base_hwirq = GIC_HWIRQ_TO_SHARED(irqd_to_hwirq(data)); 961 + bitmap_set(ipi_available, base_hwirq, nr_irqs); 837 962 } 838 963 839 964 int gic_ipi_domain_match(struct irq_domain *d, struct device_node *node, ··· 974 1071 if (!gic_irq_domain) 975 1072 panic("Failed to add GIC IRQ domain"); 976 1073 gic_irq_domain->name = "mips-gic-irq"; 977 - 978 - gic_dev_domain = irq_domain_add_hierarchy(gic_irq_domain, 0, 979 - GIC_NUM_LOCAL_INTRS + gic_shared_intrs, 980 - node, &gic_dev_domain_ops, NULL); 981 - if (!gic_dev_domain) 982 - panic("Failed to add GIC DEV domain"); 983 - gic_dev_domain->name = "mips-gic-dev"; 984 1074 985 1075 gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain, 986 1076 IRQ_DOMAIN_FLAG_IPI_PER_CPU,