diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 7 | ||||
| -rw-r--r-- | drivers/irqchip/irq-mips-gic.c | 105 |
2 files changed, 54 insertions, 58 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 = { |
