All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86/irq: Do not touch IRQ chip_data if it does not belong to x86_vector_domain
@ 2016-10-03 10:17 Mika Westerberg
  2016-10-03 13:37 ` Sakari Ailus
  2016-10-04 11:18 ` [tip:x86/urgent] x86/irq: Prevent force migration of irqs which are not in the vector domain tip-bot for Mika Westerberg
  0 siblings, 2 replies; 3+ messages in thread
From: Mika Westerberg @ 2016-10-03 10:17 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, H . Peter Anvin
  Cc: x86, Jiang Liu, Sakari Ailus, Mika Westerberg, linux-kernel

When a CPU is about to be offlined we call fixup_irqs() that resets IRQ
affinities related to the CPU in question. The same thing is also done when
the system is suspended to S-states like S3 (mem).

For each IRQ we try to complete any on-going move regardless whether the
IRQ is actually part of x86_vector_domain. For each IRQ descriptor we fetch
its chip_data, assume it is of type struct apic_chip_data and manipulate it
by clearing old_domain mask etc. For irq_chips that are not part of the
x86_vector_domain, like those created by various GPIO drivers, will find
their chip_data being changed unexpectly.

Below is an example where GPIO chip owned by pinctrl-sunrisepoint.c gets
corrupted after resume:

  # cat /sys/kernel/debug/gpio
  gpiochip0: GPIOs 360-511, parent: platform/INT344B:00, INT344B:00:
   gpio-511 (                    |sysfs               ) in  hi

  # rtcwake -s10 -mmem
  <10 seconds passes>

  # cat /sys/kernel/debug/gpio
  gpiochip0: GPIOs 360-511, parent: platform/INT344B:00, INT344B:00:
   gpio-511 (                    |sysfs               ) in  ?

Note '?' in the output. It means the struct gpio_chip ->get function is
NULL whereas before suspend it was there.

Fix this by first checking that the IRQ belongs to x86_vector_domain before
we try to use the chip_data as struct apic_chip_data.

Reported-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 arch/x86/kernel/apic/vector.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index 6066d945c40e..5d30c5e42bb1 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -661,11 +661,28 @@ void irq_complete_move(struct irq_cfg *cfg)
  */
 void irq_force_complete_move(struct irq_desc *desc)
 {
-	struct irq_data *irqdata = irq_desc_get_irq_data(desc);
-	struct apic_chip_data *data = apic_chip_data(irqdata);
-	struct irq_cfg *cfg = data ? &data->cfg : NULL;
+	struct irq_data *irqdata;
+	struct apic_chip_data *data;
+	struct irq_cfg *cfg;
 	unsigned int cpu;
 
+	/*
+	 * The function is called for all descriptors regardless of which
+	 * irqdomain they belong to. For example if an IRQ is provided by
+	 * an irq_chip as part of a GPIO driver, the chip data for that
+	 * descriptor is specific to the irq_chip in question.
+	 *
+	 * Check first that the chip_data is what we expect
+	 * (apic_chip_data) before touching it any further.
+	 */
+	irqdata = irq_domain_get_irq_data(x86_vector_domain,
+					  irq_desc_get_irq(desc));
+	if (!irqdata)
+		return;
+
+	data = apic_chip_data(irqdata);
+	cfg = data ? &data->cfg : NULL;
+
 	if (!cfg)
 		return;
 
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] x86/irq: Do not touch IRQ chip_data if it does not belong to x86_vector_domain
  2016-10-03 10:17 [PATCH] x86/irq: Do not touch IRQ chip_data if it does not belong to x86_vector_domain Mika Westerberg
@ 2016-10-03 13:37 ` Sakari Ailus
  2016-10-04 11:18 ` [tip:x86/urgent] x86/irq: Prevent force migration of irqs which are not in the vector domain tip-bot for Mika Westerberg
  1 sibling, 0 replies; 3+ messages in thread
From: Sakari Ailus @ 2016-10-03 13:37 UTC (permalink / raw)
  To: Mika Westerberg, Thomas Gleixner, Ingo Molnar, H . Peter Anvin
  Cc: x86, Jiang Liu, linux-kernel

Hi Mika,

On 10/03/16 13:17, Mika Westerberg wrote:
> When a CPU is about to be offlined we call fixup_irqs() that resets IRQ
> affinities related to the CPU in question. The same thing is also done when
> the system is suspended to S-states like S3 (mem).
> 
> For each IRQ we try to complete any on-going move regardless whether the
> IRQ is actually part of x86_vector_domain. For each IRQ descriptor we fetch
> its chip_data, assume it is of type struct apic_chip_data and manipulate it
> by clearing old_domain mask etc. For irq_chips that are not part of the
> x86_vector_domain, like those created by various GPIO drivers, will find
> their chip_data being changed unexpectly.
> 
> Below is an example where GPIO chip owned by pinctrl-sunrisepoint.c gets
> corrupted after resume:
> 
>   # cat /sys/kernel/debug/gpio
>   gpiochip0: GPIOs 360-511, parent: platform/INT344B:00, INT344B:00:
>    gpio-511 (                    |sysfs               ) in  hi
> 
>   # rtcwake -s10 -mmem
>   <10 seconds passes>
> 
>   # cat /sys/kernel/debug/gpio
>   gpiochip0: GPIOs 360-511, parent: platform/INT344B:00, INT344B:00:
>    gpio-511 (                    |sysfs               ) in  ?
> 
> Note '?' in the output. It means the struct gpio_chip ->get function is
> NULL whereas before suspend it was there.
> 
> Fix this by first checking that the IRQ belongs to x86_vector_domain before
> we try to use the chip_data as struct apic_chip_data.
> 
> Reported-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>

