Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp1010796pxb; Tue, 3 Nov 2020 19:59:59 -0800 (PST) X-Google-Smtp-Source: ABdhPJztNp2Y062E77OmyhfZgNUSV0H4Np3PKYVoAUAJyAYslLk2K+E+tK8usdHa2suxAtBS5MOJ X-Received: by 2002:a17:906:3092:: with SMTP id 18mr23243106ejv.43.1604462399631; Tue, 03 Nov 2020 19:59:59 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1604462399; cv=none; d=google.com; s=arc-20160816; b=JXITpmIOxUP+u/e6QnjwrDmLhFT8zQk75210I4a7NC165anx+RxzFqySHJcd/LOaRH hvc91dQAcVZFFSROw2z9Qnd27SLON/XwTZT6S63Uq8hVwtMCpSsuy+dNSkTk4fUWkX5W hnpEt2bs/evIkUlnue1JxIzk9B4RL3h7wIEtanM59lvtR4Nh6U9nRUg0ob2VLBapq7FE WJsxwHe+fzu1gh4eLH1hYGZBrmBPvi0hNSVqwEJwmimtPahilvXAlJpc1X9XKwYS+GfG 5IWSjNtvsbVddSGT8LgBeVUxMP+ObTbtyoqxhEiaU8fTX/U2l06gyJ0lQEDy9GS7jnig djew== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from; bh=ESAB7sUvUQ/o+xzIQeGeYYBk5OlenibRabt4tG02qbU=; b=n1zoeO4mDDBkVptf+gmRZZQI1VHKPZeqITHpZqVW8HS3sVl7qEqsYp8sCwqcZzPhD7 inqqCQ5ROZxmD9Rt8x6MR/6MLFt69hht6fJ8ylfiJz7hRuJng21A/BJFH8hXrAIWrvxd tipAlfjAJRoq2Ce7RoVcTXVfWaUdcR2oyGHJl9Fnn3CRcnKqEEovjftefKi6uL/nQKHk uajG1asJYRH+tDuUgcHctwT4nNm2AcYomphIcavaECh2ICt1VBEFRIFSmxPtvpUdjIPe VZt2khiw/wA9LPNOJEWFlkwClke2H0loJmq1y6z4AhS7NEGQmmj2oQqehDU7M4u0ERX7 zERw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id p1si519711edd.248.2020.11.03.19.59.36; Tue, 03 Nov 2020 19:59:59 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729068AbgKDDzg (ORCPT + 99 others); Tue, 3 Nov 2020 22:55:36 -0500 Received: from ozlabs.ru ([107.174.27.60]:42026 "EHLO ozlabs.ru" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726008AbgKDDzf (ORCPT ); Tue, 3 Nov 2020 22:55:35 -0500 Received: from fstn1-p1.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id 463BCAE80275; Wed, 28 Oct 2020 02:59:54 -0400 (EDT) From: Alexey Kardashevskiy To: linuxppc-dev@lists.ozlabs.org Cc: Christoph Hellwig , Michael Ellerman , iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org, Alexey Kardashevskiy Subject: [PATCH kernel v3 1/2] dma: Allow mixing bypass and mapped DMA operation Date: Wed, 28 Oct 2020 18:00:29 +1100 Message-Id: <20201028070030.60643-2-aik@ozlabs.ru> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201028070030.60643-1-aik@ozlabs.ru> References: <20201028070030.60643-1-aik@ozlabs.ru> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org At the moment we allow bypassing DMA ops only when we can do this for the entire RAM. However there are configs with mixed type memory where we could still allow bypassing IOMMU in most cases; POWERPC with persistent memory is one example. This adds an arch hook to determine where bypass can still work and we invoke direct DMA API. The following patch checks the bus limit on POWERPC to allow or disallow direct mapping. This adds a CONFIG_ARCH_HAS_DMA_SET_MASK config option to make arch_xxxx hooks no-op by default. Signed-off-by: Alexey Kardashevskiy --- kernel/dma/mapping.c | 24 ++++++++++++++++++++---- kernel/dma/Kconfig | 4 ++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c index 51bb8fa8eb89..a0bc9eb876ed 100644 --- a/kernel/dma/mapping.c +++ b/kernel/dma/mapping.c @@ -137,6 +137,18 @@ static inline bool dma_map_direct(struct device *dev, return dma_go_direct(dev, *dev->dma_mask, ops); } +#ifdef CONFIG_ARCH_HAS_DMA_MAP_DIRECT +bool arch_dma_map_page_direct(struct device *dev, phys_addr_t addr); +bool arch_dma_unmap_page_direct(struct device *dev, dma_addr_t dma_handle); +bool arch_dma_map_sg_direct(struct device *dev, struct scatterlist *sg, int nents); +bool arch_dma_unmap_sg_direct(struct device *dev, struct scatterlist *sg, int nents); +#else +#define arch_dma_map_page_direct(d, a) (0) +#define arch_dma_unmap_page_direct(d, a) (0) +#define arch_dma_map_sg_direct(d, s, n) (0) +#define arch_dma_unmap_sg_direct(d, s, n) (0) +#endif + dma_addr_t dma_map_page_attrs(struct device *dev, struct page *page, size_t offset, size_t size, enum dma_data_direction dir, unsigned long attrs) @@ -149,7 +161,8 @@ dma_addr_t dma_map_page_attrs(struct device *dev, struct page *page, if (WARN_ON_ONCE(!dev->dma_mask)) return DMA_MAPPING_ERROR; - if (dma_map_direct(dev, ops)) + if (dma_map_direct(dev, ops) || + arch_dma_map_page_direct(dev, page_to_phys(page) + offset + size)) addr = dma_direct_map_page(dev, page, offset, size, dir, attrs); else addr = ops->map_page(dev, page, offset, size, dir, attrs); @@ -165,7 +178,8 @@ void dma_unmap_page_attrs(struct device *dev, dma_addr_t addr, size_t size, const struct dma_map_ops *ops = get_dma_ops(dev); BUG_ON(!valid_dma_direction(dir)); - if (dma_map_direct(dev, ops)) + if (dma_map_direct(dev, ops) || + arch_dma_unmap_page_direct(dev, addr + size)) dma_direct_unmap_page(dev, addr, size, dir, attrs); else if (ops->unmap_page) ops->unmap_page(dev, addr, size, dir, attrs); @@ -188,7 +202,8 @@ int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, int nents, if (WARN_ON_ONCE(!dev->dma_mask)) return 0; - if (dma_map_direct(dev, ops)) + if (dma_map_direct(dev, ops) || + arch_dma_map_sg_direct(dev, sg, nents)) ents = dma_direct_map_sg(dev, sg, nents, dir, attrs); else ents = ops->map_sg(dev, sg, nents, dir, attrs); @@ -207,7 +222,8 @@ void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, BUG_ON(!valid_dma_direction(dir)); debug_dma_unmap_sg(dev, sg, nents, dir); - if (dma_map_direct(dev, ops)) + if (dma_map_direct(dev, ops) || + arch_dma_unmap_sg_direct(dev, sg, nents)) dma_direct_unmap_sg(dev, sg, nents, dir, attrs); else if (ops->unmap_sg) ops->unmap_sg(dev, sg, nents, dir, attrs); diff --git a/kernel/dma/Kconfig b/kernel/dma/Kconfig index c99de4a21458..43d106598e82 100644 --- a/kernel/dma/Kconfig +++ b/kernel/dma/Kconfig @@ -20,6 +20,10 @@ config DMA_OPS config DMA_OPS_BYPASS bool +# Lets platform IOMMU driver choose between bypass and IOMMU +config ARCH_HAS_DMA_MAP_DIRECT + bool + config NEED_SG_DMA_LENGTH bool -- 2.17.1