From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> To: amit.pundir@linaro.org, hch@lst.de, linux-kernel@vger.kernel.org, Marek Szyprowski <m.szyprowski@samsung.com>, Robin Murphy <robin.murphy@arm.com> Cc: rientjes@google.com, jeremy.linton@arm.com, linux-rpi-kernel@lists.infradead.org, Nicolas Saenz Julienne <nsaenzjulienne@suse.de>, iommu@lists.linux-foundation.org Subject: [PATCH v2 2/2] dma-pool: Only allocate from CMA when in same memory zone Date: Mon, 3 Aug 2020 18:09:56 +0200 [thread overview] Message-ID: <20200803160956.19235-3-nsaenzjulienne@suse.de> (raw) In-Reply-To: <20200803160956.19235-1-nsaenzjulienne@suse.de> There is no guarantee to CMA's placement, so allocating a zone specific atomic pool from CMA might return memory from a completely different memory zone. To get around this double check CMA's placement before allocating from it. Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> --- Changes since v1: - Make cma_in_zone() more strict, GFP_KERNEL doesn't default to true now kernel/dma/pool.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/kernel/dma/pool.c b/kernel/dma/pool.c index 5d071d4a3cba..582523ccf4fe 100644 --- a/kernel/dma/pool.c +++ b/kernel/dma/pool.c @@ -3,7 +3,9 @@ * Copyright (C) 2012 ARM Ltd. * Copyright (C) 2020 Google LLC */ +#include <linux/cma.h> #include <linux/debugfs.h> +#include <linux/dma-contiguous.h> #include <linux/dma-direct.h> #include <linux/dma-noncoherent.h> #include <linux/init.h> @@ -55,6 +57,32 @@ static void dma_atomic_pool_size_add(gfp_t gfp, size_t size) pool_size_kernel += size; } +static bool cma_in_zone(gfp_t gfp) +{ + unsigned long size; + phys_addr_t end; + struct cma *cma; + + cma = dev_get_cma_area(NULL); + if (!cma) + return false; + + size = cma_get_size(cma); + if (!size) + return false; + + /* CMA can't cross zone boundaries, see cma_activate_area() */ + end = cma_get_base(cma) - memblock_start_of_DRAM() + size - 1; + if (IS_ENABLED(CONFIG_ZONE_DMA) && (gfp & GFP_DMA)) + return end <= DMA_BIT_MASK(zone_dma_bits); + if (IS_ENABLED(CONFIG_ZONE_DMA32) && (gfp & GFP_DMA32)) + return end <= DMA_BIT_MASK(32); + if (gfp & GFP_KERNEL) + return end > DMA_BIT_MASK(32); + + return false; +} + static int atomic_pool_expand(struct gen_pool *pool, size_t pool_size, gfp_t gfp) { @@ -68,7 +96,11 @@ static int atomic_pool_expand(struct gen_pool *pool, size_t pool_size, do { pool_size = 1 << (PAGE_SHIFT + order); - page = alloc_pages(gfp, order); + if (cma_in_zone(gfp)) + page = dma_alloc_from_contiguous(NULL, 1 << order, + order, false); + if (!page) + page = alloc_pages(gfp, order); } while (!page && order-- > 0); if (!page) goto out; -- 2.28.0
WARNING: multiple messages have this Message-ID (diff)
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> To: amit.pundir@linaro.org, hch@lst.de, linux-kernel@vger.kernel.org, Marek Szyprowski <m.szyprowski@samsung.com>, Robin Murphy <robin.murphy@arm.com> Cc: iommu@lists.linux-foundation.org, linux-rpi-kernel@lists.infradead.org, jeremy.linton@arm.com, rientjes@google.com Subject: [PATCH v2 2/2] dma-pool: Only allocate from CMA when in same memory zone Date: Mon, 3 Aug 2020 18:09:56 +0200 [thread overview] Message-ID: <20200803160956.19235-3-nsaenzjulienne@suse.de> (raw) In-Reply-To: <20200803160956.19235-1-nsaenzjulienne@suse.de> There is no guarantee to CMA's placement, so allocating a zone specific atomic pool from CMA might return memory from a completely different memory zone. To get around this double check CMA's placement before allocating from it. Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> --- Changes since v1: - Make cma_in_zone() more strict, GFP_KERNEL doesn't default to true now kernel/dma/pool.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/kernel/dma/pool.c b/kernel/dma/pool.c index 5d071d4a3cba..582523ccf4fe 100644 --- a/kernel/dma/pool.c +++ b/kernel/dma/pool.c @@ -3,7 +3,9 @@ * Copyright (C) 2012 ARM Ltd. * Copyright (C) 2020 Google LLC */ +#include <linux/cma.h> #include <linux/debugfs.h> +#include <linux/dma-contiguous.h> #include <linux/dma-direct.h> #include <linux/dma-noncoherent.h> #include <linux/init.h> @@ -55,6 +57,32 @@ static void dma_atomic_pool_size_add(gfp_t gfp, size_t size) pool_size_kernel += size; } +static bool cma_in_zone(gfp_t gfp) +{ + unsigned long size; + phys_addr_t end; + struct cma *cma; + + cma = dev_get_cma_area(NULL); + if (!cma) + return false; + + size = cma_get_size(cma); + if (!size) + return false; + + /* CMA can't cross zone boundaries, see cma_activate_area() */ + end = cma_get_base(cma) - memblock_start_of_DRAM() + size - 1; + if (IS_ENABLED(CONFIG_ZONE_DMA) && (gfp & GFP_DMA)) + return end <= DMA_BIT_MASK(zone_dma_bits); + if (IS_ENABLED(CONFIG_ZONE_DMA32) && (gfp & GFP_DMA32)) + return end <= DMA_BIT_MASK(32); + if (gfp & GFP_KERNEL) + return end > DMA_BIT_MASK(32); + + return false; +} + static int atomic_pool_expand(struct gen_pool *pool, size_t pool_size, gfp_t gfp) { @@ -68,7 +96,11 @@ static int atomic_pool_expand(struct gen_pool *pool, size_t pool_size, do { pool_size = 1 << (PAGE_SHIFT + order); - page = alloc_pages(gfp, order); + if (cma_in_zone(gfp)) + page = dma_alloc_from_contiguous(NULL, 1 << order, + order, false); + if (!page) + page = alloc_pages(gfp, order); } while (!page && order-- > 0); if (!page) goto out; -- 2.28.0 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
next prev parent reply other threads:[~2020-08-03 16:10 UTC|newest] Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-08-03 16:09 [PATCH v2 0/2] dma-pool fixes Nicolas Saenz Julienne 2020-08-03 16:09 ` Nicolas Saenz Julienne 2020-08-03 16:09 ` [PATCH v2 1/2] dma-pool: fix coherent pool allocations for IOMMU mappings Nicolas Saenz Julienne 2020-08-03 16:09 ` Nicolas Saenz Julienne 2020-08-03 16:09 ` Nicolas Saenz Julienne [this message] 2020-08-03 16:09 ` [PATCH v2 2/2] dma-pool: Only allocate from CMA when in same memory zone Nicolas Saenz Julienne 2020-08-04 6:06 ` Christoph Hellwig 2020-08-04 6:06 ` Christoph Hellwig 2020-08-04 9:43 ` Nicolas Saenz Julienne 2020-08-04 9:43 ` Nicolas Saenz Julienne 2020-08-06 5:18 ` Christoph Hellwig 2020-08-06 5:18 ` Christoph Hellwig 2020-08-06 11:50 ` Nicolas Saenz Julienne 2020-08-06 11:50 ` Nicolas Saenz Julienne 2020-08-06 13:55 ` Christoph Hellwig 2020-08-06 13:55 ` Christoph Hellwig
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200803160956.19235-3-nsaenzjulienne@suse.de \ --to=nsaenzjulienne@suse.de \ --cc=amit.pundir@linaro.org \ --cc=hch@lst.de \ --cc=iommu@lists.linux-foundation.org \ --cc=jeremy.linton@arm.com \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-rpi-kernel@lists.infradead.org \ --cc=m.szyprowski@samsung.com \ --cc=rientjes@google.com \ --cc=robin.murphy@arm.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.