Adding linux-arm-kernel and devicetree (look for "raw-pfn"), since this impacts directly on those. On Mon, Feb 13, 2017 at 08:02:29PM +0800, zhouxianrong@xxxxxxxxxx wrote: > From: zhouxianrong <zhouxianrong@xxxxxxxxxx> > > just like freeing no-map area's memmap we could free reserved > area's memmap as well only when user of reserved area indicate > that we can do this in dts or drivers. that is, user of reserved > area know how to use the reserved area who could not memblock_free > or free_reserved_xxx the reserved area and regard the area as raw > pfn usage. the patch supply a way to users who want to utilize the > memmap memory corresponding to raw pfn reserved areas as many as > possible. I don't really understand this. Can you point me at a specific use-case, please? Is CMA involved here? Will (entire patch follows, for the benefit of the extra CCs) > Signed-off-by: zhouxianrong <zhouxianrong@xxxxxxxxxx> > --- > arch/arm64/mm/init.c | 14 +++++++++++++- > drivers/of/fdt.c | 31 +++++++++++++++++++++++-------- > drivers/of/of_reserved_mem.c | 21 ++++++++++++++------- > include/linux/memblock.h | 3 +++ > include/linux/of_fdt.h | 2 +- > mm/memblock.c | 24 ++++++++++++++++++++++++ > 6 files changed, 78 insertions(+), 17 deletions(-) > > diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c > index 380ebe7..7e62ef8 100644 > --- a/arch/arm64/mm/init.c > +++ b/arch/arm64/mm/init.c > @@ -358,7 +358,7 @@ static inline void free_memmap(unsigned long start_pfn, unsigned long end_pfn) > */ > static void __init free_unused_memmap(void) > { > - unsigned long start, prev_end = 0; > + unsigned long start, end, prev_end = 0; > struct memblock_region *reg; > > for_each_memblock(memory, reg) { > @@ -391,6 +391,18 @@ static void __init free_unused_memmap(void) > if (!IS_ALIGNED(prev_end, PAGES_PER_SECTION)) > free_memmap(prev_end, ALIGN(prev_end, PAGES_PER_SECTION)); > #endif > + > + for_each_memblock(reserved, reg) { > + if (!(reg->flags & MEMBLOCK_RAW_PFN)) > + continue; > + > + start = memblock_region_memory_base_pfn(reg); > + end = round_down(memblock_region_memory_end_pfn(reg), > + MAX_ORDER_NR_PAGES); > + > + if (start < end) > + free_memmap(start, end); > + } > } > #endif /* !CONFIG_SPARSEMEM_VMEMMAP */ > > diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c > index c9b5cac..39e7474 100644 > --- a/drivers/of/fdt.c > +++ b/drivers/of/fdt.c > @@ -582,7 +582,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, > phys_addr_t base, size; > int len; > const __be32 *prop; > - int nomap, first = 1; > + int nomap, raw_pfn, first = 1; > > prop = of_get_flat_dt_prop(node, "reg", &len); > if (!prop) > @@ -595,13 +595,15 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, > } > > nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; > + raw_pfn = of_get_flat_dt_prop(node, "raw-pfn", NULL) != NULL; > > while (len >= t_len) { > base = dt_mem_next_cell(dt_root_addr_cells, &prop); > size = dt_mem_next_cell(dt_root_size_cells, &prop); > > if (size && > - early_init_dt_reserve_memory_arch(base, size, nomap) == 0) > + early_init_dt_reserve_memory_arch(base, size, nomap, > + raw_pfn) == 0) > pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n", > uname, &base, (unsigned long)size / SZ_1M); > else > @@ -699,7 +701,7 @@ void __init early_init_fdt_scan_reserved_mem(void) > fdt_get_mem_rsv(initial_boot_params, n, &base, &size); > if (!size) > break; > - early_init_dt_reserve_memory_arch(base, size, 0); > + early_init_dt_reserve_memory_arch(base, size, 0, 0); > } > > of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); > @@ -717,6 +719,7 @@ void __init early_init_fdt_reserve_self(void) > /* Reserve the dtb region */ > early_init_dt_reserve_memory_arch(__pa(initial_boot_params), > fdt_totalsize(initial_boot_params), > + 0, > 0); > } > > @@ -1161,11 +1164,21 @@ int __init __weak early_init_dt_mark_hotplug_memory_arch(u64 base, u64 size) > } > > int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, > - phys_addr_t size, bool nomap) > + phys_addr_t size, bool nomap, > + bool raw_pfn) > { > + int err; > + > if (nomap) > return memblock_remove(base, size); > - return memblock_reserve(base, size); > + > + err = memblock_reserve(base, size); > + if (err == 0) { > + if (raw_pfn) > + memblock_mark_raw_pfn(base, size); > + } > + > + return err; > } > > /* > @@ -1188,10 +1201,12 @@ int __init __weak early_init_dt_mark_hotplug_memory_arch(u64 base, u64 size) > } > > int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, > - phys_addr_t size, bool nomap) > + phys_addr_t size, bool nomap, > + bool raw_pfn) > { > - pr_err("Reserved memory not supported, ignoring range %pa - %pa%s\n", > - &base, &size, nomap ? " (nomap)" : ""); > + pr_err("Reserved memory not supported, ignoring range %pa - %pa%s - %pa%s\n", > + &base, &size, nomap ? " (nomap)" : "", > + raw_pfn ? " (raw-pfn)" : ""); > return -ENOSYS; > } > > diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c > index 366d8c3..d7d9255 100644 > --- a/drivers/of/of_reserved_mem.c > +++ b/drivers/of/of_reserved_mem.c > @@ -33,7 +33,7 @@ > #include <linux/memblock.h> > int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, > phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, > - phys_addr_t *res_base) > + bool raw_pfn, phys_addr_t *res_base) > { > phys_addr_t base; > /* > @@ -56,15 +56,19 @@ int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, > *res_base = base; > if (nomap) > return memblock_remove(base, size); > + > + if (raw_pfn) > + memblock_mark_raw_pfn(base, size); > + > return 0; > } > #else > int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, > phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, > - phys_addr_t *res_base) > + bool raw_pfn, phys_addr_t *res_base) > { > - pr_err("Reserved memory not supported, ignoring region 0x%llx%s\n", > - size, nomap ? " (nomap)" : ""); > + pr_err("Reserved memory not supported, ignoring region 0x%llx%s 0x%llx%s\n", > + size, nomap ? " (nomap)" : "", raw_pfn ? " (raw-pfn)" : ""); > return -ENOSYS; > } > #endif > @@ -103,7 +107,7 @@ static int __init __reserved_mem_alloc_size(unsigned long node, > phys_addr_t base = 0, align = 0, size; > int len; > const __be32 *prop; > - int nomap; > + int nomap, raw_pfn; > int ret; > > prop = of_get_flat_dt_prop(node, "size", &len); > @@ -117,6 +121,7 @@ static int __init __reserved_mem_alloc_size(unsigned long node, > size = dt_mem_next_cell(dt_root_size_cells, &prop); > > nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; > + raw_pfn = of_get_flat_dt_prop(node, "raw-pfn", NULL) != NULL; > > prop = of_get_flat_dt_prop(node, "alignment", &len); > if (prop) { > @@ -156,7 +161,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node, > &prop); > > ret = early_init_dt_alloc_reserved_memory_arch(size, > - align, start, end, nomap, &base); > + align, start, end, nomap, > + raw_pfn, &base); > if (ret == 0) { > pr_debug("allocated memory for '%s' node: base %pa, size %ld MiB\n", > uname, &base, > @@ -168,7 +174,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node, > > } else { > ret = early_init_dt_alloc_reserved_memory_arch(size, align, > - 0, 0, nomap, &base); > + 0, 0, nomap, > + raw_pfn, &base); > if (ret == 0) > pr_debug("allocated memory for '%s' node: base %pa, size %ld MiB\n", > uname, &base, (unsigned long)size / SZ_1M); > diff --git a/include/linux/memblock.h b/include/linux/memblock.h > index 5b759c9..7266be1 100644 > --- a/include/linux/memblock.h > +++ b/include/linux/memblock.h > @@ -26,6 +26,7 @@ enum { > MEMBLOCK_HOTPLUG = 0x1, /* hotpluggable region */ > MEMBLOCK_MIRROR = 0x2, /* mirrored region */ > MEMBLOCK_NOMAP = 0x4, /* don't add to kernel direct mapping */ > + MEMBLOCK_RAW_PFN = 0x8, /* raw pfn region's memmap never used */ > }; > > struct memblock_region { > @@ -92,6 +93,8 @@ bool memblock_overlaps_region(struct memblock_type *type, > int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); > int memblock_mark_mirror(phys_addr_t base, phys_addr_t size); > int memblock_mark_nomap(phys_addr_t base, phys_addr_t size); > +int memblock_mark_raw_pfn(phys_addr_t base, phys_addr_t size); > +int memblock_clear_raw_pfn(phys_addr_t base, phys_addr_t size); > ulong choose_memblock_flags(void); > > /* Low level functions */ > diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h > index 271b3fd..29284d7 100644 > --- a/include/linux/of_fdt.h > +++ b/include/linux/of_fdt.h > @@ -73,7 +73,7 @@ extern int early_init_dt_scan_memory(unsigned long node, const char *uname, > extern void early_init_dt_add_memory_arch(u64 base, u64 size); > extern int early_init_dt_mark_hotplug_memory_arch(u64 base, u64 size); > extern int early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, > - bool no_map); > + bool no_map, bool raw_pfn); > extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align); > extern u64 dt_mem_next_cell(int s, const __be32 **cellp); > > diff --git a/mm/memblock.c b/mm/memblock.c > index 7608bc3..c103b94 100644 > --- a/mm/memblock.c > +++ b/mm/memblock.c > @@ -814,6 +814,30 @@ int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size) > } > > /** > + * memblock_mark_raw_pfn - Mark raw pfn memory with flag MEMBLOCK_RAW_PFN. > + * @base: the base phys addr of the region > + * @size: the size of the region > + * > + * Return 0 on succees, -errno on failure. > + */ > +int __init_memblock memblock_mark_raw_pfn(phys_addr_t base, phys_addr_t size) > +{ > + return memblock_setclr_flag(base, size, 1, MEMBLOCK_RAW_PFN); > +} > + > +/** > + * memblock_clear_raw_pfn - Clear flag MEMBLOCK_RAW_PFN for a specified region. > + * @base: the base phys addr of the region > + * @size: the size of the region > + * > + * Return 0 on succees, -errno on failure. > + */ > +int __init_memblock memblock_clear_raw_pfn(phys_addr_t base, phys_addr_t size) > +{ > + return memblock_setclr_flag(base, size, 0, MEMBLOCK_RAW_PFN); > +} > + > +/** > * __next_reserved_mem_region - next function for for_each_reserved_region() > * @idx: pointer to u64 loop variable > * @out_start: ptr to phys_addr_t for start address of the region, can be %NULL > -- > 1.7.9.5 > -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html