[PATCH] fixup! memblock: add KHO support for reserve_mem

From: Changyuan Lyu
Date: Thu Apr 24 2025 - 04:10:24 EST


This patch includes the suggested changes from
https://lore.kernel.org/lkml/aAeaJ2iqkrv_ffhT@xxxxxxxxxx/ and can be
squashed with "memblock: add KHO support for reserve_mem".

Fixes: 2e257a656639 ("memblock: add KHO support for reserve_mem")
Suggested-by: Mike Rapoport (Microsoft) <rppt@xxxxxxxxxx>
Signed-off-by: Changyuan Lyu <changyuanl@xxxxxxxxxx>
---
mm/memblock.c | 69 +++++++++++++++++++++++++--------------------------
1 file changed, 34 insertions(+), 35 deletions(-)

diff --git a/mm/memblock.c b/mm/memblock.c
index 3571a859f2fe1..d38a72f07ea0c 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -2490,15 +2490,6 @@ static int reserve_mem_kho_finalize(struct kho_serialization *ser)
{
int err = 0, i;

- if (!reserved_mem_count)
- return NOTIFY_DONE;
-
- if (IS_ERR(kho_fdt)) {
- err = PTR_ERR(kho_fdt);
- pr_err("memblock FDT was not prepared successfully: %d\n", err);
- return notifier_from_errno(err);
- }
-
for (i = 0; i < reserved_mem_count; i++) {
struct reserve_mem_table *map = &reserved_mem_table[i];

@@ -2528,19 +2519,14 @@ static struct notifier_block reserve_mem_kho_nb = {
.notifier_call = reserve_mem_kho_notifier,
};

-static void __init prepare_kho_fdt(void)
+static int __init prepare_kho_fdt(void)
{
int err = 0, i;
void *fdt;

- if (!reserved_mem_count)
- return;
-
kho_fdt = alloc_page(GFP_KERNEL);
- if (!kho_fdt) {
- kho_fdt = ERR_PTR(-ENOMEM);
- return;
- }
+ if (!kho_fdt)
+ return -ENOMEM;

fdt = page_to_virt(kho_fdt);

@@ -2565,18 +2551,30 @@ static void __init prepare_kho_fdt(void)
if (err) {
pr_err("failed to prepare memblock FDT for KHO: %d\n", err);
put_page(kho_fdt);
- kho_fdt = ERR_PTR(-EINVAL);
+ kho_fdt = NULL;
}
+
+ return err;
}

static int __init reserve_mem_init(void)
{
- if (!kho_is_enabled())
+ int err;
+
+ if (!kho_is_enabled() || !reserved_mem_count)
return 0;

- prepare_kho_fdt();
+ err = prepare_kho_fdt();
+ if (err)
+ return err;
+
+ err = register_kho_notifier(&reserve_mem_kho_nb);
+ if (err) {
+ put_page(kho_fdt);
+ kho_fdt = NULL;
+ }

- return register_kho_notifier(&reserve_mem_kho_nb);
+ return err;
}
late_initcall(reserve_mem_init);

@@ -2586,33 +2584,38 @@ static void *__init reserve_mem_kho_retrieve_fdt(void)
{
phys_addr_t fdt_phys;
struct folio *fdt_folio;
- void *fdt;
int err;

+ if (kho_fdt_in)
+ return kho_fdt_in;
+
err = kho_retrieve_subtree(MEMBLOCK_KHO_FDT, &fdt_phys);
if (err) {
if (err != -ENOENT)
pr_warn("failed to retrieve FDT '%s' from KHO: %d\n",
MEMBLOCK_KHO_FDT, err);
- return ERR_PTR(err);
+ goto out;
}

fdt_folio = kho_restore_folio(fdt_phys);
if (!fdt_folio) {
pr_warn("failed to restore memblock KHO FDT (0x%llx)\n", fdt_phys);
- return ERR_PTR(-EFAULT);
+ err = -EFAULT;
+ goto out;
}

- fdt = page_to_virt(folio_page(fdt_folio, 0));
+ kho_fdt_in = folio_address(fdt_folio);

- err = fdt_node_check_compatible(fdt, 0, MEMBLOCK_KHO_NODE_COMPATIBLE);
+ err = fdt_node_check_compatible(kho_fdt_in, 0, MEMBLOCK_KHO_NODE_COMPATIBLE);
if (err) {
pr_warn("FDT '%s' is incompatible with '%s': %d\n",
MEMBLOCK_KHO_FDT, MEMBLOCK_KHO_NODE_COMPATIBLE, err);
- return ERR_PTR(-EINVAL);
+ err = -EFAULT;
}
-
- return fdt;
+out:
+ if (err)
+ kho_fdt_in = ERR_PTR(err);
+ return kho_fdt_in;
}

static bool __init reserve_mem_kho_revive(const char *name, phys_addr_t size,
@@ -2622,14 +2625,10 @@ static bool __init reserve_mem_kho_revive(const char *name, phys_addr_t size,
const phys_addr_t *p_start, *p_size;
const void *fdt;

- if (!kho_fdt_in)
- kho_fdt_in = reserve_mem_kho_retrieve_fdt();
-
- if (IS_ERR(kho_fdt_in))
+ fdt = reserve_mem_kho_retrieve_fdt();
+ if (IS_ERR(fdt))
return false;

- fdt = kho_fdt_in;
-
offset = fdt_subnode_offset(fdt, 0, name);
if (offset < 0) {
pr_warn("FDT '%s' has no child '%s': %d\n",
--
2.49.0.805.g082f7c87e0-goog