Skip to content

Commit 6f94f6a

Browse files
committed
rust: add an abstraction for devices.
This will be used by the GPIO subsystem, which will come in a subsequent patch. Implement the `RawDevice` interface for Amba devices, since they actually are devices in the driver model. This will be used by the PL061 driver. Signed-off-by: Wedson Almeida Filho <[email protected]>
1 parent cbc76a2 commit 6f94f6a

File tree

3 files changed

+70
-2
lines changed

3 files changed

+70
-2
lines changed

rust/kernel/amba.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
//! C header: [`include/linux/amba/bus.h`](../../../../include/linux/amba/bus.h)
66
77
use crate::{
8-
bindings, c_types, driver, from_kernel_result, io_mem::Resource, power, str::CStr, to_result,
9-
types::PointerWrapper, Error, Result,
8+
bindings, c_types, device, driver, from_kernel_result, io_mem::Resource, power, str::CStr,
9+
to_result, types::PointerWrapper, Error, Result,
1010
};
1111
use core::{marker::PhantomData, ops::Deref};
1212

@@ -192,6 +192,14 @@ impl Device {
192192
}
193193
}
194194

195+
// SAFETY: The device returned by `raw_device` is the raw Amba device.
196+
unsafe impl device::RawDevice for Device {
197+
fn raw_device(&self) -> *mut bindings::device {
198+
// SAFETY: By the type invariants, we know that `self.ptr` is non-null and valid.
199+
unsafe { &mut (*self.ptr).dev }
200+
}
201+
}
202+
195203
/// Declares a kernel module that exposes a single amba driver.
196204
///
197205
/// # Examples

rust/kernel/device.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Generic devices that are part of the kernel's driver model.
4+
//!
5+
//! C header: [`include/linux/device.h`](../../../../include/linux/device.h)
6+
7+
use crate::bindings;
8+
9+
/// A raw device.
10+
///
11+
/// # Safety
12+
///
13+
/// Implementers must ensure that the `*mut device` returned by [`RawDevice::raw_device`] is
14+
/// related to `self`, that is, actions on it will affect `self`. For example, if one calls
15+
/// `get_device`, then the refcount on the device represented by `self` will be incremented.
16+
pub unsafe trait RawDevice {
17+
/// Returns the raw `struct device` related to `self`.
18+
fn raw_device(&self) -> *mut bindings::device;
19+
}
20+
21+
/// A ref-counted device.
22+
///
23+
/// # Invariants
24+
///
25+
/// `ptr` is valid, non-null, and has a non-zero reference count. One of the references is owned by
26+
/// `self`, and will be decremented when `self` is dropped.
27+
pub struct Device {
28+
pub(crate) ptr: *mut bindings::device,
29+
}
30+
31+
impl Device {
32+
/// Creates a new device instance.
33+
///
34+
/// # Safety
35+
///
36+
/// Callers must ensure that `ptr` is valid, non-null, and has a non-zero reference count.
37+
pub unsafe fn new(ptr: *mut bindings::device) -> Self {
38+
// SAFETY: By the safety requiments, ptr is valid and its refcounted will be incremented.
39+
unsafe { bindings::get_device(ptr) };
40+
// INVARIANT: The safety requirements satisfy all but one invariant, which is that `self`
41+
// owns a reference. This is satisfied by the call to `get_device` above.
42+
Self { ptr }
43+
}
44+
45+
/// Creates a new device instance from an existing [`RawDevice`] instance.
46+
pub fn from_dev(dev: &dyn RawDevice) -> Self {
47+
// SAFETY: The requirements are satisfied by the existence of `RawDevice` and its safety
48+
// requirements.
49+
unsafe { Self::new(dev.raw_device()) }
50+
}
51+
}
52+
53+
impl Drop for Device {
54+
fn drop(&mut self) {
55+
// SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to
56+
// relinquish it now.
57+
unsafe { bindings::put_device(self.ptr) };
58+
}
59+
}

rust/kernel/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub mod amba;
4747
pub mod buffer;
4848
pub mod c_types;
4949
pub mod chrdev;
50+
pub mod device;
5051
pub mod driver;
5152
mod error;
5253
pub mod file;

0 commit comments

Comments
 (0)