[PATCH 08/58] mtd: rawnand: plat_nand: retain open-handle state on removal
James Hilliard
james.hilliard1 at gmail.com
Sat Nov 7 02:16:05 PST 2026
Unregister MTD while notifier clients can finish their I/O, then
disconnect the NAND chip before invoking the platform hardware teardown.
Keep the chip, controller lock and software ECC metadata until the last
MTD reference is dropped.
Handle registration failures through the same reference-counted cleanup,
since partitions can have become visible before registration fails.
Fixes: 711fdf627ce1 ("[MTD] [NAND] platform NAND driver: add driver")
Signed-off-by: James Hilliard <james.hilliard1 at gmail.com>
---
drivers/mtd/nand/raw/plat_nand.c | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c
index fe31551bcf5f..8321667fae2f 100644
--- a/drivers/mtd/nand/raw/plat_nand.c
+++ b/drivers/mtd/nand/raw/plat_nand.c
@@ -21,6 +21,11 @@ struct plat_nand_data {
struct gpio_desc *ready_gpio;
};
+static void plat_nand_release(struct nand_controller *controller)
+{
+ kfree(container_of(controller, struct plat_nand_data, controller));
+}
+
static int plat_nand_attach_chip(struct nand_chip *chip)
{
if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT &&
@@ -65,10 +70,13 @@ static int plat_nand_probe(struct platform_device *pdev)
}
/* Allocate memory for the device structure (and zero it) */
- data = devm_kzalloc(&pdev->dev, sizeof(struct plat_nand_data),
- GFP_KERNEL);
+ data = kzalloc_obj(*data);
if (!data)
return -ENOMEM;
+ err = devm_nand_controller_init(&pdev->dev, &data->controller,
+ plat_nand_release);
+ if (err)
+ return err;
data->ready_gpio = devm_gpiod_get_optional(&pdev->dev, "ready",
GPIOD_IN);
@@ -77,7 +85,6 @@ static int plat_nand_probe(struct platform_device *pdev)
"could not get READY GPIO\n");
data->controller.ops = &plat_nand_ops;
- nand_controller_init(&data->controller);
data->chip.controller = &data->controller;
chip = &data->chip;
nand_set_controller_data(chip, data);
@@ -126,6 +133,11 @@ static int plat_nand_probe(struct platform_device *pdev)
goto out;
part_types = pdata->chip.part_probe_types;
+ err = nand_set_release(chip, NULL);
+ if (err) {
+ nand_cleanup(chip);
+ goto out;
+ }
err = mtd_device_parse_register(mtd, part_types, NULL,
pdata->chip.partitions,
@@ -134,7 +146,8 @@ static int plat_nand_probe(struct platform_device *pdev)
if (!err)
return err;
- nand_cleanup(&data->chip);
+ nand_disconnect(chip);
+ mtd_put_master(mtd);
out:
if (pdata->ctrl.remove)
pdata->ctrl.remove(pdev);
@@ -153,9 +166,10 @@ static void plat_nand_remove(struct platform_device *pdev)
ret = mtd_device_unregister(nand_to_mtd(chip));
WARN_ON(ret);
- nand_cleanup(chip);
+ nand_disconnect(chip);
if (pdata->ctrl.remove)
pdata->ctrl.remove(pdev);
+ mtd_put_master(nand_to_mtd(chip));
}
static const struct of_device_id plat_nand_match[] = {
--
2.53.0
More information about the linux-mtd
mailing list