[PATCH v4 58/58] mtd: rawnand: diskonchip: retain chip state across removal
From: James Hilliard
Date: Fri Nov 13 2026 - 15:42:11 EST
MTD references may outlive a partially published registration failure.
Disconnect before unmapping the device and freeing the hardware ECC
codec, while retaining chip metadata until the final MTD reference is
released. Install lifetime ownership before the late initializer
publishes partitions.
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/diskonchip.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c
index 540b6baf8bb1..2c6d0c0fdb2d 100644
--- a/drivers/mtd/nand/raw/diskonchip.c
+++ b/drivers/mtd/nand/raw/diskonchip.c
@@ -1466,7 +1466,6 @@ static int __init doc_probe(unsigned long physadr)
nand->bbt_td = (struct nand_bbt_descr *) (doc + 1);
nand->bbt_md = nand->bbt_td + 1;
- mtd->owner = THIS_MODULE;
mtd_set_ooblayout(mtd, &doc200x_ooblayout_ops);
nand->controller = &doc->base;
@@ -1494,13 +1493,21 @@ static int __init doc_probe(unsigned long physadr)
ret = nand_scan(nand, numchips);
if (ret)
goto fail;
-
- ret = doc->late_init(mtd);
+ ret = nand_set_lifetime(nand, nand);
if (ret) {
nand_cleanup(nand);
goto fail;
}
+ ret = doc->late_init(mtd);
+ if (ret) {
+ nand_disconnect(nand);
+ free_rs(doc->rs_decoder);
+ iounmap(virtadr);
+ mtd_put_master(mtd);
+ goto error_ioremap;
+ }
+
/* Success! */
doclist = mtd;
return 0;
@@ -1535,11 +1542,11 @@ static void release_nanddoc(void)
nextmtd = doc->nextdoc;
ret = mtd_device_unregister(mtd);
WARN_ON(ret);
- nand_cleanup(nand);
+ nand_disconnect(nand);
iounmap(doc->virtadr);
release_mem_region(doc->physadr, DOC_IOREMAP_LEN);
free_rs(doc->rs_decoder);
- kfree(nand);
+ mtd_put_master(mtd);
}
}
--
2.53.0