Skip to contentSkip to conversation

Device Tree support for CMA (Contiguous Memory Allocator)

PATCH Superseded Marek Szyprowski 5 participants 15 messages Jul 31, 2013 – Aug 7, 2013

Subsystems (5)

v4 of 7 Superseded Latest is v7 →

lore
Share & tools
lore
#0 lore raw

v4 cover Device Tree support for CMA (Contiguous Memory Allocator)

Hello,

This is a fourth version of my proposal for device tree integration for reserved memory and Contiguous Memory Allocator. After the comments from Grant Likely I moved back memory region definitions back to /memory node (as it was in the first version of this proposal). I've also extended the code and made it more generic, added support for so called reserved dma memory (special dma memory regions created by dma_alloc_coherent() function, for exclusive usage for dma allocation for the given device).

Just a few words for those who see this code for the first time:

The proposed bindings allows to define contiguous memory regions of specified base address and size. Then, the defined regions can be assigned to the given device(s) by adding a property with a phanle to the defined contiguous memory region. From the device tree perspective that's all. Once the bindings are added, all the memory allocations from dma-mapping subsystem will be served from the defined contiguous memory regions.

Contiguous Memory Allocator is a framework, which lets to provide a large contiguous memory buffers for (usually a multimedia) devices. The contiguous memory is reserved during early boot and then shared with kernel, which is allowed to allocate it for movable pages. Then, when device driver requests a contigouous buffer, the framework migrates movable pages out of contiguous region and gives it to the driver. When device driver frees the buffer, it is added to kernel memory pool again. For more information, please refer to commit c64be2bb1c6eb43c838b2c6d57 ("drivers: add Contiguous Memory Allocator") and d484864dd96e1830e76895 (CMA merge commit).

Why we need device tree bindings for CMA at all?

Older ARM kernels used so called board-based initialization. Those board files contained a definition of all hardware blocks available on the target system and particular kernel and driver software configuration selected by the board maintainer.

In the new approach the board files will be removed completely and Device Tree approach is used to describe all hardware blocks available on the target system. By definition, the bindings should be software independent, so at least in theory it should be possible to use those bindings with other operating systems than Linux kernel.

Reserved memory configuration belongs to the grey area. It might depend on hardware restriction of the board or modules and low-level configuration done by bootloader. Putting reserved and contiguous memory regions to /memory node and having phandles to those regions in the device nodes however matches well with the device-tree typical style of linking devices with other resources like clocks, interrupts, regulators, power domains, etc. This is the main reason to use such approach instead of putting everything to /chosen node as it has been proposed in v2 and v3.

Best regards
Marek Szyprowski
Samsung R&D Institute Poland

Changelog:

v4:
- moved back contiguous-memory bindings from /chosen/contiguous-memory to /memory nodes as suggested by Grant (see
http://article.gmane.org/gmane.linux.drivers.devicetree/41030
for more details)
- added support for DMA reserved memory with dma_declare_coherent()
- moved code to drivers/of/of_reserved_mem.c
- added generic code to scan specific path in flat device tree

v3: http://thread.gmane.org/gmane.linux.drivers.devicetree/40013/
- fixed issues pointed by Laura and updated documentation

v2: http://thread.gmane.org/gmane.linux.drivers.devicetree/34075
- moved contiguous-memory bindings from /memory to /chosen/contiguous-memory/ node to avoid spreading Linux specific parameters over the whole device tree definitions
- added support for autoconfigured regions (use zero base)
- fixes minor bugs

v1: http://thread.gmane.org/gmane.linux.drivers.devicetree/30111/
- initial proposal

Patch summary:

Marek Szyprowski (4):
drivers: dma-contiguous: clean source code and prepare for device
tree
drivers: of: add function to scan fdt nodes given by path
drivers: of: add initialization code for dma reserved memory
ARM: init: add support for reserved memory defined by device tree

 Documentation/devicetree/bindings/memory.txt |  152 ++++++++++++++++++++++
 arch/arm/mm/init.c                           |    3 +
 drivers/base/dma-contiguous.c                |  147 +++++++++++-----------
 drivers/of/Kconfig                           |    6 +
 drivers/of/Makefile                          |    1 +
 drivers/of/fdt.c                             |   76 +++++++++++
 drivers/of/of_reserved_mem.c                 |  175 ++++++++++++++++++++++++++
 include/asm-generic/dma-coherent.h           |    6 +
 include/asm-generic/dma-contiguous.h         |    2 -
 include/linux/dma-contiguous.h               |   49 +++++++-
 include/linux/of_fdt.h                       |    3 +
 11 files changed, 541 insertions(+), 79 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/memory.txt
 create mode 100644 drivers/of/of_reserved_mem.c
Signature · 1 line
1.7.9.5
#1 lore raw

PATCH v4 1/4 drivers: dma-contiguous: clean source code and prepare for device tree

This patch cleans the initialization of dma contiguous framework. The all-in-one dma_declare_contiguous() function is now separated into dma_contiguous_reserve_area() which only steals the the memory from memblock allocator and dma_contiguous_add_device() function, which assigns given device to the specified reserved memory area. This improves the flexibility in defining contiguous memory areas and assigning device to them, because now it is possible to assign more than one device to the given contiguous memory area. Such split in initialization procedure is also required for upcoming device tree support.

---
 drivers/base/dma-contiguous.c        |  147 +++++++++++++++++-----------------
 include/asm-generic/dma-contiguous.h |    2 -
 include/linux/dma-contiguous.h       |   49 +++++++++++-
 3 files changed, 119 insertions(+), 79 deletions(-)
drivers/base/dma-contiguous.c +72 -75
index 0ca5442..2cc9c77 100644
@@ -96,7 +96,7 @@ static inline __maybe_unused phys_addr_t cma_early_percent_memory(void)
 #endif
 
 /**
- * dma_contiguous_reserve() - reserve area for contiguous memory handling
+ * dma_contiguous_reserve() - reserve area(s) for contiguous memory handling
  * @limit: End address of the reserved memory (optional, 0 for any).
  *
  * This function reserves memory from early allocator. It should be
@@ -124,22 +124,29 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
 #endif
 	}
 
-	if (selected_size) {
+	if (selected_size && !dma_contiguous_default_area) {
 		pr_debug("%s: reserving %ld MiB for global area\n", __func__,
 			 (unsigned long)selected_size / SZ_1M);
 
-		dma_declare_contiguous(NULL, selected_size, 0, limit);
+		dma_contiguous_reserve_area(selected_size, 0, limit,
+					    &dma_contiguous_default_area);
 	}
 };
 
 static DEFINE_MUTEX(cma_mutex);
 
-static __init int cma_activate_area(unsigned long base_pfn, unsigned long count)
+static __init int cma_activate_area(struct cma *cma)
 {
-	unsigned long pfn = base_pfn;
-	unsigned i = count >> pageblock_order;
+	int bitmap_size = BITS_TO_LONGS(cma->count) * sizeof(long);
+	unsigned long base_pfn = cma->base_pfn, pfn = base_pfn;
+	unsigned i = cma->count >> pageblock_order;
 	struct zone *zone;
 
+	cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+
+	if (!cma->bitmap)
+		return -ENOMEM;
+
 	WARN_ON_ONCE(!pfn_valid(pfn));
 	zone = page_zone(pfn_to_page(pfn));
 
@@ -153,92 +160,53 @@ static __init int cma_activate_area(unsigned long base_pfn, unsigned long count)
 		}
 		init_cma_reserved_pageblock(pfn_to_page(base_pfn));
 	} while (--i);
-	return 0;
-}
-
-static __init struct cma *cma_create_area(unsigned long base_pfn,
-				     unsigned long count)
-{
-	int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
-	struct cma *cma;
-	int ret = -ENOMEM;
-
-	pr_debug("%s(base %08lx, count %lx)\n", __func__, base_pfn, count);
-
-	cma = kmalloc(sizeof *cma, GFP_KERNEL);
-	if (!cma)
-		return ERR_PTR(-ENOMEM);
 
-	cma->base_pfn = base_pfn;
-	cma->count = count;
-	cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-
-	if (!cma->bitmap)
-		goto no_mem;
-
-	ret = cma_activate_area(base_pfn, count);
-	if (ret)
-		goto error;
-
-	pr_debug("%s: returned %p\n", __func__, (void *)cma);
-	return cma;
-
-error:
-	kfree(cma->bitmap);
-no_mem:
-	kfree(cma);
-	return ERR_PTR(ret);
+	return 0;
 }
 
-static struct cma_reserved {
-	phys_addr_t start;
-	unsigned long size;
-	struct device *dev;
-} cma_reserved[MAX_CMA_AREAS] __initdata;
-static unsigned cma_reserved_count __initdata;
+static struct cma cma_areas[MAX_CMA_AREAS];
+static unsigned cma_area_count;
 
 static int __init cma_init_reserved_areas(void)
 {
-	struct cma_reserved *r = cma_reserved;
-	unsigned i = cma_reserved_count;
-
-	pr_debug("%s()\n", __func__);
+	int i;
 
-	for (; i; --i, ++r) {
-		struct cma *cma;
-		cma = cma_create_area(PFN_DOWN(r->start),
-				      r->size >> PAGE_SHIFT);
-		if (!IS_ERR(cma))
-			dev_set_cma_area(r->dev, cma);
+	for (i = 0; i < cma_area_count; i++) {
+		int ret = cma_activate_area(&cma_areas[i]);
+		if (ret)
+			return ret;
 	}
+
 	return 0;
 }
 core_initcall(cma_init_reserved_areas);
 
 /**
- * dma_declare_contiguous() - reserve area for contiguous memory handling
- *			      for particular device
- * @dev:   Pointer to device structure.
- * @size:  Size of the reserved memory.
- * @base:  Start address of the reserved memory (optional, 0 for any).
+ * dma_contiguous_reserve_area() - reserve custom contiguous area
+ * @size: Size of the reserved area (in bytes),
+ * @base: Base address of the reserved area optional, use 0 for any
  * @limit: End address of the reserved memory (optional, 0 for any).
+ * @res_cma: Pointer to store the created cma region.
  *
- * This function reserves memory for specified device. It should be
- * called by board specific code when early allocator (memblock or bootmem)
- * is still activate.
+ * This function reserves memory from early allocator. It should be
+ * called by arch specific code once the early allocator (memblock or bootmem)
+ * has been activated and all other subsystems have already allocated/reserved
+ * memory. This function allows to create custom reserved areas for specific
+ * devices.
  */
