From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753307AbcJDLS7 (ORCPT ); Tue, 4 Oct 2016 07:18:59 -0400 Received: from terminus.zytor.com ([198.137.202.10]:42392 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752757AbcJDLS6 (ORCPT ); Tue, 4 Oct 2016 07:18:58 -0400 Date: Tue, 4 Oct 2016 04:18:48 -0700 From: tip-bot for Mika Westerberg Message-ID: Cc: hpa@zytor.com, tglx@linutronix.de, sakari.ailus@linux.intel.com, linux-kernel@vger.kernel.org, mingo@kernel.org, mika.westerberg@linux.intel.com Reply-To: mika.westerberg@linux.intel.com, mingo@kernel.org, sakari.ailus@linux.intel.com, linux-kernel@vger.kernel.org, hpa@zytor.com, tglx@linutronix.de In-Reply-To: <20161003101708.34795-1-mika.westerberg@linux.intel.com> References: <20161003101708.34795-1-mika.westerberg@linux.intel.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/urgent] x86/irq: Prevent force migration of irqs which are not in the vector domain Git-Commit-ID: db91aa793ff984ac048e199ea1c54202543952fe X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: db91aa793ff984ac048e199ea1c54202543952fe Gitweb: http://git.kernel.org/tip/db91aa793ff984ac048e199ea1c54202543952fe Author: Mika Westerberg AuthorDate: Mon, 3 Oct 2016 13:17:08 +0300 Committer: Thomas Gleixner 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 Signed-off-by: Mika Westerberg 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 --- 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;