Loading Documentation/devicetree/bindings/memory.txt +5 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ wit the following convention: (linux,default-contiguous-region); (linux,reserve-region); (linux,memory-limit); (linux,remove-completely); label = (unique_name); }; Loading @@ -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 Loading drivers/base/dma-contiguous.c +23 −4 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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 Loading @@ -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; Loading Loading @@ -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. Loading @@ -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: Loading Loading @@ -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)); } Loading include/linux/dma-contiguous.h +6 −3 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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; Loading @@ -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; Loading Loading
Documentation/devicetree/bindings/memory.txt +5 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ wit the following convention: (linux,default-contiguous-region); (linux,reserve-region); (linux,memory-limit); (linux,remove-completely); label = (unique_name); }; Loading @@ -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 Loading
drivers/base/dma-contiguous.c +23 −4 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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 Loading @@ -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; Loading Loading @@ -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. Loading @@ -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: Loading Loading @@ -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)); } Loading
include/linux/dma-contiguous.h +6 −3 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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; Loading @@ -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; Loading