[PATCH 10/58] mtd: rawnand: stm32_fmc2: retain open-handle state on removal
James Hilliard
james.hilliard1 at gmail.com
Sat Nov 7 02:16:07 PST 2026
Keep the embedded NAND chip and controller serialization state alive for
MTD references that survive unbind. Disconnect operations before
releasing DMA channels and scatterlists and asserting write protection;
defer NAND metadata cleanup and controller storage release until the
final reference.
Preserve immediate cleanup before publication and use the retained
lifetime after MTD registration has been attempted.
Fixes: 2cd457f328c1 ("mtd: rawnand: stm32_fmc2: add STM32 FMC2 NAND flash controller driver")
Signed-off-by: James Hilliard <james.hilliard1 at gmail.com>
---
drivers/mtd/nand/raw/stm32_fmc2_nand.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 9f42f8ab3212..4b89094c89e6 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -1902,6 +1902,11 @@ static int stm32_fmc2_nfc_set_cdev(struct stm32_fmc2_nfc *nfc)
return 0;
}
+static void stm32_fmc2_nfc_release(struct nand_controller *controller)
+{
+ kfree(container_of(controller, struct stm32_fmc2_nfc, base));
+}
+
static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1915,12 +1920,14 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
int chip_cs, mem_region, ret, irq;
int start_region = 0;
- nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
+ nfc = kzalloc_obj(*nfc);
if (!nfc)
return -ENOMEM;
+ ret = devm_nand_controller_init(dev, &nfc->base, stm32_fmc2_nfc_release);
+ if (ret)
+ return ret;
nfc->dev = dev;
- nand_controller_init(&nfc->base);
nfc->base.ops = &stm32_fmc2_nfc_controller_ops;
nfc->data = of_device_get_match_data(dev);
@@ -2024,9 +2031,15 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
if (ret)
goto err_wp_enable;
- ret = mtd_device_register(mtd, NULL, 0);
+ ret = nand_set_release(chip, NULL);
if (ret)
goto err_nand_cleanup;
+ ret = mtd_device_register(mtd, NULL, 0);
+ if (ret) {
+ nand_disconnect(chip);
+ mtd_put_master(mtd);
+ goto err_wp_enable;
+ }
platform_set_drvdata(pdev, nfc);
@@ -2061,7 +2074,7 @@ static void stm32_fmc2_nfc_remove(struct platform_device *pdev)
ret = mtd_device_unregister(nand_to_mtd(chip));
WARN_ON(ret);
- nand_cleanup(chip);
+ nand_disconnect(chip);
if (nfc->dma_ecc_ch)
dma_release_channel(nfc->dma_ecc_ch);
@@ -2074,6 +2087,7 @@ static void stm32_fmc2_nfc_remove(struct platform_device *pdev)
sg_free_table(&nfc->dma_ecc_sg);
stm32_fmc2_nfc_wp_enable(nand);
+ mtd_put_master(nand_to_mtd(chip));
}
static int stm32_fmc2_nfc_suspend(struct device *dev)
--
2.53.0
More information about the linux-mtd
mailing list