-int __init dma_declare_contiguous(struct device *dev, phys_addr_t size,
-				  phys_addr_t base, phys_addr_t limit)
+int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
+				       phys_addr_t limit, struct cma **res_cma)
 {
-	struct cma_reserved *r = &cma_reserved[cma_reserved_count];
+	struct cma *cma = &cma_areas[cma_area_count];
 	phys_addr_t alignment;
+	int ret = 0;
 
 	pr_debug("%s(size %lx, base %08lx, limit %08lx)\n", __func__,
 		 (unsigned long)size, (unsigned long)base,
 		 (unsigned long)limit);
 
 	/* Sanity checks */
-	if (cma_reserved_count == ARRAY_SIZE(cma_reserved)) {
+	if (cma_area_count == ARRAY_SIZE(cma_areas)) {
 		pr_err("Not enough slots for CMA reserved regions!\n");
 		return -ENOSPC;
 	}
@@ -256,7 +224,7 @@ int __init dma_declare_contiguous(struct device *dev, phys_addr_t size,
 	if (base) {
 		if (memblock_is_region_reserved(base, size) ||
 		    memblock_reserve(base, size) < 0) {
-			base = -EBUSY;
+			ret = -EBUSY;
 			goto err;
 		}
 	} else {
@@ -266,7 +234,7 @@ int __init dma_declare_contiguous(struct device *dev, phys_addr_t size,
 		 */
 		phys_addr_t addr = __memblock_alloc_base(size, alignment, limit);
 		if (!addr) {
-			base = -ENOMEM;
+			ret = -ENOMEM;
 			goto err;
 		} else {
 			base = addr;
@@ -277,10 +245,11 @@ int __init dma_declare_contiguous(struct device *dev, phys_addr_t size,
 	 * Each reserved area must be initialised later, when more kernel
 	 * subsystems (like slab allocator) are available.
 	 */
-	r->start = base;
-	r->size = size;
-	r->dev = dev;
-	cma_reserved_count++;
+	cma->base_pfn = PFN_DOWN(base);
+	cma->count = size >> PAGE_SHIFT;
+	*res_cma = cma;
+	cma_area_count++;
+
 	pr_info("CMA: reserved %ld MiB at %08lx\n", (unsigned long)size / SZ_1M,
 		(unsigned long)base);
 
@@ -289,9 +258,37 @@ int __init dma_declare_contiguous(struct device *dev, phys_addr_t size,
 	return 0;
 err:
 	pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M);
-	return base;
+	return ret;
+}
+
+/**
+ * dma_contiguous_add_device() - add device to custom contiguous reserved area
+ * @dev:   Pointer to device structure.
+ * @cma:   Pointer to the cma structure for the reserved area
+ *
+ * This function assigns the given device to the contiguous memory area
+ * reserved earlier by dma_contiguous_reserve_area() function.
+ */
+int __init dma_contiguous_add_device(struct device *dev, struct cma *cma)
+{
+	dev_set_cma_area(dev, cma);
+	return 0;
+}
+
+/**
+ * dma_contiguous_set_default_area() - set global contiguous reserved area
+ * @cma:   Pointer to the cma structure for the reserved area
+ *
+ * This function sets global, device independent contiguous memory area to
+ * the area created earlier by dma_contiguous_reserve_area() function.
+ */
+int __init dma_contiguous_set_default_area(struct cma *cma)
+{
+	dma_contiguous_default_area = cma;
+	return 0;
 }
 
+
 /**
  * dma_alloc_from_contiguous() - allocate pages from contiguous area
  * @dev:   Pointer to device for which the allocation is performed.
include/asm-generic/dma-contiguous.h +0 -2
index 294b1e7..8979f86 100644
@@ -18,8 +18,6 @@ static inline void dev_set_cma_area(struct device *dev, struct cma *cma)
 {
 	if (dev)
 		dev->cma_area = cma;
-	if (!dev && !dma_contiguous_default_area)
-		dma_contiguous_default_area = cma;
 }
 
 #endif
include/linux/dma-contiguous.h +47 -2

61 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#2 lore raw

PATCH v4 1/4 drivers: dma-contiguous: clean source code and prepare for device tree

Quoted 10 lines · Marek Szyprowski

This patch cleans the initialization of dma contiguous framework. The all-in-one dma_declare_contiguous() function is now separated into dma_contiguous_reserve_area() which only steals the the memory from memblock allocator and dma_contiguous_add_device() function, which assigns given device to the specified reserved memory area. This improves the flexibility in defining contiguous memory areas and assigning device to them, because now it is possible to assign more than one device to the given contiguous memory area. Such split in initialization procedure is also required for upcoming device tree support.

Quoted 2 lines

Even though I have some comments.

drivers/base/dma-contiguous.c void __init dma_contiguous_reserve(phys_addr_t limit) · line 127

Quoted 6 lines
drivers/base/dma-contiguous.c +1 -1
@@ -124,22 +124,29 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
 #endif
 	}
 
-	if (selected_size) {
+	if (selected_size && !dma_contiguous_default_area) {

Perhaps check this earlier in the function? Also, maybe WARN would be in order when dma_contiguous_reserve is called with dma_contiguous_default_area already reserved.

Quoted 18 lines
drivers/base/dma-contiguous.c +4 -3
 		pr_debug("%s: reserving %ld MiB for global area\n", __func__,
 			 (unsigned long)selected_size / SZ_1M);
 
-		dma_declare_contiguous(NULL, selected_size, 0, limit);
+		dma_contiguous_reserve_area(selected_size, 0, limit,
+					    &dma_contiguous_default_area);
 	}
 };
 
 static DEFINE_MUTEX(cma_mutex);
 
 
-int __init dma_declare_contiguous(struct device *dev, phys_addr_t size,
-				  phys_addr_t base, phys_addr_t limit)
+int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
+				       phys_addr_t limit, struct cma **res_cma)
 

drivers/base/dma-contiguous.c int __init dma_declare_contiguous(struct device *dev, phys_addr_t size, · line 250

Quoted 10 lines
drivers/base/dma-contiguous.c +3 -4
@@ -277,10 +245,11 @@ int __init dma_declare_contiguous(struct device *dev, phys_addr_t size,
 	 * Each reserved area must be initialised later, when more kernel
 	 * subsystems (like slab allocator) are available.
 	 */
-	r->start = base;
-	r->size = size;
-	r->dev = dev;
-	cma_reserved_count++;
+	cma->base_pfn = PFN_DOWN(base);
+	cma->count = size >> PAGE_SHIFT;
+	*res_cma = cma;

Alternatively it could return a pointer, but either way?

drivers/base/dma-contiguous.c int __init dma_declare_contiguous(struct device *dev, phys_addr_t size, · line 276

Quoted 11 lines
drivers/base/dma-contiguous.c +7 -0
+	cma_area_count++;
+
 	pr_info("CMA: reserved %ld MiB at %08lx\n", (unsigned long)size / SZ_1M,
 		(unsigned long)base);
 
 
+int __init dma_contiguous_add_device(struct device *dev, struct cma *cma)
+{
+	dev_set_cma_area(dev, cma);
+	return 0;
+}

This never fails and it is used in dma_declare_contiguous w/o checking for errors so perhaps it should return void? Applies to some other functions as well.

Moreover, this function is so tiny, it makes me wonder why does it exist in the first place (why would anyone call it rather then dev_set_cma_area? is it just matter of name?), and since it exists, why not put it to a header file as a static inline.

drivers/base/dma-contiguous.c int __init dma_declare_contiguous(struct device *dev, phys_addr_t size, · line 289

Quoted 5 lines
drivers/base/dma-contiguous.c +4 -0
+int __init dma_contiguous_set_default_area(struct cma *cma)
+{
+	dma_contiguous_default_area = cma;
+	return 0;
 }

Ditto.

include/linux/dma-contiguous.h struct device; · line 95

Quoted 5 lines
include/linux/dma-contiguous.h +5 -0
+static inline int dma_declare_contiguous(struct device *dev, phys_addr_t size,
+					 phys_addr_t base, phys_addr_t limit)
+{
+	struct cma *cma;
+	int ret;

+ if (WARN_ON(!dev))
+ return -EINVAL;

Quoted 6 lines
include/linux/dma-contiguous.h +6 -0
+	ret = dma_contiguous_reserve_area(size, base, limit, &cma);
+	if (ret == 0)
+		dma_contiguous_add_device(dev, cma);
+
+	return ret;
+}
Signature · 11 lines
Best regards,                                         _     _
.o. | Liege of Serenely Enlightened Majesty of      o' \,=./ `o
..o | Computer Science,  Micha? ?mina86? Nazarewicz    (o o)
ooo +----<email/xmpp: [email protected]>--------------ooO--(_)--Ooo--
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130805/76f09c24/attachment.sig>
#3 lore raw

PATCH v4 2/4 drivers: of: add function to scan fdt nodes given by path

In reply to Marek Szyprowski

Add a function to scan the flattened device-tree starting from the node given by the path. It is used to extract information (like reserved memory), which is required on ealy boot before we can unflatten the tree.

---
 drivers/of/fdt.c       |   76 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_fdt.h |    3 ++
 2 files changed, 79 insertions(+)
drivers/of/fdt.c +76 -0
index 6bb7cf2..8d6e7e8 100644
@@ -543,6 +543,82 @@ int __init of_flat_dt_match(unsigned long node, const char *const *compat)
 	return of_fdt_match(initial_boot_params, node, compat);
 }
 
+struct fdt_scan_status {
+	const char *name;
+	int namelen;
+	int depth;
+	int found;
+	int (*iterator)(unsigned long node, const char *uname, int depth, void *data);
+	void *data;
+};
+
+/**
+ * fdt_scan_node_by_path - iterator for of_scan_flat_dt_by_path function
+ */
+static int __init fdt_scan_node_by_path(unsigned long node, const char *uname,
+					int depth, void *data)
+{
+	struct fdt_scan_status *st = data;
+
+	/*
+	 * if scan at the requested fdt node has been completed,
+	 * return -ENXIO to abort further scanning
+	 */
+	if (depth <= st->depth)
+		return -ENXIO;
+
+	/* requested fdt node has been found, so call iterator function */
+	if (st->found)
+		return st->iterator(node, uname, depth, st->data);
+
+	/* check if scanning automata is entering next level of fdt nodes */
+	if (depth == st->depth + 1 &&
+	    strncmp(st->name, uname, st->namelen) == 0) {
+		st->depth += 1;
+		if (st->name[st->namelen] == 0) {
+			st->found = 1;
+		} else {
+			const char *next = st->name + st->namelen + 1;
+			const char *p = next;
+			while (*p != '/' && *p != 0)
+				p++;
+			st->name = next;
+			st->namelen = p - next;
+		}
+		return 0;
+	}
+
+	/* scan next fdt node */
+	return 0;
+}
+
+/**
+ * of_scan_flat_dt_by_path - scan flattened tree blob and call callback on each
+ *			     child of the given path.
+ * @path: path to start searching for children
+ * @it: callback function
+ * @data: context data pointer
+ *
+ * This function is used to scan the flattened device-tree starting from the
+ * node given by path. It is used to extract information (like reserved
+ * memory), which is required on ealy boot before we can unflatten the tree.
+ */
+int __init of_scan_flat_dt_by_path(const char *path,
+	int (*it)(unsigned long node, const char *name, int depth, void *data),
+	void *data)
+{
+	struct fdt_scan_status st = {path, 0, -1, 0, it, data};
+	int ret = 0;
+
+	if (initial_boot_params)
+		ret = of_scan_flat_dt(fdt_scan_node_by_path, &st);
+
+	if (st.found && ret == -ENXIO)	/* scan has been completed */
+		return 0;
+	else
+		return -ENOENT;
+}
+
 #ifdef CONFIG_BLK_DEV_INITRD
 /**
  * early_init_dt_check_for_initrd - Decode initrd location from flat tree
include/linux/of_fdt.h +3 -0
index ed136ad..1151a7f 100644
@@ -90,6 +90,9 @@ extern void *of_get_flat_dt_prop(unsigned long node, const char *name,
 extern int of_flat_dt_is_compatible(unsigned long node, const char *name);
 extern int of_flat_dt_match(unsigned long node, const char *const *matches);
 extern unsigned long of_get_flat_dt_root(void);
+extern int __init of_scan_flat_dt_by_path(const char *path,
+	int (*it)(unsigned long node, const char *name, int depth, void *data),
+	void *data);
 
 extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
 				     int depth, void *data);
Signature · 1 line
1.7.9.5
#4 lore raw

PATCH v4 2/4 drivers: of: add function to scan fdt nodes given by path

Quoted 3 lines · Marek Szyprowski

Add a function to scan the flattened device-tree starting from the node given by the path. It is used to extract information (like reserved memory), which is required on ealy boot before we can unflatten the

                                ^^^^ early
Quoted 4 lines

tree.

Some minor comments inline.

Quoted 9 lines
drivers/of/fdt.c +9 -0
+static int __init fdt_scan_node_by_path(unsigned long node, const char *uname,
+					int depth, void *data)
+{
+	struct fdt_scan_status *st = data;
+
+	/*
+	 * if scan at the requested fdt node has been completed,
+	 * return -ENXIO to abort further scanning
+	 */

drivers/of/fdt.c int __init of_flat_dt_match(unsigned long node, const char *const *compat) · line 576

Quoted 10 lines
drivers/of/fdt.c +10 -0
+	if (depth <= st->depth)
+		return -ENXIO;
+
+	/* requested fdt node has been found, so call iterator function */
+	if (st->found)
+		return st->iterator(node, uname, depth, st->data);
+
+	/* check if scanning automata is entering next level of fdt nodes */
+	if (depth == st->depth + 1 &&
+	    strncmp(st->name, uname, st->namelen) == 0) {

+ strncmp(st->name, uname, st->namelen) == 0 &&
+ uname[st->namelen] == 0) {

drivers/of/fdt.c int __init of_flat_dt_match(unsigned long node, const char *const *compat) · line 586

Quoted 10 lines
drivers/of/fdt.c +10 -0
+		st->depth += 1;
+		if (st->name[st->namelen] == 0) {
+			st->found = 1;
+		} else {
+			const char *next = st->name + st->namelen + 1;
+			const char *p = next;
+			while (*p != '/' && *p != 0)
+				p++;
+			st->name = next;
+			st->namelen = p - next;

+ st->namelen = strcspn(next, "/");

except this might be slightly slower since the second argument is looped over, but something to consider I guess since it get rid of few of the lines of code.

Quoted 23 lines
drivers/of/fdt.c +23 -0
+		}
+		return 0;
+	}
+
+	/* scan next fdt node */
+	return 0;
+}
+
+/**
+ * of_scan_flat_dt_by_path - scan flattened tree blob and call callback on each
+ *			     child of the given path.
+ * @path: path to start searching for children
+ * @it: callback function
+ * @data: context data pointer
+ *
+ * This function is used to scan the flattened device-tree starting from the
+ * node given by path. It is used to extract information (like reserved
+ * memory), which is required on ealy boot before we can unflatten the tree.
+ */
+int __init of_scan_flat_dt_by_path(const char *path,
+	int (*it)(unsigned long node, const char *name, int depth, void *data),
+	void *data)
+{

drivers/of/fdt.c int __init of_flat_dt_match(unsigned long node, const char *const *compat) · line 619

Quoted 10 lines
drivers/of/fdt.c +10 -0
+	struct fdt_scan_status st = {path, 0, -1, 0, it, data};
+	int ret = 0;
+
+	if (initial_boot_params)
+		ret = of_scan_flat_dt(fdt_scan_node_by_path, &st);
+
+	if (st.found && ret == -ENXIO)	/* scan has been completed */
+		return 0;
+	else
+		return -ENOENT;

Perhaps propagate ret:

+ if (!st.found)
+ return -ENOENT;
+ else if (ret == -ENXIO)
+ return 0;
+ else
+ return ret;

Quoted 5 lines
drivers/of/fdt.c +2 -0
+}
+
 #ifdef CONFIG_BLK_DEV_INITRD
 /**
  * early_init_dt_check_for_initrd - Decode initrd location from flat tree
Signature · 11 lines
Best regards,                                         _     _
.o. | Liege of Serenely Enlightened Majesty of      o' \,=./ `o
..o | Computer Science,  Micha? ?mina86? Nazarewicz    (o o)
ooo +----<email/xmpp: [email protected]>--------------ooO--(_)--Ooo--
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130805/6cec4a65/attachment.sig>
#5 lore raw

PATCH v4 3/4 drivers: of: add initialization code for dma reserved memory

In reply to Marek Szyprowski

Add device tree support for contiguous and reserved memory regions defined in device tree. Initialization is done in 2 steps. First, the memory is reserved, what happens very early when only flattened device tree is available. Then on device initialization the corresponding cma and reserved regions are assigned to each device structure.

---
 Documentation/devicetree/bindings/memory.txt |  152 ++++++++++++++++++++++
 drivers/of/Kconfig                           |    6 +
 drivers/of/Makefile                          |    1 +
 drivers/of/of_reserved_mem.c                 |  175 ++++++++++++++++++++++++++
 include/asm-generic/dma-coherent.h           |    6 +
 5 files changed, 340 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/memory.txt
 create mode 100644 drivers/of/of_reserved_mem.c
Documentation/devicetree/bindings/memory.txt new file +152 -0
new file mode 100644
index 0000000..4aece19
@@ -0,0 +1,152 @@
+*** Memory binding ***
+
+The /memory node provides basic information about the address and size
+of the physical memory. This node is usually filled or updated by the
+bootloader, depending on the actual memory configuration of the given
+hardware.
+
+The memory layout is described by the folllowing node:
+
+memory {
+	reg =  <(baseaddr1) (size1)
+		(baseaddr2) (size2)
+		...
+		(baseaddrN) (sizeN)>;
+};
+
+baseaddrX:	the base address of the defined memory bank
+sizeX:		the size of the defined memory bank
+
+More than one memory bank can be defined.
+
+
+*** Reserved memory regions ***
+
+In /memory/reserved-memory node one can create additional nodes
+describing particular reserved (excluded from normal use) memory
+regions. Such memory regions are usually designed for the special usage
+by various device drivers. A good example are contiguous memory
+allocations or memory sharing with other operating system on the same
+hardware board. Those special memory regions might depend on the board
+configuration and devices used on the target system.
+
+Parameters for each memory region can be encoded into the device tree
+wit the following convention:
+
+[(label):] (name)@(address) {
+	compatible = "contiguous-memory-region", "reserved-memory-region";
+	reg = <(address) (size)>;
+	(linux,contiguous-region);
+	(linux,default-contiguous-region);
+};
+
+label:		label given to the defined region (optional)
+name:		an name given to the defined region
+address:	the base address of the defined region
+size:		the size of the memory region
+
+compatible:	"contiguous-memory-region" - enables binding of this
+		region to Contiguous Memory Allocator (special region for
+		contiguous memory allocations, shared with movable system
+		memory, Linux kernel-specific), alternatively if
+		"reserved-memory-region" - compatibility is defined, given
+		region is assigned for exclusive usage for DMA transfers
+
+linux,default-contiguous-region: property indicating that the region
+		is the default region for all contiguous memory
+		allocations, Linux specific (optional)
+
+Each defined region must use unique name. It is optional to specify the
+base address, so if one wants to use autoconfiguration of the base
+address, he must specify the '0' as base address in the 'reg' property
+and assign ann uniqe name to such regions.
+
+
+*** Device node's properties ***
+
+Once the regions in the /memory/reserved-memory node are defined, they
+can be assigned to device nodes to enable drivers for their special use.
+The following properties are defined:
+
+dma-memory-region = <&phandle_to_defined_region>;
+
+This property indicates that the device driver should use the
+memory region pointed by the given phandle.
+
+
+*** Example ***
+
+This example defines a memory consisting of 4 memory banks. 3 contiguous
+regions are defined for Linux kernel, one default of all device drivers
+(named contig_mem, placed at 0x72000000, 64MiB), one dedicated to the
+framebuffer device (labelled display_mem, placed at 0x78000000, 8MiB)
+and one for multimedia processing (labelled multimedia_mem, placed at
+0x77000000, 64MiB). 'display_mem' region is then assigned to fb at 12300000
+device for DMA memory allocations (Linux kernel drivers will use CMA is
+available or dma-exclusive usage otherwise). 'multimedia_mem' is
+assigned to scaller at 12500000 and codec at 12600000 devices for contiguous
+memory allocations when CMA driver is enabled.
+
+The reason for creating a separate region for framebuffer device is to
+match the framebuffer base address to the one configured by bootloader,
+so once Linux kernel drivers starts no glitches on the displayed boot
+logo appears. Scaller and codec drivers should share the memory
+allocations.
+
+/ {
+	/* ... */
+	memory {
+		reg =  <0x40000000 0x10000000
+			0x50000000 0x10000000
+			0x60000000 0x10000000
+			0x70000000 0x10000000>;
+
+		reserved-memory {
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			/*
+			 * global autoconfigured region for contiguous allocations
+			 * (used only with Contiguous Memory Allocator)
+			 */
+			contig_region at 0 {
+				compatible = "contiguous-memory-region";
+				reg = <0x0 0x4000000>;
+				linux,default-contiguous-region;
+			};
+
+			/*
+			 * special region for framebuffer
+			 */
+			display_mem: region at 78000000 {
+				compatible = "contiguous-memory-region", "reserved-memory-region";
+				reg = <0x78000000 0x800000>;
+			};
+
+			/*
+			 * special region for multimedia processing devices
+			 */
+			multimedia_mem: region at 77000000 {
+				compatible = "contiguous-memory-region";
+				reg = <0x77000000 0x4000000>;
+			};
+		};
+	};
+
+	/* ... */
+
+	fb0: fb at 12300000 {
+		status = "okay";
+		dma-memory-region = <&display_mem>;
+	};
+
+	scaller: scaller at 12500000 {
+		status = "okay";
+		dma-memory-region = <&multimedia_mem>;
+	};
+
+	codec: codec at 12600000 {
+		status = "okay";
+		dma-memory-region = <&multimedia_mem>;
+	};
+};
drivers/of/Kconfig +6 -0
index 80e5c13..a83ab43 100644
@@ -80,4 +80,10 @@ config OF_MTD
 	depends on MTD
 	def_bool y
 
+config OF_RESERVED_MEM
+	depends on CMA || (HAVE_GENERIC_DMA_COHERENT && HAVE_MEMBLOCK)
+	def_bool y
+	help
+	  Initialization code for DMA reserved memory
+
 endmenu # OF
drivers/of/Makefile +1 -0
index 1f9c0c4..e7e3322 100644
@@ -10,3 +10,4 @@ obj-$(CONFIG_OF_MDIO)	+= of_mdio.o
 obj-$(CONFIG_OF_PCI)	+= of_pci.o
 obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
 obj-$(CONFIG_OF_MTD)	+= of_mtd.o
+obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
drivers/of/of_reserved_mem.c new file +175 -0

175 lines not on this page · raw message

include/asm-generic/dma-coherent.h +6 -0
index 2be8a2d..06111d00 100644
@@ -32,4 +32,10 @@ dma_mark_declared_memory_occupied(struct device *dev,
 #define dma_mmap_from_coherent(dev, vma, vaddr, order, ret) (0)
 #endif
 
+#ifdef CONFIG_OF_RESERVED_MEM
+void __init dma_reserved_mem_of_reserve(void);
+#else
+#define dma_reserved_mem_of_reserve()
+#endif
+
 #endif
Signature · 1 line
1.7.9.5
#6 lore raw

PATCH v4 3/4 drivers: of: add initialization code for dma reserved memory

Quoted 8 lines · Marek Szyprowski

Add device tree support for contiguous and reserved memory regions defined in device tree. Initialization is done in 2 steps. First, the memory is reserved, what happens very early when only flattened device tree is available. Then on device initialization the corresponding cma and reserved regions are assigned to each device structure.

Minor comments inline.

Quoted 233 lines
---
 Documentation/devicetree/bindings/memory.txt |  152 ++++++++++++++++++++++
 drivers/of/Kconfig                           |    6 +
 drivers/of/Makefile                          |    1 +
 drivers/of/of_reserved_mem.c                 |  175 ++++++++++++++++++++++++++
 include/asm-generic/dma-coherent.h           |    6 +
 5 files changed, 340 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/memory.txt
 create mode 100644 drivers/of/of_reserved_mem.c
Documentation/devicetree/bindings/memory.txt new file +152 -0
new file mode 100644
index 0000000..4aece19
@@ -0,0 +1,152 @@
+*** Memory binding ***
+
+The /memory node provides basic information about the address and size
+of the physical memory. This node is usually filled or updated by the
+bootloader, depending on the actual memory configuration of the given
+hardware.
+
+The memory layout is described by the folllowing node:
+
+memory {
+	reg =  <(baseaddr1) (size1)
+		(baseaddr2) (size2)
+		...
+		(baseaddrN) (sizeN)>;
+};
+
+baseaddrX:	the base address of the defined memory bank
+sizeX:		the size of the defined memory bank
+
+More than one memory bank can be defined.
+
+
+*** Reserved memory regions ***
+
+In /memory/reserved-memory node one can create additional nodes
+describing particular reserved (excluded from normal use) memory
+regions. Such memory regions are usually designed for the special usage
+by various device drivers. A good example are contiguous memory
+allocations or memory sharing with other operating system on the same
+hardware board. Those special memory regions might depend on the board
+configuration and devices used on the target system.
+
+Parameters for each memory region can be encoded into the device tree
+wit the following convention:
+
+[(label):] (name)@(address) {
+	compatible = "contiguous-memory-region", "reserved-memory-region";
+	reg = <(address) (size)>;
+	(linux,contiguous-region);
+	(linux,default-contiguous-region);
+};
+
+label:		label given to the defined region (optional)
+name:		an name given to the defined region
+address:	the base address of the defined region
+size:		the size of the memory region
+
+compatible:	"contiguous-memory-region" - enables binding of this
+		region to Contiguous Memory Allocator (special region for
+		contiguous memory allocations, shared with movable system
+		memory, Linux kernel-specific), alternatively if
+		"reserved-memory-region" - compatibility is defined, given
+		region is assigned for exclusive usage for DMA transfers
+
+linux,default-contiguous-region: property indicating that the region
+		is the default region for all contiguous memory
+		allocations, Linux specific (optional)
+
+Each defined region must use unique name. It is optional to specify the
+base address, so if one wants to use autoconfiguration of the base
+address, he must specify the '0' as base address in the 'reg' property
+and assign ann uniqe name to such regions.
+
+
+*** Device node's properties ***
+
+Once the regions in the /memory/reserved-memory node are defined, they
+can be assigned to device nodes to enable drivers for their special use.
+The following properties are defined:
+
+dma-memory-region = <&phandle_to_defined_region>;
+
+This property indicates that the device driver should use the
+memory region pointed by the given phandle.
+
+
+*** Example ***
+
+This example defines a memory consisting of 4 memory banks. 3 contiguous
+regions are defined for Linux kernel, one default of all device drivers
+(named contig_mem, placed at 0x72000000, 64MiB), one dedicated to the
+framebuffer device (labelled display_mem, placed at 0x78000000, 8MiB)
+and one for multimedia processing (labelled multimedia_mem, placed at
+0x77000000, 64MiB). 'display_mem' region is then assigned to fb at 12300000
+device for DMA memory allocations (Linux kernel drivers will use CMA is
+available or dma-exclusive usage otherwise). 'multimedia_mem' is
+assigned to scaller at 12500000 and codec at 12600000 devices for contiguous
+memory allocations when CMA driver is enabled.
+
+The reason for creating a separate region for framebuffer device is to
+match the framebuffer base address to the one configured by bootloader,
+so once Linux kernel drivers starts no glitches on the displayed boot
+logo appears. Scaller and codec drivers should share the memory
+allocations.
+
+/ {
+	/* ... */
+	memory {
+		reg =  <0x40000000 0x10000000
+			0x50000000 0x10000000
+			0x60000000 0x10000000
+			0x70000000 0x10000000>;
+
+		reserved-memory {
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			/*
+			 * global autoconfigured region for contiguous allocations
+			 * (used only with Contiguous Memory Allocator)
+			 */
+			contig_region at 0 {
+				compatible = "contiguous-memory-region";
+				reg = <0x0 0x4000000>;
+				linux,default-contiguous-region;
+			};
+
+			/*
+			 * special region for framebuffer
+			 */
+			display_mem: region at 78000000 {
+				compatible = "contiguous-memory-region", "reserved-memory-region";
+				reg = <0x78000000 0x800000>;
+			};
+
+			/*
+			 * special region for multimedia processing devices
+			 */
+			multimedia_mem: region at 77000000 {
+				compatible = "contiguous-memory-region";
+				reg = <0x77000000 0x4000000>;
+			};
+		};
+	};
+
+	/* ... */
+
+	fb0: fb at 12300000 {
+		status = "okay";
+		dma-memory-region = <&display_mem>;
+	};
+
+	scaller: scaller at 12500000 {
+		status = "okay";
+		dma-memory-region = <&multimedia_mem>;
+	};
+
+	codec: codec at 12600000 {
+		status = "okay";
+		dma-memory-region = <&multimedia_mem>;
+	};
+};
drivers/of/Kconfig +6 -0
index 80e5c13..a83ab43 100644
@@ -80,4 +80,10 @@ config OF_MTD
 	depends on MTD
 	def_bool y
 
+config OF_RESERVED_MEM
+	depends on CMA || (HAVE_GENERIC_DMA_COHERENT && HAVE_MEMBLOCK)
+	def_bool y
+	help
+	  Initialization code for DMA reserved memory
+
 endmenu # OF
drivers/of/Makefile +1 -0
index 1f9c0c4..e7e3322 100644
@@ -10,3 +10,4 @@ obj-$(CONFIG_OF_MDIO)	+= of_mdio.o
 obj-$(CONFIG_OF_PCI)	+= of_pci.o
 obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
 obj-$(CONFIG_OF_MTD)	+= of_mtd.o
+obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
drivers/of/of_reserved_mem.c new file +35 -0
new file mode 100644
index 0000000..d97fcdf
@@ -0,0 +1,175 @@
+/*
+ * Device tree based initialization code for reserved memory.
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Author: Marek Szyprowski <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License or (at your optional) any later version of the license.
+ */
+
+#include <asm/dma-contiguous.h>
+
+#include <linux/memblock.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+#include <linux/mm.h>
+#include <linux/sizes.h>
+#include <linux/mm_types.h>
+#include <linux/dma-contiguous.h>
+#include <linux/dma-mapping.h>
+
+#define MAX_RESERVED_REGIONS	16
+struct reserved_mem {
+	phys_addr_t		base;
+	unsigned long		size;
+	struct cma		*cma;
+	char			name[32];
+};
+static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
+static int reserved_mem_count;

drivers/of/of_reserved_mem.c line 45

Quoted 10 lines
drivers/of/of_reserved_mem.c new file +10 -0
+
+static int __init reserved_mem_fdt_scan(unsigned long node, const char *uname,
+				    int depth, void *data)
+{
+	phys_addr_t base, size;
+	int is_cma, is_reserved;
+	unsigned long len;
+	void *prop;
+
+	is_cma = of_flat_dt_is_compatible(node, "contiguous-memory-region");

Perhaps:

+ is_cma = IS_ENABLED(CONFIG_CMA) &&
+ of_flat_dt_is_compatible(node, "contiguous-memory-region");

which will save on typing IS_ENABLED(CONFIG_CMA) later on.

drivers/of/of_reserved_mem.c line 46

Quoted 1 line
drivers/of/of_reserved_mem.c new file +1 -0
+	is_reserved = of_flat_dt_is_compatible(node, "reserved-memory-region");

is_reserved value is used only if !is_cma, so maybe skip computing it if is_cma? Just a thought.

Quoted 14 lines
drivers/of/of_reserved_mem.c new file +14 -0
+
+	if (!is_reserved && !(is_cma && IS_ENABLED(CONFIG_CMA)))
+		return 0;
+
+	prop = of_get_flat_dt_prop(node, "reg", &len);
+	if (!prop || (len != 2 * sizeof(unsigned long))) {
+		pr_err("Reserved mem: node %s, incorrect \"reg\" property\n",
+		       uname);
+		return 0;
+	}
+
+	if (sizeof(unsigned long) == 4) {
+		base = be32_to_cpu(((__be32 *)prop)[0]);
+		size = be32_to_cpu(((__be32 *)prop)[1]);

drivers/of/of_reserved_mem.c line 70

Quoted 10 lines
drivers/of/of_reserved_mem.c new file +10 -0
+	} else {
+		base = be64_to_cpu(((__be64 *)prop)[0]);
+		size = be64_to_cpu(((__be64 *)prop)[1]);
+	}
+
+	pr_info("Reserved mem: found %s, memory base %lx, size %ld MiB\n",
+		uname, (unsigned long)base, (unsigned long)size / SZ_1M);
+
+	if (reserved_mem_count == ARRAY_SIZE(reserved_mem))
+		return -ENOMEM;

+ return -ENOSPC;

drivers/of/of_reserved_mem.c line 74

Quoted 4 lines
drivers/of/of_reserved_mem.c new file +4 -0
+
+	reserved_mem[reserved_mem_count].base = base;
+	reserved_mem[reserved_mem_count].size = size;
+	strcpy(reserved_mem[reserved_mem_count].name, uname);

strlcpy(reserved_mem[reserved_mem_count].name,

        sizeof(reserved_mem[reserved_mem_count].name), uname);
Quoted 27 lines
drivers/of/of_reserved_mem.c new file +21 -0
+
+	if (IS_ENABLED(CONFIG_CMA) && is_cma) {
+		struct cma *cma;
+		if (dma_contiguous_reserve_area(size, base, 0, &cma) == 0) {
+			reserved_mem[reserved_mem_count].cma = cma;
+			reserved_mem_count++;
+
+			if (of_get_flat_dt_prop(node,
+						"linux,default-contiguous-region",
+						NULL))
+				dma_contiguous_set_default_area(cma);
+		}
+	} else if (is_reserved) {
+		if (memblock_remove(base, size) == 0)
+			reserved_mem_count++;
+		else
+			pr_err("Failed to reserve memory for %s\n", uname);
+	}
+
+	return 0;
+}
include/asm-generic/dma-coherent.h +0 -0
index 2be8a2d..06111d00 100644

include/asm-generic/dma-coherent.h dma_mark_declared_memory_occupied(struct device *dev, · line 38

Quoted 7 lines
include/asm-generic/dma-coherent.h +4 -0
@@ -32,4 +32,10 @@ dma_mark_declared_memory_occupied(struct device *dev,
 #define dma_mmap_from_coherent(dev, vma, vaddr, order, ret) (0)
 #endif
 
+#ifdef CONFIG_OF_RESERVED_MEM
+void __init dma_reserved_mem_of_reserve(void);
+#else
+#define dma_reserved_mem_of_reserve()

+#define dma_reserved_mem_of_reserve() (void)0

Quoted 3 lines
include/asm-generic/dma-coherent.h +2 -0
+#endif
+
 #endif
Signature · 11 lines
Best regards,                                         _     _
.o. | Liege of Serenely Enlightened Majesty of      o' \,=./ `o
..o | Computer Science,  Micha? ?mina86? Nazarewicz    (o o)
ooo +----<email/xmpp: [email protected]>--------------ooO--(_)--Ooo--
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130805/23e6f7c4/attachment.sig>
#7 lore raw

PATCH v4 3/4 drivers: of: add initialization code for dma reserved memory

In reply to Marek Szyprowski
Quoted 29 lines · Marek Szyprowski

Add device tree support for contiguous and reserved memory regions defined in device tree. Initialization is done in 2 steps. First, the memory is reserved, what happens very early when only flattened device tree is available. Then on device initialization the corresponding cma and reserved regions are assigned to each device structure.

---
 Documentation/devicetree/bindings/memory.txt |  152 ++++++++++++++++++++++
 drivers/of/Kconfig                           |    6 +
 drivers/of/Makefile                          |    1 +
 drivers/of/of_reserved_mem.c                 |  175 ++++++++++++++++++++++++++
 include/asm-generic/dma-coherent.h           |    6 +
 5 files changed, 340 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/memory.txt
 create mode 100644 drivers/of/of_reserved_mem.c
Documentation/devicetree/bindings/memory.txt new file +5 -0
new file mode 100644
index 0000000..4aece19
@@ -0,0 +1,152 @@
+*** Memory binding ***
+
+The /memory node provides basic information about the address and size
+of the physical memory. This node is usually filled or updated by the
+bootloader, depending on the actual memory configuration of the given

Documentation/devicetree/bindings/memory.txt line 15

Quoted 10 lines
Documentation/devicetree/bindings/memory.txt new file +10 -0
+hardware.
+
+The memory layout is described by the folllowing node:
+
+memory {
+       reg =  <(baseaddr1) (size1)
+               (baseaddr2) (size2)
+               ...
+               (baseaddrN) (sizeN)>;
+};

For compatibility and since you are documenting things, these are also required:

name = "memory";
device_type = "memory";

Quoted 37 lines
Documentation/devicetree/bindings/memory.txt new file +37 -0
+
+baseaddrX:     the base address of the defined memory bank
+sizeX:         the size of the defined memory bank
+
+More than one memory bank can be defined.
+
+
+*** Reserved memory regions ***
+
+In /memory/reserved-memory node one can create additional nodes
+describing particular reserved (excluded from normal use) memory
+regions. Such memory regions are usually designed for the special usage
+by various device drivers. A good example are contiguous memory
+allocations or memory sharing with other operating system on the same
+hardware board. Those special memory regions might depend on the board
+configuration and devices used on the target system.
+
+Parameters for each memory region can be encoded into the device tree
+wit the following convention:
+
+[(label):] (name)@(address) {
+       compatible = "contiguous-memory-region", "reserved-memory-region";
+       reg = <(address) (size)>;
+       (linux,contiguous-region);
+       (linux,default-contiguous-region);
+};
+
+label:         label given to the defined region (optional)
+name:          an name given to the defined region
+address:       the base address of the defined region
+size:          the size of the memory region
+
+compatible:    "contiguous-memory-region" - enables binding of this
+               region to Contiguous Memory Allocator (special region for
+               contiguous memory allocations, shared with movable system
+               memory, Linux kernel-specific), alternatively if
+               "reserved-memory-region" - compatibility is defined, given

Documentation/devicetree/bindings/memory.txt line 62

Quoted 10 lines
Documentation/devicetree/bindings/memory.txt new file +10 -0
+               region is assigned for exclusive usage for DMA transfers
+
+linux,default-contiguous-region: property indicating that the region
+               is the default region for all contiguous memory
+               allocations, Linux specific (optional)
+
+Each defined region must use unique name. It is optional to specify the
+base address, so if one wants to use autoconfiguration of the base
+address, he must specify the '0' as base address in the 'reg' property
+and assign ann uniqe name to such regions.

typo.

Quoted 15 lines
Documentation/devicetree/bindings/memory.txt new file +15 -0
+
+
+*** Device node's properties ***
+
+Once the regions in the /memory/reserved-memory node are defined, they
+can be assigned to device nodes to enable drivers for their special use.
+The following properties are defined:
+
+dma-memory-region = <&phandle_to_defined_region>;
+
+This property indicates that the device driver should use the
+memory region pointed by the given phandle.
+
+
+*** Example ***

Documentation/devicetree/bindings/memory.txt line 87

Quoted 10 lines
Documentation/devicetree/bindings/memory.txt new file +10 -0
+
+This example defines a memory consisting of 4 memory banks. 3 contiguous
+regions are defined for Linux kernel, one default of all device drivers
+(named contig_mem, placed at 0x72000000, 64MiB), one dedicated to the
+framebuffer device (labelled display_mem, placed at 0x78000000, 8MiB)
+and one for multimedia processing (labelled multimedia_mem, placed at
+0x77000000, 64MiB). 'display_mem' region is then assigned to fb at 12300000
+device for DMA memory allocations (Linux kernel drivers will use CMA is
+available or dma-exclusive usage otherwise). 'multimedia_mem' is
+assigned to scaller at 12500000 and codec at 12600000 devices for contiguous

s/scaller/scaler/ ?

Quoted 143 lines
Documentation/devicetree/bindings/memory.txt new file +65 -0
+memory allocations when CMA driver is enabled.
+
+The reason for creating a separate region for framebuffer device is to
+match the framebuffer base address to the one configured by bootloader,
+so once Linux kernel drivers starts no glitches on the displayed boot
+logo appears. Scaller and codec drivers should share the memory
+allocations.
+
+/ {
+       /* ... */
+       memory {
+               reg =  <0x40000000 0x10000000
+                       0x50000000 0x10000000
+                       0x60000000 0x10000000
+                       0x70000000 0x10000000>;
+
+               reserved-memory {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       /*
+                        * global autoconfigured region for contiguous allocations
+                        * (used only with Contiguous Memory Allocator)
+                        */
+                       contig_region at 0 {
+                               compatible = "contiguous-memory-region";
+                               reg = <0x0 0x4000000>;
+                               linux,default-contiguous-region;
+                       };
+
+                       /*
+                        * special region for framebuffer
+                        */
+                       display_mem: region at 78000000 {
+                               compatible = "contiguous-memory-region", "reserved-memory-region";
+                               reg = <0x78000000 0x800000>;
+                       };
+
+                       /*
+                        * special region for multimedia processing devices
+                        */
+                       multimedia_mem: region at 77000000 {
+                               compatible = "contiguous-memory-region";
+                               reg = <0x77000000 0x4000000>;
+                       };
+               };
+       };
+
+       /* ... */
+
+       fb0: fb at 12300000 {
+               status = "okay";
+               dma-memory-region = <&display_mem>;
+       };
+
+       scaller: scaller at 12500000 {
+               status = "okay";
+               dma-memory-region = <&multimedia_mem>;
+       };
+
+       codec: codec at 12600000 {
+               status = "okay";
+               dma-memory-region = <&multimedia_mem>;
+       };
+};
drivers/of/Kconfig +6 -0
index 80e5c13..a83ab43 100644
@@ -80,4 +80,10 @@ config OF_MTD
        depends on MTD
        def_bool y
 
+config OF_RESERVED_MEM
+       depends on CMA || (HAVE_GENERIC_DMA_COHERENT && HAVE_MEMBLOCK)
+       def_bool y
+       help
+         Initialization code for DMA reserved memory
+
 endmenu # OF
drivers/of/Makefile +1 -0
index 1f9c0c4..e7e3322 100644
@@ -10,3 +10,4 @@ obj-$(CONFIG_OF_MDIO) += of_mdio.o
 obj-$(CONFIG_OF_PCI)   += of_pci.o
 obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
 obj-$(CONFIG_OF_MTD)   += of_mtd.o
+obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
drivers/of/of_reserved_mem.c new file +48 -0
new file mode 100644
index 0000000..d97fcdf
@@ -0,0 +1,175 @@
+/*
+ * Device tree based initialization code for reserved memory.
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ * Author: Marek Szyprowski <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License or (at your optional) any later version of the license.
+ */
+
+#include <asm/dma-contiguous.h>
+
+#include <linux/memblock.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+#include <linux/mm.h>
+#include <linux/sizes.h>
+#include <linux/mm_types.h>
+#include <linux/dma-contiguous.h>
+#include <linux/dma-mapping.h>
+
+#define MAX_RESERVED_REGIONS   16
+struct reserved_mem {
+       phys_addr_t             base;
+       unsigned long           size;
+       struct cma              *cma;
+       char                    name[32];
+};
+static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
+static int reserved_mem_count;
+
+static int __init reserved_mem_fdt_scan(unsigned long node, const char *uname,
+                                   int depth, void *data)
+{
+       phys_addr_t base, size;
+       int is_cma, is_reserved;
+       unsigned long len;
+       void *prop;
+
+       is_cma = of_flat_dt_is_compatible(node, "contiguous-memory-region");
+       is_reserved = of_flat_dt_is_compatible(node, "reserved-memory-region");
+
+       if (!is_reserved && !(is_cma && IS_ENABLED(CONFIG_CMA)))

drivers/of/of_reserved_mem.c line 58

Quoted 10 lines
drivers/of/of_reserved_mem.c new file +10 -0
+               return 0;
+
+       prop = of_get_flat_dt_prop(node, "reg", &len);
+       if (!prop || (len != 2 * sizeof(unsigned long))) {
+               pr_err("Reserved mem: node %s, incorrect \"reg\" property\n",
+                      uname);
+               return 0;
+       }
+
+       if (sizeof(unsigned long) == 4) {

This is wrong. The sizes of the properties need to be based on #size-cells and #address-cells. There should already be code to parse reg properties correctly.

Quoted 69 lines
drivers/of/of_reserved_mem.c new file +69 -0
+               base = be32_to_cpu(((__be32 *)prop)[0]);
+               size = be32_to_cpu(((__be32 *)prop)[1]);
+       } else {
+               base = be64_to_cpu(((__be64 *)prop)[0]);
+               size = be64_to_cpu(((__be64 *)prop)[1]);
+       }
+
+       pr_info("Reserved mem: found %s, memory base %lx, size %ld MiB\n",
+               uname, (unsigned long)base, (unsigned long)size / SZ_1M);
+
+       if (reserved_mem_count == ARRAY_SIZE(reserved_mem))
+               return -ENOMEM;
+
+       reserved_mem[reserved_mem_count].base = base;
+       reserved_mem[reserved_mem_count].size = size;
+       strcpy(reserved_mem[reserved_mem_count].name, uname);
+
+       if (IS_ENABLED(CONFIG_CMA) && is_cma) {
+               struct cma *cma;
+               if (dma_contiguous_reserve_area(size, base, 0, &cma) == 0) {
+                       reserved_mem[reserved_mem_count].cma = cma;
+                       reserved_mem_count++;
+
+                       if (of_get_flat_dt_prop(node,
+                                               "linux,default-contiguous-region",
+                                               NULL))
+                               dma_contiguous_set_default_area(cma);
+               }
+       } else if (is_reserved) {
+               if (memblock_remove(base, size) == 0)
+                       reserved_mem_count++;
+               else
+                       pr_err("Failed to reserve memory for %s\n", uname);
+       }
+
+       return 0;
+}
+
+static struct reserved_mem *get_dma_memory_region(struct device *dev)
+{
+       struct device_node *node;
+       const char *name;
+       int i;
+
+       node = of_parse_phandle(dev->of_node, "dma-memory-region", 0);
+       if (!node)
+               return NULL;
+
+       name = kbasename(node->full_name);
+       for (i = 0; i < reserved_mem_count; i++)
+               if (strcmp(name, reserved_mem[i].name) == 0)
+                       return &reserved_mem[i];
+       return NULL;
+}
+
+static void reserved_mem_assign_device_from_dt(struct device *dev)
+{
+       struct reserved_mem *region = get_dma_memory_region(dev);
+       if (!region)
+               return;
+
+       if (region->cma) {
+               dma_contiguous_add_device(dev, region->cma);
+               pr_info("Assigned CMA %s to %s device\n", region->name,
+                       dev_name(dev));
+       } else {
+               if (dma_declare_coherent_memory(dev, region->base, region->base,
+                   region->size, DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) != 0)
+                       pr_info("Declared reserved memory %s to %s device\n",

drivers/of/of_reserved_mem.c line 137

Quoted 10 lines
drivers/of/of_reserved_mem.c new file +10 -0
+                               region->name, dev_name(dev));
+       }
+}
+
+static void reserved_mem_release_device_from_dt(struct device *dev)
+{
+       struct reserved_mem *region = get_dma_memory_region(dev);
+       if (!region)
+               return;
+       if (!region->cma)

if (region && !region->cma)

drivers/of/of_reserved_mem.c line 149

Quoted 12 lines
drivers/of/of_reserved_mem.c new file +12 -0
+               dma_release_declared_memory(dev);
+}
+
+static int reserved_mem_device_init_notifier_call(struct notifier_block *nb,
+                                               unsigned long event, void *data)
+{
+       struct device *dev = data;
+       if (event == BUS_NOTIFY_ADD_DEVICE && dev->of_node)
+               reserved_mem_assign_device_from_dt(dev);
+       else if (event == BUS_NOTIFY_DEL_DEVICE && dev->of_node)
+               reserved_mem_release_device_from_dt(dev);
+       return NOTIFY_DONE;

Can you just call this directly from of_platform.c code and skip the notifiers?

Rob

#8 lore raw

PATCH v4 3/4 drivers: of: add initialization code for dma reserved memory

Quoted 8 lines · Rob Herring

drivers/of/of_reserved_mem.c line 137

Quoted 6 lines
drivers/of/of_reserved_mem.c new file +6 -0
+static void reserved_mem_release_device_from_dt(struct device *dev)
+{
+       struct reserved_mem *region = get_dma_memory_region(dev);
+       if (!region)
+               return;
+       if (!region->cma)

if (region && !region->cma)

!region case is handled two lines above, so no need to check if region is not null.

Quoted 2 lines
Quoted 2 lines
(quoted diff) +2 -0
+               dma_release_declared_memory(dev);
+}
Signature · 11 lines
Best regards,                                         _     _
.o. | Liege of Serenely Enlightened Majesty of      o' \,=./ `o
..o | Computer Science,  Micha? ?mina86? Nazarewicz    (o o)
ooo +----<email/xmpp: [email protected]>--------------ooO--(_)--Ooo--
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130806/403761e4/attachment.sig>
#9 lore raw

PATCH v4 3/4 drivers: of: add initialization code for dma reserved memory

Quoted 10 lines · Michal Nazarewicz
Quoted 8 lines · Rob Herring
Quoted 8 lines
Quoted 6 lines

drivers/of/of_reserved_mem.c line 137

Quoted 6 lines
drivers/of/of_reserved_mem.c new file +6 -0
+static void reserved_mem_release_device_from_dt(struct device *dev)
+{
+       struct reserved_mem *region = get_dma_memory_region(dev);
+       if (!region)
+               return;
+       if (!region->cma)

if (region && !region->cma)

Quoted 2 lines

!region case is handled two lines above, so no need to check if region is not null.

I think Rob's suggestion was to replace two 'if' statements with a single one, which makes sense.

Thanks,
Sylwester

#10 lore raw

PATCH v4 3/4 drivers: of: add initialization code for dma reserved memory

Quoted 11 lines · Sylwester Nawrocki
Quoted 10 lines · Michal Nazarewicz
Quoted 8 lines · Rob Herring
Quoted 8 lines
Quoted 6 lines

drivers/of/of_reserved_mem.c line 137

Quoted 6 lines
drivers/of/of_reserved_mem.c new file +6 -0
+static void reserved_mem_release_device_from_dt(struct device *dev)
+{
+       struct reserved_mem *region = get_dma_memory_region(dev);
+       if (!region)
+               return;
+       if (!region->cma)

if (region && !region->cma)

Quoted 5 lines
Quoted 2 lines

!region case is handled two lines above, so no need to check if region is not null.

I think Rob's suggestion was to replace two 'if' statements with a single one, which makes sense.

Ah, yes, silly me...

Signature · 11 lines
Best regards,                                         _     _
.o. | Liege of Serenely Enlightened Majesty of      o' \,=./ `o
..o | Computer Science,  Micha? ?mina86? Nazarewicz    (o o)
ooo +----<email/xmpp: [email protected]>--------------ooO--(_)--Ooo--
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130807/16d7436a/attachment.sig>
#11 lore raw

PATCH v4 3/4 drivers: of: add initialization code for dma reserved memory

In reply to Michal Nazarewicz
Quoted 10 lines · Michal Nazarewicz
Quoted 8 lines · Rob Herring

drivers/of/of_reserved_mem.c line 137

Quoted 6 lines
drivers/of/of_reserved_mem.c new file +6 -0
+static void reserved_mem_release_device_from_dt(struct device *dev)
+{
+       struct reserved_mem *region = get_dma_memory_region(dev);
+       if (!region)
+               return;
+       if (!region->cma)

if (region && !region->cma)

Quoted 2 lines

!region case is handled two lines above, so no need to check if region is not null.

Right. Sorry if I was not clear. Combine the 3 lines into 1 line.

Rob

#12 lore raw

PATCH v4 3/4 drivers: of: add initialization code for dma reserved memory

In reply to Marek Szyprowski
Quoted 60 lines · Marek Szyprowski

Add device tree support for contiguous and reserved memory regions defined in device tree. Initialization is done in 2 steps. First, the memory is reserved, what happens very early when only flattened device tree is available. Then on device initialization the corresponding cma and reserved regions are assigned to each device structure.

---

Documentation/devicetree/bindings/memory.txt |  152 ++++++++++++++++++++++
drivers/of/Kconfig                           |    6 +
drivers/of/Makefile                          |    1 +
drivers/of/of_reserved_mem.c                 |  175 ++++++++++++++++++++++++++
include/asm-generic/dma-coherent.h           |    6 +
5 files changed, 340 insertions(+)

create mode 100644 Documentation/devicetree/bindings/memory.txt create mode 100644 drivers/of/of_reserved_mem.c

Documentation/devicetree/bindings/memory.txt new file +36 -0
new file mode 100644
index 0000000..4aece19
@@ -0,0 +1,152 @@
+*** Memory binding ***
+
+The /memory node provides basic information about the address and size
+of the physical memory. This node is usually filled or updated by the
+bootloader, depending on the actual memory configuration of the given
+hardware.
+
+The memory layout is described by the folllowing node:
+
+memory {
+	reg =  <(baseaddr1) (size1)
+		(baseaddr2) (size2)
+		...
+		(baseaddrN) (sizeN)>;
+};
+
+baseaddrX:	the base address of the defined memory bank
+sizeX:		the size of the defined memory bank
+
+More than one memory bank can be defined.
+
+
+*** Reserved memory regions ***
+
+In /memory/reserved-memory node one can create additional nodes
+describing particular reserved (excluded from normal use) memory
+regions. Such memory regions are usually designed for the special usage
+by various device drivers. A good example are contiguous memory
+allocations or memory sharing with other operating system on the same
+hardware board. Those special memory regions might depend on the board
+configuration and devices used on the target system.
+
+Parameters for each memory region can be encoded into the device tree
+wit the following convention:
+
+[(label):] (name)@(address) {

Documentation/devicetree/bindings/memory.txt line 46

Quoted 10 lines
Documentation/devicetree/bindings/memory.txt new file +10 -0
+	compatible = "contiguous-memory-region", "reserved-memory-region";
+	reg = <(address) (size)>;
+	(linux,contiguous-region);
+	(linux,default-contiguous-region);
+};
+
+label:		label given to the defined region (optional)
+name:		an name given to the defined region
+address:	the base address of the defined region
+size:		the size of the memory region

Should we try and convey some type of cacheability attributes, I know this is difficult to do in a generic way, but would seem useful and necessary.

Quoted 15 lines
Documentation/devicetree/bindings/memory.txt new file +15 -0
+
+compatible:	"contiguous-memory-region" - enables binding of this
+		region to Contiguous Memory Allocator (special region for
+		contiguous memory allocations, shared with movable system
+		memory, Linux kernel-specific), alternatively if
+		"reserved-memory-region" - compatibility is defined, given
+		region is assigned for exclusive usage for DMA transfers
+
+linux,default-contiguous-region: property indicating that the region
+		is the default region for all contiguous memory
+		allocations, Linux specific (optional)
+
+Each defined region must use unique name. It is optional to specify the
+base address, so if one wants to use autoconfiguration of the base
+address, he must specify the '0' as base address in the 'reg' property

Documentation/devicetree/bindings/memory.txt line 71

Quoted 10 lines
Documentation/devicetree/bindings/memory.txt new file +10 -0
+and assign ann uniqe name to such regions.
+
+
+*** Device node's properties ***
+
+Once the regions in the /memory/reserved-memory node are defined, they
+can be assigned to device nodes to enable drivers for their special use.
+The following properties are defined:
+
+dma-memory-region = <&phandle_to_defined_region>;

Should we go with just 'memory-region' to be more generic? An example might be a region of memory used for multiprocessor communication that isn't cache-able.

Quoted 71 lines
Documentation/devicetree/bindings/memory.txt new file +71 -0
+
+This property indicates that the device driver should use the
+memory region pointed by the given phandle.
+
+
+*** Example ***
+
+This example defines a memory consisting of 4 memory banks. 3 contiguous
+regions are defined for Linux kernel, one default of all device drivers
+(named contig_mem, placed at 0x72000000, 64MiB), one dedicated to the
+framebuffer device (labelled display_mem, placed at 0x78000000, 8MiB)
+and one for multimedia processing (labelled multimedia_mem, placed at
+0x77000000, 64MiB). 'display_mem' region is then assigned to fb at 12300000
+device for DMA memory allocations (Linux kernel drivers will use CMA is
+available or dma-exclusive usage otherwise). 'multimedia_mem' is
+assigned to scaller at 12500000 and codec at 12600000 devices for contiguous
+memory allocations when CMA driver is enabled.
+
+The reason for creating a separate region for framebuffer device is to
+match the framebuffer base address to the one configured by bootloader,
+so once Linux kernel drivers starts no glitches on the displayed boot
+logo appears. Scaller and codec drivers should share the memory
+allocations.
+
+/ {
+	/* ... */
+	memory {
+		reg =  <0x40000000 0x10000000
+			0x50000000 0x10000000
+			0x60000000 0x10000000
+			0x70000000 0x10000000>;
+
+		reserved-memory {
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			/*
+			 * global autoconfigured region for contiguous allocations
+			 * (used only with Contiguous Memory Allocator)
+			 */
+			contig_region at 0 {
+				compatible = "contiguous-memory-region";
+				reg = <0x0 0x4000000>;
+				linux,default-contiguous-region;
+			};
+
+			/*
+			 * special region for framebuffer
+			 */
+			display_mem: region at 78000000 {
+				compatible = "contiguous-memory-region", "reserved-memory-region";
+				reg = <0x78000000 0x800000>;
+			};
+
+			/*
+			 * special region for multimedia processing devices
+			 */
+			multimedia_mem: region at 77000000 {
+				compatible = "contiguous-memory-region";
+				reg = <0x77000000 0x4000000>;
+			};
+		};
+	};
+
+	/* ... */
+
+	fb0: fb at 12300000 {
+		status = "okay";
+		dma-memory-region = <&display_mem>;
+	};
+

Documentation/devicetree/bindings/memory.txt line 152

Quoted 10 lines
Documentation/devicetree/bindings/memory.txt new file +10 -0
+	scaller: scaller at 12500000 {
+		status = "okay";
+		dma-memory-region = <&multimedia_mem>;
+	};
+
+	codec: codec at 12600000 {
+		status = "okay";
+		dma-memory-region = <&multimedia_mem>;
+	};
+};

- k

--
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

#13 lore raw

PATCH v4 4/4 ARM: init: add support for reserved memory defined by device tree

In reply to Marek Szyprowski

Enable reserved memory initialization from device tree.

---
 arch/arm/mm/init.c |    3 +++
 1 file changed, 3 insertions(+)
arch/arm/mm/init.c +3 -0
index 15225d8..82db8d8 100644
@@ -20,6 +20,7 @@
 #include <linux/highmem.h>
 #include <linux/gfp.h>
 #include <linux/memblock.h>
+#include <linux/dma-mapping.h>
 #include <linux/dma-contiguous.h>
 #include <linux/sizes.h>
 
@@ -377,6 +378,8 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
 	if (mdesc->reserve)
 		mdesc->reserve();
 
+	dma_reserved_mem_of_reserve();
+
 	/*
 	 * reserve memory for DMA contigouos allocations,
 	 * must come from DMA area inside low memory
Signature · 1 line
1.7.9.5
#14 lore raw

PATCH v4 4/4 ARM: init: add support for reserved memory defined by device tree

Quoted 4 lines · Marek Szyprowski

Enable reserved memory initialization from device tree.

Quoted 28 lines
---
 arch/arm/mm/init.c |    3 +++
 1 file changed, 3 insertions(+)
arch/arm/mm/init.c +3 -0
index 15225d8..82db8d8 100644
@@ -20,6 +20,7 @@
 #include <linux/highmem.h>
 #include <linux/gfp.h>
 #include <linux/memblock.h>
+#include <linux/dma-mapping.h>
 #include <linux/dma-contiguous.h>
 #include <linux/sizes.h>
 
@@ -377,6 +378,8 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
 	if (mdesc->reserve)
 		mdesc->reserve();
 
+	dma_reserved_mem_of_reserve();
+
 	/*
 	 * reserve memory for DMA contigouos allocations,
 	 * must come from DMA area inside low memory
Signature · 1 line
1.7.9.5
Signature · 11 lines
Best regards,                                         _     _
.o. | Liege of Serenely Enlightened Majesty of      o' \,=./ `o
..o | Computer Science,  Micha? ?mina86? Nazarewicz    (o o)
ooo +----<email/xmpp: [email protected]>--------------ooO--(_)--Ooo--
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130805/937c3e43/attachment.sig>