From patchwork Tue May 16 15:14:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 9729279 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 06A91602DB for ; Tue, 16 May 2017 15:14:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EBA4B28631 for ; Tue, 16 May 2017 15:14:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DD29628A01; Tue, 16 May 2017 15:14:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A4D4F28631 for ; Tue, 16 May 2017 15:14:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752119AbdEPPOd (ORCPT ); Tue, 16 May 2017 11:14:33 -0400 Received: from galahad.ideasonboard.com ([185.26.127.97]:45454 "EHLO galahad.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750987AbdEPPOc (ORCPT ); Tue, 16 May 2017 11:14:32 -0400 Received: from avalon.bb.dnainternet.fi (dfj612ybrt5fhg77mgycy-3.rev.dnainternet.fi [IPv6:2001:14ba:21f5:5b00:2e86:4862:ef6a:2804]) by galahad.ideasonboard.com (Postfix) with ESMTPSA id 1AD1420092; Tue, 16 May 2017 17:14:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1494947666; bh=Q+rzA/9215B4FBk5W5iR55LpQGv0gsbNZqVcv63HHDo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UP1NFtsdnkDtluMR7enA+sd05PbjERFvy+o7ZvTvYjLIJse2nDCBWq33lmON8CUZF aMw0QJ6cO1DxjMj6liPMTUDoNXD+wL6J26menMmPRpErC3UWBDbECkWp56NsK+o2cS VB0gWR1RLdGZ3x9AUhHpdU4qt0Bx+uzJ7iA//aTc= From: Laurent Pinchart To: linux-arm-kernel@lists.infradead.org Cc: Sricharan R , Robin Murphy , Joerg Roedel , Geert Uytterhoeven , Will Deacon , iommu@lists.linux-foundation.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH] ARM: dma-mapping: Don't tear third-party mappings Date: Tue, 16 May 2017 18:14:34 +0300 Message-Id: <20170516151434.18830-1-laurent.pinchart+renesas@ideasonboard.com> X-Mailer: git-send-email 2.13.0 In-Reply-To: <6d9fa319-4401-c47a-7985-9a349838bcaf@arm.com> References: <6d9fa319-4401-c47a-7985-9a349838bcaf@arm.com> Sender: linux-renesas-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP arch_setup_dma_ops() is used in device probe code paths to create an IOMMU mapping and attach it to the device. The function assumes that the device is attached to a device-specific IOMMU instance (or at least a device-specific TLB in a shared IOMMU instance) and thus creates a separate mapping for every device. On several systems (Renesas R-Car Gen2 being one of them), that assumption is not true, and IOMMU mappings must be shared between multiple devices. In those cases the IOMMU driver knows better than the generic ARM dma-mapping layer and attaches mapping to devices manually with arm_iommu_attach_device(), which sets the DMA ops for the device. The arch_setup_dma_ops() function takes this into account and bails out immediately if the device already has DMA ops assigned. However, the corresponding arch_teardown_dma_ops() function, called from driver unbind code paths (including probe deferral), will tear the mapping down regardless of who created it. When the device is reprobed arch_setup_dma_ops() will be called again but won't perform any operation as the DMA ops will still be set. We need to reset the DMA ops in arch_teardown_dma_ops() to fix this. However, we can't do so unconditionally, as then a new mapping would be created by arch_setup_dma_ops() when the device is reprobed, regardless of whether the device needs to share a mapping or not. We must thus keep track of whether arch_setup_dma_ops() created the mapping, and only in that case tear it down in arch_teardown_dma_ops(). Keep track of that information in the dev_archdata structure. As the structure is embedded in all instances of struct device let's not grow it, but turn the existing dma_coherent bool field into a bitfield that can be used for other purposes. Fixes: 7b07cbefb68d ("iommu: of: Handle IOMMU lookup failure with deferred probing or error") Signed-off-by: Laurent Pinchart Reviewed-by: Robin Murphy Tested-by: Laurent Pinchart --- arch/arm/include/asm/device.h | 3 ++- arch/arm/mm/dma-mapping.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h index 36ec9c8f6e16..3234fe9bba6e 100644 --- a/arch/arm/include/asm/device.h +++ b/arch/arm/include/asm/device.h @@ -19,7 +19,8 @@ struct dev_archdata { #ifdef CONFIG_XEN const struct dma_map_ops *dev_dma_ops; #endif - bool dma_coherent; + unsigned int dma_coherent:1; + unsigned int dma_ops_setup:1; }; struct omap_device; diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index c742dfd2967b..e0272f9140e2 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -2430,9 +2430,14 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, dev->dma_ops = xen_dma_ops; } #endif + dev->archdata.dma_ops_setup = true; } void arch_teardown_dma_ops(struct device *dev) { + if (!dev->archdata.dma_ops_setup) + return; + arm_teardown_iommu_dma_ops(dev); + set_dma_ops(dev, NULL); }