Skip to content

Commit

Permalink
Merge pull request torvalds#558 from wedsonaf/device
Browse files Browse the repository at this point in the history
rust: add an abstraction for devices.
  • Loading branch information
wedsonaf authored Nov 19, 2021
2 parents cbc76a2 + 6f94f6a commit 72e59fe
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 2 deletions.
12 changes: 10 additions & 2 deletions rust/kernel/amba.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
//! C header: [`include/linux/amba/bus.h`](../../../../include/linux/amba/bus.h)
use crate::{
bindings, c_types, driver, from_kernel_result, io_mem::Resource, power, str::CStr, to_result,
types::PointerWrapper, Error, Result,
bindings, c_types, device, driver, from_kernel_result, io_mem::Resource, power, str::CStr,
to_result, types::PointerWrapper, Error, Result,
};
use core::{marker::PhantomData, ops::Deref};

Expand Down Expand Up @@ -192,6 +192,14 @@ impl Device {
}
}

// SAFETY: The device returned by `raw_device` is the raw Amba device.
unsafe impl device::RawDevice for Device {
fn raw_device(&self) -> *mut bindings::device {
// SAFETY: By the type invariants, we know that `self.ptr` is non-null and valid.
unsafe { &mut (*self.ptr).dev }
}
}

/// Declares a kernel module that exposes a single amba driver.
///
/// # Examples
Expand Down
59 changes: 59 additions & 0 deletions rust/kernel/device.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: GPL-2.0

//! Generic devices that are part of the kernel's driver model.
//!
//! C header: [`include/linux/device.h`](../../../../include/linux/device.h)
use crate::bindings;

/// A raw device.
///
/// # Safety
///
/// Implementers must ensure that the `*mut device` returned by [`RawDevice::raw_device`] is
/// related to `self`, that is, actions on it will affect `self`. For example, if one calls
/// `get_device`, then the refcount on the device represented by `self` will be incremented.
pub unsafe trait RawDevice {
/// Returns the raw `struct device` related to `self`.
fn raw_device(&self) -> *mut bindings::device;
}

/// A ref-counted device.
///
/// # Invariants
///
/// `ptr` is valid, non-null, and has a non-zero reference count. One of the references is owned by
/// `self`, and will be decremented when `self` is dropped.
pub struct Device {
pub(crate) ptr: *mut bindings::device,
}

impl Device {
/// Creates a new device instance.
///
/// # Safety
///
/// Callers must ensure that `ptr` is valid, non-null, and has a non-zero reference count.
pub unsafe fn new(ptr: *mut bindings::device) -> Self {
// SAFETY: By the safety requiments, ptr is valid and its refcounted will be incremented.
unsafe { bindings::get_device(ptr) };
// INVARIANT: The safety requirements satisfy all but one invariant, which is that `self`
// owns a reference. This is satisfied by the call to `get_device` above.
Self { ptr }
}

/// Creates a new device instance from an existing [`RawDevice`] instance.
pub fn from_dev(dev: &dyn RawDevice) -> Self {
// SAFETY: The requirements are satisfied by the existence of `RawDevice` and its safety
// requirements.
unsafe { Self::new(dev.raw_device()) }
}
}

impl Drop for Device {
fn drop(&mut self) {
// SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to
// relinquish it now.
unsafe { bindings::put_device(self.ptr) };
}
}
1 change: 1 addition & 0 deletions rust/kernel/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub mod amba;
pub mod buffer;
pub mod c_types;
pub mod chrdev;
pub mod device;
pub mod driver;
mod error;
pub mod file;
Expand Down

0 comments on commit 72e59fe

Please sign in to comment.