[PATCH v4 23/58] mtd: rawnand: ams-delta: retain open-handle state on removal

From: James Hilliard

Date: Fri Nov 13 2026 - 14:07:41 EST


Keep chip metadata and controller storage alive until the final MTD
reference is released. Unregister and disconnect each published chip
before releasing the resources used by its hardware operations.

Apply write protection after unregister notifiers finish their writes.

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/ams-delta.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 1afeb38145cd..af3641550b2c 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -250,10 +250,12 @@ static int gpio_nand_probe(struct platform_device *pdev)
}

/* Allocate memory for MTD device structure and private data */
- priv = devm_kzalloc(&pdev->dev, sizeof(struct gpio_nand),
- GFP_KERNEL);
+ priv = kzalloc_obj(*priv);
if (!priv)
return -ENOMEM;
+ err = devm_nand_controller_init(&pdev->dev, &priv->base, priv);
+ if (err)
+ return err;

this = &priv->nand_chip;

@@ -355,7 +357,6 @@ static int gpio_nand_probe(struct platform_device *pdev)

/* Initialize the NAND controller object embedded in gpio_nand. */
priv->base.ops = &gpio_nand_ops;
- nand_controller_init(&priv->base);
this->controller = &priv->base;

/*
@@ -382,9 +383,15 @@ static int gpio_nand_probe(struct platform_device *pdev)
return err;

/* Register the partitions */
- err = mtd_device_register(mtd, partitions, num_partitions);
+ err = nand_set_lifetime(this, NULL);
if (err)
goto err_nand_cleanup;
+ err = mtd_device_register(mtd, partitions, num_partitions);
+ if (err) {
+ nand_disconnect(this);
+ mtd_put_master(mtd);
+ return err;
+ }

return 0;

@@ -403,13 +410,14 @@ static void gpio_nand_remove(struct platform_device *pdev)
struct mtd_info *mtd = nand_to_mtd(&priv->nand_chip);
int ret;

- /* Apply write protection */
- gpiod_set_value(priv->gpiod_nwp, 1);
-
/* Unregister device */
ret = mtd_device_unregister(mtd);
WARN_ON(ret);
- nand_cleanup(mtd_to_nand(mtd));
+ nand_disconnect(mtd_to_nand(mtd));
+
+ /* Apply write protection after draining outstanding operations. */
+ gpiod_set_value(priv->gpiod_nwp, 1);
+ mtd_put_master(mtd);
}

#ifdef CONFIG_OF

--
2.53.0