From: Christoph Hellwig <hch@lst.de>
Date: Tue, 9 Jan 2018 23:39:03 +0100
Subject: dma-direct: add support for allocation from ZONE_DMA and ZONE_DMA32
Git-commit: c61e9637340e1d0672c6f0c0b11aa81d7262c49d
Patch-mainline: v4.16-rc1
References: jsc#SLE-6197 FATE#327012 bsc#1140559 LTC#173150
This allows to dip into zones for lower memory if they are available.
If one of the zones is not available the corresponding GFP_* flag
will evaluate to 0 so they won't change anything. We provide an
arch tunable for those architectures that do not use GFP_DMA for
the lowest 24-bits, given that there are a few.
Roughly based on the x86 code.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
lib/dma-noop.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
--- a/lib/dma-noop.c
+++ b/lib/dma-noop.c
@@ -8,12 +8,26 @@
#include <linux/dma-direct.h>
#include <linux/scatterlist.h>
+/*
+ * Most architectures use ZONE_DMA for the first 16 Megabytes, but
+ * some use it for entirely different regions:
+ */
+#ifndef ARCH_ZONE_DMA_BITS
+#define ARCH_ZONE_DMA_BITS 24
+#endif
+
static void *dma_noop_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp,
unsigned long attrs)
{
void *ret;
+ /* GFP_DMA32 and GFP_DMA are no ops without the corresponding zones: */
+ if (dev->coherent_dma_mask <= DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))
+ gfp |= GFP_DMA;
+ if (dev->coherent_dma_mask <= DMA_BIT_MASK(32) && !(gfp & GFP_DMA))
+ gfp |= GFP_DMA32;
+
ret = (void *)__get_free_pages(gfp, get_order(size));
if (ret)
*dma_handle = virt_to_phys(ret);