From f856681273ba71fa7e833f57cf23cb92e034cb0c Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 2 Feb 2021 11:24:36 +0100 Subject: [PATCH] of: fix reserved memory handling Mainline u-boot marks some secure monitor relate memory with the /memreserve/ device-tree method. On the other hand, the same memory is already defined in /reserved-memory node with the all details needed to use it by the respective secure monitor deamon. Check for such case and properly initialize such reserved memory regions instead of returning a failure. This allows to use vendor kernel with mainline u-boot on Amlogic SoCs. Signed-off-by: Marek Szyprowski Change-Id: I0bd3b51899cc17f17d1bcbd0c2c5a0d88686b245 --- drivers/of/of_reserved_mem.c | 8 ++++++++ include/linux/memblock.h | 1 + mm/memblock.c | 10 ++++++++++ 3 files changed, 19 insertions(+) diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index c4a7b04c09f7..aa5ed940d671 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -43,6 +43,14 @@ int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, phys_addr_t *res_base) { phys_addr_t base; + + /* check if the region has been alredy reserved by the bootloader */ + if (start && end && memblock_is_region_reserved(start, end - start)) { + pr_info("OF: region (%pa--%pa) is reserved both in /memreserve/ and /reserved-memory, fixing\n", + &start, &end); + memblock_unreserve(start, end - start); + } + /* * We use __memblock_alloc_base() because memblock_alloc_base() * panic()s on allocation failure. diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 4024af00b137..debfcb975a6d 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -84,6 +84,7 @@ int memblock_add(phys_addr_t base, phys_addr_t size); int memblock_remove(phys_addr_t base, phys_addr_t size); int memblock_free(phys_addr_t base, phys_addr_t size); int memblock_reserve(phys_addr_t base, phys_addr_t size); +int memblock_unreserve(phys_addr_t base, phys_addr_t size); void memblock_trim_memory(phys_addr_t align); bool memblock_overlaps_region(struct memblock_type *type, phys_addr_t base, phys_addr_t size); diff --git a/mm/memblock.c b/mm/memblock.c index 42b98af6a415..71867c275655 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -733,6 +733,16 @@ int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size) return memblock_add_range(&memblock.reserved, base, size, MAX_NUMNODES, 0); } +int __init_memblock memblock_unreserve(phys_addr_t base, phys_addr_t size) +{ + memblock_dbg(" memblock_unreserve: [%#016llx-%#016llx] %pF\n", + (unsigned long long)base, + (unsigned long long)base + size - 1, + (void *)_RET_IP_); + + return memblock_remove_range(&memblock.reserved, base, size); +} + /** * * This function isolates region [@base, @base + @size), and sets/clears flag -- 2.34.1