Skip to content

Commit 6ea4dfa

Browse files
Maciej Falkowskijannau
authored andcommitted
rust: platform: add ioremap_resource and get_resource methods
This patch adds a logic similar to `devm_platform_ioremap_resource` function adding: - `IoResource` enumerated type that groups the `IORESOURCE_*` macros. - `get_resource()` method that is a binding of `platform_get_resource` - `ioremap_resource` that is newly written method similar to `devm_platform_ioremap_resource`. Lina: Removed `bit` dependency and rebased Co-developed-by: Asahi Lina <lina@asahilina.net> Signed-off-by: Maciej Falkowski <m.falkowski@samsung.com>
1 parent 18a0c20 commit 6ea4dfa

2 files changed

Lines changed: 66 additions & 5 deletions

File tree

rust/kernel/io_mem.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
use crate::{bindings, error::code::*, error::Result};
1010
use core::convert::TryInto;
1111

12+
/// The type of `Resource`.
13+
pub enum IoResource {
14+
/// i/o memory
15+
Mem = bindings::IORESOURCE_MEM as _,
16+
}
17+
1218
/// Represents a memory resource.
1319
pub struct Resource {
1420
offset: bindings::resource_size_t,

rust/kernel/platform.rs

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::{
99
device_id::RawDeviceId,
1010
driver,
1111
error::{to_result, Result},
12+
io_mem::*,
1213
of,
1314
prelude::*,
1415
str::CStr,
@@ -186,7 +187,10 @@ pub trait Driver {
186187
/// `Device` holds a valid reference of `ARef<device::Device>` whose underlying `struct device` is a
187188
/// member of a `struct platform_device`.
188189
#[derive(Clone)]
189-
pub struct Device(ARef<device::Device>);
190+
pub struct Device {
191+
dev: ARef<device::Device>,
192+
used_resource: u64,
193+
}
190194

191195
impl Device {
192196
/// Convert a raw kernel device into a `Device`
@@ -196,22 +200,73 @@ impl Device {
196200
/// `dev` must be an `Aref<device::Device>` whose underlying `bindings::device` is a member of a
197201
/// `bindings::platform_device`.
198202
unsafe fn from_dev(dev: ARef<device::Device>) -> Self {
199-
Self(dev)
203+
Self(dev, 0)
200204
}
201205

202206
fn as_dev(&self) -> &device::Device {
203-
&self.0
207+
&self.dev
204208
}
205209

206210
fn as_raw(&self) -> *mut bindings::platform_device {
207211
// SAFETY: By the type invariant `self.0.as_raw` is a pointer to the `struct device`
208212
// embedded in `struct platform_device`.
209-
unsafe { container_of!(self.0.as_raw(), bindings::platform_device, dev) }.cast_mut()
213+
unsafe { container_of!(self.dev.as_raw(), bindings::platform_device, dev) }.cast_mut()
214+
}
215+
216+
/// Gets a system resources of a platform device.
217+
pub fn get_resource(&mut self, rtype: IoResource, num: usize) -> Result<Resource> {
218+
// SAFETY: `self.ptr` is valid by the type invariant.
219+
let res = unsafe { bindings::platform_get_resource(self.ptr, rtype as _, num as _) };
220+
if res.is_null() {
221+
return Err(EINVAL);
222+
}
223+
224+
// Get the position of the found resource in the array.
225+
// SAFETY:
226+
// - `self.ptr` is valid by the type invariant.
227+
// - `res` is a displaced pointer to one of the array's elements,
228+
// and `resource` is its base pointer.
229+
let index = unsafe { res.offset_from((*self.ptr).resource) } as usize;
230+
231+
// Make sure that the index does not exceed the 64-bit mask.
232+
assert!(index < 64);
233+
234+
if self.used_resource >> index & 1 == 1 {
235+
return Err(EBUSY);
236+
}
237+
self.used_resource |= 1 << index;
238+
239+
// SAFETY: The pointer `res` is returned from `bindings::platform_get_resource`
240+
// above and checked if it is not a NULL.
241+
unsafe { Resource::new((*res).start, (*res).end) }.ok_or(EINVAL)
242+
}
243+
244+
/// Ioremaps resources of a platform device.
245+
///
246+
/// # Safety
247+
///
248+
/// Callers must ensure that either (a) the resulting interface cannot be used to initiate DMA
249+
/// operations, or (b) that DMA operations initiated via the returned interface use DMA handles
250+
/// allocated through the `dma` module.
251+
pub unsafe fn ioremap_resource<const SIZE: usize>(
252+
&mut self,
253+
index: usize,
254+
) -> Result<IoMem<SIZE>> {
255+
let mask = self.used_resource;
256+
let res = self.get_resource(IoResource::Mem, index)?;
257+
258+
// SAFETY: Valid by the safety contract.
259+
let iomem = unsafe { IoMem::<SIZE>::try_new(res) };
260+
// If remapping fails, the given resource won't be used, so restore the old mask.
261+
if iomem.is_err() {
262+
self.used_resource = mask;
263+
}
264+
iomem
210265
}
211266
}
212267

213268
impl AsRef<device::Device> for Device {
214269
fn as_ref(&self) -> &device::Device {
215-
&self.0
270+
&self.dev
216271
}
217272
}

0 commit comments

Comments
 (0)