diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-28 12:52:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-28 12:52:40 -0400 |
commit | 4340393e5a507a9a91bf807a03c73407a1344e20 (patch) | |
tree | fcba91baad9a97333abe388265fac3127666681b | |
parent | 037d2405d0ca0d276c481e40b98fb40e5d0360b8 (diff) | |
parent | 2564970a381651865364974ea414384b569cb9c0 (diff) |
Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq fixes from Thomas Gleixner:
"This lot provides:
- plug a hotplug race in the new affinity infrastructure
- a fix for the trigger type of chained interrupts
- plug a potential memory leak in the core code
- a few fixes for ARM and MIPS GICs"
* 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
irqchip/mips-gic: Implement activate op for device domain
irqchip/mips-gic: Cleanup chip and handler setup
genirq/affinity: Use get/put_online_cpus around cpumask operations
genirq: Fix potential memleak when failing to get irq pm
irqchip/gicv3-its: Disable the ITS before initializing it
irqchip/gicv3: Remove disabling redistributor and group1 non-secure interrupts
irqchip/gic: Allow self-SGIs for SMP on UP configurations
genirq: Correctly configure the trigger on chained interrupts
-rw-r--r-- | drivers/irqchip/irq-gic-v3-its.c | 7 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 11 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic.c | 7 | ||||
-rw-r--r-- | drivers/irqchip/irq-mips-gic.c | 18 | ||||
-rw-r--r-- | kernel/irq/affinity.c | 2 | ||||
-rw-r--r-- | kernel/irq/chip.c | 11 | ||||
-rw-r--r-- | kernel/irq/manage.c | 8 |
7 files changed, 55 insertions, 9 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 7ceaba81efb4..36b9c28a5c91 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c | |||
@@ -1545,7 +1545,12 @@ static int its_force_quiescent(void __iomem *base) | |||
1545 | u32 val; | 1545 | u32 val; |
1546 | 1546 | ||
1547 | val = readl_relaxed(base + GITS_CTLR); | 1547 | val = readl_relaxed(base + GITS_CTLR); |
1548 | if (val & GITS_CTLR_QUIESCENT) | 1548 | /* |
1549 | * GIC architecture specification requires the ITS to be both | ||
1550 | * disabled and quiescent for writes to GITS_BASER<n> or | ||
1551 | * GITS_CBASER to not have UNPREDICTABLE results. | ||
1552 | */ | ||
1553 | if ((val & GITS_CTLR_QUIESCENT) && !(val & GITS_CTLR_ENABLE)) | ||
1549 | return 0; | 1554 | return 0; |
1550 | 1555 | ||
1551 | /* Disable the generation of all interrupts to this ITS */ | 1556 | /* Disable the generation of all interrupts to this ITS */ |
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 6fc56c3466b0..ede5672ab34d 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c | |||
@@ -667,13 +667,20 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, | |||
667 | #endif | 667 | #endif |
668 | 668 | ||
669 | #ifdef CONFIG_CPU_PM | 669 | #ifdef CONFIG_CPU_PM |
670 | /* Check whether it's single security state view */ | ||
671 | static bool gic_dist_security_disabled(void) | ||
672 | { | ||
673 | return readl_relaxed(gic_data.dist_base + GICD_CTLR) & GICD_CTLR_DS; | ||
674 | } | ||
675 | |||
670 | static int gic_cpu_pm_notifier(struct notifier_block *self, | 676 | static int gic_cpu_pm_notifier(struct notifier_block *self, |
671 | unsigned long cmd, void *v) | 677 | unsigned long cmd, void *v) |
672 | { | 678 | { |
673 | if (cmd == CPU_PM_EXIT) { | 679 | if (cmd == CPU_PM_EXIT) { |
674 | gic_enable_redist(true); | 680 | if (gic_dist_security_disabled()) |
681 | gic_enable_redist(true); | ||
675 | gic_cpu_sys_reg_init(); | 682 | gic_cpu_sys_reg_init(); |
676 | } else if (cmd == CPU_PM_ENTER) { | 683 | } else if (cmd == CPU_PM_ENTER && gic_dist_security_disabled()) { |
677 | gic_write_grpen1(0); | 684 | gic_write_grpen1(0); |
678 | gic_enable_redist(false); | 685 | gic_enable_redist(false); |
679 | } | 686 | } |
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index c2cab572c511..390fac59c6bc 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
@@ -769,6 +769,13 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) | |||
769 | int cpu; | 769 | int cpu; |
770 | unsigned long flags, map = 0; | 770 | unsigned long flags, map = 0; |
771 | 771 | ||
772 | if (unlikely(nr_cpu_ids == 1)) { | ||
773 | /* Only one CPU? let's do a self-IPI... */ | ||
774 | writel_relaxed(2 << 24 | irq, | ||
775 | gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); | ||
776 | return; | ||
777 | } | ||
778 | |||
772 | raw_spin_lock_irqsave(&irq_controller_lock, flags); | 779 | raw_spin_lock_irqsave(&irq_controller_lock, flags); |
773 | 780 | ||
774 | /* Convert our logical CPU mask into a physical one. */ | 781 | /* Convert our logical CPU mask into a physical one. */ |
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index c5f33c3bd228..83f498393a7f 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c | |||
@@ -713,9 +713,6 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq, | |||
713 | unsigned long flags; | 713 | unsigned long flags; |
714 | int i; | 714 | int i; |
715 | 715 | ||
716 | irq_set_chip_and_handler(virq, &gic_level_irq_controller, | ||
717 | handle_level_irq); | ||
718 | |||
719 | spin_lock_irqsave(&gic_lock, flags); | 716 | spin_lock_irqsave(&gic_lock, flags); |
720 | gic_map_to_pin(intr, gic_cpu_pin); | 717 | gic_map_to_pin(intr, gic_cpu_pin); |
721 | gic_map_to_vpe(intr, mips_cm_vp_id(vpe)); | 718 | gic_map_to_vpe(intr, mips_cm_vp_id(vpe)); |
@@ -732,6 +729,10 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, | |||
732 | { | 729 | { |
733 | if (GIC_HWIRQ_TO_LOCAL(hw) < GIC_NUM_LOCAL_INTRS) | 730 | if (GIC_HWIRQ_TO_LOCAL(hw) < GIC_NUM_LOCAL_INTRS) |
734 | return gic_local_irq_domain_map(d, virq, hw); | 731 | return gic_local_irq_domain_map(d, virq, hw); |
732 | |||
733 | irq_set_chip_and_handler(virq, &gic_level_irq_controller, | ||
734 | handle_level_irq); | ||
735 | |||
735 | return gic_shared_irq_domain_map(d, virq, hw, 0); | 736 | return gic_shared_irq_domain_map(d, virq, hw, 0); |
736 | } | 737 | } |
737 | 738 | ||
@@ -771,11 +772,13 @@ static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq, | |||
771 | hwirq = GIC_SHARED_TO_HWIRQ(base_hwirq + i); | 772 | hwirq = GIC_SHARED_TO_HWIRQ(base_hwirq + i); |
772 | 773 | ||
773 | ret = irq_domain_set_hwirq_and_chip(d, virq + i, hwirq, | 774 | ret = irq_domain_set_hwirq_and_chip(d, virq + i, hwirq, |
774 | &gic_edge_irq_controller, | 775 | &gic_level_irq_controller, |
775 | NULL); | 776 | NULL); |
776 | if (ret) | 777 | if (ret) |
777 | goto error; | 778 | goto error; |
778 | 779 | ||
780 | irq_set_handler(virq + i, handle_level_irq); | ||
781 | |||
779 | ret = gic_shared_irq_domain_map(d, virq + i, hwirq, cpu); | 782 | ret = gic_shared_irq_domain_map(d, virq + i, hwirq, cpu); |
780 | if (ret) | 783 | if (ret) |
781 | goto error; | 784 | goto error; |
@@ -890,10 +893,17 @@ void gic_dev_domain_free(struct irq_domain *d, unsigned int virq, | |||
890 | return; | 893 | return; |
891 | } | 894 | } |
892 | 895 | ||
896 | static void gic_dev_domain_activate(struct irq_domain *domain, | ||
897 | struct irq_data *d) | ||
898 | { | ||
899 | gic_shared_irq_domain_map(domain, d->irq, d->hwirq, 0); | ||
900 | } | ||
901 | |||
893 | static struct irq_domain_ops gic_dev_domain_ops = { | 902 | static struct irq_domain_ops gic_dev_domain_ops = { |
894 | .xlate = gic_dev_domain_xlate, | 903 | .xlate = gic_dev_domain_xlate, |
895 | .alloc = gic_dev_domain_alloc, | 904 | .alloc = gic_dev_domain_alloc, |
896 | .free = gic_dev_domain_free, | 905 | .free = gic_dev_domain_free, |
906 | .activate = gic_dev_domain_activate, | ||
897 | }; | 907 | }; |
898 | 908 | ||
899 | static int gic_ipi_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, | 909 | static int gic_ipi_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, |
diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c index f68959341c0f..32f6cfcff212 100644 --- a/kernel/irq/affinity.c +++ b/kernel/irq/affinity.c | |||
@@ -39,6 +39,7 @@ struct cpumask *irq_create_affinity_mask(unsigned int *nr_vecs) | |||
39 | return NULL; | 39 | return NULL; |
40 | } | 40 | } |
41 | 41 | ||
42 | get_online_cpus(); | ||
42 | if (max_vecs >= num_online_cpus()) { | 43 | if (max_vecs >= num_online_cpus()) { |
43 | cpumask_copy(affinity_mask, cpu_online_mask); | 44 | cpumask_copy(affinity_mask, cpu_online_mask); |
44 | *nr_vecs = num_online_cpus(); | 45 | *nr_vecs = num_online_cpus(); |
@@ -56,6 +57,7 @@ struct cpumask *irq_create_affinity_mask(unsigned int *nr_vecs) | |||
56 | } | 57 | } |
57 | *nr_vecs = vecs; | 58 | *nr_vecs = vecs; |
58 | } | 59 | } |
60 | put_online_cpus(); | ||
59 | 61 | ||
60 | return affinity_mask; | 62 | return affinity_mask; |
61 | } | 63 | } |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index b4c1bc7c9ca2..637389088b3f 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -820,6 +820,17 @@ __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 | /* | ||
824 | * We're about to start this interrupt immediately, | ||
825 | * hence the need to set the trigger configuration. | ||
826 | * But the .set_type callback may have overridden the | ||
827 | * flow handler, ignoring that we're dealing with a | ||
828 | * chained interrupt. Reset it immediately because we | ||
829 | * do know better. | ||
830 | */ | ||
831 | __irq_set_trigger(desc, irqd_get_trigger_type(&desc->irq_data)); | ||
832 | desc->handle_irq = handle; | ||
833 | |||
823 | irq_settings_set_noprobe(desc); | 834 | irq_settings_set_noprobe(desc); |
824 | irq_settings_set_norequest(desc); | 835 | irq_settings_set_norequest(desc); |
825 | irq_settings_set_nothread(desc); | 836 | irq_settings_set_nothread(desc); |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 73a2b786b5e9..9530fcd27704 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -1681,8 +1681,10 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler, | |||
1681 | action->dev_id = dev_id; | 1681 | action->dev_id = dev_id; |
1682 | 1682 | ||
1683 | retval = irq_chip_pm_get(&desc->irq_data); | 1683 | retval = irq_chip_pm_get(&desc->irq_data); |
1684 | if (retval < 0) | 1684 | if (retval < 0) { |
1685 | kfree(action); | ||
1685 | return retval; | 1686 | return retval; |
1687 | } | ||
1686 | 1688 | ||
1687 | chip_bus_lock(desc); | 1689 | chip_bus_lock(desc); |
1688 | retval = __setup_irq(irq, desc, action); | 1690 | retval = __setup_irq(irq, desc, action); |
@@ -1985,8 +1987,10 @@ int request_percpu_irq(unsigned int irq, irq_handler_t handler, | |||
1985 | action->percpu_dev_id = dev_id; | 1987 | action->percpu_dev_id = dev_id; |
1986 | 1988 | ||
1987 | retval = irq_chip_pm_get(&desc->irq_data); | 1989 | retval = irq_chip_pm_get(&desc->irq_data); |
1988 | if (retval < 0) | 1990 | if (retval < 0) { |
1991 | kfree(action); | ||
1989 | return retval; | 1992 | return retval; |
1993 | } | ||
1990 | 1994 | ||
1991 | chip_bus_lock(desc); | 1995 | chip_bus_lock(desc); |
1992 | retval = __setup_irq(irq, desc, action); | 1996 | retval = __setup_irq(irq, desc, action); |