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

From: James Hilliard

Date: Fri Nov 13 2026 - 14:13:08 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.

Keep the shared GPMC lock for bound devices and separately retain each
device's allocation. Disconnected handles return before touching that
lock. Finish software BCH cleanup before releasing DMA and driver code.

Signed-off-by: James Hilliard <james.hilliard1@xxxxxxxxx>
---
drivers/mtd/nand/raw/omap2.c | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c
index aee7df4d768f..12a978f5f724 100644
--- a/drivers/mtd/nand/raw/omap2.c
+++ b/drivers/mtd/nand/raw/omap2.c
@@ -142,6 +142,7 @@ static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc,
static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10};

struct omap_nand_info {
+ struct nand_storage storage;
struct nand_chip nand;
struct platform_device *pdev;

@@ -2218,10 +2219,12 @@ static int omap_nand_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
void __iomem *vaddr;

- info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info),
- GFP_KERNEL);
+ info = kzalloc_obj(*info);
if (!info)
return -ENOMEM;
+ err = devm_nand_storage_init(dev, &info->storage, info);
+ if (err)
+ return err;

info->pdev = pdev;

@@ -2282,9 +2285,16 @@ static int omap_nand_probe(struct platform_device *pdev)
if (err)
goto return_error;

- err = mtd_device_register(mtd, NULL, 0);
+ err = nand_set_shared_lifetime(nand_chip, &info->storage);
if (err)
goto cleanup_nand;
+ err = mtd_device_register(mtd, NULL, 0);
+ if (err) {
+ nand_disconnect(nand_chip);
+ rawnand_sw_bch_cleanup(nand_chip);
+ mtd_put_master(mtd);
+ goto release_dma;
+ }

platform_set_drvdata(pdev, mtd);

@@ -2294,11 +2304,11 @@ static int omap_nand_probe(struct platform_device *pdev)
nand_cleanup(nand_chip);

return_error:
+ rawnand_sw_bch_cleanup(nand_chip);
+release_dma:
if (!IS_ERR_OR_NULL(info->dma))
dma_release_channel(info->dma);

- rawnand_sw_bch_cleanup(nand_chip);
-
return err;
}

@@ -2308,12 +2318,13 @@ static void omap_nand_remove(struct platform_device *pdev)
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct omap_nand_info *info = mtd_to_omap(mtd);

+ WARN_ON(mtd_device_unregister(mtd));
+ nand_disconnect(nand_chip);
rawnand_sw_bch_cleanup(nand_chip);

if (info->dma)
dma_release_channel(info->dma);
- WARN_ON(mtd_device_unregister(mtd));
- nand_cleanup(nand_chip);
+ mtd_put_master(mtd);
}

static const struct of_device_id omap_nand_ids[] = {

--
2.53.0