[PATCH v2] rust: io: mem: Fix exclusive MMIO region requests

From: Kwanghoon Son

Date: Mon Nov 02 2026 - 20:10:22 EST


C's request_mem_region() reserves MMIO in the global resource tree.
Rust's ExclusiveIoMem reserves it under the device's resource instead,
so the global tree may not see the reservation.

Request the region from iomem_resource, matching request_mem_region()
and the existing release_mem_region() call.

Fixes: 1d0d4b28513b ("rust: io: mem: add a generic iomem abstraction")

Signed-off-by: Kwanghoon Son <asdfkwang@xxxxxxxxx>
---
The bug can be reproduced with QEMU arm64 virt's existing DT node
(CONFIG_FW_CFG_SYSFS=n):

fw-cfg@9020000 {
compatible = "qemu,fw-cfg-mmio";
reg = <0 0x09020000 0 0x18>;
};

A small Rust platform driver matches this node. Its probe maps the
resource and returns the mapping as driver data (excerpt):

let io = pdev.io_request_by_index(0).ok_or(ENODEV)?
.iomap_exclusive()?
.into_devres()?;

Unbind and bind that driver again:

cd /sys/bus/platform/drivers/mmio_repro
echo 9020000.fw-cfg > unbind
echo 9020000.fw-cfg > bind

Before the fix, unbind prints "Trying to free nonexistent resource"
and bind fails with EBUSY.
---
Changes in v2:
- Guard Resource::iomem() with CONFIG_HAS_IOMEM to match its only
caller and avoid a dead_code warning when I/O memory support is
disabled.
- Rebase onto 6628e7d4c6b2.
- Link to v1: https://lore.kernel.org/r/20261027-b4-rust-iomem-origin-master-fix-v1-1-16215ae197af@xxxxxxxxx
---
rust/kernel/io/mem.rs | 2 +-
rust/kernel/io/resource.rs | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/io/mem.rs b/rust/kernel/io/mem.rs
index 32a919099dcda79bc4b795a8a1c5f553c989b9b7..80da665821c036257900c6ea45b9419cb573c187 100644
--- a/rust/kernel/io/mem.rs
+++ b/rust/kernel/io/mem.rs
@@ -196,7 +196,7 @@ fn ioremap(dev: &'a Device<Bound>, resource: &Resource) -> Result<Self> {
let size = resource.size();
let name = resource.name().unwrap_or_default();

- let region = resource
+ let region = Resource::iomem()
.request_region(
start,
size,
diff --git a/rust/kernel/io/resource.rs b/rust/kernel/io/resource.rs
index 758ce62b3cce33c14e1e4c56a793af0e00657aa6..d61ad63428679a87b26a79c5ce822c5976a8b82f 100644
--- a/rust/kernel/io/resource.rs
+++ b/rust/kernel/io/resource.rs
@@ -79,6 +79,13 @@ unsafe impl Sync for Region {}
pub struct Resource(Opaque<bindings::resource>);

impl Resource {
+ /// Returns the global I/O memory resource root.
+ #[cfg(CONFIG_HAS_IOMEM)]
+ pub(crate) fn iomem() -> &'static Self {
+ // SAFETY: iomem_resource is permanent; C serializes resource-tree updates.
+ unsafe { Self::from_raw(&raw mut bindings::iomem_resource) }
+ }
+
/// Creates a reference to a [`Resource`] from a valid pointer.
///
/// # Safety

---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20261027-b4-rust-iomem-origin-master-fix-885f1ea244fb

Best regards,
--
Kwanghoon Son <asdfkwang@xxxxxxxxx>