Thanks for debugging this! I've tested it on the laptop where the SD
card is no longer detected after suspend; with this patch it works fine.

Tested-by: Sakari Ailus <sakari.ailus@linux.intel.com>

-- 
Sakari Ailus
sakari.ailus@linux.intel.com

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [tip:x86/urgent] x86/irq: Prevent force migration of irqs which are not in the vector domain
  2016-10-03 10:17 [PATCH] x86/irq: Do not touch IRQ chip_data if it does not belong to x86_vector_domain Mika Westerberg
  2016-10-03 13:37 ` Sakari Ailus
@ 2016-10-04 11:18 ` tip-bot for Mika Westerberg
  1 sibling, 0 replies; 3+ messages in thread
From: tip-bot for Mika Westerberg @ 2016-10-04 11:18 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, tglx, sakari.ailus, linux-kernel, mingo, mika.westerberg

Commit-ID:  db91aa793ff984ac048e199ea1c54202543952fe
Gitweb:     http://git.kernel.org/tip/db91aa793ff984ac048e199ea1c54202543952fe
Author:     Mika Westerberg <mika.westerberg@linux.intel.com>
AuthorDate: Mon, 3 Oct 2016 13:17:08 +0300
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 4 Oct 2016 13:13:47 +0200

x86/irq: Prevent force migration of irqs which are not in the vector domain

When a CPU is about to be offlined we call fixup_irqs() that resets IRQ
affinities related to the CPU in question. The same thing is also done when
the system is suspended to S-states like S3 (mem).

For each IRQ we try to complete any on-going move regardless whether the
IRQ is actually part of x86_vector_domain. For each IRQ descriptor we fetch
its chip_data, assume it is of type struct apic_chip_data and manipulate it
by clearing old_domain mask etc. For irq_chips that are not part of the
x86_vector_domain, like those created by various GPIO drivers, will find
their chip_data being changed unexpectly.

Below is an example where GPIO chip owned by pinctrl-sunrisepoint.c gets
corrupted after resume:

  # cat /sys/kernel/debug/gpio
  gpiochip0: GPIOs 360-511, parent: platform/INT344B:00, INT344B:00:
   gpio-511 (                    |sysfs               ) in  hi

  # rtcwake -s10 -mmem
  <10 seconds passes>

  # cat /sys/kernel/debug/gpio
  gpiochip0: GPIOs 360-511, parent: platform/INT344B:00, INT344B:00:
   gpio-511 (                    |sysfs               ) in  ?

Note '?' in the output. It means the struct gpio_chip ->get function is
NULL whereas before suspend it was there.

Fix this by first checking that the IRQ belongs to x86_vector_domain before
we try to use the chip_data as struct apic_chip_data.

Reported-and-tested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: stable@vger.kernel.org # 4.4+
Link: http://lkml.kernel.org/r/20161003101708.34795-1-mika.westerberg@linux.intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 arch/x86/kernel/apic/vector.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index 6066d94..5d30c5e 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -661,11 +661,28 @@ void irq_complete_move(struct irq_cfg *cfg)
  */
 void irq_force_complete_move(struct irq_desc *desc)
 {
-	struct irq_data *irqdata = irq_desc_get_irq_data(desc);
-	struct apic_chip_data *data = apic_chip_data(irqdata);
-	struct irq_cfg *cfg = data ? &data->cfg : NULL;
+	struct irq_data *irqdata;
+	struct apic_chip_data *data;
+	struct irq_cfg *cfg;
 	unsigned int cpu;
 
+	/*
+	 * The function is called for all descriptors regardless of which
+	 * irqdomain they belong to. For example if an IRQ is provided by
+	 * an irq_chip as part of a GPIO driver, the chip data for that
+	 * descriptor is specific to the irq_chip in question.
+	 *
+	 * Check first that the chip_data is what we expect
+	 * (apic_chip_data) before touching it any further.
+	 */
+	irqdata = irq_domain_get_irq_data(x86_vector_domain,
+					  irq_desc_get_irq(desc));
+	if (!irqdata)
+		return;
+
+	data = apic_chip_data(irqdata);
+	cfg = data ? &data->cfg : NULL;
+
 	if (!cfg)
 		return;
 

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-10-04 11:18 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-10-03 10:17 [PATCH] x86/irq: Do not touch IRQ chip_data if it does not belong to x86_vector_domain Mika Westerberg
2016-10-03 13:37 ` Sakari Ailus
2016-10-04 11:18 ` [tip:x86/urgent] x86/irq: Prevent force migration of irqs which are not in the vector domain tip-bot for Mika Westerberg

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.