Received: by 2002:a25:683:0:0:0:0:0 with SMTP id 125csp156930ybg; Tue, 2 Jun 2020 19:46:40 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxI6jCTvGJFGNBf/8ypNOwIKL0tiJ/apEC4vB+o1jNwhUQYQXWKdFpCQe6XzYiADnX0Vrr7 X-Received: by 2002:a17:907:33ce:: with SMTP id zk14mr25642522ejb.2.1591152400545; Tue, 02 Jun 2020 19:46:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1591152400; cv=none; d=google.com; s=arc-20160816; b=Me7v5wTDPAuD13nELUJhtRpJHrx/0YeMANShMSz6f9TY8v6qBuNaqEwDqM0ZKBrWIp qLhpSEInIfNeMOLsBn1zzAMMmdl9LWpg8J7n1/uPa3ARBTs8CWXBkafR7z8ciKJasqBe zIS4d0l72IZnwxeERNPWb3GRx9LG46/TNVEhA5QBTBkpZ6FxUgbpc1wx0VRpt/wVjkVW fsUQWNnQTJbJi6nxxZqrpt0uOchOL+wSNyGF65BpuCs9aGRhx5Yrh2fPSgPHTf4t0X7G p3v3E9PvnnzSgftwPbWDOkVsYyDiYuOyPP7O5Ps6HXTHttrI/JHAF4iGsinGdg+qBPOB NP7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=jh32FKZCrPqH+9xOtgWUiSL4xbF0HS/7X1yPr0kzHIE=; b=cajqXp0qYxcK4dwZMSkf87woJq2NRYPzCtAr4yTNY/rXTc2bKFupYA9IysAQC4VvN+ 35ZfsOMJj62Q9TDlZCv+lrBWzitxgSyrvxAG0f015ceZ6ZOCZ59DKPSN6NBcdHgva642 eGb2IexD9JswQP4ZeJ8zlLQjlJ6F25I3lGstwRana+ipSCfP4+6CVog+ybu2JRkkb/It iq8p4D8M0axLgMFZI4VUtA7vMj5a6igmJTJMDNJb5jDLMcQ2KeHFpQCF3XtYWrNrF08O /Kiny+Ol4mFgtRdVT3EZ+J/fFhhpjRiILzJHUzZTjHjOT29z1D3VoyJBQqFNF5k54zNx vi4g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id m5si328348eds.245.2020.06.02.19.46.18; Tue, 02 Jun 2020 19:46:40 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725968AbgFCCo0 (ORCPT + 99 others); Tue, 2 Jun 2020 22:44:26 -0400 Received: from szxga04-in.huawei.com ([45.249.212.190]:5842 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725836AbgFCCo0 (ORCPT ); Tue, 2 Jun 2020 22:44:26 -0400 Received: from DGGEMS406-HUB.china.huawei.com (unknown [172.30.72.60]) by Forcepoint Email with ESMTP id DE0E2348B6AB4E692FD1; Wed, 3 Jun 2020 10:44:23 +0800 (CST) Received: from SWX921481.china.huawei.com (10.126.201.193) by DGGEMS406-HUB.china.huawei.com (10.3.19.206) with Microsoft SMTP Server id 14.3.487.0; Wed, 3 Jun 2020 10:44:14 +0800 From: Barry Song To: , , , CC: , , , , , , , Barry Song , Will Deacon Subject: [PATCH 1/3] dma-direct: provide the ability to reserve per-numa CMA Date: Wed, 3 Jun 2020 14:42:29 +1200 Message-ID: <20200603024231.61748-2-song.bao.hua@hisilicon.com> X-Mailer: git-send-email 2.21.0.windows.1 In-Reply-To: <20200603024231.61748-1-song.bao.hua@hisilicon.com> References: <20200603024231.61748-1-song.bao.hua@hisilicon.com> MIME-Version: 1.0 Content-Transfer-Encoding: 7BIT Content-Type: text/plain; charset=US-ASCII X-Originating-IP: [10.126.201.193] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This is useful for two scenarios: 1. ARM64 smmu will get memory from local numa node, it can save its command queues and page tables locally. Tests show it can decrease dma_unmap latency at lot. For example, without this patch, smmu on node2 will get memory from node0 by calling dma_alloc_coherent(), typically, it has to wait for more than 560ns for the completion of CMD_SYNC in an empty command queue; with this patch, it needs 240ns only. 2. when we set iommu passthrough, drivers will get memory from CMA, local memory means much less latency. Cc: Will Deacon Cc: Robin Murphy Signed-off-by: Barry Song --- include/linux/dma-contiguous.h | 4 ++++ kernel/dma/Kconfig | 10 +++++++++ kernel/dma/contiguous.c | 41 +++++++++++++++++++++++++++++++++- 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/include/linux/dma-contiguous.h b/include/linux/dma-contiguous.h index 03f8e98e3bcc..278a80a40456 100644 --- a/include/linux/dma-contiguous.h +++ b/include/linux/dma-contiguous.h @@ -79,6 +79,8 @@ static inline void dma_contiguous_set_default(struct cma *cma) void dma_contiguous_reserve(phys_addr_t addr_limit); +void dma_pernuma_cma_reserve(void); + int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base, phys_addr_t limit, struct cma **res_cma, bool fixed); @@ -128,6 +130,8 @@ static inline void dma_contiguous_set_default(struct cma *cma) { } static inline void dma_contiguous_reserve(phys_addr_t limit) { } +static inline void dma_pernuma_cma_reserve(void) { } + static inline int dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base, phys_addr_t limit, struct cma **res_cma, bool fixed) diff --git a/kernel/dma/Kconfig b/kernel/dma/Kconfig index 4c103a24e380..14f4a1fe4285 100644 --- a/kernel/dma/Kconfig +++ b/kernel/dma/Kconfig @@ -100,6 +100,16 @@ config DMA_CMA if DMA_CMA comment "Default contiguous memory area size:" +config CMA_PERNUMA_SIZE_MBYTES + int "Size in Mega Bytes for per-numa CMA areas" + depends on NUMA + default 16 if ARM64 + default 0 + help + Defines the size (in MiB) of the per-numa memory area for Contiguous + Memory Allocator. Every numa node will get a separate CMA with this + size. If the size of 0 is selected, per-numa CMA is disabled. + config CMA_SIZE_MBYTES int "Size in Mega Bytes" depends on !CMA_SIZE_SEL_PERCENTAGE diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c index 8bc6f2d670f9..4b10d0ca0456 100644 --- a/kernel/dma/contiguous.c +++ b/kernel/dma/contiguous.c @@ -30,7 +30,14 @@ #define CMA_SIZE_MBYTES 0 #endif +#ifdef CONFIG_CMA_PERNUMA_SIZE_MBYTES +#define CMA_SIZE_PERNUMA_MBYTES CONFIG_CMA_PERNUMA_SIZE_MBYTES +#else +#define CMA_SIZE_PERNUMA_MBYTES 0 +#endif + struct cma *dma_contiguous_default_area; +struct cma *dma_contiguous_pernuma_area[MAX_NUMNODES]; /* * Default global CMA area size can be defined in kernel's .config. @@ -44,6 +51,8 @@ struct cma *dma_contiguous_default_area; */ static const phys_addr_t size_bytes __initconst = (phys_addr_t)CMA_SIZE_MBYTES * SZ_1M; +static const phys_addr_t pernuma_size_bytes __initconst = + (phys_addr_t)CMA_SIZE_PERNUMA_MBYTES * SZ_1M; static phys_addr_t size_cmdline __initdata = -1; static phys_addr_t base_cmdline __initdata; static phys_addr_t limit_cmdline __initdata; @@ -96,6 +105,31 @@ static inline __maybe_unused phys_addr_t cma_early_percent_memory(void) #endif +void __init dma_pernuma_cma_reserve(void) +{ + int nid; + + if (!pernuma_size_bytes || nr_online_nodes <= 1) + return; + + for_each_node_state(nid, N_ONLINE) { + int ret; + + ret = cma_declare_contiguous_nid(0, pernuma_size_bytes, 0, 0, + 0, false, "pernuma", + &dma_contiguous_pernuma_area[nid], + nid); + if (ret) { + pr_warn("%s: reservation failed: err %d, node %d", __func__, + ret, nid); + continue; + } + + pr_debug("%s: reserved %llu MiB on node %d\n", __func__, + pernuma_size_bytes / SZ_1M, nid); + } +} + /** * dma_contiguous_reserve() - reserve area(s) for contiguous memory handling * @limit: End address of the reserved memory (optional, 0 for any). @@ -223,7 +257,8 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages, * * This function allocates contiguous memory buffer for specified device. It * first tries to use device specific contiguous memory area if available or - * the default global one, then tries a fallback allocation of normal pages. + * the per-numa ones and default global one, then tries a fallback allocation + * of normal pages. per-numa memory areas don't support address limit * * Note that it byapss one-page size of allocations from the global area as * the addresses within one page are always contiguous, so there is no need @@ -234,9 +269,13 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp) size_t count = size >> PAGE_SHIFT; struct page *page = NULL; struct cma *cma = NULL; + int nid = dev_to_node(dev); if (dev && dev->cma_area) cma = dev->cma_area; + else if ((nid != NUMA_NO_NODE) && dma_contiguous_pernuma_area[nid] + && !(gfp & (GFP_DMA | GFP_DMA32))) + cma = dma_contiguous_pernuma_area[nid]; else if (count > 1) cma = dma_contiguous_default_area; -- 2.23.0