From: gregory.clement@free-electrons.com (Gregory CLEMENT)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 3/5] irqchip: armada-370-xp: re-enable per-CPU interrupts at resume time
Date: Tue, 20 Oct 2015 15:46:00 +0200 [thread overview]
Message-ID: <87vba1ejqf.fsf@free-electrons.com> (raw)
In-Reply-To: <1445347435-2333-4-git-send-email-thomas.petazzoni@free-electrons.com> (Thomas Petazzoni's message of "Tue, 20 Oct 2015 15:23:53 +0200")
Hi Thomas,
On mar., oct. 20 2015, Thomas Petazzoni <thomas.petazzoni@free-electrons.com> wrote:
> Commit d17cab4451df1 ("irqchip: Kill off set_irq_flags usage") changed
> the code of armada_370_xp_mpic_irq_map() from using set_irq_flags() to
> irq_set_probe().
>
> While the commit log seems to imply that there are no functional
> changes, there are indeed functional changes introduced by this
> commit: the IRQ_NOAUTOEN flag is no longer cleared. This functional
> change causes a regression on Armada XP, which no longer works
> properly after suspend/resume because per-CPU interrupts remain
> disabled.
>
> Due to how the hardware registers work, the irq-armada-370-xp cannot
> simply save/restore a bunch of registers at suspend/resume to make
> sure that the interrupts remain in the same state after
> resuming. Therefore, it relies on the kernel to say whether the
> interrupt is disabled or not, using the irqd_irq_disabled()
> function. This was all working fine while the IRQ_NOAUTOEN flag was
> cleared.
>
> With the change introduced by Rob Herring in d17cab4451df1, the
> IRQ_NOAUTOEN flag is now set for all interrupts. irqd_irq_disabled()
> returns false for per-CPU interrupts, and therefore our per-CPU
> interrupts are no longer re-enabled after resume.
>
> This commit fixes that by using irqd_irq_disabled() only for global
> interrupts, and using the newly introduced is_enabled_percpu_irq() for
> per-CPU interrupts.
>
> Also, it fixes a related problems that per-CPU interrupts were only
> re-enabled on the boot CPU and not other CPUs. Until now this wasn't a
> problem since on this platform, only the local timers are using
> per-CPU interrupts and the local timers of secondary CPUs are turned
> off/on during CPU hotplug before suspend, after after resume. However,
> in Linux 4.4, we will also be using per-CPU interrupts for the network
> controller, so we need to properly restore the per-CPU interrupts on
> secondary CPUs as well.
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> ---
> drivers/irqchip/irq-armada-370-xp.c | 45 ++++++++++++++++++++++++++++++++-----
> 1 file changed, 39 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
> index f5afe81..106ac4c 100644
> --- a/drivers/irqchip/irq-armada-370-xp.c
> +++ b/drivers/irqchip/irq-armada-370-xp.c
> @@ -311,7 +311,6 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
> irq_set_percpu_devid(virq);
> irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
> handle_percpu_devid_irq);
> -
> } else {
> irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
> handle_level_irq);
> @@ -377,12 +376,35 @@ static void armada_mpic_send_doorbell(const struct cpumask *mask,
> static int armada_xp_mpic_secondary_init(struct notifier_block *nfb,
> unsigned long action, void *hcpu)
> {
> + unsigned int nirqs, irq;
> +
> if (action != CPU_STARTING && action != CPU_STARTING_FROZEN)
> return NOTIFY_OK;
>
> armada_xp_mpic_perf_init();
> armada_xp_mpic_smp_cpu_init();
>
> + /* Re-enable per-CPU interrupts that were enabled before suspend */
> + nirqs = (readl(main_int_base + ARMADA_370_XP_INT_CONTROL) >> 2) & 0x3ff;
> + for (irq = 0; irq < nirqs; irq++) {
Actually we could reduce this loop by using
ARMADA_370_XP_MAX_PER_CPU_IRQS, as we know that we can't have more per
cpu irq.
> + struct irq_data *data;
> + int virq;
> +
> + virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq);
> + if (virq == 0)
> + continue;
> +
> + data = irq_get_irq_data(virq);
> +
> + if (irq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
> + continue;
So eventually you only manage the timer IRQs?
If it is intentional you could it differently, but I wonder why you don't
enable again the other percpu IRQ.
> +
> + if (!is_enabled_percpu_irq(virq))
> + continue;
> +
> + armada_370_xp_irq_unmask(data);
> + }
> +
> return NOTIFY_OK;
> }
>
The following chunk will conflict with "irqchip: armada-370-xp: Rework
per-cpu interrupts handling" which is in Linux next. But as this patch
is for 4.3, you can't do anything...
> @@ -550,16 +572,27 @@ static void armada_370_xp_mpic_resume(void)
> if (virq == 0)
> continue;
>
> - if (irq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
> + data = irq_get_irq_data(virq);
> +
> + if (irq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ) {
> + /* Non per-CPU interrupts */
> writel(irq, per_cpu_int_base +
> ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
> - else
> + if (!irqd_irq_disabled(data))
> + armada_370_xp_irq_unmask(data);
> + } else {
> + /* Per-CPU interrupts */
> writel(irq, main_int_base +
> ARMADA_370_XP_INT_SET_ENABLE_OFFS);
>
> - data = irq_get_irq_data(virq);
> - if (!irqd_irq_disabled(data))
> - armada_370_xp_irq_unmask(data);
> + /*
> + * Re-enable on the current CPU,
> + * armada_xp_mpic_secondary_init() will take
> + * care of secondary CPUs when they come up.
> + */
> + if (is_enabled_percpu_irq(virq))
> + armada_370_xp_irq_unmask(data);
> + }
> }
>
> /* Reconfigure doorbells for IPIs and MSIs */
> --
> 2.6.2
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
WARNING: multiple messages have this Message-ID (diff)
From: Gregory CLEMENT <gregory.clement@free-electrons.com>
To: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Thomas Gleixner <tglx@linutronix.de>,
Jason Cooper <jason@lakedaemon.net>,
Marc Zyngier <marc.zyngier@arm.com>,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
Tawfik Bayouk <tawfik@marvell.com>,
Nadav Haklai <nadavh@marvell.com>,
Lior Amsalem <alior@marvell.com>, Andrew Lunn <andrew@lunn.ch>,
Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Subject: Re: [PATCH 3/5] irqchip: armada-370-xp: re-enable per-CPU interrupts at resume time
Date: Tue, 20 Oct 2015 15:46:00 +0200 [thread overview]
Message-ID: <87vba1ejqf.fsf@free-electrons.com> (raw)
In-Reply-To: <1445347435-2333-4-git-send-email-thomas.petazzoni@free-electrons.com> (Thomas Petazzoni's message of "Tue, 20 Oct 2015 15:23:53 +0200")
Hi Thomas,
On mar., oct. 20 2015, Thomas Petazzoni <thomas.petazzoni@free-electrons.com> wrote:
> Commit d17cab4451df1 ("irqchip: Kill off set_irq_flags usage") changed
> the code of armada_370_xp_mpic_irq_map() from using set_irq_flags() to
> irq_set_probe().
>
> While the commit log seems to imply that there are no functional
> changes, there are indeed functional changes introduced by this
> commit: the IRQ_NOAUTOEN flag is no longer cleared. This functional
> change causes a regression on Armada XP, which no longer works
> properly after suspend/resume because per-CPU interrupts remain
> disabled.
>
> Due to how the hardware registers work, the irq-armada-370-xp cannot
> simply save/restore a bunch of registers at suspend/resume to make
> sure that the interrupts remain in the same state after
> resuming. Therefore, it relies on the kernel to say whether the
> interrupt is disabled or not, using the irqd_irq_disabled()
> function. This was all working fine while the IRQ_NOAUTOEN flag was
> cleared.
>
> With the change introduced by Rob Herring in d17cab4451df1, the
> IRQ_NOAUTOEN flag is now set for all interrupts. irqd_irq_disabled()
> returns false for per-CPU interrupts, and therefore our per-CPU
> interrupts are no longer re-enabled after resume.
>
> This commit fixes that by using irqd_irq_disabled() only for global
> interrupts, and using the newly introduced is_enabled_percpu_irq() for
> per-CPU interrupts.
>
> Also, it fixes a related problems that per-CPU interrupts were only
> re-enabled on the boot CPU and not other CPUs. Until now this wasn't a
> problem since on this platform, only the local timers are using
> per-CPU interrupts and the local timers of secondary CPUs are turned
> off/on during CPU hotplug before suspend, after after resume. However,
> in Linux 4.4, we will also be using per-CPU interrupts for the network
> controller, so we need to properly restore the per-CPU interrupts on
> secondary CPUs as well.
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> ---
> drivers/irqchip/irq-armada-370-xp.c | 45 ++++++++++++++++++++++++++++++++-----
> 1 file changed, 39 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
> index f5afe81..106ac4c 100644
> --- a/drivers/irqchip/irq-armada-370-xp.c
> +++ b/drivers/irqchip/irq-armada-370-xp.c
> @@ -311,7 +311,6 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
> irq_set_percpu_devid(virq);
> irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
> handle_percpu_devid_irq);
> -
> } else {
> irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
> handle_level_irq);
> @@ -377,12 +376,35 @@ static void armada_mpic_send_doorbell(const struct cpumask *mask,
> static int armada_xp_mpic_secondary_init(struct notifier_block *nfb,
> unsigned long action, void *hcpu)
> {
> + unsigned int nirqs, irq;
> +
> if (action != CPU_STARTING && action != CPU_STARTING_FROZEN)
> return NOTIFY_OK;
>
> armada_xp_mpic_perf_init();
> armada_xp_mpic_smp_cpu_init();
>
> + /* Re-enable per-CPU interrupts that were enabled before suspend */
> + nirqs = (readl(main_int_base + ARMADA_370_XP_INT_CONTROL) >> 2) & 0x3ff;
> + for (irq = 0; irq < nirqs; irq++) {
Actually we could reduce this loop by using
ARMADA_370_XP_MAX_PER_CPU_IRQS, as we know that we can't have more per
cpu irq.
> + struct irq_data *data;
> + int virq;
> +
> + virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq);
> + if (virq == 0)
> + continue;
> +
> + data = irq_get_irq_data(virq);
> +
> + if (irq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
> + continue;
So eventually you only manage the timer IRQs?
If it is intentional you could it differently, but I wonder why you don't
enable again the other percpu IRQ.
> +
> + if (!is_enabled_percpu_irq(virq))
> + continue;
> +
> + armada_370_xp_irq_unmask(data);
> + }
> +
> return NOTIFY_OK;
> }
>
The following chunk will conflict with "irqchip: armada-370-xp: Rework
per-cpu interrupts handling" which is in Linux next. But as this patch
is for 4.3, you can't do anything...
> @@ -550,16 +572,27 @@ static void armada_370_xp_mpic_resume(void)
> if (virq == 0)
> continue;
>
> - if (irq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
> + data = irq_get_irq_data(virq);
> +
> + if (irq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ) {
> + /* Non per-CPU interrupts */
> writel(irq, per_cpu_int_base +
> ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
> - else
> + if (!irqd_irq_disabled(data))
> + armada_370_xp_irq_unmask(data);
> + } else {
> + /* Per-CPU interrupts */
> writel(irq, main_int_base +
> ARMADA_370_XP_INT_SET_ENABLE_OFFS);
>
> - data = irq_get_irq_data(virq);
> - if (!irqd_irq_disabled(data))
> - armada_370_xp_irq_unmask(data);
> + /*
> + * Re-enable on the current CPU,
> + * armada_xp_mpic_secondary_init() will take
> + * care of secondary CPUs when they come up.
> + */
> + if (is_enabled_percpu_irq(virq))
> + armada_370_xp_irq_unmask(data);
> + }
> }
>
> /* Reconfigure doorbells for IPIs and MSIs */
> --
> 2.6.2
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
next prev parent reply other threads:[~2015-10-20 13:46 UTC|newest]
Thread overview: 75+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-10-20 13:23 [PATCH 0/5] Fix regression introduced by set_irq_flags() removal Thomas Petazzoni
2015-10-20 13:23 ` Thomas Petazzoni
2015-10-20 13:23 ` [PATCH 1/5] kernel: irq: implement is_enabled_percpu_irq() Thomas Petazzoni
2015-10-20 13:23 ` Thomas Petazzoni
2015-12-08 11:57 ` [tip:irq/core] genirq: Implement irq_percpu_is_enabled() tip-bot for Thomas Petazzoni
2015-10-20 13:23 ` [PATCH 2/5] irqchip: armada-370-xp: prepare additions to armada_xp_mpic_secondary_init() Thomas Petazzoni
2015-10-20 13:23 ` Thomas Petazzoni
2015-10-20 14:00 ` Gregory CLEMENT
2015-10-20 14:00 ` Gregory CLEMENT
2015-10-20 13:23 ` [PATCH 3/5] irqchip: armada-370-xp: re-enable per-CPU interrupts at resume time Thomas Petazzoni
2015-10-20 13:23 ` Thomas Petazzoni
2015-10-20 13:46 ` Gregory CLEMENT [this message]
2015-10-20 13:46 ` Gregory CLEMENT
2015-10-20 13:50 ` Thomas Petazzoni
2015-10-20 13:50 ` Thomas Petazzoni
2015-10-25 21:22 ` Marcin Wojtas
2015-10-25 21:22 ` Marcin Wojtas
2015-10-26 0:10 ` Thomas Petazzoni
2015-10-26 0:10 ` Thomas Petazzoni
2015-10-26 4:35 ` Marcin Wojtas
2015-10-26 4:35 ` Marcin Wojtas
2015-10-26 5:09 ` Thomas Petazzoni
2015-10-26 5:09 ` Thomas Petazzoni
2015-10-26 7:06 ` Marcin Wojtas
2015-10-26 7:06 ` Marcin Wojtas
2015-10-26 8:27 ` Thomas Petazzoni
2015-10-26 8:27 ` Thomas Petazzoni
2015-10-20 13:23 ` [PATCH 4/5] irqchip: armada-370-xp: re-order register definitions Thomas Petazzoni
2015-10-20 13:23 ` Thomas Petazzoni
2015-10-20 13:55 ` Gregory CLEMENT
2015-10-20 13:55 ` Gregory CLEMENT
2015-10-20 13:23 ` [PATCH 5/5] irqchip: armada-370-xp: document the overall driver logic Thomas Petazzoni
2015-10-20 13:23 ` Thomas Petazzoni
2015-10-20 13:59 ` Gregory CLEMENT
2015-10-20 13:59 ` Gregory CLEMENT
2015-10-20 14:00 ` Thomas Petazzoni
2015-10-20 14:00 ` Thomas Petazzoni
2015-10-20 14:07 ` Jason Cooper
2015-10-20 14:07 ` Jason Cooper
2015-10-20 14:04 ` [PATCH 0/5] Fix regression introduced by set_irq_flags() removal Jason Cooper
2015-10-20 14:04 ` Jason Cooper
2015-10-20 14:08 ` Thomas Petazzoni
2015-10-20 14:08 ` Thomas Petazzoni
2015-10-20 14:17 ` Russell King - ARM Linux
2015-10-20 14:17 ` Russell King - ARM Linux
2015-10-20 14:23 ` Thomas Petazzoni
2015-10-20 14:23 ` Thomas Petazzoni
2015-10-20 19:24 ` Thomas Gleixner
2015-10-20 19:24 ` Thomas Gleixner
2015-10-22 8:01 ` Thomas Gleixner
2015-10-22 8:01 ` Thomas Gleixner
2015-10-20 19:23 ` Thomas Gleixner
2015-10-20 19:23 ` Thomas Gleixner
2015-10-21 13:48 ` [PATCH] irqchip: irq-armada-370-xp: fix regression by clearing IRQ_NOAUTOEN Thomas Petazzoni
2015-10-21 13:48 ` Thomas Petazzoni
2015-10-21 14:41 ` Jason Cooper
2015-10-21 14:41 ` Jason Cooper
2015-10-21 13:49 ` [PATCH 0/5] Fix regression introduced by set_irq_flags() removal Thomas Petazzoni
2015-10-21 13:49 ` Thomas Petazzoni
2015-11-11 8:26 ` Thomas Petazzoni
2015-11-11 8:26 ` Thomas Petazzoni
2015-11-13 20:11 ` Thomas Gleixner
2015-11-13 20:11 ` Thomas Gleixner
2015-12-04 11:03 ` Thomas Petazzoni
2015-12-04 11:03 ` Thomas Petazzoni
2015-12-05 17:24 ` Thomas Gleixner
2015-12-05 17:24 ` Thomas Gleixner
2015-12-06 9:28 ` Thomas Gleixner
2015-12-06 9:28 ` Thomas Gleixner
2015-12-08 8:58 ` Thomas Petazzoni
2015-12-08 8:58 ` Thomas Petazzoni
2015-12-08 10:54 ` Thomas Gleixner
2015-12-08 10:54 ` Thomas Gleixner
2017-02-24 16:56 ` Thomas Petazzoni
2017-02-24 16:56 ` Thomas Petazzoni
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87vba1ejqf.fsf@free-electrons.com \
--to=gregory.clement@free-electrons.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.