diff options
-rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 7 | ||||
-rw-r--r-- | drivers/irqchip/irq-mips-gic.c | 105 | ||||
-rw-r--r-- | kernel/irq/chip.c | 8 |
3 files changed, 60 insertions, 60 deletions
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index ede5672ab34d..da6c0ba61d4f 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c | |||
@@ -548,7 +548,7 @@ static int gic_starting_cpu(unsigned int cpu) | |||
548 | static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask, | 548 | static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask, |
549 | unsigned long cluster_id) | 549 | unsigned long cluster_id) |
550 | { | 550 | { |
551 | int cpu = *base_cpu; | 551 | int next_cpu, cpu = *base_cpu; |
552 | unsigned long mpidr = cpu_logical_map(cpu); | 552 | unsigned long mpidr = cpu_logical_map(cpu); |
553 | u16 tlist = 0; | 553 | u16 tlist = 0; |
554 | 554 | ||
@@ -562,9 +562,10 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask, | |||
562 | 562 | ||
563 | tlist |= 1 << (mpidr & 0xf); | 563 | tlist |= 1 << (mpidr & 0xf); |
564 | 564 | ||
565 | cpu = cpumask_next(cpu, mask); | 565 | next_cpu = cpumask_next(cpu, mask); |
566 | if (cpu >= nr_cpu_ids) | 566 | if (next_cpu >= nr_cpu_ids) |
567 | goto out; | 567 | goto out; |
568 | cpu = next_cpu; | ||
568 | 569 | ||
569 | mpidr = cpu_logical_map(cpu); | 570 | mpidr = cpu_logical_map(cpu); |
570 | 571 | ||
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 83f498393a7f..6185696405d5 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c | |||
@@ -638,27 +638,6 @@ static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq, | |||
638 | if (!gic_local_irq_is_routable(intr)) | 638 | if (!gic_local_irq_is_routable(intr)) |
639 | return -EPERM; | 639 | return -EPERM; |
640 | 640 | ||
641 | /* | ||
642 | * HACK: These are all really percpu interrupts, but the rest | ||
643 | * of the MIPS kernel code does not use the percpu IRQ API for | ||
644 | * the CP0 timer and performance counter interrupts. | ||
645 | */ | ||
646 | switch (intr) { | ||
647 | case GIC_LOCAL_INT_TIMER: | ||
648 | case GIC_LOCAL_INT_PERFCTR: | ||
649 | case GIC_LOCAL_INT_FDC: | ||
650 | irq_set_chip_and_handler(virq, | ||
651 | &gic_all_vpes_local_irq_controller, | ||
652 | handle_percpu_irq); | ||
653 | break; | ||
654 | default: | ||
655 | irq_set_chip_and_handler(virq, | ||
656 | &gic_local_irq_controller, | ||
657 | handle_percpu_devid_irq); | ||
658 | irq_set_percpu_devid(virq); | ||
659 | break; | ||
660 | } | ||
661 | |||
662 | spin_lock_irqsave(&gic_lock, flags); | 641 | spin_lock_irqsave(&gic_lock, flags); |
663 | for (i = 0; i < gic_vpes; i++) { | 642 | for (i = 0; i < gic_vpes; i++) { |
664 | u32 val = GIC_MAP_TO_PIN_MSK | gic_cpu_pin; | 643 | u32 val = GIC_MAP_TO_PIN_MSK | gic_cpu_pin; |
@@ -724,16 +703,42 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq, | |||
724 | return 0; | 703 | return 0; |
725 | } | 704 | } |
726 | 705 | ||
727 | static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, | 706 | static int gic_setup_dev_chip(struct irq_domain *d, unsigned int virq, |
728 | irq_hw_number_t hw) | 707 | unsigned int hwirq) |
729 | { | 708 | { |
730 | if (GIC_HWIRQ_TO_LOCAL(hw) < GIC_NUM_LOCAL_INTRS) | 709 | struct irq_chip *chip; |
731 | return gic_local_irq_domain_map(d, virq, hw); | 710 | int err; |
711 | |||
712 | if (hwirq >= GIC_SHARED_HWIRQ_BASE) { | ||
713 | err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, | ||
714 | &gic_level_irq_controller, | ||
715 | NULL); | ||
716 | } else { | ||
717 | switch (GIC_HWIRQ_TO_LOCAL(hwirq)) { | ||
718 | case GIC_LOCAL_INT_TIMER: | ||
719 | case GIC_LOCAL_INT_PERFCTR: | ||
720 | case GIC_LOCAL_INT_FDC: | ||
721 | /* | ||
722 | * HACK: These are all really percpu interrupts, but | ||
723 | * the rest of the MIPS kernel code does not use the | ||
724 | * percpu IRQ API for them. | ||
725 | */ | ||
726 | chip = &gic_all_vpes_local_irq_controller; | ||
727 | irq_set_handler(virq, handle_percpu_irq); | ||
728 | break; | ||
729 | |||
730 | default: | ||
731 | chip = &gic_local_irq_controller; | ||
732 | irq_set_handler(virq, handle_percpu_devid_irq); | ||
733 | irq_set_percpu_devid(virq); | ||
734 | break; | ||
735 | } | ||
732 | 736 | ||
733 | irq_set_chip_and_handler(virq, &gic_level_irq_controller, | 737 | err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, |
734 | handle_level_irq); | 738 | chip, NULL); |
739 | } | ||
735 | 740 | ||
736 | return gic_shared_irq_domain_map(d, virq, hw, 0); | 741 | return err; |
737 | } | 742 | } |
738 | 743 | ||
739 | static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq, | 744 | static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq, |
@@ -744,15 +749,12 @@ static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq, | |||
744 | int cpu, ret, i; | 749 | int cpu, ret, i; |
745 | 750 | ||
746 | if (spec->type == GIC_DEVICE) { | 751 | if (spec->type == GIC_DEVICE) { |
747 | /* verify that it doesn't conflict with an IPI irq */ | 752 | /* verify that shared irqs don't conflict with an IPI irq */ |
748 | if (test_bit(spec->hwirq, ipi_resrv)) | 753 | if ((spec->hwirq >= GIC_SHARED_HWIRQ_BASE) && |
754 | test_bit(GIC_HWIRQ_TO_SHARED(spec->hwirq), ipi_resrv)) | ||
749 | return -EBUSY; | 755 | return -EBUSY; |
750 | 756 | ||
751 | hwirq = GIC_SHARED_TO_HWIRQ(spec->hwirq); | 757 | return gic_setup_dev_chip(d, virq, spec->hwirq); |
752 | |||
753 | return irq_domain_set_hwirq_and_chip(d, virq, hwirq, | ||
754 | &gic_level_irq_controller, | ||
755 | NULL); | ||
756 | } else { | 758 | } else { |
757 | base_hwirq = find_first_bit(ipi_resrv, gic_shared_intrs); | 759 | base_hwirq = find_first_bit(ipi_resrv, gic_shared_intrs); |
758 | if (base_hwirq == gic_shared_intrs) { | 760 | if (base_hwirq == gic_shared_intrs) { |
@@ -821,7 +823,6 @@ int gic_irq_domain_match(struct irq_domain *d, struct device_node *node, | |||
821 | } | 823 | } |
822 | 824 | ||
823 | static const struct irq_domain_ops gic_irq_domain_ops = { | 825 | static const struct irq_domain_ops gic_irq_domain_ops = { |
824 | .map = gic_irq_domain_map, | ||
825 | .alloc = gic_irq_domain_alloc, | 826 | .alloc = gic_irq_domain_alloc, |
826 | .free = gic_irq_domain_free, | 827 | .free = gic_irq_domain_free, |
827 | .match = gic_irq_domain_match, | 828 | .match = gic_irq_domain_match, |
@@ -852,29 +853,20 @@ static int gic_dev_domain_alloc(struct irq_domain *d, unsigned int virq, | |||
852 | struct irq_fwspec *fwspec = arg; | 853 | struct irq_fwspec *fwspec = arg; |
853 | struct gic_irq_spec spec = { | 854 | struct gic_irq_spec spec = { |
854 | .type = GIC_DEVICE, | 855 | .type = GIC_DEVICE, |
855 | .hwirq = fwspec->param[1], | ||
856 | }; | 856 | }; |
857 | int i, ret; | 857 | int i, ret; |
858 | bool is_shared = fwspec->param[0] == GIC_SHARED; | ||
859 | 858 | ||
860 | if (is_shared) { | 859 | if (fwspec->param[0] == GIC_SHARED) |
861 | ret = irq_domain_alloc_irqs_parent(d, virq, nr_irqs, &spec); | 860 | spec.hwirq = GIC_SHARED_TO_HWIRQ(fwspec->param[1]); |
862 | if (ret) | 861 | else |
863 | return ret; | 862 | spec.hwirq = GIC_LOCAL_TO_HWIRQ(fwspec->param[1]); |
864 | } | ||
865 | |||
866 | for (i = 0; i < nr_irqs; i++) { | ||
867 | irq_hw_number_t hwirq; | ||
868 | 863 | ||
869 | if (is_shared) | 864 | ret = irq_domain_alloc_irqs_parent(d, virq, nr_irqs, &spec); |
870 | hwirq = GIC_SHARED_TO_HWIRQ(spec.hwirq + i); | 865 | if (ret) |
871 | else | 866 | return ret; |
872 | hwirq = GIC_LOCAL_TO_HWIRQ(spec.hwirq + i); | ||
873 | 867 | ||
874 | ret = irq_domain_set_hwirq_and_chip(d, virq + i, | 868 | for (i = 0; i < nr_irqs; i++) { |
875 | hwirq, | 869 | ret = gic_setup_dev_chip(d, virq + i, spec.hwirq + i); |
876 | &gic_level_irq_controller, | ||
877 | NULL); | ||
878 | if (ret) | 870 | if (ret) |
879 | goto error; | 871 | goto error; |
880 | } | 872 | } |
@@ -896,7 +888,10 @@ void gic_dev_domain_free(struct irq_domain *d, unsigned int virq, | |||
896 | static void gic_dev_domain_activate(struct irq_domain *domain, | 888 | static void gic_dev_domain_activate(struct irq_domain *domain, |
897 | struct irq_data *d) | 889 | struct irq_data *d) |
898 | { | 890 | { |
899 | gic_shared_irq_domain_map(domain, d->irq, d->hwirq, 0); | 891 | if (GIC_HWIRQ_TO_LOCAL(d->hwirq) < GIC_NUM_LOCAL_INTRS) |
892 | gic_local_irq_domain_map(domain, d->irq, d->hwirq); | ||
893 | else | ||
894 | gic_shared_irq_domain_map(domain, d->irq, d->hwirq, 0); | ||
900 | } | 895 | } |
901 | 896 | ||
902 | static struct irq_domain_ops gic_dev_domain_ops = { | 897 | static struct irq_domain_ops gic_dev_domain_ops = { |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 637389088b3f..26ba5654d9d5 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -820,6 +820,8 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, | |||
820 | desc->name = name; | 820 | desc->name = name; |
821 | 821 | ||
822 | if (handle != handle_bad_irq && is_chained) { | 822 | if (handle != handle_bad_irq && is_chained) { |
823 | unsigned int type = irqd_get_trigger_type(&desc->irq_data); | ||
824 | |||
823 | /* | 825 | /* |
824 | * We're about to start this interrupt immediately, | 826 | * We're about to start this interrupt immediately, |
825 | * hence the need to set the trigger configuration. | 827 | * hence the need to set the trigger configuration. |
@@ -828,8 +830,10 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, | |||
828 | * chained interrupt. Reset it immediately because we | 830 | * chained interrupt. Reset it immediately because we |
829 | * do know better. | 831 | * do know better. |
830 | */ | 832 | */ |
831 | __irq_set_trigger(desc, irqd_get_trigger_type(&desc->irq_data)); | 833 | if (type != IRQ_TYPE_NONE) { |
832 | desc->handle_irq = handle; | 834 | __irq_set_trigger(desc, type); |
835 | desc->handle_irq = handle; | ||
836 | } | ||
833 | 837 | ||
834 | irq_settings_set_noprobe(desc); | 838 | irq_settings_set_noprobe(desc); |
835 | irq_settings_set_norequest(desc); | 839 | irq_settings_set_norequest(desc); |