Skip to content

Commit 40c2d5e

Browse files
author
Maciej Falkowski
committed
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`. Signed-off-by: Maciej Falkowski <[email protected]>
1 parent 37bfea1 commit 40c2d5e

File tree

2 files changed

+66
-4
lines changed

2 files changed

+66
-4
lines changed

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::*, 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 & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@
77
//! C header: [`include/linux/platform_device.h`](../../../../include/linux/platform_device.h)
88
99
use crate::{
10-
bindings, c_types,
10+
bindings, bit, c_types,
1111
device::{self, RawDevice},
1212
driver,
13-
error::{from_kernel_result, Result},
13+
error::{code::*, from_kernel_result},
14+
io_mem::{IoMem, IoResource, Resource},
1415
of,
1516
str::CStr,
1617
to_result,
1718
types::PointerWrapper,
18-
ThisModule,
19+
Result, ThisModule,
1920
};
2021

2122
/// A registration of a platform driver.
@@ -161,6 +162,7 @@ pub trait Driver {
161162
/// The field `ptr` is non-null and valid for the lifetime of the object.
162163
pub struct Device {
163164
ptr: *mut bindings::platform_device,
165+
used_resource: u64,
164166
}
165167

166168
impl Device {
@@ -172,14 +174,68 @@ impl Device {
172174
/// instance.
173175
unsafe fn from_ptr(ptr: *mut bindings::platform_device) -> Self {
174176
// INVARIANT: The safety requirements of the function ensure the lifetime invariant.
175-
Self { ptr }
177+
Self {
178+
ptr,
179+
used_resource: 0,
180+
}
176181
}
177182

178183
/// Returns id of the platform device.
179184
pub fn id(&self) -> i32 {
180185
// SAFETY: By the type invariants, we know that `self.ptr` is non-null and valid.
181186
unsafe { (*self.ptr).id }
182187
}
188+
189+
/// Gets a system resources of a platform device.
190+
pub fn get_resource(&mut self, rtype: IoResource, num: usize) -> Result<Resource> {
191+
// SAFETY: `self.ptr` is valid by the type invariant.
192+
let res = unsafe { bindings::platform_get_resource(self.ptr, rtype as _, num as _) };
193+
if res.is_null() {
194+
return Err(EINVAL);
195+
}
196+
197+
// Get the position of the found resource in the array.
198+
// SAFETY:
199+
// - `self.ptr` is valid by the type invariant.
200+
// - `res` is a displaced pointer to one of the array's elements,
201+
// and `resource` is its base pointer.
202+
let index = unsafe { res.offset_from((*self.ptr).resource) } as usize;
203+
204+
// Make sure that the index does not exceed the 64-bit mask.
205+
assert!(index < 64);
206+
207+
if self.used_resource >> index & bit(0) == 1 {
208+
return Err(EBUSY);
209+
}
210+
self.used_resource |= bit(index);
211+
212+
// SAFETY: The pointer `res` is returned from `bindings::platform_get_resource`
213+
// above and checked if it is not a NULL.
214+
unsafe { Resource::new((*res).start, (*res).end) }.ok_or(EINVAL)
215+
}
216+
217+
/// Ioremaps resources of a platform device.
218+
///
219+
/// # Safety
220+
///
221+
/// Callers must ensure that either (a) the resulting interface cannot be used to initiate DMA
222+
/// operations, or (b) that DMA operations initiated via the returned interface use DMA handles
223+
/// allocated through the `dma` module.
224+
pub unsafe fn ioremap_resource<const SIZE: usize>(
225+
&mut self,
226+
index: usize,
227+
) -> Result<IoMem<SIZE>> {
228+
let mask = self.used_resource;
229+
let res = self.get_resource(IoResource::Mem, index)?;
230+
231+
// SAFETY: Valid by the safety contract.
232+
let iomem = unsafe { IoMem::<SIZE>::try_new(res) };
233+
// If remapping fails, the given resource won't be used, so restore the old mask.
234+
if iomem.is_err() {
235+
self.used_resource = mask;
236+
}
237+
iomem
238+
}
183239
}
184240

185241
// SAFETY: The device returned by `raw_device` is the raw platform device.

0 commit comments

Comments
 (0)