* [patch 0/4] genirq/exynos timers: Fix the CPU hotplug wreckage sanely @ 2014-04-16 14:36 Thomas Gleixner 2014-04-16 14:36 ` [patch 2/4] irqchip: gic: Support forced affinity setting Thomas Gleixner ` (4 more replies) 0 siblings, 5 replies; 11+ messages in thread From: Thomas Gleixner @ 2014-04-16 14:36 UTC (permalink / raw) To: LKML Cc: Krzysztof Kozlowski, Kyungmin Park, Marek Szyprowski, Bartlomiej Zolnierkiewicz, Tomasz Figa, Daniel Lezcano, Kukjin Kim, linux-arm-kernel, stable The current implementation of irq_set_affinity() refuses rightfully to route an interrupt to an offline cpu. But there is a special case, where this is actually desired. Some of the ARM SoCs have per cpu timers which require setting the affinity during cpu startup where the cpu is not yet in the online mask. If we can't do that, then the local timer interrupt for the about to become online cpu is routed to some random online cpu. The developers of the affected machines tried to work around that issue, but that results in a massive mess in that timer code. It's saner to provide a facility to force the affinity and make the affected machines use that. The following series implements that logic w/o impact on any existing users. The change to the genirq core code is not that bad: arch/mips/cavium-octeon/octeon-irq.c | 2 +- include/linux/interrupt.h | 35 ++++++++++++++++++++++++++++++++++- include/linux/irq.h | 3 ++- kernel/irq/manage.c | 17 ++++++----------- 4 files changed, 43 insertions(+), 14 deletions(-) The resulting fixup for gic/exynos_mct is: clocksource/exynos_mct.c | 12 +++--------- irqchip/irq-gic.c | 8 ++++++-- 2 files changed, 9 insertions(+), 11 deletions(-) Krzysztofs proposed workaround was slightly smaller than that, but I prefer having a clean solution for backporting to stable rather than a messy hack around which works. @Krzysztof: Can you please retest the series? I've changed the core implementation versus the first attempt to make it less intrusive. Thanks, tglx ^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 2/4] irqchip: gic: Support forced affinity setting 2014-04-16 14:36 [patch 0/4] genirq/exynos timers: Fix the CPU hotplug wreckage sanely Thomas Gleixner @ 2014-04-16 14:36 ` Thomas Gleixner 2014-04-17 21:39 ` [tip:irq/urgent] irqchip: Gic: " tip-bot for Thomas Gleixner 2014-04-16 14:36 ` [patch 1/4] genirq: Allow forcing cpu affinity of interrupts Thomas Gleixner ` (3 subsequent siblings) 4 siblings, 1 reply; 11+ messages in thread From: Thomas Gleixner @ 2014-04-16 14:36 UTC (permalink / raw) To: LKML Cc: Krzysztof Kozlowski, Kyungmin Park, Marek Szyprowski, Bartlomiej Zolnierkiewicz, Tomasz Figa, Daniel Lezcano, Kukjin Kim, linux-arm-kernel, stable [-- Attachment #1: irqchip-gic-allow-force-affinity.patch --] [-- Type: text/plain, Size: 1100 bytes --] To support the affinity setting of per cpu timers in the early startup of a not yet online cpu, implement the force logic, which disables the cpu online check. Tagged for stable to allow a simple fix of the affected SoC clock event drivers. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- drivers/irqchip/irq-gic.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) Index: tip/drivers/irqchip/irq-gic.c =================================================================== --- tip.orig/drivers/irqchip/irq-gic.c +++ tip/drivers/irqchip/irq-gic.c @@ -246,10 +246,14 @@ static int gic_set_affinity(struct irq_d bool force) { void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); - unsigned int shift = (gic_irq(d) % 4) * 8; - unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask); + unsigned int cpu, shift = (gic_irq(d) % 4) * 8; u32 val, mask, bit; + if (!force) + cpu = cpumask_any_and(mask_val, cpu_online_mask); + else + cpu = cpumask_first(mask_val); + if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids) return -EINVAL; ^ permalink raw reply [flat|nested] 11+ messages in thread
* [tip:irq/urgent] irqchip: Gic: Support forced affinity setting 2014-04-16 14:36 ` [patch 2/4] irqchip: gic: Support forced affinity setting Thomas Gleixner @ 2014-04-17 21:39 ` tip-bot for Thomas Gleixner 0 siblings, 0 replies; 11+ messages in thread From: tip-bot for Thomas Gleixner @ 2014-04-17 21:39 UTC (permalink / raw) To: linux-tip-commits Cc: linux-kernel, hpa, mingo, k.kozlowski, kgene.kim, kyungmin.park, b.zolnierkie, m.szyprowski, tglx Commit-ID: ffde1de64012c406dfdda8690918248b472f24e4 Gitweb: http://git.kernel.org/tip/ffde1de64012c406dfdda8690918248b472f24e4 Author: Thomas Gleixner <tglx@linutronix.de> AuthorDate: Wed, 16 Apr 2014 14:36:44 +0000 Committer: Thomas Gleixner <tglx@linutronix.de> CommitDate: Thu, 17 Apr 2014 23:36:28 +0200 irqchip: Gic: Support forced affinity setting To support the affinity setting of per cpu timers in the early startup of a not yet online cpu, implement the force logic, which disables the cpu online check. Tagged for stable to allow a simple fix of the affected SoC clock event drivers. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Cc: Kyungmin Park <kyungmin.park@samsung.com> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Cc: Tomasz Figa <t.figa@samsung.com>, Cc: Daniel Lezcano <daniel.lezcano@linaro.org>, Cc: Kukjin Kim <kgene.kim@samsung.com> Cc: linux-arm-kernel@lists.infradead.org, Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/20140416143315.916984416@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- drivers/irqchip/irq-gic.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 4300b66..57d165e 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -246,10 +246,14 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) { void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); - unsigned int shift = (gic_irq(d) % 4) * 8; - unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask); + unsigned int cpu, shift = (gic_irq(d) % 4) * 8; u32 val, mask, bit; + if (!force) + cpu = cpumask_any_and(mask_val, cpu_online_mask); + else + cpu = cpumask_first(mask_val); + if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids) return -EINVAL; ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [patch 1/4] genirq: Allow forcing cpu affinity of interrupts 2014-04-16 14:36 [patch 0/4] genirq/exynos timers: Fix the CPU hotplug wreckage sanely Thomas Gleixner 2014-04-16 14:36 ` [patch 2/4] irqchip: gic: Support forced affinity setting Thomas Gleixner @ 2014-04-16 14:36 ` Thomas Gleixner 2014-04-17 21:39 ` [tip:irq/urgent] " tip-bot for Thomas Gleixner 2014-04-16 14:36 ` [patch 4/4] clocksource: exynos_mct: Register clock event after request_irq() Thomas Gleixner ` (2 subsequent siblings) 4 siblings, 1 reply; 11+ messages in thread From: Thomas Gleixner @ 2014-04-16 14:36 UTC (permalink / raw) To: LKML Cc: Krzysztof Kozlowski, Kyungmin Park, Marek Szyprowski, Bartlomiej Zolnierkiewicz, Tomasz Figa, Daniel Lezcano, Kukjin Kim, linux-arm-kernel, stable [-- Attachment #1: genirq-allow-forcing-cpuaffinity.patch --] [-- Type: text/plain, Size: 5917 bytes --] The current implementation of irq_set_affinity() refuses rightfully to route an interrupt to an offline cpu. But there is a special case, where this is actually desired. Some of the ARM SoCs have per cpu timers which require setting the affinity during cpu startup where the cpu is not yet in the online mask. If we can't do that, then the local timer interrupt for the about to become online cpu is routed to some random online cpu. The developers of the affected machines tried to work around that issue, but that results in a massive mess in that timer code. We have a yet unused argument in the set_affinity callbacks of the irq chips, which I added back then for a similar reason. It was never required so it got not used. But I'm happy that I never removed it. That allows us to implement a sane handling of the above scenario. So the affected SoC drivers can add the required force handling to their interrupt chip, switch the timer code to irq_force_affinity() and things just work. This does not affect any existing user of irq_set_affinity(). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- arch/mips/cavium-octeon/octeon-irq.c | 2 +- include/linux/interrupt.h | 35 ++++++++++++++++++++++++++++++++++- include/linux/irq.h | 3 ++- kernel/irq/manage.c | 17 ++++++----------- 4 files changed, 43 insertions(+), 14 deletions(-) Index: tip/arch/mips/cavium-octeon/octeon-irq.c =================================================================== --- tip.orig/arch/mips/cavium-octeon/octeon-irq.c +++ tip/arch/mips/cavium-octeon/octeon-irq.c @@ -635,7 +635,7 @@ static void octeon_irq_cpu_offline_ciu(s cpumask_clear(&new_affinity); cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity); } - __irq_set_affinity_locked(data, &new_affinity); + irq_set_affinity_locked(data, &new_affinity, false); } static int octeon_irq_ciu_set_affinity(struct irq_data *data, Index: tip/include/linux/interrupt.h =================================================================== --- tip.orig/include/linux/interrupt.h +++ tip/include/linux/interrupt.h @@ -203,7 +203,40 @@ static inline int check_wakeup_irqs(void extern cpumask_var_t irq_default_affinity; -extern int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask); +/* Internal implementation. Use the helpers below */ +extern int __irq_set_affinity(unsigned int irq, const struct cpumask *cpumask, + bool force); + +/** + * irq_set_affinity - Set the irq affinity of a given irq + * @irq: Interrupt to set affinity + * @mask: cpumask + * + * Fails if cpumask does not contain an online CPU + */ +static inline int +irq_set_affinity(unsigned int irq, const struct cpumask *cpumask) +{ + return __irq_set_affinity(irq, cpumask, false); +} + +/** + * irq_force_affinity - Force the irq affinity of a given irq + * @irq: Interrupt to set affinity + * @mask: cpumask + * + * Same as irq_set_affinity, but without checking the mask against + * online cpus. + * + * Solely for low level cpu hotplug code, where we need to make per + * cpu interrupts affine before the cpu becomes online. + */ +static inline int +irq_force_affinity(unsigned int irq, const struct cpumask *cpumask) +{ + return __irq_set_affinity(irq, cpumask, true); +} + extern int irq_can_set_affinity(unsigned int irq); extern int irq_select_affinity(unsigned int irq); Index: tip/include/linux/irq.h =================================================================== --- tip.orig/include/linux/irq.h +++ tip/include/linux/irq.h @@ -394,7 +394,8 @@ extern void remove_percpu_irq(unsigned i extern void irq_cpu_online(void); extern void irq_cpu_offline(void); -extern int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *cpumask); +extern int irq_set_affinity_locked(struct irq_data *data, + const struct cpumask *cpumask, bool force); #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ) void irq_move_irq(struct irq_data *data); Index: tip/kernel/irq/manage.c =================================================================== --- tip.orig/kernel/irq/manage.c +++ tip/kernel/irq/manage.c @@ -180,7 +180,7 @@ int irq_do_set_affinity(struct irq_data struct irq_chip *chip = irq_data_get_irq_chip(data); int ret; - ret = chip->irq_set_affinity(data, mask, false); + ret = chip->irq_set_affinity(data, mask, force); switch (ret) { case IRQ_SET_MASK_OK: cpumask_copy(data->affinity, mask); @@ -192,7 +192,8 @@ int irq_do_set_affinity(struct irq_data return ret; } -int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask) +int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask, + bool force) { struct irq_chip *chip = irq_data_get_irq_chip(data); struct irq_desc *desc = irq_data_to_desc(data); @@ -202,7 +203,7 @@ int __irq_set_affinity_locked(struct irq return -EINVAL; if (irq_can_move_pcntxt(data)) { - ret = irq_do_set_affinity(data, mask, false); + ret = irq_do_set_affinity(data, mask, force); } else { irqd_set_move_pending(data); irq_copy_pending(desc, mask); @@ -217,13 +218,7 @@ int __irq_set_affinity_locked(struct irq return ret; } -/** - * irq_set_affinity - Set the irq affinity of a given irq - * @irq: Interrupt to set affinity - * @mask: cpumask - * - */ -int irq_set_affinity(unsigned int irq, const struct cpumask *mask) +int __irq_set_affinity(unsigned int irq, const struct cpumask *mask, bool force) { struct irq_desc *desc = irq_to_desc(irq); unsigned long flags; @@ -233,7 +228,7 @@ int irq_set_affinity(unsigned int irq, c return -EINVAL; raw_spin_lock_irqsave(&desc->lock, flags); - ret = __irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask); + ret = irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask, force); raw_spin_unlock_irqrestore(&desc->lock, flags); return ret; } ^ permalink raw reply [flat|nested] 11+ messages in thread
* [tip:irq/urgent] genirq: Allow forcing cpu affinity of interrupts 2014-04-16 14:36 ` [patch 1/4] genirq: Allow forcing cpu affinity of interrupts Thomas Gleixner @ 2014-04-17 21:39 ` tip-bot for Thomas Gleixner 0 siblings, 0 replies; 11+ messages in thread From: tip-bot for Thomas Gleixner @ 2014-04-17 21:39 UTC (permalink / raw) To: linux-tip-commits Cc: linux-kernel, hpa, mingo, k.kozlowski, kgene.kim, kyungmin.park, b.zolnierkie, m.szyprowski, tglx Commit-ID: 01f8fa4f01d8362358eb90e412bd7ae18a3ec1ad Gitweb: http://git.kernel.org/tip/01f8fa4f01d8362358eb90e412bd7ae18a3ec1ad Author: Thomas Gleixner <tglx@linutronix.de> AuthorDate: Wed, 16 Apr 2014 14:36:44 +0000 Committer: Thomas Gleixner <tglx@linutronix.de> CommitDate: Thu, 17 Apr 2014 23:36:27 +0200 genirq: Allow forcing cpu affinity of interrupts The current implementation of irq_set_affinity() refuses rightfully to route an interrupt to an offline cpu. But there is a special case, where this is actually desired. Some of the ARM SoCs have per cpu timers which require setting the affinity during cpu startup where the cpu is not yet in the online mask. If we can't do that, then the local timer interrupt for the about to become online cpu is routed to some random online cpu. The developers of the affected machines tried to work around that issue, but that results in a massive mess in that timer code. We have a yet unused argument in the set_affinity callbacks of the irq chips, which I added back then for a similar reason. It was never required so it got not used. But I'm happy that I never removed it. That allows us to implement a sane handling of the above scenario. So the affected SoC drivers can add the required force handling to their interrupt chip, switch the timer code to irq_force_affinity() and things just work. This does not affect any existing user of irq_set_affinity(). Tagged for stable to allow a simple fix of the affected SoC clock event drivers. Reported-and-tested-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Kyungmin Park <kyungmin.park@samsung.com> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Cc: Tomasz Figa <t.figa@samsung.com>, Cc: Daniel Lezcano <daniel.lezcano@linaro.org>, Cc: Kukjin Kim <kgene.kim@samsung.com> Cc: linux-arm-kernel@lists.infradead.org, Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/20140416143315.717251504@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- arch/mips/cavium-octeon/octeon-irq.c | 2 +- include/linux/interrupt.h | 35 ++++++++++++++++++++++++++++++++++- include/linux/irq.h | 3 ++- kernel/irq/manage.c | 17 ++++++----------- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index c2bb4f8..3aa5b46 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -635,7 +635,7 @@ static void octeon_irq_cpu_offline_ciu(struct irq_data *data) cpumask_clear(&new_affinity); cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity); } - __irq_set_affinity_locked(data, &new_affinity); + irq_set_affinity_locked(data, &new_affinity, false); } static int octeon_irq_ciu_set_affinity(struct irq_data *data, diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index c7bfac1..8834a7e 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -203,7 +203,40 @@ static inline int check_wakeup_irqs(void) { return 0; } extern cpumask_var_t irq_default_affinity; -extern int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask); +/* Internal implementation. Use the helpers below */ +extern int __irq_set_affinity(unsigned int irq, const struct cpumask *cpumask, + bool force); + +/** + * irq_set_affinity - Set the irq affinity of a given irq + * @irq: Interrupt to set affinity + * @mask: cpumask + * + * Fails if cpumask does not contain an online CPU + */ +static inline int +irq_set_affinity(unsigned int irq, const struct cpumask *cpumask) +{ + return __irq_set_affinity(irq, cpumask, false); +} + +/** + * irq_force_affinity - Force the irq affinity of a given irq + * @irq: Interrupt to set affinity + * @mask: cpumask + * + * Same as irq_set_affinity, but without checking the mask against + * online cpus. + * + * Solely for low level cpu hotplug code, where we need to make per + * cpu interrupts affine before the cpu becomes online. + */ +static inline int +irq_force_affinity(unsigned int irq, const struct cpumask *cpumask) +{ + return __irq_set_affinity(irq, cpumask, true); +} + extern int irq_can_set_affinity(unsigned int irq); extern int irq_select_affinity(unsigned int irq); diff --git a/include/linux/irq.h b/include/linux/irq.h index d278838..10a0b1a 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -394,7 +394,8 @@ extern void remove_percpu_irq(unsigned int irq, struct irqaction *act); extern void irq_cpu_online(void); extern void irq_cpu_offline(void); -extern int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *cpumask); +extern int irq_set_affinity_locked(struct irq_data *data, + const struct cpumask *cpumask, bool force); #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ) void irq_move_irq(struct irq_data *data); diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 2486a4c..d34131c 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -180,7 +180,7 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, struct irq_chip *chip = irq_data_get_irq_chip(data); int ret; - ret = chip->irq_set_affinity(data, mask, false); + ret = chip->irq_set_affinity(data, mask, force); switch (ret) { case IRQ_SET_MASK_OK: cpumask_copy(data->affinity, mask); @@ -192,7 +192,8 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, return ret; } -int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask) +int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask, + bool force) { struct irq_chip *chip = irq_data_get_irq_chip(data); struct irq_desc *desc = irq_data_to_desc(data); @@ -202,7 +203,7 @@ int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask) return -EINVAL; if (irq_can_move_pcntxt(data)) { - ret = irq_do_set_affinity(data, mask, false); + ret = irq_do_set_affinity(data, mask, force); } else { irqd_set_move_pending(data); irq_copy_pending(desc, mask); @@ -217,13 +218,7 @@ int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask) return ret; } -/** - * irq_set_affinity - Set the irq affinity of a given irq - * @irq: Interrupt to set affinity - * @mask: cpumask - * - */ -int irq_set_affinity(unsigned int irq, const struct cpumask *mask) +int __irq_set_affinity(unsigned int irq, const struct cpumask *mask, bool force) { struct irq_desc *desc = irq_to_desc(irq); unsigned long flags; @@ -233,7 +228,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *mask) return -EINVAL; raw_spin_lock_irqsave(&desc->lock, flags); - ret = __irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask); + ret = irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask, force); raw_spin_unlock_irqrestore(&desc->lock, flags); return ret; } ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [patch 4/4] clocksource: exynos_mct: Register clock event after request_irq() 2014-04-16 14:36 [patch 0/4] genirq/exynos timers: Fix the CPU hotplug wreckage sanely Thomas Gleixner 2014-04-16 14:36 ` [patch 2/4] irqchip: gic: Support forced affinity setting Thomas Gleixner 2014-04-16 14:36 ` [patch 1/4] genirq: Allow forcing cpu affinity of interrupts Thomas Gleixner @ 2014-04-16 14:36 ` Thomas Gleixner 2014-04-17 21:40 ` [tip:irq/urgent] clocksource: Exynos_mct: " tip-bot for Krzysztof Kozlowski 2014-04-16 14:36 ` [patch 3/4] clocksource: exynos_mct: Use irq_force_affinity() in cpu bringup Thomas Gleixner 2014-04-16 15:59 ` [patch 0/4] genirq/exynos timers: Fix the CPU hotplug wreckage sanely Krzysztof Kozlowski 4 siblings, 1 reply; 11+ messages in thread From: Thomas Gleixner @ 2014-04-16 14:36 UTC (permalink / raw) To: LKML Cc: Krzysztof Kozlowski, Kyungmin Park, Marek Szyprowski, Bartlomiej Zolnierkiewicz, Tomasz Figa, Daniel Lezcano, Kukjin Kim, linux-arm-kernel, stable [-- Attachment #1: clocksource-exynos_mct-fix-too-early-isr-fire-up-on-wrong-cpu.patch --] [-- Type: text/plain, Size: 1463 bytes --] From: Krzysztof Kozlowski <k.kozlowski@samsung.com> After hotplugging CPU1 the first call of interrupt handler for CPU1 oneshot timer was called on CPU0 because it fired before setting IRQ affinity. Affected are SoCs where Multi Core Timer interrupts are shared (SPI), e.g. Exynos 4210. During setup of the MCT timers the clock event device should be registered after setting the affinity for interrupt. This will prevent starting the timer too early. Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- drivers/clocksource/exynos_mct.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) Index: tip/drivers/clocksource/exynos_mct.c =================================================================== --- tip.orig/drivers/clocksource/exynos_mct.c +++ tip/drivers/clocksource/exynos_mct.c @@ -416,8 +416,6 @@ static int exynos4_local_timer_setup(str evt->set_mode = exynos4_tick_set_mode; evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; evt->rating = 450; - clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1), - 0xf, 0x7fffffff); exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET); @@ -434,6 +432,8 @@ static int exynos4_local_timer_setup(str } else { enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0); } + clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1), + 0xf, 0x7fffffff); return 0; } ^ permalink raw reply [flat|nested] 11+ messages in thread
* [tip:irq/urgent] clocksource: Exynos_mct: Register clock event after request_irq() 2014-04-16 14:36 ` [patch 4/4] clocksource: exynos_mct: Register clock event after request_irq() Thomas Gleixner @ 2014-04-17 21:40 ` tip-bot for Krzysztof Kozlowski 0 siblings, 0 replies; 11+ messages in thread From: tip-bot for Krzysztof Kozlowski @ 2014-04-17 21:40 UTC (permalink / raw) To: linux-tip-commits Cc: linux-kernel, hpa, mingo, k.kozlowski, kgene.kim, kyungmin.park, b.zolnierkie, m.szyprowski, tglx Commit-ID: 8db6e5104b77de5d0b7002b95069da0992a34be9 Gitweb: http://git.kernel.org/tip/8db6e5104b77de5d0b7002b95069da0992a34be9 Author: Krzysztof Kozlowski <k.kozlowski@samsung.com> AuthorDate: Wed, 16 Apr 2014 14:36:45 +0000 Committer: Thomas Gleixner <tglx@linutronix.de> CommitDate: Thu, 17 Apr 2014 23:36:28 +0200 clocksource: Exynos_mct: Register clock event after request_irq() After hotplugging CPU1 the first call of interrupt handler for CPU1 oneshot timer was called on CPU0 because it fired before setting IRQ affinity. Affected are SoCs where Multi Core Timer interrupts are shared (SPI), e.g. Exynos 4210. During setup of the MCT timers the clock event device should be registered after setting the affinity for interrupt. This will prevent starting the timer too early. Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Kyungmin Park <kyungmin.park@samsung.com> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Cc: Tomasz Figa <t.figa@samsung.com>, Cc: Daniel Lezcano <daniel.lezcano@linaro.org>, Cc: Kukjin Kim <kgene.kim@samsung.com> Cc: linux-arm-kernel@lists.infradead.org, Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/20140416143316.299247848@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- drivers/clocksource/exynos_mct.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index b2d4163..acf5a32 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -416,8 +416,6 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) evt->set_mode = exynos4_tick_set_mode; evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; evt->rating = 450; - clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1), - 0xf, 0x7fffffff); exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET); @@ -434,6 +432,8 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) } else { enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0); } + clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1), + 0xf, 0x7fffffff); return 0; } ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [patch 3/4] clocksource: exynos_mct: Use irq_force_affinity() in cpu bringup 2014-04-16 14:36 [patch 0/4] genirq/exynos timers: Fix the CPU hotplug wreckage sanely Thomas Gleixner ` (2 preceding siblings ...) 2014-04-16 14:36 ` [patch 4/4] clocksource: exynos_mct: Register clock event after request_irq() Thomas Gleixner @ 2014-04-16 14:36 ` Thomas Gleixner 2014-04-17 21:40 ` [tip:irq/urgent] clocksource: Exynos_mct: Use irq_force_affinity( ) " tip-bot for Thomas Gleixner 2014-04-16 15:59 ` [patch 0/4] genirq/exynos timers: Fix the CPU hotplug wreckage sanely Krzysztof Kozlowski 4 siblings, 1 reply; 11+ messages in thread From: Thomas Gleixner @ 2014-04-16 14:36 UTC (permalink / raw) To: LKML Cc: Krzysztof Kozlowski, Kyungmin Park, Marek Szyprowski, Bartlomiej Zolnierkiewicz, Tomasz Figa, Daniel Lezcano, Kukjin Kim, linux-arm-kernel, stable [-- Attachment #1: clocksource-exynos_mct-use-irq-force-affinity.patch --] [-- Type: text/plain, Size: 1496 bytes --] The starting cpu is not yet in the online mask so irq_set_affinity() fails which results in per cpu timers for this cpu ending up on some other online cpu, ususally cpu 0. Use irq_force_affinity() which disables the online mask check and makes things work. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- drivers/clocksource/exynos_mct.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) Index: tip/drivers/clocksource/exynos_mct.c =================================================================== --- tip.orig/drivers/clocksource/exynos_mct.c +++ tip/drivers/clocksource/exynos_mct.c @@ -430,6 +430,7 @@ static int exynos4_local_timer_setup(str evt->irq); return -EIO; } + irq_force_affinity(mct_irqs[MCT_L0_IRQ + cpu], cpumask_of(cpu)); } else { enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0); } @@ -450,7 +451,6 @@ static int exynos4_mct_cpu_notify(struct unsigned long action, void *hcpu) { struct mct_clock_event_device *mevt; - unsigned int cpu; /* * Grab cpu pointer in each case to avoid spurious @@ -461,12 +461,6 @@ static int exynos4_mct_cpu_notify(struct mevt = this_cpu_ptr(&percpu_mct_tick); exynos4_local_timer_setup(&mevt->evt); break; - case CPU_ONLINE: - cpu = (unsigned long)hcpu; - if (mct_int_type == MCT_INT_SPI) - irq_set_affinity(mct_irqs[MCT_L0_IRQ + cpu], - cpumask_of(cpu)); - break; case CPU_DYING: mevt = this_cpu_ptr(&percpu_mct_tick); exynos4_local_timer_stop(&mevt->evt); ^ permalink raw reply [flat|nested] 11+ messages in thread
* [tip:irq/urgent] clocksource: Exynos_mct: Use irq_force_affinity( ) in cpu bringup 2014-04-16 14:36 ` [patch 3/4] clocksource: exynos_mct: Use irq_force_affinity() in cpu bringup Thomas Gleixner @ 2014-04-17 21:40 ` tip-bot for Thomas Gleixner 0 siblings, 0 replies; 11+ messages in thread From: tip-bot for Thomas Gleixner @ 2014-04-17 21:40 UTC (permalink / raw) To: linux-tip-commits Cc: linux-kernel, hpa, mingo, k.kozlowski, kgene.kim, kyungmin.park, b.zolnierkie, m.szyprowski, tglx Commit-ID: 30ccf03b4a6a2102a2219058bdc6d779dc637dd7 Gitweb: http://git.kernel.org/tip/30ccf03b4a6a2102a2219058bdc6d779dc637dd7 Author: Thomas Gleixner <tglx@linutronix.de> AuthorDate: Wed, 16 Apr 2014 14:36:45 +0000 Committer: Thomas Gleixner <tglx@linutronix.de> CommitDate: Thu, 17 Apr 2014 23:36:28 +0200 clocksource: Exynos_mct: Use irq_force_affinity() in cpu bringup The starting cpu is not yet in the online mask so irq_set_affinity() fails which results in per cpu timers for this cpu ending up on some other online cpu, ususally cpu 0. Use irq_force_affinity() which disables the online mask check and makes things work. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Cc: Kyungmin Park <kyungmin.park@samsung.com> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Cc: Tomasz Figa <t.figa@samsung.com>, Cc: Daniel Lezcano <daniel.lezcano@linaro.org>, Cc: Kukjin Kim <kgene.kim@samsung.com> Cc: linux-arm-kernel@lists.infradead.org, Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/20140416143316.106665251@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- drivers/clocksource/exynos_mct.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index a6ee6d7..b2d4163 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -430,6 +430,7 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) evt->irq); return -EIO; } + irq_force_affinity(mct_irqs[MCT_L0_IRQ + cpu], cpumask_of(cpu)); } else { enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0); } @@ -450,7 +451,6 @@ static int exynos4_mct_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { struct mct_clock_event_device *mevt; - unsigned int cpu; /* * Grab cpu pointer in each case to avoid spurious @@ -461,12 +461,6 @@ static int exynos4_mct_cpu_notify(struct notifier_block *self, mevt = this_cpu_ptr(&percpu_mct_tick); exynos4_local_timer_setup(&mevt->evt); break; - case CPU_ONLINE: - cpu = (unsigned long)hcpu; - if (mct_int_type == MCT_INT_SPI) - irq_set_affinity(mct_irqs[MCT_L0_IRQ + cpu], - cpumask_of(cpu)); - break; case CPU_DYING: mevt = this_cpu_ptr(&percpu_mct_tick); exynos4_local_timer_stop(&mevt->evt); ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [patch 0/4] genirq/exynos timers: Fix the CPU hotplug wreckage sanely 2014-04-16 14:36 [patch 0/4] genirq/exynos timers: Fix the CPU hotplug wreckage sanely Thomas Gleixner ` (3 preceding siblings ...) 2014-04-16 14:36 ` [patch 3/4] clocksource: exynos_mct: Use irq_force_affinity() in cpu bringup Thomas Gleixner @ 2014-04-16 15:59 ` Krzysztof Kozlowski 2014-04-16 21:16 ` Thomas Gleixner 4 siblings, 1 reply; 11+ messages in thread From: Krzysztof Kozlowski @ 2014-04-16 15:59 UTC (permalink / raw) To: Thomas Gleixner Cc: LKML, Kyungmin Park, Marek Szyprowski, Bartlomiej Zolnierkiewicz, Tomasz Figa, Daniel Lezcano, Kukjin Kim, linux-arm-kernel, stable On śro, 2014-04-16 at 14:36 +0000, Thomas Gleixner wrote: > The current implementation of irq_set_affinity() refuses rightfully to > route an interrupt to an offline cpu. > > But there is a special case, where this is actually desired. Some of > the ARM SoCs have per cpu timers which require setting the affinity > during cpu startup where the cpu is not yet in the online mask. > > If we can't do that, then the local timer interrupt for the about to > become online cpu is routed to some random online cpu. > > The developers of the affected machines tried to work around that > issue, but that results in a massive mess in that timer code. > > It's saner to provide a facility to force the affinity and make the > affected machines use that. > > The following series implements that logic w/o impact on any existing > users. > > The change to the genirq core code is not that bad: > > arch/mips/cavium-octeon/octeon-irq.c | 2 +- > include/linux/interrupt.h | 35 ++++++++++++++++++++++++++++++++++- > include/linux/irq.h | 3 ++- > kernel/irq/manage.c | 17 ++++++----------- > 4 files changed, 43 insertions(+), 14 deletions(-) > > The resulting fixup for gic/exynos_mct is: > > clocksource/exynos_mct.c | 12 +++--------- > irqchip/irq-gic.c | 8 ++++++-- > 2 files changed, 9 insertions(+), 11 deletions(-) > > Krzysztofs proposed workaround was slightly smaller than that, but I > prefer having a clean solution for backporting to stable rather than a > messy hack around which works. > > @Krzysztof: Can you please retest the series? I've changed the core > implementation versus the first attempt to make it less intrusive. Works fine. Tested whole patchset on board with Exynos 3250. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [patch 0/4] genirq/exynos timers: Fix the CPU hotplug wreckage sanely 2014-04-16 15:59 ` [patch 0/4] genirq/exynos timers: Fix the CPU hotplug wreckage sanely Krzysztof Kozlowski @ 2014-04-16 21:16 ` Thomas Gleixner 0 siblings, 0 replies; 11+ messages in thread From: Thomas Gleixner @ 2014-04-16 21:16 UTC (permalink / raw) To: Krzysztof Kozlowski Cc: LKML, Kyungmin Park, Marek Szyprowski, Bartlomiej Zolnierkiewicz, Tomasz Figa, Daniel Lezcano, Kukjin Kim, linux-arm-kernel, stable [-- Attachment #1: Type: TEXT/PLAIN, Size: 355 bytes --] On Wed, 16 Apr 2014, Krzysztof Kozlowski wrote: > On śro, 2014-04-16 at 14:36 +0000, Thomas Gleixner wrote: > > @Krzysztof: Can you please retest the series? I've changed the core > > implementation versus the first attempt to make it less intrusive. > > Works fine. Tested whole patchset on board with Exynos 3250. Great! Now I just need to sell it :) ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2014-04-17 21:40 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-04-16 14:36 [patch 0/4] genirq/exynos timers: Fix the CPU hotplug wreckage sanely Thomas Gleixner 2014-04-16 14:36 ` [patch 2/4] irqchip: gic: Support forced affinity setting Thomas Gleixner 2014-04-17 21:39 ` [tip:irq/urgent] irqchip: Gic: " tip-bot for Thomas Gleixner 2014-04-16 14:36 ` [patch 1/4] genirq: Allow forcing cpu affinity of interrupts Thomas Gleixner 2014-04-17 21:39 ` [tip:irq/urgent] " tip-bot for Thomas Gleixner 2014-04-16 14:36 ` [patch 4/4] clocksource: exynos_mct: Register clock event after request_irq() Thomas Gleixner 2014-04-17 21:40 ` [tip:irq/urgent] clocksource: Exynos_mct: " tip-bot for Krzysztof Kozlowski 2014-04-16 14:36 ` [patch 3/4] clocksource: exynos_mct: Use irq_force_affinity() in cpu bringup Thomas Gleixner 2014-04-17 21:40 ` [tip:irq/urgent] clocksource: Exynos_mct: Use irq_force_affinity( ) " tip-bot for Thomas Gleixner 2014-04-16 15:59 ` [patch 0/4] genirq/exynos timers: Fix the CPU hotplug wreckage sanely Krzysztof Kozlowski 2014-04-16 21:16 ` Thomas Gleixner
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).