[PATCH v4 37/58] mtd: rawnand: meson: retain open-handle state on removal

From: James Hilliard

Date: Fri Nov 13 2026 - 16:03:00 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.

Free transfer buffers in the synchronous NAND detach callback.

Cc: Jerome Brunet <jbrunet@xxxxxxxxxxxx>
Cc: Kevin Hilman <khilman@xxxxxxxxxxxx>
Cc: Liang Yang <liang.yang@xxxxxxxxxxx>
Cc: linux-amlogic@xxxxxxxxxxxxxxxxxxx
Cc: linux-arm-kernel@xxxxxxxxxxxxxxxxxxx
Cc: Martin Blumenstingl <martin.blumenstingl@xxxxxxxxxxxxxx>
Cc: Neil Armstrong <neil.armstrong@xxxxxxxxxx>
Signed-off-by: James Hilliard <james.hilliard1@xxxxxxxxx>
---
drivers/mtd/nand/raw/meson_nand.c | 47 +++++++++++++++++++++++++--------------
1 file changed, 30 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
index 2a554f62a25e..871dc5e22759 100644
--- a/drivers/mtd/nand/raw/meson_nand.c
+++ b/drivers/mtd/nand/raw/meson_nand.c
@@ -1398,8 +1398,7 @@ meson_nfc_nand_chip_init(struct device *dev,
return -EINVAL;
}

- meson_chip = devm_kzalloc(dev, struct_size(meson_chip, sels, nsels),
- GFP_KERNEL);
+ meson_chip = kzalloc(struct_size(meson_chip, sels, nsels), GFP_KERNEL);
if (!meson_chip)
return -ENOMEM;

@@ -1410,12 +1409,13 @@ meson_nfc_nand_chip_init(struct device *dev,
if (ret) {
dev_err(dev, "could not retrieve register property: %d\n",
ret);
- return ret;
+ goto free_chip;
}

if (test_and_set_bit(tmp, &nfc->assigned_cs)) {
dev_err(dev, "CS %d already assigned\n", tmp);
- return -EINVAL;
+ ret = -EINVAL;
+ goto free_chip;
}
}

@@ -1427,21 +1427,23 @@ meson_nfc_nand_chip_init(struct device *dev,

nand->options |= NAND_USES_DMA;
mtd = nand_to_mtd(nand);
- mtd->owner = THIS_MODULE;
+
mtd->parent_dev = dev;

ret = of_property_read_u32(np, "nand-rb", &nand_rb_val);
if (ret == -EINVAL)
nfc->no_rb_pin = true;
else if (ret)
- return ret;
+ goto free_chip;

- if (nand_rb_val)
- return -EINVAL;
+ if (nand_rb_val) {
+ ret = -EINVAL;
+ goto free_chip;
+ }

ret = nand_scan(nand, nsels);
if (ret)
- return ret;
+ goto free_chip;

if (nand->options & NAND_IS_BOOT_MEDIUM) {
ret = of_property_read_u32(np, "amlogic,boot-pages",
@@ -1449,8 +1451,7 @@ meson_nfc_nand_chip_init(struct device *dev,
if (ret) {
dev_err(dev, "could not retrieve 'amlogic,boot-pages' property: %d",
ret);
- nand_cleanup(nand);
- return ret;
+ goto cleanup_nand;
}

ret = of_property_read_u32(np, "amlogic,boot-page-step",
@@ -1458,21 +1459,30 @@ meson_nfc_nand_chip_init(struct device *dev,
if (ret) {
dev_err(dev, "could not retrieve 'amlogic,boot-page-step' property: %d",
ret);
- nand_cleanup(nand);
- return ret;
+ goto cleanup_nand;
}
}

+ ret = nand_set_lifetime(nand, to_meson_nand(nand));
+ if (ret)
+ goto cleanup_nand;
ret = mtd_device_register(mtd, NULL, 0);
if (ret) {
dev_err(dev, "failed to register MTD device: %d\n", ret);
- nand_cleanup(nand);
+ nand_disconnect(nand);
+ mtd_put_master(mtd);
return ret;
}

list_add_tail(&meson_chip->node, &nfc->chips);

return 0;
+
+cleanup_nand:
+ nand_cleanup(nand);
+free_chip:
+ kfree(meson_chip);
+ return ret;
}

static void meson_nfc_nand_chips_cleanup(struct meson_nfc *nfc)
@@ -1486,8 +1496,9 @@ static void meson_nfc_nand_chips_cleanup(struct meson_nfc *nfc)
mtd = nand_to_mtd(&meson_chip->nand);
WARN_ON(mtd_device_unregister(mtd));

- nand_cleanup(&meson_chip->nand);
+ nand_disconnect(&meson_chip->nand);
list_del(&meson_chip->node);
+ mtd_put_master(mtd);
}
}

@@ -1550,15 +1561,17 @@ static int meson_nfc_probe(struct platform_device *pdev)
struct meson_nfc *nfc;
int ret, irq;

- nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
+ nfc = kzalloc_obj(*nfc);
if (!nfc)
return -ENOMEM;
+ ret = devm_nand_controller_init(dev, &nfc->controller, nfc);
+ if (ret)
+ return ret;

nfc->data = of_device_get_match_data(&pdev->dev);
if (!nfc->data)
return -ENODEV;

- nand_controller_init(&nfc->controller);
INIT_LIST_HEAD(&nfc->chips);
init_completion(&nfc->completion);


--
2.53.0