Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751679AbdHQI3g (ORCPT ); Thu, 17 Aug 2017 04:29:36 -0400 Received: from lucky1.263xmail.com ([211.157.147.131]:35613 "EHLO lucky1.263xmail.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750857AbdHQI3d (ORCPT ); Thu, 17 Aug 2017 04:29:33 -0400 X-263anti-spam: KSV:0; X-MAIL-GRAY: 1 X-MAIL-DELIVERY: 0 X-KSVirus-check: 0 X-ABS-CHECKED: 4 X-RL-SENDER: shawn.lin@rock-chips.com X-FST-TO: tglx@linutronix.de X-SENDER-IP: 58.22.7.114 X-LOGIN-NAME: shawn.lin@rock-chips.com X-UNIQUE-TAG: X-ATTACHMENT-NUM: 0 X-DNS-TYPE: 0 From: Shawn Lin To: Thomas Gleixner , Marc Zyngier Cc: Jason Cooper , linux-kernel@vger.kernel.org, Joerg Roedel , Robin Murphy , iommu@lists.linux-foundation.org, Shawn Lin Subject: [PATCH] irqchip/gic-{v2m, v3-its}: check iommu capable before doing iommu map Date: Thu, 17 Aug 2017 16:28:28 +0800 Message-Id: <1502958508-195670-1-git-send-email-shawn.lin@rock-chips.com> X-Mailer: git-send-email 1.9.1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6349 Lines: 166 If a PCIe RC use gic-v2m or gic-v3-its as a msi domain but doesn't have iommu support, we don't need to do iommu_dma_map_msi_msg to get mapped iommu address as all we need is the physical address. Otherwise we see the oops shown below as we can't get a iommu_group for a device without iommu capable. Unable to handle kernel NULL pointer dereference at virtual address 000000d0 [00000000000000d0] user address but active_mm is swapper Internal error: Oops: 96000004 [#1] PREEMPT SMP Modules linked in: CPU: 3 PID: 1 Comm: swapper/0 Not tainted 4.13.0-rc5-next-20170815-00001-g0744890-dirty #53 Hardware name: Firefly-RK3399 Board (DT) task: ffff80007bc70000 task.stack: ffff80007bc6c000 PC is at iommu_get_domain_for_dev+0x38/0x50 LR is at iommu_dma_map_msi_msg+0x3c/0x1b8 pc : [] lr : [] pstate: a0000045 ... [] iommu_get_domain_for_dev+0x38/0x50 [] iommu_dma_map_msi_msg+0x3c/0x1b8 [] its_irq_compose_msi_msg+0x44/0x50 [] irq_chip_compose_msi_msg+0x40/0x58 [] msi_domain_activate+0x1c/0x48 [] __irq_domain_activate_irq+0x40/0x58 [] irq_domain_activate_irq+0x24/0x40 [] msi_domain_alloc_irqs+0x104/0x190 [] pci_msi_setup_msi_irqs+0x3c/0x48 [] __pci_enable_msi_range+0x21c/0x408 [] pci_alloc_irq_vectors_affinity+0x104/0x168 [] pcie_port_device_register+0x200/0x488 [] pcie_portdrv_probe+0x34/0xd0 [] local_pci_probe+0x3c/0xb8 [] pci_device_probe+0x138/0x170 [] driver_probe_device+0x21c/0x2d8 [] __device_attach_driver+0x9c/0xf8 [] bus_for_each_drv+0x5c/0x98 [] __device_attach+0xc4/0x138 [] device_attach+0x10/0x18 [] pci_bus_add_device+0x4c/0xa8 [] pci_bus_add_devices+0x44/0x90 [] rockchip_pcie_probe+0xc70/0xcc8 [] platform_drv_probe+0x58/0xc0 [] driver_probe_device+0x21c/0x2d8 [] __driver_attach+0xac/0xb0 [] bus_for_each_dev+0x64/0xa0 [] driver_attach+0x20/0x28 [] bus_add_driver+0x110/0x230 [] driver_register+0x60/0xf8 [] __platform_driver_register+0x40/0x48 [] rockchip_pcie_driver_init+0x18/0x20 [] do_one_initcall+0xb0/0x120 [] kernel_init_freeable+0x184/0x224 [] kernel_init+0x10/0x100 [] ret_from_fork+0x10/0x18 This patch is to fix the problem exposed by the commit mentioned below. Before this commit, iommu has a work around method to fix this but now it doesn't. So we could fix this in gic code but maybe still need a fixes tag here. Fixes: 05f80300dc8b ("iommu: Finish making iommu_group support mandatory") Signed-off-by: Shawn Lin --- drivers/irqchip/irq-gic-common.c | 10 ++++++++++ drivers/irqchip/irq-gic-common.h | 2 +- drivers/irqchip/irq-gic-v2m.c | 6 +++++- drivers/irqchip/irq-gic-v3-its.c | 4 +++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c index 9ae7180..c340d70 100644 --- a/drivers/irqchip/irq-gic-common.c +++ b/drivers/irqchip/irq-gic-common.c @@ -14,6 +14,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -146,3 +147,12 @@ void gic_cpu_config(void __iomem *base, void (*sync_access)(void)) if (sync_access) sync_access(); } + +bool gic_check_iommu_capable(struct device *dev) +{ + struct device_node *np = dev->of_node; + int ret; + + ret = of_count_phandle_with_args(np, "iommus", "#iommu-cells"); + return (ret > 0); +} diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h index 205e5fd..61c5db3 100644 --- a/drivers/irqchip/irq-gic-common.h +++ b/drivers/irqchip/irq-gic-common.h @@ -37,5 +37,5 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks, void *data); void gic_set_kvm_info(const struct gic_kvm_info *info); - +bool gic_check_iommu_capable(struct device *dev); #endif /* _IRQ_GIC_COMMON_H */ diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c index 993a842..87235d6 100644 --- a/drivers/irqchip/irq-gic-v2m.c +++ b/drivers/irqchip/irq-gic-v2m.c @@ -27,6 +27,8 @@ #include #include +#include "irq-gic-common.h" + /* * MSI_TYPER: * [31:26] Reserved @@ -101,6 +103,7 @@ static void gicv2m_unmask_msi_irq(struct irq_data *d) static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) { struct v2m_data *v2m = irq_data_get_irq_chip_data(data); + struct device *dev = msi_desc_to_dev(irq_get_msi_desc(data->irq)); phys_addr_t addr = v2m->res.start + V2M_MSI_SETSPI_NS; msg->address_hi = upper_32_bits(addr); @@ -110,7 +113,8 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET) msg->data -= v2m->spi_offset; - iommu_dma_map_msi_msg(data->irq, msg); + if (gic_check_iommu_capable(dev)) + iommu_dma_map_msi_msg(data->irq, msg); } static struct irq_chip gicv2m_irq_chip = { diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 6893287..843d56a 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -658,6 +658,7 @@ static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) { struct its_device *its_dev = irq_data_get_irq_chip_data(d); struct its_node *its; + struct device *dev = msi_desc_to_dev(irq_get_msi_desc(d->irq)); u64 addr; its = its_dev->its; @@ -667,7 +668,8 @@ static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) msg->address_hi = upper_32_bits(addr); msg->data = its_get_event_id(d); - iommu_dma_map_msi_msg(d->irq, msg); + if (gic_check_iommu_capable(dev)) + iommu_dma_map_msi_msg(d->irq, msg); } static struct irq_chip its_irq_chip = { -- 1.9.1