[PATCH v2 00/58] mtd: rawnand: retain chip and controller state across removal
From: James Hilliard
Date: Tue Nov 10 2026 - 02:45:25 EST
An MTD handle can outlive controller unbind. Its metadata and NAND locks
must remain valid, including when a writable file closes and calls sync,
while further hardware access must be rejected after disconnection.
This builds on earlier MTD removal-lifetime work. Commit 19bfa9ebebb5
("mtd: use refcount to prevent corruption") added MTD reference counting
[0], but retaining an MTD reference does not by itself retain the
driver-owned allocation containing the master. The 2025 read/unbind
discussion also covered raw NAND [1] and highlighted the need to drain
active operations before releasing resources [2]. Tze Yee Ng's SPI-NOR
series addresses the corresponding SPI-NOR paths [3]. This series adds
shared backing-object ownership and applies it to raw-NAND drivers.
Introduce an opt-in backing-object lifetime for MTD masters and separate
raw-NAND hardware disconnection from final cleanup. Registered MTD nodes,
device references and open handles retain the backing chip; nested
partitions also retain their parent metadata. Removal notifiers can
finish I/O before disconnection drains admitted operations. Hardware
resources are then released without waiting for open files to close.
Virtual concatenations retain their original hidden components and backing
objects across removal. Serialize staging across controllers, publish in
DT order after partition registration completes, and release incomplete
registrations without disturbing another controller's components.
OTP providers retain their callback context through final NVMEM device
release while keeping their existing physical-device parent. Add opt-in
NVMEM context references to support that ownership.
Device release callbacks keep their module loaded until they return.
Add an opt-in device-core owner reference so MTD can hand the final
module put to built-in code after its callback finishes.
Share the chip and controller ownership helpers and convert the raw-NAND
controller drivers. Each driver conversion keeps metadata cleanup
separate from hardware teardown, including partially published probes.
Shared controllers remain allocated until their last retained chip is
released. R852 allocates a new chip for each inserted card, and NDFC
allocates controller state per binding, so old handles cannot refer to
replacement media or a new binding.
The series adds the common lifetime support and converts its driver
users. It is based on NAND next at 30daaf3e7897 with Tze Yee Ng's
module-reference ordering fix [4] and Karl Mehltretter's upstream OTP
cleanup fix [6]. The separately posted MTD registration, NAND
operation-locking and controller probe/teardown fixes are prerequisites
as well; the prerequisite metadata identifies their posted versions.
The master-open reference accounting fix is included in the MTD
ownership patch because it overlaps the module-reference ordering
prerequisite.
TLA+ models of retained-handle, controller and OTP ownership, including
their assumptions and coverage limits, are available in [5].
[0] https://lore.kernel.org/r/20230620131905.648089-2-alexander.usyskin@xxxxxxxxx
[1] https://lore.kernel.org/r/CAND4H7dz94Gsi_tXSQmLNme9uROnouOUwuCX9BW_+RCc2ZFDqA@xxxxxxxxxxxxxx
[2] https://lore.kernel.org/r/mafs0bjs73tbq.fsf@xxxxxxxxxx
[3] https://lore.kernel.org/r/20261022035352.52129-1-tze.yee.ng@xxxxxxxxxx
[4] https://lore.kernel.org/r/20261022035352.52129-2-tze.yee.ng@xxxxxxxxxx
[5] https://github.com/jameshilliard/linux-h616-nand-tla
[6] https://lore.kernel.org/r/20260816163027.10044-1-kmehltretter@xxxxxxxxx
Assisted-by: Codex:gpt-6-astra
Signed-off-by: James Hilliard <james.hilliard1@xxxxxxxxx>
---
Changes in v2:
- Keep the MTD device callback owner pinned through callback return,
with the final module put performed by the device core.
- Retain virtual-concat components across removal and rebind, serialize
staging/publication and unwind incomplete partition registrations.
- Balance Tegra's probe-time child-node reference separately from the
reference retained for the chip lifetime.
- Refresh the prerequisite stack to the separately posted fixes, using
the latest QCOM child-probe revision.
- Keep the lifetime changes on top of those fixes: preserve QCOM scan
before publication, R852 per-card initialization and Intel probe
hardware shutdown.
- Fold Macronix disconnection handling into the NAND disconnect patch;
its operation locking is supplied by the posted prerequisite.
- Use Karl Mehltretter's posted OTP cleanup fix as a prerequisite in
place of the duplicate preparatory patch.
- Keep the NVMEM context callback module pinned until its final callback
returns, independently of the provider's consumer owner.
- Use the posted fixes for dynamic partition publication and partition-node
ownership. Keep master get/put accounting independent of
later master registration in the MTD ownership patch.
- Propagate disconnection through BBT error recovery without marking
the eraseblock bad.
- Make suspend of a disconnected, retained NAND device a no-op.
- Handle R852 card events during removal while preventing new work from
being queued.
- Initialize Denali and Atmel cleanup variables at allocation and add
the introducing-commit trailers for Orion and MPC5121.
- Link to v1: https://patch.msgid.link/20261107-submit-rawnand-retained-handle-lifetime-v1-v1-0-0181ef0cc4c8@xxxxxxxxx
---
James Hilliard (58):
nvmem: retain provider context through final device release
driver core: retain the owner of device release callbacks
mtd: add opt-in lifetime ownership for backing objects
mtd: retain virtual concatenations across component removal
mtd: rawnand: separate hardware disconnection from cleanup
mtd: rawnand: share retained chip and controller ownership
mtd: rawnand: sunxi: retain chip state until the final MTD put
mtd: rawnand: plat_nand: retain open-handle state on removal
mtd: rawnand: gpio: retain open-handle state on removal
mtd: rawnand: stm32_fmc2: retain open-handle state on removal
mtd: rawnand: denali: retain chips across controller removal
mtd: rawnand: arasan: retain chips across controller removal
mtd: rawnand: mxic: retain open-handle state on removal
mtd: rawnand: intel: retain open-handle state on removal
mtd: rawnand: tegra: retain open-handle state on removal
mtd: rawnand: mtk: retain chips across controller removal
mtd: rawnand: rockchip: retain chips across controller removal
mtd: rawnand: atmel: retain chips across controller removal
mtd: rawnand: orion: retain open-handle state on removal
mtd: rawnand: socrates: retain open-handle state on removal
mtd: rawnand: fsl_upm: retain open-handle state on removal
mtd: rawnand: pasemi: retain open-handle state on removal
mtd: rawnand: ams-delta: retain open-handle state on removal
mtd: rawnand: xway: retain open-handle state on removal
mtd: rawnand: hisi504: retain open-handle state on removal
mtd: rawnand: vf610: retain open-handle state on removal
mtd: rawnand: technologic: retain open-handle state on removal
mtd: rawnand: loongson: retain open-handle state on removal
mtd: rawnand: ma35d1: retain open-handle state on removal
mtd: rawnand: pl35x: retain open-handle state on removal
mtd: rawnand: mxc: retain open-handle state on removal
mtd: rawnand: fsmc: retain open-handle state on removal
mtd: rawnand: gpmi: retain open-handle state on removal
mtd: rawnand: omap2: retain open-handle state on removal
mtd: rawnand: marvell: retain open-handle state on removal
mtd: rawnand: renesas: retain open-handle state on removal
mtd: rawnand: meson: retain open-handle state on removal
mtd: rawnand: cadence: retain open-handle state on removal
mtd: rawnand: qcom: retain open-handle state on removal
mtd: rawnand: cafe: retain open-handle state on removal
mtd: rawnand: brcmnand: retain open-handle state on removal
mtd: rawnand: au1550nd: retain chip state across removal
mtd: rawnand: sharpsl: retain chip state across removal
mtd: rawnand: davinci: retain chip state across removal
mtd: rawnand: sh_flctl: retain chip state across removal
mtd: rawnand: lpc32xx_slc: retain chip state across removal
mtd: rawnand: lpc32xx_mlc: retain chip state across removal
mtd: rawnand: ndfc: retain chip state across removal
mtd: rawnand: txx9ndfmc: retain chip state across removal
mtd: rawnand: ingenic: retain chip state across removal
mtd: rawnand: mpc5121: retain chip state across removal
mtd: rawnand: bcm47xxnflash: retain chip state across removal
mtd: rawnand: fsl_elbc: retain chip state across removal
mtd: rawnand: fsl_ifc: retain chip state across removal
mtd: rawnand: r852: retain chip state across removal
mtd: rawnand: nandsim: retain chip state across removal
mtd: rawnand: cs553x: retain chip state across removal
mtd: rawnand: diskonchip: retain chip state across removal
drivers/base/core.c | 9 +
drivers/mtd/mtd_virt_concat.c | 513 ++++++++++-----------
drivers/mtd/mtdcore.c | 199 ++++++--
drivers/mtd/mtdcore.h | 3 +
drivers/mtd/mtdpart.c | 14 +-
drivers/mtd/nand/raw/Makefile | 1 +
drivers/mtd/nand/raw/ams-delta.c | 29 +-
drivers/mtd/nand/raw/arasan-nand-controller.c | 57 ++-
drivers/mtd/nand/raw/atmel/nand-controller.c | 59 ++-
drivers/mtd/nand/raw/au1550nd.c | 26 +-
drivers/mtd/nand/raw/bcm47xxnflash/main.c | 23 +-
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 72 ++-
drivers/mtd/nand/raw/cadence-nand-controller.c | 60 ++-
drivers/mtd/nand/raw/cafe_nand.c | 37 +-
drivers/mtd/nand/raw/cs553x_nand.c | 46 +-
drivers/mtd/nand/raw/davinci_nand.c | 29 +-
drivers/mtd/nand/raw/denali.c | 31 +-
drivers/mtd/nand/raw/denali_dt.c | 21 +-
drivers/mtd/nand/raw/denali_pci.c | 15 +-
drivers/mtd/nand/raw/diskonchip.c | 21 +-
drivers/mtd/nand/raw/fsl_elbc_nand.c | 68 ++-
drivers/mtd/nand/raw/fsl_ifc_nand.c | 58 ++-
drivers/mtd/nand/raw/fsl_upm.c | 23 +-
drivers/mtd/nand/raw/fsmc_nand.c | 22 +-
drivers/mtd/nand/raw/gpio.c | 21 +-
drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 22 +-
drivers/mtd/nand/raw/hisi504_nand.c | 23 +-
drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c | 49 +-
drivers/mtd/nand/raw/intel-nand-controller.c | 23 +-
drivers/mtd/nand/raw/internals.h | 2 +-
drivers/mtd/nand/raw/loongson-nand-controller.c | 23 +-
drivers/mtd/nand/raw/lpc32xx_mlc.c | 26 +-
drivers/mtd/nand/raw/lpc32xx_slc.c | 26 +-
drivers/mtd/nand/raw/marvell_nand.c | 54 ++-
drivers/mtd/nand/raw/meson_nand.c | 55 ++-
drivers/mtd/nand/raw/mpc5121_nfc.c | 29 +-
drivers/mtd/nand/raw/mtk_nand.c | 44 +-
drivers/mtd/nand/raw/mxc_nand.c | 24 +-
drivers/mtd/nand/raw/mxic_nand.c | 26 +-
drivers/mtd/nand/raw/nand_base.c | 76 ++-
drivers/mtd/nand/raw/nand_bbt.c | 24 +-
drivers/mtd/nand/raw/nand_lifetime.c | 118 +++++
drivers/mtd/nand/raw/nand_macronix.c | 4 +-
drivers/mtd/nand/raw/nandsim.c | 24 +-
drivers/mtd/nand/raw/ndfc.c | 37 +-
.../mtd/nand/raw/nuvoton-ma35d1-nand-controller.c | 44 +-
drivers/mtd/nand/raw/omap2.c | 45 +-
drivers/mtd/nand/raw/orion_nand.c | 27 +-
drivers/mtd/nand/raw/pasemi_nand.c | 25 +-
drivers/mtd/nand/raw/pl35x-nand-controller.c | 46 +-
drivers/mtd/nand/raw/plat_nand.c | 24 +-
drivers/mtd/nand/raw/qcom_nandc.c | 46 +-
drivers/mtd/nand/raw/r852.c | 114 +++--
drivers/mtd/nand/raw/r852.h | 1 +
drivers/mtd/nand/raw/renesas-nand-controller.c | 45 +-
drivers/mtd/nand/raw/rockchip-nand-controller.c | 49 +-
drivers/mtd/nand/raw/sh_flctl.c | 25 +-
drivers/mtd/nand/raw/sharpsl.c | 25 +-
drivers/mtd/nand/raw/sm_common.c | 15 +-
drivers/mtd/nand/raw/sm_common.h | 2 +-
drivers/mtd/nand/raw/socrates_nand.c | 22 +-
drivers/mtd/nand/raw/stm32_fmc2_nand.c | 22 +-
drivers/mtd/nand/raw/sunxi_nand.c | 59 ++-
drivers/mtd/nand/raw/technologic-nand-controller.c | 25 +-
drivers/mtd/nand/raw/tegra_nand.c | 39 +-
drivers/mtd/nand/raw/txx9ndfmc.c | 42 +-
drivers/mtd/nand/raw/vf610_nfc.c | 22 +-
drivers/mtd/nand/raw/xway_nand.c | 27 +-
drivers/nvmem/core.c | 18 +-
drivers/nvmem/internals.h | 2 +
include/linux/device.h | 4 +
include/linux/mtd/concat.h | 18 +-
include/linux/mtd/mtd.h | 16 +
include/linux/mtd/rawnand.h | 21 +-
include/linux/nvmem-provider.h | 12 +
75 files changed, 2240 insertions(+), 808 deletions(-)
---
base-commit: 30daaf3e7897b4a8d9b72e5b0c86dd6e2a4d7d85
change-id: 20261104-submit-rawnand-retained-handle-lifetime-v1-0b4225e5ce0b
prerequisite-patch-id: a51b9cb4077105499133c413d58c7ad21d973b38
prerequisite-patch-id: b3679cda4dcb45ce7712bffe2dd0576b254df44d
prerequisite-patch-id: 07b5c70e44ad951d20eea9478c98fda35ec765c0
prerequisite-patch-id: abea50275922fe359d72ca4de5cbc211b04bbd57
prerequisite-patch-id: 57776b214ffb0331319f024412f21d35e4ca9056
prerequisite-patch-id: 09be2baaffe1f053704263cc4b0d39f2faa4f49c
prerequisite-patch-id: c3ad85600dc897ac310be450d8daa2275fb91ee6
prerequisite-patch-id: 4a85600553ddcc7db5a9537efd905a71cd623f65
prerequisite-patch-id: 579990ee4a49297efc5a593b00efb9cd73fa15e8
prerequisite-patch-id: 2ee61a8a32fd147d52e0f9d03758634912d8bfef
prerequisite-patch-id: 1487df8ce8e6c48471fd77c7470ce9de582dfe3c
prerequisite-patch-id: 5ecbe86f928d9c5c0bf2cb6065c5672708511fc4
prerequisite-patch-id: ac68e9b65d3aa5661bd7ac0f2e77dcf5c75fcfe0
prerequisite-patch-id: e70f0f0c4d430d416a3ad848b37ffad16bd7df07
prerequisite-patch-id: 05adcddbc50f745ee2640b8c21f3bf76a217f249
prerequisite-patch-id: 0b60b7ab6196076f327c919be5e7b8bb2051ee12
Best regards,
--
James Hilliard <james.hilliard1@xxxxxxxxx>