Blob Blame History Raw
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);