Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c825a1d7 authored by Laura Abbott's avatar Laura Abbott
Browse files

cma: Add support for removed regions



In addition to reserving memory from the system, there may
be uses where memory should be completely removed from control
of the linux page allocator. Add the appropriate information to
be able to remove the memory.

Change-Id: Ia2e959e0858fb240ab5c0deee49b0d6e4aecfc00
Signed-off-by: default avatarLaura Abbott <lauraa@codeaurora.org>
parent d06f4207
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ wit the following convention:
	(linux,default-contiguous-region);
	(linux,reserve-region);
	(linux,memory-limit);
	(linux,remove-completely);
        label = (unique_name);
};

@@ -58,6 +59,10 @@ linux,memory-limit: property specifying an upper bound on the physical address
		is specificed, the region may be placed anywhere in the physical
		address space. 0 may be used to specify lowmem (i.e. the region
		will be placed in the direct mapped lowmem region)
linux,remove-completely: property indicating the memory will be removed from the
		linux page allocator completely. This means that page structures
		associated with the memory will not be valid. This binding is
		expected to be used in conjunction with linux,reserve-region.
label:		an internal name used for automatically associating the
		cma region with a given device. The label is optional;
		if the label is not given the client is responsible for
+23 −4
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@
#include <linux/swap.h>
#include <linux/mm_types.h>
#include <linux/dma-contiguous.h>
#include <linux/dma-removed.h>
#include <trace/events/kmem.h>

struct cma {
@@ -220,6 +221,7 @@ int __init cma_fdt_scan(unsigned long node, const char *uname,
	__be32 *prop;
	char *name;
	bool in_system;
	bool remove;
	unsigned long size_cells = dt_root_size_cells;
	unsigned long addr_cells = dt_root_addr_cells;
	phys_addr_t limit = MEMBLOCK_ALLOC_ANYWHERE;
@@ -250,10 +252,13 @@ int __init cma_fdt_scan(unsigned long node, const char *uname,
	if (prop)
		limit = be32_to_cpu(prop[0]);

	remove =
	     of_get_flat_dt_prop(node, "linux,remove-completely", NULL) ? 1 : 0;

	pr_info("Found %s, memory base %pa, size %ld MiB, limit %pa\n", uname,
			&base, (unsigned long)size / SZ_1M, &limit);
	dma_contiguous_reserve_area(size, &base, limit, name,
					in_system);
					in_system, remove);

	return 0;
}
@@ -295,7 +300,7 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
			 (unsigned long)sel_size / SZ_1M);

		if (dma_contiguous_reserve_area(sel_size, &base, limit, NULL,
		    CMA_RESERVE_AREA) == 0)
		    CMA_RESERVE_AREA, false) == 0)
			dma_contiguous_def_base = base;
	}
#ifdef CONFIG_OF
@@ -319,7 +324,7 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
 */
int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t *res_base,
				       phys_addr_t limit, const char *name,
				       bool to_system)
				       bool to_system, bool remove)
{
	phys_addr_t base = *res_base;
	phys_addr_t alignment;
@@ -365,6 +370,15 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t *res_base,
		}
	}

	if (remove) {
		if (!to_system) {
			memblock_free(base, size);
			memblock_remove(base, size);
		} else {
			WARN(1, "Removing is incompatible with staying in the system\n");
		}
	}

	/*
	 * Each reserved area must be initialised later, when more kernel
	 * subsystems (like slab allocator) are available.
@@ -380,6 +394,7 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t *res_base,
		 &base);

	/* Architecture specific contiguous memory fixup. */
	if (!remove)
		dma_contiguous_early_fixup(base, size);
	return 0;
err:
@@ -430,6 +445,10 @@ static void cma_assign_device_from_dt(struct device *dev)
		return;

	dev_set_cma_area(dev, cma);

	if (of_property_read_bool(node, "linux,remove-completely"))
		set_dma_ops(dev, &removed_dma_ops);

	pr_info("Assigned CMA region at %lx to %s device\n", (unsigned long)value, dev_name(dev));
}

+6 −3
Original line number Diff line number Diff line
@@ -74,7 +74,8 @@ void dma_contiguous_reserve(phys_addr_t addr_limit);

int dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t *res_base,
				  phys_addr_t limit, const char *name,
				  bool in_system);
				  bool in_system,
				  bool remove);

int dma_contiguous_add_device(struct device *dev, phys_addr_t base);

@@ -95,7 +96,8 @@ static inline int dma_declare_contiguous(struct device *dev, phys_addr_t size,
					 phys_addr_t base, phys_addr_t limit)
{
	int ret;
	ret = dma_contiguous_reserve_area(size, &base, limit, NULL, true);
	ret = dma_contiguous_reserve_area(size, &base, limit, NULL, true,
						false);
	if (ret == 0)
		ret = dma_contiguous_add_device(dev, base);
	return ret;
@@ -107,7 +109,8 @@ static inline int dma_declare_contiguous_reserved(struct device *dev,
					 phys_addr_t limit)
{
	int ret;
	ret = dma_contiguous_reserve_area(size, &base, limit, NULL, false);
	ret = dma_contiguous_reserve_area(size, &base, limit, NULL, false,
						false);
	if (ret == 0)
		ret = dma_contiguous_add_device(dev, base);
	return ret;