From patchwork Sun Nov 10 13:46:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13869827 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 B5670D6409B for ; Sun, 10 Nov 2024 13:47:42 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 444976B0092; Sun, 10 Nov 2024 08:47:42 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 3CE646B0093; Sun, 10 Nov 2024 08:47:42 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 220A46B0096; Sun, 10 Nov 2024 08:47:42 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id F1EE36B0092 for ; Sun, 10 Nov 2024 08:47:41 -0500 (EST) Received: from smtpin26.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay07.hostedemail.com (Postfix) with ESMTP id 7DD5016125D for ; Sun, 10 Nov 2024 13:47:41 +0000 (UTC) X-FDA: 82770311904.26.3EC8BA3 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf22.hostedemail.com (Postfix) with ESMTP id EE83AC000D for ; Sun, 10 Nov 2024 13:46:50 +0000 (UTC) Authentication-Results: imf22.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=BKSoimGD; spf=pass (imf22.hostedemail.com: domain of leon@kernel.org designates 139.178.84.217 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=1731246269; 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=X/p9lF0JgZac8OtJRRR5sWEE536H+ASNZKb44rUtAK8=; b=frUvpSTYrSfwWdc3fDBJZRp20TDnNvT4Qvi4R3rsccN4TxomDPG6uKVjWQPSRUlpsmWWUI LDME6WavjRLD8l8ExfFKwEQODy2iRkSkO2r3NosbDB1SWKmrnAgbBXp0+IHuhLkDgJmrVD kWyHzXJ2m3n5AB81iOQy+u2fHV6H+6w= ARC-Authentication-Results: i=1; imf22.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=BKSoimGD; spf=pass (imf22.hostedemail.com: domain of leon@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=leon@kernel.org; dmarc=pass (policy=quarantine) header.from=kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1731246269; a=rsa-sha256; cv=none; b=uVLJD9/gSd6+DLnRrb7En3TPP5dz6vzBxlXBBIXkYd6jDNTnAeTqW/nLHPu+OYGd36gkA0 XrDL4+4iNusNpsN6Z3dkJzh+nKUv1YXhYvNeqYz/jW8Ansa4c1WUBtcep+YuskvYzEsms9 FbXfNk97JMdp+CMUJiI8s/GGnXjhiQw= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 864E25C5620; Sun, 10 Nov 2024 13:46:54 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4C561C4CEE3; Sun, 10 Nov 2024 13:47:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1731246458; bh=kaaNm90pDGFtHWSKL1yQ8jnPuKnBeiUpEsxBGDfH5mU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BKSoimGD3YPBt06x6rU7d3cP2xA+cI28F5UVz43amUZsAUgCgm0GkH+jGQQgKM34B RN5FKivVWOPFL+t13B++Wc8TWImmkCPQunBGZ6Mw61phoPUwXOsu9ufld/Ie6Nb0bp EmvoIztAjk2Dif5h4YJTgoA5mj92wqahWOO8d1ImYz1lXGqF4gM+tW+VDW52dP8LQ+ oRjYv3/BrooUhiyGj8mGf9AV0vH3kO/hbn6cz0RCYhHBHJOBEo0AcYz/F5r8AOhMd1 vCVpIcFe2geUoTdhT7hjH0VPW4XkfLNbOCuKV78WyhHbrakUOK37qO/qGFYPE6x4d6 pqbc/+gaenPng== 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, Randy Dunlap Subject: [PATCH v3 05/17] dma: Provide an interface to allow allocate IOVA Date: Sun, 10 Nov 2024 15:46:52 +0200 Message-ID: X-Mailer: git-send-email 2.47.0 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Server: rspam07 X-Rspamd-Queue-Id: EE83AC000D X-Stat-Signature: o8q9gerrxton5z7pdcpmarhuiruppbig X-Rspam-User: X-HE-Tag: 1731246410-607678 X-HE-Meta: U2FsdGVkX1+Mv76NMfCWXNmDb7qK4gMPa8mUuE9lLLP6GZCCywbRzkIrCS+FBNtpHvBrbwtoNZo34CYMMWyy3At+FdWsaEVs69qJ+2iGH6tFSmzbfiCZsEnLYTA+/2FFgAi+Az4QYHEqyPtalUB2AnzM1ehcxdWrJoD+wkKqaJ9d/1bXK1l2OegUCO0Uwj4OhjUX9QXtcqcfzB0lvdhQtqvxW2TzJDcHctM7ngjfFhS6nH62vaNkGSTWoXeA4OFM02apArXjuDtG7cJZ4y0nt4AWq4mR6WqB4qKo1p7a3Pn/og5ueZlD+Y9eXnoyw2HUAyXH7Sxg+iJZklg76aM1s2Av0P7nrzhgZofc5s/wsFUhC1gj5aiROftKqtI8zYjFUErWxH56FzzuXVhpi8AHUCeqvd6qjQYebcJaAhBzcZJnAbp++Z7pU8A4pqbsyRx6buCaMNjzUqfrIg6na2hbdoPtFxxWa8N8O6lACh2w6hi+rhlnN3CyCSWP9KeGKkTdfRZG+oHUZd5uHm/uaW2YD29EyGzEedJeFkL35f0sAj3OJMS27o2KLiBgfXqkGlX2m3wvnN4PSXJoS+CfINgNUFXcrV1kgg6h6ttCGJDNNC7ia5E7+w1NDFbU5oRbxnv1CuuCJ7AGqW4Q02IanklzQuKUVBUuJku9m0qrv+hJn4PizJqzRH6aE7oR0GFwi1ChgMvmecvLae80shgu3AWPE5SW3+ZiMFcZrXIoqxbW/NnLpafEzUqJNnzKZPIE5dpLzVTf+XwENxR5YS6BiPN1AwandUDM6P9TAszofssiMBrya4u/vrjQhvGLbvg7GX0LzQLv3JMyeqmo68+nNF4uRuAt86IotohFWPp5Agv4mgn5RnUsUHsjiiJGA3Mcg2dYZVZKHn5nIMQuFXbO8FSNPhCuai0HBRix6chdJ8UhtpNVLEPNtvAMeLeQcJtLjC/rAtdiDngL22wvJ1R1s+R w5iQObMl 2YVXvYMGjkJIjngLs3ueOOb1l1G16HesjiQomf2V8T2b5P4uYcKdxirpX9VBpUOoAwInbXGliI+ZE7fpFbvCZksmNh+goV1xVpAmmSGzlNUGt1ZF8zwL4CJP9E6iYU6jjCDBp9aK907P/1OtDhLEurUg9Ncukhpb01d6Ckgm3PEhFOgAlHyZ2bGaFJvGU0xJ6wMbpzt4IoqNZ+wsT+WroXV6uGUCiUia2Kgdyd81iZk2uFzcP/fR++6pY9We+9EI11+Mc9zID1NBL0s2hJJi9Ns2bo26dIfMqUzb3nvZpyDm03ddyOkV6qCw2Y0kv7Oj2Un6O 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 853247c42f7d..127150f63c95 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -1746,6 +1746,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)