From patchwork Wed Feb 5 14:40:21 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961180 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 98066C02192 for ; Wed, 5 Feb 2025 14:41:07 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 124EC6B009A; Wed, 5 Feb 2025 09:41:07 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 0AE4B6B009B; Wed, 5 Feb 2025 09:41:07 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id E8FE86B009C; Wed, 5 Feb 2025 09:41:06 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id C6D616B009A for ; Wed, 5 Feb 2025 09:41:06 -0500 (EST) Received: from smtpin15.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay05.hostedemail.com (Postfix) with ESMTP id 405AF47F2C for ; Wed, 5 Feb 2025 14:41:06 +0000 (UTC) X-FDA: 83086153332.15.4C85770 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf12.hostedemail.com (Postfix) with ESMTP id 7BA6040011 for ; Wed, 5 Feb 2025 14:41:02 +0000 (UTC) Authentication-Results: imf12.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=lsRVB81D; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf12.hostedemail.com: domain of leon@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=leon@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738766462; a=rsa-sha256; cv=none; b=5h5/X+Moc2j+r4pFC0aLvjSB1culdTkx8UJpQR+YXdXafPSCrANT0/S103+qOnyUW9/TRB bONGmV6dtmorv9qRjD+uGlOsxAr2XnzSn/dDzPNYkAfcCKLFdug27JJVaMHASE8FH+vT5d /4g35CmlWwnh0LHAY3F26VeI0WESXIA= ARC-Authentication-Results: i=1; imf12.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=lsRVB81D; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf12.hostedemail.com: domain of leon@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=leon@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1738766462; 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=MRp7iV5WXUscLEHX65zZS8/q7rhvh7CeQJlSv0rwwV8=; b=XKOr8QcUYj2VcZsECWWDuZynX0iUopDhH820yTrRADY/0nTi+Qs08QdUmxZYU6KY8X7X4E LZWMPOBqSDQ9UiXMWvKDmv7NukEVjBBs5sTKhfkQCzeC+xQeBk2mc9Efpu+0NEuEsA9klj 25KEbIHOygJkzx71luUpIcGKcIEJk3I= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id D709B5C6551; Wed, 5 Feb 2025 14:40:20 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id BCA3CC4CEE2; Wed, 5 Feb 2025 14:40:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766460; bh=igiSat1dX5JpZ8Rk07V+4SozwrjyZTKwu3DZB8pCubA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lsRVB81DG/IRLq7pr5O0mHOSgO71WvvN987DhEny1Mr86py5YJFjuCPdxtMmQ1Byp LnfElstV/vT6MG/HV5nhWWK9iCICb3nC1H8xpRSjnp7EHNGKrSlI/Bi1et3YMLZVCM vneeeWvBsKi9yzYQtRa2Tw37IMKnoc4Vk0oRpsOYmj5PTCaNYdGIyHPKfwAMQkQxPE hdJVJLUG1FZQSEMIKVS749LysjkJ9Nut+dFRZCJVNlzwtPULiIRAqcSUy24PbQtgQn SlwpN72RLz06MuemWdVhHGPMnve9HM49yhNRXDG9M2XMsL4vxPyEW6zDMNy3Z7c8Lv zEANkD7Y4LSLg== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 01/17] PCI/P2PDMA: Refactor the p2pdma mapping helpers Date: Wed, 5 Feb 2025 16:40:21 +0200 Message-ID: <9a0176593a8777fb0b3e5b1e97c4ae4c8fa22626.1738765879.git.leonro@nvidia.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Server: rspam04 X-Rspamd-Queue-Id: 7BA6040011 X-Stat-Signature: wz1asp71gdemdzspp9ecscipbat94wf5 X-Rspam-User: X-HE-Tag: 1738766462-157256 X-HE-Meta: U2FsdGVkX1+gkM9sRxfEh8QBsS9Urhyy38hu0YCi8+LiXoGtgFl1I1v3zVlGPVk+rh4wtfdez3tFCtQ+Y3yRKppM2Q9PCA9PYEds84YgUe5I6fqoX1ePknaqhUR+iyMKHwYxxZrM5bjvvH+2A7lyBTKurGRK26TS4w4rnSvx3sQEXU06Ml/HPmrILqvxcdDDNThTSYKAxMuM8mic2T7pD4e7JlQFOHlYwLCFXMauhKDRQhZVNvG01SZozKPQnRzjFxvjorFANm+exgx8S5Y2kHe6LJNKCzsvSlM6TohSwjvmVnMz3zZNJluF7B0BJsafZr41inASqiQxG1U6+XV2HVeekl+edONXf9v//xl3gLwml9JMXipNohJcS8VrDJVSNF2oEPMAXwDn5Gim6rbJbWJ+01w3Uga7s4asy2SIh9Fnt+b0qBBfJLGlg4QK/gjGSxn94EIfv0/KrT+F9WeOWdtSedrDrSCpMqkdXbh9/TDA2a1gKLAj5wmNe7DO/6SgbMkc8HFhRTIR7B2HVpN9eGATYRah2M2N/C6QP41omUe5Fuh+zhN7RD9pUN7GJZHIKLaCktain6Y9VXZP5Ahwj0nKPHgT38c/AF8DaRmJWLFTL23GpmNcknC+eisSp+wLFWTRfHjsTj7PMk0I21Q6J47D3a8rSRWKUvoGg2vvEvr2I4JoTM1SfmO0JDYRUJpNF4Cx/zKvNOGkHgRvMUFrnJ5apNGWNOCVt4uyRqQmX8V25fGlh8Yv9jmApWLYa1lJ9wGkCzyMHMN7K8UEwuFuEj7yZW210d8Nk5AfvvpsjWIIJAB9lufS/w7W0Dp+FykUC796q5Hy7rsoA1niNsyiHNOKbARcIAS/9moTBQu6Cbd6ZbxRnPU2XxBXqp2e20zhVwaRfWmBxqFD3elk++27O6SNjLCnN3miPexwLPokaN6ycBJ8+Fm/UNkPjNSVesN6NjWJCZQMZDraRuAVR2p kb0upuwz 4w6yWEZ5J44dFNHiHKapJEiNgb1QqjLm/pSfpJjbdlnwCZkrpcggV33ZGn+1ukWd7LMsd1bHvOGtmQS5/xgyI8CFRUZa0OofUI7/gceTWZCxGiF97LN2LHVgI677nEuu+D7GhZ8vHQmJd93RH7CfL0aSAIThqXWxYasfBtcQ6uPnTXi/nNWawVP7nSxVstD/5CWZLhnu6dV65MgQcT0SJEjVw2R+FCpx/XoOFVsXkGDrSVUlzyhxsvvAOtgVchacAHtL27EJo2S1Tk5SvUt9jauYESQ== 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: Christoph Hellwig The current scheme with a single helper to determine the P2P status and map a scatterlist segment force users to always use the map_sg helper to DMA map, which we're trying to get away from because they are very cache inefficient. Refactor the code so that there is a single helper that checks the P2P state for a page, including the result that it is not a P2P page to simplify the callers, and a second one to perform the address translation for a bus mapped P2P transfer that does not depend on the scatterlist structure. Signed-off-by: Christoph Hellwig Reviewed-by: Logan Gunthorpe Acked-by: Bjorn Helgaas Signed-off-by: Leon Romanovsky --- drivers/iommu/dma-iommu.c | 47 +++++++++++++++++----------------- drivers/pci/p2pdma.c | 38 ++++----------------------- include/linux/dma-map-ops.h | 51 +++++++++++++++++++++++++++++-------- kernel/dma/direct.c | 43 +++++++++++++++---------------- 4 files changed, 91 insertions(+), 88 deletions(-) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 2a9fa0c8cc00..5746ffaf0061 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -1382,7 +1382,6 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, struct scatterlist *s, *prev = NULL; int prot = dma_info_to_prot(dir, dev_is_dma_coherent(dev), attrs); struct pci_p2pdma_map_state p2pdma_state = {}; - enum pci_p2pdma_map_type map; dma_addr_t iova; size_t iova_len = 0; unsigned long mask = dma_get_seg_boundary(dev); @@ -1412,28 +1411,30 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, size_t s_length = s->length; size_t pad_len = (mask - iova_len + 1) & mask; - if (is_pci_p2pdma_page(sg_page(s))) { - map = pci_p2pdma_map_segment(&p2pdma_state, dev, s); - switch (map) { - case PCI_P2PDMA_MAP_BUS_ADDR: - /* - * iommu_map_sg() will skip this segment as - * it is marked as a bus address, - * __finalise_sg() will copy the dma address - * into the output segment. - */ - continue; - case PCI_P2PDMA_MAP_THRU_HOST_BRIDGE: - /* - * Mapping through host bridge should be - * mapped with regular IOVAs, thus we - * do nothing here and continue below. - */ - break; - default: - ret = -EREMOTEIO; - goto out_restore_sg; - } + switch (pci_p2pdma_state(&p2pdma_state, dev, sg_page(s))) { + case PCI_P2PDMA_MAP_THRU_HOST_BRIDGE: + /* + * Mapping through host bridge should be mapped with + * regular IOVAs, thus we do nothing here and continue + * below. + */ + break; + case PCI_P2PDMA_MAP_NONE: + break; + case PCI_P2PDMA_MAP_BUS_ADDR: + /* + * iommu_map_sg() will skip this segment as it is marked + * as a bus address, __finalise_sg() will copy the dma + * address into the output segment. + */ + s->dma_address = pci_p2pdma_bus_addr_map(&p2pdma_state, + sg_phys(s)); + sg_dma_len(s) = sg->length; + sg_dma_mark_bus_address(s); + continue; + default: + ret = -EREMOTEIO; + goto out_restore_sg; } sg_dma_address(s) = s_iova_off; diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c index 0cb7e0aaba0e..31c6e6e4a950 100644 --- a/drivers/pci/p2pdma.c +++ b/drivers/pci/p2pdma.c @@ -995,40 +995,12 @@ static enum pci_p2pdma_map_type pci_p2pdma_map_type(struct dev_pagemap *pgmap, return type; } -/** - * pci_p2pdma_map_segment - map an sg segment determining the mapping type - * @state: State structure that should be declared outside of the for_each_sg() - * loop and initialized to zero. - * @dev: DMA device that's doing the mapping operation - * @sg: scatterlist segment to map - * - * This is a helper to be used by non-IOMMU dma_map_sg() implementations where - * the sg segment is the same for the page_link and the dma_address. - * - * Attempt to map a single segment in an SGL with the PCI bus address. - * The segment must point to a PCI P2PDMA page and thus must be - * wrapped in a is_pci_p2pdma_page(sg_page(sg)) check. - * - * Returns the type of mapping used and maps the page if the type is - * PCI_P2PDMA_MAP_BUS_ADDR. - */ -enum pci_p2pdma_map_type -pci_p2pdma_map_segment(struct pci_p2pdma_map_state *state, struct device *dev, - struct scatterlist *sg) +void __pci_p2pdma_update_state(struct pci_p2pdma_map_state *state, + struct device *dev, struct page *page) { - if (state->pgmap != sg_page(sg)->pgmap) { - state->pgmap = sg_page(sg)->pgmap; - state->map = pci_p2pdma_map_type(state->pgmap, dev); - state->bus_off = to_p2p_pgmap(state->pgmap)->bus_offset; - } - - if (state->map == PCI_P2PDMA_MAP_BUS_ADDR) { - sg->dma_address = sg_phys(sg) + state->bus_off; - sg_dma_len(sg) = sg->length; - sg_dma_mark_bus_address(sg); - } - - return state->map; + state->pgmap = page->pgmap; + state->map = pci_p2pdma_map_type(state->pgmap, dev); + state->bus_off = to_p2p_pgmap(state->pgmap)->bus_offset; } /** diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h index e172522cd936..63dd480e209b 100644 --- a/include/linux/dma-map-ops.h +++ b/include/linux/dma-map-ops.h @@ -443,6 +443,11 @@ enum pci_p2pdma_map_type { */ PCI_P2PDMA_MAP_UNKNOWN = 0, + /* + * Not a PCI P2PDMA transfer. + */ + PCI_P2PDMA_MAP_NONE, + /* * PCI_P2PDMA_MAP_NOT_SUPPORTED: Indicates the transaction will * traverse the host bridge and the host bridge is not in the @@ -471,21 +476,47 @@ enum pci_p2pdma_map_type { struct pci_p2pdma_map_state { struct dev_pagemap *pgmap; - int map; + enum pci_p2pdma_map_type map; u64 bus_off; }; -#ifdef CONFIG_PCI_P2PDMA -enum pci_p2pdma_map_type -pci_p2pdma_map_segment(struct pci_p2pdma_map_state *state, struct device *dev, - struct scatterlist *sg); -#else /* CONFIG_PCI_P2PDMA */ +/* helper for pci_p2pdma_state(), do not use directly */ +void __pci_p2pdma_update_state(struct pci_p2pdma_map_state *state, + struct device *dev, struct page *page); + +/** + * pci_p2pdma_state - check the P2P transfer state of a page + * @state: P2P state structure + * @dev: device to transfer to/from + * @page: page to map + * + * Check if @page is a PCI P2PDMA page, and if yes of what kind. Returns the + * map type, and updates @state with all information needed for a P2P transfer. + */ static inline enum pci_p2pdma_map_type -pci_p2pdma_map_segment(struct pci_p2pdma_map_state *state, struct device *dev, - struct scatterlist *sg) +pci_p2pdma_state(struct pci_p2pdma_map_state *state, struct device *dev, + struct page *page) +{ + if (IS_ENABLED(CONFIG_PCI_P2PDMA) && is_pci_p2pdma_page(page)) { + if (state->pgmap != page->pgmap) + __pci_p2pdma_update_state(state, dev, page); + return state->map; + } + return PCI_P2PDMA_MAP_NONE; +} + +/** + * pci_p2pdma_bus_addr_map - map a PCI_P2PDMA_MAP_BUS_ADDR P2P transfer + * @state: P2P state structure + * @paddr: physical address to map + * + * Map a physically contigous PCI_P2PDMA_MAP_BUS_ADDR transfer. + */ +static inline dma_addr_t +pci_p2pdma_bus_addr_map(struct pci_p2pdma_map_state *state, phys_addr_t paddr) { - return PCI_P2PDMA_MAP_NOT_SUPPORTED; + WARN_ON_ONCE(state->map != PCI_P2PDMA_MAP_BUS_ADDR); + return paddr + state->bus_off; } -#endif /* CONFIG_PCI_P2PDMA */ #endif /* _LINUX_DMA_MAP_OPS_H */ diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c index 5b4e6d3bf7bc..e289ad27d1b5 100644 --- a/kernel/dma/direct.c +++ b/kernel/dma/direct.c @@ -462,34 +462,33 @@ int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents, enum dma_data_direction dir, unsigned long attrs) { struct pci_p2pdma_map_state p2pdma_state = {}; - enum pci_p2pdma_map_type map; struct scatterlist *sg; int i, ret; for_each_sg(sgl, sg, nents, i) { - if (is_pci_p2pdma_page(sg_page(sg))) { - map = pci_p2pdma_map_segment(&p2pdma_state, dev, sg); - switch (map) { - case PCI_P2PDMA_MAP_BUS_ADDR: - continue; - case PCI_P2PDMA_MAP_THRU_HOST_BRIDGE: - /* - * Any P2P mapping that traverses the PCI - * host bridge must be mapped with CPU physical - * address and not PCI bus addresses. This is - * done with dma_direct_map_page() below. - */ - break; - default: - ret = -EREMOTEIO; + switch (pci_p2pdma_state(&p2pdma_state, dev, sg_page(sg))) { + case PCI_P2PDMA_MAP_THRU_HOST_BRIDGE: + /* + * Any P2P mapping that traverses the PCI host bridge + * must be mapped with CPU physical address and not PCI + * bus addresses. + */ + break; + case PCI_P2PDMA_MAP_NONE: + sg->dma_address = dma_direct_map_page(dev, sg_page(sg), + sg->offset, sg->length, dir, attrs); + if (sg->dma_address == DMA_MAPPING_ERROR) { + ret = -EIO; goto out_unmap; } - } - - sg->dma_address = dma_direct_map_page(dev, sg_page(sg), - sg->offset, sg->length, dir, attrs); - if (sg->dma_address == DMA_MAPPING_ERROR) { - ret = -EIO; + break; + case PCI_P2PDMA_MAP_BUS_ADDR: + sg->dma_address = pci_p2pdma_bus_addr_map(&p2pdma_state, + sg_phys(sg)); + sg_dma_mark_bus_address(sg); + continue; + default: + ret = -EREMOTEIO; goto out_unmap; } sg_dma_len(sg) = sg->length; From patchwork Wed Feb 5 14:40:22 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961184 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 01573C02192 for ; Wed, 5 Feb 2025 14:41:19 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 8A90A280001; Wed, 5 Feb 2025 09:41:19 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 829D8280002; Wed, 5 Feb 2025 09:41:19 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 6A4B5280001; Wed, 5 Feb 2025 09:41:19 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 448D36B00A2 for ; Wed, 5 Feb 2025 09:41:19 -0500 (EST) Received: from smtpin28.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay10.hostedemail.com (Postfix) with ESMTP id F2062C0D32 for ; Wed, 5 Feb 2025 14:41:18 +0000 (UTC) X-FDA: 83086153836.28.9F366BB Received: from nyc.source.kernel.org (nyc.source.kernel.org [147.75.193.91]) by imf28.hostedemail.com (Postfix) with ESMTP id 464FEC000F for ; Wed, 5 Feb 2025 14:41:16 +0000 (UTC) Authentication-Results: imf28.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b="M/ZWUKBV"; spf=pass (imf28.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=1738766476; 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=DYl4EnFYcCL1nWNRYMjMR1h4594qCjPEHt+OKKO2MdE=; b=P199Nn8GI5gVeda3Pvqt2jDF5F59Yqq3fumAC0gQQNg7nshZP8Yr6ASt1+nmZhxHmj7KK8 vbhEM67tH82eOlUEKBADKvOS2cf6bPlpsmxW2JvcGacNdT3QTySTrJmuui/V5kPhYwwRqx h2ApBCNMUgioitrqOvHdyJp9VKJcdmo= ARC-Authentication-Results: i=1; imf28.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b="M/ZWUKBV"; spf=pass (imf28.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-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738766476; a=rsa-sha256; cv=none; b=KMGx6+Qh+9AD1odl5r04C82M9vaYEoYipciV457gCcmZ4b5D6LDquTrfyuejsQjRjHW73e WMRypcs1+9D0ZFKwrXyiFFftXkOT5vbaSv/Xpp25QcCgMn0wltRi/PDoHYtzgVnXeaFZ2x +ypNextQLxcpGbW5jVOPQ19crmRXHxU= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 7BD28A436B2; Wed, 5 Feb 2025 14:39:29 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 68464C4CEE2; Wed, 5 Feb 2025 14:41:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766475; bh=rDd5+AEBVvFnWWvevLz/veAtXtu4dnJimBZ2rziLMe8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=M/ZWUKBV+oMEe/aoCuMSHpIgfKzXegQZjFdM5hqBD/+SkqOxNNzyqMOdd+0mTOUyT aOmrYap1v09OtkkimHsMZHiTVlEnVaTUrioW5LIalQKVX6KVa3hx5PuRyil8rrHK8l a6NXAH+Zxz3cZZOOMKK97ROS2Nqwimk0yfzsAtOHcfnbt6F18e9k54nZEurCSEJfbF +nGJSHlYegV/kXxcZh1gb7ss9qZUvVSyygtEXU1hKq0oBvW6Ly0SKdD+cBq1gwCEk0 9rW5DZE+RFdAGOF3rpxnenXvOLU0g6NpCWVYHFXh/RA5TM6u38bvvur2NpzKHn9J+T JHAIBp0mWBzhg== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 02/17] dma-mapping: move the PCI P2PDMA mapping helpers to pci-p2pdma.h Date: Wed, 5 Feb 2025 16:40:22 +0200 Message-ID: X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Queue-Id: 464FEC000F X-Rspam-User: X-Rspamd-Server: rspam11 X-Stat-Signature: ctw8c1hgpet9pjs8ta3h7h99h9xihim3 X-HE-Tag: 1738766476-383658 X-HE-Meta: U2FsdGVkX19ye1LtrK5l/wncJ82cMn86DLKU7wxCkLB17YAvvjIR7A+qD+8Hb/aaJt4moDt+6sYSGs5yUF13tQ8XPjZNuQh3Bb8IW6f/m6zloYE1kftKiUClePNjJ3gv9CPkIbrAJJm5w6iY+AoM9khkCe4o6XGz/gzkf0e2BsSL74wG1Ww9PxZ5Juc8IkkxGvoBhJNSl5CgE77cYy8Fh9orKsaniU1Qf6BAHUUK01wU2dLMfrhEhgt1wlS2ScMZwWzt5d1gwwCalgjisId859ld9ez1mepQgz0AN4r9mcYlOnQ4bPaFmHRrBunztmDwtJTkfhqQJd7WEaVuke9xgagLn2juJ2okXI0Ayx84dXQfOcNkrPfPz1jruCczsFWfsz5udTpD9zT0c0vPv7Fu5F31v10r1ssv+j1c8ZZydTMt+X5l/1vqnhvXdJBqEqnTZB2jFyNbGmXG37PJ4wT+Mtb9fDZQWeF1VAWKSDIha7DKwmWXIY4tiFqf+jlE5CZA5NcRFcc0XuC2TTDV566qC/Mnp8oZ/2ytiN5mZOSXr/TGvqdnrbEPzXWzk+5zKu8vkfugfNC8iWi86odXueKK6lyTiGIlF/4iw69ABlqXyvupCEHJ2TFw42aaRQTNHQ9bQtipNB3Z3G5tuOJKfMrYXK1+gJdr2y3/UX89l/9EyVPcbMBpnurZZK/mOJoSW+33Cv33Ik2DdfJHaVgh0zNRybb9sXYkDcrKcyzSpx2yzvd8HjqXGcIrrl/MIKMHmx0XUSD5Auyl7+JQ2pM3Nnyz6sEK+L/ut1hhBNvCZKIfXpgJZX8nLrhQdbunntjQ5o0IqvRBGkJU5B77w1Ib2zzC3+tzGqzKNNhzP11+svdTWOPzk1qzI9Mmks7pzdLlriHFyFzuETMb1cGk20WpVyzyyuAtuGgTbP2FeCsTJkbzEUj3AqVIv8fFKTeThpKgAXAWvwlDKbRWu7rJQto6SQk /Mmz34xU ZcpPQmhvFmJ4WP/8smZXgUc+ld1TGaGGTICGjzpckQnF9S84Q0/CY947mN5Ln+znbOcJcVEWLDz/FlRJclD79UFnySwUC4xb3h3ExtTTrLmw/nKoO+qQ9Pq03N+zJ/d+2UDtWNNKpv5CRbTRLXrmSw++Dd9tPDnYYQdJY41YI2bFfI+pNaXJayMzTxJt2FqnSEzpol9c8o7Z5jGKI8CKcRcCLd3Ig5SQaJKs5GvO7LVJKfwIC4Wq+UQibqnpeRnc3q9xx7/VPLXhUbx/qEs52VQxakw== 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: Christoph Hellwig To support the upcoming non-scatterlist mapping helpers, we need to go back to have them called outside of the DMA API. Thus move them out of dma-map-ops.h, which is only for DMA API implementations to pci-p2pdma.h, which is for driver use. Note that the core helper is still not exported as the mapping is expected to be done only by very highlevel subsystem code at least for now. Signed-off-by: Christoph Hellwig Reviewed-by: Logan Gunthorpe Acked-by: Bjorn Helgaas Signed-off-by: Leon Romanovsky --- drivers/iommu/dma-iommu.c | 1 + include/linux/dma-map-ops.h | 85 ------------------------------------- include/linux/pci-p2pdma.h | 84 ++++++++++++++++++++++++++++++++++++ kernel/dma/direct.c | 1 + 4 files changed, 86 insertions(+), 85 deletions(-) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 5746ffaf0061..853247c42f7d 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h index 63dd480e209b..f48e5fb88bd5 100644 --- a/include/linux/dma-map-ops.h +++ b/include/linux/dma-map-ops.h @@ -434,89 +434,4 @@ static inline void debug_dma_dump_mappings(struct device *dev) #endif /* CONFIG_DMA_API_DEBUG */ extern const struct dma_map_ops dma_dummy_ops; - -enum pci_p2pdma_map_type { - /* - * PCI_P2PDMA_MAP_UNKNOWN: Used internally for indicating the mapping - * type hasn't been calculated yet. Functions that return this enum - * never return this value. - */ - PCI_P2PDMA_MAP_UNKNOWN = 0, - - /* - * Not a PCI P2PDMA transfer. - */ - PCI_P2PDMA_MAP_NONE, - - /* - * PCI_P2PDMA_MAP_NOT_SUPPORTED: Indicates the transaction will - * traverse the host bridge and the host bridge is not in the - * allowlist. DMA Mapping routines should return an error when - * this is returned. - */ - PCI_P2PDMA_MAP_NOT_SUPPORTED, - - /* - * PCI_P2PDMA_BUS_ADDR: Indicates that two devices can talk to - * each other directly through a PCI switch and the transaction will - * not traverse the host bridge. Such a mapping should program - * the DMA engine with PCI bus addresses. - */ - PCI_P2PDMA_MAP_BUS_ADDR, - - /* - * PCI_P2PDMA_MAP_THRU_HOST_BRIDGE: Indicates two devices can talk - * to each other, but the transaction traverses a host bridge on the - * allowlist. In this case, a normal mapping either with CPU physical - * addresses (in the case of dma-direct) or IOVA addresses (in the - * case of IOMMUs) should be used to program the DMA engine. - */ - PCI_P2PDMA_MAP_THRU_HOST_BRIDGE, -}; - -struct pci_p2pdma_map_state { - struct dev_pagemap *pgmap; - enum pci_p2pdma_map_type map; - u64 bus_off; -}; - -/* helper for pci_p2pdma_state(), do not use directly */ -void __pci_p2pdma_update_state(struct pci_p2pdma_map_state *state, - struct device *dev, struct page *page); - -/** - * pci_p2pdma_state - check the P2P transfer state of a page - * @state: P2P state structure - * @dev: device to transfer to/from - * @page: page to map - * - * Check if @page is a PCI P2PDMA page, and if yes of what kind. Returns the - * map type, and updates @state with all information needed for a P2P transfer. - */ -static inline enum pci_p2pdma_map_type -pci_p2pdma_state(struct pci_p2pdma_map_state *state, struct device *dev, - struct page *page) -{ - if (IS_ENABLED(CONFIG_PCI_P2PDMA) && is_pci_p2pdma_page(page)) { - if (state->pgmap != page->pgmap) - __pci_p2pdma_update_state(state, dev, page); - return state->map; - } - return PCI_P2PDMA_MAP_NONE; -} - -/** - * pci_p2pdma_bus_addr_map - map a PCI_P2PDMA_MAP_BUS_ADDR P2P transfer - * @state: P2P state structure - * @paddr: physical address to map - * - * Map a physically contigous PCI_P2PDMA_MAP_BUS_ADDR transfer. - */ -static inline dma_addr_t -pci_p2pdma_bus_addr_map(struct pci_p2pdma_map_state *state, phys_addr_t paddr) -{ - WARN_ON_ONCE(state->map != PCI_P2PDMA_MAP_BUS_ADDR); - return paddr + state->bus_off; -} - #endif /* _LINUX_DMA_MAP_OPS_H */ diff --git a/include/linux/pci-p2pdma.h b/include/linux/pci-p2pdma.h index 2c07aa6b7665..e839f52b512b 100644 --- a/include/linux/pci-p2pdma.h +++ b/include/linux/pci-p2pdma.h @@ -104,4 +104,88 @@ static inline struct pci_dev *pci_p2pmem_find(struct device *client) return pci_p2pmem_find_many(&client, 1); } +enum pci_p2pdma_map_type { + /* + * PCI_P2PDMA_MAP_UNKNOWN: Used internally for indicating the mapping + * type hasn't been calculated yet. Functions that return this enum + * never return this value. + */ + PCI_P2PDMA_MAP_UNKNOWN = 0, + + /* + * Not a PCI P2PDMA transfer. + */ + PCI_P2PDMA_MAP_NONE, + + /* + * PCI_P2PDMA_MAP_NOT_SUPPORTED: Indicates the transaction will + * traverse the host bridge and the host bridge is not in the + * allowlist. DMA Mapping routines should return an error when + * this is returned. + */ + PCI_P2PDMA_MAP_NOT_SUPPORTED, + + /* + * PCI_P2PDMA_BUS_ADDR: Indicates that two devices can talk to + * each other directly through a PCI switch and the transaction will + * not traverse the host bridge. Such a mapping should program + * the DMA engine with PCI bus addresses. + */ + PCI_P2PDMA_MAP_BUS_ADDR, + + /* + * PCI_P2PDMA_MAP_THRU_HOST_BRIDGE: Indicates two devices can talk + * to each other, but the transaction traverses a host bridge on the + * allowlist. In this case, a normal mapping either with CPU physical + * addresses (in the case of dma-direct) or IOVA addresses (in the + * case of IOMMUs) should be used to program the DMA engine. + */ + PCI_P2PDMA_MAP_THRU_HOST_BRIDGE, +}; + +struct pci_p2pdma_map_state { + struct dev_pagemap *pgmap; + enum pci_p2pdma_map_type map; + u64 bus_off; +}; + +/* helper for pci_p2pdma_state(), do not use directly */ +void __pci_p2pdma_update_state(struct pci_p2pdma_map_state *state, + struct device *dev, struct page *page); + +/** + * pci_p2pdma_state - check the P2P transfer state of a page + * @state: P2P state structure + * @dev: device to transfer to/from + * @page: page to map + * + * Check if @page is a PCI P2PDMA page, and if yes of what kind. Returns the + * map type, and updates @state with all information needed for a P2P transfer. + */ +static inline enum pci_p2pdma_map_type +pci_p2pdma_state(struct pci_p2pdma_map_state *state, struct device *dev, + struct page *page) +{ + if (IS_ENABLED(CONFIG_PCI_P2PDMA) && is_pci_p2pdma_page(page)) { + if (state->pgmap != page->pgmap) + __pci_p2pdma_update_state(state, dev, page); + return state->map; + } + return PCI_P2PDMA_MAP_NONE; +} + +/** + * pci_p2pdma_bus_addr_map - map a PCI_P2PDMA_MAP_BUS_ADDR P2P transfer + * @state: P2P state structure + * @paddr: physical address to map + * + * Map a physically contigous PCI_P2PDMA_MAP_BUS_ADDR transfer. + */ +static inline dma_addr_t +pci_p2pdma_bus_addr_map(struct pci_p2pdma_map_state *state, phys_addr_t paddr) +{ + WARN_ON_ONCE(state->map != PCI_P2PDMA_MAP_BUS_ADDR); + return paddr + state->bus_off; +} + #endif /* _LINUX_PCI_P2P_H */ diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c index e289ad27d1b5..c9b3893257d4 100644 --- a/kernel/dma/direct.c +++ b/kernel/dma/direct.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "direct.h" /* From patchwork Wed Feb 5 14:40:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961181 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 A17D0C02198 for ; Wed, 5 Feb 2025 14:41:08 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 7B59E6B009B; Wed, 5 Feb 2025 09:41:07 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 764426B009C; Wed, 5 Feb 2025 09:41:07 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 5DE306B009D; Wed, 5 Feb 2025 09:41:07 -0500 (EST) 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 3AEDD6B009B for ; Wed, 5 Feb 2025 09:41:07 -0500 (EST) Received: from smtpin25.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id D1584120DAB for ; Wed, 5 Feb 2025 14:41:06 +0000 (UTC) X-FDA: 83086153332.25.9661335 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf30.hostedemail.com (Postfix) with ESMTP id 20BBE80014 for ; Wed, 5 Feb 2025 14:41:04 +0000 (UTC) Authentication-Results: imf30.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=PFU1cub4; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf30.hostedemail.com: domain of leon@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=leon@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738766465; a=rsa-sha256; cv=none; b=goysM5KDnL/hasu6JE39rtIcVkx3BBZuRSDlLYtUniPUDUZ/eiQOp3F6vR+9Dzozh1EnDe y79ZFJsAnEp2ktup/+wM82F35bXDyuWd4ntfwYOegFb6uH9pUyDoj+8VYHEb9jILcIQpQa gOLEzbpVX4yWCkS1CrTtphQSjwPLu+E= ARC-Authentication-Results: i=1; imf30.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=PFU1cub4; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf30.hostedemail.com: domain of leon@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=leon@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1738766465; 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=12ko7sc0uNx7TL5zWA+a9qmI1uhVqCyaT+ACFapRx4s=; b=Fdp6n1PFG3RSMn6jE1/2zmPJUjRhrmIyZAGpnn6izc28Grqef3CnIYx7lJeIZQOwWAEB/3 5Pgh81wygzRuZpqLixVPUU0bezMpQ3JlutLKBz1Su0zERBuv1X/ZqorGnD6XN+PR62qJiT Ajpo1vIHlSrw9lkeePFs/YQ+OATLEKA= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 770905C6AA9; Wed, 5 Feb 2025 14:40:24 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 63F55C4CEE7; Wed, 5 Feb 2025 14:41:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766464; bh=kMJok7jnjFYjv25BG0NXDx/P4+jGmqumTNiB5h/lh4A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PFU1cub4gp7Q6tLcz4pr226x5t1Uynibb/l4rFTElf0xdejDMb4+N1qKztRUfLDna 0fCF+yg+FOEax1V+5R5SkoqukyQXtybN7tWdndBBroCh5pfH8ZnzmDz/7nmx50PWnm 54zyGbF/fiC3HXR07giJ6BHA9BJQmFc+A+ijTG2TbaKNR2R2y6F5kZXwO4evb5yTf3 dVsnBlE+zAkipTDXIV2Msdmo+g1BlqolgPV6KoU8ZE33dOSIWeNleLz11Smev+MbDl uIywtkIeU0WuSGyyoWWGQesAa6naYiF+P9EqHdQRW3XAtVGv9Gg2YrW7tL/0EuuFX1 DyHxYT0TJABcg== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 03/17] iommu: generalize the batched sync after map interface Date: Wed, 5 Feb 2025 16:40:23 +0200 Message-ID: X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Server: rspam04 X-Rspamd-Queue-Id: 20BBE80014 X-Stat-Signature: 66xknuqch9orbuwpkd87euch5z1k9pa7 X-Rspam-User: X-HE-Tag: 1738766464-239365 X-HE-Meta: U2FsdGVkX1822yrnqDyH0ubgwK+Z7GiWN60FW/msxqPbOjR2egwnaKYZd7KpRqvYgLyECXTLNuXFNhy87Mn4SyDQf4glMzlTGkDTqkp25hQDiiEu6S8m8+iL2R0ouCqv4jYlm6WsxfBuxBzDB6c0cBBerm57b7ux4WsF3mqDZXatHQHP2vE0pRs365zsMzpVQdqH/AUr15/Ufyxf4T3d/MAitN35zwy0VU9kLwfyIoksgFF/bqWUWraqgY2NC76vAWusivBarB3pyF5XrCUeHH4yPEkP69FaBHkKrxIzV7TXjuOpxCxCZ9n1f+hDjLrI9/GdeN54V5Ix/TbHUok/yMkABfTigD181GaOy3UkCsy4ZskXwyAoqWRMSNfx+U5weLgRKIeKpmvNmXBBvc/a0aTFnygcE6dVqz5OUN5uDrfsx8SW/Dlh7BCWt4tWDEKo5qyMYPxQEBUJcbb171wMgwn5Svv1YBD1rPZpCdDMXM7yJpYddiYGZTPf5uC9KIEGuDe6HCRwgSvyevDFuD/PUoLtKOaPZS2ZpBg2nheIS+tn+a6GWNIfZ5SmQD+E1bQ3LVV8VkMSwN7mZMh+ZBlgmNCwTiP3fMX0rh8kjdhpHA2byqtChjmDAh+B2hEHf81lGOALu2G7lhJHlXeluhWN94ZFKplmOOxLGigHFXiB3xh4ocFwNCrLWe9B/diW0a5O5qkSiXz/9lpVQ+dyP11bI8U2m/Wv8RuSUYpc9SPHu5yShGhiKCoUI9qePkBS8tGN8d/pOC6e+owGSwZAjqhwbhg3AfJ/ppzwptIsvDxhn5oFWqjg8/yDozsVijVu/Xzq2B+yjiS1QifQpAnybSPnGBv24TEWNG8d9D1eWcMR00u1s/obgX/CleH/7bqTxyvjMRSqDoXFWy0LuWPYXzatql/DZbaQdKgUSqvhZFjmY18rRXTH8vNnyB5Z9tPtyRFjrJYKWdZG3WagbtLai3c Zo/fr5IQ Lw3P5FkPrIj0BdUvUslQaKGB3olILD3p+hZlmodve+vs/6ZEv6pfUq0TANY0AUcgO5V2k8hez1P/aDA5YLC/awg/hvvw6ET6kEV/JiGvwjd/mSyxF/ZoUYKUFjmhkFzSRunTHamYJXZb+d/U2lBBx+qhUhycSrX+AllVZlaL9neNC8cGYL2diMaDAjy6aw1Q35YE4L63qMOHrPiOSLlSx9TwGvQ== 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: Christoph Hellwig For the upcoming IOVA-based DMA API we want to use the interface batch the sync after mapping multiple entries from dma-iommu without having a scatterlist. For that move more sanity checks from the callers into __iommu_map and make that function available outside of iommu.c as iommu_map_nosync. Add a wrapper for the map_sync as iommu_sync_map so that callers don't need to poke into the methods directly. Signed-off-by: Christoph Hellwig Acked-by: Will Deacon Signed-off-by: Leon Romanovsky --- drivers/iommu/iommu.c | 65 +++++++++++++++++++------------------------ include/linux/iommu.h | 4 +++ 2 files changed, 33 insertions(+), 36 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 870c3cdbd0f6..32b161988c4b 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2412,8 +2412,8 @@ static size_t iommu_pgsize(struct iommu_domain *domain, unsigned long iova, return pgsize; } -static int __iommu_map(struct iommu_domain *domain, unsigned long iova, - phys_addr_t paddr, size_t size, int prot, gfp_t gfp) +int iommu_map_nosync(struct iommu_domain *domain, unsigned long iova, + phys_addr_t paddr, size_t size, int prot, gfp_t gfp) { const struct iommu_domain_ops *ops = domain->ops; unsigned long orig_iova = iova; @@ -2422,12 +2422,19 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t orig_paddr = paddr; int ret = 0; + might_sleep_if(gfpflags_allow_blocking(gfp)); + if (unlikely(!(domain->type & __IOMMU_DOMAIN_PAGING))) return -EINVAL; if (WARN_ON(!ops->map_pages || domain->pgsize_bitmap == 0UL)) return -ENODEV; + /* Discourage passing strange GFP flags */ + if (WARN_ON_ONCE(gfp & (__GFP_COMP | __GFP_DMA | __GFP_DMA32 | + __GFP_HIGHMEM))) + return -EINVAL; + /* find out the minimum page size supported */ min_pagesz = 1 << __ffs(domain->pgsize_bitmap); @@ -2475,31 +2482,27 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova, return ret; } -int iommu_map(struct iommu_domain *domain, unsigned long iova, - phys_addr_t paddr, size_t size, int prot, gfp_t gfp) +int iommu_sync_map(struct iommu_domain *domain, unsigned long iova, size_t size) { const struct iommu_domain_ops *ops = domain->ops; - int ret; - - might_sleep_if(gfpflags_allow_blocking(gfp)); - /* Discourage passing strange GFP flags */ - if (WARN_ON_ONCE(gfp & (__GFP_COMP | __GFP_DMA | __GFP_DMA32 | - __GFP_HIGHMEM))) - return -EINVAL; + if (!ops->iotlb_sync_map) + return 0; + return ops->iotlb_sync_map(domain, iova, size); +} - ret = __iommu_map(domain, iova, paddr, size, prot, gfp); - if (ret == 0 && ops->iotlb_sync_map) { - ret = ops->iotlb_sync_map(domain, iova, size); - if (ret) - goto out_err; - } +int iommu_map(struct iommu_domain *domain, unsigned long iova, + phys_addr_t paddr, size_t size, int prot, gfp_t gfp) +{ + int ret; - return ret; + ret = iommu_map_nosync(domain, iova, paddr, size, prot, gfp); + if (ret) + return ret; -out_err: - /* undo mappings already done */ - iommu_unmap(domain, iova, size); + ret = iommu_sync_map(domain, iova, size); + if (ret) + iommu_unmap(domain, iova, size); return ret; } @@ -2599,26 +2602,17 @@ ssize_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova, struct scatterlist *sg, unsigned int nents, int prot, gfp_t gfp) { - const struct iommu_domain_ops *ops = domain->ops; size_t len = 0, mapped = 0; phys_addr_t start; unsigned int i = 0; int ret; - might_sleep_if(gfpflags_allow_blocking(gfp)); - - /* Discourage passing strange GFP flags */ - if (WARN_ON_ONCE(gfp & (__GFP_COMP | __GFP_DMA | __GFP_DMA32 | - __GFP_HIGHMEM))) - return -EINVAL; - while (i <= nents) { phys_addr_t s_phys = sg_phys(sg); if (len && s_phys != start + len) { - ret = __iommu_map(domain, iova + mapped, start, + ret = iommu_map_nosync(domain, iova + mapped, start, len, prot, gfp); - if (ret) goto out_err; @@ -2641,11 +2635,10 @@ ssize_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova, sg = sg_next(sg); } - if (ops->iotlb_sync_map) { - ret = ops->iotlb_sync_map(domain, iova, mapped); - if (ret) - goto out_err; - } + ret = iommu_sync_map(domain, iova, mapped); + if (ret) + goto out_err; + return mapped; out_err: diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 38c65e92ecd0..7ae9aa3a1894 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -857,6 +857,10 @@ extern struct iommu_domain *iommu_get_domain_for_dev(struct device *dev); extern struct iommu_domain *iommu_get_dma_domain(struct device *dev); extern int iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot, gfp_t gfp); +int iommu_map_nosync(struct iommu_domain *domain, unsigned long iova, + phys_addr_t paddr, size_t size, int prot, gfp_t gfp); +int iommu_sync_map(struct iommu_domain *domain, unsigned long iova, + size_t size); extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size); extern size_t iommu_unmap_fast(struct iommu_domain *domain, From patchwork Wed Feb 5 14:40:24 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961182 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 A0E56C02192 for ; Wed, 5 Feb 2025 14:41:11 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 2FA396B009D; Wed, 5 Feb 2025 09:41:11 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 283866B009E; Wed, 5 Feb 2025 09:41:11 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 0AFBF6B009F; Wed, 5 Feb 2025 09:41:11 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id DBB686B009D for ; Wed, 5 Feb 2025 09:41:10 -0500 (EST) Received: from smtpin22.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 98FCF80D9D for ; Wed, 5 Feb 2025 14:41:10 +0000 (UTC) X-FDA: 83086153500.22.EFBC7DC Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf08.hostedemail.com (Postfix) with ESMTP id C293316000E for ; Wed, 5 Feb 2025 14:41:08 +0000 (UTC) Authentication-Results: imf08.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=paVneeAJ; spf=pass (imf08.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=1738766468; 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=KcdVDY3nkPjZIk2xsNfw4g8jnbbHUTBzu+xP34Eyl+k=; b=2IDtD+noBfCoJ/BZ6kqqWZx1C/ScDBCBFxEBiO7ae/EU0X1iOQzhnyqZWx4ByBYkdoarLQ erTOi1Ad5SV+yCL/JdfHyW34t/pYaDgAYaFyxkwYdf3TFIrXjcw9IIxknjvQxjMFRkYfXG zk7otAuUXIBsoM3Na5W5pe+kBDUU+1M= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738766468; a=rsa-sha256; cv=none; b=BbpsonDIxfO5jxb44dl0xKLqgBv3K+RS2OyrtOyhBXtfJPHgmMtYoArpzTmEizLDDpcF6A tka7F1PLv3ZNMe8WnkGyhQrSTv6eiJ3FO5e8hyJB92szKQ/7F3A7O+s6fPd0DAZMm3KDHN SpWU70z/5fCnf6e3HgX2KnbgEXf4al0= ARC-Authentication-Results: i=1; imf08.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=paVneeAJ; spf=pass (imf08.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 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 3B0335C6C94; Wed, 5 Feb 2025 14:40:28 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 19E9DC4CEDD; Wed, 5 Feb 2025 14:41:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766467; bh=0zY9wH2OP9d22rL1O7KXuZTa/ogQAL5HzMoIiMUubaE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=paVneeAJqn/ltBJv6BGhRXTQ/1o7gRgteq2iCdVfu0se6SR44/XZ19uVDs57AYcx5 G6SYFwf9oPkm9cSNiuGfKntNAWNpRrba6qFPBtdsBpcbKc4/ygjDK7v9rRTgtNgXJY wMEOH+TPUG4apPSNsLSopbZGBVV/xLPSIuqZV6NOJslRLA1vKskQA0UyhxlHcTpCDu DL1YnlM5CiKBwg4+D+3xSdmQ51egLGcf890c1UIfYj2+bGGKlIShSQq08wTw6gpzyw F/J3DHrDVo1YPqcaiE1BNjK2tJyO9YQnTqr6eKZ8NQTx3Y+qbGNoPheStWyzcZwbPr fZsxDVy3Q2DYg== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Leon Romanovsky , Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 , Jason Gunthorpe Subject: [PATCH v7 04/17] iommu: add kernel-doc for iommu_unmap and iommu_unmap_fast Date: Wed, 5 Feb 2025 16:40:24 +0200 Message-ID: <49d9ef3273ab03821931114329c49ae02b1cd902.1738765879.git.leonro@nvidia.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Stat-Signature: mocreep51qbywqjxjspiieen79ew1ist X-Rspam-User: X-Rspamd-Queue-Id: C293316000E X-Rspamd-Server: rspam03 X-HE-Tag: 1738766468-551742 X-HE-Meta: U2FsdGVkX18L6NAnCx1RXOEB+FohSEtfyGSdQr6O09TN92w4PZ4ikXOaR4lqUgR8Y7mi+OFa+/x637ygCyv7tpuIerchB5X4KQSoWwyboc5EJmtgPExtmfeWDuw4JZHXqFeLpsginjOK4+7iYYmjEQj8m1PRvKU0GbToUB4SUP99AeDPKPLVSC3s2Obc2um8UQPtss6bWBCyf9R/cSFBGqKwA9YEo6eTVpeN70giBbXVGdfG/fAgCdCVX/nmIjk1Sf/gRzd//18Ao2+ba372lFg3NutMHo0csW2TtgBi/q2OdVFSBnRJ1qFwGsBYwau0dzEVKn2MApna/KXkK0mbwyHxmywcSs6zAZVQ/EJXlyDJ/8+oRB53Le7SYipdMbCY1L0yiR2tKSpLohC5kKH4h0jRdEcQ3At4uVxvVXfOUaR54+2bFbTy+sMKHHPdlnlrPVMC55LXDaC2kXzL8xsEOz25g+Bg62SKtb/gNEsPRZa4BW4n6DD/OLnqv/qJV6IFzZGBEjYHqNtyYAjFDhZYwhHtnQLIfUQMemMmph8f2pRr524UbbZT/ywD1b+t4w4B7QWNO/8b9M4MVsSDE7MilmlhbUlDK/iMXy0nKhr1NKPmCxJ4SDnY5xtQE3NxoBCctmgJMCW6Y0rsJPeTiG+ZMh3cmJNJYlCgRMNxZvGGCb5tdXcRomj378NpMW6PJNRJ9I70tOjM3XPU1xulLu//PMl7KWIkMLR1F8YxvN7pmf29Gp+NWAWQ4SXinN9KZGMq6i96Si2UZoQNv3+b8srxSKtTyu535BPAT9g+mE32k2PS8BmMWmTB9to4uul62uzigwke8iH9lUU9yyRYC+QphNPuyNkWPPk/xCAe9UmF7gShZdSXAM4mx7jb3Tn3G7KasHWO1eyddw9pBBzWm8p4ZbJ6KEMyl/v5ptHhxgTWGBSOGEPA7/ukRWr07vGU6NWLZSb7vKFqWntElkn1x9d ZQa8rBdA O33DxU+3zlve6rtbpJaT4mUQ3Lb2IFa3YOWYRR1InZdsJ77SdA44pjWuPoZlQePcpO6myVI1Ud+ShHU+f/dcY0q7xyXUuFEARieqCNgDa6RnknGsYrXmuzur7+f8GzdfwQ9GPIbE2TcvLeL1e8RYAi5BuunpYgbLa3H9ymI9Ls/RlOg2e0H7t208dPOp35r514jN2EwMCNxqqApqzXrR8XMwDsbMN0f8V4yA2qB7x+eGpKQ9iOtnWqdtuJzX0nvLp/w4ro/bl6u/tShY= 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 Add kernel-doc section for iommu_unmap and iommu_unmap_fast to document existing limitation of underlying functions which can't split individual ranges. Suggested-by: Jason Gunthorpe Acked-by: Will Deacon Reviewed-by: Christoph Hellwig Signed-off-by: Leon Romanovsky --- drivers/iommu/iommu.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 32b161988c4b..89b538eec5cb 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2590,6 +2590,25 @@ size_t iommu_unmap(struct iommu_domain *domain, } EXPORT_SYMBOL_GPL(iommu_unmap); +/** + * iommu_unmap_fast() - Remove mappings from a range of IOVA without IOTLB sync + * @domain: Domain to manipulate + * @iova: IO virtual address to start + * @size: Length of the range starting from @iova + * @iotlb_gather: range information for a pending IOTLB flush + * + * iommu_unmap_fast() will remove a translation created by iommu_map(). + * It can't subdivide a mapping created by iommu_map(), so it should be + * called with IOVA ranges that match what was passed to iommu_map(). The + * range can aggregate contiguous iommu_map() calls so long as no individual + * range is split. + * + * Basically iommu_unmap_fast() is the same as iommu_unmap() but for callers + * which manage the IOTLB flushing externally to perform a batched sync. + * + * Returns: Number of bytes of IOVA unmapped. iova + res will be the point + * unmapping stopped. + */ size_t iommu_unmap_fast(struct iommu_domain *domain, unsigned long iova, size_t size, struct iommu_iotlb_gather *iotlb_gather) From patchwork Wed Feb 5 14:40:25 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961183 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 92B81C02194 for ; Wed, 5 Feb 2025 14:41:16 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 1C2826B00A0; Wed, 5 Feb 2025 09:41:16 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 14D226B00A1; Wed, 5 Feb 2025 09:41:16 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id EE0AE6B00A2; Wed, 5 Feb 2025 09:41:15 -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 B87166B00A0 for ; Wed, 5 Feb 2025 09:41:15 -0500 (EST) Received: from smtpin11.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 7DBA0A0D01 for ; Wed, 5 Feb 2025 14:41:14 +0000 (UTC) X-FDA: 83086153668.11.0549DB2 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf17.hostedemail.com (Postfix) with ESMTP id 8AB844000B for ; Wed, 5 Feb 2025 14:41:12 +0000 (UTC) Authentication-Results: imf17.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=iTWYed5O; spf=pass (imf17.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=1738766472; 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=3lLNVIx5egQ1baVigt/jrTl4N9mDneACLjBJ0ZJyQEk=; b=xIGR61YQ2rAIykBioO2c8udXJTR8099tmOsfbY7TIjuAI1ePmANSnkKsb0rdmB+/IZuzRh g6fuc007bYgfJJjHYsLMoT40LhWxPMgownk0dPHioZW6gvJEk3b+fG/hWGS9WgSn1RK8ro T1V+GqS38ogf1llcjmCxqgArGYYqJi0= ARC-Authentication-Results: i=1; imf17.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=iTWYed5O; spf=pass (imf17.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=1738766472; a=rsa-sha256; cv=none; b=uOUBxcSSvurJzVDn3ePiaSsMKmmG6t3NWR2gCPqrTLAwO1m7AubxjMLER/AA5icWOtXCyz 6C+bEnejAjtpyhqlrjYmwayw6576U/oytd1V3mCgeWunHV9hkKeVsfhekG6+O+s5igQad2 f4WmC8KRtnsaRIu+vx8wXn2BuqVTgDM= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id DD5CB5C6C88; Wed, 5 Feb 2025 14:40:31 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id AA13BC4CED1; Wed, 5 Feb 2025 14:41:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766471; bh=uV4uj3yeiNXqqcz2c2OkIk3RkgFn7bCeOfhFKxSpwPI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iTWYed5O1K/U9rA1bRBxEOd828iIZhTEnYHTSy31QG3sX/iO27+V7HPnyikUfmhe/ 53uWUyjnAdqq0ApJ5JFFE+QIBIs2GzGH1t6YNswRVDQw5Mv6+r3NYDmDfUAO3e8rzz R8ymFk+lnl3FU6zFFVB/P0IJHAecXf/t00V0rQtrC74QRlczO4Pt1liC1QZ7diigRJ BeDCpKoZoI+j0ApoMMJRKDuHyWBgAq9OfMDzAMbN2/6cU4ylP/9sYQkyf709sJl9Iv lEsq5nt3WFJ6NeYNK+QHQU0ndIQ5Peuh4SfXKzD4/z6CXt3WrP2F510RAoFo7SuZuy YwwMrQRBNSclA== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Leon Romanovsky , Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 05/17] dma-mapping: Provide an interface to allow allocate IOVA Date: Wed, 5 Feb 2025 16:40:25 +0200 Message-ID: <4cea6252ff6815b836ab29ff809083ddd1b39417.1738765879.git.leonro@nvidia.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Queue-Id: 8AB844000B X-Rspam-User: X-Rspamd-Server: rspam11 X-Stat-Signature: xqux8ogecqusj6kf34ad9rwu1fhp5hm5 X-HE-Tag: 1738766472-550069 X-HE-Meta: U2FsdGVkX1/x86ng5A2kLPw8IoIS8GfCBZdmHe5GrOpLeG3V/6pOrnNXVBgHqCkc6/IPvr0pkoTgB81CgdhPKbd2y0ObcU4koDYziXMoW69EahItYsoQ9Bx33HjSzw+tNbyXF7+3V5i2UzwlKle7P1pnJIfe2NhQQIyIhJBU2QeFjqTGDBR9Kx3AY4j+XWLO+j1tkWu6Ud5aN2S3xvo6FZgHYy93sb4cVA4coJR0Lo59QU1n7l7hj+ebpu/mpPzHgPya45kbzjXYQxBc1YsstuufgMxYv0KM+G/afegb0748NDA+uSUWtzA0N9OxMBCG0YvYvA9FRPqfcOMbu2HVxyQTqf7AFBuVvpKbG7dqn5EeMOQSJRKdDMg9Dxzp1h1q77J1BGQTzVcX/Vz0RYLZucO7PftMfE5m3psyxB3VPwf/qX2oFQaVE0zNW9v7LTVEoeUmkDluU3Er4oMfuWExB6K2FjNOd/Q8EFTy1CUibdYOEb9g4R1WRXD8dGxyBDInTygIvp1OSz+zeo7v9SW3e5jjyyi/qlZ6DwTVkm/HBMM7fyNhmo3Sd8ePuw82SbrBGkdZAp/rsscM7XT8depJ+okBhx2A9NNFgG6VJSGiKQLBsK63dnl2K7myRwVuF49qztvAqF0LQRCXX3nA1A+zuuuMt35YW8yyWV79KN5XFVNh2xPHmw1o/kDx8SM4/Sw0d+2C3c3dhXjd13PVFKnFj8CbVoFJdX9AN5jva+MrRDVU+Nvg5RPvynyeOfUc3uTMpo7Iwu5d8CHSIi/TWgMUCvppqKEOKPFIR3yTBHpXNA9M/IkYAySDLOykPOmhcDcIvZ/a3eTNY42fiKg1oQfynMbXc2ZmFgDxIQA1efJIW1V6rLIubAg4vnNPrWDgh5iS0tcsP/S9cSnBB9L2Hn8NJ/ksAqmF+cWD49OpJBKWYMKIJZswBk4DTNl32lcSdTu02kZr6+/u2ZrwUufh8MM dWuX9JdP //Opponz+ZvvGanWkGmuLT1GjieEoJ5wVmAylJCxn4wb4ywsArGC4ZfoAiwmvif0e/+bDGK8gjXyVd98mk7oAmkIlj2lkiAwBvdTPIQfa2O1DZ6U+eDAjzcktiblXwaESsW4WNIQZNWFmaXztuhgfqw5wmrtv2seZtHVwkTKHqmC38nSu1tSrwwVeHZ3RnX2td7dp 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. In the new API a DMA mapping transaction is identified by a struct dma_iova_state, which holds some recomputed information for the transaction which does not change for each page being mapped, so add a check if IOVA can be used for the specific transaction. 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. Reviewed-by: Christoph Hellwig Signed-off-by: Leon Romanovsky --- drivers/iommu/dma-iommu.c | 86 +++++++++++++++++++++++++++++++++++++ include/linux/dma-mapping.h | 48 +++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 853247c42f7d..309d278b1d86 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -1746,6 +1746,92 @@ size_t iommu_dma_max_mapping_size(struct device *dev) return SIZE_MAX; } +/** + * 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) +{ + struct iommu_dma_cookie *cookie; + struct iommu_domain *domain; + struct iova_domain *iovad; + size_t iova_off; + dma_addr_t addr; + + memset(state, 0, sizeof(*state)); + if (!use_dma_iommu(dev)) + return false; + + domain = iommu_get_dma_domain(dev); + cookie = domain->iova_cookie; + iovad = &cookie->iovad; + iova_off = iova_offset(iovad, phys); + + if (static_branch_unlikely(&iommu_deferred_attach_enabled) && + iommu_deferred_attach(dev, iommu_get_domain_for_dev(dev))) + return false; + + if (WARN_ON_ONCE(!size)) + return false; + + /* + * DMA_IOVA_USE_SWIOTLB is flag which is set by dma-iommu + * internals, make sure that caller didn't set it and/or + * didn't use this interface to map SIZE_MAX. + */ + if (WARN_ON_ONCE((u64)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; +} +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 b79925b1c433..de7f73810d54 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -72,6 +72,22 @@ #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) +struct dma_iova_state { + dma_addr_t addr; + u64 __size; +}; + +/* + * Use the high bit to mark if we used swiotlb for one or more ranges. + */ +#define DMA_IOVA_USE_SWIOTLB (1ULL << 63) + +static inline size_t dma_iova_size(struct dma_iova_state *state) +{ + /* Casting is needed for 32-bits systems */ + return (size_t)(state->__size & ~DMA_IOVA_USE_SWIOTLB); +} + #ifdef CONFIG_DMA_API_DEBUG void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr); void debug_dma_map_single(struct device *dev, const void *addr, @@ -277,6 +293,38 @@ static inline int dma_mmap_noncontiguous(struct device *dev, } #endif /* CONFIG_HAS_DMA */ +#ifdef CONFIG_IOMMU_DMA +/** + * dma_use_iova - check if the IOVA API is used for this state + * @state: IOVA state + * + * Return %true if the DMA transfers uses the dma_iova_*() calls or %false if + * they can't be used. + */ +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) void __dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir); From patchwork Wed Feb 5 14:40:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961187 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 7B0A6C02194 for ; Wed, 5 Feb 2025 14:41:30 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id D0D77280005; Wed, 5 Feb 2025 09:41:28 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id CBE5C280002; Wed, 5 Feb 2025 09:41:28 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id AE872280005; Wed, 5 Feb 2025 09:41:28 -0500 (EST) 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 8982E280002 for ; Wed, 5 Feb 2025 09:41:28 -0500 (EST) Received: from smtpin11.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id 45E69B187A for ; Wed, 5 Feb 2025 14:41:28 +0000 (UTC) X-FDA: 83086154256.11.AE03255 Received: from nyc.source.kernel.org (nyc.source.kernel.org [147.75.193.91]) by imf10.hostedemail.com (Postfix) with ESMTP id 9E418C0012 for ; Wed, 5 Feb 2025 14:41:26 +0000 (UTC) Authentication-Results: imf10.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=dVIn6T63; spf=pass (imf10.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=1738766486; 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=nbsmQc6BOdogabvWwJMN2WWcAdfn/8sUwSEOcSYrSC8=; b=1vkFW57t6xtIgb8OTbBRsoYsNApHy+CPzAlr6r8ejqQGg0DG+dXrtb+CgMrrOF/k4Ibrnb 5ujuyGFbZMf8uT4GMu7IDANWkWOcl6irlAiUgej02OY4YWeQ1+TquXkJgpUwh6EmhAFq97 baPJ4DY9ua8MuRpfcVF4J4IlPlksjLo= ARC-Authentication-Results: i=1; imf10.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=dVIn6T63; spf=pass (imf10.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-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738766486; a=rsa-sha256; cv=none; b=bgQUMUnQulY2GXIckaOAb3vdKT0Z6FwkjoFw70PvDJV6vLsNvGkRVBmPV+GFwl7Ubxen1Z YPrpE1yA4xHIZifkM2uG02GWPqSMYlx2HOCv6FsjlNv347eHhMM/eUiB9ReNH6yTqzaDfE uGMU6WwXKpcMoTPMWEIKR48AgX8JX3Y= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 03DC8A436BA; Wed, 5 Feb 2025 14:39:40 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 15F37C4CED1; Wed, 5 Feb 2025 14:41:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766485; bh=6Ai1gt0w10mq1r3SBiKNGGAp0oww0hCWygmK6vVlFiM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dVIn6T63yACvKBXXsPbv0oV/aj5UdNusQV2vQ8C5ZbC6U6GC5Ypa29dBOrgc9ITah U2TAX9SUR/hqSN92vnLtoQb7xOTLMg+PnnbiNUSh0+L1H0TzpXliOozFt7FoQ+G1MM UIA0BPob49QrpErBKVeEv/KcEtv9q31WiWst5vLl7lZnsnHlYix21IoxlSGm03NxAI RV+MGYJfznd5+9hZTN6AsCY4GbLPcCuiiAXkbAOUG+3MxlpKkJ26A0GWAAkMgpX+/0 LaGyTOZIbH4a0RFSKNokQOz1RWmILJtaPg8PLGGFJdjK4rlyJCpFsLw/8dMY56Sdtl ab82/62QBFK3w== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 06/17] iommu/dma: Factor out a iommu_dma_map_swiotlb helper Date: Wed, 5 Feb 2025 16:40:26 +0200 Message-ID: <49bf0300d6c49b784d88db6922c20dfe78f3047d.1738765879.git.leonro@nvidia.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Queue-Id: 9E418C0012 X-Stat-Signature: k6airdwsbupxog155aygh635ei565je1 X-Rspamd-Server: rspam08 X-Rspam-User: X-HE-Tag: 1738766486-47211 X-HE-Meta: U2FsdGVkX19FGitIzqTNsElXZUOdTCy0n8q6iEo+Y9gci4+oDEomXO7l+u3VCIR8gutIQEEpkH+8OyF+6NqIYVijrEajKxLWvPV5OBoBtdWf6plzjv9vy98TM6j01rEfQ/55ftsw50kn71I4A6BElCwvf/CnDqt2UZHi858VQtwQHWGDbNrjLgrHemYBDotPagv2ZrjMFyGEvpiBCe26mURk86TUcT9VvRYKFfJ+PX2i2Ru9fXstvOq3ni3j8giZJrBxBPb6lNizNynwDFJZyOnp2S4Uj2wzbaHEreEXQLZ154Jk7iW+Zj9EFm2GaERyFugwTRlLls3l+QBvYy+lFA8PF71nwYKPZMQkygRSBjYH8QL7VM3YarBV46qnnSrd8zG1SJAFK9NIYDfzdAQ95YKUvmEEUq3ZEQL4EgcSRfdeZQFOGdTNdzXNJKSUsxRieXbtG382hX/yFmkj2RzxiUkUFvQRMcH5YagEdUGCCVsxecaj6WfD1jAAgIz/o6ig+HamxsbgqFYrtbONk8ySlP8WgpBAvbfL+QunRq3frOyd4hjgWUGsFUX0ZtAXoGOLhxxh0Bq2qhoKwkLmZj66q7s+4NfO7NBJuqURbS4dim/+nE196+P/e9IMboC5U7ezfolzKNtkbPbGOE26RlOailJAi7F3mUUrszWW22C9/wWGaD6uAy9jHv/YeU86AAW0Aw63a+x6u9Wyo6dURyMzmrQ0Tbv3FWlIjZ6iN5uiEzuFsNwz0Tre7+oYLZja8pc7s9/DICXBzcjpTpadSRjTrUmoglNTTZGhMZBSyrzBkz7nBLr3tfiVKO7GorXhdgLpBwSGH+IXy0Ig/HxrFq2u3uhh3kh3woIgAfFpQ+l3WBWNO/7bz81BjopvRPyqxfpT4tzz9M/LrlEcAH4PNEIpSQLghsuNjj5oPW1wfErwD0LMAX2a9+VM9VksrRD5aw795YwiC1vrZpOu809dUvW w1w8OY7d 1zBrJuJxlL7vBfqtqsvJsxvs2PC/BAjTXM2sFZOlmiM2fSzuv1fapiQF95pTEfHaG2lFt8e33vEUh4LyZCwSjtQrM3ndaPO8Fy232adWvWdr7Km+F1LU2n1cpWDayDCjLm/Izu8/SL5WIhfUjkgdWeoPPIYJWiFQqwReABs16JqcXLC3EQgQtfk7zbXYIl1b8xjSaJ6XdB/GLywQn7ZOxmgYXvj0njhTE6BqTnL9IFBIbkz4FQ8Ad6WNemQ== 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: Christoph Hellwig Split the iommu logic from iommu_dma_map_page into a separate helper. This not only keeps the code neatly separated, but will also allow for reuse in another caller. Signed-off-by: Christoph Hellwig Signed-off-by: Leon Romanovsky --- drivers/iommu/dma-iommu.c | 73 ++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 309d278b1d86..80cc2c51ac99 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -1161,6 +1161,43 @@ void iommu_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl, arch_sync_dma_for_device(sg_phys(sg), sg->length, dir); } +static phys_addr_t iommu_dma_map_swiotlb(struct device *dev, phys_addr_t phys, + size_t size, enum dma_data_direction dir, unsigned long attrs) +{ + struct iommu_domain *domain = iommu_get_dma_domain(dev); + struct iova_domain *iovad = &domain->iova_cookie->iovad; + + if (!is_swiotlb_active(dev)) { + dev_warn_once(dev, "DMA bounce buffers are inactive, unable to map unaligned transaction.\n"); + return DMA_MAPPING_ERROR; + } + + trace_swiotlb_bounced(dev, phys, size); + + phys = swiotlb_tbl_map_single(dev, phys, size, iova_mask(iovad), dir, + attrs); + + /* + * Untrusted devices should not see padding areas with random leftover + * kernel data, so zero the pre- and post-padding. + * swiotlb_tbl_map_single() has initialized the bounce buffer proper to + * the contents of the original memory buffer. + */ + if (phys != DMA_MAPPING_ERROR && dev_is_untrusted(dev)) { + size_t start, virt = (size_t)phys_to_virt(phys); + + /* Pre-padding */ + start = iova_align_down(iovad, virt); + memset((void *)start, 0, virt - start); + + /* Post-padding */ + start = virt + size; + memset((void *)start, 0, iova_align(iovad, start) - start); + } + + return phys; +} + dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction dir, unsigned long attrs) @@ -1174,42 +1211,14 @@ dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page, dma_addr_t iova, dma_mask = dma_get_mask(dev); /* - * If both the physical buffer start address and size are - * page aligned, we don't need to use a bounce page. + * If both the physical buffer start address and size are page aligned, + * we don't need to use a bounce page. */ if (dev_use_swiotlb(dev, size, dir) && iova_offset(iovad, phys | size)) { - if (!is_swiotlb_active(dev)) { - dev_warn_once(dev, "DMA bounce buffers are inactive, unable to map unaligned transaction.\n"); - return DMA_MAPPING_ERROR; - } - - trace_swiotlb_bounced(dev, phys, size); - - phys = swiotlb_tbl_map_single(dev, phys, size, - iova_mask(iovad), dir, attrs); - + phys = iommu_dma_map_swiotlb(dev, phys, size, dir, attrs); if (phys == DMA_MAPPING_ERROR) - return DMA_MAPPING_ERROR; - - /* - * Untrusted devices should not see padding areas with random - * leftover kernel data, so zero the pre- and post-padding. - * swiotlb_tbl_map_single() has initialized the bounce buffer - * proper to the contents of the original memory buffer. - */ - if (dev_is_untrusted(dev)) { - size_t start, virt = (size_t)phys_to_virt(phys); - - /* Pre-padding */ - start = iova_align_down(iovad, virt); - memset((void *)start, 0, virt - start); - - /* Post-padding */ - start = virt + size; - memset((void *)start, 0, - iova_align(iovad, start) - start); - } + return phys; } if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) From patchwork Wed Feb 5 14:40:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961185 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 5A70AC02192 for ; Wed, 5 Feb 2025 14:41:25 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id DD0EB280003; Wed, 5 Feb 2025 09:41:24 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id D7F5E280002; Wed, 5 Feb 2025 09:41:24 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id C212C280003; Wed, 5 Feb 2025 09:41:24 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 7F182280002 for ; Wed, 5 Feb 2025 09:41:23 -0500 (EST) Received: from smtpin24.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 27C8480D98 for ; Wed, 5 Feb 2025 14:41:23 +0000 (UTC) X-FDA: 83086154046.24.A074067 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf18.hostedemail.com (Postfix) with ESMTP id 473691C0005 for ; Wed, 5 Feb 2025 14:41:19 +0000 (UTC) Authentication-Results: imf18.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=efKtBmLe; spf=pass (imf18.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=1738766480; 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=E9CbV4JEHmC9f7InM7nQNzRQwknALNZ23SL/7hfYhvs=; b=QZ2eI4eJgfzWEoOPT9ZBiNCaVivjxGrFmPAXs/yz0DaDVbETqoafO3JD0LAd3FAvy5f68S D7mUEzI+4kwNQnbxI/zZYvIQsviFwtpWt97Yvrtd1UJpvDBemGttsOBAy35u+S69FP8D9T nhRtkSL2lGeeK7SSZpPoiNet81WKwUI= ARC-Authentication-Results: i=1; imf18.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=efKtBmLe; spf=pass (imf18.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=1738766480; a=rsa-sha256; cv=none; b=nx2CKffEghQsdlyzkPw1lQaALVUHmbhOJRmAFuGeucc+E9QLE/3PcUbb5hf9FqhMIImFMt XNdeCkyHfxKkv1oyp3/4ES3ZRIH2rKR8u8m7SrOLmk9K7qfaI+VAV0TtV7wb5ofjb2nsi4 gl2H3zzmiKK8V5b4DPnXyZKCJGOoLiI= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 5CC7F5C6CAF; Wed, 5 Feb 2025 14:40:39 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 16473C4CED6; Wed, 5 Feb 2025 14:41:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766478; bh=YD0+/xtc+bT3zwV9GlRlpz9XDcLOQJ54Gk+vxUzvMs0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=efKtBmLeZP1Tm78hQW4LouJcZdMN2mtcWlKASUuQJnXEg3l55snLCN3bcIYmkieoN Ks64KJY87c24m0T+TTNOgVHn/ZB5ZvmGFGCqR9290qzcV1eYZXu5MA1AzmnC+gpKUT QGD7+quuTtHDAd9Jw02G/R3h5s8H9Wj3W5a9SPn8fboHCNO3xbSEwsChvORq+HqoJn ErYKu64Vy2ARJMuQD7lSlb+zkjeE7YWYCiCqaOfEHND7bLJF9wW/Yrk4D7o4udaST/ 1LgXudZfjpTwo0QMyKVkxpFjpLbNfTduCk7CrFNRCJStgvvUgHR8rnb7PwEjICIqD4 IlHkLEt2LlNwg== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Leon Romanovsky , Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 07/17] dma-mapping: Implement link/unlink ranges API Date: Wed, 5 Feb 2025 16:40:27 +0200 Message-ID: X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Server: rspam02 X-Rspamd-Queue-Id: 473691C0005 X-Stat-Signature: bdamhnq5951r3h5sfortedzrozuzcpju X-Rspam-User: X-HE-Tag: 1738766479-40264 X-HE-Meta: U2FsdGVkX1+Xa/DwfrBj/XMcbPhcM5HyMMh6krUMyakx014/872ln3ITbibeYswGidZqXPasE2mWJYg1Sav6vb5M89WO0w9MlHFsU61O7qEHDunNbEa3Z+776N7U6NUHc7J9q9dA7kx79YuZz4vWXrDYa71CX1uZiCZj4tRzp3JgXoBzkds8l7b5edeisNg2VFLIE02pd2FqP6h/UL16L1EMV2nh/BCTqS3NZAm3BC6cUVIP+NDTu/BqPlgZIXTzBmyDPO9vbSocotRA5U727bHgVfeAdgEGD5nSSapcfivdJqdh57KhrVZXd79TsmZMcr08WQ8ShFKi4Cw9gJ8zK7G7aqGpdxR5zm+GlHwehri5h7daj9zOdsQrLDwHiaCTSM3FZHy7UDVoZYjao49mf9rktqdrxYVpqyjtMft5/z5eYMvVPspBGDXRrGYDtqetrGPGMOdNx68qv9DEKSuk4dGJriDkfl5cnbahQHnmDLUsjgqmvxITN/mxZ6793lu9+k+W/tq0AUkd7hV5yDcH0J0rv2YwfsTLgehGPAZbTl3EI0zmB6DSx2fbsZS/6lcifW5HDMIE1OgxCUF/m/nbQLb5vLb5pDRHHILUTPM+TWzbh1HDvf8XZPDFsS5L9D9l2XBJLO+izLE5WERu63j3JA36FEe02SeEP7GC5mDN+rWWKIbe293VM74uNBjJ7T3GhAt7mXLkveiuKbdcNi+ebfrWoVHDJTc23mwX4uI7AXH04XmK31Td5Cj5idCvodmYiT3HyyGcSMSze5+tgvdwcxqB0wIKJErzKLf3HkbjhYJ0EDh3MvjV6RSgKlakl8G9b6IV6wqPDzay2pg3466zHzEr/eXxAhuI2RGF5lqqAQamSjwU555EjDKn1B63zJ3ZzkM2fqe/yDLCmvgeynrQDamibX+DyEcwhUQX8T6kRsAOVBy/CTGE96r+RzFw7lar24pIajk24zNO0gMHJBx Xwc0LQ25 T01Es2ZUABc6bOUFQP3iqY9JIYT9w0NHUqFzje+j77UYWH3ATSHaxtcwcr0ADOdSRKlenaITqk+dH8rw9+yeTpdbQWiCZRHsZqBUIslPa/rjKVPL7EmkVwSeay2BVxYLGa7UUms2HsVrLROJcgLYNADsLIDUpZNQYurQ0JPnBsSIsBIm78iAI15UGDLFBE6+Esl6f 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 Introduce new DMA APIs to perform DMA linkage of buffers in layers higher than DMA. In proposed API, the callers will perform the following steps. In map path: if (dma_can_use_iova(...)) dma_iova_alloc() for (page in range) dma_iova_link_next(...) dma_iova_sync(...) else /* Fallback to legacy map pages */ for (all pages) dma_map_page(...) In unmap path: if (dma_can_use_iova(...)) dma_iova_destroy() else for (all pages) dma_unmap_page(...) Reviewed-by: Christoph Hellwig Signed-off-by: Leon Romanovsky --- drivers/iommu/dma-iommu.c | 261 ++++++++++++++++++++++++++++++++++++ include/linux/dma-mapping.h | 32 +++++ 2 files changed, 293 insertions(+) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 80cc2c51ac99..67cb537bde3f 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -1841,6 +1841,267 @@ void dma_iova_free(struct device *dev, struct dma_iova_state *state) } EXPORT_SYMBOL_GPL(dma_iova_free); +static int __dma_iova_link(struct device *dev, dma_addr_t addr, + phys_addr_t phys, size_t size, enum dma_data_direction dir, + unsigned long attrs) +{ + bool coherent = dev_is_dma_coherent(dev); + + if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) + arch_sync_dma_for_device(phys, size, dir); + + return iommu_map_nosync(iommu_get_dma_domain(dev), addr, phys, size, + dma_info_to_prot(dir, coherent, attrs), GFP_ATOMIC); +} + +static int iommu_dma_iova_bounce_and_link(struct device *dev, dma_addr_t addr, + phys_addr_t phys, size_t bounce_len, + enum dma_data_direction dir, unsigned long attrs, + size_t iova_start_pad) +{ + struct iommu_domain *domain = iommu_get_dma_domain(dev); + struct iova_domain *iovad = &domain->iova_cookie->iovad; + phys_addr_t bounce_phys; + int error; + + bounce_phys = iommu_dma_map_swiotlb(dev, phys, bounce_len, dir, attrs); + if (bounce_phys == DMA_MAPPING_ERROR) + return -ENOMEM; + + error = __dma_iova_link(dev, addr - iova_start_pad, + bounce_phys - iova_start_pad, + iova_align(iovad, bounce_len), dir, attrs); + if (error) + swiotlb_tbl_unmap_single(dev, bounce_phys, bounce_len, dir, + attrs); + return error; +} + +static int iommu_dma_iova_link_swiotlb(struct device *dev, + struct dma_iova_state *state, phys_addr_t phys, size_t offset, + size_t size, enum dma_data_direction dir, unsigned long attrs) +{ + 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, phys); + size_t iova_end_pad = iova_offset(iovad, phys + size); + dma_addr_t addr = state->addr + offset; + size_t mapped = 0; + int error; + + if (iova_start_pad) { + size_t bounce_len = min(size, iovad->granule - iova_start_pad); + + error = iommu_dma_iova_bounce_and_link(dev, addr, phys, + bounce_len, dir, attrs, iova_start_pad); + if (error) + return error; + state->__size |= DMA_IOVA_USE_SWIOTLB; + + mapped += bounce_len; + size -= bounce_len; + if (!size) + return 0; + } + + size -= iova_end_pad; + error = __dma_iova_link(dev, addr + mapped, phys + mapped, size, dir, + attrs); + if (error) + goto out_unmap; + mapped += size; + + if (iova_end_pad) { + error = iommu_dma_iova_bounce_and_link(dev, addr + mapped, + phys + mapped, iova_end_pad, dir, attrs, 0); + if (error) + goto out_unmap; + state->__size |= DMA_IOVA_USE_SWIOTLB; + } + + return 0; + +out_unmap: + dma_iova_unlink(dev, state, 0, mapped, dir, attrs); + return error; +} + +/** + * dma_iova_link - Link a range of IOVA space + * @dev: DMA device + * @state: IOVA state + * @phys: physical address to link + * @offset: offset into the IOVA state to map into + * @size: size of the buffer + * @dir: DMA direction + * @attrs: attributes of mapping properties + * + * Link a range of IOVA space for the given IOVA state without IOTLB sync. + * This function is used to link multiple physical addresses in contigueous + * IOVA space without performing costly IOTLB sync. + * + * The caller is responsible to call to dma_iova_sync() to sync IOTLB at + * the end of linkage. + */ +int dma_iova_link(struct device *dev, struct dma_iova_state *state, + phys_addr_t phys, size_t offset, size_t size, + enum dma_data_direction dir, unsigned long attrs) +{ + 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, phys); + + if (WARN_ON_ONCE(iova_start_pad && offset > 0)) + return -EIO; + + if (dev_use_swiotlb(dev, size, dir) && iova_offset(iovad, phys | size)) + return iommu_dma_iova_link_swiotlb(dev, state, phys, offset, + size, dir, attrs); + + return __dma_iova_link(dev, state->addr + offset - iova_start_pad, + phys - iova_start_pad, + iova_align(iovad, size + iova_start_pad), dir, attrs); +} +EXPORT_SYMBOL_GPL(dma_iova_link); + +/** + * dma_iova_sync - Sync IOTLB + * @dev: DMA device + * @state: IOVA state + * @offset: offset into the IOVA state to sync + * @size: size of the buffer + * + * Sync IOTLB for the given IOVA state. This function should be called on + * the IOVA-contigous range created by one ore more dma_iova_link() calls + * to sync the IOTLB. + */ +int dma_iova_sync(struct device *dev, struct dma_iova_state *state, + size_t offset, 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; + dma_addr_t addr = state->addr + offset; + size_t iova_start_pad = iova_offset(iovad, addr); + + return iommu_sync_map(domain, addr - iova_start_pad, + iova_align(iovad, size + iova_start_pad)); +} +EXPORT_SYMBOL_GPL(dma_iova_sync); + +static void iommu_dma_iova_unlink_range_slow(struct device *dev, + dma_addr_t addr, size_t size, enum dma_data_direction dir, + unsigned long attrs) +{ + 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, addr); + dma_addr_t end = addr + size; + + do { + phys_addr_t phys; + size_t len; + + phys = iommu_iova_to_phys(domain, addr); + if (WARN_ON(!phys)) + /* Something very horrible happen here */ + return; + + len = min_t(size_t, + end - addr, iovad->granule - iova_start_pad); + + if (!dev_is_dma_coherent(dev) && + !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) + arch_sync_dma_for_cpu(phys, len, dir); + + swiotlb_tbl_unmap_single(dev, phys, len, dir, attrs); + + addr += len; + iova_start_pad = 0; + } while (addr < end); +} + +static void __iommu_dma_iova_unlink(struct device *dev, + struct dma_iova_state *state, size_t offset, size_t size, + enum dma_data_direction dir, unsigned long attrs, + bool free_iova) +{ + struct iommu_domain *domain = iommu_get_dma_domain(dev); + struct iommu_dma_cookie *cookie = domain->iova_cookie; + struct iova_domain *iovad = &cookie->iovad; + dma_addr_t addr = state->addr + offset; + size_t iova_start_pad = iova_offset(iovad, addr); + struct iommu_iotlb_gather iotlb_gather; + size_t unmapped; + + if ((state->__size & DMA_IOVA_USE_SWIOTLB) || + (!dev_is_dma_coherent(dev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))) + iommu_dma_iova_unlink_range_slow(dev, addr, size, dir, attrs); + + iommu_iotlb_gather_init(&iotlb_gather); + iotlb_gather.queued = free_iova && READ_ONCE(cookie->fq_domain); + + size = iova_align(iovad, size + iova_start_pad); + addr -= iova_start_pad; + unmapped = iommu_unmap_fast(domain, addr, size, &iotlb_gather); + WARN_ON(unmapped != size); + + if (!iotlb_gather.queued) + iommu_iotlb_sync(domain, &iotlb_gather); + if (free_iova) + iommu_dma_free_iova(cookie, addr, size, &iotlb_gather); +} + +/** + * dma_iova_unlink - Unlink a range of IOVA space + * @dev: DMA device + * @state: IOVA state + * @offset: offset into the IOVA state to unlink + * @size: size of the buffer + * @dir: DMA direction + * @attrs: attributes of mapping properties + * + * Unlink a range of IOVA space for the given IOVA state. + */ +void dma_iova_unlink(struct device *dev, struct dma_iova_state *state, + size_t offset, size_t size, enum dma_data_direction dir, + unsigned long attrs) +{ + __iommu_dma_iova_unlink(dev, state, offset, size, dir, attrs, false); +} +EXPORT_SYMBOL_GPL(dma_iova_unlink); + +/** + * dma_iova_destroy - Finish a DMA mapping transaction + * @dev: DMA device + * @state: IOVA state + * @mapped_len: number of bytes to unmap + * @dir: DMA direction + * @attrs: attributes of mapping properties + * + * Unlink the IOVA range up to @mapped_len and free the entire IOVA space. The + * range of IOVA from dma_addr to @mapped_len must all be linked, and be the + * only linked IOVA in state. + */ +void dma_iova_destroy(struct device *dev, struct dma_iova_state *state, + size_t mapped_len, enum dma_data_direction dir, + unsigned long attrs) +{ + if (mapped_len) + __iommu_dma_iova_unlink(dev, state, 0, mapped_len, dir, attrs, + true); + else + /* + * We can be here if first call to dma_iova_link() failed and + * there is nothing to unlink, so let's be more clear. + */ + dma_iova_free(dev, state); +} +EXPORT_SYMBOL_GPL(dma_iova_destroy); + 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 de7f73810d54..a71e110f1e9d 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -309,6 +309,17 @@ static inline bool dma_use_iova(struct dma_iova_state *state) 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); +void dma_iova_destroy(struct device *dev, struct dma_iova_state *state, + size_t mapped_len, enum dma_data_direction dir, + unsigned long attrs); +int dma_iova_sync(struct device *dev, struct dma_iova_state *state, + size_t offset, size_t size); +int dma_iova_link(struct device *dev, struct dma_iova_state *state, + phys_addr_t phys, size_t offset, size_t size, + enum dma_data_direction dir, unsigned long attrs); +void dma_iova_unlink(struct device *dev, struct dma_iova_state *state, + size_t offset, size_t size, enum dma_data_direction dir, + unsigned long attrs); #else /* CONFIG_IOMMU_DMA */ static inline bool dma_use_iova(struct dma_iova_state *state) { @@ -323,6 +334,27 @@ static inline void dma_iova_free(struct device *dev, struct dma_iova_state *state) { } +static inline void dma_iova_destroy(struct device *dev, + struct dma_iova_state *state, size_t mapped_len, + enum dma_data_direction dir, unsigned long attrs) +{ +} +static inline int dma_iova_sync(struct device *dev, + struct dma_iova_state *state, size_t offset, size_t size) +{ + return -EOPNOTSUPP; +} +static inline int dma_iova_link(struct device *dev, + struct dma_iova_state *state, phys_addr_t phys, size_t offset, + size_t size, enum dma_data_direction dir, unsigned long attrs) +{ + return -EOPNOTSUPP; +} +static inline void dma_iova_unlink(struct device *dev, + struct dma_iova_state *state, size_t offset, size_t size, + enum dma_data_direction dir, unsigned long attrs) +{ +} #endif /* CONFIG_IOMMU_DMA */ #if defined(CONFIG_HAS_DMA) && defined(CONFIG_DMA_NEED_SYNC) From patchwork Wed Feb 5 14:40:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961186 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 39301C02198 for ; Wed, 5 Feb 2025 14:41:28 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id BACE0280004; Wed, 5 Feb 2025 09:41:27 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id B5D93280002; Wed, 5 Feb 2025 09:41:27 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 93A29280004; Wed, 5 Feb 2025 09:41:27 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 6DB72280002 for ; Wed, 5 Feb 2025 09:41:27 -0500 (EST) Received: from smtpin02.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 28354A0C75 for ; Wed, 5 Feb 2025 14:41:26 +0000 (UTC) X-FDA: 83086154172.02.80FE237 Received: from nyc.source.kernel.org (nyc.source.kernel.org [147.75.193.91]) by imf03.hostedemail.com (Postfix) with ESMTP id 873752000B for ; Wed, 5 Feb 2025 14:41:23 +0000 (UTC) Authentication-Results: imf03.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=EQyxrQTb; spf=pass (imf03.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=1738766483; 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=FCvKJduO115Hwr3m8euFET908wS6PQ2RwDpc3mnAlyc=; b=IgCV1n9ZeB/3RPh3NtiFBAF3s6MYkRFUShgJVliq+iinBnfcTbvaTEYCOecSDslgOQ3v58 Lprx9RjqD4YhYqxV/EfRkPUcqDAnc5atyRAQwQqmBMDwfr6TR2uYsaacbuUeY6P7QJ8zio oxXLx1FNDGJ2IJ/lNu4K366Wrv1Rm0M= ARC-Authentication-Results: i=1; imf03.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=EQyxrQTb; spf=pass (imf03.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-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738766483; a=rsa-sha256; cv=none; b=EkLrtP72SmWRgmZef2Dah8qZhn0F4xiFOgvCr2TDu1C8ZZYrGqtxkjVxBygBuSenvlcu/y 6dpVTlATDeME06ZMyUxFDA5T0LNOi2xqXPHiPUrK+fLI7hx50se9y+QpBpTBjdhQDYpqFA Lz+0ltvdr4gGBwPcZJXVz8YtdQdVi2M= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 7CF0CA436BC; Wed, 5 Feb 2025 14:39:36 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8E0BCC4CEDD; Wed, 5 Feb 2025 14:41:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766482; bh=h/yBzjhoClTiKMl8LmMlOxeyuG0iINYdLuYFXO+3beM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EQyxrQTbpGC5ELIJR6leSqpKifyAyAeb8I25BfLUz1ZlNtPRHHXvoAx88ZmrkyhEj oiWitEtgqYTOWTpFkQbSoNIgY697J6MH3fgUibpLubW6kyqypRIhWVHQGweM5VjovX Y1kC2pXK7i3BJenUde3znE6Y9+xI1LxPrSgIzVCpeRFAFE2Mk+Y2KOQSzJRqpjmsik lZLP6NauWc5PCH6knOGMgYGQ2xZ4Jq10wd5UPj6rUnemzBirIatwxYpFvbihAfjv4l iAoBLOEQbRc5Y/oScO3iFxYYMiLToSeN6xqr8mVzjSijcHqG6FQdSWfyW/ezi5a2FL 0IJKIrd4mwf4A== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 08/17] dma-mapping: add a dma_need_unmap helper Date: Wed, 5 Feb 2025 16:40:28 +0200 Message-ID: <6c134d9e273433c52ca406de30112ecbc13f3b88.1738765879.git.leonro@nvidia.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Queue-Id: 873752000B X-Rspam-User: X-Rspamd-Server: rspam11 X-Stat-Signature: agya5dnmyew3c4fq3kx963t3mbrnxgd7 X-HE-Tag: 1738766483-672833 X-HE-Meta: U2FsdGVkX1+ORowxVaeYs2e0QW16iDzmbOCjEp/AjSWqUxSZWVMfQFYWKme64woGe9oMTZPEvB0962V8V9X5RDY1bJVR9rsm0Av26b5qLYOn0F8lsw37rpH/4gR1rvq9G2gNO6XaS0+d73oM08w9mHG/eb9uwFWIDZtSIax/N57WbnUUvK9Eu0YMlh/jh1NCrzBvwuFL11DZOYrrW1rhicdYS9LopkiO2lfgjEK+CFYg+Fg2rCeG7YJqpQntblhhBZfe+YC0+4QKNsiRKtjV217+XIjxKZZ6NiPMmsNN5aXmM12Kuh5CoaYQj+PkzZCxJLqW+pcWwyOlV7uKh/uaAhBDU/kuel5+mEFWZ5WJJZK1y1y5emeVUjT/9XifrkrZe2Ek/lDOEZMuRXBSxreAy0cj9QmWRHKEHvzQLr9BbjH0uNMwkMmu6Jwnu1yheyvDuThjmTMqMzI+3fVU2R2pifT4399OcpfrG9vOeiMpNF5ilZwZVXVvodi5GawC2flYDp0jm9eyBa5kgr8WfjqeQ26l7GpIIZqd6NzvS/aamggxJH2BW5WNxPKb+DRDnW9H5DgZet2ZBMNCF3hwrEjQA7cqEvKEeVNjHe5cMjBYf8opo26HNK2AFQKZqT65SMfli3oX70O2Y50/6DuF9jyXTb+a1SPZvHvH2i5/0tQi4cOPA9YyV08WiP4bbiQCfLscQrcHPPzui61dT7GfFNz6b8Rz+kGsd+w2dc+MnhAXfV7T/dILyoMRbx2vNySF/8eHym57q5Dq4HP50AVisuMqtP64xUe+Tg6kvJ+4SQp+qEVf8C84Wy5+AGNPztFGk4eLFvHDTqqGGenJo0zaPvI+dxQ6JrISNWeEo0YV/KHWbifxwm4ThaESy/bfYmEGadoG59r/FWMwE7xTaGlieZsYtCZ3l4OsrhloxClEHpMKrJN/XThX8hwpicHJHWBRwAmwPDlWcABa0Vca90brRhN ZR2Cow0G tgS2bJFLmJyoeG6CjfOGkOZ5P6WHAghjoMs4zGDS4lYJJK+zjVogNOmdCckX4/Cy9xx0KDihL9lpojtzaLa6BM8NKGyoPjEO668vVO2/UwDxXCXEKXj4pxI8ctZ405ysodETvWEu/WKZN+SAVKW6gIWA7O6tyh5Eig4tXv+kFuoQrRvJRrXr73g/O0oVKF7JTU8g4zE+dY1Q5/5WJAEbj3dnMvsuzlfqFg6v8OzN5mWgvYmm9LKJv8xTwpA== 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: Christoph Hellwig Add helper that allows a driver to skip calling dma_unmap_* if the DMA layer can guarantee that they are no-nops. Signed-off-by: Christoph Hellwig Signed-off-by: Leon Romanovsky --- include/linux/dma-mapping.h | 5 +++++ kernel/dma/mapping.c | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index a71e110f1e9d..d2f358c5a25d 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -406,6 +406,7 @@ static inline bool dma_need_sync(struct device *dev, dma_addr_t dma_addr) { return dma_dev_need_sync(dev) ? __dma_need_sync(dev, dma_addr) : false; } +bool dma_need_unmap(struct device *dev); #else /* !CONFIG_HAS_DMA || !CONFIG_DMA_NEED_SYNC */ static inline bool dma_dev_need_sync(const struct device *dev) { @@ -431,6 +432,10 @@ static inline bool dma_need_sync(struct device *dev, dma_addr_t dma_addr) { return false; } +static inline bool dma_need_unmap(struct device *dev) +{ + return false; +} #endif /* !CONFIG_HAS_DMA || !CONFIG_DMA_NEED_SYNC */ struct page *dma_alloc_pages(struct device *dev, size_t size, diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c index cda127027e48..3c3204ad2839 100644 --- a/kernel/dma/mapping.c +++ b/kernel/dma/mapping.c @@ -443,6 +443,24 @@ bool __dma_need_sync(struct device *dev, dma_addr_t dma_addr) } EXPORT_SYMBOL_GPL(__dma_need_sync); +/** + * dma_need_unmap - does this device need dma_unmap_* operations + * @dev: device to check + * + * If this function returns %false, drivers can skip calling dma_unmap_* after + * finishing an I/O. This function must be called after all mappings that might + * need to be unmapped have been performed. + */ +bool dma_need_unmap(struct device *dev) +{ + if (!dma_map_direct(dev, get_dma_ops(dev))) + return true; + if (!dev->dma_skip_sync) + return true; + return IS_ENABLED(CONFIG_DMA_API_DEBUG); +} +EXPORT_SYMBOL_GPL(dma_need_unmap); + static void dma_setup_need_sync(struct device *dev) { const struct dma_map_ops *ops = get_dma_ops(dev); From patchwork Wed Feb 5 14:40:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961189 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 3956FC02194 for ; Wed, 5 Feb 2025 14:41:38 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id BD646280007; Wed, 5 Feb 2025 09:41:37 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id B8483280002; Wed, 5 Feb 2025 09:41:37 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 9E23E280007; Wed, 5 Feb 2025 09:41:37 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 7652B280002 for ; Wed, 5 Feb 2025 09:41:37 -0500 (EST) Received: from smtpin07.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 30B6CA0D04 for ; Wed, 5 Feb 2025 14:41:37 +0000 (UTC) X-FDA: 83086154634.07.884205E Received: from nyc.source.kernel.org (nyc.source.kernel.org [147.75.193.91]) by imf07.hostedemail.com (Postfix) with ESMTP id 9AC634000F for ; Wed, 5 Feb 2025 14:41:35 +0000 (UTC) Authentication-Results: imf07.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=G7y6FNpG; spf=pass (imf07.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=1738766495; 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=hhLvg5xENLD8Hdo8SBjemzkxMX4jbTWJP8evBqnvRIY=; b=5hjigd5ZJYvGpEz3LmH6TBTjuLspmgyAd8QFmS1LVI3wW1pAZRNGr6QInHO55357IrSTp6 vj4pPD0Z86bwYI1O4BNItdW5n3so6LRofrer7zCsyR8NxRP8VdU+deNCWGdM6/AN9nMi1q o/h9Xy9uwrnhaOs2iO2Mi9xWQCGzkKA= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738766495; a=rsa-sha256; cv=none; b=ad+0nd8MPhc9IEgkYIlvr3nUMSTiYCjULObCBK2O36tPCqyw0I0hpVhF5fm8pji0F8Sl6h AnTV1MurHpeYTWnH9+kJ8Somru6C64P+iNnsIyL9xSmiT54Wgzou5YB14eRx4wrJ6ItYJz cn1Tk6u6cez9S9Lwio/Z6rnRFt18UhA= ARC-Authentication-Results: i=1; imf07.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=G7y6FNpG; spf=pass (imf07.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 C5B31A436BD; Wed, 5 Feb 2025 14:39:48 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 75406C4CEE2; Wed, 5 Feb 2025 14:41:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766494; bh=bwt/yttc57skms9Ne++frz0MugkbreUIXAgb1ccLqXg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=G7y6FNpGumoGrA+jV3Y8fmODmJJ7PYXSr0PbcK43L3T3pldBjHH5k+mxWah92Ei0r s0NR5oe5OqAX7KCtL0D5BdnkgIx0cZFUARawFKJAZy2n1/mkwDYzYVLLJMOWBVW8nX JNGxLhON8Ukz3k0pT39ARqaLs9kOA2jwslCT4NUOY8ZPo5EYbm0UOJD2BGGoYh+tJS p6v9FAc27I6tmAoMyKhiOH0t8rhKWk0Cfs17Uwd4iJa2RHOZ6XcTk+gTVqVU0ythyC 34qrycHhfu1HNKHYq9+r7Z3G9HhUInj6L90FxWP8OkRQKfkpJVrSBY3moIVL7/ctyc 6WCrLd3BZ5jIw== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 09/17] docs: core-api: document the IOVA-based API Date: Wed, 5 Feb 2025 16:40:29 +0200 Message-ID: X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Stat-Signature: 9cuug9wuzk4xn7ppqn1y3xbt5n1bcu1y X-Rspam-User: X-Rspamd-Queue-Id: 9AC634000F X-Rspamd-Server: rspam03 X-HE-Tag: 1738766495-258594 X-HE-Meta: U2FsdGVkX197jCkra2mQ6qyUEnhoOhqf75DYnphDoIZIGz1+IBVfZ/lVTy1kcG1oLYyik1yBC7wRVBoLb+gSfSSMKs0NhKW7driW1zycfNJNaup4kB9ljJjVd2yrr1mfxOtvfQfknX/Qjz/kfrfT7vIG+/g/pzh+9443quClwslzzFj9ifb6cimibeXkEuX1s99m3I/rNpaxnenXikO27E8RXhwuSK3/AI3AzTbn+Lw9hiGfzvQm4V7krEd1NmtUY0nGl74tg6dVXZQILxUo+ZLRsuy/5b5//tPlv2UhClIZScZ9l6lJXQ8AZKkwZD8/SakP+JUc2Nib/lqVt62K1V0/MhvSbN3T/Ou2J/tOEULXy2+EEqT9pVGc4N7SA+DTWWYSQPLV3MJ8NQWxuZKOoG8ZJRnz7TmvrH4b/Z0ToLxxlZOC53vKOsNj/GBpetJSFRr11ivELJOTrBmH+srwunQmkTy/8VXRwY/3+dVZQF1/5B3BIlxb/rk9lahfutlHFror21flmuHncIT51nxq72h0ywD6f3i1FIvmwgcO4NTOAmjkZal0ZE9Wq8px1zdQePZ0cwLKUvfNISij+enCJz9G5Zbu9gidh+Dq9ES/Wr0u3NuBzOZOAxuiGV8oxsDulAzJPlsHBiXir9J3SOp3uliYvZ6VYuIoJLRcjycaz2RApHV0S6Q7QyUGeP7v/MqcH6ElJX/w/s0rnRNp7y7p9ZuzZB/5ApkBnsx+J3F8YxGDeRgN0f4WJ67LRk8XeAudFPWWCfFG8FrPgzPUcizyzkUfxy58GbkYQst6PFr9dY+AJIQW/aQEBUHPCvLrZa8NYdusw0FdPItBnjmhwEmm2Z7cHCBNk2Mbm+xxSGy/LFI/+RxK89jpUlPETMN2ZYnm1cul2mlggvKCecgnD29nER9YSUKO7YalYITQCIbaWkknabWgM9C+v6HV1r/0VHwcuxDXnnhbbVkmfKAjiVH wtMWWKBp PYIiA47mA+zUq64j1zTs9OqDkWhOkfr5+SdIaPDTe/qJjjk1ZY9YIdqg9HDVQo065tpMkEZCDMu/ngEhdqNV+3M23F4XH0jf001dJKI9ii9y0LJTsgeyBAP8akcAz1WOtpbQwgPvTDdqd8ES2+tpSsIXQscBiU4O2xZiDT1LUQSky/nOM4rHe0XUnbjlioHeJ7jqR 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: Christoph Hellwig Add an explanation of the newly added IOVA-based mapping API. Signed-off-by: Christoph Hellwig Signed-off-by: Leon Romanovsky --- Documentation/core-api/dma-api.rst | 70 ++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/Documentation/core-api/dma-api.rst b/Documentation/core-api/dma-api.rst index 8e3cce3d0a23..61d6f4fe3d88 100644 --- a/Documentation/core-api/dma-api.rst +++ b/Documentation/core-api/dma-api.rst @@ -530,6 +530,76 @@ routines, e.g.::: .... } +Part Ie - IOVA-based DMA mappings +--------------------------------- + +These APIs allow a very efficient mapping when using an IOMMU. They are an +optional path that requires extra code and are only recommended for drivers +where DMA mapping performance, or the space usage for storing the DMA addresses +matter. All the considerations from the previous section apply here as well. + +:: + + bool dma_iova_try_alloc(struct device *dev, struct dma_iova_state *state, + phys_addr_t phys, size_t size); + +Is used to try to allocate IOVA space for mapping operation. If it returns +false this API can't be used for the given device and the normal streaming +DMA mapping API should be used. The ``struct dma_iova_state`` is allocated +by the driver and must be kept around until unmap time. + +:: + + static inline bool dma_use_iova(struct dma_iova_state *state) + +Can be used by the driver to check if the IOVA-based API is used after a +call to dma_iova_try_alloc. This can be useful in the unmap path. + +:: + + int dma_iova_link(struct device *dev, struct dma_iova_state *state, + phys_addr_t phys, size_t offset, size_t size, + enum dma_data_direction dir, unsigned long attrs); + +Is used to link ranges to the IOVA previously allocated. The start of all +but the first call to dma_iova_link for a given state must be aligned +to the DMA merge boundary returned by ``dma_get_merge_boundary())``, and +the size of all but the last range must be aligned to the DMA merge boundary +as well. + +:: + + int dma_iova_sync(struct device *dev, struct dma_iova_state *state, + size_t offset, size_t size); + +Must be called to sync the IOMMU page tables for IOVA-range mapped by one or +more calls to ``dma_iova_link()``. + +For drivers that use a one-shot mapping, all ranges can be unmapped and the +IOVA freed by calling: + +:: + + void dma_iova_destroy(struct device *dev, struct dma_iova_state *state, + enum dma_data_direction dir, unsigned long attrs); + +Alternatively drivers can dynamically manage the IOVA space by unmapping +and mapping individual regions. In that case + +:: + + void dma_iova_unlink(struct device *dev, struct dma_iova_state *state, + size_t offset, size_t size, enum dma_data_direction dir, + unsigned long attrs); + +is used to unmap a range previously mapped, and + +:: + + void dma_iova_free(struct device *dev, struct dma_iova_state *state); + +is used to free the IOVA space. All regions must have been unmapped using +``dma_iova_unlink()`` before calling ``dma_iova_free()``. Part II - Non-coherent DMA allocations -------------------------------------- From patchwork Wed Feb 5 14:40:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961188 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 96A8BC02194 for ; Wed, 5 Feb 2025 14:41:33 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id CEE39280006; Wed, 5 Feb 2025 09:41:32 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id C4992280002; Wed, 5 Feb 2025 09:41:32 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id A26D4280006; Wed, 5 Feb 2025 09:41:32 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 798D7280002 for ; Wed, 5 Feb 2025 09:41:32 -0500 (EST) Received: from smtpin11.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 2F5FD1A0D4F for ; Wed, 5 Feb 2025 14:41:32 +0000 (UTC) X-FDA: 83086154424.11.68C2EFE Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf02.hostedemail.com (Postfix) with ESMTP id 8ECA880015 for ; Wed, 5 Feb 2025 14:41:30 +0000 (UTC) Authentication-Results: imf02.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=MmYZuNtb; spf=pass (imf02.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=1738766490; 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=DIJO+24ad9vDGmaHVsAVu3JrfX9q54SvQz8P9QHl0Fg=; b=1Th35gRxgOYpeUWsILqX+Z+tQ2I9x0W5ImuyUwJMZGAg7WDpxT3WtM/Lu1k2rthql5GQjp yOSRAQBZqt/NS1h5Vv7CSbbZsUDsmlS5PVhSliMS0gUmP5uYZKkka0jlsfT6cEWftZd2NG ySrz5TKG+BfsVlJmLwgHGQOkp3ZCMxs= ARC-Authentication-Results: i=1; imf02.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=MmYZuNtb; spf=pass (imf02.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=1738766490; a=rsa-sha256; cv=none; b=mk3evBpmOCmgc0bt2MFngHRIQyZfT/DUXi0e9tNGfC7sQUM30veLNIyGzaYyzSO814/Kea 7thYAvzD7AWOSk5r2jYwf8Gi90ujiEUEoN8wP25V646tvbhaFWqaaOM2X2JNTvCKFsUF7e bkDAGTii/JJfSlw0wo+PSpD/ZSp7Cqk= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id E6E9F5C5530; Wed, 5 Feb 2025 14:40:49 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id B4761C4CED1; Wed, 5 Feb 2025 14:41:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766489; bh=1duzLMAGFBI5eIoee0bClSdhTdn7Gg5VjGv5Oh0QytA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MmYZuNtbS6QLoi6OOv5byqLDz590SF4gxj8qw60jmXERWj1pMQCqXtJjQDU1dtnmJ I49gvJilDg2s2dUa+tqPo5A44RRyvrYFFekDrUfStVtqnREoihzrEiH021FCONs/we I0t/MxA0MfedfNHxZyc9jswRtfPtZHiFYpjEw4N5ttmBIGKihSgtg25SCTf/w3g48q dvG1pC0huUPSeRKdDE/0h7gKxctMvTsLrdZGVDVA5b6/NIBf8c4ELC3f9n6tNZgYq8 n7y21IG/f+wFTBnwUna2sgrwwkMb7tObkmAsllwYyeL4VA5ehl8sGIibNxlNdCB7X0 zopkQxks5Gd1Q== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Leon Romanovsky , Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 10/17] mm/hmm: let users to tag specific PFN with DMA mapped bit Date: Wed, 5 Feb 2025 16:40:30 +0200 Message-ID: X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam09 X-Rspamd-Queue-Id: 8ECA880015 X-Stat-Signature: 3uoruqeyz79d6n1koxcbq9ktsz5zjrh1 X-HE-Tag: 1738766490-139558 X-HE-Meta: U2FsdGVkX1/0wIQqwRvBbYrEg/y9v2d3kaLTPi7008mK7M3Z76NZmatTFPAEQLoL1eHiNJS4b1h7+7HW6UrvT7veyzRQXzfNdvNgXDcvun+CpiL2rvk4ZXerpBG7Rzyvxv+6kSiiKtdphIODgnT3iLq9Ck5VeqqsiGh6F/clDW85dQzc8lgyvJ0bio7mxUSmLpBpsItpM17MBFx/6yuQQgPJbicFFuLBcdbs7uFy+QViSw/QeITzIq+EvQqnYLopa64Dj7CZ7UCU+tDDV3ILbpwa9MKplnz2J0iL/tLNINC2mi+wacS++SvXjId7Bb10nuSPIUEPPiEZ1EKg6FkaZwbWvoZ+LgIC4ipPnp+an7kJwoS3E9eLQxqnptzRME4HJjPjW59MIvLnBQZUOMUjDfTEhBavk+U+pUdTyMrSCpadyyM8ZYyxFZg0SuBefB9+91yXJTKE6+GAyy+7d/mv7588HnzG4lj4QYABInXppEbzLf33olehC/1/ozfxuRCI0uHN2AGDjRgy5+UK3D18RAGKwzA2vOM0p2eVkQD0KnKWNiEURmwTC3Z68j0BjdWBE/o4LK0VGmLaROx3jSXlQU649TAtO6Zxaeze+1a3kISGTqZUn3QnMafephl2bey9Hebfgc9uX2A0d2ReLdH0xSp8u6MwVKE6rI8ZjNqejgtut7UEhs2lFuMugc/5/DEDdgoq0MHa30zlVQvwJqh27ljQI4S/pDoYVOOdDHOAgiPVR8oqZUYiu5iE/Ck8JbTSkHD46XVpTceWOWOt//cz1FriueMnuME+E6fNs9jtzjUlzQjyjD3yDULAPucMcsl62Hhz1QApILC+7dM1mA7Snfpv+ePur5/8MpVwDHpe+EedwlP9zsHnvK0HWbmYpXR6EJjcLAQfmipgXValoF0pnS/aj3guLAL6ia9NsIN7P/S1mnDet8Fqf1BrUzPsK07mTfbAt0fnh+GzEwGE49A /tm/GhK9 Hvmtoc1xnNl3I+VWQ/+JinBnG4n8LvmrjCiWOCEPxZtwPMWjgAy8MXeMJVctPi41IY1izyREgTGFKBo0pHeJjkB9MRZLcx5gKkQdj7h4nUeHorPXq3MuF464JUzR/SvZmjEbEJd1+baMHz8/bBzy2+fsYfzLZHoa/duFGUL5Ho3QsnYnh6eUhBnCPfaVG/ifRr8Yv 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 Introduce new sticky flag (HMM_PFN_DMA_MAPPED), which isn't overwritten by HMM range fault. Such flag allows users to tag specific PFNs with information if this specific PFN was already DMA mapped. Signed-off-by: Leon Romanovsky --- include/linux/hmm.h | 17 +++++++++++++++ mm/hmm.c | 51 ++++++++++++++++++++++++++++----------------- 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/include/linux/hmm.h b/include/linux/hmm.h index 126a36571667..a1ddbedc19c0 100644 --- a/include/linux/hmm.h +++ b/include/linux/hmm.h @@ -23,6 +23,8 @@ struct mmu_interval_notifier; * HMM_PFN_WRITE - if the page memory can be written to (requires HMM_PFN_VALID) * HMM_PFN_ERROR - accessing the pfn is impossible and the device should * fail. ie poisoned memory, special pages, no vma, etc + * HMM_PFN_DMA_MAPPED - Flag preserved on input-to-output transformation + * to mark that page is already DMA mapped * * On input: * 0 - Return the current state of the page, do not fault it. @@ -36,6 +38,13 @@ enum hmm_pfn_flags { HMM_PFN_VALID = 1UL << (BITS_PER_LONG - 1), HMM_PFN_WRITE = 1UL << (BITS_PER_LONG - 2), HMM_PFN_ERROR = 1UL << (BITS_PER_LONG - 3), + + /* + * Sticky flags, carried from input to output, + * don't forget to update HMM_PFN_INOUT_FLAGS + */ + HMM_PFN_DMA_MAPPED = 1UL << (BITS_PER_LONG - 7), + HMM_PFN_ORDER_SHIFT = (BITS_PER_LONG - 8), /* Input flags */ @@ -57,6 +66,14 @@ static inline struct page *hmm_pfn_to_page(unsigned long hmm_pfn) return pfn_to_page(hmm_pfn & ~HMM_PFN_FLAGS); } +/* + * hmm_pfn_to_phys() - return physical address pointed to by a device entry + */ +static inline phys_addr_t hmm_pfn_to_phys(unsigned long hmm_pfn) +{ + return __pfn_to_phys(hmm_pfn & ~HMM_PFN_FLAGS); +} + /* * hmm_pfn_to_map_order() - return the CPU mapping size order * diff --git a/mm/hmm.c b/mm/hmm.c index 7e0229ae4a5a..da5743f6d854 100644 --- a/mm/hmm.c +++ b/mm/hmm.c @@ -39,13 +39,20 @@ enum { HMM_NEED_ALL_BITS = HMM_NEED_FAULT | HMM_NEED_WRITE_FAULT, }; +enum { + /* These flags are carried from input-to-output */ + HMM_PFN_INOUT_FLAGS = HMM_PFN_DMA_MAPPED, +}; + static int hmm_pfns_fill(unsigned long addr, unsigned long end, struct hmm_range *range, unsigned long cpu_flags) { unsigned long i = (addr - range->start) >> PAGE_SHIFT; - for (; addr < end; addr += PAGE_SIZE, i++) - range->hmm_pfns[i] = cpu_flags; + for (; addr < end; addr += PAGE_SIZE, i++) { + range->hmm_pfns[i] &= HMM_PFN_INOUT_FLAGS; + range->hmm_pfns[i] |= cpu_flags; + } return 0; } @@ -202,8 +209,10 @@ static int hmm_vma_handle_pmd(struct mm_walk *walk, unsigned long addr, return hmm_vma_fault(addr, end, required_fault, walk); pfn = pmd_pfn(pmd) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); - for (i = 0; addr < end; addr += PAGE_SIZE, i++, pfn++) - hmm_pfns[i] = pfn | cpu_flags; + for (i = 0; addr < end; addr += PAGE_SIZE, i++, pfn++) { + hmm_pfns[i] &= HMM_PFN_INOUT_FLAGS; + hmm_pfns[i] |= pfn | cpu_flags; + } return 0; } #else /* CONFIG_TRANSPARENT_HUGEPAGE */ @@ -230,14 +239,14 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr, unsigned long cpu_flags; pte_t pte = ptep_get(ptep); uint64_t pfn_req_flags = *hmm_pfn; + uint64_t new_pfn_flags = 0; if (pte_none_mostly(pte)) { required_fault = hmm_pte_need_fault(hmm_vma_walk, pfn_req_flags, 0); if (required_fault) goto fault; - *hmm_pfn = 0; - return 0; + goto out; } if (!pte_present(pte)) { @@ -253,16 +262,14 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr, cpu_flags = HMM_PFN_VALID; if (is_writable_device_private_entry(entry)) cpu_flags |= HMM_PFN_WRITE; - *hmm_pfn = swp_offset_pfn(entry) | cpu_flags; - return 0; + new_pfn_flags = swp_offset_pfn(entry) | cpu_flags; + goto out; } required_fault = hmm_pte_need_fault(hmm_vma_walk, pfn_req_flags, 0); - if (!required_fault) { - *hmm_pfn = 0; - return 0; - } + if (!required_fault) + goto out; if (!non_swap_entry(entry)) goto fault; @@ -304,11 +311,13 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr, pte_unmap(ptep); return -EFAULT; } - *hmm_pfn = HMM_PFN_ERROR; - return 0; + new_pfn_flags = HMM_PFN_ERROR; + goto out; } - *hmm_pfn = pte_pfn(pte) | cpu_flags; + new_pfn_flags = pte_pfn(pte) | cpu_flags; +out: + *hmm_pfn = (*hmm_pfn & HMM_PFN_INOUT_FLAGS) | new_pfn_flags; return 0; fault: @@ -448,8 +457,10 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end, } pfn = pud_pfn(pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); - for (i = 0; i < npages; ++i, ++pfn) - hmm_pfns[i] = pfn | cpu_flags; + for (i = 0; i < npages; ++i, ++pfn) { + hmm_pfns[i] &= HMM_PFN_INOUT_FLAGS; + hmm_pfns[i] |= pfn | cpu_flags; + } goto out_unlock; } @@ -507,8 +518,10 @@ static int hmm_vma_walk_hugetlb_entry(pte_t *pte, unsigned long hmask, } pfn = pte_pfn(entry) + ((start & ~hmask) >> PAGE_SHIFT); - for (; addr < end; addr += PAGE_SIZE, i++, pfn++) - range->hmm_pfns[i] = pfn | cpu_flags; + for (; addr < end; addr += PAGE_SIZE, i++, pfn++) { + range->hmm_pfns[i] &= HMM_PFN_INOUT_FLAGS; + range->hmm_pfns[i] |= pfn | cpu_flags; + } spin_unlock(ptl); return 0; From patchwork Wed Feb 5 14:40:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961191 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 C32ADC02192 for ; Wed, 5 Feb 2025 14:41:48 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 51EFF280009; Wed, 5 Feb 2025 09:41:48 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 4CDB1280002; Wed, 5 Feb 2025 09:41:48 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 347CC280009; Wed, 5 Feb 2025 09:41:48 -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 0F54C280002 for ; Wed, 5 Feb 2025 09:41:48 -0500 (EST) Received: from smtpin04.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id BC2D680DA0 for ; Wed, 5 Feb 2025 14:41:47 +0000 (UTC) X-FDA: 83086155054.04.FE5217E Received: from nyc.source.kernel.org (nyc.source.kernel.org [147.75.193.91]) by imf29.hostedemail.com (Postfix) with ESMTP id 2E566120014 for ; Wed, 5 Feb 2025 14:41:46 +0000 (UTC) Authentication-Results: imf29.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=TsI3Z0kq; spf=pass (imf29.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=1738766506; 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=K150YFnZpFzxE2Tw5QAd++iqX2dnfkDotaa8eZVuYsU=; b=5uCtSkgNh0/vyDEOuHv01mtwob3q+vlgg0ilDaziiWXRsikV3+5raUIptqzwyVYGv76Fp8 c21jq60RH54GDudEgAxF7ANd5pMSkuQ+MwgK4luTpyZPGhq+1XwcMb6MHbFnSqI81LIC9W fbc6Qy7HWLsvSd9Wkr46/l+a7VdFeG4= ARC-Authentication-Results: i=1; imf29.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=TsI3Z0kq; spf=pass (imf29.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-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738766506; a=rsa-sha256; cv=none; b=tlZo7VpMVvautTwtStPSShdLZ1fc4PCnphFwypm7gh/CtdxnXF3IjMG8+KNsPOJWUxIElh ViEfZFJbmRRqhbkdpVK2boxwEy8Ze1u1jI5Kyco03j8SFCsHrWub1OH7GkyG3cZcKeF91N rcRMb9XW1yNAojykiO0LhPk/ITwzGXw= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 54E64A436BA; Wed, 5 Feb 2025 14:39:59 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 130B7C4CEE4; Wed, 5 Feb 2025 14:41:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766505; bh=Xatk+lrCVGdwoGOa8kfsR+WTT/K6zVHeNO1fIMQwJWk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TsI3Z0kq7ZVEwmy8YAFG4Sb3RiEYefgmSarFC8IzZVi06U/Pyjyx978u0II1wpQut 03IReTCDXxBvQeqIji3ZclaIGOF3WxNnCdb+MFGxiDJ6AOJVSTNUoOHgF98BmdYz0o UO9wRPYO6HQb6BUkRqcB//usSl43vmMPla0/hOfM5VyANGaig3Ga5m8N8XX61VQkBI qYMFXLG5DEsy2cB6106zdrephQwUzoYup8CL8ipaVKu+T5PkSWBsNpZYYY94mxL5rY pK1Lo1WRWU1eaQ04Wb3/AoTnz4zQ5a/NzWjrjIGSOCP2eVlj8WQGyHVID0whVSB7I5 V5zMMrhjfYpWg== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Leon Romanovsky , Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 11/17] mm/hmm: provide generic DMA managing logic Date: Wed, 5 Feb 2025 16:40:31 +0200 Message-ID: X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Server: rspam02 X-Rspamd-Queue-Id: 2E566120014 X-Stat-Signature: 8jsjjgjm65osoqkxd97w3uq5eahbpo8x X-Rspam-User: X-HE-Tag: 1738766506-963267 X-HE-Meta: U2FsdGVkX18bWrA4Kyh+L6dNIQ+3mnYUuNSD4aV+XqBGs5JFlysLI9Jl2S0dkcPLgtmM7/v/gaSZQ8nS/ajP0Yoxp4iwMmb5mwmSQaR3CFjGDti/rCfNIMEIRFEKlJNT4jjPbI+q+NqEQ8WcHzrz6p3wsCNfnstBsMtNHO9/u3k2KENZoTnMsLQVXZ0YtRIBeNNMJkf4gFoFKSdZyJMge5TgtKzI1Ob/AGLQ5/8cFKmXo/pg4nBpJr/GwfrQLsa79aJnB5cDTse3fFCqWnGTsfN6gNtbBgKOznW4tnkChharADdQawi2ONemJYKYiwTaZXKBvB4gkaSuZKpr250toSioynYpvhO82G8mPfoJiNvWrpMHhycHXXYBDG7xf9oBkFYO1QL7BHQLqIdk/NiweZllBiieO4VfKUQxMbr9WA/2XlI9ddvRboS2R02NI1/ksNO+na8L1vyxwzpWJGThwBk7bddhhCTusiKVQrKtq3GBG1Z8j/orINwh4G3Dl6MxNLlFPv+n+4NHcgMEr1tx7GYA+5RaJXtAPKvioCiHMZpnTa+gItT+Ao+sudjWmfOQfK7xJuqJLYngCI3/sSPlQhJErrd54MzkfXU5UBJrzU4j3rb9aL1lkvnre2uUwXOtWRqvWDcL/I/OfMNRuR/DmlRdLdf9YeBs5Kiqt6d1SM5OC4jYZHqapa6j2V7v43wsOF1epcKxjgiieL26+0lA070z6w5807XVVUP2ajEuhy8SnbSpOTfLfBt04GTQykv2ySF2bLsxN3k5lyZC9UOaaAQCWENL2CkxyyE2ENpPdXLjSESA9V2UrsaLOrnQb+mr+6E0Es087x1++LuHQoOLwpq8BM3HxdAvYtL9EsiZ+cTOGu5DyeDQhSQcNz9AdVC4lAihYZPQ4sXKJUJG0vA5UHw/ig/6G5fDhRzp/RtYCn8fxAhfYg9uzbUvmbYb9Kb1k0AGX1lhk/c59L8xvmj zP7IWnWW AX7jvuWpTPaCase2iFF0rojB7aP1bRQnjwSFQ66YCBRN7FlzZP2d9/VOYHCiGhjwfoHXC5wV6eDpNbn/ZDZu0uXKfZPMtFn9nUtfL/Cb/VNya2p1GmDY2EWuhvePpq9ouPWqGxvNWm5W7yd3BUFm5Ld2XCVDto6WgRkdffq0+j888aTOsWRYqiKIrRn7EtEawFVOF 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 HMM callers use PFN list to populate range while calling to hmm_range_fault(), the conversion from PFN to DMA address is done by the callers with help of another DMA list. However, it is wasteful on any modern platform and by doing the right logic, that DMA list can be avoided. Provide generic logic to manage these lists and gave an interface to map/unmap PFNs to DMA addresses, without requiring from the callers to be an experts in DMA core API. Signed-off-by: Leon Romanovsky --- include/linux/hmm-dma.h | 33 ++++++ include/linux/hmm.h | 4 + mm/hmm.c | 215 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 include/linux/hmm-dma.h diff --git a/include/linux/hmm-dma.h b/include/linux/hmm-dma.h new file mode 100644 index 000000000000..f58b9fc71999 --- /dev/null +++ b/include/linux/hmm-dma.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */ +#ifndef LINUX_HMM_DMA_H +#define LINUX_HMM_DMA_H + +#include + +struct dma_iova_state; +struct pci_p2pdma_map_state; + +/* + * struct hmm_dma_map - array of PFNs and DMA addresses + * + * @state: DMA IOVA state + * @pfns: array of PFNs + * @dma_list: array of DMA addresses + * @dma_entry_size: size of each DMA entry in the array + */ +struct hmm_dma_map { + struct dma_iova_state state; + unsigned long *pfn_list; + dma_addr_t *dma_list; + size_t dma_entry_size; +}; + +int hmm_dma_map_alloc(struct device *dev, struct hmm_dma_map *map, + size_t nr_entries, size_t dma_entry_size); +void hmm_dma_map_free(struct device *dev, struct hmm_dma_map *map); +dma_addr_t hmm_dma_map_pfn(struct device *dev, struct hmm_dma_map *map, + size_t idx, + struct pci_p2pdma_map_state *p2pdma_state); +bool hmm_dma_unmap_pfn(struct device *dev, struct hmm_dma_map *map, size_t idx); +#endif /* LINUX_HMM_DMA_H */ diff --git a/include/linux/hmm.h b/include/linux/hmm.h index a1ddbedc19c0..1bc33e4c20ea 100644 --- a/include/linux/hmm.h +++ b/include/linux/hmm.h @@ -23,6 +23,8 @@ struct mmu_interval_notifier; * HMM_PFN_WRITE - if the page memory can be written to (requires HMM_PFN_VALID) * HMM_PFN_ERROR - accessing the pfn is impossible and the device should * fail. ie poisoned memory, special pages, no vma, etc + * HMM_PFN_P2PDMA - P2P page + * HMM_PFN_P2PDMA_BUS - Bus mapped P2P transfer * HMM_PFN_DMA_MAPPED - Flag preserved on input-to-output transformation * to mark that page is already DMA mapped * @@ -43,6 +45,8 @@ enum hmm_pfn_flags { * Sticky flags, carried from input to output, * don't forget to update HMM_PFN_INOUT_FLAGS */ + HMM_PFN_P2PDMA = 1UL << (BITS_PER_LONG - 5), + HMM_PFN_P2PDMA_BUS = 1UL << (BITS_PER_LONG - 6), HMM_PFN_DMA_MAPPED = 1UL << (BITS_PER_LONG - 7), HMM_PFN_ORDER_SHIFT = (BITS_PER_LONG - 8), diff --git a/mm/hmm.c b/mm/hmm.c index da5743f6d854..c9a0c396b288 100644 --- a/mm/hmm.c +++ b/mm/hmm.c @@ -10,6 +10,7 @@ */ #include #include +#include #include #include #include @@ -23,6 +24,7 @@ #include #include #include +#include #include #include @@ -41,7 +43,8 @@ enum { enum { /* These flags are carried from input-to-output */ - HMM_PFN_INOUT_FLAGS = HMM_PFN_DMA_MAPPED, + HMM_PFN_INOUT_FLAGS = HMM_PFN_DMA_MAPPED | HMM_PFN_P2PDMA | + HMM_PFN_P2PDMA_BUS, }; static int hmm_pfns_fill(unsigned long addr, unsigned long end, @@ -620,3 +623,213 @@ int hmm_range_fault(struct hmm_range *range) return ret; } EXPORT_SYMBOL(hmm_range_fault); + +/** + * hmm_dma_map_alloc - Allocate HMM map structure + * @dev: device to allocate structure for + * @map: HMM map to allocate + * @nr_entries: number of entries in the map + * @dma_entry_size: size of the DMA entry in the map + * + * Allocate the HMM map structure and all the lists it contains. + * Return 0 on success, -ENOMEM on failure. + */ +int hmm_dma_map_alloc(struct device *dev, struct hmm_dma_map *map, + size_t nr_entries, size_t dma_entry_size) +{ + bool dma_need_sync = false; + bool use_iova; + + if (!(nr_entries * PAGE_SIZE / dma_entry_size)) + return -EINVAL; + + /* + * The HMM API violates our normal DMA buffer ownership rules and can't + * transfer buffer ownership. The dma_addressing_limited() check is a + * best approximation to ensure no swiotlb buffering happens. + */ +#ifdef CONFIG_DMA_NEED_SYNC + dma_need_sync = !dev->dma_skip_sync; +#endif /* CONFIG_DMA_NEED_SYNC */ + if (dma_need_sync || dma_addressing_limited(dev)) + return -EOPNOTSUPP; + + map->dma_entry_size = dma_entry_size; + map->pfn_list = + kvcalloc(nr_entries, sizeof(*map->pfn_list), GFP_KERNEL); + if (!map->pfn_list) + return -ENOMEM; + + use_iova = dma_iova_try_alloc(dev, &map->state, 0, + nr_entries * PAGE_SIZE); + if (!use_iova && dma_need_unmap(dev)) { + map->dma_list = kvcalloc(nr_entries, sizeof(*map->dma_list), + GFP_KERNEL); + if (!map->dma_list) + goto err_dma; + } + return 0; + +err_dma: + kvfree(map->pfn_list); + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(hmm_dma_map_alloc); + +/** + * hmm_dma_map_free - iFree HMM map structure + * @dev: device to free structure from + * @map: HMM map containing the various lists and state + * + * Free the HMM map structure and all the lists it contains. + */ +void hmm_dma_map_free(struct device *dev, struct hmm_dma_map *map) +{ + if (dma_use_iova(&map->state)) + dma_iova_free(dev, &map->state); + kvfree(map->pfn_list); + kvfree(map->dma_list); +} +EXPORT_SYMBOL_GPL(hmm_dma_map_free); + +/** + * hmm_dma_map_pfn - Map a physical HMM page to DMA address + * @dev: Device to map the page for + * @map: HMM map + * @idx: Index into the PFN and dma address arrays + * @p2pdma_state: PCI P2P state. + * + * dma_alloc_iova() allocates IOVA based on the size specified by their use in + * iova->size. Call this function after IOVA allocation to link whole @page + * to get the DMA address. Note that very first call to this function + * will have @offset set to 0 in the IOVA space allocated from + * dma_alloc_iova(). For subsequent calls to this function on same @iova, + * @offset needs to be advanced by the caller with the size of previous + * page that was linked + DMA address returned for the previous page that was + * linked by this function. + */ +dma_addr_t hmm_dma_map_pfn(struct device *dev, struct hmm_dma_map *map, + size_t idx, + struct pci_p2pdma_map_state *p2pdma_state) +{ + struct dma_iova_state *state = &map->state; + dma_addr_t *dma_addrs = map->dma_list; + unsigned long *pfns = map->pfn_list; + struct page *page = hmm_pfn_to_page(pfns[idx]); + phys_addr_t paddr = hmm_pfn_to_phys(pfns[idx]); + size_t offset = idx * map->dma_entry_size; + unsigned long attrs = 0; + dma_addr_t dma_addr; + int ret; + + if ((pfns[idx] & HMM_PFN_DMA_MAPPED) && + !(pfns[idx] & HMM_PFN_P2PDMA_BUS)) { + /* + * We are in this flow when there is a need to resync flags, + * for example when page was already linked in prefetch call + * with READ flag and now we need to add WRITE flag + * + * This page was already programmed to HW and we don't want/need + * to unlink and link it again just to resync flags. + */ + if (dma_use_iova(state)) + return state->addr + offset; + + /* + * Without dma_need_unmap, the dma_addrs array is NULL, thus we + * need to regenerate the address below even if there already + * was a mapping. But !dma_need_unmap implies that the + * mapping stateless, so this is fine. + */ + if (dma_need_unmap(dev)) + return dma_addrs[idx]; + + /* Continue to remapping */ + } + + switch (pci_p2pdma_state(p2pdma_state, dev, page)) { + case PCI_P2PDMA_MAP_NONE: + break; + case PCI_P2PDMA_MAP_THRU_HOST_BRIDGE: + attrs |= DMA_ATTR_SKIP_CPU_SYNC; + pfns[idx] |= HMM_PFN_P2PDMA; + break; + case PCI_P2PDMA_MAP_BUS_ADDR: + pfns[idx] |= HMM_PFN_P2PDMA_BUS | HMM_PFN_DMA_MAPPED; + return pci_p2pdma_bus_addr_map(p2pdma_state, paddr); + default: + return DMA_MAPPING_ERROR; + } + + if (dma_use_iova(state)) { + ret = dma_iova_link(dev, state, paddr, offset, + map->dma_entry_size, DMA_BIDIRECTIONAL, + attrs); + if (ret) + goto error; + + ret = dma_iova_sync(dev, state, offset, map->dma_entry_size); + if (ret) { + dma_iova_unlink(dev, state, offset, map->dma_entry_size, + DMA_BIDIRECTIONAL, attrs); + goto error; + } + + dma_addr = state->addr + offset; + } else { + if (WARN_ON_ONCE(dma_need_unmap(dev) && !dma_addrs)) + goto error; + + dma_addr = dma_map_page(dev, page, 0, map->dma_entry_size, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(dev, dma_addr)) + goto error; + + if (dma_need_unmap(dev)) + dma_addrs[idx] = dma_addr; + } + pfns[idx] |= HMM_PFN_DMA_MAPPED; + return dma_addr; +error: + pfns[idx] &= ~HMM_PFN_P2PDMA; + return DMA_MAPPING_ERROR; + +} +EXPORT_SYMBOL_GPL(hmm_dma_map_pfn); + +/** + * hmm_dma_unmap_pfn - Unmap a physical HMM page from DMA address + * @dev: Device to unmap the page from + * @map: HMM map + * @idx: Index of the PFN to unmap + * + * Returns true if the PFN was mapped and has been unmapped, false otherwise. + */ +bool hmm_dma_unmap_pfn(struct device *dev, struct hmm_dma_map *map, size_t idx) +{ + struct dma_iova_state *state = &map->state; + dma_addr_t *dma_addrs = map->dma_list; + unsigned long *pfns = map->pfn_list; + unsigned long attrs = 0; + +#define HMM_PFN_VALID_DMA (HMM_PFN_VALID | HMM_PFN_DMA_MAPPED) + if ((pfns[idx] & HMM_PFN_VALID_DMA) != HMM_PFN_VALID_DMA) + return false; +#undef HMM_PFN_VALID_DMA + + if (pfns[idx] & HMM_PFN_P2PDMA_BUS) + ; /* no need to unmap bus address P2P mappings */ + else if (dma_use_iova(state)) { + if (pfns[idx] & HMM_PFN_P2PDMA) + attrs |= DMA_ATTR_SKIP_CPU_SYNC; + dma_iova_unlink(dev, state, idx * map->dma_entry_size, + map->dma_entry_size, DMA_BIDIRECTIONAL, attrs); + } else if (dma_need_unmap(dev)) + dma_unmap_page(dev, dma_addrs[idx], map->dma_entry_size, + DMA_BIDIRECTIONAL); + + pfns[idx] &= + ~(HMM_PFN_DMA_MAPPED | HMM_PFN_P2PDMA | HMM_PFN_P2PDMA_BUS); + return true; +} +EXPORT_SYMBOL_GPL(hmm_dma_unmap_pfn); From patchwork Wed Feb 5 14:40:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961190 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 EBBD4C02192 for ; Wed, 5 Feb 2025 14:41:43 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 7B827280008; Wed, 5 Feb 2025 09:41:43 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 766AE280002; Wed, 5 Feb 2025 09:41:43 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 5B7FE280008; Wed, 5 Feb 2025 09:41:43 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id 36BFD280002 for ; Wed, 5 Feb 2025 09:41:43 -0500 (EST) Received: from smtpin27.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id E570EB1856 for ; Wed, 5 Feb 2025 14:41:42 +0000 (UTC) X-FDA: 83086154844.27.8123DE6 Received: from nyc.source.kernel.org (nyc.source.kernel.org [147.75.193.91]) by imf25.hostedemail.com (Postfix) with ESMTP id 4AABEA000C for ; Wed, 5 Feb 2025 14:41:41 +0000 (UTC) Authentication-Results: imf25.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=jqB0Z4Dj; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf25.hostedemail.com: domain of leon@kernel.org designates 147.75.193.91 as permitted sender) smtp.mailfrom=leon@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738766501; a=rsa-sha256; cv=none; b=GLh1Exs921iXD3xd+UElWLy25sdemsdjPayKf5xJQfIMO+OHbxZbcj4VMeAsSSqYd67zsa ogUZN3lh4uhjbOyom3cCw+po/1tHvdGp8afDwGr6DhdTOcNPPvHlCt+veRLQ4yO/Dn2Tav 9AAS7kPI8542H5o4VnWyg4yIfwk9W7k= ARC-Authentication-Results: i=1; imf25.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=jqB0Z4Dj; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf25.hostedemail.com: domain of leon@kernel.org designates 147.75.193.91 as permitted sender) smtp.mailfrom=leon@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1738766501; 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=X5hFcPyDu15If8V7sNtDwvJ8Xu+JkPnHXBNPzWYzEjE=; b=bZMrBP0eIAlkvp6MF42qnRaysm3ujaYN8XVdd7RuPOWd68Fs/h6u14p8gKQpTgSJAWEfXz 9XSG2f007M4irusz4P1kkb+R8BnlWD31MI0JTUlYVnaMngpvq6IRWlnggD6yOyltQPlNnU 1Bx2HL3gc1XYN4I4c5Hgr+DEvVIDYSc= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 838C7A436BF; Wed, 5 Feb 2025 14:39:54 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 62643C4CED1; Wed, 5 Feb 2025 14:41:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766499; bh=1NtzYG/HNM1opZyJkrQLiGTX/MtRD6ibirQ0ZeaHPIQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jqB0Z4DjEdA/HUDgteh5YGGZ5z4ZjMVTJeiuwcegETFy6m2clnnhRDEI/E8sIIDkD 4LqMLN923PSxMWj9Zw2gfYTotq/dSAAyG2ivF4LR34K4KTS9rZrKTnr+KX8/FOev8Y /0Tz9BRAeRHdlGancpLzubdfvOZkjPVIYZFN2Jx3m4wWHsxaqDkocvMp899aetcJ52 EjKwTQVs3nzt0z6lZzCRkdnOYGChwEOWCtNJl2jiHpnrH4wDj3wsMUWdOIbvB/fZp2 g66/J0WurN1mcKKcLv8pwU6LQCWc6i8VBfF9pRgQlfMQcvUwOJxSQNXT3KIjdBgQIw e8r02sHsq5Djw== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Leon Romanovsky , Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 12/17] RDMA/umem: Store ODP access mask information in PFN Date: Wed, 5 Feb 2025 16:40:32 +0200 Message-ID: <8b6d2d95cc7e35740ae1c73f37b8ea11d0d70d32.1738765879.git.leonro@nvidia.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam01 X-Rspamd-Queue-Id: 4AABEA000C X-Stat-Signature: 3zbhzn4i7roka5pzh4x1dpbrb4kkwo93 X-HE-Tag: 1738766501-823150 X-HE-Meta: U2FsdGVkX19oAIGVZTk373Z/9QFFa7I5LavAdq3SP/HgicWcBy5/rYz8ugG52KrKa4tH/+A+npvLlYSt0/jVHS1eHEwsHgaA3B0ru3t9aMXXR2IklOS6eD6wYFtQ8bnu4+QX6yBAYXcCiGehpXagEpwF05ezr7nXfYDXIC+WiQIUsFW+3PVUwUrAB5qrDo73PFiY05tO1oNsuiJAUZONx26pOHXC65ijVQBd0VlGx+Npw08UHrjGGxb0buUJCiEhvLrzLvwdsRSwDJjb3SxOKDKC5LSb7GQkalWDdwULPLBu0itW3AURzao9vAE87x1OjrSSUyf8AUIgV0xmKnsZjF4Dpy+M26TfpXnQPZIVLF8vFDiMvFkddmmTkJRhw2hOaGTezLoS8wAdjOdnkXMBEZMK2e0+L3yyOQZ5lE1XvVsClQFtYv//3k5l7zaI78DDAQCwIFzy18GIWv9lgRfzOeiqCRCpLysretCs5t5IIZw6vFxkwI2S0pxkwa2EAL4meRTKo2QOARve7eX/RgZUnkR0v+4+cxjv/saKaCAPf15djZzF0utgjRcJ4W1QC8ocnDNqilmuBSeWTvWPi8bz3ucvxDSYkUAq9bsLRSOIa1J65OYfaH5hLeVIgd3ub0FJO+RxCHOzOsQiL0prQ3E2WZc0PMs37IaZ40OjJUVMENvXw1E+jH3Evdh3fr9jpyjgo+n/3LeF9gzsOt9WbAEJNxdY2jvUYX2W8KlLAnFFjr88RPQtt8S17kAqPGOozTnHjJwyEiHSdqYW4grPvegUUUOcaOKAXth9ui9IorAOk+WjD7FQAjgzcPkvPK8wyvq8vW0GIquMLN9IcXYoB5ITHrHQ0h4YpHwGrQGHhoNNfuhx0K7z/x091cIUqf/4b4tLWp//Xpie7g2AH1+qrl4Q72L3XjtMgznJD9FE3Tt/S9ciMGpt/zeKlUx8/TcA+opWaYIUGVyO35B/6KQEp0g EMG/gwzj t6LNHECbJbHnhcjjh6jNwWqx1zh5TaesjUZ2XESBkiTAyj8KIy+0j4YOkNBuHUpKvOeozO/bd8J81GnTaIOvG9PYfeUTjbcM7n3jdf8DTC8G7IARg8Ko2avaXxw2X0Qlj/XY8zBmLCUxSQ0r5JL1ma0VcFTCorjpG40Ry56OxJ48nMduOS6d7istaDY4lINhSIzhQ 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 As a preparation to remove dma_list, store access mask in PFN pointer and not in dma_addr_t. Signed-off-by: Leon Romanovsky --- drivers/infiniband/core/umem_odp.c | 103 +++++++++++---------------- drivers/infiniband/hw/mlx5/mlx5_ib.h | 1 + drivers/infiniband/hw/mlx5/odp.c | 37 +++++----- include/rdma/ib_umem_odp.h | 14 +--- 4 files changed, 64 insertions(+), 91 deletions(-) diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c index e9fa22d31c23..e1a5a567efb3 100644 --- a/drivers/infiniband/core/umem_odp.c +++ b/drivers/infiniband/core/umem_odp.c @@ -296,22 +296,11 @@ EXPORT_SYMBOL(ib_umem_odp_release); static int ib_umem_odp_map_dma_single_page( struct ib_umem_odp *umem_odp, unsigned int dma_index, - struct page *page, - u64 access_mask) + struct page *page) { struct ib_device *dev = umem_odp->umem.ibdev; dma_addr_t *dma_addr = &umem_odp->dma_list[dma_index]; - if (*dma_addr) { - /* - * If the page is already dma mapped it means it went through - * a non-invalidating trasition, like read-only to writable. - * Resync the flags. - */ - *dma_addr = (*dma_addr & ODP_DMA_ADDR_MASK) | access_mask; - return 0; - } - *dma_addr = ib_dma_map_page(dev, page, 0, 1 << umem_odp->page_shift, DMA_BIDIRECTIONAL); if (ib_dma_mapping_error(dev, *dma_addr)) { @@ -319,7 +308,6 @@ static int ib_umem_odp_map_dma_single_page( return -EFAULT; } umem_odp->npages++; - *dma_addr |= access_mask; return 0; } @@ -355,9 +343,6 @@ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *umem_odp, u64 user_virt, struct hmm_range range = {}; unsigned long timeout; - if (access_mask == 0) - return -EINVAL; - if (user_virt < ib_umem_start(umem_odp) || user_virt + bcnt > ib_umem_end(umem_odp)) return -EFAULT; @@ -383,7 +368,7 @@ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *umem_odp, u64 user_virt, if (fault) { range.default_flags = HMM_PFN_REQ_FAULT; - if (access_mask & ODP_WRITE_ALLOWED_BIT) + if (access_mask & HMM_PFN_WRITE) range.default_flags |= HMM_PFN_REQ_WRITE; } @@ -415,22 +400,17 @@ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *umem_odp, u64 user_virt, for (pfn_index = 0; pfn_index < num_pfns; pfn_index += 1 << (page_shift - PAGE_SHIFT), dma_index++) { - if (fault) { - /* - * Since we asked for hmm_range_fault() to populate - * pages it shouldn't return an error entry on success. - */ - WARN_ON(range.hmm_pfns[pfn_index] & HMM_PFN_ERROR); - WARN_ON(!(range.hmm_pfns[pfn_index] & HMM_PFN_VALID)); - } else { - if (!(range.hmm_pfns[pfn_index] & HMM_PFN_VALID)) { - WARN_ON(umem_odp->dma_list[dma_index]); - continue; - } - access_mask = ODP_READ_ALLOWED_BIT; - if (range.hmm_pfns[pfn_index] & HMM_PFN_WRITE) - access_mask |= ODP_WRITE_ALLOWED_BIT; - } + /* + * Since we asked for hmm_range_fault() to populate + * pages it shouldn't return an error entry on success. + */ + WARN_ON(fault && range.hmm_pfns[pfn_index] & HMM_PFN_ERROR); + WARN_ON(fault && !(range.hmm_pfns[pfn_index] & HMM_PFN_VALID)); + if (!(range.hmm_pfns[pfn_index] & HMM_PFN_VALID)) + continue; + + if (range.hmm_pfns[pfn_index] & HMM_PFN_DMA_MAPPED) + continue; hmm_order = hmm_pfn_to_map_order(range.hmm_pfns[pfn_index]); /* If a hugepage was detected and ODP wasn't set for, the umem @@ -445,13 +425,14 @@ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *umem_odp, u64 user_virt, } ret = ib_umem_odp_map_dma_single_page( - umem_odp, dma_index, hmm_pfn_to_page(range.hmm_pfns[pfn_index]), - access_mask); + umem_odp, dma_index, + hmm_pfn_to_page(range.hmm_pfns[pfn_index])); if (ret < 0) { ibdev_dbg(umem_odp->umem.ibdev, "ib_umem_odp_map_dma_single_page failed with error %d\n", ret); break; } + range.hmm_pfns[pfn_index] |= HMM_PFN_DMA_MAPPED; } /* upon success lock should stay on hold for the callee */ if (!ret) @@ -471,7 +452,6 @@ EXPORT_SYMBOL(ib_umem_odp_map_dma_and_lock); void ib_umem_odp_unmap_dma_pages(struct ib_umem_odp *umem_odp, u64 virt, u64 bound) { - dma_addr_t dma_addr; dma_addr_t dma; int idx; u64 addr; @@ -482,34 +462,37 @@ void ib_umem_odp_unmap_dma_pages(struct ib_umem_odp *umem_odp, u64 virt, virt = max_t(u64, virt, ib_umem_start(umem_odp)); bound = min_t(u64, bound, ib_umem_end(umem_odp)); for (addr = virt; addr < bound; addr += BIT(umem_odp->page_shift)) { + unsigned long pfn_idx = (addr - ib_umem_start(umem_odp)) >> + PAGE_SHIFT; + struct page *page = + hmm_pfn_to_page(umem_odp->pfn_list[pfn_idx]); + idx = (addr - ib_umem_start(umem_odp)) >> umem_odp->page_shift; dma = umem_odp->dma_list[idx]; - /* The access flags guaranteed a valid DMA address in case was NULL */ - if (dma) { - unsigned long pfn_idx = (addr - ib_umem_start(umem_odp)) >> PAGE_SHIFT; - struct page *page = hmm_pfn_to_page(umem_odp->pfn_list[pfn_idx]); - - dma_addr = dma & ODP_DMA_ADDR_MASK; - ib_dma_unmap_page(dev, dma_addr, - BIT(umem_odp->page_shift), - DMA_BIDIRECTIONAL); - if (dma & ODP_WRITE_ALLOWED_BIT) { - struct page *head_page = compound_head(page); - /* - * set_page_dirty prefers being called with - * the page lock. However, MMU notifiers are - * called sometimes with and sometimes without - * the lock. We rely on the umem_mutex instead - * to prevent other mmu notifiers from - * continuing and allowing the page mapping to - * be removed. - */ - set_page_dirty(head_page); - } - umem_odp->dma_list[idx] = 0; - umem_odp->npages--; + if (!(umem_odp->pfn_list[pfn_idx] & HMM_PFN_VALID)) + goto clear; + if (!(umem_odp->pfn_list[pfn_idx] & HMM_PFN_DMA_MAPPED)) + goto clear; + + ib_dma_unmap_page(dev, dma, BIT(umem_odp->page_shift), + DMA_BIDIRECTIONAL); + if (umem_odp->pfn_list[pfn_idx] & HMM_PFN_WRITE) { + struct page *head_page = compound_head(page); + /* + * set_page_dirty prefers being called with + * the page lock. However, MMU notifiers are + * called sometimes with and sometimes without + * the lock. We rely on the umem_mutex instead + * to prevent other mmu notifiers from + * continuing and allowing the page mapping to + * be removed. + */ + set_page_dirty(head_page); } + umem_odp->npages--; +clear: + umem_odp->pfn_list[pfn_idx] &= ~HMM_PFN_FLAGS; } } EXPORT_SYMBOL(ib_umem_odp_unmap_dma_pages); diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index 974a45c92fbb..53a06a7142ea 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h @@ -336,6 +336,7 @@ struct mlx5_ib_flow_db { #define MLX5_IB_UPD_XLT_PD BIT(4) #define MLX5_IB_UPD_XLT_ACCESS BIT(5) #define MLX5_IB_UPD_XLT_INDIRECT BIT(6) +#define MLX5_IB_UPD_XLT_DOWNGRADE BIT(7) /* Private QP creation flags to be passed in ib_qp_init_attr.create_flags. * diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c index f1e23583e6c0..dcfdf644cfe2 100644 --- a/drivers/infiniband/hw/mlx5/odp.c +++ b/drivers/infiniband/hw/mlx5/odp.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "mlx5_ib.h" #include "cmd.h" @@ -158,22 +159,12 @@ static void populate_klm(struct mlx5_klm *pklm, size_t idx, size_t nentries, } } -static u64 umem_dma_to_mtt(dma_addr_t umem_dma) -{ - u64 mtt_entry = umem_dma & ODP_DMA_ADDR_MASK; - - if (umem_dma & ODP_READ_ALLOWED_BIT) - mtt_entry |= MLX5_IB_MTT_READ; - if (umem_dma & ODP_WRITE_ALLOWED_BIT) - mtt_entry |= MLX5_IB_MTT_WRITE; - - return mtt_entry; -} - static void populate_mtt(__be64 *pas, size_t idx, size_t nentries, struct mlx5_ib_mr *mr, int flags) { struct ib_umem_odp *odp = to_ib_umem_odp(mr->umem); + bool downgrade = flags & MLX5_IB_UPD_XLT_DOWNGRADE; + unsigned long pfn; dma_addr_t pa; size_t i; @@ -181,8 +172,17 @@ static void populate_mtt(__be64 *pas, size_t idx, size_t nentries, return; for (i = 0; i < nentries; i++) { + pfn = odp->pfn_list[idx + i]; + if (!(pfn & HMM_PFN_VALID)) + /* ODP initialization */ + continue; + pa = odp->dma_list[idx + i]; - pas[i] = cpu_to_be64(umem_dma_to_mtt(pa)); + pa |= MLX5_IB_MTT_READ; + if ((pfn & HMM_PFN_WRITE) && !downgrade) + pa |= MLX5_IB_MTT_WRITE; + + pas[i] = cpu_to_be64(pa); } } @@ -302,8 +302,7 @@ static bool mlx5_ib_invalidate_range(struct mmu_interval_notifier *mni, * estimate the cost of another UMR vs. the cost of bigger * UMR. */ - if (umem_odp->dma_list[idx] & - (ODP_READ_ALLOWED_BIT | ODP_WRITE_ALLOWED_BIT)) { + if (umem_odp->pfn_list[idx] & HMM_PFN_VALID) { if (!in_block) { blk_start_idx = idx; in_block = 1; @@ -684,7 +683,7 @@ static int pagefault_real_mr(struct mlx5_ib_mr *mr, struct ib_umem_odp *odp, { int page_shift, ret, np; bool downgrade = flags & MLX5_PF_FLAGS_DOWNGRADE; - u64 access_mask; + u64 access_mask = 0; u64 start_idx; bool fault = !(flags & MLX5_PF_FLAGS_SNAPSHOT); u32 xlt_flags = MLX5_IB_UPD_XLT_ATOMIC; @@ -692,12 +691,14 @@ static int pagefault_real_mr(struct mlx5_ib_mr *mr, struct ib_umem_odp *odp, if (flags & MLX5_PF_FLAGS_ENABLE) xlt_flags |= MLX5_IB_UPD_XLT_ENABLE; + if (flags & MLX5_PF_FLAGS_DOWNGRADE) + xlt_flags |= MLX5_IB_UPD_XLT_DOWNGRADE; + page_shift = odp->page_shift; start_idx = (user_va - ib_umem_start(odp)) >> page_shift; - access_mask = ODP_READ_ALLOWED_BIT; if (odp->umem.writable && !downgrade) - access_mask |= ODP_WRITE_ALLOWED_BIT; + access_mask |= HMM_PFN_WRITE; np = ib_umem_odp_map_dma_and_lock(odp, user_va, bcnt, access_mask, fault); if (np < 0) diff --git a/include/rdma/ib_umem_odp.h b/include/rdma/ib_umem_odp.h index 0844c1d05ac6..a345c26a745d 100644 --- a/include/rdma/ib_umem_odp.h +++ b/include/rdma/ib_umem_odp.h @@ -8,6 +8,7 @@ #include #include +#include struct ib_umem_odp { struct ib_umem umem; @@ -67,19 +68,6 @@ static inline size_t ib_umem_odp_num_pages(struct ib_umem_odp *umem_odp) umem_odp->page_shift; } -/* - * The lower 2 bits of the DMA address signal the R/W permissions for - * the entry. To upgrade the permissions, provide the appropriate - * bitmask to the map_dma_pages function. - * - * Be aware that upgrading a mapped address might result in change of - * the DMA address for the page. - */ -#define ODP_READ_ALLOWED_BIT (1<<0ULL) -#define ODP_WRITE_ALLOWED_BIT (1<<1ULL) - -#define ODP_DMA_ADDR_MASK (~(ODP_READ_ALLOWED_BIT | ODP_WRITE_ALLOWED_BIT)) - #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING struct ib_umem_odp * From patchwork Wed Feb 5 14:40:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961192 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 AD128C02192 for ; Wed, 5 Feb 2025 14:41:52 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 3724E28000B; Wed, 5 Feb 2025 09:41:52 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 3212E28000A; Wed, 5 Feb 2025 09:41:52 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 1292928000B; Wed, 5 Feb 2025 09:41:52 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id DE8CF280002 for ; Wed, 5 Feb 2025 09:41:51 -0500 (EST) Received: from smtpin03.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 9D2BA80D9D for ; Wed, 5 Feb 2025 14:41:51 +0000 (UTC) X-FDA: 83086155222.03.036DB9B Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf05.hostedemail.com (Postfix) with ESMTP id F142410000D for ; Wed, 5 Feb 2025 14:41:49 +0000 (UTC) Authentication-Results: imf05.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=qQJafauM; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf05.hostedemail.com: domain of leon@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=leon@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738766510; a=rsa-sha256; cv=none; b=dB3WwSIQj9RnbudEB6fT/RLy2jOJWpP+rphi7t6V87QPGrTqLSfKM50KzY7edPdiWRNJMK zeAvfunj6oW2e0JyBrWbjWTfjFgBZpQ2ryt1QHuNzHJOwy2KZ2UQfnyqHzX0hmASOaGcdt m/8K7QPxzDpt9HLZzWtZUhOw2x/dG18= ARC-Authentication-Results: i=1; imf05.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=qQJafauM; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf05.hostedemail.com: domain of leon@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=leon@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1738766510; 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=gSErGTlTA53GGEQPs6cj4ixd5K7eQbDIyRsKKiIcfaE=; b=fq9NjhgEVe0iZTVV74k7WfYSe+KR6ukm4JUs+h03/sydYXOF1hzLmj0duzWivnzEsOSv5Q DnxJjccmViK5z9QFA1Too3vNzKbz5A9UhAmY9e4s96dNo5S1EJIhrzTNQGkMkh1S6xx6bi +sMjQeBH9Ki4j7WV8yVNwsgh9zXOyvc= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 3676D5C5530; Wed, 5 Feb 2025 14:41:09 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 00BD1C4CEE9; Wed, 5 Feb 2025 14:41:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766508; bh=eTHEWrFjx55o9+x73STU3unpNAcrCq86XGZTMQ1dxJo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qQJafauMEecsTo/PIEhKZ8zTDNOfBfMs1QeVeyVSzqyh6LjhOgJTEj7JdOxCrYXfb fad9cQwVea/XvMPh0UsRcMo/4KpwYQJbAtsTYOoSfrECr83lXzXjomFSjLBToGG+8H /HjQ5bGMSjUUVXS0kskKcANlRtY7pRY61S+jM5EsAd8wSvKQbv3Qg0znFGs51jiLWH A7fQCdCq1Fabq/1UMPb1GUdKBm9fBRDcT0pKRny4t46tHiZmevq7Qft6/aMWvV6JbP pNT/cwsucF1yIVDBW3T7epg+i67b3JkAaPXiab67qzK5C/sshVG1MCNwCOxKtyZgF7 CwCMtS0AbWkzw== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Leon Romanovsky , Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 13/17] RDMA/core: Convert UMEM ODP DMA mapping to caching IOVA and page linkage Date: Wed, 5 Feb 2025 16:40:33 +0200 Message-ID: <8a1b4d4f32a75faedb0f673173288ab048c0a839.1738765879.git.leonro@nvidia.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Server: rspam04 X-Rspamd-Queue-Id: F142410000D X-Stat-Signature: 88e6bzs1zf7edq1t3wi5ezw95jsfr5mu X-Rspam-User: X-HE-Tag: 1738766509-78518 X-HE-Meta: U2FsdGVkX1/P/+gwKLP+fd+epuv0OKfyIoD3q/9JJfdQp2IP/p29EaLaGuZvJsB7Pud0QzC2z60w/IQMDSqCxffFw2tIlu1dtss8QqL3/RJBQobnQdxiCJ8iwLWbJm3y7hQ2Z/eQmurX+jEappKQXy10PtdHL/CrbAEJThCqP3HnMixag8ccuOLL/j9g0KP00ezGdqAHZITZMlqHt49xfk1y/ZKL4SjA4s6mLAxpQfbuqTIr+r+DOXwHGCbkWw9NevmVbQ0PfUeAO8n8CjaPzQk2ks5UAE1SPRnhGy8id/AK6Lz8CJWYY90btT9SNg80hBwNjQ9QMhorogFr77cbo3/Lj1UeVSNqxnav4wYQui/Nuk3SKjEW8vfRp8dHSnYL1/toDe0vehZ//x9S//WCN5pg+Paf0gLa03ZBU/qrkvUKonS7YThWv57Pmirxqen+S3rvOk5wN9xP7Es24RX/vKn9Mec59bdXZGBGLKikg1fUzwZZ17VRRaoIk4Mpvsdj69cBwmn5EkxIOM1R1ZYi5WEIfGHry4YJK9hulUSsGtl4RVcZlx5Jh4Ved8Onf3SPYPM4o0xPkj2AGd7YtUqdCM7z3eVMkl8n/5ZHKyxAQkoSn7nTmrFljm1HF/WmLTLngZ/2zzhvuJ2yFM2N2/TFDgT0lbvopsCTT8pdHMNpqvKwO7fwsFPbvcMRKFqzOcERFPY2Ln10P9X6hNJfwU2nb5WXscrmwbIz7mU5mryTrTpy8BD9UvOEF7m20ymooRecS7VtG+2udzjA0Vw5Dg8leEjYXOPeK7fcyj7kN618m1q+kBDA/fm8v4Vuy5HYAelSKLqeP67HnJz4FPKy8o7Hnk3yhUfGdFIq/57CTnldBWcJKDdy667aCLg+loQEUlLAIAsxMYYYwDi+iBIpm89DLzlokg9ibX5GwGRufiHKoSjuIL1wKRzc+DT5OMb60FAiXo82QWoU5Zs4HYGxwJm b3GL3mNF 981TmDoB+0tJJq+z/+58qIDmBdqpkX0AzKzXDB9QyYfpPP0F6qTRPIf/kuapQjrZr8pCx2Zgo2cqoOIubnncYTAUSLedUKDXAwoSxRslkqJGTl9UjTWd04h2U+83V6Xcr3H0QUwRUwS4S9WoYCBiXypH3/RWzh6llTbEP14BV9MTMPfLL6BH+X4WCdLJ8hqqk27n/ 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 Reuse newly added DMA API to cache IOVA and only link/unlink pages in fast path for UMEM ODP flow. Signed-off-by: Leon Romanovsky --- drivers/infiniband/core/umem_odp.c | 104 ++++++--------------------- drivers/infiniband/hw/mlx5/mlx5_ib.h | 11 +-- drivers/infiniband/hw/mlx5/odp.c | 40 +++++++---- drivers/infiniband/hw/mlx5/umr.c | 12 +++- include/rdma/ib_umem_odp.h | 13 +--- 5 files changed, 69 insertions(+), 111 deletions(-) diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c index e1a5a567efb3..30cd8f353476 100644 --- a/drivers/infiniband/core/umem_odp.c +++ b/drivers/infiniband/core/umem_odp.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,7 @@ static inline int ib_init_umem_odp(struct ib_umem_odp *umem_odp, const struct mmu_interval_notifier_ops *ops) { + struct ib_device *dev = umem_odp->umem.ibdev; int ret; umem_odp->umem.is_odp = 1; @@ -59,7 +61,6 @@ static inline int ib_init_umem_odp(struct ib_umem_odp *umem_odp, size_t page_size = 1UL << umem_odp->page_shift; unsigned long start; unsigned long end; - size_t ndmas, npfns; start = ALIGN_DOWN(umem_odp->umem.address, page_size); if (check_add_overflow(umem_odp->umem.address, @@ -70,36 +71,23 @@ static inline int ib_init_umem_odp(struct ib_umem_odp *umem_odp, if (unlikely(end < page_size)) return -EOVERFLOW; - ndmas = (end - start) >> umem_odp->page_shift; - if (!ndmas) - return -EINVAL; - - npfns = (end - start) >> PAGE_SHIFT; - umem_odp->pfn_list = kvcalloc( - npfns, sizeof(*umem_odp->pfn_list), GFP_KERNEL); - if (!umem_odp->pfn_list) - return -ENOMEM; - - umem_odp->dma_list = kvcalloc( - ndmas, sizeof(*umem_odp->dma_list), GFP_KERNEL); - if (!umem_odp->dma_list) { - ret = -ENOMEM; - goto out_pfn_list; - } + ret = hmm_dma_map_alloc(dev->dma_device, &umem_odp->map, + (end - start) >> PAGE_SHIFT, + 1 << umem_odp->page_shift); + if (ret) + return ret; ret = mmu_interval_notifier_insert(&umem_odp->notifier, umem_odp->umem.owning_mm, start, end - start, ops); if (ret) - goto out_dma_list; + goto out_free_map; } return 0; -out_dma_list: - kvfree(umem_odp->dma_list); -out_pfn_list: - kvfree(umem_odp->pfn_list); +out_free_map: + hmm_dma_map_free(dev->dma_device, &umem_odp->map); return ret; } @@ -262,6 +250,8 @@ EXPORT_SYMBOL(ib_umem_odp_get); void ib_umem_odp_release(struct ib_umem_odp *umem_odp) { + struct ib_device *dev = umem_odp->umem.ibdev; + /* * Ensure that no more pages are mapped in the umem. * @@ -274,48 +264,17 @@ void ib_umem_odp_release(struct ib_umem_odp *umem_odp) ib_umem_end(umem_odp)); mutex_unlock(&umem_odp->umem_mutex); mmu_interval_notifier_remove(&umem_odp->notifier); - kvfree(umem_odp->dma_list); - kvfree(umem_odp->pfn_list); + hmm_dma_map_free(dev->dma_device, &umem_odp->map); } put_pid(umem_odp->tgid); kfree(umem_odp); } EXPORT_SYMBOL(ib_umem_odp_release); -/* - * Map for DMA and insert a single page into the on-demand paging page tables. - * - * @umem: the umem to insert the page to. - * @dma_index: index in the umem to add the dma to. - * @page: the page struct to map and add. - * @access_mask: access permissions needed for this page. - * - * The function returns -EFAULT if the DMA mapping operation fails. - * - */ -static int ib_umem_odp_map_dma_single_page( - struct ib_umem_odp *umem_odp, - unsigned int dma_index, - struct page *page) -{ - struct ib_device *dev = umem_odp->umem.ibdev; - dma_addr_t *dma_addr = &umem_odp->dma_list[dma_index]; - - *dma_addr = ib_dma_map_page(dev, page, 0, 1 << umem_odp->page_shift, - DMA_BIDIRECTIONAL); - if (ib_dma_mapping_error(dev, *dma_addr)) { - *dma_addr = 0; - return -EFAULT; - } - umem_odp->npages++; - return 0; -} - /** * ib_umem_odp_map_dma_and_lock - DMA map userspace memory in an ODP MR and lock it. * * Maps the range passed in the argument to DMA addresses. - * The DMA addresses of the mapped pages is updated in umem_odp->dma_list. * Upon success the ODP MR will be locked to let caller complete its device * page table update. * @@ -372,7 +331,7 @@ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *umem_odp, u64 user_virt, range.default_flags |= HMM_PFN_REQ_WRITE; } - range.hmm_pfns = &(umem_odp->pfn_list[pfn_start_idx]); + range.hmm_pfns = &(umem_odp->map.pfn_list[pfn_start_idx]); timeout = jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); retry: @@ -423,16 +382,6 @@ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *umem_odp, u64 user_virt, __func__, hmm_order, page_shift); break; } - - ret = ib_umem_odp_map_dma_single_page( - umem_odp, dma_index, - hmm_pfn_to_page(range.hmm_pfns[pfn_index])); - if (ret < 0) { - ibdev_dbg(umem_odp->umem.ibdev, - "ib_umem_odp_map_dma_single_page failed with error %d\n", ret); - break; - } - range.hmm_pfns[pfn_index] |= HMM_PFN_DMA_MAPPED; } /* upon success lock should stay on hold for the callee */ if (!ret) @@ -452,32 +401,23 @@ EXPORT_SYMBOL(ib_umem_odp_map_dma_and_lock); void ib_umem_odp_unmap_dma_pages(struct ib_umem_odp *umem_odp, u64 virt, u64 bound) { - dma_addr_t dma; - int idx; - u64 addr; struct ib_device *dev = umem_odp->umem.ibdev; + u64 addr; lockdep_assert_held(&umem_odp->umem_mutex); virt = max_t(u64, virt, ib_umem_start(umem_odp)); bound = min_t(u64, bound, ib_umem_end(umem_odp)); for (addr = virt; addr < bound; addr += BIT(umem_odp->page_shift)) { - unsigned long pfn_idx = (addr - ib_umem_start(umem_odp)) >> - PAGE_SHIFT; - struct page *page = - hmm_pfn_to_page(umem_odp->pfn_list[pfn_idx]); - - idx = (addr - ib_umem_start(umem_odp)) >> umem_odp->page_shift; - dma = umem_odp->dma_list[idx]; + u64 offset = addr - ib_umem_start(umem_odp); + size_t idx = offset >> umem_odp->page_shift; + unsigned long pfn = umem_odp->map.pfn_list[idx]; - if (!(umem_odp->pfn_list[pfn_idx] & HMM_PFN_VALID)) - goto clear; - if (!(umem_odp->pfn_list[pfn_idx] & HMM_PFN_DMA_MAPPED)) + if (!hmm_dma_unmap_pfn(dev->dma_device, &umem_odp->map, idx)) goto clear; - ib_dma_unmap_page(dev, dma, BIT(umem_odp->page_shift), - DMA_BIDIRECTIONAL); - if (umem_odp->pfn_list[pfn_idx] & HMM_PFN_WRITE) { + if (pfn & HMM_PFN_WRITE) { + struct page *page = hmm_pfn_to_page(pfn); struct page *head_page = compound_head(page); /* * set_page_dirty prefers being called with @@ -492,7 +432,7 @@ void ib_umem_odp_unmap_dma_pages(struct ib_umem_odp *umem_odp, u64 virt, } umem_odp->npages--; clear: - umem_odp->pfn_list[pfn_idx] &= ~HMM_PFN_FLAGS; + umem_odp->map.pfn_list[idx] &= ~HMM_PFN_FLAGS; } } EXPORT_SYMBOL(ib_umem_odp_unmap_dma_pages); diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index 53a06a7142ea..6ebbe39fa807 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h @@ -1451,8 +1451,8 @@ void mlx5_ib_odp_cleanup_one(struct mlx5_ib_dev *ibdev); int __init mlx5_ib_odp_init(void); void mlx5_ib_odp_cleanup(void); int mlx5_odp_init_mkey_cache(struct mlx5_ib_dev *dev); -void mlx5_odp_populate_xlt(void *xlt, size_t idx, size_t nentries, - struct mlx5_ib_mr *mr, int flags); +int mlx5_odp_populate_xlt(void *xlt, size_t idx, size_t nentries, + struct mlx5_ib_mr *mr, int flags); int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd, enum ib_uverbs_advise_mr_advice advice, @@ -1473,8 +1473,11 @@ static inline int mlx5_odp_init_mkey_cache(struct mlx5_ib_dev *dev) { return 0; } -static inline void mlx5_odp_populate_xlt(void *xlt, size_t idx, size_t nentries, - struct mlx5_ib_mr *mr, int flags) {} +static inline int mlx5_odp_populate_xlt(void *xlt, size_t idx, size_t nentries, + struct mlx5_ib_mr *mr, int flags) +{ + return -EOPNOTSUPP; +} static inline int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd, diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c index dcfdf644cfe2..89057faf3bf4 100644 --- a/drivers/infiniband/hw/mlx5/odp.c +++ b/drivers/infiniband/hw/mlx5/odp.c @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include "mlx5_ib.h" #include "cmd.h" @@ -159,40 +161,50 @@ static void populate_klm(struct mlx5_klm *pklm, size_t idx, size_t nentries, } } -static void populate_mtt(__be64 *pas, size_t idx, size_t nentries, - struct mlx5_ib_mr *mr, int flags) +static int populate_mtt(__be64 *pas, size_t start, size_t nentries, + struct mlx5_ib_mr *mr, int flags) { struct ib_umem_odp *odp = to_ib_umem_odp(mr->umem); bool downgrade = flags & MLX5_IB_UPD_XLT_DOWNGRADE; - unsigned long pfn; - dma_addr_t pa; + struct pci_p2pdma_map_state p2pdma_state = {}; + struct ib_device *dev = odp->umem.ibdev; size_t i; if (flags & MLX5_IB_UPD_XLT_ZAP) - return; + return 0; for (i = 0; i < nentries; i++) { - pfn = odp->pfn_list[idx + i]; + unsigned long pfn = odp->map.pfn_list[start + i]; + dma_addr_t dma_addr; + + pfn = odp->map.pfn_list[start + i]; if (!(pfn & HMM_PFN_VALID)) /* ODP initialization */ continue; - pa = odp->dma_list[idx + i]; - pa |= MLX5_IB_MTT_READ; + dma_addr = hmm_dma_map_pfn(dev->dma_device, &odp->map, + start + i, &p2pdma_state); + if (ib_dma_mapping_error(dev, dma_addr)) + return -EFAULT; + + dma_addr |= MLX5_IB_MTT_READ; if ((pfn & HMM_PFN_WRITE) && !downgrade) - pa |= MLX5_IB_MTT_WRITE; + dma_addr |= MLX5_IB_MTT_WRITE; - pas[i] = cpu_to_be64(pa); + pas[i] = cpu_to_be64(dma_addr); + odp->npages++; } + return 0; } -void mlx5_odp_populate_xlt(void *xlt, size_t idx, size_t nentries, - struct mlx5_ib_mr *mr, int flags) +int mlx5_odp_populate_xlt(void *xlt, size_t idx, size_t nentries, + struct mlx5_ib_mr *mr, int flags) { if (flags & MLX5_IB_UPD_XLT_INDIRECT) { populate_klm(xlt, idx, nentries, mr, flags); + return 0; } else { - populate_mtt(xlt, idx, nentries, mr, flags); + return populate_mtt(xlt, idx, nentries, mr, flags); } } @@ -302,7 +314,7 @@ static bool mlx5_ib_invalidate_range(struct mmu_interval_notifier *mni, * estimate the cost of another UMR vs. the cost of bigger * UMR. */ - if (umem_odp->pfn_list[idx] & HMM_PFN_VALID) { + if (umem_odp->map.pfn_list[idx] & HMM_PFN_VALID) { if (!in_block) { blk_start_idx = idx; in_block = 1; diff --git a/drivers/infiniband/hw/mlx5/umr.c b/drivers/infiniband/hw/mlx5/umr.c index 887fd6fa3ba9..d7fa94ab23cf 100644 --- a/drivers/infiniband/hw/mlx5/umr.c +++ b/drivers/infiniband/hw/mlx5/umr.c @@ -811,7 +811,17 @@ int mlx5r_umr_update_xlt(struct mlx5_ib_mr *mr, u64 idx, int npages, size_to_map = npages * desc_size; dma_sync_single_for_cpu(ddev, sg.addr, sg.length, DMA_TO_DEVICE); - mlx5_odp_populate_xlt(xlt, idx, npages, mr, flags); + /* + * npages is the maximum number of pages to map, but we + * can't guarantee that all pages are actually mapped. + * + * For example, if page is p2p of type which is not supported + * for mapping, the number of pages mapped will be less than + * requested. + */ + err = mlx5_odp_populate_xlt(xlt, idx, npages, mr, flags); + if (err) + return err; dma_sync_single_for_device(ddev, sg.addr, sg.length, DMA_TO_DEVICE); sg.length = ALIGN(size_to_map, MLX5_UMR_FLEX_ALIGNMENT); diff --git a/include/rdma/ib_umem_odp.h b/include/rdma/ib_umem_odp.h index a345c26a745d..2a24bf791c10 100644 --- a/include/rdma/ib_umem_odp.h +++ b/include/rdma/ib_umem_odp.h @@ -8,24 +8,17 @@ #include #include -#include +#include struct ib_umem_odp { struct ib_umem umem; struct mmu_interval_notifier notifier; struct pid *tgid; - /* An array of the pfns included in the on-demand paging umem. */ - unsigned long *pfn_list; + struct hmm_dma_map map; /* - * An array with DMA addresses mapped for pfns in pfn_list. - * The lower two bits designate access permissions. - * See ODP_READ_ALLOWED_BIT and ODP_WRITE_ALLOWED_BIT. - */ - dma_addr_t *dma_list; - /* - * The umem_mutex protects the page_list and dma_list fields of an ODP + * The umem_mutex protects the page_list field of an ODP * umem, allowing only a single thread to map/unmap pages. The mutex * also protects access to the mmu notifier counters. */ From patchwork Wed Feb 5 14:40:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961196 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 BA008C02194 for ; Wed, 5 Feb 2025 14:42:16 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 2D513280015; Wed, 5 Feb 2025 09:42:08 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 283E1280013; Wed, 5 Feb 2025 09:42:08 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 0E060280015; Wed, 5 Feb 2025 09:42:08 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id DECBA280013 for ; Wed, 5 Feb 2025 09:42:07 -0500 (EST) Received: from smtpin03.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay10.hostedemail.com (Postfix) with ESMTP id 9E889C0D22 for ; Wed, 5 Feb 2025 14:42:07 +0000 (UTC) X-FDA: 83086155894.03.1DA3F87 Received: from nyc.source.kernel.org (nyc.source.kernel.org [147.75.193.91]) by imf19.hostedemail.com (Postfix) with ESMTP id 0765A1A0006 for ; Wed, 5 Feb 2025 14:42:05 +0000 (UTC) Authentication-Results: imf19.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=W2YNA18v; spf=pass (imf19.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=1738766526; 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=8jc4NUQPjjS4VfvHj2jV5GAgx18ShSuYw6TOIM4M5Bc=; b=IlP5TAOV2rsKR3fIw0e+eDNRSj+OwN8Flu9/XC+1Vu038dBl/mNdwFtj8YmIOaDQSr06Yk /id6+anp/46OPacs7vLDGNq6PP0c3FaajRE0j/XQAn2DnVIzoNDMhfjnj4UkiEV43/jKHI EqoFo87VsE2QSmUAkz2hvwaQYfU25lE= ARC-Authentication-Results: i=1; imf19.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=W2YNA18v; spf=pass (imf19.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-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738766526; a=rsa-sha256; cv=none; b=c1a9bRi5uF320jkJHLKUJxnDIyZ64WkhacmeSx/iSs52d5ELN0GZgtQzmZ9qRc0efFeyAa eiBsgUYXSJAnJKT5qTFU/pHbDR43Rq3uLk0ipgA5iRrBaBJnkaA1HYImSIxqnJfWTkofS3 7WBsGgjENLX8knpejzU38qDfSbofcXE= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 6C4A9A436C4; Wed, 5 Feb 2025 14:40:19 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6BEBAC4CED1; Wed, 5 Feb 2025 14:42:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766525; bh=7aNBsgnJ1xpYJupIDdeW59JsJ73w9EGqwdcut5LVDS4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=W2YNA18v52GskOrMKLkrTwzfQn8Km0PjGIUu87kMojGGjoog/10G95TBZ6vnkCJOA YBN2VL9nccEhcQB+VjXd8HFCxCAmenqSYB1f1SLAze41y9IxYfGcUyvzovhFkucE4f p08Hgr2aFu7TPrkMKUHPLcHRhBWfTuIFNxLXuqn9BzHXEN+JSM2GV9t331JEbLcVO1 GSPh9+fHX0PFZ54Xj0VKJbbudJl6ZriCoRRfT0mEAv2qtfV12c5C2YyCHBJpXp/Avp 6rDEaptuPvVVvZW3SFE4g/gPs6SQsVGFwUV+bcIiAAsYiTd1k+zUacXb4F76FSGdZJ rbwrAoMwir3bw== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Leon Romanovsky , Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 14/17] RDMA/umem: Separate implicit ODP initialization from explicit ODP Date: Wed, 5 Feb 2025 16:40:34 +0200 Message-ID: X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Server: rspam05 X-Rspamd-Queue-Id: 0765A1A0006 X-Stat-Signature: w773piwwwfo91drthuqkb68o4641k6i4 X-Rspam-User: X-HE-Tag: 1738766525-200982 X-HE-Meta: U2FsdGVkX19btUFSku7Uoig+P+EkcorrR2tVds4EeKQCd584P4bYKiubALmc3YctYM1qxX3sUSdesCjAUXOTkhURvG83FRGu+PFEhOB/2aY+ZKs57xBIOsf/YzSxi6j0FWVXSf72xi9wvAUsaQ2yfAPlI3odopb6uffNH276X58h0dtjbu3eeuUiCdCuohVd2ePisCYGLst0ESFm0yy42p03fhsXwGp6vys0gQq7p+TQ4/KOaBb9FmSEJarWPJeF/GkKneT0qvQGKBpPaCcsWm6tOxY84VtstY+Gbf/WRfvxmyiBRuYyMggXjLyPMF92vMxfb6RaHkZr3aQrLjVv49zKD+N1WZx31X9SMDM5FZ1HL1jw9wfFkdycjadS7E0buv6MsWntxE08d7N+tpOM3MqvwIOoAwngLPzJnvnV8JQ5OBArOj+bQrgWOMwoCnf3w24Wf/MIH+uzrcQk5KeJRq0G2JP2/CifJJepz6ePB5JeDjIH0BSUvGLmfLXhQo0tVsVEMUp4M6yjrS372BnABQ2BembP/F5B2jH28uzKzZIgcTwuI5WRT/96S7thaEi76OFyZYtUpndCJGAVwkBE5HbitZ2m0zyAb2PQ56Bnj6EVoXpsaWWGvEWEHYhuo1MwTBiJOyduehCysLESTK7PkCS1o6EVkzDeLWfWl1VVaKWLnrLrWLKpzFTUOU3u5WmMJb8I4Qbza8l1GMHNdjy5NOq8iQO0icfsSqXdowQV+cAUXfpDLqeZYGJUXdGzq/TGRjTKQMGlMME64ZQAPL39NqiWhoBIr7/6yU6T9CbQ7opzmLKESBjSn3Z7Ux/5oK290P6YDBwQ03Cc3cKa64A2ZN/uqGRrrd0IJAHvBjFG2GhBX3cryoaxI10SBrOlUM9aBZWl2S1ob01KP/JZlGweMXDG5Qtg5pBpdw3H7S+PwlmDPTnfCE0dqVFaeasyHW5Dxai/dfaDZwKofd/DdNt 4ncOAp11 bavxPlVZGxYQpGqDNjSYZlxHWLLj700sTTc+t8n4d/gUVB4K430ccN/FdiiCOebDhVQfP+pEb4OxS+6jaj2xiEI3y/PFKTIecOX5Ot/p+Wz03GnzlnjBAMFhl/lUFxdxmTRoWUVkynfgiWzi3XSK96mQc8l0dUwS5WZywwIgwMq6fZLFBAVWYqKM0WlEqaW60U7+z 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 Create separate functions for the implicit ODP initialization which is different from the explicit ODP initialization. Signed-off-by: Leon Romanovsky --- drivers/infiniband/core/umem_odp.c | 91 +++++++++++++++--------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c index 30cd8f353476..51d518989914 100644 --- a/drivers/infiniband/core/umem_odp.c +++ b/drivers/infiniband/core/umem_odp.c @@ -48,41 +48,44 @@ #include "uverbs.h" -static inline int ib_init_umem_odp(struct ib_umem_odp *umem_odp, - const struct mmu_interval_notifier_ops *ops) +static void ib_init_umem_implicit_odp(struct ib_umem_odp *umem_odp) +{ + umem_odp->is_implicit_odp = 1; + umem_odp->umem.is_odp = 1; + mutex_init(&umem_odp->umem_mutex); +} + +static int ib_init_umem_odp(struct ib_umem_odp *umem_odp, + const struct mmu_interval_notifier_ops *ops) { struct ib_device *dev = umem_odp->umem.ibdev; + size_t page_size = 1UL << umem_odp->page_shift; + unsigned long start; + unsigned long end; int ret; umem_odp->umem.is_odp = 1; mutex_init(&umem_odp->umem_mutex); - if (!umem_odp->is_implicit_odp) { - size_t page_size = 1UL << umem_odp->page_shift; - unsigned long start; - unsigned long end; - - start = ALIGN_DOWN(umem_odp->umem.address, page_size); - if (check_add_overflow(umem_odp->umem.address, - (unsigned long)umem_odp->umem.length, - &end)) - return -EOVERFLOW; - end = ALIGN(end, page_size); - if (unlikely(end < page_size)) - return -EOVERFLOW; - - ret = hmm_dma_map_alloc(dev->dma_device, &umem_odp->map, - (end - start) >> PAGE_SHIFT, - 1 << umem_odp->page_shift); - if (ret) - return ret; - - ret = mmu_interval_notifier_insert(&umem_odp->notifier, - umem_odp->umem.owning_mm, - start, end - start, ops); - if (ret) - goto out_free_map; - } + start = ALIGN_DOWN(umem_odp->umem.address, page_size); + if (check_add_overflow(umem_odp->umem.address, + (unsigned long)umem_odp->umem.length, &end)) + return -EOVERFLOW; + end = ALIGN(end, page_size); + if (unlikely(end < page_size)) + return -EOVERFLOW; + + ret = hmm_dma_map_alloc(dev->dma_device, &umem_odp->map, + (end - start) >> PAGE_SHIFT, + 1 << umem_odp->page_shift); + if (ret) + return ret; + + ret = mmu_interval_notifier_insert(&umem_odp->notifier, + umem_odp->umem.owning_mm, start, + end - start, ops); + if (ret) + goto out_free_map; return 0; @@ -106,7 +109,6 @@ struct ib_umem_odp *ib_umem_odp_alloc_implicit(struct ib_device *device, { struct ib_umem *umem; struct ib_umem_odp *umem_odp; - int ret; if (access & IB_ACCESS_HUGETLB) return ERR_PTR(-EINVAL); @@ -118,16 +120,10 @@ struct ib_umem_odp *ib_umem_odp_alloc_implicit(struct ib_device *device, umem->ibdev = device; umem->writable = ib_access_writable(access); umem->owning_mm = current->mm; - umem_odp->is_implicit_odp = 1; umem_odp->page_shift = PAGE_SHIFT; umem_odp->tgid = get_task_pid(current->group_leader, PIDTYPE_PID); - ret = ib_init_umem_odp(umem_odp, NULL); - if (ret) { - put_pid(umem_odp->tgid); - kfree(umem_odp); - return ERR_PTR(ret); - } + ib_init_umem_implicit_odp(umem_odp); return umem_odp; } EXPORT_SYMBOL(ib_umem_odp_alloc_implicit); @@ -248,7 +244,7 @@ struct ib_umem_odp *ib_umem_odp_get(struct ib_device *device, } EXPORT_SYMBOL(ib_umem_odp_get); -void ib_umem_odp_release(struct ib_umem_odp *umem_odp) +static void ib_umem_odp_free(struct ib_umem_odp *umem_odp) { struct ib_device *dev = umem_odp->umem.ibdev; @@ -258,14 +254,19 @@ void ib_umem_odp_release(struct ib_umem_odp *umem_odp) * It is the driver's responsibility to ensure, before calling us, * that the hardware will not attempt to access the MR any more. */ - if (!umem_odp->is_implicit_odp) { - mutex_lock(&umem_odp->umem_mutex); - ib_umem_odp_unmap_dma_pages(umem_odp, ib_umem_start(umem_odp), - ib_umem_end(umem_odp)); - mutex_unlock(&umem_odp->umem_mutex); - mmu_interval_notifier_remove(&umem_odp->notifier); - hmm_dma_map_free(dev->dma_device, &umem_odp->map); - } + mutex_lock(&umem_odp->umem_mutex); + ib_umem_odp_unmap_dma_pages(umem_odp, ib_umem_start(umem_odp), + ib_umem_end(umem_odp)); + mutex_unlock(&umem_odp->umem_mutex); + mmu_interval_notifier_remove(&umem_odp->notifier); + hmm_dma_map_free(dev->dma_device, &umem_odp->map); +} + +void ib_umem_odp_release(struct ib_umem_odp *umem_odp) +{ + if (!umem_odp->is_implicit_odp) + ib_umem_odp_free(umem_odp); + put_pid(umem_odp->tgid); kfree(umem_odp); } From patchwork Wed Feb 5 14:40:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961193 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 345D5C02192 for ; Wed, 5 Feb 2025 14:41:58 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 4A94428000C; Wed, 5 Feb 2025 09:41:56 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 4594628000A; Wed, 5 Feb 2025 09:41:56 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 283E128000C; Wed, 5 Feb 2025 09:41:56 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 0110728000A for ; Wed, 5 Feb 2025 09:41:55 -0500 (EST) Received: from smtpin09.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id B7C7FA0D1A for ; Wed, 5 Feb 2025 14:41:55 +0000 (UTC) X-FDA: 83086155390.09.AAB5B8D Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf24.hostedemail.com (Postfix) with ESMTP id 15EF7180008 for ; Wed, 5 Feb 2025 14:41:53 +0000 (UTC) Authentication-Results: imf24.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=um2dctUx; spf=pass (imf24.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=1738766514; 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=zRZAQno64qm5mHMPf2OxgXQBGimvgNmJmfzClWy9LOI=; b=HGtGeL/Aav0ujVIQikxsYBdp8RZrhiVirCObkCuHlxpO40EubffNcpQQxLs3O22b3LPl3i SqRZd6Z4QZhRIa9ePpoixcXkwl1jXOAtIzav6vNmFKF6kLuu0uXVRkhzdlVFsuPdZM76pd x7DYujtDDbJUjlWooDFXyJQ7KAxAUcg= ARC-Authentication-Results: i=1; imf24.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=um2dctUx; spf=pass (imf24.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=1738766514; a=rsa-sha256; cv=none; b=Fa4blyqfcqAVqesNI8jG7tf9lRJ6YFinaBe1RHkl8337Wzc4r7IillVlpQV2neE8z363UL P9YEM4Ps+1+bY/FTQz/ejYpfJw/TGOvlvu3p92V//OevI/UG+1knWwy+tIl4fbEbSa2mcE QBtKFekTzg37iQQRKWF/aCWGJyca4e4= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 7F68D5C6CAE; Wed, 5 Feb 2025 14:41:13 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1E0CDC4CEE7; Wed, 5 Feb 2025 14:41:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766512; bh=cPGoCRHCCVl8re/kt65HxtLt4epPmaW5gOofAE9+FRg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=um2dctUx2vLjVcM6gPb79wMh98dfTlJc5PeHhD+85EBj/6BY/8QyJsIYMc3MJlLBP //tX5vquXGO61O38VjlAJoqLeRuC3knLNfadfIM+Uz+ZAZgOutZhZ5BJOfO74ewuOa //H2CVjhPTqJYCFx1toDPSWaselapAhpHYsrZbdRVLCSK3y+7L+NrXiC9U+FQyhrj5 Cy5ma0GL+Om5D3WQRF6IF3rlu2ioHmv6RRv8rVql5zyd1sAZjUQEqVdyTuEe1TTTLX Do8bkXjbEkjOKnBfVteB0G+LY5wjLFDh7UX8lHHwgC5Xpk7bDuYaK8OPpA8DKkFum2 Q9YEpln2k43MA== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Leon Romanovsky , Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 15/17] vfio/mlx5: Explicitly use number of pages instead of allocated length Date: Wed, 5 Feb 2025 16:40:35 +0200 Message-ID: X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Server: rspam05 X-Rspamd-Queue-Id: 15EF7180008 X-Stat-Signature: sfnay4nt8ocemj6zyqgato8kcsqukuta X-Rspam-User: X-HE-Tag: 1738766513-672968 X-HE-Meta: U2FsdGVkX1/+4vPSrWawNqCoq+PiggL9KwOkB5lJV0+KdQOMlvuEcfXrvWiQEW2b2n22qB778ePICMDPlsBe2jqX6AyyFMyTmkNskDst6HQCVA0Eg60fog8F8ThDGdjRBiADN2of8YhgIhoc33f5qE8+h+bRg2/R8BQUXwdc0tr8fxEopevWVF9baqUgw+HVHDGOLSUNMoW7IFebk+tUVB3zpqG4dZ3Dler/YQAlhQbtTO8kPgBOLqwpHsSpihyibpSEb6WSCV2jduPwsSGdg/GxPiV2UTOS831qkgay0cjnd9wPcP25xwXb1/r0UR+5ykBiZX6APJ8wEy2K/p0rSJQvJ+5zdY5Z/vk5TpgCYRwm11qptDg35cHojcG87wF7L1Mh1e4j7NcMWwEHRYBNGiKfVdfBToI/oFsUsW+batWB1eWdMBN1zPliy8IOKAbVwOH4zmKaFPDfGrvHPUlQFZGHMONIA3qyDgKESOaK6wROl9UkEzgbE8LvjGdpSalJVbf8XwdEAxmG8jFDIan/WPMecCgx1Jk9RR+6Mphb4q52pwW/rjoZUPwb9ov1s6GfECBRDAhO0ZfHodsQ8C6CjIc0Xh0b6R4NXx1h/9297gqdxygNhjdeL0NaheFDiskahfTeoQqwZIlLwXf9IT34V3+nzaYEjaBH8LU/6Cg24JH2K3eSz9JPdkRT//pKVqFVa6/DpGJtZX/7u6GbDfDkHIR0UsvG9FPv1ZLtTDASzvSg0vCVHbaWj9yGSHybgPEnRG0m+0Xx9ck5GQOboI3BwM4bQO8GruZW1NdZggg9g4jt7H2hRc9Lvc+juACOAWggAe8dUfVDJwzgk7XJvZGAhNxWELAb0bTdeMEcGupL2Ly34he5GdTFmyuCwrBBmakNqzULvxTtzLCAdvyg/lClSO1pgUXiNY8GxwMuJw/d+6hzVqF2h5Jlis9NmvTtgEwIyf3vM+tug9J/2vE5po6 /v9HzQKa eGTLiXWD/MpuvCrpWgGNQCofG3NqGj9tS1MEgydNNVaQLlTNgttq++6BEt/4OlSgl0pXghivvJIhxs7PBVN+zOIkWMDGkLrwb/gP7qwDZ+1XbtSIB0i1dQVzNup2p06i4DOUp65IX3+FXlq60es2AeIJIzGc8TgdXxp7q/zll2VTAqiIVJgcZTThqKBTpomT23QrF 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 allocated_length is a multiple of page size and number of pages, so let's change the functions to accept number of pages. It opens us a venue to combine receive and send paths together with code readability improvement. Signed-off-by: Leon Romanovsky --- drivers/vfio/pci/mlx5/cmd.c | 32 ++++++++++----------- drivers/vfio/pci/mlx5/cmd.h | 10 +++---- drivers/vfio/pci/mlx5/main.c | 56 +++++++++++++++++++++++------------- 3 files changed, 57 insertions(+), 41 deletions(-) diff --git a/drivers/vfio/pci/mlx5/cmd.c b/drivers/vfio/pci/mlx5/cmd.c index 11eda6b207f1..377dee7765fb 100644 --- a/drivers/vfio/pci/mlx5/cmd.c +++ b/drivers/vfio/pci/mlx5/cmd.c @@ -318,8 +318,7 @@ static int _create_mkey(struct mlx5_core_dev *mdev, u32 pdn, struct mlx5_vhca_recv_buf *recv_buf, u32 *mkey) { - size_t npages = buf ? DIV_ROUND_UP(buf->allocated_length, PAGE_SIZE) : - recv_buf->npages; + size_t npages = buf ? buf->npages : recv_buf->npages; int err = 0, inlen; __be64 *mtt; void *mkc; @@ -375,7 +374,7 @@ static int mlx5vf_dma_data_buffer(struct mlx5_vhca_data_buffer *buf) if (mvdev->mdev_detach) return -ENOTCONN; - if (buf->dmaed || !buf->allocated_length) + if (buf->dmaed || !buf->npages) return -EINVAL; ret = dma_map_sgtable(mdev->device, &buf->table.sgt, buf->dma_dir, 0); @@ -445,7 +444,7 @@ static int mlx5vf_add_migration_pages(struct mlx5_vhca_data_buffer *buf, if (ret) goto err_append; - buf->allocated_length += filled * PAGE_SIZE; + buf->npages += filled; /* clean input for another bulk allocation */ memset(page_list, 0, filled * sizeof(*page_list)); to_fill = min_t(unsigned int, to_alloc, @@ -464,8 +463,7 @@ static int mlx5vf_add_migration_pages(struct mlx5_vhca_data_buffer *buf, } struct mlx5_vhca_data_buffer * -mlx5vf_alloc_data_buffer(struct mlx5_vf_migration_file *migf, - size_t length, +mlx5vf_alloc_data_buffer(struct mlx5_vf_migration_file *migf, u32 npages, enum dma_data_direction dma_dir) { struct mlx5_vhca_data_buffer *buf; @@ -477,9 +475,8 @@ mlx5vf_alloc_data_buffer(struct mlx5_vf_migration_file *migf, buf->dma_dir = dma_dir; buf->migf = migf; - if (length) { - ret = mlx5vf_add_migration_pages(buf, - DIV_ROUND_UP_ULL(length, PAGE_SIZE)); + if (npages) { + ret = mlx5vf_add_migration_pages(buf, npages); if (ret) goto end; @@ -505,8 +502,8 @@ void mlx5vf_put_data_buffer(struct mlx5_vhca_data_buffer *buf) } struct mlx5_vhca_data_buffer * -mlx5vf_get_data_buffer(struct mlx5_vf_migration_file *migf, - size_t length, enum dma_data_direction dma_dir) +mlx5vf_get_data_buffer(struct mlx5_vf_migration_file *migf, u32 npages, + enum dma_data_direction dma_dir) { struct mlx5_vhca_data_buffer *buf, *temp_buf; struct list_head free_list; @@ -521,7 +518,7 @@ mlx5vf_get_data_buffer(struct mlx5_vf_migration_file *migf, list_for_each_entry_safe(buf, temp_buf, &migf->avail_list, buf_elm) { if (buf->dma_dir == dma_dir) { list_del_init(&buf->buf_elm); - if (buf->allocated_length >= length) { + if (buf->npages >= npages) { spin_unlock_irq(&migf->list_lock); goto found; } @@ -535,7 +532,7 @@ mlx5vf_get_data_buffer(struct mlx5_vf_migration_file *migf, } } spin_unlock_irq(&migf->list_lock); - buf = mlx5vf_alloc_data_buffer(migf, length, dma_dir); + buf = mlx5vf_alloc_data_buffer(migf, npages, dma_dir); found: while ((temp_buf = list_first_entry_or_null(&free_list, @@ -716,7 +713,7 @@ int mlx5vf_cmd_save_vhca_state(struct mlx5vf_pci_core_device *mvdev, MLX5_SET(save_vhca_state_in, in, op_mod, 0); MLX5_SET(save_vhca_state_in, in, vhca_id, mvdev->vhca_id); MLX5_SET(save_vhca_state_in, in, mkey, buf->mkey); - MLX5_SET(save_vhca_state_in, in, size, buf->allocated_length); + MLX5_SET(save_vhca_state_in, in, size, buf->npages * PAGE_SIZE); MLX5_SET(save_vhca_state_in, in, incremental, inc); MLX5_SET(save_vhca_state_in, in, set_track, track); @@ -738,8 +735,11 @@ int mlx5vf_cmd_save_vhca_state(struct mlx5vf_pci_core_device *mvdev, } if (!header_buf) { - header_buf = mlx5vf_get_data_buffer(migf, - sizeof(struct mlx5_vf_migration_header), DMA_NONE); + header_buf = mlx5vf_get_data_buffer( + migf, + DIV_ROUND_UP(sizeof(struct mlx5_vf_migration_header), + PAGE_SIZE), + DMA_NONE); if (IS_ERR(header_buf)) { err = PTR_ERR(header_buf); goto err_free; diff --git a/drivers/vfio/pci/mlx5/cmd.h b/drivers/vfio/pci/mlx5/cmd.h index df421dc6de04..7d4a833b6900 100644 --- a/drivers/vfio/pci/mlx5/cmd.h +++ b/drivers/vfio/pci/mlx5/cmd.h @@ -56,7 +56,7 @@ struct mlx5_vhca_data_buffer { struct sg_append_table table; loff_t start_pos; u64 length; - u64 allocated_length; + u32 npages; u32 mkey; enum dma_data_direction dma_dir; u8 dmaed:1; @@ -217,12 +217,12 @@ int mlx5vf_cmd_alloc_pd(struct mlx5_vf_migration_file *migf); void mlx5vf_cmd_dealloc_pd(struct mlx5_vf_migration_file *migf); void mlx5fv_cmd_clean_migf_resources(struct mlx5_vf_migration_file *migf); struct mlx5_vhca_data_buffer * -mlx5vf_alloc_data_buffer(struct mlx5_vf_migration_file *migf, - size_t length, enum dma_data_direction dma_dir); +mlx5vf_alloc_data_buffer(struct mlx5_vf_migration_file *migf, u32 npages, + enum dma_data_direction dma_dir); void mlx5vf_free_data_buffer(struct mlx5_vhca_data_buffer *buf); struct mlx5_vhca_data_buffer * -mlx5vf_get_data_buffer(struct mlx5_vf_migration_file *migf, - size_t length, enum dma_data_direction dma_dir); +mlx5vf_get_data_buffer(struct mlx5_vf_migration_file *migf, u32 npages, + enum dma_data_direction dma_dir); void mlx5vf_put_data_buffer(struct mlx5_vhca_data_buffer *buf); struct page *mlx5vf_get_migration_page(struct mlx5_vhca_data_buffer *buf, unsigned long offset); diff --git a/drivers/vfio/pci/mlx5/main.c b/drivers/vfio/pci/mlx5/main.c index 709543e7eb04..bc0f468f741b 100644 --- a/drivers/vfio/pci/mlx5/main.c +++ b/drivers/vfio/pci/mlx5/main.c @@ -308,6 +308,7 @@ static struct mlx5_vhca_data_buffer * mlx5vf_mig_file_get_stop_copy_buf(struct mlx5_vf_migration_file *migf, u8 index, size_t required_length) { + u32 npages = DIV_ROUND_UP(required_length, PAGE_SIZE); struct mlx5_vhca_data_buffer *buf = migf->buf[index]; u8 chunk_num; @@ -315,12 +316,11 @@ mlx5vf_mig_file_get_stop_copy_buf(struct mlx5_vf_migration_file *migf, chunk_num = buf->stop_copy_chunk_num; buf->migf->buf[index] = NULL; /* Checking whether the pre-allocated buffer can fit */ - if (buf->allocated_length >= required_length) + if (buf->npages >= npages) return buf; mlx5vf_put_data_buffer(buf); - buf = mlx5vf_get_data_buffer(buf->migf, required_length, - DMA_FROM_DEVICE); + buf = mlx5vf_get_data_buffer(buf->migf, npages, DMA_FROM_DEVICE); if (IS_ERR(buf)) return buf; @@ -373,7 +373,8 @@ static int mlx5vf_add_stop_copy_header(struct mlx5_vf_migration_file *migf, u8 *to_buff; int ret; - header_buf = mlx5vf_get_data_buffer(migf, size, DMA_NONE); + header_buf = mlx5vf_get_data_buffer(migf, DIV_ROUND_UP(size, PAGE_SIZE), + DMA_NONE); if (IS_ERR(header_buf)) return PTR_ERR(header_buf); @@ -388,7 +389,7 @@ static int mlx5vf_add_stop_copy_header(struct mlx5_vf_migration_file *migf, to_buff = kmap_local_page(page); memcpy(to_buff, &header, sizeof(header)); header_buf->length = sizeof(header); - data.stop_copy_size = cpu_to_le64(migf->buf[0]->allocated_length); + data.stop_copy_size = cpu_to_le64(migf->buf[0]->npages * PAGE_SIZE); memcpy(to_buff + sizeof(header), &data, sizeof(data)); header_buf->length += sizeof(data); kunmap_local(to_buff); @@ -437,15 +438,20 @@ static int mlx5vf_prep_stop_copy(struct mlx5vf_pci_core_device *mvdev, num_chunks = mvdev->chunk_mode ? MAX_NUM_CHUNKS : 1; for (i = 0; i < num_chunks; i++) { - buf = mlx5vf_get_data_buffer(migf, inc_state_size, DMA_FROM_DEVICE); + buf = mlx5vf_get_data_buffer( + migf, DIV_ROUND_UP(inc_state_size, PAGE_SIZE), + DMA_FROM_DEVICE); if (IS_ERR(buf)) { ret = PTR_ERR(buf); goto err; } migf->buf[i] = buf; - buf = mlx5vf_get_data_buffer(migf, - sizeof(struct mlx5_vf_migration_header), DMA_NONE); + buf = mlx5vf_get_data_buffer( + migf, + DIV_ROUND_UP(sizeof(struct mlx5_vf_migration_header), + PAGE_SIZE), + DMA_NONE); if (IS_ERR(buf)) { ret = PTR_ERR(buf); goto err; @@ -553,7 +559,8 @@ static long mlx5vf_precopy_ioctl(struct file *filp, unsigned int cmd, * We finished transferring the current state and the device has a * dirty state, save a new state to be ready for. */ - buf = mlx5vf_get_data_buffer(migf, inc_length, DMA_FROM_DEVICE); + buf = mlx5vf_get_data_buffer(migf, DIV_ROUND_UP(inc_length, PAGE_SIZE), + DMA_FROM_DEVICE); if (IS_ERR(buf)) { ret = PTR_ERR(buf); mlx5vf_mark_err(migf); @@ -675,8 +682,8 @@ mlx5vf_pci_save_device_data(struct mlx5vf_pci_core_device *mvdev, bool track) if (track) { /* leave the allocated buffer ready for the stop-copy phase */ - buf = mlx5vf_alloc_data_buffer(migf, - migf->buf[0]->allocated_length, DMA_FROM_DEVICE); + buf = mlx5vf_alloc_data_buffer(migf, migf->buf[0]->npages, + DMA_FROM_DEVICE); if (IS_ERR(buf)) { ret = PTR_ERR(buf); goto out_pd; @@ -917,11 +924,14 @@ static ssize_t mlx5vf_resume_write(struct file *filp, const char __user *buf, goto out_unlock; break; case MLX5_VF_LOAD_STATE_PREP_HEADER_DATA: - if (vhca_buf_header->allocated_length < migf->record_size) { + { + u32 npages = DIV_ROUND_UP(migf->record_size, PAGE_SIZE); + + if (vhca_buf_header->npages < npages) { mlx5vf_free_data_buffer(vhca_buf_header); - migf->buf_header[0] = mlx5vf_alloc_data_buffer(migf, - migf->record_size, DMA_NONE); + migf->buf_header[0] = mlx5vf_alloc_data_buffer( + migf, npages, DMA_NONE); if (IS_ERR(migf->buf_header[0])) { ret = PTR_ERR(migf->buf_header[0]); migf->buf_header[0] = NULL; @@ -934,6 +944,7 @@ static ssize_t mlx5vf_resume_write(struct file *filp, const char __user *buf, vhca_buf_header->start_pos = migf->max_pos; migf->load_state = MLX5_VF_LOAD_STATE_READ_HEADER_DATA; break; + } case MLX5_VF_LOAD_STATE_READ_HEADER_DATA: ret = mlx5vf_resume_read_header_data(migf, vhca_buf_header, &buf, &len, pos, &done); @@ -944,12 +955,13 @@ static ssize_t mlx5vf_resume_write(struct file *filp, const char __user *buf, { u64 size = max(migf->record_size, migf->stop_copy_prep_size); + u32 npages = DIV_ROUND_UP(size, PAGE_SIZE); - if (vhca_buf->allocated_length < size) { + if (vhca_buf->npages < npages) { mlx5vf_free_data_buffer(vhca_buf); - migf->buf[0] = mlx5vf_alloc_data_buffer(migf, - size, DMA_TO_DEVICE); + migf->buf[0] = mlx5vf_alloc_data_buffer( + migf, npages, DMA_TO_DEVICE); if (IS_ERR(migf->buf[0])) { ret = PTR_ERR(migf->buf[0]); migf->buf[0] = NULL; @@ -1037,8 +1049,11 @@ mlx5vf_pci_resume_device_data(struct mlx5vf_pci_core_device *mvdev) } migf->buf[0] = buf; - buf = mlx5vf_alloc_data_buffer(migf, - sizeof(struct mlx5_vf_migration_header), DMA_NONE); + buf = mlx5vf_alloc_data_buffer( + migf, + DIV_ROUND_UP(sizeof(struct mlx5_vf_migration_header), + PAGE_SIZE), + DMA_NONE); if (IS_ERR(buf)) { ret = PTR_ERR(buf); goto out_buf; @@ -1148,7 +1163,8 @@ mlx5vf_pci_step_device_state_locked(struct mlx5vf_pci_core_device *mvdev, MLX5VF_QUERY_INC | MLX5VF_QUERY_CLEANUP); if (ret) return ERR_PTR(ret); - buf = mlx5vf_get_data_buffer(migf, size, DMA_FROM_DEVICE); + buf = mlx5vf_get_data_buffer(migf, + DIV_ROUND_UP(size, PAGE_SIZE), DMA_FROM_DEVICE); if (IS_ERR(buf)) return ERR_CAST(buf); /* pre_copy cleanup */ From patchwork Wed Feb 5 14:40:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961194 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 628B1C02194 for ; Wed, 5 Feb 2025 14:42:04 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 0B1A528000E; Wed, 5 Feb 2025 09:42:00 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 03BF028000A; Wed, 5 Feb 2025 09:41:59 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id DD20B28000E; Wed, 5 Feb 2025 09:41:59 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id AE89F28000A for ; Wed, 5 Feb 2025 09:41:59 -0500 (EST) Received: from smtpin11.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 719D4140D36 for ; Wed, 5 Feb 2025 14:41:59 +0000 (UTC) X-FDA: 83086155558.11.848E73C Received: from nyc.source.kernel.org (nyc.source.kernel.org [147.75.193.91]) by imf04.hostedemail.com (Postfix) with ESMTP id DA7674000D for ; Wed, 5 Feb 2025 14:41:57 +0000 (UTC) Authentication-Results: imf04.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=pU2Tbd99; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf04.hostedemail.com: domain of leon@kernel.org designates 147.75.193.91 as permitted sender) smtp.mailfrom=leon@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738766517; a=rsa-sha256; cv=none; b=p1PLo/9/wyDXAuJoJXoZn6bJvL69V3bLbrcHYHzwiSdqJe5m1fud53+F1kvJnM2bS1CSUT Nj0HQOdMlMGRgv7fLsrblYCWd/d5aVd6DeCElJTQM1OPgTaKJmMDXdaL0Hl1+MsKbo9yiT J8l6uKVgvnj05KDv49BwOolyh7aZcW0= ARC-Authentication-Results: i=1; imf04.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=pU2Tbd99; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf04.hostedemail.com: domain of leon@kernel.org designates 147.75.193.91 as permitted sender) smtp.mailfrom=leon@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1738766517; 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=fBrqrw4XKTgkmKK/QVXz21CmReVqQ8hw2SSZ065TBk0=; b=HdgKxlzX3pBdVkrkZz4A4VvdaCocdzm2hDHqo4U6gu+Vascko116Kn6QsNU8mHbRDgbETB nhUrOB7lkRHjkJWDoL2sG/X6rcaPdVQ2WI28mV5sVsrwx/erBhfA430zwI14bIR1MNJYCu NYsZJ7aJT/chP7FpDHOmHj6kEyhin28= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 37B3DA436C6; Wed, 5 Feb 2025 14:40:11 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 191D4C4CED1; Wed, 5 Feb 2025 14:41:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766517; bh=x3UT1ADjlx2LpwoYgnvBEmyZ0Bh00H5bAdA8NSKIOiY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pU2Tbd99J3bM/UgxHxbmF6rOHdw2alW6ctSgG23UiJzYiN6xbBUsJLpvhihigLc2A GKzMuw0JywaphQUG8UWo1Fo6NYuslcXPArkHh9g5GwMykuqKda6UZvURatdfKBlwJu ovnciCc+aEnUZvs+CKQY8TLqOsy35DvKEu0UYHo43mE5IhQf33OX3OQR+oYvJO/1ny K7gzUteCBuDVvvYsqGIfypdpoDor74wtC+I88wM4mDpwPHAKNV9gCIZaMCcrFL1dCx /caHXOR3JJYhiKM52V3pisteL6t811EIaTepd49FEZc6FcGDDKxzWGlEjwFJrih2Vt 8YhyjiWuABgQw== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Leon Romanovsky , Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 16/17] vfio/mlx5: Rewrite create mkey flow to allow better code reuse Date: Wed, 5 Feb 2025 16:40:36 +0200 Message-ID: <7a56f40052dc02d7bced4b920525de65c810c035.1738765879.git.leonro@nvidia.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Server: rspam04 X-Rspamd-Queue-Id: DA7674000D X-Stat-Signature: 9d157xnu7nnkaqufg1x9mtztyw5hmsm6 X-Rspam-User: X-HE-Tag: 1738766517-99126 X-HE-Meta: U2FsdGVkX1/vMPQSgB6n7On09sn2md/lMcrqhZy6DlHLFVo4QMmmWxIoiSsAc+jausoSY+WalYiS1W8amIfeeg2hvxoBP8scHY7xb7oC/X3ItDHZoFOaZGKiJkWcXLxvCh2BNf1Xbwl4lSsk1CltYVCi+isUVBmtX/oPqNWUEwXYDFrBJ9vTMx9bhoyj8hKvUjD3e0kI65n6jN2uC/FLZQ6XK7YskyPd4DJAMleahN3sIC+E0EdI+pvrHr++rP+OHEGSchXXwLqFoSU1gxCTF0MMbochb+5B7L4EeHSCDtIyM+jeHAsSc+X7aWZrEDq2zeLI5wieMrmrRd9eHfjJD1WIJKcU/4NL1APcZxPoBM4VdvWJGq+QwwXdmG7WFJIvj859mFRpnB3w4CwJp1JedEN+fjr6ml42vglXDBFTNXsxlez3czUgPze9bzX/4ZrHrV0l3IchktKzCbIAwT/Kppkhg9szFuM+0TgpBsEToczDLlcghL0QKxEEKYipGYtW/kr1dI+4BNAWyhlamCujAHYOKeinIR1cO82yxtyXBHnhAsoRsQuh+p2ektK5zDNpsGdwdNsqylkMYsY9EdbysEoKbR5WOIawJ2vj7XrVAqHYZ0iLximqWm60dn5E2eVofooBo0/Q/t5DgMreWfuoiZkhQWuOZUjVKE4F7vfSunG80899CeMCZxQ1G8fzfDki92QHQvbISHcGuOjqpEAScXG6S/p6PaMwI37thEBTMMGa/CNag6OZKDbCdnuHRCMZZfa5zYTMx4GjiyZ/cQA9lqt/KKttYwXz7nCCKJbraYiTLft4s4oFNCvHua0ydvtqsLtOziR5qzq9Yun+F9bZD61yrzerM4Jrc+lG9wRKYruLu+MhyXHOse5kuaj5nOpJXhZwxXvp1SytwMi3JN4IbRsdq5t27VyCSPa2HiDeuKzrL5fQFnJ4L90sgVb0KHqx9n4f29CY8D3cNngCoWd tcdo/Jj7 1TwW3J76IxB7jBZmzQ7mnV5DK59Yj5EzQpFVFnjSfnOc4v/vCZnAqKXsfnOPHrC+dqk1c4IHVVSwGv8r5nFxNsQrxrNKWa+pqNMHmzgx2q6npCva4pLVtOhp9vDtojIcrk4JfFS0lopLgeaVmc4AaifinODhlnGtOb+KgWEhTjTPNZ0Gskv1JrYQdgByP6LULDCTe 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 Change the creation of mkey to be performed in multiple steps: data allocation, DMA setup and actual call to HW to create that mkey. In this new flow, the whole input to MKEY command is saved to eliminate the need to keep array of pointers for DMA addresses for receive list and in the future patches for send list too. In addition to memory size reduce and elimination of unnecessary data movements to set MKEY input, the code is prepared for future reuse. Signed-off-by: Leon Romanovsky --- drivers/vfio/pci/mlx5/cmd.c | 157 ++++++++++++++++++++---------------- drivers/vfio/pci/mlx5/cmd.h | 4 +- 2 files changed, 91 insertions(+), 70 deletions(-) diff --git a/drivers/vfio/pci/mlx5/cmd.c b/drivers/vfio/pci/mlx5/cmd.c index 377dee7765fb..84dc3bc128c6 100644 --- a/drivers/vfio/pci/mlx5/cmd.c +++ b/drivers/vfio/pci/mlx5/cmd.c @@ -313,39 +313,21 @@ static int mlx5vf_cmd_get_vhca_id(struct mlx5_core_dev *mdev, u16 function_id, return ret; } -static int _create_mkey(struct mlx5_core_dev *mdev, u32 pdn, - struct mlx5_vhca_data_buffer *buf, - struct mlx5_vhca_recv_buf *recv_buf, - u32 *mkey) +static u32 *alloc_mkey_in(u32 npages, u32 pdn) { - size_t npages = buf ? buf->npages : recv_buf->npages; - int err = 0, inlen; - __be64 *mtt; + int inlen; void *mkc; u32 *in; inlen = MLX5_ST_SZ_BYTES(create_mkey_in) + - sizeof(*mtt) * round_up(npages, 2); + sizeof(__be64) * round_up(npages, 2); - in = kvzalloc(inlen, GFP_KERNEL); + in = kvzalloc(inlen, GFP_KERNEL_ACCOUNT); if (!in) - return -ENOMEM; + return NULL; MLX5_SET(create_mkey_in, in, translations_octword_actual_size, DIV_ROUND_UP(npages, 2)); - mtt = (__be64 *)MLX5_ADDR_OF(create_mkey_in, in, klm_pas_mtt); - - if (buf) { - struct sg_dma_page_iter dma_iter; - - for_each_sgtable_dma_page(&buf->table.sgt, &dma_iter, 0) - *mtt++ = cpu_to_be64(sg_page_iter_dma_address(&dma_iter)); - } else { - int i; - - for (i = 0; i < npages; i++) - *mtt++ = cpu_to_be64(recv_buf->dma_addrs[i]); - } mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry); MLX5_SET(mkc, mkc, access_mode_1_0, MLX5_MKC_ACCESS_MODE_MTT); @@ -359,9 +341,30 @@ static int _create_mkey(struct mlx5_core_dev *mdev, u32 pdn, MLX5_SET(mkc, mkc, log_page_size, PAGE_SHIFT); MLX5_SET(mkc, mkc, translations_octword_size, DIV_ROUND_UP(npages, 2)); MLX5_SET64(mkc, mkc, len, npages * PAGE_SIZE); - err = mlx5_core_create_mkey(mdev, mkey, in, inlen); - kvfree(in); - return err; + + return in; +} + +static int create_mkey(struct mlx5_core_dev *mdev, u32 npages, + struct mlx5_vhca_data_buffer *buf, u32 *mkey_in, + u32 *mkey) +{ + __be64 *mtt; + int inlen; + + mtt = (__be64 *)MLX5_ADDR_OF(create_mkey_in, mkey_in, klm_pas_mtt); + if (buf) { + struct sg_dma_page_iter dma_iter; + + for_each_sgtable_dma_page(&buf->table.sgt, &dma_iter, 0) + *mtt++ = cpu_to_be64( + sg_page_iter_dma_address(&dma_iter)); + } + + inlen = MLX5_ST_SZ_BYTES(create_mkey_in) + + sizeof(__be64) * round_up(npages, 2); + + return mlx5_core_create_mkey(mdev, mkey, mkey_in, inlen); } static int mlx5vf_dma_data_buffer(struct mlx5_vhca_data_buffer *buf) @@ -374,20 +377,28 @@ static int mlx5vf_dma_data_buffer(struct mlx5_vhca_data_buffer *buf) if (mvdev->mdev_detach) return -ENOTCONN; - if (buf->dmaed || !buf->npages) + if (buf->mkey_in || !buf->npages) return -EINVAL; ret = dma_map_sgtable(mdev->device, &buf->table.sgt, buf->dma_dir, 0); if (ret) return ret; - ret = _create_mkey(mdev, buf->migf->pdn, buf, NULL, &buf->mkey); - if (ret) + buf->mkey_in = alloc_mkey_in(buf->npages, buf->migf->pdn); + if (!buf->mkey_in) { + ret = -ENOMEM; goto err; + } - buf->dmaed = true; + ret = create_mkey(mdev, buf->npages, buf, buf->mkey_in, &buf->mkey); + if (ret) + goto err_create_mkey; return 0; + +err_create_mkey: + kvfree(buf->mkey_in); + buf->mkey_in = NULL; err: dma_unmap_sgtable(mdev->device, &buf->table.sgt, buf->dma_dir, 0); return ret; @@ -401,8 +412,9 @@ void mlx5vf_free_data_buffer(struct mlx5_vhca_data_buffer *buf) lockdep_assert_held(&migf->mvdev->state_mutex); WARN_ON(migf->mvdev->mdev_detach); - if (buf->dmaed) { + if (buf->mkey_in) { mlx5_core_destroy_mkey(migf->mvdev->mdev, buf->mkey); + kvfree(buf->mkey_in); dma_unmap_sgtable(migf->mvdev->mdev->device, &buf->table.sgt, buf->dma_dir, 0); } @@ -783,7 +795,7 @@ int mlx5vf_cmd_load_vhca_state(struct mlx5vf_pci_core_device *mvdev, if (mvdev->mdev_detach) return -ENOTCONN; - if (!buf->dmaed) { + if (!buf->mkey_in) { err = mlx5vf_dma_data_buffer(buf); if (err) return err; @@ -1384,56 +1396,54 @@ static int alloc_recv_pages(struct mlx5_vhca_recv_buf *recv_buf, kvfree(recv_buf->page_list); return -ENOMEM; } +static void unregister_dma_pages(struct mlx5_core_dev *mdev, u32 npages, + u32 *mkey_in) +{ + dma_addr_t addr; + __be64 *mtt; + int i; + + mtt = (__be64 *)MLX5_ADDR_OF(create_mkey_in, mkey_in, klm_pas_mtt); + for (i = npages - 1; i >= 0; i--) { + addr = be64_to_cpu(mtt[i]); + dma_unmap_single(mdev->device, addr, PAGE_SIZE, + DMA_FROM_DEVICE); + } +} -static int register_dma_recv_pages(struct mlx5_core_dev *mdev, - struct mlx5_vhca_recv_buf *recv_buf) +static int register_dma_pages(struct mlx5_core_dev *mdev, u32 npages, + struct page **page_list, u32 *mkey_in) { - int i, j; + dma_addr_t addr; + __be64 *mtt; + int i; - recv_buf->dma_addrs = kvcalloc(recv_buf->npages, - sizeof(*recv_buf->dma_addrs), - GFP_KERNEL_ACCOUNT); - if (!recv_buf->dma_addrs) - return -ENOMEM; + mtt = (__be64 *)MLX5_ADDR_OF(create_mkey_in, mkey_in, klm_pas_mtt); - for (i = 0; i < recv_buf->npages; i++) { - recv_buf->dma_addrs[i] = dma_map_page(mdev->device, - recv_buf->page_list[i], - 0, PAGE_SIZE, - DMA_FROM_DEVICE); - if (dma_mapping_error(mdev->device, recv_buf->dma_addrs[i])) + for (i = 0; i < npages; i++) { + addr = dma_map_page(mdev->device, page_list[i], 0, PAGE_SIZE, + DMA_FROM_DEVICE); + if (dma_mapping_error(mdev->device, addr)) goto error; + + *mtt++ = cpu_to_be64(addr); } + return 0; error: - for (j = 0; j < i; j++) - dma_unmap_single(mdev->device, recv_buf->dma_addrs[j], - PAGE_SIZE, DMA_FROM_DEVICE); - - kvfree(recv_buf->dma_addrs); + unregister_dma_pages(mdev, i, mkey_in); return -ENOMEM; } -static void unregister_dma_recv_pages(struct mlx5_core_dev *mdev, - struct mlx5_vhca_recv_buf *recv_buf) -{ - int i; - - for (i = 0; i < recv_buf->npages; i++) - dma_unmap_single(mdev->device, recv_buf->dma_addrs[i], - PAGE_SIZE, DMA_FROM_DEVICE); - - kvfree(recv_buf->dma_addrs); -} - static void mlx5vf_free_qp_recv_resources(struct mlx5_core_dev *mdev, struct mlx5_vhca_qp *qp) { struct mlx5_vhca_recv_buf *recv_buf = &qp->recv_buf; mlx5_core_destroy_mkey(mdev, recv_buf->mkey); - unregister_dma_recv_pages(mdev, recv_buf); + unregister_dma_pages(mdev, recv_buf->npages, recv_buf->mkey_in); + kvfree(recv_buf->mkey_in); free_recv_pages(&qp->recv_buf); } @@ -1449,18 +1459,29 @@ static int mlx5vf_alloc_qp_recv_resources(struct mlx5_core_dev *mdev, if (err < 0) return err; - err = register_dma_recv_pages(mdev, recv_buf); - if (err) + recv_buf->mkey_in = alloc_mkey_in(npages, pdn); + if (!recv_buf->mkey_in) { + err = -ENOMEM; goto end; + } + + err = register_dma_pages(mdev, npages, recv_buf->page_list, + recv_buf->mkey_in); + if (err) + goto err_register_dma; - err = _create_mkey(mdev, pdn, NULL, recv_buf, &recv_buf->mkey); + err = create_mkey(mdev, npages, NULL, recv_buf->mkey_in, + &recv_buf->mkey); if (err) goto err_create_mkey; return 0; err_create_mkey: - unregister_dma_recv_pages(mdev, recv_buf); + unregister_dma_pages(mdev, npages, recv_buf->mkey_in); +err_register_dma: + kvfree(recv_buf->mkey_in); + recv_buf->mkey_in = NULL; end: free_recv_pages(recv_buf); return err; diff --git a/drivers/vfio/pci/mlx5/cmd.h b/drivers/vfio/pci/mlx5/cmd.h index 7d4a833b6900..25dd6ff54591 100644 --- a/drivers/vfio/pci/mlx5/cmd.h +++ b/drivers/vfio/pci/mlx5/cmd.h @@ -58,8 +58,8 @@ struct mlx5_vhca_data_buffer { u64 length; u32 npages; u32 mkey; + u32 *mkey_in; enum dma_data_direction dma_dir; - u8 dmaed:1; u8 stop_copy_chunk_num; struct list_head buf_elm; struct mlx5_vf_migration_file *migf; @@ -133,8 +133,8 @@ struct mlx5_vhca_cq { struct mlx5_vhca_recv_buf { u32 npages; struct page **page_list; - dma_addr_t *dma_addrs; u32 next_rq_offset; + u32 *mkey_in; u32 mkey; }; From patchwork Wed Feb 5 14:40:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 13961195 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 5223FC02194 for ; Wed, 5 Feb 2025 14:42:10 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id EBAB5280011; Wed, 5 Feb 2025 09:42:04 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id E6C45280010; Wed, 5 Feb 2025 09:42:04 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id C9628280011; Wed, 5 Feb 2025 09:42:04 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id A1B2E280010 for ; Wed, 5 Feb 2025 09:42:04 -0500 (EST) Received: from smtpin09.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id 5AD99120CC2 for ; Wed, 5 Feb 2025 14:42:04 +0000 (UTC) X-FDA: 83086155768.09.8C17BA5 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf27.hostedemail.com (Postfix) with ESMTP id AC14F40003 for ; Wed, 5 Feb 2025 14:42:02 +0000 (UTC) Authentication-Results: imf27.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=JWJQTe9q; spf=pass (imf27.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=1738766522; 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=F1KRAorjU1OFhcjOjItLinOBA+JdFx+C+wDP/JuBb+4=; b=OilTgmZ2Cxr9ABPlzk/cp6CoqT4CUsIfVPM6kge1ZBzxOb3W3WlQYj9AngiICep7dOGvNA Nqsu8eFUjyVNvhGg+EHloaK58+Iu/Y8nTGW7YqH1hg/B2mYVlgNZOcZ0N1sxWvUP1ivelT n/5M000HYuoPMLsCB9hR/hC1iGcOD80= ARC-Authentication-Results: i=1; imf27.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=JWJQTe9q; spf=pass (imf27.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=1738766522; a=rsa-sha256; cv=none; b=h+sQnjJKrUyyDdCetZcygOnWNcjNN6Yl0mcDO7FKrRABB+mHmlDwRKrAS/7X62oLNf4AoW CLP4kpjL4UZS57q8Zk5afNh2ZKHU3D0tUQyUmRkySn5jTbRLTvDwAw+4f1Ke0gnhwT1ug6 ag9X7WX4fr5FoMIuF9/bLeYOlDC2pyk= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id EAB6A5C555D; Wed, 5 Feb 2025 14:41:21 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7597FC4CEDD; Wed, 5 Feb 2025 14:42:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1738766521; bh=8QSTooCeiZmn5JcSnvBQX/pgjSrH/ExrcOOnIDjAG9c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JWJQTe9q4hVOHPDcn4ApGAo0VfLZUoGvklTpYjTa/ut4i4CU7q8P/QHh3rrOOKhMl keMWSkdjYZ2oDqKJqpMoLtfHfwKOQ6+2oGNtvx/gSYc6OcBi8KDklnkW4jV/K/+ymk H2amzmMp7cD4Ve/X5xCoS5fy6BonI2Lx4ZrfthSoALBAgTv5p8rwKAwtvfYV29aJej i7CEQd+Zqbsr1RK45dl8XaQDNFcmP5VaVQ3IrNaOJ7jH6oNXvxYYgili7ZuHoNC2NA 0mYoNeSMtcblFV8FBa0P6JUMwFtW/2Alwz4C7xYVXMnoVXTNsgOgwFGDUIox+nR2vU f+o9IBE5g5TQQ== From: Leon Romanovsky To: Christoph Hellwig , Jason Gunthorpe , Robin Murphy Cc: Leon Romanovsky , Jens Axboe , Joerg Roedel , Will Deacon , Sagi Grimberg , 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 v7 17/17] vfio/mlx5: Enable the DMA link API Date: Wed, 5 Feb 2025 16:40:37 +0200 Message-ID: <1a7fd81aed2468c0e950fbcc85655cf3b2c0470b.1738765879.git.leonro@nvidia.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam09 X-Rspamd-Queue-Id: AC14F40003 X-Stat-Signature: 6bniffqnk73pw8ybdknqgdwyrrmumtyd X-HE-Tag: 1738766522-134735 X-HE-Meta: U2FsdGVkX18qZcX3pRRAvSuqWZuUtUE4NZPJ3g5ek8Rd5Sn9Mm/GwnC2HO8V8M+tpeOjXYdgNscw7gu3kFlbQULjrqSTe2gxFCSRzGyHbfNO0xjvkFmOiVvAzIHpOYwAo4Uo3zGmL9xUgkG/LzptYIBW5ro8yZpBghF2P/9W5JQMuIpJH8XwfqHa9AUos1P29fRSI6LT0aa10CskDjqGrhvBS0KulG8FPLCzm+5EofT4H0Y71Hhp8qvyoA4Xw8g4o3RnHtxWy0zdZrkiOvYd9TBCi5CA/NblMO+VDiQxIMv1yobM9bOJazxIG7LD/vbYn2KyxIR1UNxIH2Zv6sc5QtWbO+QU3zGpAnP3IzFRiYfsOXLpSvdWTDft4w5aJfBoKoNTBR5b8zNKA1SZS1OwyTb5AwEVDFIpBcCjB1F5aXvgo+MrR9po8KHrcmO++ok8hV7BZ1Jvp1Alq5F9RKFb3JhPqNADQXR+WbXimrG6cNWxv8T5NXDIyxCbhc8HQiiYDCz6J1DaBF5BK2QBT2rQzdoYbDx49oXbxASCD1AIrpbwQlZXBVAI5MTdAtt2ZudO1gAl4lxSce3+xwhQGuZdjm8B0HwdnGK3fX8iuGhT6AkbwnDQCzA1MWK/Pl7gjYzpdKOrN+ozDqGKE2vVFYnn94v+bSFuhAGFD+PBIF49wpfR97haK3AGWMaPeImfAIA0AhQjEijhI7VyFBedxGdAnllz66DqlF0Rr+iOIO3cPV2HR7RMZ2RVlcGeSfSxKebC2bgcyT0uQsYh/+P8Xa9dNc7tzxBxPIVUI/VGzWiTzl/CW5OT+pY+VOOZB4VoIWANWCHt7192BqOtSnh0nKVxzkZeEyHCzZWihCy0g5o13KrOZZgN5jpPYssHKFLEKUH5JfCstssQZaMjX1n65x/cwDXY2o564730N4Ayieix2GkZ2X1MLodPbPxx6SK7VICzryjvzep+da647Z3eFUV XdoDtKj3 8fz+uN2Svc/k0ziKjpDPiUOza413MxSWS09PjjGMDX01hZDp7rfOHtlzef1mjyOPjJxh7IqSxW9kxDI4moruT27WOhFXJBrkYbGpFWVCuw087HSeevuzirZ31/a2HEQOmVjlEEKt0ZBFh28QIu75KxAJ65mVcoiuiO9q67kDeUsOoNC3Mul2mhGD/eVxA3r8Tr4Ma 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 Remove intermediate scatter-gather table completely and enable new DMA link API. Signed-off-by: Leon Romanovsky --- drivers/vfio/pci/mlx5/cmd.c | 298 ++++++++++++++++------------------- drivers/vfio/pci/mlx5/cmd.h | 21 ++- drivers/vfio/pci/mlx5/main.c | 31 ---- 3 files changed, 147 insertions(+), 203 deletions(-) diff --git a/drivers/vfio/pci/mlx5/cmd.c b/drivers/vfio/pci/mlx5/cmd.c index 84dc3bc128c6..b162e44112fb 100644 --- a/drivers/vfio/pci/mlx5/cmd.c +++ b/drivers/vfio/pci/mlx5/cmd.c @@ -345,26 +345,82 @@ static u32 *alloc_mkey_in(u32 npages, u32 pdn) return in; } -static int create_mkey(struct mlx5_core_dev *mdev, u32 npages, - struct mlx5_vhca_data_buffer *buf, u32 *mkey_in, +static int create_mkey(struct mlx5_core_dev *mdev, u32 npages, u32 *mkey_in, u32 *mkey) { + int inlen = MLX5_ST_SZ_BYTES(create_mkey_in) + + sizeof(__be64) * round_up(npages, 2); + + return mlx5_core_create_mkey(mdev, mkey, mkey_in, inlen); +} + +static void unregister_dma_pages(struct mlx5_core_dev *mdev, u32 npages, + u32 *mkey_in, struct dma_iova_state *state, + enum dma_data_direction dir) +{ + dma_addr_t addr; __be64 *mtt; - int inlen; + int i; - mtt = (__be64 *)MLX5_ADDR_OF(create_mkey_in, mkey_in, klm_pas_mtt); - if (buf) { - struct sg_dma_page_iter dma_iter; + WARN_ON_ONCE(dir == DMA_NONE); - for_each_sgtable_dma_page(&buf->table.sgt, &dma_iter, 0) - *mtt++ = cpu_to_be64( - sg_page_iter_dma_address(&dma_iter)); + if (dma_use_iova(state)) { + dma_iova_destroy(mdev->device, state, npages * PAGE_SIZE, dir, + 0); + } else { + mtt = (__be64 *)MLX5_ADDR_OF(create_mkey_in, mkey_in, + klm_pas_mtt); + for (i = npages - 1; i >= 0; i--) { + addr = be64_to_cpu(mtt[i]); + dma_unmap_page(mdev->device, addr, PAGE_SIZE, dir); + } } +} - inlen = MLX5_ST_SZ_BYTES(create_mkey_in) + - sizeof(__be64) * round_up(npages, 2); +static int register_dma_pages(struct mlx5_core_dev *mdev, u32 npages, + struct page **page_list, u32 *mkey_in, + struct dma_iova_state *state, + enum dma_data_direction dir) +{ + dma_addr_t addr; + size_t mapped = 0; + __be64 *mtt; + int i, err; - return mlx5_core_create_mkey(mdev, mkey, mkey_in, inlen); + WARN_ON_ONCE(dir == DMA_NONE); + + mtt = (__be64 *)MLX5_ADDR_OF(create_mkey_in, mkey_in, klm_pas_mtt); + + if (dma_iova_try_alloc(mdev->device, state, 0, npages * PAGE_SIZE)) { + addr = state->addr; + for (i = 0; i < npages; i++) { + err = dma_iova_link(mdev->device, state, + page_to_phys(page_list[i]), mapped, + PAGE_SIZE, dir, 0); + if (err) + goto error; + *mtt++ = cpu_to_be64(addr); + addr += PAGE_SIZE; + mapped += PAGE_SIZE; + } + err = dma_iova_sync(mdev->device, state, 0, mapped); + if (err) + goto error; + } else { + for (i = 0; i < npages; i++) { + addr = dma_map_page(mdev->device, page_list[i], 0, + PAGE_SIZE, dir); + err = dma_mapping_error(mdev->device, addr); + if (err) + goto error; + *mtt++ = cpu_to_be64(addr); + } + } + return 0; + +error: + unregister_dma_pages(mdev, i, mkey_in, state, dir); + return err; } static int mlx5vf_dma_data_buffer(struct mlx5_vhca_data_buffer *buf) @@ -380,98 +436,90 @@ static int mlx5vf_dma_data_buffer(struct mlx5_vhca_data_buffer *buf) if (buf->mkey_in || !buf->npages) return -EINVAL; - ret = dma_map_sgtable(mdev->device, &buf->table.sgt, buf->dma_dir, 0); - if (ret) - return ret; - buf->mkey_in = alloc_mkey_in(buf->npages, buf->migf->pdn); - if (!buf->mkey_in) { - ret = -ENOMEM; - goto err; - } + if (!buf->mkey_in) + return -ENOMEM; - ret = create_mkey(mdev, buf->npages, buf, buf->mkey_in, &buf->mkey); + ret = register_dma_pages(mdev, buf->npages, buf->page_list, + buf->mkey_in, &buf->state, buf->dma_dir); + if (ret) + goto err_register_dma; + + ret = create_mkey(mdev, buf->npages, buf->mkey_in, &buf->mkey); if (ret) goto err_create_mkey; return 0; err_create_mkey: + unregister_dma_pages(mdev, buf->npages, buf->mkey_in, &buf->state, + buf->dma_dir); +err_register_dma: kvfree(buf->mkey_in); buf->mkey_in = NULL; -err: - dma_unmap_sgtable(mdev->device, &buf->table.sgt, buf->dma_dir, 0); return ret; } +static void free_page_list(u32 npages, struct page **page_list) +{ + int i; + + /* Undo alloc_pages_bulk() */ + for (i = npages - 1; i >= 0; i--) + __free_page(page_list[i]); + + kvfree(page_list); +} + void mlx5vf_free_data_buffer(struct mlx5_vhca_data_buffer *buf) { - struct mlx5_vf_migration_file *migf = buf->migf; - struct sg_page_iter sg_iter; + struct mlx5vf_pci_core_device *mvdev = buf->migf->mvdev; + struct mlx5_core_dev *mdev = mvdev->mdev; - lockdep_assert_held(&migf->mvdev->state_mutex); - WARN_ON(migf->mvdev->mdev_detach); + lockdep_assert_held(&mvdev->state_mutex); + WARN_ON(mvdev->mdev_detach); if (buf->mkey_in) { - mlx5_core_destroy_mkey(migf->mvdev->mdev, buf->mkey); + mlx5_core_destroy_mkey(mdev, buf->mkey); + unregister_dma_pages(mdev, buf->npages, buf->mkey_in, + &buf->state, buf->dma_dir); kvfree(buf->mkey_in); - dma_unmap_sgtable(migf->mvdev->mdev->device, &buf->table.sgt, - buf->dma_dir, 0); } - /* Undo alloc_pages_bulk() */ - for_each_sgtable_page(&buf->table.sgt, &sg_iter, 0) - __free_page(sg_page_iter_page(&sg_iter)); - sg_free_append_table(&buf->table); + free_page_list(buf->npages, buf->page_list); kfree(buf); } -static int mlx5vf_add_migration_pages(struct mlx5_vhca_data_buffer *buf, - unsigned int npages) +static int mlx5vf_add_pages(struct page ***page_list, unsigned int npages) { - unsigned int to_alloc = npages; - struct page **page_list; - unsigned long filled; - unsigned int to_fill; - int ret; + unsigned int filled, done = 0; int i; - to_fill = min_t(unsigned int, npages, PAGE_SIZE / sizeof(*page_list)); - page_list = kvzalloc(to_fill * sizeof(*page_list), GFP_KERNEL_ACCOUNT); - if (!page_list) + *page_list = + kvcalloc(npages, sizeof(struct page *), GFP_KERNEL_ACCOUNT); + if (!*page_list) return -ENOMEM; - do { - filled = alloc_pages_bulk(GFP_KERNEL_ACCOUNT, to_fill, - page_list); - if (!filled) { - ret = -ENOMEM; + for (;;) { + filled = alloc_pages_bulk(GFP_KERNEL_ACCOUNT, npages - done, + *page_list + done); + if (!filled) goto err; - } - to_alloc -= filled; - ret = sg_alloc_append_table_from_pages( - &buf->table, page_list, filled, 0, - filled << PAGE_SHIFT, UINT_MAX, SG_MAX_SINGLE_ALLOC, - GFP_KERNEL_ACCOUNT); - if (ret) - goto err_append; - buf->npages += filled; - /* clean input for another bulk allocation */ - memset(page_list, 0, filled * sizeof(*page_list)); - to_fill = min_t(unsigned int, to_alloc, - PAGE_SIZE / sizeof(*page_list)); - } while (to_alloc > 0); + done += filled; + if (done == npages) + break; + } - kvfree(page_list); return 0; -err_append: - for (i = filled - 1; i >= 0; i--) - __free_page(page_list[i]); err: - kvfree(page_list); - return ret; + for (i = 0; i < done; i++) + __free_page(*page_list[i]); + + kvfree(*page_list); + *page_list = NULL; + return -ENOMEM; } struct mlx5_vhca_data_buffer * @@ -488,10 +536,12 @@ mlx5vf_alloc_data_buffer(struct mlx5_vf_migration_file *migf, u32 npages, buf->dma_dir = dma_dir; buf->migf = migf; if (npages) { - ret = mlx5vf_add_migration_pages(buf, npages); + ret = mlx5vf_add_pages(&buf->page_list, npages); if (ret) goto end; + buf->npages = npages; + if (dma_dir != DMA_NONE) { ret = mlx5vf_dma_data_buffer(buf); if (ret) @@ -1350,101 +1400,16 @@ static void mlx5vf_destroy_qp(struct mlx5_core_dev *mdev, kfree(qp); } -static void free_recv_pages(struct mlx5_vhca_recv_buf *recv_buf) -{ - int i; - - /* Undo alloc_pages_bulk() */ - for (i = 0; i < recv_buf->npages; i++) - __free_page(recv_buf->page_list[i]); - - kvfree(recv_buf->page_list); -} - -static int alloc_recv_pages(struct mlx5_vhca_recv_buf *recv_buf, - unsigned int npages) -{ - unsigned int filled = 0, done = 0; - int i; - - recv_buf->page_list = kvcalloc(npages, sizeof(*recv_buf->page_list), - GFP_KERNEL_ACCOUNT); - if (!recv_buf->page_list) - return -ENOMEM; - - for (;;) { - filled = alloc_pages_bulk(GFP_KERNEL_ACCOUNT, - npages - done, - recv_buf->page_list + done); - if (!filled) - goto err; - - done += filled; - if (done == npages) - break; - } - - recv_buf->npages = npages; - return 0; - -err: - for (i = 0; i < npages; i++) { - if (recv_buf->page_list[i]) - __free_page(recv_buf->page_list[i]); - } - - kvfree(recv_buf->page_list); - return -ENOMEM; -} -static void unregister_dma_pages(struct mlx5_core_dev *mdev, u32 npages, - u32 *mkey_in) -{ - dma_addr_t addr; - __be64 *mtt; - int i; - - mtt = (__be64 *)MLX5_ADDR_OF(create_mkey_in, mkey_in, klm_pas_mtt); - for (i = npages - 1; i >= 0; i--) { - addr = be64_to_cpu(mtt[i]); - dma_unmap_single(mdev->device, addr, PAGE_SIZE, - DMA_FROM_DEVICE); - } -} - -static int register_dma_pages(struct mlx5_core_dev *mdev, u32 npages, - struct page **page_list, u32 *mkey_in) -{ - dma_addr_t addr; - __be64 *mtt; - int i; - - mtt = (__be64 *)MLX5_ADDR_OF(create_mkey_in, mkey_in, klm_pas_mtt); - - for (i = 0; i < npages; i++) { - addr = dma_map_page(mdev->device, page_list[i], 0, PAGE_SIZE, - DMA_FROM_DEVICE); - if (dma_mapping_error(mdev->device, addr)) - goto error; - - *mtt++ = cpu_to_be64(addr); - } - - return 0; - -error: - unregister_dma_pages(mdev, i, mkey_in); - return -ENOMEM; -} - static void mlx5vf_free_qp_recv_resources(struct mlx5_core_dev *mdev, struct mlx5_vhca_qp *qp) { struct mlx5_vhca_recv_buf *recv_buf = &qp->recv_buf; mlx5_core_destroy_mkey(mdev, recv_buf->mkey); - unregister_dma_pages(mdev, recv_buf->npages, recv_buf->mkey_in); + unregister_dma_pages(mdev, recv_buf->npages, recv_buf->mkey_in, + &recv_buf->state, DMA_FROM_DEVICE); kvfree(recv_buf->mkey_in); - free_recv_pages(&qp->recv_buf); + free_page_list(recv_buf->npages, recv_buf->page_list); } static int mlx5vf_alloc_qp_recv_resources(struct mlx5_core_dev *mdev, @@ -1455,10 +1420,12 @@ static int mlx5vf_alloc_qp_recv_resources(struct mlx5_core_dev *mdev, struct mlx5_vhca_recv_buf *recv_buf = &qp->recv_buf; int err; - err = alloc_recv_pages(recv_buf, npages); - if (err < 0) + err = mlx5vf_add_pages(&recv_buf->page_list, npages); + if (err) return err; + recv_buf->npages = npages; + recv_buf->mkey_in = alloc_mkey_in(npages, pdn); if (!recv_buf->mkey_in) { err = -ENOMEM; @@ -1466,24 +1433,25 @@ static int mlx5vf_alloc_qp_recv_resources(struct mlx5_core_dev *mdev, } err = register_dma_pages(mdev, npages, recv_buf->page_list, - recv_buf->mkey_in); + recv_buf->mkey_in, &recv_buf->state, + DMA_FROM_DEVICE); if (err) goto err_register_dma; - err = create_mkey(mdev, npages, NULL, recv_buf->mkey_in, - &recv_buf->mkey); + err = create_mkey(mdev, npages, recv_buf->mkey_in, &recv_buf->mkey); if (err) goto err_create_mkey; return 0; err_create_mkey: - unregister_dma_pages(mdev, npages, recv_buf->mkey_in); + unregister_dma_pages(mdev, npages, recv_buf->mkey_in, &recv_buf->state, + DMA_FROM_DEVICE); err_register_dma: kvfree(recv_buf->mkey_in); recv_buf->mkey_in = NULL; end: - free_recv_pages(recv_buf); + free_page_list(npages, recv_buf->page_list); return err; } diff --git a/drivers/vfio/pci/mlx5/cmd.h b/drivers/vfio/pci/mlx5/cmd.h index 25dd6ff54591..d7821b5ca772 100644 --- a/drivers/vfio/pci/mlx5/cmd.h +++ b/drivers/vfio/pci/mlx5/cmd.h @@ -53,7 +53,8 @@ struct mlx5_vf_migration_header { }; struct mlx5_vhca_data_buffer { - struct sg_append_table table; + struct page **page_list; + struct dma_iova_state state; loff_t start_pos; u64 length; u32 npages; @@ -63,10 +64,6 @@ struct mlx5_vhca_data_buffer { u8 stop_copy_chunk_num; struct list_head buf_elm; struct mlx5_vf_migration_file *migf; - /* Optimize mlx5vf_get_migration_page() for sequential access */ - struct scatterlist *last_offset_sg; - unsigned int sg_last_entry; - unsigned long last_offset; }; struct mlx5vf_async_data { @@ -133,6 +130,7 @@ struct mlx5_vhca_cq { struct mlx5_vhca_recv_buf { u32 npages; struct page **page_list; + struct dma_iova_state state; u32 next_rq_offset; u32 *mkey_in; u32 mkey; @@ -224,8 +222,17 @@ struct mlx5_vhca_data_buffer * mlx5vf_get_data_buffer(struct mlx5_vf_migration_file *migf, u32 npages, enum dma_data_direction dma_dir); void mlx5vf_put_data_buffer(struct mlx5_vhca_data_buffer *buf); -struct page *mlx5vf_get_migration_page(struct mlx5_vhca_data_buffer *buf, - unsigned long offset); +static inline struct page * +mlx5vf_get_migration_page(struct mlx5_vhca_data_buffer *buf, + unsigned long offset) +{ + int page_entry = offset / PAGE_SIZE; + + if (page_entry >= buf->npages) + return NULL; + + return buf->page_list[page_entry]; +} void mlx5vf_state_mutex_unlock(struct mlx5vf_pci_core_device *mvdev); void mlx5vf_disable_fds(struct mlx5vf_pci_core_device *mvdev, enum mlx5_vf_migf_state *last_save_state); diff --git a/drivers/vfio/pci/mlx5/main.c b/drivers/vfio/pci/mlx5/main.c index bc0f468f741b..93f894fe60d2 100644 --- a/drivers/vfio/pci/mlx5/main.c +++ b/drivers/vfio/pci/mlx5/main.c @@ -34,37 +34,6 @@ static struct mlx5vf_pci_core_device *mlx5vf_drvdata(struct pci_dev *pdev) core_device); } -struct page * -mlx5vf_get_migration_page(struct mlx5_vhca_data_buffer *buf, - unsigned long offset) -{ - unsigned long cur_offset = 0; - struct scatterlist *sg; - unsigned int i; - - /* All accesses are sequential */ - if (offset < buf->last_offset || !buf->last_offset_sg) { - buf->last_offset = 0; - buf->last_offset_sg = buf->table.sgt.sgl; - buf->sg_last_entry = 0; - } - - cur_offset = buf->last_offset; - - for_each_sg(buf->last_offset_sg, sg, - buf->table.sgt.orig_nents - buf->sg_last_entry, i) { - if (offset < sg->length + cur_offset) { - buf->last_offset_sg = sg; - buf->sg_last_entry += i; - buf->last_offset = cur_offset; - return nth_page(sg_page(sg), - (offset - cur_offset) / PAGE_SIZE); - } - cur_offset += sg->length; - } - return NULL; -} - static void mlx5vf_disable_fd(struct mlx5_vf_migration_file *migf) { mutex_lock(&migf->lock);