[PATCH 23/58] mtd: rawnand: ams-delta: retain open-handle state on removal
James Hilliard
james.hilliard1 at gmail.com
Sat Nov 7 02:16:20 PST 2026
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.
Signed-off-by: James Hilliard <james.hilliard1 at gmail.com>
---
drivers/mtd/nand/raw/ams-delta.c | 29 +++++++++++++++++++++--------
1 file changed, 21 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index fb2b7db70297..ca3fd966c4ff 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -233,6 +233,11 @@ static const struct nand_controller_ops gpio_nand_ops = {
/*
* Main initialization routine
*/
+static void gpio_nand_release(struct nand_controller *controller)
+{
+ kfree(container_of(controller, struct gpio_nand, base));
+}
+
static int gpio_nand_probe(struct platform_device *pdev)
{
struct gpio_nand_platdata *pdata = dev_get_platdata(&pdev->dev);
@@ -250,10 +255,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, gpio_nand_release);
+ if (err)
+ return err;
this = &priv->nand_chip;
@@ -355,7 +362,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 +388,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_release(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 +415,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
More information about the linux-mtd
mailing list