The previous patches have added the abstractions for Resources and the
ability to map them and therefore read and write the underlying memory .
The only thing missing to make this accessible for platform devices is
to provide accessors that return instances of IoRequest<'a>. These
ensure that the resource are valid only for the lifetime of the platform
device, and that the platform device is in the Bound state.
Therefore, add these accessors. Also make it possible to retrieve
resources from platform devices in Rust using either a name or an index.
Acked-by: Miguel Ojeda <ojeda@kernel.org>
Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com>
---
rust/kernel/platform.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 59 insertions(+), 1 deletion(-)
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index 86f9d73c64b38ffe067be329a77b2fc04564c7fe..57f9964bb736cf5749ec3954def03c0d02873642 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -5,8 +5,11 @@
//! C header: [`include/linux/platform_device.h`](srctree/include/linux/platform_device.h)
use crate::{
- acpi, bindings, container_of, device, driver,
+ acpi, bindings, container_of,
+ device::{self, Bound},
+ driver,
error::{to_result, Result},
+ io::{mem::IoRequest, Resource},
of,
prelude::*,
str::CStr,
@@ -211,6 +214,61 @@ impl<Ctx: device::DeviceContext> Device<Ctx> {
fn as_raw(&self) -> *mut bindings::platform_device {
self.0.get()
}
+
+ /// Returns the resource at `index`, if any.
+ pub fn resource_by_index(&self, index: u32) -> Option<&Resource> {
+ // SAFETY: `self.as_raw()` returns a valid pointer to a `struct platform_device`.
+ let resource = unsafe {
+ bindings::platform_get_resource(self.as_raw(), bindings::IORESOURCE_MEM, index)
+ };
+
+ if resource.is_null() {
+ return None;
+ }
+
+ // SAFETY: `resource` is a valid pointer to a `struct resource` as
+ // returned by `platform_get_resource`.
+ Some(unsafe { Resource::from_raw(resource) })
+ }
+
+ /// Returns the resource with a given `name`, if any.
+ pub fn resource_by_name(&self, name: &CStr) -> Option<&Resource> {
+ // SAFETY: `self.as_raw()` returns a valid pointer to a `struct
+ // platform_device` and `name` points to a valid C string.
+ let resource = unsafe {
+ bindings::platform_get_resource_byname(
+ self.as_raw(),
+ bindings::IORESOURCE_MEM,
+ name.as_char_ptr(),
+ )
+ };
+
+ if resource.is_null() {
+ return None;
+ }
+
+ // SAFETY: `resource` is a valid pointer to a `struct resource` as
+ // returned by `platform_get_resource`.
+ Some(unsafe { Resource::from_raw(resource) })
+ }
+}
+
+impl Device<Bound> {
+ /// Returns an `IoRequest` for the resource at `index`, if any.
+ pub fn io_request_by_index(&self, index: u32) -> Option<IoRequest<'_>> {
+ // SAFETY: `resource` is a valid resource for `&self` during the
+ // lifetime of the `IoRequest`.
+ self.resource_by_index(index)
+ .map(|resource| unsafe { IoRequest::new(self.as_ref(), resource) })
+ }
+
+ /// Returns an `IoRequest` for the resource with a given `name`, if any.
+ pub fn io_request_by_name(&self, name: &CStr) -> Option<IoRequest<'_>> {
+ // SAFETY: `resource` is a valid resource for `&self` during the
+ // lifetime of the `IoRequest`.
+ self.resource_by_name(name)
+ .map(|resource| unsafe { IoRequest::new(self.as_ref(), resource) })
+ }
}
// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic
--
2.50.0
On Thu Jul 17, 2025 at 5:55 PM CEST, Daniel Almeida wrote: > +impl Device<Bound> { > + /// Returns an `IoRequest` for the resource at `index`, if any. > + pub fn io_request_by_index(&self, index: u32) -> Option<IoRequest<'_>> { > + // SAFETY: `resource` is a valid resource for `&self` during the > + // lifetime of the `IoRequest`. > + self.resource_by_index(index) > + .map(|resource| unsafe { IoRequest::new(self.as_ref(), resource) }) It seems there's a bug in some clippy versions we support. My regular testing shows a warning for this with clippy 1.78: warning: unsafe block missing a safety comment --> rust/kernel/platform.rs:275:29 | 275 | .map(|resource| unsafe { IoRequest::new(self.as_ref(), resource) }) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | However, there clearly is a safety comment. It seems it gets confused by the multiline formatting. If I write this as self.resource_by_index(index) // SAFETY: `resource` is a valid resource for `&self` during the // lifetime of the `IoRequest`. .map(|resource| unsafe { IoRequest::new(self.as_ref(), resource) }) the warning goes away. @Miguel: What's the preferred way dealing with this? I assume we just want to ignore this warning for the affected compiler versions? > + } > + > + /// Returns an `IoRequest` for the resource with a given `name`, if any. > + pub fn io_request_by_name(&self, name: &CStr) -> Option<IoRequest<'_>> { > + // SAFETY: `resource` is a valid resource for `&self` during the > + // lifetime of the `IoRequest`. > + self.resource_by_name(name) > + .map(|resource| unsafe { IoRequest::new(self.as_ref(), resource) }) > + } > }
On Sat, Jul 19, 2025 at 3:15 PM Danilo Krummrich <dakr@kernel.org> wrote: > > @Miguel: What's the preferred way dealing with this? I assume we just want to > ignore this warning for the affected compiler versions? Yeah, we had this in the past -- when I introduced the lint, I just went with putting in the middle, e.g. in `rust/kernel/sync/lock.rs`'s `do_unlocked`. It has been fairly confusing, because long ago AFAIU it was not intended to be supported, but then they introduced a config option for it, and then it was made the default, but there were false positives. It seems it has been finally fixed in https://github.com/rust-lang/rust-clippy/pull/13888 for Rust 1.87.0. I would say just put it in the middle. The only advantage of using an `allow` would be using the "reason" field to say we can move it >= 1.87, but if we really want to move it, we can always use a normal comment to say so instead. Cheers, Miguel
On Sat, Jul 19, 2025 at 6:19 PM Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> wrote: > > Yeah, we had this in the past -- when I introduced the lint, I just > went with putting in the middle, e.g. in `rust/kernel/sync/lock.rs`'s > `do_unlocked`. > > It has been fairly confusing, because long ago AFAIU it was not > intended to be supported, but then they introduced a config option for > it, and then it was made the default, but there were false positives. > > It seems it has been finally fixed in > https://github.com/rust-lang/rust-clippy/pull/13888 for Rust 1.87.0. > > I would say just put it in the middle. The only advantage of using an > `allow` would be using the "reason" field to say we can move it >= > 1.87, but if we really want to move it, we can always use a normal > comment to say so instead. I have added some information and links about this to https://github.com/Rust-for-Linux/linux/issues/349. Cheers, Miguel
© 2016 - 2025 Red Hat, Inc.