[PATCH v4 56/58] mtd: rawnand: nandsim: retain chip state across removal
From: James Hilliard
Date: Fri Nov 13 2026 - 15:24:05 EST
A failed registration or subsequent debugfs initialization can unwind
after MTD handles have been acquired. Disconnect before freeing the
simulated media, and retain chip metadata until the final MTD put. Use
the shared lifetime cleanup for both initialization rollback and module
removal.
Run NAND cleanup during disconnection; the final core-owned put only
releases retained allocation and layout data.
Signed-off-by: James Hilliard <james.hilliard1@xxxxxxxxx>
---
drivers/mtd/nand/raw/nandsim.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c
index 6716eafb4b00..dd000c766ed3 100644
--- a/drivers/mtd/nand/raw/nandsim.c
+++ b/drivers/mtd/nand/raw/nandsim.c
@@ -2263,6 +2263,7 @@ static int __init ns_init_module(void)
struct nand_chip *chip;
struct nandsim *ns;
int ret;
+ bool retained = false;
if (bus_width != 8 && bus_width != 16) {
NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width);
@@ -2317,8 +2318,6 @@ static int __init ns_init_module(void)
chip->options |= NAND_BUSWIDTH_16;
}
- nsmtd->owner = THIS_MODULE;
-
ret = ns_parse_weakblocks();
if (ret)
goto free_ns_struct;
@@ -2377,6 +2376,10 @@ static int __init ns_init_module(void)
ret = ns_parse_badblocks(ns, nsmtd);
if (ret)
goto free_ns_object;
+ ret = nand_set_lifetime(chip, nand_get_controller_data(chip));
+ if (ret)
+ goto free_ns_object;
+ retained = true;
/* Register NAND partitions */
ret = mtd_device_register(nsmtd, &ns->partitions[0], ns->nbparts);
@@ -2392,11 +2395,16 @@ static int __init ns_init_module(void)
unregister_mtd:
WARN_ON(mtd_device_unregister(nsmtd));
free_ns_object:
+ if (retained)
+ nand_disconnect(chip);
ns_free(ns);
free_ebw:
kfree(erase_block_wear);
cleanup_nand:
- nand_cleanup(chip);
+ if (retained)
+ mtd_put_master(nsmtd);
+ else
+ nand_cleanup(chip);
free_gp_list:
list_for_each_safe(pos, n, &grave_pages) {
list_del(pos);
@@ -2413,7 +2421,8 @@ static int __init ns_init_module(void)
kfree(list_entry(pos, struct weak_block, list));
}
free_ns_struct:
- kfree(ns);
+ if (!retained)
+ kfree(ns);
return ret;
}
@@ -2431,9 +2440,9 @@ static void __exit ns_cleanup_module(void)
ns_debugfs_remove(ns);
WARN_ON(mtd_device_unregister(nsmtd));
+ nand_disconnect(chip);
ns_free(ns);
kfree(erase_block_wear);
- nand_cleanup(chip);
list_for_each_safe(pos, n, &grave_pages) {
list_del(pos);
@@ -2450,7 +2459,7 @@ static void __exit ns_cleanup_module(void)
kfree(list_entry(pos, struct weak_block, list));
}
- kfree(ns);
+ mtd_put_master(nsmtd);
}
module_exit(ns_cleanup_module);
--
2.53.0