From patchwork Sun Oct 27 14:21:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13852561 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2AECBD13561 for ; Sun, 27 Oct 2024 14:22:12 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 992C36B00A1; Sun, 27 Oct 2024 10:22:11 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 942706B00A2; Sun, 27 Oct 2024 10:22:11 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 7E2D26B00A3; Sun, 27 Oct 2024 10:22:11 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0010.hostedemail.com [216.40.44.10]) by kanga.kvack.org (Postfix) with ESMTP id 572546B00A1 for ; Sun, 27 Oct 2024 10:22:11 -0400 (EDT) Received: from smtpin01.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id A34B7A1C27 for ; Sun, 27 Oct 2024 14:21:31 +0000 (UTC) X-FDA: 82719595770.01.8548AE8 Received: from nyc.source.kernel.org (nyc.source.kernel.org [147.75.193.91]) by imf06.hostedemail.com (Postfix) with ESMTP id AFCB3180013 for ; Sun, 27 Oct 2024 14:21:53 +0000 (UTC) Authentication-Results: imf06.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=vJ4SOP7g; spf=pass (imf06.hostedemail.com: domain of leon@kernel.org designates 147.75.193.91 as permitted sender) smtp.mailfrom=leon@kernel.org; dmarc=pass (policy=quarantine) header.from=kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1730038774; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=NDTPA/jhN45f72ExSB7FDz7Zdbv+u1YzP4KVh20yN9Y=; b=DDKoL3dCay4IgmHB8iAwsIYCQuwdb1StpEHEDjWzE2gEbDZV9uTBOPkQDNHTTS1v/SNPBO uTwdzPv3xibF00gDgzgADkRrUTR/PbPspiIObP5PhsZUemjia2ts2o6sZLQ6xzZ7SLfcd3 Cg/ol1GTys6zRIPFvkLSWwpcO6oKuT4= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1730038774; a=rsa-sha256; cv=none; b=TQkR4iMB/veq/RZGVmX6EN3JcWDT0cxsn1bj/M6dl7trRl1zV4rab8SeUP8YNcaRfcg7uK MgpyMlWkMKAeihwGnqcwl/4uh9GJVflMUuBg4PvAqppFLG5gkISsafNazfprH5tIrvI0bt 26HWwxQ0Qy3EwFgiJU31JmixUPMpQgs= ARC-Authentication-Results: i=1; imf06.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=vJ4SOP7g; spf=pass (imf06.hostedemail.com: domain of leon@kernel.org designates 147.75.193.91 as permitted sender) smtp.mailfrom=leon@kernel.org; dmarc=pass (policy=quarantine) header.from=kernel.org Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id D147AA403FF; Sun, 27 Oct 2024 14:20:12 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D842BC4CEC3; Sun, 27 Oct 2024 14:22:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1730038928; bh=obFrC/8mEpgTohWqbSf2NYuferMlyIrijdEaJsyBjag=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vJ4SOP7gvCOmSakM9GmH61r5dlq/Vh89T+kjFaLLN13hmZfQf1jhZ7VnJUvpO8RS4 Ot3h88WLGyBGodBhbgLFLO1oRjoH2dXt3/qea4ZIVujmyq7q3rs6aftzpdKbd7dkwe iOFz72QAKcFESW/zKQLGKVCBDj6ce/d2SSag7jvmvjfIppKDQf2PdUc3aVWYQaKjX9 Ef5ORwF0V0m4xYd8ZkrUAFuAiBSVYhj9uTpCNLQOiwkzTg1y7CbjTrKVVGc/9UVgW5 JRPQ3E00Lla8siHhJD3YV2HS3Up33U/zketrX8P/VXaRAoQEMFgZ6k1BDQvsGyfH2E tWdMh0n6h7Jkg== From: Leon Romanovsky To: Jens Axboe , Jason Gunthorpe , Robin Murphy , Joerg Roedel , Will Deacon , Christoph Hellwig , Sagi Grimberg Cc: Leon Romanovsky , Keith Busch , Bjorn Helgaas , Logan Gunthorpe , Yishai Hadas , Shameer Kolothum , Kevin Tian , Alex Williamson , Marek Szyprowski , =?utf-8?b?SsOpcsO0bWUgR2xpc3Nl?= , Andrew Morton , Jonathan Corbet , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-block@vger.kernel.org, linux-rdma@vger.kernel.org, iommu@lists.linux.dev, linux-nvme@lists.infradead.org, linux-pci@vger.kernel.org, kvm@vger.kernel.org, linux-mm@kvack.org Subject: [PATCH 05/18] dma: Provide an interface to allow allocate IOVA Date: Sun, 27 Oct 2024 16:21:05 +0200 Message-ID: <844f3dcf9c341b8178bfbc90909ef13d11dd2193.1730037276.git.leon@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Queue-Id: AFCB3180013 X-Stat-Signature: 7yr9k3ufg8znhhxt8qjrwx8fa8rik67u X-Rspamd-Server: rspam09 X-Rspam-User: X-HE-Tag: 1730038913-830024 X-HE-Meta: U2FsdGVkX18syC5mjwebFn6dJklzeGoq+wFMBoGLrKxDyR5YGFKCaDZP+KYpw8Px7b+pm/T2phkltMx0YcfzsHIuEulhLXtOFohhI1w10kWCs3ktrpgH6TLkuuTneERcSdIhu9T/ZkIhMYvIBOfkaVkWR2tD+NDNdNPuOmWKO+07zDuhlQQtZwiwwEVmWqI16cnIPkosMJWwcbQVRXPBO1yDBHgbFHf6+7/MCb4zy3ZLQSR6WSrIdgpM3iuLJrk0fcVCx035EmHR3Elnn+472NzbRXqWXZZ3gB/eoUu4LWp7TJ5i1b1KA4BZplET3NjctoKlExWR1CS7uN4s41WviUYsZD0Pdju8GKyTUVGF/LvEmDGLTSP7gXRX5cQdEz8qNKBZKAa7rKlfdWnPcfdlhXfYsicx7lqftlM5i30XfH1eG2mpS08PVvIrzyCd4/H1oF7ObacQxKCLpTGpAxzl+addmQXkwoYA+Ba+QlRtOevYwPOR3t3xJM1s+inw/BflURajZJ52Lcy7spM9dgC0OOkTgH9+C9OEtGYPFX+Melzl3k4hSKeOYiQ0YuULlm9IqVDG3meuxNd/Js3lpH5kk8+fcqWuBy3nJFnA0foioeIEp3WKZoF/cN5HJ+xXz0+EqMGsYHsg9fz83XNhoMMAkdZo0jW9s1zHkqxFPKdpR+gPAvg0QvKDFRA1rIf7R+ZP4/JKXAVcPTt8CCAmqxCPbQhbeJDyw+AU1tXus0VX/wa5LQySk1XU0kN1W9/u+Cwfyelo2DIe38m8OYc4Kj0VkCv+eaij7hpOhB4GpjtU6SvGuzWAHQDEIhswTDZrbiYtBebatKAg8Ru/OzEMfATc7DERedgvRCwhllnkgFt0GNV1KqVeFfgiF/4Enf3PSVmhIwQVs317lN91U7wRAvvNUF+r5pALbJZylzvhfcGndH8LM/kRGtlGraAsaLvnA0RGIW6n1ZnwciwaFG3/iN8 9C935wXN MZisJvvKaWPA5K3YQss021wx8ZLVsXDQKmWcFHCYZLcrhuuBHZxhzOgJ1b9BqODYU37XLTvv+Kjxtifnxumj+7fPnWd9f3xT5wuwYlYSSqO34EUa/TMXDNi1itZkz/2MHado0qY8hcmN2hNOFUhVJdZM2Kh1lbu0NVPc62CZBwgb2OrE3zXu31hps8NYSej202edxr8NAxTIjmmVgpAtV6sQGdNo/99PYpxUuNkg81HZV1V0= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: From: Leon Romanovsky The existing .map_page() callback provides both allocating of IOVA and linking DMA pages. That combination works great for most of the callers who use it in control paths, but is less effective in fast paths where there may be multiple calls to map_page(). These advanced callers already manage their data in some sort of database and can perform IOVA allocation in advance, leaving range linkage operation to be in fast path. Provide an interface to allocate/deallocate IOVA and next patch link/unlink DMA ranges to that specific IOVA. The API is exported from dma-iommu as it is the only implementation supported, the namespace is clearly different from iommu_* functions which are not allowed to be used. This code layout allows us to save function call per API call used in datapath as well as a lot of boilerplate code. Signed-off-by: Leon Romanovsky --- drivers/iommu/dma-iommu.c | 79 +++++++++++++++++++++++++++++++++++++ include/linux/dma-mapping.h | 15 +++++++ 2 files changed, 94 insertions(+) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index c422e36c0d66..0644152c5aad 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -1745,6 +1745,85 @@ size_t iommu_dma_max_mapping_size(struct device *dev) return SIZE_MAX; } +static bool iommu_dma_iova_alloc(struct device *dev, + struct dma_iova_state *state, phys_addr_t phys, size_t size) +{ + struct iommu_domain *domain = iommu_get_dma_domain(dev); + struct iommu_dma_cookie *cookie = domain->iova_cookie; + struct iova_domain *iovad = &cookie->iovad; + size_t iova_off = iova_offset(iovad, phys); + dma_addr_t addr; + + if (WARN_ON_ONCE(!size)) + return false; + if (WARN_ON_ONCE(size & DMA_IOVA_USE_SWIOTLB)) + return false; + + addr = iommu_dma_alloc_iova(domain, + iova_align(iovad, size + iova_off), + dma_get_mask(dev), dev); + if (!addr) + return false; + + state->addr = addr + iova_off; + state->__size = size; + return true; +} + +/** + * dma_iova_try_alloc - Try to allocate an IOVA space + * @dev: Device to allocate the IOVA space for + * @state: IOVA state + * @phys: physical address + * @size: IOVA size + * + * Check if @dev supports the IOVA-based DMA API, and if yes allocate IOVA space + * for the given base address and size. + * + * Note: @phys is only used to calculate the IOVA alignment. Callers that always + * do PAGE_SIZE aligned transfers can safely pass 0 here. + * + * Returns %true if the IOVA-based DMA API can be used and IOVA space has been + * allocated, or %false if the regular DMA API should be used. + */ +bool dma_iova_try_alloc(struct device *dev, struct dma_iova_state *state, + phys_addr_t phys, size_t size) +{ + memset(state, 0, sizeof(*state)); + if (!use_dma_iommu(dev)) + return false; + if (static_branch_unlikely(&iommu_deferred_attach_enabled) && + iommu_deferred_attach(dev, iommu_get_domain_for_dev(dev))) + return false; + return iommu_dma_iova_alloc(dev, state, phys, size); +} +EXPORT_SYMBOL_GPL(dma_iova_try_alloc); + +/** + * dma_iova_free - Free an IOVA space + * @dev: Device to free the IOVA space for + * @state: IOVA state + * + * Undoes a successful dma_try_iova_alloc(). + * + * Note that all dma_iova_link() calls need to be undone first. For callers + * that never call dma_iova_unlink(), dma_iova_destroy() can be used instead + * which unlinks all ranges and frees the IOVA space in a single efficient + * operation. + */ +void dma_iova_free(struct device *dev, struct dma_iova_state *state) +{ + struct iommu_domain *domain = iommu_get_dma_domain(dev); + struct iommu_dma_cookie *cookie = domain->iova_cookie; + struct iova_domain *iovad = &cookie->iovad; + size_t iova_start_pad = iova_offset(iovad, state->addr); + size_t size = dma_iova_size(state); + + iommu_dma_free_iova(cookie, state->addr - iova_start_pad, + iova_align(iovad, size + iova_start_pad), NULL); +} +EXPORT_SYMBOL_GPL(dma_iova_free); + void iommu_setup_dma_ops(struct device *dev) { struct iommu_domain *domain = iommu_get_domain_for_dev(dev); diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 6075e0708deb..817f11bce7bc 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -11,6 +11,7 @@ #include #include #include +#include /** * List of possible attributes associated with a DMA mapping. The semantics @@ -77,6 +78,7 @@ #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) struct dma_iova_state { + dma_addr_t addr; size_t __size; }; @@ -307,11 +309,24 @@ static inline bool dma_use_iova(struct dma_iova_state *state) { return state->__size != 0; } + +bool dma_iova_try_alloc(struct device *dev, struct dma_iova_state *state, + phys_addr_t phys, size_t size); +void dma_iova_free(struct device *dev, struct dma_iova_state *state); #else /* CONFIG_IOMMU_DMA */ static inline bool dma_use_iova(struct dma_iova_state *state) { return false; } +static inline bool dma_iova_try_alloc(struct device *dev, + struct dma_iova_state *state, phys_addr_t phys, size_t size) +{ + return false; +} +static inline void dma_iova_free(struct device *dev, + struct dma_iova_state *state) +{ +} #endif /* CONFIG_IOMMU_DMA */ #if defined(CONFIG_HAS_DMA) && defined(CONFIG_DMA_NEED_SYNC)